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/cookie_settings.h"
12 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
13 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
14 #include "chrome/browser/favicon/favicon_tab_helper.h"
15 #include "chrome/browser/infobars/infobar_service.h"
16 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
17 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
20 #include "chrome/browser/ui/browser_navigator.h"
21 #include "chrome/browser/ui/collected_cookies_infobar_delegate.h"
22 #include "chrome/browser/ui/content_settings/content_setting_bubble_model_delegate.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/common/render_messages.h"
26 #include "chrome/grit/generated_resources.h"
27 #include "components/content_settings/core/browser/content_settings_utils.h"
28 #include "components/content_settings/core/common/content_settings.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/components_strings.h"
37 #include "net/base/net_util.h"
38 #include "ui/base/l10n/l10n_util.h"
39 #include "ui/base/resource/resource_bundle.h"
40 #include "ui/resources/grit/ui_resources.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);
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 void ContentSettingTitleAndLinkModel::SetLearnMoreLink() {
160 static const ContentSettingsTypeIdEntry kLearnMoreIDs[] = {
161 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_LEARN_MORE},
164 GetIdForContentType(kLearnMoreIDs, arraysize(kLearnMoreIDs),
167 set_learn_more_link(l10n_util::GetStringUTF8(learn_more_id));
170 void ContentSettingTitleAndLinkModel::OnLearnMoreLinkClicked() {
172 delegate_->ShowLearnMorePage(content_type());
175 class ContentSettingTitleLinkAndCustomModel
176 : public ContentSettingTitleAndLinkModel {
178 ContentSettingTitleLinkAndCustomModel(Delegate* delegate,
179 WebContents* web_contents,
181 ContentSettingsType content_type);
182 ~ContentSettingTitleLinkAndCustomModel() override {}
185 void SetCustomLink();
186 void OnCustomLinkClicked() override {}
189 ContentSettingTitleLinkAndCustomModel::ContentSettingTitleLinkAndCustomModel(
191 WebContents* web_contents,
193 ContentSettingsType content_type)
194 : ContentSettingTitleAndLinkModel(
195 delegate, web_contents, profile, content_type) {
199 void ContentSettingTitleLinkAndCustomModel::SetCustomLink() {
200 static const ContentSettingsTypeIdEntry kCustomIDs[] = {
201 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_INFO},
202 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LOAD_ALL},
203 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_ALLOW_INSECURE_CONTENT_BUTTON},
206 GetIdForContentType(kCustomIDs, arraysize(kCustomIDs), content_type());
208 set_custom_link(l10n_util::GetStringUTF8(custom_link_id));
211 class ContentSettingSingleRadioGroup
212 : public ContentSettingTitleLinkAndCustomModel {
214 ContentSettingSingleRadioGroup(Delegate* delegate,
215 WebContents* web_contents,
217 ContentSettingsType content_type);
218 ~ContentSettingSingleRadioGroup() override;
221 bool settings_changed() const;
222 int selected_item() const { return selected_item_; }
225 void SetRadioGroup();
226 void AddException(ContentSetting setting);
227 void OnRadioClicked(int radio_index) override;
229 ContentSetting block_setting_;
233 ContentSettingSingleRadioGroup::ContentSettingSingleRadioGroup(
235 WebContents* web_contents,
237 ContentSettingsType content_type)
238 : ContentSettingTitleLinkAndCustomModel(delegate, web_contents, profile,
240 block_setting_(CONTENT_SETTING_BLOCK),
245 ContentSettingSingleRadioGroup::~ContentSettingSingleRadioGroup() {
246 if (settings_changed()) {
247 ContentSetting setting =
248 selected_item_ == kAllowButtonIndex ?
249 CONTENT_SETTING_ALLOW :
251 AddException(setting);
255 bool ContentSettingSingleRadioGroup::settings_changed() const {
256 return selected_item_ != bubble_content().radio_group.default_item;
259 // Initialize the radio group by setting the appropriate labels for the
260 // content type and setting the default value based on the content setting.
261 void ContentSettingSingleRadioGroup::SetRadioGroup() {
262 GURL url = web_contents()->GetURL();
263 base::string16 display_host;
264 net::AppendFormattedHost(
266 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
269 if (display_host.empty())
270 display_host = base::ASCIIToUTF16(url.spec());
272 TabSpecificContentSettings* content_settings =
273 TabSpecificContentSettings::FromWebContents(web_contents());
275 !content_settings->IsContentBlocked(content_type());
277 content_settings->IsContentAllowed(content_type()));
279 RadioGroup radio_group;
280 radio_group.url = url;
282 static const ContentSettingsTypeIdEntry kBlockedAllowIDs[] = {
283 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
284 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_UNBLOCK},
285 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_UNBLOCK},
286 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_UNBLOCK_ALL},
287 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_UNBLOCK},
288 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_UNBLOCK},
289 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_UNBLOCK},
291 // Fields as for kBlockedAllowIDs, above.
292 static const ContentSettingsTypeIdEntry kAllowedAllowIDs[] = {
293 // TODO(bauerb): The string shouldn't be "unblock" (they weren't blocked).
294 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
295 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_NO_ACTION},
296 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_NO_ACTION},
299 std::string radio_allow_label;
301 int resource_id = GetIdForContentType(kAllowedAllowIDs,
302 arraysize(kAllowedAllowIDs),
304 radio_allow_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
305 l10n_util::GetStringFUTF8(resource_id, display_host) :
306 l10n_util::GetStringUTF8(resource_id);
308 radio_allow_label = l10n_util::GetStringFUTF8(
309 GetIdForContentType(kBlockedAllowIDs, arraysize(kBlockedAllowIDs),
314 static const ContentSettingsTypeIdEntry kBlockedBlockIDs[] = {
315 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
316 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_NO_ACTION},
317 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_NO_ACTION},
318 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_NO_ACTION},
319 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_NO_ACTION},
320 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_NO_ACTION},
321 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_NO_ACTION},
323 static const ContentSettingsTypeIdEntry kAllowedBlockIDs[] = {
324 // TODO(bauerb): The string should say "block".
325 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
326 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_BLOCK},
327 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_BLOCK},
330 std::string radio_block_label;
332 int resource_id = GetIdForContentType(kAllowedBlockIDs,
333 arraysize(kAllowedBlockIDs),
335 radio_block_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
336 l10n_util::GetStringUTF8(resource_id) :
337 l10n_util::GetStringFUTF8(resource_id, display_host);
339 radio_block_label = l10n_util::GetStringUTF8(
340 GetIdForContentType(kBlockedBlockIDs, arraysize(kBlockedBlockIDs),
344 radio_group.radio_items.push_back(radio_allow_label);
345 radio_group.radio_items.push_back(radio_block_label);
346 ContentSetting setting;
347 SettingSource setting_source = SETTING_SOURCE_NONE;
348 bool setting_is_wildcard = false;
350 if (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) {
351 CookieSettings* cookie_settings =
352 CookieSettings::Factory::GetForProfile(profile()).get();
353 setting = cookie_settings->GetCookieSetting(
354 url, url, true, &setting_source);
357 HostContentSettingsMap* map = profile()->GetHostContentSettingsMap();
358 scoped_ptr<base::Value> value =
359 map->GetWebsiteSetting(url, url, content_type(), std::string(), &info);
360 setting = content_settings::ValueToContentSetting(value.get());
361 setting_source = info.source;
362 setting_is_wildcard =
363 info.primary_pattern == ContentSettingsPattern::Wildcard() &&
364 info.secondary_pattern == ContentSettingsPattern::Wildcard();
367 if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS &&
368 setting == CONTENT_SETTING_ALLOW &&
369 setting_is_wildcard) {
370 // In the corner case of unrecognized plugins (which are now blocked by
371 // default) we indicate the blocked state in the UI and allow the user to
373 radio_group.default_item = 1;
374 } else if (setting == CONTENT_SETTING_ALLOW) {
375 radio_group.default_item = kAllowButtonIndex;
376 // |block_setting_| is already set to |CONTENT_SETTING_BLOCK|.
378 radio_group.default_item = 1;
379 block_setting_ = setting;
382 set_setting_is_managed(setting_source != SETTING_SOURCE_USER);
383 if (setting_source != SETTING_SOURCE_USER) {
384 set_radio_group_enabled(false);
386 set_radio_group_enabled(true);
388 selected_item_ = radio_group.default_item;
389 set_radio_group(radio_group);
392 void ContentSettingSingleRadioGroup::AddException(ContentSetting setting) {
394 profile()->GetHostContentSettingsMap()->AddExceptionForURL(
395 bubble_content().radio_group.url,
396 bubble_content().radio_group.url,
402 void ContentSettingSingleRadioGroup::OnRadioClicked(int radio_index) {
403 selected_item_ = radio_index;
406 class ContentSettingCookiesBubbleModel : public ContentSettingSingleRadioGroup {
408 ContentSettingCookiesBubbleModel(Delegate* delegate,
409 WebContents* web_contents,
411 ContentSettingsType content_type);
413 ~ContentSettingCookiesBubbleModel() override;
416 void OnCustomLinkClicked() override;
419 ContentSettingCookiesBubbleModel::ContentSettingCookiesBubbleModel(
421 WebContents* web_contents,
423 ContentSettingsType content_type)
424 : ContentSettingSingleRadioGroup(
425 delegate, web_contents, profile, content_type) {
426 DCHECK_EQ(CONTENT_SETTINGS_TYPE_COOKIES, content_type);
427 set_custom_link_enabled(true);
430 ContentSettingCookiesBubbleModel::~ContentSettingCookiesBubbleModel() {
431 // On some plattforms e.g. MacOS X it is possible to close a tab while the
432 // cookies settings bubble is open. This resets the web contents to NULL.
433 if (settings_changed() && web_contents()) {
434 CollectedCookiesInfoBarDelegate::Create(
435 InfoBarService::FromWebContents(web_contents()));
439 void ContentSettingCookiesBubbleModel::OnCustomLinkClicked() {
442 content::NotificationService::current()->Notify(
443 chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN,
444 content::Source<TabSpecificContentSettings>(
445 TabSpecificContentSettings::FromWebContents(web_contents())),
446 content::NotificationService::NoDetails());
447 delegate()->ShowCollectedCookiesDialog(web_contents());
450 class ContentSettingPluginBubbleModel : public ContentSettingSingleRadioGroup {
452 ContentSettingPluginBubbleModel(Delegate* delegate,
453 WebContents* web_contents,
455 ContentSettingsType content_type);
457 ~ContentSettingPluginBubbleModel() override;
460 void OnCustomLinkClicked() override;
463 ContentSettingPluginBubbleModel::ContentSettingPluginBubbleModel(
465 WebContents* web_contents,
467 ContentSettingsType content_type)
468 : ContentSettingSingleRadioGroup(
469 delegate, web_contents, profile, content_type) {
470 DCHECK_EQ(content_type, CONTENT_SETTINGS_TYPE_PLUGINS);
471 // Disable the "Run all plugins this time" link if the setting is managed and
472 // can't be controlled by the user or if the user already clicked on the link
473 // and ran all plugins.
474 set_custom_link_enabled(!setting_is_managed() &&
476 TabSpecificContentSettings::FromWebContents(
477 web_contents)->load_plugins_link_enabled());
480 ContentSettingPluginBubbleModel::~ContentSettingPluginBubbleModel() {
481 if (settings_changed()) {
482 // If the user elected to allow all plugins then run plugins at this time.
483 if (selected_item() == kAllowButtonIndex)
484 OnCustomLinkClicked();
488 void ContentSettingPluginBubbleModel::OnCustomLinkClicked() {
489 content::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble"));
490 DCHECK(web_contents());
491 #if defined(ENABLE_PLUGINS)
492 // TODO(bauerb): We should send the identifiers of blocked plug-ins here.
493 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
494 web_contents(), true, std::string());
496 set_custom_link_enabled(false);
497 TabSpecificContentSettings::FromWebContents(web_contents())->
498 set_load_plugins_link_enabled(false);
501 class ContentSettingPopupBubbleModel : public ContentSettingSingleRadioGroup {
503 ContentSettingPopupBubbleModel(Delegate* delegate,
504 WebContents* web_contents,
506 ContentSettingsType content_type);
507 ~ContentSettingPopupBubbleModel() override {}
511 void OnPopupClicked(int index) override;
514 ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel(
516 WebContents* web_contents,
518 ContentSettingsType content_type)
519 : ContentSettingSingleRadioGroup(
520 delegate, web_contents, profile, content_type) {
525 void ContentSettingPopupBubbleModel::SetPopups() {
526 std::map<int32, GURL> blocked_popups =
527 PopupBlockerTabHelper::FromWebContents(web_contents())
528 ->GetBlockedPopupRequests();
529 for (std::map<int32, GURL>::const_iterator iter = blocked_popups.begin();
530 iter != blocked_popups.end();
532 std::string title(iter->second.spec());
533 // The popup may not have a valid URL.
535 title = l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE);
536 PopupItem popup_item(
537 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
538 IDR_DEFAULT_FAVICON),
541 add_popup(popup_item);
545 void ContentSettingPopupBubbleModel::OnPopupClicked(int index) {
546 if (web_contents()) {
547 PopupBlockerTabHelper::FromWebContents(web_contents())->
548 ShowBlockedPopup(bubble_content().popup_items[index].popup_id);
552 // The model of the content settings bubble for media settings.
553 class ContentSettingMediaStreamBubbleModel
554 : public ContentSettingTitleAndLinkModel {
556 ContentSettingMediaStreamBubbleModel(Delegate* delegate,
557 WebContents* web_contents,
560 ~ContentSettingMediaStreamBubbleModel() override;
564 // Sets the data for the radio buttons of the bubble.
565 void SetRadioGroup();
566 // Sets the data for the media menus of the bubble.
567 void SetMediaMenus();
568 void SetCustomLink();
569 // Updates the camera and microphone setting with the passed |setting|.
570 void UpdateSettings(ContentSetting setting);
571 // Updates the camera and microphone default device with the passed |type|
573 void UpdateDefaultDeviceForType(content::MediaStreamType type,
574 const std::string& device);
576 // ContentSettingBubbleModel implementation.
577 void OnRadioClicked(int radio_index) override;
578 void OnMediaMenuClicked(content::MediaStreamType type,
579 const std::string& selected_device) override;
581 // The index of the selected radio item.
583 // The content settings that are associated with the individual radio
585 ContentSetting radio_item_setting_[2];
586 // The state of the microphone and camera access.
587 TabSpecificContentSettings::MicrophoneCameraState state_;
590 ContentSettingMediaStreamBubbleModel::ContentSettingMediaStreamBubbleModel(
592 WebContents* web_contents,
594 : ContentSettingTitleAndLinkModel(
595 delegate, web_contents, profile, CONTENT_SETTINGS_TYPE_MEDIASTREAM),
597 state_(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED) {
599 // Initialize the content settings associated with the individual radio
601 radio_item_setting_[0] = CONTENT_SETTING_ASK;
602 radio_item_setting_[1] = CONTENT_SETTING_BLOCK;
604 TabSpecificContentSettings* content_settings =
605 TabSpecificContentSettings::FromWebContents(web_contents);
606 state_ = content_settings->GetMicrophoneCameraState();
607 DCHECK(state_ & (TabSpecificContentSettings::MICROPHONE_ACCESSED |
608 TabSpecificContentSettings::CAMERA_ACCESSED));
616 ContentSettingMediaStreamBubbleModel::~ContentSettingMediaStreamBubbleModel() {
617 // On some platforms (e.g. MacOS X) it is possible to close a tab while the
618 // media stream bubble is open. This resets the web contents to NULL.
622 for (MediaMenuMap::const_iterator it = bubble_content().media_menus.begin();
623 it != bubble_content().media_menus.end(); ++it) {
624 if (it->second.selected_device.id != it->second.default_device.id) {
625 UpdateDefaultDeviceForType(it->first, it->second.selected_device.id);
629 // Update the media settings if the radio button selection was changed.
630 if (selected_item_ != bubble_content().radio_group.default_item) {
631 UpdateSettings(radio_item_setting_[selected_item_]);
635 void ContentSettingMediaStreamBubbleModel::SetTitle() {
636 DCHECK_NE(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED, state_);
638 if (state_ & TabSpecificContentSettings::MICROPHONE_BLOCKED) {
639 title_id = (state_ & TabSpecificContentSettings::CAMERA_BLOCKED) ?
640 IDS_MICROPHONE_CAMERA_BLOCKED : IDS_MICROPHONE_BLOCKED;
641 } else if (state_ & TabSpecificContentSettings::CAMERA_BLOCKED) {
642 title_id = IDS_CAMERA_BLOCKED;
643 } else if (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) {
644 title_id = (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) ?
645 IDS_MICROPHONE_CAMERA_ALLOWED : IDS_MICROPHONE_ACCESSED;
646 } else if (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) {
647 title_id = IDS_CAMERA_ACCESSED;
649 set_title(l10n_util::GetStringUTF8(title_id));
652 void ContentSettingMediaStreamBubbleModel::SetRadioGroup() {
653 TabSpecificContentSettings* content_settings =
654 TabSpecificContentSettings::FromWebContents(web_contents());
655 GURL url = content_settings->media_stream_access_origin();
656 RadioGroup radio_group;
657 radio_group.url = url;
659 base::string16 display_host_utf16;
660 net::AppendFormattedHost(
662 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
663 &display_host_utf16);
664 std::string display_host(base::UTF16ToUTF8(display_host_utf16));
665 if (display_host.empty())
666 display_host = url.spec();
668 bool is_mic = (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) != 0;
669 bool is_cam = (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) != 0;
670 DCHECK(is_mic || is_cam);
671 int radio_allow_label_id = 0;
672 int radio_block_label_id = 0;
673 if (state_ & (TabSpecificContentSettings::MICROPHONE_BLOCKED |
674 TabSpecificContentSettings::CAMERA_BLOCKED)) {
675 if (url.SchemeIsSecure()) {
676 radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
677 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW;
679 radio_allow_label_id = is_cam ?
680 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ALLOW :
681 IDS_BLOCKED_MEDIASTREAM_MIC_ALLOW;
683 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK;
685 radio_allow_label_id = is_cam ?
686 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ASK :
687 IDS_BLOCKED_MEDIASTREAM_MIC_ASK;
689 radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION;
691 radio_block_label_id = is_cam ?
692 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION :
693 IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION;
695 if (is_mic && is_cam) {
696 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION;
697 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK;
699 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION;
700 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK;
702 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION;
703 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK;
707 (is_mic && content_settings->IsContentBlocked(
708 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC)) ||
709 (is_cam && content_settings->IsContentBlocked(
710 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA)) ? 1 : 0;
712 std::string radio_allow_label = l10n_util::GetStringFUTF8(
713 radio_allow_label_id, base::UTF8ToUTF16(display_host));
714 std::string radio_block_label =
715 l10n_util::GetStringUTF8(radio_block_label_id);
717 radio_group.default_item = selected_item_;
718 radio_group.radio_items.push_back(radio_allow_label);
719 radio_group.radio_items.push_back(radio_block_label);
721 set_radio_group(radio_group);
722 set_radio_group_enabled(true);
725 void ContentSettingMediaStreamBubbleModel::UpdateSettings(
726 ContentSetting setting) {
728 HostContentSettingsMap* content_settings =
729 profile()->GetHostContentSettingsMap();
730 TabSpecificContentSettings* tab_content_settings =
731 TabSpecificContentSettings::FromWebContents(web_contents());
732 // The same patterns must be used as in other places (e.g. the infobar) in
733 // order to override the existing rule. Otherwise a new rule is created.
734 // TODO(markusheintz): Extract to a helper so that there is only a single
736 ContentSettingsPattern primary_pattern =
737 ContentSettingsPattern::FromURLNoWildcard(
738 tab_content_settings->media_stream_access_origin());
739 ContentSettingsPattern secondary_pattern =
740 ContentSettingsPattern::Wildcard();
741 if (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) {
742 content_settings->SetContentSetting(
743 primary_pattern, secondary_pattern,
744 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string(), setting);
746 if (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) {
747 content_settings->SetContentSetting(
748 primary_pattern, secondary_pattern,
749 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string(), setting);
754 void ContentSettingMediaStreamBubbleModel::UpdateDefaultDeviceForType(
755 content::MediaStreamType type,
756 const std::string& device) {
757 PrefService* prefs = profile()->GetPrefs();
758 if (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
759 prefs->SetString(prefs::kDefaultAudioCaptureDevice, device);
761 DCHECK_EQ(content::MEDIA_DEVICE_VIDEO_CAPTURE, type);
762 prefs->SetString(prefs::kDefaultVideoCaptureDevice, device);
766 void ContentSettingMediaStreamBubbleModel::SetMediaMenus() {
767 TabSpecificContentSettings* content_settings =
768 TabSpecificContentSettings::FromWebContents(web_contents());
769 const std::string& requested_microphone =
770 content_settings->media_stream_requested_audio_device();
771 const std::string& requested_camera =
772 content_settings->media_stream_requested_video_device();
774 // Add microphone menu.
775 PrefService* prefs = profile()->GetPrefs();
776 MediaCaptureDevicesDispatcher* dispatcher =
777 MediaCaptureDevicesDispatcher::GetInstance();
778 const content::MediaStreamDevices& microphones =
779 dispatcher->GetAudioCaptureDevices();
781 if (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) {
783 mic_menu.label = l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_MIC_LABEL);
784 if (!microphones.empty()) {
785 std::string preferred_mic;
786 if (requested_microphone.empty()) {
787 preferred_mic = prefs->GetString(prefs::kDefaultAudioCaptureDevice);
788 mic_menu.disabled = false;
790 // Set the |disabled| to true in order to disable the device selection
791 // menu on the media settings bubble. This must be done if the website
792 // manages the microphone devices itself.
793 preferred_mic = requested_microphone;
794 mic_menu.disabled = true;
797 mic_menu.default_device = GetMediaDeviceById(preferred_mic, microphones);
798 mic_menu.selected_device = mic_menu.default_device;
800 add_media_menu(content::MEDIA_DEVICE_AUDIO_CAPTURE, mic_menu);
803 if (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) {
804 const content::MediaStreamDevices& cameras =
805 dispatcher->GetVideoCaptureDevices();
806 MediaMenu camera_menu;
808 l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_CAMERA_LABEL);
809 if (!cameras.empty()) {
810 std::string preferred_camera;
811 if (requested_camera.empty()) {
812 preferred_camera = prefs->GetString(prefs::kDefaultVideoCaptureDevice);
813 camera_menu.disabled = false;
815 // Disable the menu since the website is managing the camera devices
817 preferred_camera = requested_camera;
818 camera_menu.disabled = true;
821 camera_menu.default_device =
822 GetMediaDeviceById(preferred_camera, cameras);
823 camera_menu.selected_device = camera_menu.default_device;
825 add_media_menu(content::MEDIA_DEVICE_VIDEO_CAPTURE, camera_menu);
829 void ContentSettingMediaStreamBubbleModel::SetCustomLink() {
830 TabSpecificContentSettings* content_settings =
831 TabSpecificContentSettings::FromWebContents(web_contents());
832 if (content_settings->IsMicrophoneCameraStateChanged()) {
833 set_custom_link(l10n_util::GetStringUTF8(
834 IDS_MEDIASTREAM_SETTING_CHANGED_MESSAGE));
838 void ContentSettingMediaStreamBubbleModel::OnRadioClicked(int radio_index) {
839 selected_item_ = radio_index;
842 void ContentSettingMediaStreamBubbleModel::OnMediaMenuClicked(
843 content::MediaStreamType type,
844 const std::string& selected_device_id) {
845 DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
846 type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
847 DCHECK_EQ(1U, bubble_content().media_menus.count(type));
848 MediaCaptureDevicesDispatcher* dispatcher =
849 MediaCaptureDevicesDispatcher::GetInstance();
850 const content::MediaStreamDevices& devices =
851 (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) ?
852 dispatcher->GetAudioCaptureDevices() :
853 dispatcher->GetVideoCaptureDevices();
854 set_selected_device(GetMediaDeviceById(selected_device_id, devices));
857 class ContentSettingDomainListBubbleModel
858 : public ContentSettingTitleAndLinkModel {
860 ContentSettingDomainListBubbleModel(Delegate* delegate,
861 WebContents* web_contents,
863 ContentSettingsType content_type);
864 ~ContentSettingDomainListBubbleModel() override {}
867 void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
868 void SetDomainsAndCustomLink();
869 void OnCustomLinkClicked() override;
872 ContentSettingDomainListBubbleModel::ContentSettingDomainListBubbleModel(
874 WebContents* web_contents,
876 ContentSettingsType content_type)
877 : ContentSettingTitleAndLinkModel(
878 delegate, web_contents, profile, content_type) {
879 DCHECK_EQ(CONTENT_SETTINGS_TYPE_GEOLOCATION, content_type) <<
880 "SetDomains currently only supports geolocation content type";
881 SetDomainsAndCustomLink();
884 void ContentSettingDomainListBubbleModel::MaybeAddDomainList(
885 const std::set<std::string>& hosts, int title_id) {
886 if (!hosts.empty()) {
887 DomainList domain_list;
888 domain_list.title = l10n_util::GetStringUTF8(title_id);
889 domain_list.hosts = hosts;
890 add_domain_list(domain_list);
894 void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() {
895 TabSpecificContentSettings* content_settings =
896 TabSpecificContentSettings::FromWebContents(web_contents());
897 const ContentSettingsUsagesState& usages =
898 content_settings->geolocation_usages_state();
899 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
900 unsigned int tab_state_flags = 0;
901 usages.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
902 // Divide the tab's current geolocation users into sets according to their
904 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
905 IDS_GEOLOCATION_BUBBLE_SECTION_ALLOWED);
907 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
908 IDS_GEOLOCATION_BUBBLE_SECTION_DENIED);
910 if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
911 set_custom_link(l10n_util::GetStringUTF8(
912 IDS_GEOLOCATION_BUBBLE_CLEAR_LINK));
913 set_custom_link_enabled(true);
914 } else if (tab_state_flags &
915 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
916 set_custom_link(l10n_util::GetStringUTF8(
917 IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
921 void ContentSettingDomainListBubbleModel::OnCustomLinkClicked() {
924 // Reset this embedder's entry to default for each of the requesting
925 // origins currently on the page.
926 const GURL& embedder_url = web_contents()->GetURL();
927 TabSpecificContentSettings* content_settings =
928 TabSpecificContentSettings::FromWebContents(web_contents());
929 const ContentSettingsUsagesState::StateMap& state_map =
930 content_settings->geolocation_usages_state().state_map();
931 HostContentSettingsMap* settings_map =
932 profile()->GetHostContentSettingsMap();
934 for (ContentSettingsUsagesState::StateMap::const_iterator it =
935 state_map.begin(); it != state_map.end(); ++it) {
936 settings_map->SetContentSetting(
937 ContentSettingsPattern::FromURLNoWildcard(it->first),
938 ContentSettingsPattern::FromURLNoWildcard(embedder_url),
939 CONTENT_SETTINGS_TYPE_GEOLOCATION,
941 CONTENT_SETTING_DEFAULT);
945 class ContentSettingMixedScriptBubbleModel
946 : public ContentSettingTitleLinkAndCustomModel {
948 ContentSettingMixedScriptBubbleModel(Delegate* delegate,
949 WebContents* web_contents,
951 ContentSettingsType content_type);
953 ~ContentSettingMixedScriptBubbleModel() override {}
956 void OnCustomLinkClicked() override;
959 ContentSettingMixedScriptBubbleModel::ContentSettingMixedScriptBubbleModel(
961 WebContents* web_contents,
963 ContentSettingsType content_type)
964 : ContentSettingTitleLinkAndCustomModel(
965 delegate, web_contents, profile, content_type) {
966 DCHECK_EQ(content_type, CONTENT_SETTINGS_TYPE_MIXEDSCRIPT);
967 TabSpecificContentSettings::RecordMixedScriptAction(
968 TabSpecificContentSettings::MIXED_SCRIPT_ACTION_DISPLAYED_BUBBLE);
969 set_custom_link_enabled(true);
972 void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
973 TabSpecificContentSettings::RecordMixedScriptAction(
974 TabSpecificContentSettings::MIXED_SCRIPT_ACTION_CLICKED_ALLOW);
975 DCHECK(web_contents());
976 web_contents()->SendToAllFrames(
977 new ChromeViewMsg_SetAllowRunningInsecureContent(MSG_ROUTING_NONE, true));
978 web_contents()->GetMainFrame()->Send(new ChromeViewMsg_ReloadFrame(
979 web_contents()->GetMainFrame()->GetRoutingID()));
982 ContentSettingRPHBubbleModel::ContentSettingRPHBubbleModel(
984 WebContents* web_contents,
986 ProtocolHandlerRegistry* registry,
987 ContentSettingsType content_type)
988 : ContentSettingTitleAndLinkModel(
989 delegate, web_contents, profile, content_type),
992 pending_handler_(ProtocolHandler::EmptyProtocolHandler()),
993 previous_handler_(ProtocolHandler::EmptyProtocolHandler()) {
994 DCHECK_EQ(CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, content_type);
996 TabSpecificContentSettings* content_settings =
997 TabSpecificContentSettings::FromWebContents(web_contents);
998 pending_handler_ = content_settings->pending_protocol_handler();
999 previous_handler_ = content_settings->previous_protocol_handler();
1001 base::string16 protocol;
1002 if (pending_handler_.protocol() == "mailto") {
1003 protocol = l10n_util::GetStringUTF16(
1004 IDS_REGISTER_PROTOCOL_HANDLER_MAILTO_NAME);
1005 } else if (pending_handler_.protocol() == "webcal") {
1006 protocol = l10n_util::GetStringUTF16(
1007 IDS_REGISTER_PROTOCOL_HANDLER_WEBCAL_NAME);
1009 protocol = base::UTF8ToUTF16(pending_handler_.protocol());
1012 // Note that we ignore the |title| parameter.
1013 if (previous_handler_.IsEmpty()) {
1014 set_title(l10n_util::GetStringFUTF8(
1015 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM,
1016 base::UTF8ToUTF16(pending_handler_.url().host()),
1019 set_title(l10n_util::GetStringFUTF8(
1020 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM_REPLACE,
1021 base::UTF8ToUTF16(pending_handler_.url().host()),
1023 base::UTF8ToUTF16(previous_handler_.url().host())));
1026 std::string radio_allow_label =
1027 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_ACCEPT);
1028 std::string radio_deny_label =
1029 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_DENY);
1030 std::string radio_ignore_label =
1031 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_IGNORE);
1033 GURL url = web_contents->GetURL();
1034 RadioGroup radio_group;
1035 radio_group.url = url;
1037 radio_group.radio_items.push_back(radio_allow_label);
1038 radio_group.radio_items.push_back(radio_deny_label);
1039 radio_group.radio_items.push_back(radio_ignore_label);
1040 ContentSetting setting =
1041 content_settings->pending_protocol_handler_setting();
1042 if (setting == CONTENT_SETTING_ALLOW)
1043 radio_group.default_item = RPH_ALLOW;
1044 else if (setting == CONTENT_SETTING_BLOCK)
1045 radio_group.default_item = RPH_BLOCK;
1047 radio_group.default_item = RPH_IGNORE;
1049 selected_item_ = radio_group.default_item;
1050 set_radio_group_enabled(true);
1051 set_radio_group(radio_group);
1054 void ContentSettingRPHBubbleModel::OnRadioClicked(int radio_index) {
1055 if (selected_item_ == radio_index)
1058 selected_item_ = radio_index;
1060 if (radio_index == RPH_ALLOW)
1061 RegisterProtocolHandler();
1062 else if (radio_index == RPH_BLOCK)
1063 UnregisterProtocolHandler();
1064 else if (radio_index == RPH_IGNORE)
1065 IgnoreProtocolHandler();
1070 void ContentSettingRPHBubbleModel::OnDoneClicked() {
1071 // The user has one chance to deal with the RPH content setting UI,
1072 // then we remove it.
1073 TabSpecificContentSettings::FromWebContents(web_contents())->
1074 ClearPendingProtocolHandler();
1075 content::NotificationService::current()->Notify(
1076 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
1077 content::Source<WebContents>(web_contents()),
1078 content::NotificationService::NoDetails());
1081 void ContentSettingRPHBubbleModel::RegisterProtocolHandler() {
1082 // A no-op if the handler hasn't been ignored, but needed in case the user
1083 // selects sequences like register/ignore/register.
1084 registry_->RemoveIgnoredHandler(pending_handler_);
1086 registry_->OnAcceptRegisterProtocolHandler(pending_handler_);
1087 TabSpecificContentSettings::FromWebContents(web_contents())->
1088 set_pending_protocol_handler_setting(CONTENT_SETTING_ALLOW);
1091 void ContentSettingRPHBubbleModel::UnregisterProtocolHandler() {
1092 registry_->OnDenyRegisterProtocolHandler(pending_handler_);
1093 TabSpecificContentSettings::FromWebContents(web_contents())->
1094 set_pending_protocol_handler_setting(CONTENT_SETTING_BLOCK);
1095 ClearOrSetPreviousHandler();
1098 void ContentSettingRPHBubbleModel::IgnoreProtocolHandler() {
1099 registry_->OnIgnoreRegisterProtocolHandler(pending_handler_);
1100 TabSpecificContentSettings::FromWebContents(web_contents())->
1101 set_pending_protocol_handler_setting(CONTENT_SETTING_DEFAULT);
1102 ClearOrSetPreviousHandler();
1105 void ContentSettingRPHBubbleModel::ClearOrSetPreviousHandler() {
1106 if (previous_handler_.IsEmpty()) {
1107 registry_->ClearDefault(pending_handler_.protocol());
1109 registry_->OnAcceptRegisterProtocolHandler(previous_handler_);
1113 class ContentSettingMidiSysExBubbleModel
1114 : public ContentSettingTitleAndLinkModel {
1116 ContentSettingMidiSysExBubbleModel(Delegate* delegate,
1117 WebContents* web_contents,
1119 ContentSettingsType content_type);
1120 ~ContentSettingMidiSysExBubbleModel() override {}
1123 void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
1124 void SetDomainsAndCustomLink();
1125 void OnCustomLinkClicked() override;
1128 ContentSettingMidiSysExBubbleModel::ContentSettingMidiSysExBubbleModel(
1130 WebContents* web_contents,
1132 ContentSettingsType content_type)
1133 : ContentSettingTitleAndLinkModel(
1134 delegate, web_contents, profile, content_type) {
1135 DCHECK_EQ(CONTENT_SETTINGS_TYPE_MIDI_SYSEX, content_type);
1136 SetDomainsAndCustomLink();
1139 void ContentSettingMidiSysExBubbleModel::MaybeAddDomainList(
1140 const std::set<std::string>& hosts, int title_id) {
1141 if (!hosts.empty()) {
1142 DomainList domain_list;
1143 domain_list.title = l10n_util::GetStringUTF8(title_id);
1144 domain_list.hosts = hosts;
1145 add_domain_list(domain_list);
1149 void ContentSettingMidiSysExBubbleModel::SetDomainsAndCustomLink() {
1150 TabSpecificContentSettings* content_settings =
1151 TabSpecificContentSettings::FromWebContents(web_contents());
1152 const ContentSettingsUsagesState& usages_state =
1153 content_settings->midi_usages_state();
1154 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
1155 unsigned int tab_state_flags = 0;
1156 usages_state.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
1157 // Divide the tab's current MIDI sysex users into sets according to their
1158 // permission state.
1159 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
1160 IDS_MIDI_SYSEX_BUBBLE_ALLOWED);
1162 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
1163 IDS_MIDI_SYSEX_BUBBLE_DENIED);
1165 if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
1166 set_custom_link(l10n_util::GetStringUTF8(
1167 IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK));
1168 set_custom_link_enabled(true);
1169 } else if (tab_state_flags &
1170 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
1171 set_custom_link(l10n_util::GetStringUTF8(
1172 IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
1176 void ContentSettingMidiSysExBubbleModel::OnCustomLinkClicked() {
1177 if (!web_contents())
1179 // Reset this embedder's entry to default for each of the requesting
1180 // origins currently on the page.
1181 TabSpecificContentSettings* content_settings =
1182 TabSpecificContentSettings::FromWebContents(web_contents());
1183 const ContentSettingsUsagesState::StateMap& state_map =
1184 content_settings->midi_usages_state().state_map();
1185 HostContentSettingsMap* settings_map =
1186 profile()->GetHostContentSettingsMap();
1188 for (ContentSettingsUsagesState::StateMap::const_iterator it =
1189 state_map.begin(); it != state_map.end(); ++it) {
1190 settings_map->SetContentSetting(
1191 ContentSettingsPattern::FromURLNoWildcard(it->first),
1192 ContentSettingsPattern::Wildcard(),
1193 CONTENT_SETTINGS_TYPE_MIDI_SYSEX,
1195 CONTENT_SETTING_DEFAULT);
1200 ContentSettingBubbleModel*
1201 ContentSettingBubbleModel::CreateContentSettingBubbleModel(
1203 WebContents* web_contents,
1205 ContentSettingsType content_type) {
1206 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES) {
1207 return new ContentSettingCookiesBubbleModel(delegate, web_contents, profile,
1210 if (content_type == CONTENT_SETTINGS_TYPE_POPUPS) {
1211 return new ContentSettingPopupBubbleModel(delegate, web_contents, profile,
1214 if (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
1215 return new ContentSettingDomainListBubbleModel(delegate, web_contents,
1216 profile, content_type);
1218 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM) {
1219 return new ContentSettingMediaStreamBubbleModel(delegate, web_contents,
1222 if (content_type == CONTENT_SETTINGS_TYPE_PLUGINS) {
1223 return new ContentSettingPluginBubbleModel(delegate, web_contents, profile,
1226 if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT) {
1227 return new ContentSettingMixedScriptBubbleModel(delegate, web_contents,
1228 profile, content_type);
1230 if (content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS) {
1231 ProtocolHandlerRegistry* registry =
1232 ProtocolHandlerRegistryFactory::GetForBrowserContext(profile);
1233 return new ContentSettingRPHBubbleModel(delegate, web_contents, profile,
1234 registry, content_type);
1236 if (content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
1237 return new ContentSettingMidiSysExBubbleModel(delegate, web_contents,
1238 profile, content_type);
1240 return new ContentSettingSingleRadioGroup(delegate, web_contents, profile,
1244 ContentSettingBubbleModel::ContentSettingBubbleModel(
1245 WebContents* web_contents,
1247 ContentSettingsType content_type)
1248 : web_contents_(web_contents),
1250 content_type_(content_type),
1251 setting_is_managed_(false) {
1252 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
1253 content::Source<WebContents>(web_contents));
1254 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
1255 content::Source<Profile>(profile_));
1258 ContentSettingBubbleModel::~ContentSettingBubbleModel() {
1261 ContentSettingBubbleModel::RadioGroup::RadioGroup() : default_item(0) {}
1263 ContentSettingBubbleModel::RadioGroup::~RadioGroup() {}
1265 ContentSettingBubbleModel::DomainList::DomainList() {}
1267 ContentSettingBubbleModel::DomainList::~DomainList() {}
1269 ContentSettingBubbleModel::MediaMenu::MediaMenu() : disabled(false) {}
1271 ContentSettingBubbleModel::MediaMenu::~MediaMenu() {}
1273 ContentSettingBubbleModel::BubbleContent::BubbleContent()
1274 : radio_group_enabled(false),
1275 custom_link_enabled(false) {
1278 ContentSettingBubbleModel::BubbleContent::~BubbleContent() {}
1280 void ContentSettingBubbleModel::Observe(
1282 const content::NotificationSource& source,
1283 const content::NotificationDetails& details) {
1284 if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) {
1285 DCHECK_EQ(web_contents_,
1286 content::Source<WebContents>(source).ptr());
1287 web_contents_ = NULL;
1289 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
1290 DCHECK_EQ(profile_, content::Source<Profile>(source).ptr());