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/content_settings_utils.h"
12 #include "chrome/browser/content_settings/cookie_settings.h"
13 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
14 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
15 #include "chrome/browser/favicon/favicon_tab_helper.h"
16 #include "chrome/browser/infobars/infobar_service.h"
17 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
18 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
21 #include "chrome/browser/ui/browser_navigator.h"
22 #include "chrome/browser/ui/collected_cookies_infobar_delegate.h"
23 #include "chrome/browser/ui/content_settings/content_setting_bubble_model_delegate.h"
24 #include "chrome/browser/ui/content_settings/media_setting_changed_infobar_delegate.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/content_settings.h"
27 #include "chrome/common/pref_names.h"
28 #include "chrome/common/render_messages.h"
29 #include "content/public/browser/notification_service.h"
30 #include "content/public/browser/render_frame_host.h"
31 #include "content/public/browser/render_process_host.h"
32 #include "content/public/browser/render_view_host.h"
33 #include "content/public/browser/user_metrics.h"
34 #include "content/public/browser/web_contents.h"
35 #include "content/public/browser/web_contents_delegate.h"
36 #include "grit/generated_resources.h"
37 #include "grit/theme_resources.h"
38 #include "grit/ui_resources.h"
39 #include "net/base/net_util.h"
40 #include "ui/base/l10n/l10n_util.h"
41 #include "ui/base/resource/resource_bundle.h"
43 using base::UserMetricsAction
;
44 using content::WebContents
;
45 using content_settings::SettingInfo
;
46 using content_settings::SettingSource
;
47 using content_settings::SETTING_SOURCE_USER
;
48 using content_settings::SETTING_SOURCE_NONE
;
52 const int kAllowButtonIndex
= 0;
54 struct ContentSettingsTypeIdEntry
{
55 ContentSettingsType type
;
59 int GetIdForContentType(const ContentSettingsTypeIdEntry
* entries
,
61 ContentSettingsType type
) {
62 for (size_t i
= 0; i
< num_entries
; ++i
) {
63 if (entries
[i
].type
== type
)
69 const content::MediaStreamDevice
& GetMediaDeviceById(
70 const std::string
& device_id
,
71 const content::MediaStreamDevices
& devices
) {
72 DCHECK(!devices
.empty());
73 for (content::MediaStreamDevices::const_iterator it
= devices
.begin();
74 it
!= devices
.end(); ++it
) {
75 if (it
->id
== device_id
)
79 // A device with the |device_id| was not found. It is likely that the device
80 // has been unplugged from the OS. Return the first device as the default
82 return *devices
.begin();
87 ContentSettingTitleAndLinkModel::ContentSettingTitleAndLinkModel(
89 WebContents
* web_contents
,
91 ContentSettingsType content_type
)
92 : ContentSettingBubbleModel(web_contents
, profile
, content_type
),
94 // Notifications do not have a bubble.
95 DCHECK_NE(content_type
, CONTENT_SETTINGS_TYPE_NOTIFICATIONS
);
100 void ContentSettingTitleAndLinkModel::SetTitle() {
101 static const ContentSettingsTypeIdEntry kBlockedTitleIDs
[] = {
102 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_TITLE
},
103 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_TITLE
},
104 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_TITLE
},
105 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_MESSAGE
},
106 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_TITLE
},
107 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
,
108 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT
},
109 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
,
110 IDS_BLOCKED_PPAPI_BROKER_TITLE
},
111 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_TITLE
},
113 // Fields as for kBlockedTitleIDs, above.
114 static const ContentSettingsTypeIdEntry kAccessedTitleIDs
[] = {
115 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_ACCESSED_COOKIES_TITLE
},
116 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_TITLE
},
117 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_TITLE
},
119 const ContentSettingsTypeIdEntry
*title_ids
= kBlockedTitleIDs
;
120 size_t num_title_ids
= arraysize(kBlockedTitleIDs
);
121 if (web_contents() &&
122 TabSpecificContentSettings::FromWebContents(
123 web_contents())->IsContentAllowed(content_type()) &&
124 !TabSpecificContentSettings::FromWebContents(
125 web_contents())->IsContentBlocked(content_type())) {
126 title_ids
= kAccessedTitleIDs
;
127 num_title_ids
= arraysize(kAccessedTitleIDs
);
130 GetIdForContentType(title_ids
, num_title_ids
, content_type());
132 set_title(l10n_util::GetStringUTF8(title_id
));
135 void ContentSettingTitleAndLinkModel::SetManageLink() {
136 static const ContentSettingsTypeIdEntry kLinkIDs
[] = {
137 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_LINK
},
138 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_LINK
},
139 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_LINK
},
140 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_LINK
},
141 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_LINK
},
142 {CONTENT_SETTINGS_TYPE_GEOLOCATION
, IDS_GEOLOCATION_BUBBLE_MANAGE_LINK
},
143 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
, IDS_LEARN_MORE
},
144 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
, IDS_HANDLERS_BUBBLE_MANAGE_LINK
},
145 {CONTENT_SETTINGS_TYPE_MEDIASTREAM
, IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK
},
146 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_PPAPI_BROKER_BUBBLE_MANAGE_LINK
},
147 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOADS_LINK
},
148 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK
},
150 set_manage_link(l10n_util::GetStringUTF8(
151 GetIdForContentType(kLinkIDs
, arraysize(kLinkIDs
), content_type())));
154 void ContentSettingTitleAndLinkModel::OnManageLinkClicked() {
156 delegate_
->ShowContentSettingsPage(content_type());
159 class ContentSettingTitleLinkAndCustomModel
160 : public ContentSettingTitleAndLinkModel
{
162 ContentSettingTitleLinkAndCustomModel(Delegate
* delegate
,
163 WebContents
* web_contents
,
165 ContentSettingsType content_type
);
166 virtual ~ContentSettingTitleLinkAndCustomModel() {}
169 void SetCustomLink();
170 virtual void OnCustomLinkClicked() OVERRIDE
{}
173 ContentSettingTitleLinkAndCustomModel::ContentSettingTitleLinkAndCustomModel(
175 WebContents
* web_contents
,
177 ContentSettingsType content_type
)
178 : ContentSettingTitleAndLinkModel(
179 delegate
, web_contents
, profile
, content_type
) {
183 void ContentSettingTitleLinkAndCustomModel::SetCustomLink() {
184 static const ContentSettingsTypeIdEntry kCustomIDs
[] = {
185 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_INFO
},
186 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_LOAD_ALL
},
187 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
, IDS_ALLOW_INSECURE_CONTENT_BUTTON
},
190 GetIdForContentType(kCustomIDs
, arraysize(kCustomIDs
), content_type());
192 set_custom_link(l10n_util::GetStringUTF8(custom_link_id
));
195 class ContentSettingSingleRadioGroup
196 : public ContentSettingTitleLinkAndCustomModel
{
198 ContentSettingSingleRadioGroup(Delegate
* delegate
,
199 WebContents
* web_contents
,
201 ContentSettingsType content_type
);
202 virtual ~ContentSettingSingleRadioGroup();
205 bool settings_changed() const;
206 int selected_item() const { return selected_item_
; }
209 void SetRadioGroup();
210 void AddException(ContentSetting setting
);
211 virtual void OnRadioClicked(int radio_index
) OVERRIDE
;
213 ContentSetting block_setting_
;
217 ContentSettingSingleRadioGroup::ContentSettingSingleRadioGroup(
219 WebContents
* web_contents
,
221 ContentSettingsType content_type
)
222 : ContentSettingTitleLinkAndCustomModel(delegate
, web_contents
, profile
,
224 block_setting_(CONTENT_SETTING_BLOCK
),
229 ContentSettingSingleRadioGroup::~ContentSettingSingleRadioGroup() {
230 if (settings_changed()) {
231 ContentSetting setting
=
232 selected_item_
== kAllowButtonIndex
?
233 CONTENT_SETTING_ALLOW
:
235 AddException(setting
);
239 bool ContentSettingSingleRadioGroup::settings_changed() const {
240 return selected_item_
!= bubble_content().radio_group
.default_item
;
243 // Initialize the radio group by setting the appropriate labels for the
244 // content type and setting the default value based on the content setting.
245 void ContentSettingSingleRadioGroup::SetRadioGroup() {
246 GURL url
= web_contents()->GetURL();
247 base::string16 display_host
;
248 net::AppendFormattedHost(
250 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages
),
253 if (display_host
.empty())
254 display_host
= base::ASCIIToUTF16(url
.spec());
256 TabSpecificContentSettings
* content_settings
=
257 TabSpecificContentSettings::FromWebContents(web_contents());
259 !content_settings
->IsContentBlocked(content_type());
261 content_settings
->IsContentAllowed(content_type()));
263 RadioGroup radio_group
;
264 radio_group
.url
= url
;
266 static const ContentSettingsTypeIdEntry kBlockedAllowIDs
[] = {
267 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_UNBLOCK
},
268 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_UNBLOCK
},
269 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_UNBLOCK
},
270 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_UNBLOCK_ALL
},
271 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_UNBLOCK
},
272 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_BLOCKED_PPAPI_BROKER_UNBLOCK
},
273 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_UNBLOCK
},
275 // Fields as for kBlockedAllowIDs, above.
276 static const ContentSettingsTypeIdEntry kAllowedAllowIDs
[] = {
277 // TODO(bauerb): The string shouldn't be "unblock" (they weren't blocked).
278 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_UNBLOCK
},
279 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_NO_ACTION
},
280 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_NO_ACTION
},
283 std::string radio_allow_label
;
285 int resource_id
= GetIdForContentType(kAllowedAllowIDs
,
286 arraysize(kAllowedAllowIDs
),
288 radio_allow_label
= (content_type() == CONTENT_SETTINGS_TYPE_COOKIES
) ?
289 l10n_util::GetStringFUTF8(resource_id
, display_host
) :
290 l10n_util::GetStringUTF8(resource_id
);
292 radio_allow_label
= l10n_util::GetStringFUTF8(
293 GetIdForContentType(kBlockedAllowIDs
, arraysize(kBlockedAllowIDs
),
298 static const ContentSettingsTypeIdEntry kBlockedBlockIDs
[] = {
299 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_NO_ACTION
},
300 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_NO_ACTION
},
301 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_NO_ACTION
},
302 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_NO_ACTION
},
303 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_NO_ACTION
},
304 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_BLOCKED_PPAPI_BROKER_NO_ACTION
},
305 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_NO_ACTION
},
307 static const ContentSettingsTypeIdEntry kAllowedBlockIDs
[] = {
308 // TODO(bauerb): The string should say "block".
309 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_NO_ACTION
},
310 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_BLOCK
},
311 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_BLOCK
},
314 std::string radio_block_label
;
316 int resource_id
= GetIdForContentType(kAllowedBlockIDs
,
317 arraysize(kAllowedBlockIDs
),
319 radio_block_label
= (content_type() == CONTENT_SETTINGS_TYPE_COOKIES
) ?
320 l10n_util::GetStringUTF8(resource_id
) :
321 l10n_util::GetStringFUTF8(resource_id
, display_host
);
323 radio_block_label
= l10n_util::GetStringUTF8(
324 GetIdForContentType(kBlockedBlockIDs
, arraysize(kBlockedBlockIDs
),
328 radio_group
.radio_items
.push_back(radio_allow_label
);
329 radio_group
.radio_items
.push_back(radio_block_label
);
330 ContentSetting setting
;
331 SettingSource setting_source
= SETTING_SOURCE_NONE
;
332 bool setting_is_wildcard
= false;
334 if (content_type() == CONTENT_SETTINGS_TYPE_COOKIES
) {
335 CookieSettings
* cookie_settings
=
336 CookieSettings::Factory::GetForProfile(profile()).get();
337 setting
= cookie_settings
->GetCookieSetting(
338 url
, url
, true, &setting_source
);
341 HostContentSettingsMap
* map
= profile()->GetHostContentSettingsMap();
342 scoped_ptr
<base::Value
> value(map
->GetWebsiteSetting(
343 url
, url
, content_type(), std::string(), &info
));
344 setting
= content_settings::ValueToContentSetting(value
.get());
345 setting_source
= info
.source
;
346 setting_is_wildcard
=
347 info
.primary_pattern
== ContentSettingsPattern::Wildcard() &&
348 info
.secondary_pattern
== ContentSettingsPattern::Wildcard();
351 if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS
&&
352 setting
== CONTENT_SETTING_ALLOW
&&
353 setting_is_wildcard
) {
354 // In the corner case of unrecognized plugins (which are now blocked by
355 // default) we indicate the blocked state in the UI and allow the user to
357 radio_group
.default_item
= 1;
358 } else if (setting
== CONTENT_SETTING_ALLOW
) {
359 radio_group
.default_item
= kAllowButtonIndex
;
360 // |block_setting_| is already set to |CONTENT_SETTING_BLOCK|.
362 radio_group
.default_item
= 1;
363 block_setting_
= setting
;
366 set_setting_is_managed(setting_source
!= SETTING_SOURCE_USER
);
367 if (setting_source
!= SETTING_SOURCE_USER
) {
368 set_radio_group_enabled(false);
370 set_radio_group_enabled(true);
372 selected_item_
= radio_group
.default_item
;
373 set_radio_group(radio_group
);
376 void ContentSettingSingleRadioGroup::AddException(ContentSetting setting
) {
378 profile()->GetHostContentSettingsMap()->AddExceptionForURL(
379 bubble_content().radio_group
.url
,
380 bubble_content().radio_group
.url
,
386 void ContentSettingSingleRadioGroup::OnRadioClicked(int radio_index
) {
387 selected_item_
= radio_index
;
390 class ContentSettingCookiesBubbleModel
: public ContentSettingSingleRadioGroup
{
392 ContentSettingCookiesBubbleModel(Delegate
* delegate
,
393 WebContents
* web_contents
,
395 ContentSettingsType content_type
);
397 virtual ~ContentSettingCookiesBubbleModel();
400 virtual void OnCustomLinkClicked() OVERRIDE
;
403 ContentSettingCookiesBubbleModel::ContentSettingCookiesBubbleModel(
405 WebContents
* web_contents
,
407 ContentSettingsType content_type
)
408 : ContentSettingSingleRadioGroup(
409 delegate
, web_contents
, profile
, content_type
) {
410 DCHECK_EQ(CONTENT_SETTINGS_TYPE_COOKIES
, content_type
);
411 set_custom_link_enabled(true);
414 ContentSettingCookiesBubbleModel::~ContentSettingCookiesBubbleModel() {
415 // On some plattforms e.g. MacOS X it is possible to close a tab while the
416 // cookies settings bubble is open. This resets the web contents to NULL.
417 if (settings_changed() && web_contents()) {
418 CollectedCookiesInfoBarDelegate::Create(
419 InfoBarService::FromWebContents(web_contents()));
423 void ContentSettingCookiesBubbleModel::OnCustomLinkClicked() {
426 content::NotificationService::current()->Notify(
427 chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN
,
428 content::Source
<TabSpecificContentSettings
>(
429 TabSpecificContentSettings::FromWebContents(web_contents())),
430 content::NotificationService::NoDetails());
431 delegate()->ShowCollectedCookiesDialog(web_contents());
434 class ContentSettingPluginBubbleModel
: public ContentSettingSingleRadioGroup
{
436 ContentSettingPluginBubbleModel(Delegate
* delegate
,
437 WebContents
* web_contents
,
439 ContentSettingsType content_type
);
441 virtual ~ContentSettingPluginBubbleModel();
444 virtual void OnCustomLinkClicked() OVERRIDE
;
447 ContentSettingPluginBubbleModel::ContentSettingPluginBubbleModel(
449 WebContents
* web_contents
,
451 ContentSettingsType content_type
)
452 : ContentSettingSingleRadioGroup(
453 delegate
, web_contents
, profile
, content_type
) {
454 DCHECK_EQ(content_type
, CONTENT_SETTINGS_TYPE_PLUGINS
);
455 // Disable the "Run all plugins this time" link if the setting is managed and
456 // can't be controlled by the user or if the user already clicked on the link
457 // and ran all plugins.
458 set_custom_link_enabled(!setting_is_managed() &&
460 TabSpecificContentSettings::FromWebContents(
461 web_contents
)->load_plugins_link_enabled());
464 ContentSettingPluginBubbleModel::~ContentSettingPluginBubbleModel() {
465 if (settings_changed()) {
466 // If the user elected to allow all plugins then run plugins at this time.
467 if (selected_item() == kAllowButtonIndex
)
468 OnCustomLinkClicked();
472 void ContentSettingPluginBubbleModel::OnCustomLinkClicked() {
473 content::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble"));
474 DCHECK(web_contents());
475 #if defined(ENABLE_PLUGINS)
476 // TODO(bauerb): We should send the identifiers of blocked plug-ins here.
477 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
478 web_contents(), true, std::string());
480 set_custom_link_enabled(false);
481 TabSpecificContentSettings::FromWebContents(web_contents())->
482 set_load_plugins_link_enabled(false);
485 class ContentSettingPopupBubbleModel
: public ContentSettingSingleRadioGroup
{
487 ContentSettingPopupBubbleModel(Delegate
* delegate
,
488 WebContents
* web_contents
,
490 ContentSettingsType content_type
);
491 virtual ~ContentSettingPopupBubbleModel() {}
495 virtual void OnPopupClicked(int index
) OVERRIDE
;
498 ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel(
500 WebContents
* web_contents
,
502 ContentSettingsType content_type
)
503 : ContentSettingSingleRadioGroup(
504 delegate
, web_contents
, profile
, content_type
) {
509 void ContentSettingPopupBubbleModel::SetPopups() {
510 std::map
<int32
, GURL
> blocked_popups
=
511 PopupBlockerTabHelper::FromWebContents(web_contents())
512 ->GetBlockedPopupRequests();
513 for (std::map
<int32
, GURL
>::const_iterator iter
= blocked_popups
.begin();
514 iter
!= blocked_popups
.end();
516 std::string
title(iter
->second
.spec());
517 // The popup may not have a valid URL.
519 title
= l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE
);
520 PopupItem
popup_item(
521 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
522 IDR_DEFAULT_FAVICON
),
525 add_popup(popup_item
);
529 void ContentSettingPopupBubbleModel::OnPopupClicked(int index
) {
530 if (web_contents()) {
531 PopupBlockerTabHelper::FromWebContents(web_contents())->
532 ShowBlockedPopup(bubble_content().popup_items
[index
].popup_id
);
536 // The model of the content settings bubble for media settings.
537 class ContentSettingMediaStreamBubbleModel
538 : public ContentSettingTitleAndLinkModel
{
540 ContentSettingMediaStreamBubbleModel(Delegate
* delegate
,
541 WebContents
* web_contents
,
544 virtual ~ContentSettingMediaStreamBubbleModel();
548 // Sets the data for the radio buttons of the bubble.
549 void SetRadioGroup();
550 // Sets the data for the media menus of the bubble.
551 void SetMediaMenus();
552 // Updates the camera and microphone setting with the passed |setting|.
553 void UpdateSettings(ContentSetting setting
);
554 // Updates the camera and microphone default device with the passed |type|
556 void UpdateDefaultDeviceForType(content::MediaStreamType type
,
557 const std::string
& device
);
559 // ContentSettingBubbleModel implementation.
560 virtual void OnRadioClicked(int radio_index
) OVERRIDE
;
561 virtual void OnMediaMenuClicked(content::MediaStreamType type
,
562 const std::string
& selected_device
) OVERRIDE
;
564 // The index of the selected radio item.
566 // The content settings that are associated with the individual radio
568 ContentSetting radio_item_setting_
[2];
569 // The state of the microphone and camera access.
570 TabSpecificContentSettings::MicrophoneCameraState state_
;
573 ContentSettingMediaStreamBubbleModel::ContentSettingMediaStreamBubbleModel(
575 WebContents
* web_contents
,
577 : ContentSettingTitleAndLinkModel(
578 delegate
, web_contents
, profile
, CONTENT_SETTINGS_TYPE_MEDIASTREAM
),
580 state_(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED
) {
582 // Initialize the content settings associated with the individual radio
584 radio_item_setting_
[0] = CONTENT_SETTING_ASK
;
585 radio_item_setting_
[1] = CONTENT_SETTING_BLOCK
;
587 TabSpecificContentSettings
* content_settings
=
588 TabSpecificContentSettings::FromWebContents(web_contents
);
589 state_
= content_settings
->GetMicrophoneCameraState();
596 ContentSettingMediaStreamBubbleModel::~ContentSettingMediaStreamBubbleModel() {
597 // On some platforms (e.g. MacOS X) it is possible to close a tab while the
598 // media stream bubble is open. This resets the web contents to NULL.
602 bool media_setting_changed
= false;
603 for (MediaMenuMap::const_iterator it
= bubble_content().media_menus
.begin();
604 it
!= bubble_content().media_menus
.end(); ++it
) {
605 if (it
->second
.selected_device
.id
!= it
->second
.default_device
.id
) {
606 UpdateDefaultDeviceForType(it
->first
, it
->second
.selected_device
.id
);
607 media_setting_changed
= true;
611 // Update the media settings if the radio button selection was changed.
612 if (selected_item_
!= bubble_content().radio_group
.default_item
) {
613 UpdateSettings(radio_item_setting_
[selected_item_
]);
614 media_setting_changed
= true;
617 // Trigger the reload infobar if the media setting has been changed.
618 if (media_setting_changed
) {
619 MediaSettingChangedInfoBarDelegate::Create(
620 InfoBarService::FromWebContents(web_contents()));
624 void ContentSettingMediaStreamBubbleModel::SetTitle() {
627 case TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED
:
628 // If neither microphone nor camera stream was accessed, then there is no
629 // icon didplayed in the omnibox and no settings bubble availbale. Hence
630 // there is no title.
633 case TabSpecificContentSettings::MICROPHONE_ACCESSED
:
634 title_id
= IDS_MICROPHONE_ACCESSED
;
636 case TabSpecificContentSettings::CAMERA_ACCESSED
:
637 title_id
= IDS_CAMERA_ACCESSED
;
639 case TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED
:
640 title_id
= IDS_MICROPHONE_CAMERA_ALLOWED
;
642 case TabSpecificContentSettings::MICROPHONE_BLOCKED
:
643 title_id
= IDS_MICROPHONE_BLOCKED
;
645 case TabSpecificContentSettings::CAMERA_BLOCKED
:
646 title_id
= IDS_CAMERA_BLOCKED
;
648 case TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED
:
649 title_id
= IDS_MICROPHONE_CAMERA_BLOCKED
;
652 set_title(l10n_util::GetStringUTF8(title_id
));
655 void ContentSettingMediaStreamBubbleModel::SetRadioGroup() {
656 TabSpecificContentSettings
* content_settings
=
657 TabSpecificContentSettings::FromWebContents(web_contents());
658 GURL url
= content_settings
->media_stream_access_origin();
659 RadioGroup radio_group
;
660 radio_group
.url
= url
;
662 base::string16 display_host_utf16
;
663 net::AppendFormattedHost(
665 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages
),
666 &display_host_utf16
);
667 std::string
display_host(base::UTF16ToUTF8(display_host_utf16
));
668 if (display_host
.empty())
669 display_host
= url
.spec();
671 int radio_allow_label_id
= 0;
672 int radio_block_label_id
= 0;
674 case TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED
:
677 case TabSpecificContentSettings::MICROPHONE_ACCESSED
:
678 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION
;
679 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK
;
682 case TabSpecificContentSettings::CAMERA_ACCESSED
:
683 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION
;
684 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK
;
687 case TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED
:
688 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION
;
689 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK
;
692 case TabSpecificContentSettings::MICROPHONE_BLOCKED
:
693 if (url
.SchemeIsSecure()) {
694 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_MIC_ALLOW
;
695 radio_item_setting_
[0] = CONTENT_SETTING_ALLOW
;
697 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_MIC_ASK
;
700 radio_block_label_id
= IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION
;
703 case TabSpecificContentSettings::CAMERA_BLOCKED
:
704 if (url
.SchemeIsSecure()) {
705 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW
;
706 radio_item_setting_
[0] = CONTENT_SETTING_ALLOW
;
708 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK
;
711 radio_block_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION
;
714 case TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED
:
715 if (url
.SchemeIsSecure()) {
716 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ALLOW
;
717 radio_item_setting_
[0] = CONTENT_SETTING_ALLOW
;
719 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ASK
;
722 radio_block_label_id
= IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION
;
727 std::string radio_allow_label
= l10n_util::GetStringFUTF8(
728 radio_allow_label_id
, base::UTF8ToUTF16(display_host
));
729 std::string radio_block_label
=
730 l10n_util::GetStringUTF8(radio_block_label_id
);
732 radio_group
.default_item
= selected_item_
;
733 radio_group
.radio_items
.push_back(radio_allow_label
);
734 radio_group
.radio_items
.push_back(radio_block_label
);
736 set_radio_group(radio_group
);
737 set_radio_group_enabled(true);
740 void ContentSettingMediaStreamBubbleModel::UpdateSettings(
741 ContentSetting setting
) {
743 HostContentSettingsMap
* content_settings
=
744 profile()->GetHostContentSettingsMap();
745 TabSpecificContentSettings
* tab_content_settings
=
746 TabSpecificContentSettings::FromWebContents(web_contents());
747 // The same patterns must be used as in other places (e.g. the infobar) in
748 // order to override the existing rule. Otherwise a new rule is created.
749 // TODO(markusheintz): Extract to a helper so that there is only a single
751 ContentSettingsPattern primary_pattern
=
752 ContentSettingsPattern::FromURLNoWildcard(
753 tab_content_settings
->media_stream_access_origin());
754 ContentSettingsPattern secondary_pattern
=
755 ContentSettingsPattern::Wildcard();
756 if (state_
== TabSpecificContentSettings::MICROPHONE_ACCESSED
||
757 state_
== TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED
||
758 state_
== TabSpecificContentSettings::MICROPHONE_BLOCKED
||
759 state_
== TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED
) {
760 content_settings
->SetContentSetting(
761 primary_pattern
, secondary_pattern
,
762 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
, std::string(), setting
);
764 if (state_
== TabSpecificContentSettings::CAMERA_ACCESSED
||
765 state_
== TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED
||
766 state_
== TabSpecificContentSettings::CAMERA_BLOCKED
||
767 state_
== TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED
) {
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();
803 (state_
== TabSpecificContentSettings::MICROPHONE_ACCESSED
||
804 state_
== TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED
||
805 state_
== TabSpecificContentSettings::MICROPHONE_BLOCKED
||
806 state_
== TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED
);
807 bool show_camera_menu
=
808 (state_
== TabSpecificContentSettings::CAMERA_ACCESSED
||
809 state_
== TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED
||
810 state_
== TabSpecificContentSettings::CAMERA_BLOCKED
||
811 state_
== TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED
);
812 DCHECK(show_mic_menu
|| show_camera_menu
);
816 mic_menu
.label
= l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_MIC_LABEL
);
817 if (!microphones
.empty()) {
818 std::string preferred_mic
;
819 if (requested_microphone
.empty()) {
820 preferred_mic
= prefs
->GetString(prefs::kDefaultAudioCaptureDevice
);
821 mic_menu
.disabled
= false;
823 // Set the |disabled| to true in order to disable the device selection
824 // menu on the media settings bubble. This must be done if the website
825 // manages the microphone devices itself.
826 preferred_mic
= requested_microphone
;
827 mic_menu
.disabled
= true;
830 mic_menu
.default_device
= GetMediaDeviceById(preferred_mic
, microphones
);
831 mic_menu
.selected_device
= mic_menu
.default_device
;
833 add_media_menu(content::MEDIA_DEVICE_AUDIO_CAPTURE
, mic_menu
);
836 if (show_camera_menu
) {
837 const content::MediaStreamDevices
& cameras
=
838 dispatcher
->GetVideoCaptureDevices();
839 MediaMenu camera_menu
;
841 l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_CAMERA_LABEL
);
842 if (!cameras
.empty()) {
843 std::string preferred_camera
;
844 if (requested_camera
.empty()) {
845 preferred_camera
= prefs
->GetString(prefs::kDefaultVideoCaptureDevice
);
846 camera_menu
.disabled
= false;
848 // Disable the menu since the website is managing the camera devices
850 preferred_camera
= requested_camera
;
851 camera_menu
.disabled
= true;
854 camera_menu
.default_device
=
855 GetMediaDeviceById(preferred_camera
, cameras
);
856 camera_menu
.selected_device
= camera_menu
.default_device
;
858 add_media_menu(content::MEDIA_DEVICE_VIDEO_CAPTURE
, camera_menu
);
862 void ContentSettingMediaStreamBubbleModel::OnRadioClicked(int radio_index
) {
863 selected_item_
= radio_index
;
866 void ContentSettingMediaStreamBubbleModel::OnMediaMenuClicked(
867 content::MediaStreamType type
,
868 const std::string
& selected_device_id
) {
869 DCHECK(type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
||
870 type
== content::MEDIA_DEVICE_VIDEO_CAPTURE
);
871 DCHECK_EQ(1U, bubble_content().media_menus
.count(type
));
872 MediaCaptureDevicesDispatcher
* dispatcher
=
873 MediaCaptureDevicesDispatcher::GetInstance();
874 const content::MediaStreamDevices
& devices
=
875 (type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
) ?
876 dispatcher
->GetAudioCaptureDevices() :
877 dispatcher
->GetVideoCaptureDevices();
878 set_selected_device(GetMediaDeviceById(selected_device_id
, devices
));
881 class ContentSettingDomainListBubbleModel
882 : public ContentSettingTitleAndLinkModel
{
884 ContentSettingDomainListBubbleModel(Delegate
* delegate
,
885 WebContents
* web_contents
,
887 ContentSettingsType content_type
);
888 virtual ~ContentSettingDomainListBubbleModel() {}
891 void MaybeAddDomainList(const std::set
<std::string
>& hosts
, int title_id
);
892 void SetDomainsAndCustomLink();
893 virtual void OnCustomLinkClicked() OVERRIDE
;
896 ContentSettingDomainListBubbleModel::ContentSettingDomainListBubbleModel(
898 WebContents
* web_contents
,
900 ContentSettingsType content_type
)
901 : ContentSettingTitleAndLinkModel(
902 delegate
, web_contents
, profile
, content_type
) {
903 DCHECK_EQ(CONTENT_SETTINGS_TYPE_GEOLOCATION
, content_type
) <<
904 "SetDomains currently only supports geolocation content type";
905 SetDomainsAndCustomLink();
908 void ContentSettingDomainListBubbleModel::MaybeAddDomainList(
909 const std::set
<std::string
>& hosts
, int title_id
) {
910 if (!hosts
.empty()) {
911 DomainList domain_list
;
912 domain_list
.title
= l10n_util::GetStringUTF8(title_id
);
913 domain_list
.hosts
= hosts
;
914 add_domain_list(domain_list
);
918 void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() {
919 TabSpecificContentSettings
* content_settings
=
920 TabSpecificContentSettings::FromWebContents(web_contents());
921 const ContentSettingsUsagesState
& usages
=
922 content_settings
->geolocation_usages_state();
923 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state
;
924 unsigned int tab_state_flags
= 0;
925 usages
.GetDetailedInfo(&formatted_hosts_per_state
, &tab_state_flags
);
926 // Divide the tab's current geolocation users into sets according to their
928 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_ALLOW
],
929 IDS_GEOLOCATION_BUBBLE_SECTION_ALLOWED
);
931 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_BLOCK
],
932 IDS_GEOLOCATION_BUBBLE_SECTION_DENIED
);
934 if (tab_state_flags
& ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION
) {
935 set_custom_link(l10n_util::GetStringUTF8(
936 IDS_GEOLOCATION_BUBBLE_CLEAR_LINK
));
937 set_custom_link_enabled(true);
938 } else if (tab_state_flags
&
939 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED
) {
940 set_custom_link(l10n_util::GetStringUTF8(
941 IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR
));
945 void ContentSettingDomainListBubbleModel::OnCustomLinkClicked() {
948 // Reset this embedder's entry to default for each of the requesting
949 // origins currently on the page.
950 const GURL
& embedder_url
= web_contents()->GetURL();
951 TabSpecificContentSettings
* content_settings
=
952 TabSpecificContentSettings::FromWebContents(web_contents());
953 const ContentSettingsUsagesState::StateMap
& state_map
=
954 content_settings
->geolocation_usages_state().state_map();
955 HostContentSettingsMap
* settings_map
=
956 profile()->GetHostContentSettingsMap();
958 for (ContentSettingsUsagesState::StateMap::const_iterator it
=
959 state_map
.begin(); it
!= state_map
.end(); ++it
) {
960 settings_map
->SetContentSetting(
961 ContentSettingsPattern::FromURLNoWildcard(it
->first
),
962 ContentSettingsPattern::FromURLNoWildcard(embedder_url
),
963 CONTENT_SETTINGS_TYPE_GEOLOCATION
,
965 CONTENT_SETTING_DEFAULT
);
969 class ContentSettingMixedScriptBubbleModel
970 : public ContentSettingTitleLinkAndCustomModel
{
972 ContentSettingMixedScriptBubbleModel(Delegate
* delegate
,
973 WebContents
* web_contents
,
975 ContentSettingsType content_type
);
977 virtual ~ContentSettingMixedScriptBubbleModel() {}
980 virtual void OnCustomLinkClicked() OVERRIDE
;
983 ContentSettingMixedScriptBubbleModel::ContentSettingMixedScriptBubbleModel(
985 WebContents
* web_contents
,
987 ContentSettingsType content_type
)
988 : ContentSettingTitleLinkAndCustomModel(
989 delegate
, web_contents
, profile
, content_type
) {
990 DCHECK_EQ(content_type
, CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
);
991 set_custom_link_enabled(true);
994 void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
995 content::RecordAction(UserMetricsAction("MixedScript_LoadAnyway_Bubble"));
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()) {
1016 DCHECK_EQ(CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
, content_type
);
1018 TabSpecificContentSettings
* content_settings
=
1019 TabSpecificContentSettings::FromWebContents(web_contents
);
1020 pending_handler_
= content_settings
->pending_protocol_handler();
1021 previous_handler_
= content_settings
->previous_protocol_handler();
1023 base::string16 protocol
;
1024 if (pending_handler_
.protocol() == "mailto") {
1025 protocol
= l10n_util::GetStringUTF16(
1026 IDS_REGISTER_PROTOCOL_HANDLER_MAILTO_NAME
);
1027 } else if (pending_handler_
.protocol() == "webcal") {
1028 protocol
= l10n_util::GetStringUTF16(
1029 IDS_REGISTER_PROTOCOL_HANDLER_WEBCAL_NAME
);
1031 protocol
= base::UTF8ToUTF16(pending_handler_
.protocol());
1034 if (previous_handler_
.IsEmpty()) {
1035 set_title(l10n_util::GetStringFUTF8(
1036 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM
,
1037 pending_handler_
.title(),
1038 base::UTF8ToUTF16(pending_handler_
.url().host()),
1041 set_title(l10n_util::GetStringFUTF8(
1042 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM_REPLACE
,
1043 pending_handler_
.title(),
1044 base::UTF8ToUTF16(pending_handler_
.url().host()),
1045 protocol
, previous_handler_
.title()));
1048 std::string radio_allow_label
=
1049 l10n_util::GetStringFUTF8(IDS_REGISTER_PROTOCOL_HANDLER_ACCEPT
,
1050 pending_handler_
.title());
1051 std::string radio_deny_label
=
1052 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_DENY
);
1053 std::string radio_ignore_label
=
1054 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_IGNORE
);
1056 GURL url
= web_contents
->GetURL();
1057 RadioGroup radio_group
;
1058 radio_group
.url
= url
;
1060 radio_group
.radio_items
.push_back(radio_allow_label
);
1061 radio_group
.radio_items
.push_back(radio_deny_label
);
1062 radio_group
.radio_items
.push_back(radio_ignore_label
);
1063 ContentSetting setting
=
1064 content_settings
->pending_protocol_handler_setting();
1065 if (setting
== CONTENT_SETTING_ALLOW
)
1066 radio_group
.default_item
= RPH_ALLOW
;
1067 else if (setting
== CONTENT_SETTING_BLOCK
)
1068 radio_group
.default_item
= RPH_BLOCK
;
1070 radio_group
.default_item
= RPH_IGNORE
;
1072 selected_item_
= radio_group
.default_item
;
1073 set_radio_group_enabled(true);
1074 set_radio_group(radio_group
);
1077 void ContentSettingRPHBubbleModel::OnRadioClicked(int radio_index
) {
1078 if (selected_item_
== radio_index
)
1081 selected_item_
= radio_index
;
1083 if (radio_index
== RPH_ALLOW
)
1084 RegisterProtocolHandler();
1085 else if (radio_index
== RPH_BLOCK
)
1086 UnregisterProtocolHandler();
1087 else if (radio_index
== RPH_IGNORE
)
1088 IgnoreProtocolHandler();
1093 void ContentSettingRPHBubbleModel::OnDoneClicked() {
1094 // The user has one chance to deal with the RPH content setting UI,
1095 // then we remove it.
1096 TabSpecificContentSettings::FromWebContents(web_contents())->
1097 ClearPendingProtocolHandler();
1098 content::NotificationService::current()->Notify(
1099 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED
,
1100 content::Source
<WebContents
>(web_contents()),
1101 content::NotificationService::NoDetails());
1104 void ContentSettingRPHBubbleModel::RegisterProtocolHandler() {
1105 // A no-op if the handler hasn't been ignored, but needed in case the user
1106 // selects sequences like register/ignore/register.
1107 registry_
->RemoveIgnoredHandler(pending_handler_
);
1109 registry_
->OnAcceptRegisterProtocolHandler(pending_handler_
);
1110 TabSpecificContentSettings::FromWebContents(web_contents())->
1111 set_pending_protocol_handler_setting(CONTENT_SETTING_ALLOW
);
1114 void ContentSettingRPHBubbleModel::UnregisterProtocolHandler() {
1115 registry_
->OnDenyRegisterProtocolHandler(pending_handler_
);
1116 TabSpecificContentSettings::FromWebContents(web_contents())->
1117 set_pending_protocol_handler_setting(CONTENT_SETTING_BLOCK
);
1118 ClearOrSetPreviousHandler();
1121 void ContentSettingRPHBubbleModel::IgnoreProtocolHandler() {
1122 registry_
->OnIgnoreRegisterProtocolHandler(pending_handler_
);
1123 TabSpecificContentSettings::FromWebContents(web_contents())->
1124 set_pending_protocol_handler_setting(CONTENT_SETTING_DEFAULT
);
1125 ClearOrSetPreviousHandler();
1128 void ContentSettingRPHBubbleModel::ClearOrSetPreviousHandler() {
1129 if (previous_handler_
.IsEmpty()) {
1130 registry_
->ClearDefault(pending_handler_
.protocol());
1132 registry_
->OnAcceptRegisterProtocolHandler(previous_handler_
);
1136 class ContentSettingMidiSysExBubbleModel
1137 : public ContentSettingTitleAndLinkModel
{
1139 ContentSettingMidiSysExBubbleModel(Delegate
* delegate
,
1140 WebContents
* web_contents
,
1142 ContentSettingsType content_type
);
1143 virtual ~ContentSettingMidiSysExBubbleModel() {}
1146 void MaybeAddDomainList(const std::set
<std::string
>& hosts
, int title_id
);
1147 void SetDomainsAndCustomLink();
1148 virtual void OnCustomLinkClicked() OVERRIDE
;
1151 ContentSettingMidiSysExBubbleModel::ContentSettingMidiSysExBubbleModel(
1153 WebContents
* web_contents
,
1155 ContentSettingsType content_type
)
1156 : ContentSettingTitleAndLinkModel(
1157 delegate
, web_contents
, profile
, content_type
) {
1158 DCHECK_EQ(CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, content_type
);
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 TabSpecificContentSettings
* content_settings
=
1205 TabSpecificContentSettings::FromWebContents(web_contents());
1206 const ContentSettingsUsagesState::StateMap
& state_map
=
1207 content_settings
->midi_usages_state().state_map();
1208 HostContentSettingsMap
* settings_map
=
1209 profile()->GetHostContentSettingsMap();
1211 for (ContentSettingsUsagesState::StateMap::const_iterator it
=
1212 state_map
.begin(); it
!= state_map
.end(); ++it
) {
1213 settings_map
->SetContentSetting(
1214 ContentSettingsPattern::FromURLNoWildcard(it
->first
),
1215 ContentSettingsPattern::Wildcard(),
1216 CONTENT_SETTINGS_TYPE_MIDI_SYSEX
,
1218 CONTENT_SETTING_DEFAULT
);
1223 ContentSettingBubbleModel
*
1224 ContentSettingBubbleModel::CreateContentSettingBubbleModel(
1226 WebContents
* web_contents
,
1228 ContentSettingsType content_type
) {
1229 if (content_type
== CONTENT_SETTINGS_TYPE_COOKIES
) {
1230 return new ContentSettingCookiesBubbleModel(delegate
, web_contents
, profile
,
1233 if (content_type
== CONTENT_SETTINGS_TYPE_POPUPS
) {
1234 return new ContentSettingPopupBubbleModel(delegate
, web_contents
, profile
,
1237 if (content_type
== CONTENT_SETTINGS_TYPE_GEOLOCATION
) {
1238 return new ContentSettingDomainListBubbleModel(delegate
, web_contents
,
1239 profile
, content_type
);
1241 if (content_type
== CONTENT_SETTINGS_TYPE_MEDIASTREAM
) {
1242 return new ContentSettingMediaStreamBubbleModel(delegate
, web_contents
,
1245 if (content_type
== CONTENT_SETTINGS_TYPE_PLUGINS
) {
1246 return new ContentSettingPluginBubbleModel(delegate
, web_contents
, profile
,
1249 if (content_type
== CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
) {
1250 return new ContentSettingMixedScriptBubbleModel(delegate
, web_contents
,
1251 profile
, content_type
);
1253 if (content_type
== CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
) {
1254 ProtocolHandlerRegistry
* registry
=
1255 ProtocolHandlerRegistryFactory::GetForProfile(profile
);
1256 return new ContentSettingRPHBubbleModel(delegate
, web_contents
, profile
,
1257 registry
, content_type
);
1259 if (content_type
== CONTENT_SETTINGS_TYPE_MIDI_SYSEX
) {
1260 return new ContentSettingMidiSysExBubbleModel(delegate
, web_contents
,
1261 profile
, content_type
);
1263 return new ContentSettingSingleRadioGroup(delegate
, web_contents
, profile
,
1267 ContentSettingBubbleModel::ContentSettingBubbleModel(
1268 WebContents
* web_contents
,
1270 ContentSettingsType content_type
)
1271 : web_contents_(web_contents
),
1273 content_type_(content_type
),
1274 setting_is_managed_(false) {
1275 registrar_
.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED
,
1276 content::Source
<WebContents
>(web_contents
));
1277 registrar_
.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED
,
1278 content::Source
<Profile
>(profile_
));
1281 ContentSettingBubbleModel::~ContentSettingBubbleModel() {
1284 ContentSettingBubbleModel::RadioGroup::RadioGroup() : default_item(0) {}
1286 ContentSettingBubbleModel::RadioGroup::~RadioGroup() {}
1288 ContentSettingBubbleModel::DomainList::DomainList() {}
1290 ContentSettingBubbleModel::DomainList::~DomainList() {}
1292 ContentSettingBubbleModel::MediaMenu::MediaMenu() : disabled(false) {}
1294 ContentSettingBubbleModel::MediaMenu::~MediaMenu() {}
1296 ContentSettingBubbleModel::BubbleContent::BubbleContent()
1297 : radio_group_enabled(false),
1298 custom_link_enabled(false) {
1301 ContentSettingBubbleModel::BubbleContent::~BubbleContent() {}
1303 void ContentSettingBubbleModel::Observe(
1305 const content::NotificationSource
& source
,
1306 const content::NotificationDetails
& details
) {
1307 if (type
== content::NOTIFICATION_WEB_CONTENTS_DESTROYED
) {
1308 DCHECK_EQ(web_contents_
,
1309 content::Source
<WebContents
>(source
).ptr());
1310 web_contents_
= NULL
;
1312 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED
, type
);
1313 DCHECK_EQ(profile_
, content::Source
<Profile
>(source
).ptr());