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 content::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);
95 SetBlockedResources();
100 void ContentSettingTitleAndLinkModel::SetBlockedResources() {
101 TabSpecificContentSettings* settings =
102 TabSpecificContentSettings::FromWebContents(web_contents());
103 const std::set<std::string>& resources = settings->BlockedResourcesForType(
105 for (std::set<std::string>::const_iterator it = resources.begin();
106 it != resources.end(); ++it) {
107 AddBlockedResource(*it);
111 void ContentSettingTitleAndLinkModel::SetTitle() {
112 static const ContentSettingsTypeIdEntry kBlockedTitleIDs[] = {
113 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_TITLE},
114 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_TITLE},
115 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_TITLE},
116 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_MESSAGE},
117 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_TITLE},
118 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT,
119 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT},
120 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER,
121 IDS_BLOCKED_PPAPI_BROKER_TITLE},
122 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_TITLE},
124 // Fields as for kBlockedTitleIDs, above.
125 static const ContentSettingsTypeIdEntry
126 kResourceSpecificBlockedTitleIDs[] = {
127 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_TITLE},
129 static const ContentSettingsTypeIdEntry kAccessedTitleIDs[] = {
130 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_ACCESSED_COOKIES_TITLE},
131 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_TITLE},
132 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_TITLE},
134 const ContentSettingsTypeIdEntry *title_ids = kBlockedTitleIDs;
135 size_t num_title_ids = arraysize(kBlockedTitleIDs);
136 if (web_contents() &&
137 TabSpecificContentSettings::FromWebContents(
138 web_contents())->IsContentAllowed(content_type()) &&
139 !TabSpecificContentSettings::FromWebContents(
140 web_contents())->IsContentBlocked(content_type())) {
141 title_ids = kAccessedTitleIDs;
142 num_title_ids = arraysize(kAccessedTitleIDs);
143 } else if (!bubble_content().resource_identifiers.empty()) {
144 title_ids = kResourceSpecificBlockedTitleIDs;
145 num_title_ids = arraysize(kResourceSpecificBlockedTitleIDs);
148 GetIdForContentType(title_ids, num_title_ids, content_type());
150 set_title(l10n_util::GetStringUTF8(title_id));
153 void ContentSettingTitleAndLinkModel::SetManageLink() {
154 static const ContentSettingsTypeIdEntry kLinkIDs[] = {
155 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_LINK},
156 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_LINK},
157 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_LINK},
158 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LINK},
159 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_LINK},
160 {CONTENT_SETTINGS_TYPE_GEOLOCATION, IDS_GEOLOCATION_BUBBLE_MANAGE_LINK},
161 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_LEARN_MORE},
162 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, IDS_HANDLERS_BUBBLE_MANAGE_LINK},
163 {CONTENT_SETTINGS_TYPE_MEDIASTREAM, IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK},
164 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_PPAPI_BROKER_BUBBLE_MANAGE_LINK},
165 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOADS_LINK},
166 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX, IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK},
167 {CONTENT_SETTINGS_TYPE_SAVE_PASSWORD,
168 IDS_OPTIONS_PASSWORDS_MANAGE_PASSWORDS},
170 set_manage_link(l10n_util::GetStringUTF8(
171 GetIdForContentType(kLinkIDs, arraysize(kLinkIDs), content_type())));
174 void ContentSettingTitleAndLinkModel::OnManageLinkClicked() {
176 delegate_->ShowContentSettingsPage(content_type());
179 class ContentSettingTitleLinkAndCustomModel
180 : public ContentSettingTitleAndLinkModel {
182 ContentSettingTitleLinkAndCustomModel(Delegate* delegate,
183 WebContents* web_contents,
185 ContentSettingsType content_type);
186 virtual ~ContentSettingTitleLinkAndCustomModel() {}
189 void SetCustomLink();
190 virtual void OnCustomLinkClicked() OVERRIDE {}
193 ContentSettingTitleLinkAndCustomModel::ContentSettingTitleLinkAndCustomModel(
195 WebContents* web_contents,
197 ContentSettingsType content_type)
198 : ContentSettingTitleAndLinkModel(
199 delegate, web_contents, profile, content_type) {
203 void ContentSettingTitleLinkAndCustomModel::SetCustomLink() {
204 static const ContentSettingsTypeIdEntry kCustomIDs[] = {
205 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_INFO},
206 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LOAD_ALL},
207 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_ALLOW_INSECURE_CONTENT_BUTTON},
210 GetIdForContentType(kCustomIDs, arraysize(kCustomIDs), content_type());
212 set_custom_link(l10n_util::GetStringUTF8(custom_link_id));
215 class ContentSettingSingleRadioGroup
216 : public ContentSettingTitleLinkAndCustomModel {
218 ContentSettingSingleRadioGroup(Delegate* delegate,
219 WebContents* web_contents,
221 ContentSettingsType content_type);
222 virtual ~ContentSettingSingleRadioGroup();
225 bool settings_changed() const;
226 int selected_item() const { return selected_item_; }
229 void SetRadioGroup();
230 void AddException(ContentSetting setting,
231 const std::string& resource_identifier);
232 virtual void OnRadioClicked(int radio_index) OVERRIDE;
234 ContentSetting block_setting_;
238 ContentSettingSingleRadioGroup::ContentSettingSingleRadioGroup(
240 WebContents* web_contents,
242 ContentSettingsType content_type)
243 : ContentSettingTitleLinkAndCustomModel(delegate, web_contents, profile,
245 block_setting_(CONTENT_SETTING_BLOCK),
250 ContentSettingSingleRadioGroup::~ContentSettingSingleRadioGroup() {
251 if (settings_changed()) {
252 ContentSetting setting =
253 selected_item_ == kAllowButtonIndex ?
254 CONTENT_SETTING_ALLOW :
256 const std::set<std::string>& resources =
257 bubble_content().resource_identifiers;
258 if (resources.empty()) {
259 AddException(setting, std::string());
261 for (std::set<std::string>::const_iterator it = resources.begin();
262 it != resources.end(); ++it) {
263 AddException(setting, *it);
269 bool ContentSettingSingleRadioGroup::settings_changed() const {
270 return selected_item_ != bubble_content().radio_group.default_item;
273 // Initialize the radio group by setting the appropriate labels for the
274 // content type and setting the default value based on the content setting.
275 void ContentSettingSingleRadioGroup::SetRadioGroup() {
276 GURL url = web_contents()->GetURL();
277 string16 display_host;
278 net::AppendFormattedHost(
280 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
283 if (display_host.empty())
284 display_host = ASCIIToUTF16(url.spec());
286 const std::set<std::string>& resources =
287 bubble_content().resource_identifiers;
289 TabSpecificContentSettings* content_settings =
290 TabSpecificContentSettings::FromWebContents(web_contents());
292 !content_settings->IsContentBlocked(content_type());
294 content_settings->IsContentAllowed(content_type()));
296 RadioGroup radio_group;
297 radio_group.url = url;
299 static const ContentSettingsTypeIdEntry kBlockedAllowIDs[] = {
300 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
301 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_UNBLOCK},
302 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_UNBLOCK},
303 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_UNBLOCK_ALL},
304 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_UNBLOCK},
305 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_UNBLOCK},
306 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_UNBLOCK},
308 // Fields as for kBlockedAllowIDs, above.
309 static const ContentSettingsTypeIdEntry kResourceSpecificBlockedAllowIDs[] = {
310 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_UNBLOCK},
312 static const ContentSettingsTypeIdEntry kAllowedAllowIDs[] = {
313 // TODO(bauerb): The string shouldn't be "unblock" (they weren't blocked).
314 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
315 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_NO_ACTION},
316 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_NO_ACTION},
319 std::string radio_allow_label;
321 int resource_id = GetIdForContentType(kAllowedAllowIDs,
322 arraysize(kAllowedAllowIDs),
324 radio_allow_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
325 l10n_util::GetStringFUTF8(resource_id, display_host) :
326 l10n_util::GetStringUTF8(resource_id);
327 } else if (resources.empty()) {
328 radio_allow_label = l10n_util::GetStringFUTF8(
329 GetIdForContentType(kBlockedAllowIDs, arraysize(kBlockedAllowIDs),
333 radio_allow_label = l10n_util::GetStringFUTF8(
334 GetIdForContentType(kResourceSpecificBlockedAllowIDs,
335 arraysize(kResourceSpecificBlockedAllowIDs),
340 static const ContentSettingsTypeIdEntry kBlockedBlockIDs[] = {
341 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
342 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_NO_ACTION},
343 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_NO_ACTION},
344 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_NO_ACTION},
345 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_NO_ACTION},
346 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_NO_ACTION},
347 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_NO_ACTION},
349 static const ContentSettingsTypeIdEntry kAllowedBlockIDs[] = {
350 // TODO(bauerb): The string should say "block".
351 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
352 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_BLOCK},
353 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_BLOCK},
356 std::string radio_block_label;
358 int resource_id = GetIdForContentType(kAllowedBlockIDs,
359 arraysize(kAllowedBlockIDs),
361 radio_block_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
362 l10n_util::GetStringUTF8(resource_id) :
363 l10n_util::GetStringFUTF8(resource_id, display_host);
365 radio_block_label = l10n_util::GetStringUTF8(
366 GetIdForContentType(kBlockedBlockIDs, arraysize(kBlockedBlockIDs),
370 radio_group.radio_items.push_back(radio_allow_label);
371 radio_group.radio_items.push_back(radio_block_label);
372 HostContentSettingsMap* map = profile()->GetHostContentSettingsMap();
373 CookieSettings* cookie_settings =
374 CookieSettings::Factory::GetForProfile(profile()).get();
375 ContentSetting most_restrictive_setting;
376 SettingSource most_restrictive_setting_source = SETTING_SOURCE_NONE;
377 bool most_restrictive_setting_is_wildcard = false;
379 if (resources.empty()) {
380 if (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) {
381 most_restrictive_setting = cookie_settings->GetCookieSetting(
382 url, url, true, &most_restrictive_setting_source);
385 scoped_ptr<Value> value(map->GetWebsiteSetting(
386 url, url, content_type(), std::string(), &info));
387 most_restrictive_setting =
388 content_settings::ValueToContentSetting(value.get());
389 most_restrictive_setting_source = info.source;
390 most_restrictive_setting_is_wildcard =
391 info.primary_pattern == ContentSettingsPattern::Wildcard() &&
392 info.secondary_pattern == ContentSettingsPattern::Wildcard();
395 most_restrictive_setting = CONTENT_SETTING_ALLOW;
396 for (std::set<std::string>::const_iterator it = resources.begin();
397 it != resources.end(); ++it) {
399 scoped_ptr<Value> val(map->GetWebsiteSetting(
400 url, url, content_type(), *it, &info));
401 ContentSetting setting =
402 content_settings::ValueToContentSetting(val.get());
403 if (setting == CONTENT_SETTING_BLOCK) {
404 most_restrictive_setting = CONTENT_SETTING_BLOCK;
405 most_restrictive_setting_source = info.source;
406 most_restrictive_setting_is_wildcard =
407 info.primary_pattern == ContentSettingsPattern::Wildcard() &&
408 info.secondary_pattern == ContentSettingsPattern::Wildcard();
411 if (setting == CONTENT_SETTING_ASK) {
412 most_restrictive_setting = CONTENT_SETTING_ASK;
413 most_restrictive_setting_source = info.source;
414 most_restrictive_setting_is_wildcard =
415 info.primary_pattern == ContentSettingsPattern::Wildcard() &&
416 info.secondary_pattern == ContentSettingsPattern::Wildcard();
421 if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS &&
422 most_restrictive_setting == CONTENT_SETTING_ALLOW &&
423 most_restrictive_setting_is_wildcard) {
424 // In the corner case of unrecognized plugins (which are now blocked by
425 // default) we indicate the blocked state in the UI and allow the user to
427 radio_group.default_item = 1;
428 } else if (most_restrictive_setting == CONTENT_SETTING_ALLOW) {
429 radio_group.default_item = kAllowButtonIndex;
430 // |block_setting_| is already set to |CONTENT_SETTING_BLOCK|.
432 radio_group.default_item = 1;
433 block_setting_ = most_restrictive_setting;
435 if (most_restrictive_setting_source != SETTING_SOURCE_USER) {
436 set_radio_group_enabled(false);
438 set_radio_group_enabled(true);
440 selected_item_ = radio_group.default_item;
441 set_radio_group(radio_group);
444 void ContentSettingSingleRadioGroup::AddException(
445 ContentSetting setting,
446 const std::string& resource_identifier) {
448 profile()->GetHostContentSettingsMap()->AddExceptionForURL(
449 bubble_content().radio_group.url,
450 bubble_content().radio_group.url,
457 void ContentSettingSingleRadioGroup::OnRadioClicked(int radio_index) {
458 selected_item_ = radio_index;
461 class ContentSettingCookiesBubbleModel : public ContentSettingSingleRadioGroup {
463 ContentSettingCookiesBubbleModel(Delegate* delegate,
464 WebContents* web_contents,
466 ContentSettingsType content_type);
468 virtual ~ContentSettingCookiesBubbleModel();
471 virtual void OnCustomLinkClicked() OVERRIDE;
474 ContentSettingCookiesBubbleModel::ContentSettingCookiesBubbleModel(
476 WebContents* web_contents,
478 ContentSettingsType content_type)
479 : ContentSettingSingleRadioGroup(
480 delegate, web_contents, profile, content_type) {
481 DCHECK_EQ(CONTENT_SETTINGS_TYPE_COOKIES, content_type);
482 set_custom_link_enabled(true);
485 ContentSettingCookiesBubbleModel::~ContentSettingCookiesBubbleModel() {
486 // On some plattforms e.g. MacOS X it is possible to close a tab while the
487 // cookies settings bubble is open. This resets the web contents to NULL.
488 if (settings_changed() && web_contents()) {
489 CollectedCookiesInfoBarDelegate::Create(
490 InfoBarService::FromWebContents(web_contents()));
494 void ContentSettingCookiesBubbleModel::OnCustomLinkClicked() {
497 content::NotificationService::current()->Notify(
498 chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN,
499 content::Source<TabSpecificContentSettings>(
500 TabSpecificContentSettings::FromWebContents(web_contents())),
501 content::NotificationService::NoDetails());
502 delegate()->ShowCollectedCookiesDialog(web_contents());
505 class ContentSettingPluginBubbleModel : public ContentSettingSingleRadioGroup {
507 ContentSettingPluginBubbleModel(Delegate* delegate,
508 WebContents* web_contents,
510 ContentSettingsType content_type);
512 virtual ~ContentSettingPluginBubbleModel();
515 virtual void OnCustomLinkClicked() OVERRIDE;
518 ContentSettingPluginBubbleModel::ContentSettingPluginBubbleModel(
520 WebContents* web_contents,
522 ContentSettingsType content_type)
523 : ContentSettingSingleRadioGroup(
524 delegate, web_contents, profile, content_type) {
525 DCHECK_EQ(content_type, CONTENT_SETTINGS_TYPE_PLUGINS);
526 set_custom_link_enabled(web_contents &&
527 TabSpecificContentSettings::FromWebContents(
528 web_contents)->load_plugins_link_enabled());
531 ContentSettingPluginBubbleModel::~ContentSettingPluginBubbleModel() {
532 if (settings_changed()) {
533 // If the user elected to allow all plugins then run plugins at this time.
534 if (selected_item() == kAllowButtonIndex)
535 OnCustomLinkClicked();
539 void ContentSettingPluginBubbleModel::OnCustomLinkClicked() {
540 content::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble"));
541 DCHECK(web_contents());
542 content::RenderViewHost* host = web_contents()->GetRenderViewHost();
543 #if defined(ENABLE_PLUGINS)
544 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
545 host->GetProcess()->GetID());
547 // TODO(bauerb): We should send the identifiers of blocked plug-ins here.
548 host->Send(new ChromeViewMsg_LoadBlockedPlugins(host->GetRoutingID(),
550 set_custom_link_enabled(false);
551 TabSpecificContentSettings::FromWebContents(web_contents())->
552 set_load_plugins_link_enabled(false);
555 class ContentSettingPopupBubbleModel : public ContentSettingSingleRadioGroup {
557 ContentSettingPopupBubbleModel(Delegate* delegate,
558 WebContents* web_contents,
560 ContentSettingsType content_type);
561 virtual ~ContentSettingPopupBubbleModel() {}
565 virtual void OnPopupClicked(int index) OVERRIDE;
568 ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel(
570 WebContents* web_contents,
572 ContentSettingsType content_type)
573 : ContentSettingSingleRadioGroup(
574 delegate, web_contents, profile, content_type) {
579 void ContentSettingPopupBubbleModel::SetPopups() {
580 std::map<int32, GURL> blocked_popups =
581 PopupBlockerTabHelper::FromWebContents(web_contents())
582 ->GetBlockedPopupRequests();
583 for (std::map<int32, GURL>::const_iterator iter = blocked_popups.begin();
584 iter != blocked_popups.end();
586 std::string title(iter->second.spec());
587 // The popup may not have a valid URL.
589 title = l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE);
590 PopupItem popup_item(
591 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
592 IDR_DEFAULT_FAVICON),
595 add_popup(popup_item);
599 void ContentSettingPopupBubbleModel::OnPopupClicked(int index) {
600 if (web_contents()) {
601 PopupBlockerTabHelper::FromWebContents(web_contents())->
602 ShowBlockedPopup(bubble_content().popup_items[index].popup_id);
606 // The model for the save password bubble.
607 SavePasswordBubbleModel::SavePasswordBubbleModel(Delegate* delegate,
608 WebContents* web_contents,
610 : ContentSettingTitleAndLinkModel(delegate, web_contents, profile,
611 CONTENT_SETTINGS_TYPE_SAVE_PASSWORD),
612 state_(TabSpecificContentSettings::NO_PASSWORD_TO_BE_SAVED) {
614 TabSpecificContentSettings* content_settings =
615 TabSpecificContentSettings::FromWebContents(web_contents);
616 state_ = content_settings->GetPasswordSavingState();
621 SavePasswordBubbleModel::~SavePasswordBubbleModel() {}
623 void SavePasswordBubbleModel::SetTitle() {
625 // If the save password icon was accessed, the icon is displayed and the
626 // bubble is instantiated
627 if (state_ == TabSpecificContentSettings::PASSWORD_TO_BE_SAVED)
628 title_id = IDS_SAVE_PASSWORD;
630 set_title(l10n_util::GetStringUTF8(title_id));
633 void SavePasswordBubbleModel::OnCancelClicked() {
634 TabSpecificContentSettings* content_settings =
635 TabSpecificContentSettings::FromWebContents(web_contents());
636 content_settings->set_password_action(PasswordFormManager::BLACKLIST);
639 void SavePasswordBubbleModel::OnDoneClicked() {
640 TabSpecificContentSettings* content_settings =
641 TabSpecificContentSettings::FromWebContents(web_contents());
642 content_settings->set_password_action(PasswordFormManager::DO_NOTHING);
645 void SavePasswordBubbleModel::OnSaveClicked() {
646 TabSpecificContentSettings* content_settings =
647 TabSpecificContentSettings::FromWebContents(web_contents());
648 content_settings->set_password_action(PasswordFormManager::SAVE);
651 // The model of the content settings bubble for media settings.
652 class ContentSettingMediaStreamBubbleModel
653 : public ContentSettingTitleAndLinkModel {
655 ContentSettingMediaStreamBubbleModel(Delegate* delegate,
656 WebContents* web_contents,
659 virtual ~ContentSettingMediaStreamBubbleModel();
663 // Sets the data for the radio buttons of the bubble.
664 void SetRadioGroup();
665 // Sets the data for the media menus of the bubble.
666 void SetMediaMenus();
667 // Updates the camera and microphone setting with the passed |setting|.
668 void UpdateSettings(ContentSetting setting);
669 // Updates the camera and microphone default device with the passed |type|
671 void UpdateDefaultDeviceForType(content::MediaStreamType type,
672 const std::string& device);
674 // ContentSettingBubbleModel implementation.
675 virtual void OnRadioClicked(int radio_index) OVERRIDE;
676 virtual void OnMediaMenuClicked(content::MediaStreamType type,
677 const std::string& selected_device) OVERRIDE;
679 // The index of the selected radio item.
681 // The content settings that are associated with the individual radio
683 ContentSetting radio_item_setting_[2];
684 // The state of the microphone and camera access.
685 TabSpecificContentSettings::MicrophoneCameraState state_;
688 ContentSettingMediaStreamBubbleModel::ContentSettingMediaStreamBubbleModel(
690 WebContents* web_contents,
692 : ContentSettingTitleAndLinkModel(
693 delegate, web_contents, profile, CONTENT_SETTINGS_TYPE_MEDIASTREAM),
695 state_(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED) {
697 // Initialize the content settings associated with the individual radio
699 radio_item_setting_[0] = CONTENT_SETTING_ASK;
700 radio_item_setting_[1] = CONTENT_SETTING_BLOCK;
702 TabSpecificContentSettings* content_settings =
703 TabSpecificContentSettings::FromWebContents(web_contents);
704 state_ = content_settings->GetMicrophoneCameraState();
711 ContentSettingMediaStreamBubbleModel::~ContentSettingMediaStreamBubbleModel() {
712 // On some platforms (e.g. MacOS X) it is possible to close a tab while the
713 // media stream bubble is open. This resets the web contents to NULL.
717 bool media_setting_changed = false;
718 for (MediaMenuMap::const_iterator it = bubble_content().media_menus.begin();
719 it != bubble_content().media_menus.end(); ++it) {
720 if (it->second.selected_device.id != it->second.default_device.id) {
721 UpdateDefaultDeviceForType(it->first, it->second.selected_device.id);
722 media_setting_changed = true;
726 // Update the media settings if the radio button selection was changed.
727 if (selected_item_ != bubble_content().radio_group.default_item) {
728 UpdateSettings(radio_item_setting_[selected_item_]);
729 media_setting_changed = true;
732 // Trigger the reload infobar if the media setting has been changed.
733 if (media_setting_changed) {
734 MediaSettingChangedInfoBarDelegate::Create(
735 InfoBarService::FromWebContents(web_contents()));
739 void ContentSettingMediaStreamBubbleModel::SetTitle() {
742 case TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED:
743 // If neither microphone nor camera stream was accessed, then there is no
744 // icon didplayed in the omnibox and no settings bubble availbale. Hence
745 // there is no title.
748 case TabSpecificContentSettings::MICROPHONE_ACCESSED:
749 title_id = IDS_MICROPHONE_ACCESSED;
751 case TabSpecificContentSettings::CAMERA_ACCESSED:
752 title_id = IDS_CAMERA_ACCESSED;
754 case TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED:
755 title_id = IDS_MICROPHONE_CAMERA_ALLOWED;
757 case TabSpecificContentSettings::MICROPHONE_BLOCKED:
758 title_id = IDS_MICROPHONE_BLOCKED;
760 case TabSpecificContentSettings::CAMERA_BLOCKED:
761 title_id = IDS_CAMERA_BLOCKED;
763 case TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED:
764 title_id = IDS_MICROPHONE_CAMERA_BLOCKED;
767 set_title(l10n_util::GetStringUTF8(title_id));
770 void ContentSettingMediaStreamBubbleModel::SetRadioGroup() {
771 TabSpecificContentSettings* content_settings =
772 TabSpecificContentSettings::FromWebContents(web_contents());
773 GURL url = content_settings->media_stream_access_origin();
774 RadioGroup radio_group;
775 radio_group.url = url;
777 string16 display_host_utf16;
778 net::AppendFormattedHost(
780 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
781 &display_host_utf16);
782 std::string display_host(UTF16ToUTF8(display_host_utf16));
783 if (display_host.empty())
784 display_host = url.spec();
786 int radio_allow_label_id = 0;
787 int radio_block_label_id = 0;
789 case TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED:
792 case TabSpecificContentSettings::MICROPHONE_ACCESSED:
793 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION;
794 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK;
797 case TabSpecificContentSettings::CAMERA_ACCESSED:
798 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION;
799 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK;
802 case TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED:
803 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION;
804 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK;
807 case TabSpecificContentSettings::MICROPHONE_BLOCKED:
808 if (url.SchemeIsSecure()) {
809 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_ALLOW;
810 radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
812 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_ASK;
815 radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION;
818 case TabSpecificContentSettings::CAMERA_BLOCKED:
819 if (url.SchemeIsSecure()) {
820 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW;
821 radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
823 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK;
826 radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION;
829 case TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED:
830 if (url.SchemeIsSecure()) {
831 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ALLOW;
832 radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
834 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ASK;
837 radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION;
842 std::string radio_allow_label = l10n_util::GetStringFUTF8(
843 radio_allow_label_id, UTF8ToUTF16(display_host));
844 std::string radio_block_label =
845 l10n_util::GetStringUTF8(radio_block_label_id);
847 radio_group.default_item = selected_item_;
848 radio_group.radio_items.push_back(radio_allow_label);
849 radio_group.radio_items.push_back(radio_block_label);
851 set_radio_group(radio_group);
852 set_radio_group_enabled(true);
855 void ContentSettingMediaStreamBubbleModel::UpdateSettings(
856 ContentSetting setting) {
858 HostContentSettingsMap* content_settings =
859 profile()->GetHostContentSettingsMap();
860 TabSpecificContentSettings* tab_content_settings =
861 TabSpecificContentSettings::FromWebContents(web_contents());
862 // The same patterns must be used as in other places (e.g. the infobar) in
863 // order to override the existing rule. Otherwise a new rule is created.
864 // TODO(markusheintz): Extract to a helper so that there is only a single
866 ContentSettingsPattern primary_pattern =
867 ContentSettingsPattern::FromURLNoWildcard(
868 tab_content_settings->media_stream_access_origin());
869 ContentSettingsPattern secondary_pattern =
870 ContentSettingsPattern::Wildcard();
871 if (state_ == TabSpecificContentSettings::MICROPHONE_ACCESSED ||
872 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
873 state_ == TabSpecificContentSettings::MICROPHONE_BLOCKED ||
874 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED) {
875 content_settings->SetContentSetting(
876 primary_pattern, secondary_pattern,
877 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string(), setting);
879 if (state_ == TabSpecificContentSettings::CAMERA_ACCESSED ||
880 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
881 state_ == TabSpecificContentSettings::CAMERA_BLOCKED ||
882 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED) {
883 content_settings->SetContentSetting(
884 primary_pattern, secondary_pattern,
885 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string(), setting);
890 void ContentSettingMediaStreamBubbleModel::UpdateDefaultDeviceForType(
891 content::MediaStreamType type,
892 const std::string& device) {
893 PrefService* prefs = profile()->GetPrefs();
894 if (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
895 prefs->SetString(prefs::kDefaultAudioCaptureDevice, device);
897 DCHECK_EQ(content::MEDIA_DEVICE_VIDEO_CAPTURE, type);
898 prefs->SetString(prefs::kDefaultVideoCaptureDevice, device);
902 void ContentSettingMediaStreamBubbleModel::SetMediaMenus() {
903 TabSpecificContentSettings* content_settings =
904 TabSpecificContentSettings::FromWebContents(web_contents());
905 const std::string& requested_microphone =
906 content_settings->media_stream_requested_audio_device();
907 const std::string& requested_camera =
908 content_settings->media_stream_requested_video_device();
910 // Add microphone menu.
911 PrefService* prefs = profile()->GetPrefs();
912 MediaCaptureDevicesDispatcher* dispatcher =
913 MediaCaptureDevicesDispatcher::GetInstance();
914 const content::MediaStreamDevices& microphones =
915 dispatcher->GetAudioCaptureDevices();
918 (state_ == TabSpecificContentSettings::MICROPHONE_ACCESSED ||
919 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
920 state_ == TabSpecificContentSettings::MICROPHONE_BLOCKED ||
921 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED);
922 bool show_camera_menu =
923 (state_ == TabSpecificContentSettings::CAMERA_ACCESSED ||
924 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
925 state_ == TabSpecificContentSettings::CAMERA_BLOCKED ||
926 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED);
927 DCHECK(show_mic_menu || show_camera_menu);
931 mic_menu.label = l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_MIC_LABEL);
932 if (!microphones.empty()) {
933 std::string preferred_mic;
934 if (requested_microphone.empty()) {
935 preferred_mic = prefs->GetString(prefs::kDefaultAudioCaptureDevice);
936 mic_menu.disabled = false;
938 // Set the |disabled| to true in order to disable the device selection
939 // menu on the media settings bubble. This must be done if the website
940 // manages the microphone devices itself.
941 preferred_mic = requested_microphone;
942 mic_menu.disabled = true;
945 mic_menu.default_device = GetMediaDeviceById(preferred_mic, microphones);
946 mic_menu.selected_device = mic_menu.default_device;
948 add_media_menu(content::MEDIA_DEVICE_AUDIO_CAPTURE, mic_menu);
951 if (show_camera_menu) {
952 const content::MediaStreamDevices& cameras =
953 dispatcher->GetVideoCaptureDevices();
954 MediaMenu camera_menu;
956 l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_CAMERA_LABEL);
957 if (!cameras.empty()) {
958 std::string preferred_camera;
959 if (requested_camera.empty()) {
960 preferred_camera = prefs->GetString(prefs::kDefaultVideoCaptureDevice);
961 camera_menu.disabled = false;
963 // Disable the menu since the website is managing the camera devices
965 preferred_camera = requested_camera;
966 camera_menu.disabled = true;
969 camera_menu.default_device =
970 GetMediaDeviceById(preferred_camera, cameras);
971 camera_menu.selected_device = camera_menu.default_device;
973 add_media_menu(content::MEDIA_DEVICE_VIDEO_CAPTURE, camera_menu);
977 void ContentSettingMediaStreamBubbleModel::OnRadioClicked(int radio_index) {
978 selected_item_ = radio_index;
981 void ContentSettingMediaStreamBubbleModel::OnMediaMenuClicked(
982 content::MediaStreamType type,
983 const std::string& selected_device_id) {
984 DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
985 type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
986 DCHECK_EQ(1U, bubble_content().media_menus.count(type));
987 MediaCaptureDevicesDispatcher* dispatcher =
988 MediaCaptureDevicesDispatcher::GetInstance();
989 const content::MediaStreamDevices& devices =
990 (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) ?
991 dispatcher->GetAudioCaptureDevices() :
992 dispatcher->GetVideoCaptureDevices();
993 set_selected_device(GetMediaDeviceById(selected_device_id, devices));
996 class ContentSettingDomainListBubbleModel
997 : public ContentSettingTitleAndLinkModel {
999 ContentSettingDomainListBubbleModel(Delegate* delegate,
1000 WebContents* web_contents,
1002 ContentSettingsType content_type);
1003 virtual ~ContentSettingDomainListBubbleModel() {}
1006 void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
1007 void SetDomainsAndCustomLink();
1008 virtual void OnCustomLinkClicked() OVERRIDE;
1011 ContentSettingDomainListBubbleModel::ContentSettingDomainListBubbleModel(
1013 WebContents* web_contents,
1015 ContentSettingsType content_type)
1016 : ContentSettingTitleAndLinkModel(
1017 delegate, web_contents, profile, content_type) {
1018 DCHECK_EQ(CONTENT_SETTINGS_TYPE_GEOLOCATION, content_type) <<
1019 "SetDomains currently only supports geolocation content type";
1020 SetDomainsAndCustomLink();
1023 void ContentSettingDomainListBubbleModel::MaybeAddDomainList(
1024 const std::set<std::string>& hosts, int title_id) {
1025 if (!hosts.empty()) {
1026 DomainList domain_list;
1027 domain_list.title = l10n_util::GetStringUTF8(title_id);
1028 domain_list.hosts = hosts;
1029 add_domain_list(domain_list);
1033 void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() {
1034 TabSpecificContentSettings* content_settings =
1035 TabSpecificContentSettings::FromWebContents(web_contents());
1036 const ContentSettingsUsagesState& usages =
1037 content_settings->geolocation_usages_state();
1038 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
1039 unsigned int tab_state_flags = 0;
1040 usages.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
1041 // Divide the tab's current geolocation users into sets according to their
1042 // permission state.
1043 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
1044 IDS_GEOLOCATION_BUBBLE_SECTION_ALLOWED);
1046 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
1047 IDS_GEOLOCATION_BUBBLE_SECTION_DENIED);
1049 if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
1050 set_custom_link(l10n_util::GetStringUTF8(
1051 IDS_GEOLOCATION_BUBBLE_CLEAR_LINK));
1052 set_custom_link_enabled(true);
1053 } else if (tab_state_flags &
1054 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
1055 set_custom_link(l10n_util::GetStringUTF8(
1056 IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
1060 void ContentSettingDomainListBubbleModel::OnCustomLinkClicked() {
1061 if (!web_contents())
1063 // Reset this embedder's entry to default for each of the requesting
1064 // origins currently on the page.
1065 const GURL& embedder_url = web_contents()->GetURL();
1066 TabSpecificContentSettings* content_settings =
1067 TabSpecificContentSettings::FromWebContents(web_contents());
1068 const ContentSettingsUsagesState::StateMap& state_map =
1069 content_settings->geolocation_usages_state().state_map();
1070 HostContentSettingsMap* settings_map =
1071 profile()->GetHostContentSettingsMap();
1073 for (ContentSettingsUsagesState::StateMap::const_iterator it =
1074 state_map.begin(); it != state_map.end(); ++it) {
1075 settings_map->SetContentSetting(
1076 ContentSettingsPattern::FromURLNoWildcard(it->first),
1077 ContentSettingsPattern::FromURLNoWildcard(embedder_url),
1078 CONTENT_SETTINGS_TYPE_GEOLOCATION,
1080 CONTENT_SETTING_DEFAULT);
1084 class ContentSettingMixedScriptBubbleModel
1085 : public ContentSettingTitleLinkAndCustomModel {
1087 ContentSettingMixedScriptBubbleModel(Delegate* delegate,
1088 WebContents* web_contents,
1090 ContentSettingsType content_type);
1092 virtual ~ContentSettingMixedScriptBubbleModel() {}
1095 virtual void OnCustomLinkClicked() OVERRIDE;
1098 ContentSettingMixedScriptBubbleModel::ContentSettingMixedScriptBubbleModel(
1100 WebContents* web_contents,
1102 ContentSettingsType content_type)
1103 : ContentSettingTitleLinkAndCustomModel(
1104 delegate, web_contents, profile, content_type) {
1105 DCHECK_EQ(content_type, CONTENT_SETTINGS_TYPE_MIXEDSCRIPT);
1106 set_custom_link_enabled(true);
1109 void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
1110 content::RecordAction(UserMetricsAction("MixedScript_LoadAnyway_Bubble"));
1111 DCHECK(web_contents());
1112 content::RenderViewHost* host = web_contents()->GetRenderViewHost();
1113 host->Send(new ChromeViewMsg_SetAllowRunningInsecureContent(
1114 host->GetRoutingID(), true));
1117 ContentSettingRPHBubbleModel::ContentSettingRPHBubbleModel(
1119 WebContents* web_contents,
1121 ProtocolHandlerRegistry* registry,
1122 ContentSettingsType content_type)
1123 : ContentSettingTitleAndLinkModel(
1124 delegate, web_contents, profile, content_type),
1126 registry_(registry),
1127 pending_handler_(ProtocolHandler::EmptyProtocolHandler()),
1128 previous_handler_(ProtocolHandler::EmptyProtocolHandler()) {
1130 DCHECK_EQ(CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, content_type);
1132 TabSpecificContentSettings* content_settings =
1133 TabSpecificContentSettings::FromWebContents(web_contents);
1134 pending_handler_ = content_settings->pending_protocol_handler();
1135 previous_handler_ = content_settings->previous_protocol_handler();
1138 if (pending_handler_.protocol() == "mailto") {
1139 protocol = l10n_util::GetStringUTF16(
1140 IDS_REGISTER_PROTOCOL_HANDLER_MAILTO_NAME);
1141 } else if (pending_handler_.protocol() == "webcal") {
1142 protocol = l10n_util::GetStringUTF16(
1143 IDS_REGISTER_PROTOCOL_HANDLER_WEBCAL_NAME);
1145 protocol = UTF8ToUTF16(pending_handler_.protocol());
1148 if (previous_handler_.IsEmpty()) {
1149 set_title(l10n_util::GetStringFUTF8(
1150 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM,
1151 pending_handler_.title(), UTF8ToUTF16(pending_handler_.url().host()),
1154 set_title(l10n_util::GetStringFUTF8(
1155 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM_REPLACE,
1156 pending_handler_.title(), UTF8ToUTF16(pending_handler_.url().host()),
1157 protocol, previous_handler_.title()));
1160 std::string radio_allow_label =
1161 l10n_util::GetStringFUTF8(IDS_REGISTER_PROTOCOL_HANDLER_ACCEPT,
1162 pending_handler_.title());
1163 std::string radio_deny_label =
1164 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_DENY);
1165 std::string radio_ignore_label =
1166 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_IGNORE);
1168 GURL url = web_contents->GetURL();
1169 RadioGroup radio_group;
1170 radio_group.url = url;
1172 radio_group.radio_items.push_back(radio_allow_label);
1173 radio_group.radio_items.push_back(radio_deny_label);
1174 radio_group.radio_items.push_back(radio_ignore_label);
1175 ContentSetting setting =
1176 content_settings->pending_protocol_handler_setting();
1177 if (setting == CONTENT_SETTING_ALLOW)
1178 radio_group.default_item = RPH_ALLOW;
1179 else if (setting == CONTENT_SETTING_BLOCK)
1180 radio_group.default_item = RPH_BLOCK;
1182 radio_group.default_item = RPH_IGNORE;
1184 selected_item_ = radio_group.default_item;
1185 set_radio_group_enabled(true);
1186 set_radio_group(radio_group);
1189 void ContentSettingRPHBubbleModel::OnRadioClicked(int radio_index) {
1190 if (selected_item_ == radio_index)
1193 selected_item_ = radio_index;
1195 if (radio_index == RPH_ALLOW)
1196 RegisterProtocolHandler();
1197 else if (radio_index == RPH_BLOCK)
1198 UnregisterProtocolHandler();
1199 else if (radio_index == RPH_IGNORE)
1200 IgnoreProtocolHandler();
1205 void ContentSettingRPHBubbleModel::OnDoneClicked() {
1206 // The user has one chance to deal with the RPH content setting UI,
1207 // then we remove it.
1208 TabSpecificContentSettings::FromWebContents(web_contents())->
1209 ClearPendingProtocolHandler();
1210 content::NotificationService::current()->Notify(
1211 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
1212 content::Source<WebContents>(web_contents()),
1213 content::NotificationService::NoDetails());
1216 void ContentSettingRPHBubbleModel::RegisterProtocolHandler() {
1217 // A no-op if the handler hasn't been ignored, but needed in case the user
1218 // selects sequences like register/ignore/register.
1219 registry_->RemoveIgnoredHandler(pending_handler_);
1221 registry_->OnAcceptRegisterProtocolHandler(pending_handler_);
1222 TabSpecificContentSettings::FromWebContents(web_contents())->
1223 set_pending_protocol_handler_setting(CONTENT_SETTING_ALLOW);
1226 void ContentSettingRPHBubbleModel::UnregisterProtocolHandler() {
1227 registry_->OnDenyRegisterProtocolHandler(pending_handler_);
1228 TabSpecificContentSettings::FromWebContents(web_contents())->
1229 set_pending_protocol_handler_setting(CONTENT_SETTING_BLOCK);
1230 ClearOrSetPreviousHandler();
1233 void ContentSettingRPHBubbleModel::IgnoreProtocolHandler() {
1234 registry_->OnIgnoreRegisterProtocolHandler(pending_handler_);
1235 TabSpecificContentSettings::FromWebContents(web_contents())->
1236 set_pending_protocol_handler_setting(CONTENT_SETTING_DEFAULT);
1237 ClearOrSetPreviousHandler();
1240 void ContentSettingRPHBubbleModel::ClearOrSetPreviousHandler() {
1241 if (previous_handler_.IsEmpty()) {
1242 registry_->ClearDefault(pending_handler_.protocol());
1244 registry_->OnAcceptRegisterProtocolHandler(previous_handler_);
1248 // TODO(toyoshim): Should share as many code with geolocation as possible.
1249 class ContentSettingMIDISysExBubbleModel
1250 : public ContentSettingTitleAndLinkModel {
1252 ContentSettingMIDISysExBubbleModel(Delegate* delegate,
1253 WebContents* web_contents,
1255 ContentSettingsType content_type);
1256 virtual ~ContentSettingMIDISysExBubbleModel() {}
1259 void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
1260 void SetDomainsAndCustomLink();
1261 virtual void OnCustomLinkClicked() OVERRIDE;
1264 ContentSettingMIDISysExBubbleModel::ContentSettingMIDISysExBubbleModel(
1266 WebContents* web_contents,
1268 ContentSettingsType content_type)
1269 : ContentSettingTitleAndLinkModel(
1270 delegate, web_contents, profile, content_type) {
1271 DCHECK_EQ(CONTENT_SETTINGS_TYPE_MIDI_SYSEX, content_type);
1272 SetDomainsAndCustomLink();
1275 void ContentSettingMIDISysExBubbleModel::MaybeAddDomainList(
1276 const std::set<std::string>& hosts, int title_id) {
1277 if (!hosts.empty()) {
1278 DomainList domain_list;
1279 domain_list.title = l10n_util::GetStringUTF8(title_id);
1280 domain_list.hosts = hosts;
1281 add_domain_list(domain_list);
1285 void ContentSettingMIDISysExBubbleModel::SetDomainsAndCustomLink() {
1286 TabSpecificContentSettings* content_settings =
1287 TabSpecificContentSettings::FromWebContents(web_contents());
1288 const ContentSettingsUsagesState& usages_state =
1289 content_settings->midi_usages_state();
1290 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
1291 unsigned int tab_state_flags = 0;
1292 usages_state.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
1293 // Divide the tab's current MIDI sysex users into sets according to their
1294 // permission state.
1295 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
1296 IDS_MIDI_SYSEX_BUBBLE_ALLOWED);
1298 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
1299 IDS_MIDI_SYSEX_BUBBLE_DENIED);
1301 if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
1302 set_custom_link(l10n_util::GetStringUTF8(
1303 IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK));
1304 set_custom_link_enabled(true);
1305 } else if (tab_state_flags &
1306 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
1307 set_custom_link(l10n_util::GetStringUTF8(
1308 IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
1312 void ContentSettingMIDISysExBubbleModel::OnCustomLinkClicked() {
1313 if (!web_contents())
1315 // Reset this embedder's entry to default for each of the requesting
1316 // origins currently on the page.
1317 TabSpecificContentSettings* content_settings =
1318 TabSpecificContentSettings::FromWebContents(web_contents());
1319 const ContentSettingsUsagesState::StateMap& state_map =
1320 content_settings->midi_usages_state().state_map();
1321 HostContentSettingsMap* settings_map =
1322 profile()->GetHostContentSettingsMap();
1324 for (ContentSettingsUsagesState::StateMap::const_iterator it =
1325 state_map.begin(); it != state_map.end(); ++it) {
1326 settings_map->SetContentSetting(
1327 ContentSettingsPattern::FromURLNoWildcard(it->first),
1328 ContentSettingsPattern::Wildcard(),
1329 CONTENT_SETTINGS_TYPE_MIDI_SYSEX,
1331 CONTENT_SETTING_DEFAULT);
1336 ContentSettingBubbleModel*
1337 ContentSettingBubbleModel::CreateContentSettingBubbleModel(
1339 WebContents* web_contents,
1341 ContentSettingsType content_type) {
1342 if (content_type == CONTENT_SETTINGS_TYPE_SAVE_PASSWORD) {
1343 return new SavePasswordBubbleModel(delegate, web_contents, profile);
1345 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES) {
1346 return new ContentSettingCookiesBubbleModel(delegate, web_contents, profile,
1349 if (content_type == CONTENT_SETTINGS_TYPE_POPUPS) {
1350 return new ContentSettingPopupBubbleModel(delegate, web_contents, profile,
1353 if (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
1354 return new ContentSettingDomainListBubbleModel(delegate, web_contents,
1355 profile, content_type);
1357 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM) {
1358 return new ContentSettingMediaStreamBubbleModel(delegate, web_contents,
1361 if (content_type == CONTENT_SETTINGS_TYPE_PLUGINS) {
1362 return new ContentSettingPluginBubbleModel(delegate, web_contents, profile,
1365 if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT) {
1366 return new ContentSettingMixedScriptBubbleModel(delegate, web_contents,
1367 profile, content_type);
1369 if (content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS) {
1370 ProtocolHandlerRegistry* registry =
1371 ProtocolHandlerRegistryFactory::GetForProfile(profile);
1372 return new ContentSettingRPHBubbleModel(delegate, web_contents, profile,
1373 registry, content_type);
1375 if (content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
1376 return new ContentSettingMIDISysExBubbleModel(delegate, web_contents,
1377 profile, content_type);
1379 return new ContentSettingSingleRadioGroup(delegate, web_contents, profile,
1383 ContentSettingBubbleModel::ContentSettingBubbleModel(
1384 WebContents* web_contents,
1386 ContentSettingsType content_type)
1387 : web_contents_(web_contents),
1389 content_type_(content_type) {
1390 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
1391 content::Source<WebContents>(web_contents));
1392 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
1393 content::Source<Profile>(profile_));
1396 ContentSettingBubbleModel::~ContentSettingBubbleModel() {
1399 ContentSettingBubbleModel::RadioGroup::RadioGroup() : default_item(0) {}
1401 ContentSettingBubbleModel::RadioGroup::~RadioGroup() {}
1403 ContentSettingBubbleModel::DomainList::DomainList() {}
1405 ContentSettingBubbleModel::DomainList::~DomainList() {}
1407 ContentSettingBubbleModel::MediaMenu::MediaMenu() : disabled(false) {}
1409 ContentSettingBubbleModel::MediaMenu::~MediaMenu() {}
1411 ContentSettingBubbleModel::BubbleContent::BubbleContent()
1412 : radio_group_enabled(false),
1413 custom_link_enabled(false) {
1416 ContentSettingBubbleModel::BubbleContent::~BubbleContent() {}
1419 void ContentSettingBubbleModel::AddBlockedResource(
1420 const std::string& resource_identifier) {
1421 bubble_content_.resource_identifiers.insert(resource_identifier);
1424 void ContentSettingBubbleModel::Observe(
1426 const content::NotificationSource& source,
1427 const content::NotificationDetails& details) {
1428 if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) {
1429 DCHECK_EQ(web_contents_,
1430 content::Source<WebContents>(source).ptr());
1431 web_contents_ = NULL;
1433 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
1434 DCHECK_EQ(profile_, content::Source<Profile>(source).ptr());