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_process_host.h"
31 #include "content/public/browser/render_view_host.h"
32 #include "content/public/browser/user_metrics.h"
33 #include "content/public/browser/web_contents.h"
34 #include "content/public/browser/web_contents_delegate.h"
35 #include "grit/generated_resources.h"
36 #include "grit/theme_resources.h"
37 #include "grit/ui_resources.h"
38 #include "net/base/net_util.h"
39 #include "ui/base/l10n/l10n_util.h"
40 #include "ui/base/resource/resource_bundle.h"
42 using base::UserMetricsAction
;
43 using content::WebContents
;
44 using content_settings::SettingInfo
;
45 using content_settings::SettingSource
;
46 using content_settings::SETTING_SOURCE_USER
;
47 using content_settings::SETTING_SOURCE_NONE
;
51 const int kAllowButtonIndex
= 0;
53 struct ContentSettingsTypeIdEntry
{
54 ContentSettingsType type
;
58 int GetIdForContentType(const ContentSettingsTypeIdEntry
* entries
,
60 ContentSettingsType type
) {
61 for (size_t i
= 0; i
< num_entries
; ++i
) {
62 if (entries
[i
].type
== type
)
68 const content::MediaStreamDevice
& GetMediaDeviceById(
69 const std::string
& device_id
,
70 const content::MediaStreamDevices
& devices
) {
71 DCHECK(!devices
.empty());
72 for (content::MediaStreamDevices::const_iterator it
= devices
.begin();
73 it
!= devices
.end(); ++it
) {
74 if (it
->id
== device_id
)
78 // A device with the |device_id| was not found. It is likely that the device
79 // has been unplugged from the OS. Return the first device as the default
81 return *devices
.begin();
86 ContentSettingTitleAndLinkModel::ContentSettingTitleAndLinkModel(
88 WebContents
* web_contents
,
90 ContentSettingsType content_type
)
91 : ContentSettingBubbleModel(web_contents
, profile
, content_type
),
93 // Notifications do not have a bubble.
94 DCHECK_NE(content_type
, CONTENT_SETTINGS_TYPE_NOTIFICATIONS
);
99 void ContentSettingTitleAndLinkModel::SetTitle() {
100 static const ContentSettingsTypeIdEntry kBlockedTitleIDs
[] = {
101 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_TITLE
},
102 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_TITLE
},
103 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_TITLE
},
104 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_MESSAGE
},
105 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_TITLE
},
106 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
,
107 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT
},
108 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
,
109 IDS_BLOCKED_PPAPI_BROKER_TITLE
},
110 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_TITLE
},
112 // Fields as for kBlockedTitleIDs, above.
113 static const ContentSettingsTypeIdEntry kAccessedTitleIDs
[] = {
114 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_ACCESSED_COOKIES_TITLE
},
115 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_TITLE
},
116 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_TITLE
},
118 const ContentSettingsTypeIdEntry
*title_ids
= kBlockedTitleIDs
;
119 size_t num_title_ids
= arraysize(kBlockedTitleIDs
);
120 if (web_contents() &&
121 TabSpecificContentSettings::FromWebContents(
122 web_contents())->IsContentAllowed(content_type()) &&
123 !TabSpecificContentSettings::FromWebContents(
124 web_contents())->IsContentBlocked(content_type())) {
125 title_ids
= kAccessedTitleIDs
;
126 num_title_ids
= arraysize(kAccessedTitleIDs
);
129 GetIdForContentType(title_ids
, num_title_ids
, content_type());
131 set_title(l10n_util::GetStringUTF8(title_id
));
134 void ContentSettingTitleAndLinkModel::SetManageLink() {
135 static const ContentSettingsTypeIdEntry kLinkIDs
[] = {
136 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_LINK
},
137 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_LINK
},
138 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_LINK
},
139 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_LINK
},
140 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_LINK
},
141 {CONTENT_SETTINGS_TYPE_GEOLOCATION
, IDS_GEOLOCATION_BUBBLE_MANAGE_LINK
},
142 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
, IDS_LEARN_MORE
},
143 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
, IDS_HANDLERS_BUBBLE_MANAGE_LINK
},
144 {CONTENT_SETTINGS_TYPE_MEDIASTREAM
, IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK
},
145 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_PPAPI_BROKER_BUBBLE_MANAGE_LINK
},
146 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOADS_LINK
},
147 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK
},
149 set_manage_link(l10n_util::GetStringUTF8(
150 GetIdForContentType(kLinkIDs
, arraysize(kLinkIDs
), content_type())));
153 void ContentSettingTitleAndLinkModel::OnManageLinkClicked() {
155 delegate_
->ShowContentSettingsPage(content_type());
158 class ContentSettingTitleLinkAndCustomModel
159 : public ContentSettingTitleAndLinkModel
{
161 ContentSettingTitleLinkAndCustomModel(Delegate
* delegate
,
162 WebContents
* web_contents
,
164 ContentSettingsType content_type
);
165 virtual ~ContentSettingTitleLinkAndCustomModel() {}
168 void SetCustomLink();
169 virtual void OnCustomLinkClicked() OVERRIDE
{}
172 ContentSettingTitleLinkAndCustomModel::ContentSettingTitleLinkAndCustomModel(
174 WebContents
* web_contents
,
176 ContentSettingsType content_type
)
177 : ContentSettingTitleAndLinkModel(
178 delegate
, web_contents
, profile
, content_type
) {
182 void ContentSettingTitleLinkAndCustomModel::SetCustomLink() {
183 static const ContentSettingsTypeIdEntry kCustomIDs
[] = {
184 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_INFO
},
185 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_LOAD_ALL
},
186 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
, IDS_ALLOW_INSECURE_CONTENT_BUTTON
},
189 GetIdForContentType(kCustomIDs
, arraysize(kCustomIDs
), content_type());
191 set_custom_link(l10n_util::GetStringUTF8(custom_link_id
));
194 class ContentSettingSingleRadioGroup
195 : public ContentSettingTitleLinkAndCustomModel
{
197 ContentSettingSingleRadioGroup(Delegate
* delegate
,
198 WebContents
* web_contents
,
200 ContentSettingsType content_type
);
201 virtual ~ContentSettingSingleRadioGroup();
204 bool settings_changed() const;
205 int selected_item() const { return selected_item_
; }
208 void SetRadioGroup();
209 void AddException(ContentSetting setting
);
210 virtual void OnRadioClicked(int radio_index
) OVERRIDE
;
212 ContentSetting block_setting_
;
216 ContentSettingSingleRadioGroup::ContentSettingSingleRadioGroup(
218 WebContents
* web_contents
,
220 ContentSettingsType content_type
)
221 : ContentSettingTitleLinkAndCustomModel(delegate
, web_contents
, profile
,
223 block_setting_(CONTENT_SETTING_BLOCK
),
228 ContentSettingSingleRadioGroup::~ContentSettingSingleRadioGroup() {
229 if (settings_changed()) {
230 ContentSetting setting
=
231 selected_item_
== kAllowButtonIndex
?
232 CONTENT_SETTING_ALLOW
:
234 AddException(setting
);
238 bool ContentSettingSingleRadioGroup::settings_changed() const {
239 return selected_item_
!= bubble_content().radio_group
.default_item
;
242 // Initialize the radio group by setting the appropriate labels for the
243 // content type and setting the default value based on the content setting.
244 void ContentSettingSingleRadioGroup::SetRadioGroup() {
245 GURL url
= web_contents()->GetURL();
246 base::string16 display_host
;
247 net::AppendFormattedHost(
249 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages
),
252 if (display_host
.empty())
253 display_host
= base::ASCIIToUTF16(url
.spec());
255 TabSpecificContentSettings
* content_settings
=
256 TabSpecificContentSettings::FromWebContents(web_contents());
258 !content_settings
->IsContentBlocked(content_type());
260 content_settings
->IsContentAllowed(content_type()));
262 RadioGroup radio_group
;
263 radio_group
.url
= url
;
265 static const ContentSettingsTypeIdEntry kBlockedAllowIDs
[] = {
266 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_UNBLOCK
},
267 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_UNBLOCK
},
268 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_UNBLOCK
},
269 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_UNBLOCK_ALL
},
270 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_UNBLOCK
},
271 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_BLOCKED_PPAPI_BROKER_UNBLOCK
},
272 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_UNBLOCK
},
274 // Fields as for kBlockedAllowIDs, above.
275 static const ContentSettingsTypeIdEntry kAllowedAllowIDs
[] = {
276 // TODO(bauerb): The string shouldn't be "unblock" (they weren't blocked).
277 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_UNBLOCK
},
278 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_NO_ACTION
},
279 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_NO_ACTION
},
282 std::string radio_allow_label
;
284 int resource_id
= GetIdForContentType(kAllowedAllowIDs
,
285 arraysize(kAllowedAllowIDs
),
287 radio_allow_label
= (content_type() == CONTENT_SETTINGS_TYPE_COOKIES
) ?
288 l10n_util::GetStringFUTF8(resource_id
, display_host
) :
289 l10n_util::GetStringUTF8(resource_id
);
291 radio_allow_label
= l10n_util::GetStringFUTF8(
292 GetIdForContentType(kBlockedAllowIDs
, arraysize(kBlockedAllowIDs
),
297 static const ContentSettingsTypeIdEntry kBlockedBlockIDs
[] = {
298 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_NO_ACTION
},
299 {CONTENT_SETTINGS_TYPE_IMAGES
, IDS_BLOCKED_IMAGES_NO_ACTION
},
300 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, IDS_BLOCKED_JAVASCRIPT_NO_ACTION
},
301 {CONTENT_SETTINGS_TYPE_PLUGINS
, IDS_BLOCKED_PLUGINS_NO_ACTION
},
302 {CONTENT_SETTINGS_TYPE_POPUPS
, IDS_BLOCKED_POPUPS_NO_ACTION
},
303 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_BLOCKED_PPAPI_BROKER_NO_ACTION
},
304 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_BLOCKED_DOWNLOAD_NO_ACTION
},
306 static const ContentSettingsTypeIdEntry kAllowedBlockIDs
[] = {
307 // TODO(bauerb): The string should say "block".
308 {CONTENT_SETTINGS_TYPE_COOKIES
, IDS_BLOCKED_COOKIES_NO_ACTION
},
309 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, IDS_ALLOWED_PPAPI_BROKER_BLOCK
},
310 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, IDS_ALLOWED_DOWNLOAD_BLOCK
},
313 std::string radio_block_label
;
315 int resource_id
= GetIdForContentType(kAllowedBlockIDs
,
316 arraysize(kAllowedBlockIDs
),
318 radio_block_label
= (content_type() == CONTENT_SETTINGS_TYPE_COOKIES
) ?
319 l10n_util::GetStringUTF8(resource_id
) :
320 l10n_util::GetStringFUTF8(resource_id
, display_host
);
322 radio_block_label
= l10n_util::GetStringUTF8(
323 GetIdForContentType(kBlockedBlockIDs
, arraysize(kBlockedBlockIDs
),
327 radio_group
.radio_items
.push_back(radio_allow_label
);
328 radio_group
.radio_items
.push_back(radio_block_label
);
329 ContentSetting setting
;
330 SettingSource setting_source
= SETTING_SOURCE_NONE
;
331 bool setting_is_wildcard
= false;
333 if (content_type() == CONTENT_SETTINGS_TYPE_COOKIES
) {
334 CookieSettings
* cookie_settings
=
335 CookieSettings::Factory::GetForProfile(profile()).get();
336 setting
= cookie_settings
->GetCookieSetting(
337 url
, url
, true, &setting_source
);
340 HostContentSettingsMap
* map
= profile()->GetHostContentSettingsMap();
341 scoped_ptr
<base::Value
> value(map
->GetWebsiteSetting(
342 url
, url
, content_type(), std::string(), &info
));
343 setting
= content_settings::ValueToContentSetting(value
.get());
344 setting_source
= info
.source
;
345 setting_is_wildcard
=
346 info
.primary_pattern
== ContentSettingsPattern::Wildcard() &&
347 info
.secondary_pattern
== ContentSettingsPattern::Wildcard();
350 if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS
&&
351 setting
== CONTENT_SETTING_ALLOW
&&
352 setting_is_wildcard
) {
353 // In the corner case of unrecognized plugins (which are now blocked by
354 // default) we indicate the blocked state in the UI and allow the user to
356 radio_group
.default_item
= 1;
357 } else if (setting
== CONTENT_SETTING_ALLOW
) {
358 radio_group
.default_item
= kAllowButtonIndex
;
359 // |block_setting_| is already set to |CONTENT_SETTING_BLOCK|.
361 radio_group
.default_item
= 1;
362 block_setting_
= setting
;
365 set_setting_is_managed(setting_source
!= SETTING_SOURCE_USER
);
366 if (setting_source
!= SETTING_SOURCE_USER
) {
367 set_radio_group_enabled(false);
369 set_radio_group_enabled(true);
371 selected_item_
= radio_group
.default_item
;
372 set_radio_group(radio_group
);
375 void ContentSettingSingleRadioGroup::AddException(ContentSetting setting
) {
377 profile()->GetHostContentSettingsMap()->AddExceptionForURL(
378 bubble_content().radio_group
.url
,
379 bubble_content().radio_group
.url
,
385 void ContentSettingSingleRadioGroup::OnRadioClicked(int radio_index
) {
386 selected_item_
= radio_index
;
389 class ContentSettingCookiesBubbleModel
: public ContentSettingSingleRadioGroup
{
391 ContentSettingCookiesBubbleModel(Delegate
* delegate
,
392 WebContents
* web_contents
,
394 ContentSettingsType content_type
);
396 virtual ~ContentSettingCookiesBubbleModel();
399 virtual void OnCustomLinkClicked() OVERRIDE
;
402 ContentSettingCookiesBubbleModel::ContentSettingCookiesBubbleModel(
404 WebContents
* web_contents
,
406 ContentSettingsType content_type
)
407 : ContentSettingSingleRadioGroup(
408 delegate
, web_contents
, profile
, content_type
) {
409 DCHECK_EQ(CONTENT_SETTINGS_TYPE_COOKIES
, content_type
);
410 set_custom_link_enabled(true);
413 ContentSettingCookiesBubbleModel::~ContentSettingCookiesBubbleModel() {
414 // On some plattforms e.g. MacOS X it is possible to close a tab while the
415 // cookies settings bubble is open. This resets the web contents to NULL.
416 if (settings_changed() && web_contents()) {
417 CollectedCookiesInfoBarDelegate::Create(
418 InfoBarService::FromWebContents(web_contents()));
422 void ContentSettingCookiesBubbleModel::OnCustomLinkClicked() {
425 content::NotificationService::current()->Notify(
426 chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN
,
427 content::Source
<TabSpecificContentSettings
>(
428 TabSpecificContentSettings::FromWebContents(web_contents())),
429 content::NotificationService::NoDetails());
430 delegate()->ShowCollectedCookiesDialog(web_contents());
433 class ContentSettingPluginBubbleModel
: public ContentSettingSingleRadioGroup
{
435 ContentSettingPluginBubbleModel(Delegate
* delegate
,
436 WebContents
* web_contents
,
438 ContentSettingsType content_type
);
440 virtual ~ContentSettingPluginBubbleModel();
443 virtual void OnCustomLinkClicked() OVERRIDE
;
446 ContentSettingPluginBubbleModel::ContentSettingPluginBubbleModel(
448 WebContents
* web_contents
,
450 ContentSettingsType content_type
)
451 : ContentSettingSingleRadioGroup(
452 delegate
, web_contents
, profile
, content_type
) {
453 DCHECK_EQ(content_type
, CONTENT_SETTINGS_TYPE_PLUGINS
);
454 // Disable the "Run all plugins this time" link if the setting is managed and
455 // can't be controlled by the user or if the user already clicked on the link
456 // and ran all plugins.
457 set_custom_link_enabled(!setting_is_managed() &&
459 TabSpecificContentSettings::FromWebContents(
460 web_contents
)->load_plugins_link_enabled());
463 ContentSettingPluginBubbleModel::~ContentSettingPluginBubbleModel() {
464 if (settings_changed()) {
465 // If the user elected to allow all plugins then run plugins at this time.
466 if (selected_item() == kAllowButtonIndex
)
467 OnCustomLinkClicked();
471 void ContentSettingPluginBubbleModel::OnCustomLinkClicked() {
472 content::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble"));
473 DCHECK(web_contents());
474 #if defined(ENABLE_PLUGINS)
475 // TODO(bauerb): We should send the identifiers of blocked plug-ins here.
476 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
477 web_contents(), true, std::string());
479 set_custom_link_enabled(false);
480 TabSpecificContentSettings::FromWebContents(web_contents())->
481 set_load_plugins_link_enabled(false);
484 class ContentSettingPopupBubbleModel
: public ContentSettingSingleRadioGroup
{
486 ContentSettingPopupBubbleModel(Delegate
* delegate
,
487 WebContents
* web_contents
,
489 ContentSettingsType content_type
);
490 virtual ~ContentSettingPopupBubbleModel() {}
494 virtual void OnPopupClicked(int index
) OVERRIDE
;
497 ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel(
499 WebContents
* web_contents
,
501 ContentSettingsType content_type
)
502 : ContentSettingSingleRadioGroup(
503 delegate
, web_contents
, profile
, content_type
) {
508 void ContentSettingPopupBubbleModel::SetPopups() {
509 std::map
<int32
, GURL
> blocked_popups
=
510 PopupBlockerTabHelper::FromWebContents(web_contents())
511 ->GetBlockedPopupRequests();
512 for (std::map
<int32
, GURL
>::const_iterator iter
= blocked_popups
.begin();
513 iter
!= blocked_popups
.end();
515 std::string
title(iter
->second
.spec());
516 // The popup may not have a valid URL.
518 title
= l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE
);
519 PopupItem
popup_item(
520 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
521 IDR_DEFAULT_FAVICON
),
524 add_popup(popup_item
);
528 void ContentSettingPopupBubbleModel::OnPopupClicked(int index
) {
529 if (web_contents()) {
530 PopupBlockerTabHelper::FromWebContents(web_contents())->
531 ShowBlockedPopup(bubble_content().popup_items
[index
].popup_id
);
535 // The model of the content settings bubble for media settings.
536 class ContentSettingMediaStreamBubbleModel
537 : public ContentSettingTitleAndLinkModel
{
539 ContentSettingMediaStreamBubbleModel(Delegate
* delegate
,
540 WebContents
* web_contents
,
543 virtual ~ContentSettingMediaStreamBubbleModel();
547 // Sets the data for the radio buttons of the bubble.
548 void SetRadioGroup();
549 // Sets the data for the media menus of the bubble.
550 void SetMediaMenus();
551 // Updates the camera and microphone setting with the passed |setting|.
552 void UpdateSettings(ContentSetting setting
);
553 // Updates the camera and microphone default device with the passed |type|
555 void UpdateDefaultDeviceForType(content::MediaStreamType type
,
556 const std::string
& device
);
558 // ContentSettingBubbleModel implementation.
559 virtual void OnRadioClicked(int radio_index
) OVERRIDE
;
560 virtual void OnMediaMenuClicked(content::MediaStreamType type
,
561 const std::string
& selected_device
) OVERRIDE
;
563 // The index of the selected radio item.
565 // The content settings that are associated with the individual radio
567 ContentSetting radio_item_setting_
[2];
568 // The state of the microphone and camera access.
569 TabSpecificContentSettings::MicrophoneCameraState state_
;
572 ContentSettingMediaStreamBubbleModel::ContentSettingMediaStreamBubbleModel(
574 WebContents
* web_contents
,
576 : ContentSettingTitleAndLinkModel(
577 delegate
, web_contents
, profile
, CONTENT_SETTINGS_TYPE_MEDIASTREAM
),
579 state_(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED
) {
581 // Initialize the content settings associated with the individual radio
583 radio_item_setting_
[0] = CONTENT_SETTING_ASK
;
584 radio_item_setting_
[1] = CONTENT_SETTING_BLOCK
;
586 TabSpecificContentSettings
* content_settings
=
587 TabSpecificContentSettings::FromWebContents(web_contents
);
588 state_
= content_settings
->GetMicrophoneCameraState();
595 ContentSettingMediaStreamBubbleModel::~ContentSettingMediaStreamBubbleModel() {
596 // On some platforms (e.g. MacOS X) it is possible to close a tab while the
597 // media stream bubble is open. This resets the web contents to NULL.
601 bool media_setting_changed
= false;
602 for (MediaMenuMap::const_iterator it
= bubble_content().media_menus
.begin();
603 it
!= bubble_content().media_menus
.end(); ++it
) {
604 if (it
->second
.selected_device
.id
!= it
->second
.default_device
.id
) {
605 UpdateDefaultDeviceForType(it
->first
, it
->second
.selected_device
.id
);
606 media_setting_changed
= true;
610 // Update the media settings if the radio button selection was changed.
611 if (selected_item_
!= bubble_content().radio_group
.default_item
) {
612 UpdateSettings(radio_item_setting_
[selected_item_
]);
613 media_setting_changed
= true;
616 // Trigger the reload infobar if the media setting has been changed.
617 if (media_setting_changed
) {
618 MediaSettingChangedInfoBarDelegate::Create(
619 InfoBarService::FromWebContents(web_contents()));
623 void ContentSettingMediaStreamBubbleModel::SetTitle() {
626 case TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED
:
627 // If neither microphone nor camera stream was accessed, then there is no
628 // icon didplayed in the omnibox and no settings bubble availbale. Hence
629 // there is no title.
632 case TabSpecificContentSettings::MICROPHONE_ACCESSED
:
633 title_id
= IDS_MICROPHONE_ACCESSED
;
635 case TabSpecificContentSettings::CAMERA_ACCESSED
:
636 title_id
= IDS_CAMERA_ACCESSED
;
638 case TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED
:
639 title_id
= IDS_MICROPHONE_CAMERA_ALLOWED
;
641 case TabSpecificContentSettings::MICROPHONE_BLOCKED
:
642 title_id
= IDS_MICROPHONE_BLOCKED
;
644 case TabSpecificContentSettings::CAMERA_BLOCKED
:
645 title_id
= IDS_CAMERA_BLOCKED
;
647 case TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED
:
648 title_id
= IDS_MICROPHONE_CAMERA_BLOCKED
;
651 set_title(l10n_util::GetStringUTF8(title_id
));
654 void ContentSettingMediaStreamBubbleModel::SetRadioGroup() {
655 TabSpecificContentSettings
* content_settings
=
656 TabSpecificContentSettings::FromWebContents(web_contents());
657 GURL url
= content_settings
->media_stream_access_origin();
658 RadioGroup radio_group
;
659 radio_group
.url
= url
;
661 base::string16 display_host_utf16
;
662 net::AppendFormattedHost(
664 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages
),
665 &display_host_utf16
);
666 std::string
display_host(base::UTF16ToUTF8(display_host_utf16
));
667 if (display_host
.empty())
668 display_host
= url
.spec();
670 int radio_allow_label_id
= 0;
671 int radio_block_label_id
= 0;
673 case TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED
:
676 case TabSpecificContentSettings::MICROPHONE_ACCESSED
:
677 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION
;
678 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK
;
681 case TabSpecificContentSettings::CAMERA_ACCESSED
:
682 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION
;
683 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK
;
686 case TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED
:
687 radio_allow_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION
;
688 radio_block_label_id
= IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK
;
691 case TabSpecificContentSettings::MICROPHONE_BLOCKED
:
692 if (url
.SchemeIsSecure()) {
693 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_MIC_ALLOW
;
694 radio_item_setting_
[0] = CONTENT_SETTING_ALLOW
;
696 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_MIC_ASK
;
699 radio_block_label_id
= IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION
;
702 case TabSpecificContentSettings::CAMERA_BLOCKED
:
703 if (url
.SchemeIsSecure()) {
704 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW
;
705 radio_item_setting_
[0] = CONTENT_SETTING_ALLOW
;
707 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK
;
710 radio_block_label_id
= IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION
;
713 case TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED
:
714 if (url
.SchemeIsSecure()) {
715 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ALLOW
;
716 radio_item_setting_
[0] = CONTENT_SETTING_ALLOW
;
718 radio_allow_label_id
= IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ASK
;
721 radio_block_label_id
= IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION
;
726 std::string radio_allow_label
= l10n_util::GetStringFUTF8(
727 radio_allow_label_id
, base::UTF8ToUTF16(display_host
));
728 std::string radio_block_label
=
729 l10n_util::GetStringUTF8(radio_block_label_id
);
731 radio_group
.default_item
= selected_item_
;
732 radio_group
.radio_items
.push_back(radio_allow_label
);
733 radio_group
.radio_items
.push_back(radio_block_label
);
735 set_radio_group(radio_group
);
736 set_radio_group_enabled(true);
739 void ContentSettingMediaStreamBubbleModel::UpdateSettings(
740 ContentSetting setting
) {
742 HostContentSettingsMap
* content_settings
=
743 profile()->GetHostContentSettingsMap();
744 TabSpecificContentSettings
* tab_content_settings
=
745 TabSpecificContentSettings::FromWebContents(web_contents());
746 // The same patterns must be used as in other places (e.g. the infobar) in
747 // order to override the existing rule. Otherwise a new rule is created.
748 // TODO(markusheintz): Extract to a helper so that there is only a single
750 ContentSettingsPattern primary_pattern
=
751 ContentSettingsPattern::FromURLNoWildcard(
752 tab_content_settings
->media_stream_access_origin());
753 ContentSettingsPattern secondary_pattern
=
754 ContentSettingsPattern::Wildcard();
755 if (state_
== TabSpecificContentSettings::MICROPHONE_ACCESSED
||
756 state_
== TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED
||
757 state_
== TabSpecificContentSettings::MICROPHONE_BLOCKED
||
758 state_
== TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED
) {
759 content_settings
->SetContentSetting(
760 primary_pattern
, secondary_pattern
,
761 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
, std::string(), setting
);
763 if (state_
== TabSpecificContentSettings::CAMERA_ACCESSED
||
764 state_
== TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED
||
765 state_
== TabSpecificContentSettings::CAMERA_BLOCKED
||
766 state_
== TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED
) {
767 content_settings
->SetContentSetting(
768 primary_pattern
, secondary_pattern
,
769 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
, std::string(), setting
);
774 void ContentSettingMediaStreamBubbleModel::UpdateDefaultDeviceForType(
775 content::MediaStreamType type
,
776 const std::string
& device
) {
777 PrefService
* prefs
= profile()->GetPrefs();
778 if (type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
) {
779 prefs
->SetString(prefs::kDefaultAudioCaptureDevice
, device
);
781 DCHECK_EQ(content::MEDIA_DEVICE_VIDEO_CAPTURE
, type
);
782 prefs
->SetString(prefs::kDefaultVideoCaptureDevice
, device
);
786 void ContentSettingMediaStreamBubbleModel::SetMediaMenus() {
787 TabSpecificContentSettings
* content_settings
=
788 TabSpecificContentSettings::FromWebContents(web_contents());
789 const std::string
& requested_microphone
=
790 content_settings
->media_stream_requested_audio_device();
791 const std::string
& requested_camera
=
792 content_settings
->media_stream_requested_video_device();
794 // Add microphone menu.
795 PrefService
* prefs
= profile()->GetPrefs();
796 MediaCaptureDevicesDispatcher
* dispatcher
=
797 MediaCaptureDevicesDispatcher::GetInstance();
798 const content::MediaStreamDevices
& microphones
=
799 dispatcher
->GetAudioCaptureDevices();
802 (state_
== TabSpecificContentSettings::MICROPHONE_ACCESSED
||
803 state_
== TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED
||
804 state_
== TabSpecificContentSettings::MICROPHONE_BLOCKED
||
805 state_
== TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED
);
806 bool show_camera_menu
=
807 (state_
== TabSpecificContentSettings::CAMERA_ACCESSED
||
808 state_
== TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED
||
809 state_
== TabSpecificContentSettings::CAMERA_BLOCKED
||
810 state_
== TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED
);
811 DCHECK(show_mic_menu
|| show_camera_menu
);
815 mic_menu
.label
= l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_MIC_LABEL
);
816 if (!microphones
.empty()) {
817 std::string preferred_mic
;
818 if (requested_microphone
.empty()) {
819 preferred_mic
= prefs
->GetString(prefs::kDefaultAudioCaptureDevice
);
820 mic_menu
.disabled
= false;
822 // Set the |disabled| to true in order to disable the device selection
823 // menu on the media settings bubble. This must be done if the website
824 // manages the microphone devices itself.
825 preferred_mic
= requested_microphone
;
826 mic_menu
.disabled
= true;
829 mic_menu
.default_device
= GetMediaDeviceById(preferred_mic
, microphones
);
830 mic_menu
.selected_device
= mic_menu
.default_device
;
832 add_media_menu(content::MEDIA_DEVICE_AUDIO_CAPTURE
, mic_menu
);
835 if (show_camera_menu
) {
836 const content::MediaStreamDevices
& cameras
=
837 dispatcher
->GetVideoCaptureDevices();
838 MediaMenu camera_menu
;
840 l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_CAMERA_LABEL
);
841 if (!cameras
.empty()) {
842 std::string preferred_camera
;
843 if (requested_camera
.empty()) {
844 preferred_camera
= prefs
->GetString(prefs::kDefaultVideoCaptureDevice
);
845 camera_menu
.disabled
= false;
847 // Disable the menu since the website is managing the camera devices
849 preferred_camera
= requested_camera
;
850 camera_menu
.disabled
= true;
853 camera_menu
.default_device
=
854 GetMediaDeviceById(preferred_camera
, cameras
);
855 camera_menu
.selected_device
= camera_menu
.default_device
;
857 add_media_menu(content::MEDIA_DEVICE_VIDEO_CAPTURE
, camera_menu
);
861 void ContentSettingMediaStreamBubbleModel::OnRadioClicked(int radio_index
) {
862 selected_item_
= radio_index
;
865 void ContentSettingMediaStreamBubbleModel::OnMediaMenuClicked(
866 content::MediaStreamType type
,
867 const std::string
& selected_device_id
) {
868 DCHECK(type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
||
869 type
== content::MEDIA_DEVICE_VIDEO_CAPTURE
);
870 DCHECK_EQ(1U, bubble_content().media_menus
.count(type
));
871 MediaCaptureDevicesDispatcher
* dispatcher
=
872 MediaCaptureDevicesDispatcher::GetInstance();
873 const content::MediaStreamDevices
& devices
=
874 (type
== content::MEDIA_DEVICE_AUDIO_CAPTURE
) ?
875 dispatcher
->GetAudioCaptureDevices() :
876 dispatcher
->GetVideoCaptureDevices();
877 set_selected_device(GetMediaDeviceById(selected_device_id
, devices
));
880 class ContentSettingDomainListBubbleModel
881 : public ContentSettingTitleAndLinkModel
{
883 ContentSettingDomainListBubbleModel(Delegate
* delegate
,
884 WebContents
* web_contents
,
886 ContentSettingsType content_type
);
887 virtual ~ContentSettingDomainListBubbleModel() {}
890 void MaybeAddDomainList(const std::set
<std::string
>& hosts
, int title_id
);
891 void SetDomainsAndCustomLink();
892 virtual void OnCustomLinkClicked() OVERRIDE
;
895 ContentSettingDomainListBubbleModel::ContentSettingDomainListBubbleModel(
897 WebContents
* web_contents
,
899 ContentSettingsType content_type
)
900 : ContentSettingTitleAndLinkModel(
901 delegate
, web_contents
, profile
, content_type
) {
902 DCHECK_EQ(CONTENT_SETTINGS_TYPE_GEOLOCATION
, content_type
) <<
903 "SetDomains currently only supports geolocation content type";
904 SetDomainsAndCustomLink();
907 void ContentSettingDomainListBubbleModel::MaybeAddDomainList(
908 const std::set
<std::string
>& hosts
, int title_id
) {
909 if (!hosts
.empty()) {
910 DomainList domain_list
;
911 domain_list
.title
= l10n_util::GetStringUTF8(title_id
);
912 domain_list
.hosts
= hosts
;
913 add_domain_list(domain_list
);
917 void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() {
918 TabSpecificContentSettings
* content_settings
=
919 TabSpecificContentSettings::FromWebContents(web_contents());
920 const ContentSettingsUsagesState
& usages
=
921 content_settings
->geolocation_usages_state();
922 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state
;
923 unsigned int tab_state_flags
= 0;
924 usages
.GetDetailedInfo(&formatted_hosts_per_state
, &tab_state_flags
);
925 // Divide the tab's current geolocation users into sets according to their
927 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_ALLOW
],
928 IDS_GEOLOCATION_BUBBLE_SECTION_ALLOWED
);
930 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_BLOCK
],
931 IDS_GEOLOCATION_BUBBLE_SECTION_DENIED
);
933 if (tab_state_flags
& ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION
) {
934 set_custom_link(l10n_util::GetStringUTF8(
935 IDS_GEOLOCATION_BUBBLE_CLEAR_LINK
));
936 set_custom_link_enabled(true);
937 } else if (tab_state_flags
&
938 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED
) {
939 set_custom_link(l10n_util::GetStringUTF8(
940 IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR
));
944 void ContentSettingDomainListBubbleModel::OnCustomLinkClicked() {
947 // Reset this embedder's entry to default for each of the requesting
948 // origins currently on the page.
949 const GURL
& embedder_url
= web_contents()->GetURL();
950 TabSpecificContentSettings
* content_settings
=
951 TabSpecificContentSettings::FromWebContents(web_contents());
952 const ContentSettingsUsagesState::StateMap
& state_map
=
953 content_settings
->geolocation_usages_state().state_map();
954 HostContentSettingsMap
* settings_map
=
955 profile()->GetHostContentSettingsMap();
957 for (ContentSettingsUsagesState::StateMap::const_iterator it
=
958 state_map
.begin(); it
!= state_map
.end(); ++it
) {
959 settings_map
->SetContentSetting(
960 ContentSettingsPattern::FromURLNoWildcard(it
->first
),
961 ContentSettingsPattern::FromURLNoWildcard(embedder_url
),
962 CONTENT_SETTINGS_TYPE_GEOLOCATION
,
964 CONTENT_SETTING_DEFAULT
);
968 class ContentSettingMixedScriptBubbleModel
969 : public ContentSettingTitleLinkAndCustomModel
{
971 ContentSettingMixedScriptBubbleModel(Delegate
* delegate
,
972 WebContents
* web_contents
,
974 ContentSettingsType content_type
);
976 virtual ~ContentSettingMixedScriptBubbleModel() {}
979 virtual void OnCustomLinkClicked() OVERRIDE
;
982 ContentSettingMixedScriptBubbleModel::ContentSettingMixedScriptBubbleModel(
984 WebContents
* web_contents
,
986 ContentSettingsType content_type
)
987 : ContentSettingTitleLinkAndCustomModel(
988 delegate
, web_contents
, profile
, content_type
) {
989 DCHECK_EQ(content_type
, CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
);
990 set_custom_link_enabled(true);
993 void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
994 content::RecordAction(UserMetricsAction("MixedScript_LoadAnyway_Bubble"));
995 DCHECK(web_contents());
996 content::RenderViewHost
* host
= web_contents()->GetRenderViewHost();
997 host
->Send(new ChromeViewMsg_SetAllowRunningInsecureContent(
998 host
->GetRoutingID(), true));
1001 ContentSettingRPHBubbleModel::ContentSettingRPHBubbleModel(
1003 WebContents
* web_contents
,
1005 ProtocolHandlerRegistry
* registry
,
1006 ContentSettingsType content_type
)
1007 : ContentSettingTitleAndLinkModel(
1008 delegate
, web_contents
, profile
, content_type
),
1010 registry_(registry
),
1011 pending_handler_(ProtocolHandler::EmptyProtocolHandler()),
1012 previous_handler_(ProtocolHandler::EmptyProtocolHandler()) {
1014 DCHECK_EQ(CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
, content_type
);
1016 TabSpecificContentSettings
* content_settings
=
1017 TabSpecificContentSettings::FromWebContents(web_contents
);
1018 pending_handler_
= content_settings
->pending_protocol_handler();
1019 previous_handler_
= content_settings
->previous_protocol_handler();
1021 base::string16 protocol
;
1022 if (pending_handler_
.protocol() == "mailto") {
1023 protocol
= l10n_util::GetStringUTF16(
1024 IDS_REGISTER_PROTOCOL_HANDLER_MAILTO_NAME
);
1025 } else if (pending_handler_
.protocol() == "webcal") {
1026 protocol
= l10n_util::GetStringUTF16(
1027 IDS_REGISTER_PROTOCOL_HANDLER_WEBCAL_NAME
);
1029 protocol
= base::UTF8ToUTF16(pending_handler_
.protocol());
1032 if (previous_handler_
.IsEmpty()) {
1033 set_title(l10n_util::GetStringFUTF8(
1034 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM
,
1035 pending_handler_
.title(),
1036 base::UTF8ToUTF16(pending_handler_
.url().host()),
1039 set_title(l10n_util::GetStringFUTF8(
1040 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM_REPLACE
,
1041 pending_handler_
.title(),
1042 base::UTF8ToUTF16(pending_handler_
.url().host()),
1043 protocol
, previous_handler_
.title()));
1046 std::string radio_allow_label
=
1047 l10n_util::GetStringFUTF8(IDS_REGISTER_PROTOCOL_HANDLER_ACCEPT
,
1048 pending_handler_
.title());
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 // TODO(toyoshim): Should share as many code with geolocation as possible.
1135 class ContentSettingMIDISysExBubbleModel
1136 : public ContentSettingTitleAndLinkModel
{
1138 ContentSettingMIDISysExBubbleModel(Delegate
* delegate
,
1139 WebContents
* web_contents
,
1141 ContentSettingsType content_type
);
1142 virtual ~ContentSettingMIDISysExBubbleModel() {}
1145 void MaybeAddDomainList(const std::set
<std::string
>& hosts
, int title_id
);
1146 void SetDomainsAndCustomLink();
1147 virtual void OnCustomLinkClicked() OVERRIDE
;
1150 ContentSettingMIDISysExBubbleModel::ContentSettingMIDISysExBubbleModel(
1152 WebContents
* web_contents
,
1154 ContentSettingsType content_type
)
1155 : ContentSettingTitleAndLinkModel(
1156 delegate
, web_contents
, profile
, content_type
) {
1157 DCHECK_EQ(CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, content_type
);
1158 SetDomainsAndCustomLink();
1161 void ContentSettingMIDISysExBubbleModel::MaybeAddDomainList(
1162 const std::set
<std::string
>& hosts
, int title_id
) {
1163 if (!hosts
.empty()) {
1164 DomainList domain_list
;
1165 domain_list
.title
= l10n_util::GetStringUTF8(title_id
);
1166 domain_list
.hosts
= hosts
;
1167 add_domain_list(domain_list
);
1171 void ContentSettingMIDISysExBubbleModel::SetDomainsAndCustomLink() {
1172 TabSpecificContentSettings
* content_settings
=
1173 TabSpecificContentSettings::FromWebContents(web_contents());
1174 const ContentSettingsUsagesState
& usages_state
=
1175 content_settings
->midi_usages_state();
1176 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state
;
1177 unsigned int tab_state_flags
= 0;
1178 usages_state
.GetDetailedInfo(&formatted_hosts_per_state
, &tab_state_flags
);
1179 // Divide the tab's current MIDI sysex users into sets according to their
1180 // permission state.
1181 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_ALLOW
],
1182 IDS_MIDI_SYSEX_BUBBLE_ALLOWED
);
1184 MaybeAddDomainList(formatted_hosts_per_state
[CONTENT_SETTING_BLOCK
],
1185 IDS_MIDI_SYSEX_BUBBLE_DENIED
);
1187 if (tab_state_flags
& ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION
) {
1188 set_custom_link(l10n_util::GetStringUTF8(
1189 IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK
));
1190 set_custom_link_enabled(true);
1191 } else if (tab_state_flags
&
1192 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED
) {
1193 set_custom_link(l10n_util::GetStringUTF8(
1194 IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR
));
1198 void ContentSettingMIDISysExBubbleModel::OnCustomLinkClicked() {
1199 if (!web_contents())
1201 // Reset this embedder's entry to default for each of the requesting
1202 // origins currently on the page.
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::Wildcard(),
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::GetForProfile(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());