Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / ui / content_settings / content_setting_bubble_model.cc
blob8b37d7dcc412897e4cb904cba2e01403e42d6499
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
7 #include "base/command_line.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/content_settings/chrome_content_settings_utils.h"
12 #include "chrome/browser/content_settings/cookie_settings.h"
13 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
14 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
15 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
16 #include "chrome/browser/favicon/favicon_tab_helper.h"
17 #include "chrome/browser/infobars/infobar_service.h"
18 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
19 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
22 #include "chrome/browser/ui/browser_navigator.h"
23 #include "chrome/browser/ui/collected_cookies_infobar_delegate.h"
24 #include "chrome/browser/ui/content_settings/content_setting_bubble_model_delegate.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/pref_names.h"
27 #include "chrome/common/render_messages.h"
28 #include "chrome/grit/generated_resources.h"
29 #include "components/content_settings/core/browser/content_settings_utils.h"
30 #include "components/content_settings/core/common/content_settings.h"
31 #include "content/public/browser/notification_service.h"
32 #include "content/public/browser/render_frame_host.h"
33 #include "content/public/browser/render_process_host.h"
34 #include "content/public/browser/render_view_host.h"
35 #include "content/public/browser/user_metrics.h"
36 #include "content/public/browser/web_contents.h"
37 #include "content/public/browser/web_contents_delegate.h"
38 #include "grit/components_strings.h"
39 #include "grit/theme_resources.h"
40 #include "net/base/net_util.h"
41 #include "ui/base/l10n/l10n_util.h"
42 #include "ui/base/resource/resource_bundle.h"
43 #include "ui/resources/grit/ui_resources.h"
45 using base::UserMetricsAction;
46 using content::WebContents;
47 using content_settings::SettingInfo;
48 using content_settings::SettingSource;
49 using content_settings::SETTING_SOURCE_USER;
50 using content_settings::SETTING_SOURCE_NONE;
52 namespace {
54 const int kAllowButtonIndex = 0;
56 // These states must match the order of appearance of the radio buttons
57 // in the XIB file for the Mac port.
58 enum RPHState {
59 RPH_ALLOW = 0,
60 RPH_BLOCK,
61 RPH_IGNORE,
64 struct ContentSettingsTypeIdEntry {
65 ContentSettingsType type;
66 int id;
69 int GetIdForContentType(const ContentSettingsTypeIdEntry* entries,
70 size_t num_entries,
71 ContentSettingsType type) {
72 for (size_t i = 0; i < num_entries; ++i) {
73 if (entries[i].type == type)
74 return entries[i].id;
76 return 0;
79 const content::MediaStreamDevice& GetMediaDeviceById(
80 const std::string& device_id,
81 const content::MediaStreamDevices& devices) {
82 DCHECK(!devices.empty());
83 for (const content::MediaStreamDevice& device : devices) {
84 if (device.id == device_id)
85 return device;
88 // A device with the |device_id| was not found. It is likely that the device
89 // has been unplugged from the OS. Return the first device as the default
90 // device.
91 return *devices.begin();
94 } // namespace
96 ContentSettingTitleAndLinkModel::ContentSettingTitleAndLinkModel(
97 Delegate* delegate,
98 WebContents* web_contents,
99 Profile* profile,
100 ContentSettingsType content_type)
101 : ContentSettingBubbleModel(web_contents, profile, content_type),
102 delegate_(delegate) {
103 // Notifications do not have a bubble.
104 DCHECK_NE(content_type, CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
105 SetTitle();
106 SetManageLink();
107 SetLearnMoreLink();
110 void ContentSettingTitleAndLinkModel::SetTitle() {
111 TabSpecificContentSettings* content_settings = NULL;
112 if (web_contents()) {
113 content_settings =
114 TabSpecificContentSettings::FromWebContents(web_contents());
117 static const ContentSettingsTypeIdEntry kBlockedTitleIDs[] = {
118 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_TITLE},
119 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_TITLE},
120 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_TITLE},
121 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_TITLE},
122 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_TITLE},
123 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT,
124 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT},
125 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER,
126 IDS_BLOCKED_PPAPI_BROKER_TITLE},
127 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_TITLE},
129 // Fields as for kBlockedTitleIDs, above.
130 static const ContentSettingsTypeIdEntry kAccessedTitleIDs[] = {
131 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_ACCESSED_COOKIES_TITLE},
132 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_TITLE},
133 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_TITLE},
135 const ContentSettingsTypeIdEntry *title_ids = kBlockedTitleIDs;
136 size_t num_title_ids = arraysize(kBlockedTitleIDs);
137 if (content_settings && content_settings->IsContentAllowed(content_type()) &&
138 !content_settings->IsContentBlocked(content_type())) {
139 title_ids = kAccessedTitleIDs;
140 num_title_ids = arraysize(kAccessedTitleIDs);
142 int title_id =
143 GetIdForContentType(title_ids, num_title_ids, content_type());
144 if (title_id)
145 set_title(l10n_util::GetStringUTF8(title_id));
148 void ContentSettingTitleAndLinkModel::SetManageLink() {
149 static const ContentSettingsTypeIdEntry kLinkIDs[] = {
150 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_LINK},
151 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_LINK},
152 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_LINK},
153 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LINK},
154 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_LINK},
155 {CONTENT_SETTINGS_TYPE_GEOLOCATION, IDS_GEOLOCATION_BUBBLE_MANAGE_LINK},
156 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_LEARN_MORE},
157 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, IDS_HANDLERS_BUBBLE_MANAGE_LINK},
158 {CONTENT_SETTINGS_TYPE_MEDIASTREAM, IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK},
159 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_PPAPI_BROKER_BUBBLE_MANAGE_LINK},
160 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOADS_LINK},
161 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX, IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK},
163 set_manage_link(l10n_util::GetStringUTF8(
164 GetIdForContentType(kLinkIDs, arraysize(kLinkIDs), content_type())));
167 void ContentSettingTitleAndLinkModel::OnManageLinkClicked() {
168 if (delegate_)
169 delegate_->ShowContentSettingsPage(content_type());
172 void ContentSettingTitleAndLinkModel::SetLearnMoreLink() {
173 static const ContentSettingsTypeIdEntry kLearnMoreIDs[] = {
174 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_LEARN_MORE},
176 int learn_more_id =
177 GetIdForContentType(kLearnMoreIDs, arraysize(kLearnMoreIDs),
178 content_type());
179 if (learn_more_id)
180 set_learn_more_link(l10n_util::GetStringUTF8(learn_more_id));
183 void ContentSettingTitleAndLinkModel::OnLearnMoreLinkClicked() {
184 if (delegate_)
185 delegate_->ShowLearnMorePage(content_type());
188 class ContentSettingTitleLinkAndCustomModel
189 : public ContentSettingTitleAndLinkModel {
190 public:
191 ContentSettingTitleLinkAndCustomModel(Delegate* delegate,
192 WebContents* web_contents,
193 Profile* profile,
194 ContentSettingsType content_type);
195 ~ContentSettingTitleLinkAndCustomModel() override {}
197 private:
198 void SetCustomLink();
199 void OnCustomLinkClicked() override {}
202 ContentSettingTitleLinkAndCustomModel::ContentSettingTitleLinkAndCustomModel(
203 Delegate* delegate,
204 WebContents* web_contents,
205 Profile* profile,
206 ContentSettingsType content_type)
207 : ContentSettingTitleAndLinkModel(
208 delegate, web_contents, profile, content_type) {
209 SetCustomLink();
212 void ContentSettingTitleLinkAndCustomModel::SetCustomLink() {
213 static const ContentSettingsTypeIdEntry kCustomIDs[] = {
214 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_INFO},
215 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LOAD_ALL},
216 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_ALLOW_INSECURE_CONTENT_BUTTON},
218 int custom_link_id =
219 GetIdForContentType(kCustomIDs, arraysize(kCustomIDs), content_type());
220 if (custom_link_id)
221 set_custom_link(l10n_util::GetStringUTF8(custom_link_id));
224 class ContentSettingSingleRadioGroup
225 : public ContentSettingTitleLinkAndCustomModel {
226 public:
227 ContentSettingSingleRadioGroup(Delegate* delegate,
228 WebContents* web_contents,
229 Profile* profile,
230 ContentSettingsType content_type);
231 ~ContentSettingSingleRadioGroup() override;
233 protected:
234 bool settings_changed() const;
235 int selected_item() const { return selected_item_; }
237 private:
238 void SetRadioGroup();
239 void AddException(ContentSetting setting);
240 void OnRadioClicked(int radio_index) override;
242 ContentSetting block_setting_;
243 int selected_item_;
246 ContentSettingSingleRadioGroup::ContentSettingSingleRadioGroup(
247 Delegate* delegate,
248 WebContents* web_contents,
249 Profile* profile,
250 ContentSettingsType content_type)
251 : ContentSettingTitleLinkAndCustomModel(delegate, web_contents, profile,
252 content_type),
253 block_setting_(CONTENT_SETTING_BLOCK),
254 selected_item_(0) {
255 SetRadioGroup();
258 ContentSettingSingleRadioGroup::~ContentSettingSingleRadioGroup() {
259 if (settings_changed()) {
260 ContentSetting setting =
261 selected_item_ == kAllowButtonIndex ?
262 CONTENT_SETTING_ALLOW :
263 block_setting_;
264 AddException(setting);
268 bool ContentSettingSingleRadioGroup::settings_changed() const {
269 return selected_item_ != bubble_content().radio_group.default_item;
272 // Initialize the radio group by setting the appropriate labels for the
273 // content type and setting the default value based on the content setting.
274 void ContentSettingSingleRadioGroup::SetRadioGroup() {
275 GURL url = web_contents()->GetURL();
276 base::string16 display_host;
277 net::AppendFormattedHost(
278 url,
279 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
280 &display_host);
282 if (display_host.empty())
283 display_host = base::ASCIIToUTF16(url.spec());
285 TabSpecificContentSettings* content_settings =
286 TabSpecificContentSettings::FromWebContents(web_contents());
287 bool allowed =
288 !content_settings->IsContentBlocked(content_type());
289 DCHECK(!allowed ||
290 content_settings->IsContentAllowed(content_type()));
292 RadioGroup radio_group;
293 radio_group.url = url;
295 static const ContentSettingsTypeIdEntry kBlockedAllowIDs[] = {
296 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
297 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_UNBLOCK},
298 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_UNBLOCK},
299 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_UNBLOCK_ALL},
300 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_UNBLOCK},
301 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_UNBLOCK},
302 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_UNBLOCK},
304 // Fields as for kBlockedAllowIDs, above.
305 static const ContentSettingsTypeIdEntry kAllowedAllowIDs[] = {
306 // TODO(bauerb): The string shouldn't be "unblock" (they weren't blocked).
307 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
308 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_NO_ACTION},
309 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_NO_ACTION},
312 std::string radio_allow_label;
313 if (allowed) {
314 int resource_id = GetIdForContentType(kAllowedAllowIDs,
315 arraysize(kAllowedAllowIDs),
316 content_type());
317 radio_allow_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
318 l10n_util::GetStringFUTF8(resource_id, display_host) :
319 l10n_util::GetStringUTF8(resource_id);
320 } else {
321 radio_allow_label = l10n_util::GetStringFUTF8(
322 GetIdForContentType(kBlockedAllowIDs, arraysize(kBlockedAllowIDs),
323 content_type()),
324 display_host);
327 static const ContentSettingsTypeIdEntry kBlockedBlockIDs[] = {
328 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
329 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_NO_ACTION},
330 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_NO_ACTION},
331 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_NO_ACTION},
332 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_NO_ACTION},
333 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_NO_ACTION},
334 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_NO_ACTION},
336 static const ContentSettingsTypeIdEntry kAllowedBlockIDs[] = {
337 // TODO(bauerb): The string should say "block".
338 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
339 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_BLOCK},
340 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_BLOCK},
343 std::string radio_block_label;
344 if (allowed) {
345 int resource_id = GetIdForContentType(kAllowedBlockIDs,
346 arraysize(kAllowedBlockIDs),
347 content_type());
348 radio_block_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
349 l10n_util::GetStringUTF8(resource_id) :
350 l10n_util::GetStringFUTF8(resource_id, display_host);
351 } else {
352 radio_block_label = l10n_util::GetStringUTF8(
353 GetIdForContentType(kBlockedBlockIDs, arraysize(kBlockedBlockIDs),
354 content_type()));
357 radio_group.radio_items.push_back(radio_allow_label);
358 radio_group.radio_items.push_back(radio_block_label);
359 ContentSetting setting;
360 SettingSource setting_source = SETTING_SOURCE_NONE;
361 bool setting_is_wildcard = false;
363 if (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) {
364 CookieSettings* cookie_settings =
365 CookieSettings::Factory::GetForProfile(profile()).get();
366 setting = cookie_settings->GetCookieSetting(
367 url, url, true, &setting_source);
368 } else {
369 SettingInfo info;
370 HostContentSettingsMap* map = profile()->GetHostContentSettingsMap();
371 scoped_ptr<base::Value> value =
372 map->GetWebsiteSetting(url, url, content_type(), std::string(), &info);
373 setting = content_settings::ValueToContentSetting(value.get());
374 setting_source = info.source;
375 setting_is_wildcard =
376 info.primary_pattern == ContentSettingsPattern::Wildcard() &&
377 info.secondary_pattern == ContentSettingsPattern::Wildcard();
380 if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS &&
381 setting == CONTENT_SETTING_ALLOW &&
382 setting_is_wildcard) {
383 // In the corner case of unrecognized plugins (which are now blocked by
384 // default) we indicate the blocked state in the UI and allow the user to
385 // whitelist.
386 radio_group.default_item = 1;
387 } else if (setting == CONTENT_SETTING_ALLOW) {
388 radio_group.default_item = kAllowButtonIndex;
389 // |block_setting_| is already set to |CONTENT_SETTING_BLOCK|.
390 } else {
391 radio_group.default_item = 1;
392 block_setting_ = setting;
395 set_setting_is_managed(setting_source != SETTING_SOURCE_USER);
396 if (setting_source != SETTING_SOURCE_USER) {
397 set_radio_group_enabled(false);
398 } else {
399 set_radio_group_enabled(true);
401 selected_item_ = radio_group.default_item;
402 set_radio_group(radio_group);
405 void ContentSettingSingleRadioGroup::AddException(ContentSetting setting) {
406 if (profile()) {
407 profile()->GetHostContentSettingsMap()->AddExceptionForURL(
408 bubble_content().radio_group.url,
409 bubble_content().radio_group.url,
410 content_type(),
411 setting);
415 void ContentSettingSingleRadioGroup::OnRadioClicked(int radio_index) {
416 selected_item_ = radio_index;
419 class ContentSettingCookiesBubbleModel : public ContentSettingSingleRadioGroup {
420 public:
421 ContentSettingCookiesBubbleModel(Delegate* delegate,
422 WebContents* web_contents,
423 Profile* profile);
425 ~ContentSettingCookiesBubbleModel() override;
427 private:
428 void OnCustomLinkClicked() override;
431 ContentSettingCookiesBubbleModel::ContentSettingCookiesBubbleModel(
432 Delegate* delegate,
433 WebContents* web_contents,
434 Profile* profile)
435 : ContentSettingSingleRadioGroup(delegate,
436 web_contents,
437 profile,
438 CONTENT_SETTINGS_TYPE_COOKIES) {
439 set_custom_link_enabled(true);
442 ContentSettingCookiesBubbleModel::~ContentSettingCookiesBubbleModel() {
443 // On some plattforms e.g. MacOS X it is possible to close a tab while the
444 // cookies settings bubble is open. This resets the web contents to NULL.
445 if (settings_changed() && web_contents()) {
446 CollectedCookiesInfoBarDelegate::Create(
447 InfoBarService::FromWebContents(web_contents()));
451 void ContentSettingCookiesBubbleModel::OnCustomLinkClicked() {
452 if (!web_contents())
453 return;
454 content::NotificationService::current()->Notify(
455 chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN,
456 content::Source<TabSpecificContentSettings>(
457 TabSpecificContentSettings::FromWebContents(web_contents())),
458 content::NotificationService::NoDetails());
459 delegate()->ShowCollectedCookiesDialog(web_contents());
462 class ContentSettingPluginBubbleModel : public ContentSettingSingleRadioGroup {
463 public:
464 ContentSettingPluginBubbleModel(Delegate* delegate,
465 WebContents* web_contents,
466 Profile* profile);
468 ~ContentSettingPluginBubbleModel() override;
470 private:
471 void OnCustomLinkClicked() override;
474 ContentSettingPluginBubbleModel::ContentSettingPluginBubbleModel(
475 Delegate* delegate,
476 WebContents* web_contents,
477 Profile* profile)
478 : ContentSettingSingleRadioGroup(delegate,
479 web_contents,
480 profile,
481 CONTENT_SETTINGS_TYPE_PLUGINS) {
482 // Disable the "Run all plugins this time" link if the setting is managed and
483 // can't be controlled by the user or if the user already clicked on the link
484 // and ran all plugins.
485 set_custom_link_enabled(!setting_is_managed() &&
486 web_contents &&
487 TabSpecificContentSettings::FromWebContents(
488 web_contents)->load_plugins_link_enabled());
489 // Build blocked plugin list.
490 if (web_contents) {
491 TabSpecificContentSettings* content_settings =
492 TabSpecificContentSettings::FromWebContents(web_contents);
494 const std::vector<base::string16>& blocked_plugins =
495 content_settings->blocked_plugin_names();
496 for (const base::string16& blocked_plugin : blocked_plugins) {
497 ListItem plugin_item(
498 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
499 IDR_BLOCKED_PLUGINS),
500 base::UTF16ToUTF8(blocked_plugin), false, 0);
501 add_list_item(plugin_item);
506 ContentSettingPluginBubbleModel::~ContentSettingPluginBubbleModel() {
507 if (settings_changed()) {
508 // If the user elected to allow all plugins then run plugins at this time.
509 if (selected_item() == kAllowButtonIndex)
510 OnCustomLinkClicked();
514 void ContentSettingPluginBubbleModel::OnCustomLinkClicked() {
515 content::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble"));
516 // Web contents can be NULL if the tab was closed while the plugins
517 // settings bubble is visible.
518 if (!web_contents())
519 return;
520 #if defined(ENABLE_PLUGINS)
521 // TODO(bauerb): We should send the identifiers of blocked plugins here.
522 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
523 web_contents(), true, std::string());
524 #endif
525 set_custom_link_enabled(false);
526 TabSpecificContentSettings::FromWebContents(web_contents())->
527 set_load_plugins_link_enabled(false);
530 class ContentSettingPopupBubbleModel : public ContentSettingSingleRadioGroup {
531 public:
532 ContentSettingPopupBubbleModel(Delegate* delegate,
533 WebContents* web_contents,
534 Profile* profile);
535 ~ContentSettingPopupBubbleModel() override {}
537 private:
538 void OnListItemClicked(int index) override;
540 int32 item_id_from_item_index(int index) const {
541 return bubble_content().list_items[index].item_id;
545 ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel(
546 Delegate* delegate,
547 WebContents* web_contents,
548 Profile* profile)
549 : ContentSettingSingleRadioGroup(delegate,
550 web_contents,
551 profile,
552 CONTENT_SETTINGS_TYPE_POPUPS) {
553 if (web_contents) {
554 // Build blocked popup list.
555 std::map<int32, GURL> blocked_popups =
556 PopupBlockerTabHelper::FromWebContents(web_contents)
557 ->GetBlockedPopupRequests();
558 for (const std::pair<int32, GURL>& blocked_popup : blocked_popups) {
559 std::string title(blocked_popup.second.spec());
560 // The popup may not have a valid URL.
561 if (title.empty())
562 title = l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE);
563 ListItem popup_item(ui::ResourceBundle::GetSharedInstance().GetImageNamed(
564 IDR_DEFAULT_FAVICON),
565 title, true, blocked_popup.first);
566 add_list_item(popup_item);
571 void ContentSettingPopupBubbleModel::OnListItemClicked(int index) {
572 if (web_contents()) {
573 PopupBlockerTabHelper::FromWebContents(web_contents())
574 ->ShowBlockedPopup(item_id_from_item_index(index));
578 // The model of the content settings bubble for media settings.
579 class ContentSettingMediaStreamBubbleModel
580 : public ContentSettingTitleAndLinkModel {
581 public:
582 ContentSettingMediaStreamBubbleModel(Delegate* delegate,
583 WebContents* web_contents,
584 Profile* profile);
586 ~ContentSettingMediaStreamBubbleModel() override;
588 private:
589 void SetTitle();
590 // Sets the data for the radio buttons of the bubble.
591 void SetRadioGroup();
592 // Sets the data for the media menus of the bubble.
593 void SetMediaMenus();
594 void SetCustomLink();
595 // Updates the camera and microphone setting with the passed |setting|.
596 void UpdateSettings(ContentSetting setting);
597 // Updates the camera and microphone default device with the passed |type|
598 // and device.
599 void UpdateDefaultDeviceForType(content::MediaStreamType type,
600 const std::string& device);
602 // ContentSettingBubbleModel implementation.
603 void OnRadioClicked(int radio_index) override;
604 void OnMediaMenuClicked(content::MediaStreamType type,
605 const std::string& selected_device) override;
607 // The index of the selected radio item.
608 int selected_item_;
609 // The content settings that are associated with the individual radio
610 // buttons.
611 ContentSetting radio_item_setting_[2];
612 // The state of the microphone and camera access.
613 TabSpecificContentSettings::MicrophoneCameraState state_;
616 ContentSettingMediaStreamBubbleModel::ContentSettingMediaStreamBubbleModel(
617 Delegate* delegate,
618 WebContents* web_contents,
619 Profile* profile)
620 : ContentSettingTitleAndLinkModel(
621 delegate, web_contents, profile, CONTENT_SETTINGS_TYPE_MEDIASTREAM),
622 selected_item_(0),
623 state_(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED) {
624 DCHECK(profile);
625 // Initialize the content settings associated with the individual radio
626 // buttons.
627 radio_item_setting_[0] = CONTENT_SETTING_ASK;
628 radio_item_setting_[1] = CONTENT_SETTING_BLOCK;
630 TabSpecificContentSettings* content_settings =
631 TabSpecificContentSettings::FromWebContents(web_contents);
632 state_ = content_settings->GetMicrophoneCameraState();
633 DCHECK(state_ & (TabSpecificContentSettings::MICROPHONE_ACCESSED |
634 TabSpecificContentSettings::CAMERA_ACCESSED));
636 SetTitle();
637 SetRadioGroup();
638 SetMediaMenus();
639 SetCustomLink();
642 ContentSettingMediaStreamBubbleModel::~ContentSettingMediaStreamBubbleModel() {
643 // On some platforms (e.g. MacOS X) it is possible to close a tab while the
644 // media stream bubble is open. This resets the web contents to NULL.
645 if (!web_contents())
646 return;
648 for (const std::pair<content::MediaStreamType, MediaMenu>& media_menu :
649 bubble_content().media_menus) {
650 if (media_menu.second.selected_device.id !=
651 media_menu.second.default_device.id) {
652 UpdateDefaultDeviceForType(media_menu.first,
653 media_menu.second.selected_device.id);
657 // Update the media settings if the radio button selection was changed.
658 if (selected_item_ != bubble_content().radio_group.default_item) {
659 UpdateSettings(radio_item_setting_[selected_item_]);
663 void ContentSettingMediaStreamBubbleModel::SetTitle() {
664 DCHECK_NE(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED, state_);
665 int title_id = 0;
666 if (state_ & TabSpecificContentSettings::MICROPHONE_BLOCKED) {
667 title_id = (state_ & TabSpecificContentSettings::CAMERA_BLOCKED) ?
668 IDS_MICROPHONE_CAMERA_BLOCKED : IDS_MICROPHONE_BLOCKED;
669 } else if (state_ & TabSpecificContentSettings::CAMERA_BLOCKED) {
670 title_id = IDS_CAMERA_BLOCKED;
671 } else if (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) {
672 title_id = (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) ?
673 IDS_MICROPHONE_CAMERA_ALLOWED : IDS_MICROPHONE_ACCESSED;
674 } else if (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) {
675 title_id = IDS_CAMERA_ACCESSED;
677 set_title(l10n_util::GetStringUTF8(title_id));
680 void ContentSettingMediaStreamBubbleModel::SetRadioGroup() {
681 TabSpecificContentSettings* content_settings =
682 TabSpecificContentSettings::FromWebContents(web_contents());
683 GURL url = content_settings->media_stream_access_origin();
684 RadioGroup radio_group;
685 radio_group.url = url;
687 base::string16 display_host_utf16;
688 net::AppendFormattedHost(
689 url,
690 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
691 &display_host_utf16);
692 std::string display_host(base::UTF16ToUTF8(display_host_utf16));
693 if (display_host.empty())
694 display_host = url.spec();
696 bool is_mic = (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) != 0;
697 bool is_cam = (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) != 0;
698 DCHECK(is_mic || is_cam);
699 int radio_allow_label_id = 0;
700 int radio_block_label_id = 0;
701 if (state_ & (TabSpecificContentSettings::MICROPHONE_BLOCKED |
702 TabSpecificContentSettings::CAMERA_BLOCKED)) {
703 if (url.SchemeIsSecure()) {
704 radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
705 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW;
706 if (is_mic)
707 radio_allow_label_id = is_cam ?
708 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ALLOW :
709 IDS_BLOCKED_MEDIASTREAM_MIC_ALLOW;
710 } else {
711 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK;
712 if (is_mic)
713 radio_allow_label_id = is_cam ?
714 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ASK :
715 IDS_BLOCKED_MEDIASTREAM_MIC_ASK;
717 radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION;
718 if (is_mic)
719 radio_block_label_id = is_cam ?
720 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION :
721 IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION;
722 } else {
723 if (is_mic && is_cam) {
724 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION;
725 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK;
726 } else if (is_mic) {
727 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION;
728 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK;
729 } else {
730 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION;
731 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK;
734 selected_item_ =
735 (is_mic && content_settings->IsContentBlocked(
736 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC)) ||
737 (is_cam && content_settings->IsContentBlocked(
738 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA)) ? 1 : 0;
740 std::string radio_allow_label = l10n_util::GetStringFUTF8(
741 radio_allow_label_id, base::UTF8ToUTF16(display_host));
742 std::string radio_block_label =
743 l10n_util::GetStringUTF8(radio_block_label_id);
745 radio_group.default_item = selected_item_;
746 radio_group.radio_items.push_back(radio_allow_label);
747 radio_group.radio_items.push_back(radio_block_label);
749 set_radio_group(radio_group);
750 set_radio_group_enabled(true);
753 void ContentSettingMediaStreamBubbleModel::UpdateSettings(
754 ContentSetting setting) {
755 if (profile()) {
756 HostContentSettingsMap* content_settings =
757 profile()->GetHostContentSettingsMap();
758 TabSpecificContentSettings* tab_content_settings =
759 TabSpecificContentSettings::FromWebContents(web_contents());
760 // The same patterns must be used as in other places (e.g. the infobar) in
761 // order to override the existing rule. Otherwise a new rule is created.
762 // TODO(markusheintz): Extract to a helper so that there is only a single
763 // place to touch.
764 ContentSettingsPattern primary_pattern =
765 ContentSettingsPattern::FromURLNoWildcard(
766 tab_content_settings->media_stream_access_origin());
767 ContentSettingsPattern secondary_pattern =
768 ContentSettingsPattern::Wildcard();
769 if (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) {
770 content_settings->SetContentSetting(
771 primary_pattern, secondary_pattern,
772 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string(), setting);
774 if (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) {
775 content_settings->SetContentSetting(
776 primary_pattern, secondary_pattern,
777 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string(), setting);
782 void ContentSettingMediaStreamBubbleModel::UpdateDefaultDeviceForType(
783 content::MediaStreamType type,
784 const std::string& device) {
785 PrefService* prefs = profile()->GetPrefs();
786 if (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
787 prefs->SetString(prefs::kDefaultAudioCaptureDevice, device);
788 } else {
789 DCHECK_EQ(content::MEDIA_DEVICE_VIDEO_CAPTURE, type);
790 prefs->SetString(prefs::kDefaultVideoCaptureDevice, device);
794 void ContentSettingMediaStreamBubbleModel::SetMediaMenus() {
795 TabSpecificContentSettings* content_settings =
796 TabSpecificContentSettings::FromWebContents(web_contents());
797 const std::string& requested_microphone =
798 content_settings->media_stream_requested_audio_device();
799 const std::string& requested_camera =
800 content_settings->media_stream_requested_video_device();
802 // Add microphone menu.
803 PrefService* prefs = profile()->GetPrefs();
804 MediaCaptureDevicesDispatcher* dispatcher =
805 MediaCaptureDevicesDispatcher::GetInstance();
806 const content::MediaStreamDevices& microphones =
807 dispatcher->GetAudioCaptureDevices();
809 if (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) {
810 MediaMenu mic_menu;
811 mic_menu.label = l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_MIC_LABEL);
812 if (!microphones.empty()) {
813 std::string preferred_mic;
814 if (requested_microphone.empty()) {
815 preferred_mic = prefs->GetString(prefs::kDefaultAudioCaptureDevice);
816 mic_menu.disabled = false;
817 } else {
818 // Set the |disabled| to true in order to disable the device selection
819 // menu on the media settings bubble. This must be done if the website
820 // manages the microphone devices itself.
821 preferred_mic = requested_microphone;
822 mic_menu.disabled = true;
825 mic_menu.default_device = GetMediaDeviceById(preferred_mic, microphones);
826 mic_menu.selected_device = mic_menu.default_device;
828 add_media_menu(content::MEDIA_DEVICE_AUDIO_CAPTURE, mic_menu);
831 if (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) {
832 const content::MediaStreamDevices& cameras =
833 dispatcher->GetVideoCaptureDevices();
834 MediaMenu camera_menu;
835 camera_menu.label =
836 l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_CAMERA_LABEL);
837 if (!cameras.empty()) {
838 std::string preferred_camera;
839 if (requested_camera.empty()) {
840 preferred_camera = prefs->GetString(prefs::kDefaultVideoCaptureDevice);
841 camera_menu.disabled = false;
842 } else {
843 // Disable the menu since the website is managing the camera devices
844 // itself.
845 preferred_camera = requested_camera;
846 camera_menu.disabled = true;
849 camera_menu.default_device =
850 GetMediaDeviceById(preferred_camera, cameras);
851 camera_menu.selected_device = camera_menu.default_device;
853 add_media_menu(content::MEDIA_DEVICE_VIDEO_CAPTURE, camera_menu);
857 void ContentSettingMediaStreamBubbleModel::SetCustomLink() {
858 TabSpecificContentSettings* content_settings =
859 TabSpecificContentSettings::FromWebContents(web_contents());
860 if (content_settings->IsMicrophoneCameraStateChanged()) {
861 set_custom_link(l10n_util::GetStringUTF8(
862 IDS_MEDIASTREAM_SETTING_CHANGED_MESSAGE));
866 void ContentSettingMediaStreamBubbleModel::OnRadioClicked(int radio_index) {
867 selected_item_ = radio_index;
870 void ContentSettingMediaStreamBubbleModel::OnMediaMenuClicked(
871 content::MediaStreamType type,
872 const std::string& selected_device_id) {
873 DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
874 type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
875 DCHECK_EQ(1U, bubble_content().media_menus.count(type));
876 MediaCaptureDevicesDispatcher* dispatcher =
877 MediaCaptureDevicesDispatcher::GetInstance();
878 const content::MediaStreamDevices& devices =
879 (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) ?
880 dispatcher->GetAudioCaptureDevices() :
881 dispatcher->GetVideoCaptureDevices();
882 set_selected_device(GetMediaDeviceById(selected_device_id, devices));
885 class ContentSettingDomainListBubbleModel
886 : public ContentSettingTitleAndLinkModel {
887 public:
888 ContentSettingDomainListBubbleModel(Delegate* delegate,
889 WebContents* web_contents,
890 Profile* profile,
891 ContentSettingsType content_type);
892 ~ContentSettingDomainListBubbleModel() override {}
894 private:
895 void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
896 void SetDomainsAndCustomLink();
897 void OnCustomLinkClicked() override;
900 ContentSettingDomainListBubbleModel::ContentSettingDomainListBubbleModel(
901 Delegate* delegate,
902 WebContents* web_contents,
903 Profile* profile,
904 ContentSettingsType content_type)
905 : ContentSettingTitleAndLinkModel(
906 delegate, web_contents, profile, content_type) {
907 DCHECK_EQ(CONTENT_SETTINGS_TYPE_GEOLOCATION, content_type) <<
908 "SetDomains currently only supports geolocation content type";
909 SetDomainsAndCustomLink();
912 void ContentSettingDomainListBubbleModel::MaybeAddDomainList(
913 const std::set<std::string>& hosts, int title_id) {
914 if (!hosts.empty()) {
915 DomainList domain_list;
916 domain_list.title = l10n_util::GetStringUTF8(title_id);
917 domain_list.hosts = hosts;
918 add_domain_list(domain_list);
922 void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() {
923 TabSpecificContentSettings* content_settings =
924 TabSpecificContentSettings::FromWebContents(web_contents());
925 const ContentSettingsUsagesState& usages =
926 content_settings->geolocation_usages_state();
927 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
928 unsigned int tab_state_flags = 0;
929 usages.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
930 // Divide the tab's current geolocation users into sets according to their
931 // permission state.
932 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
933 IDS_GEOLOCATION_BUBBLE_SECTION_ALLOWED);
935 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
936 IDS_GEOLOCATION_BUBBLE_SECTION_DENIED);
938 if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
939 set_custom_link(l10n_util::GetStringUTF8(
940 IDS_GEOLOCATION_BUBBLE_CLEAR_LINK));
941 set_custom_link_enabled(true);
942 } else if (tab_state_flags &
943 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
944 set_custom_link(l10n_util::GetStringUTF8(
945 IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
949 void ContentSettingDomainListBubbleModel::OnCustomLinkClicked() {
950 if (!web_contents())
951 return;
952 // Reset this embedder's entry to default for each of the requesting
953 // origins currently on the page.
954 const GURL& embedder_url = web_contents()->GetURL();
955 TabSpecificContentSettings* content_settings =
956 TabSpecificContentSettings::FromWebContents(web_contents());
957 const ContentSettingsUsagesState::StateMap& state_map =
958 content_settings->geolocation_usages_state().state_map();
959 HostContentSettingsMap* settings_map =
960 profile()->GetHostContentSettingsMap();
962 for (const std::pair<GURL, ContentSetting>& map_entry : state_map) {
963 settings_map->SetContentSetting(
964 ContentSettingsPattern::FromURLNoWildcard(map_entry.first),
965 ContentSettingsPattern::FromURLNoWildcard(embedder_url),
966 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string(),
967 CONTENT_SETTING_DEFAULT);
971 class ContentSettingMixedScriptBubbleModel
972 : public ContentSettingTitleLinkAndCustomModel {
973 public:
974 ContentSettingMixedScriptBubbleModel(Delegate* delegate,
975 WebContents* web_contents,
976 Profile* profile);
978 ~ContentSettingMixedScriptBubbleModel() override {}
980 private:
981 void OnCustomLinkClicked() override;
984 ContentSettingMixedScriptBubbleModel::ContentSettingMixedScriptBubbleModel(
985 Delegate* delegate,
986 WebContents* web_contents,
987 Profile* profile)
988 : ContentSettingTitleLinkAndCustomModel(delegate,
989 web_contents,
990 profile,
991 CONTENT_SETTINGS_TYPE_MIXEDSCRIPT) {
992 content_settings::RecordMixedScriptAction(
993 content_settings::MIXED_SCRIPT_ACTION_DISPLAYED_BUBBLE);
994 set_custom_link_enabled(true);
997 void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
998 content_settings::RecordMixedScriptAction(
999 content_settings::MIXED_SCRIPT_ACTION_CLICKED_ALLOW);
1000 DCHECK(web_contents());
1001 web_contents()->SendToAllFrames(
1002 new ChromeViewMsg_SetAllowRunningInsecureContent(MSG_ROUTING_NONE, true));
1003 web_contents()->GetMainFrame()->Send(new ChromeViewMsg_ReloadFrame(
1004 web_contents()->GetMainFrame()->GetRoutingID()));
1007 ContentSettingRPHBubbleModel::ContentSettingRPHBubbleModel(
1008 Delegate* delegate,
1009 WebContents* web_contents,
1010 Profile* profile,
1011 ProtocolHandlerRegistry* registry)
1012 : ContentSettingTitleAndLinkModel(delegate,
1013 web_contents,
1014 profile,
1015 CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS),
1016 selected_item_(0),
1017 registry_(registry),
1018 pending_handler_(ProtocolHandler::EmptyProtocolHandler()),
1019 previous_handler_(ProtocolHandler::EmptyProtocolHandler()) {
1020 TabSpecificContentSettings* content_settings =
1021 TabSpecificContentSettings::FromWebContents(web_contents);
1022 pending_handler_ = content_settings->pending_protocol_handler();
1023 previous_handler_ = content_settings->previous_protocol_handler();
1025 base::string16 protocol;
1026 if (pending_handler_.protocol() == "mailto") {
1027 protocol = l10n_util::GetStringUTF16(
1028 IDS_REGISTER_PROTOCOL_HANDLER_MAILTO_NAME);
1029 } else if (pending_handler_.protocol() == "webcal") {
1030 protocol = l10n_util::GetStringUTF16(
1031 IDS_REGISTER_PROTOCOL_HANDLER_WEBCAL_NAME);
1032 } else {
1033 protocol = base::UTF8ToUTF16(pending_handler_.protocol());
1036 // Note that we ignore the |title| parameter.
1037 if (previous_handler_.IsEmpty()) {
1038 set_title(l10n_util::GetStringFUTF8(
1039 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM,
1040 base::UTF8ToUTF16(pending_handler_.url().host()),
1041 protocol));
1042 } else {
1043 set_title(l10n_util::GetStringFUTF8(
1044 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM_REPLACE,
1045 base::UTF8ToUTF16(pending_handler_.url().host()),
1046 protocol,
1047 base::UTF8ToUTF16(previous_handler_.url().host())));
1050 std::string radio_allow_label =
1051 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_ACCEPT);
1052 std::string radio_deny_label =
1053 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_DENY);
1054 std::string radio_ignore_label =
1055 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_IGNORE);
1057 GURL url = web_contents->GetURL();
1058 RadioGroup radio_group;
1059 radio_group.url = url;
1061 radio_group.radio_items.push_back(radio_allow_label);
1062 radio_group.radio_items.push_back(radio_deny_label);
1063 radio_group.radio_items.push_back(radio_ignore_label);
1064 ContentSetting setting =
1065 content_settings->pending_protocol_handler_setting();
1066 if (setting == CONTENT_SETTING_ALLOW)
1067 radio_group.default_item = RPH_ALLOW;
1068 else if (setting == CONTENT_SETTING_BLOCK)
1069 radio_group.default_item = RPH_BLOCK;
1070 else
1071 radio_group.default_item = RPH_IGNORE;
1073 selected_item_ = radio_group.default_item;
1074 set_radio_group_enabled(true);
1075 set_radio_group(radio_group);
1078 void ContentSettingRPHBubbleModel::OnRadioClicked(int radio_index) {
1079 if (selected_item_ == radio_index)
1080 return;
1082 selected_item_ = radio_index;
1084 if (radio_index == RPH_ALLOW)
1085 RegisterProtocolHandler();
1086 else if (radio_index == RPH_BLOCK)
1087 UnregisterProtocolHandler();
1088 else if (radio_index == RPH_IGNORE)
1089 IgnoreProtocolHandler();
1090 else
1091 NOTREACHED();
1094 void ContentSettingRPHBubbleModel::OnDoneClicked() {
1095 // The user has one chance to deal with the RPH content setting UI,
1096 // then we remove it.
1097 TabSpecificContentSettings::FromWebContents(web_contents())->
1098 ClearPendingProtocolHandler();
1099 content::NotificationService::current()->Notify(
1100 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
1101 content::Source<WebContents>(web_contents()),
1102 content::NotificationService::NoDetails());
1105 void ContentSettingRPHBubbleModel::RegisterProtocolHandler() {
1106 // A no-op if the handler hasn't been ignored, but needed in case the user
1107 // selects sequences like register/ignore/register.
1108 registry_->RemoveIgnoredHandler(pending_handler_);
1110 registry_->OnAcceptRegisterProtocolHandler(pending_handler_);
1111 TabSpecificContentSettings::FromWebContents(web_contents())->
1112 set_pending_protocol_handler_setting(CONTENT_SETTING_ALLOW);
1115 void ContentSettingRPHBubbleModel::UnregisterProtocolHandler() {
1116 registry_->OnDenyRegisterProtocolHandler(pending_handler_);
1117 TabSpecificContentSettings::FromWebContents(web_contents())->
1118 set_pending_protocol_handler_setting(CONTENT_SETTING_BLOCK);
1119 ClearOrSetPreviousHandler();
1122 void ContentSettingRPHBubbleModel::IgnoreProtocolHandler() {
1123 registry_->OnIgnoreRegisterProtocolHandler(pending_handler_);
1124 TabSpecificContentSettings::FromWebContents(web_contents())->
1125 set_pending_protocol_handler_setting(CONTENT_SETTING_DEFAULT);
1126 ClearOrSetPreviousHandler();
1129 void ContentSettingRPHBubbleModel::ClearOrSetPreviousHandler() {
1130 if (previous_handler_.IsEmpty()) {
1131 registry_->ClearDefault(pending_handler_.protocol());
1132 } else {
1133 registry_->OnAcceptRegisterProtocolHandler(previous_handler_);
1137 class ContentSettingMidiSysExBubbleModel
1138 : public ContentSettingTitleAndLinkModel {
1139 public:
1140 ContentSettingMidiSysExBubbleModel(Delegate* delegate,
1141 WebContents* web_contents,
1142 Profile* profile);
1143 ~ContentSettingMidiSysExBubbleModel() override {}
1145 private:
1146 void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
1147 void SetDomainsAndCustomLink();
1148 void OnCustomLinkClicked() override;
1151 ContentSettingMidiSysExBubbleModel::ContentSettingMidiSysExBubbleModel(
1152 Delegate* delegate,
1153 WebContents* web_contents,
1154 Profile* profile)
1155 : ContentSettingTitleAndLinkModel(delegate,
1156 web_contents,
1157 profile,
1158 CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
1159 SetDomainsAndCustomLink();
1162 void ContentSettingMidiSysExBubbleModel::MaybeAddDomainList(
1163 const std::set<std::string>& hosts, int title_id) {
1164 if (!hosts.empty()) {
1165 DomainList domain_list;
1166 domain_list.title = l10n_util::GetStringUTF8(title_id);
1167 domain_list.hosts = hosts;
1168 add_domain_list(domain_list);
1172 void ContentSettingMidiSysExBubbleModel::SetDomainsAndCustomLink() {
1173 TabSpecificContentSettings* content_settings =
1174 TabSpecificContentSettings::FromWebContents(web_contents());
1175 const ContentSettingsUsagesState& usages_state =
1176 content_settings->midi_usages_state();
1177 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
1178 unsigned int tab_state_flags = 0;
1179 usages_state.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
1180 // Divide the tab's current MIDI sysex users into sets according to their
1181 // permission state.
1182 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
1183 IDS_MIDI_SYSEX_BUBBLE_ALLOWED);
1185 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
1186 IDS_MIDI_SYSEX_BUBBLE_DENIED);
1188 if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
1189 set_custom_link(l10n_util::GetStringUTF8(
1190 IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK));
1191 set_custom_link_enabled(true);
1192 } else if (tab_state_flags &
1193 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
1194 set_custom_link(l10n_util::GetStringUTF8(
1195 IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
1199 void ContentSettingMidiSysExBubbleModel::OnCustomLinkClicked() {
1200 if (!web_contents())
1201 return;
1202 // Reset this embedder's entry to default for each of the requesting
1203 // origins currently on the page.
1204 const GURL& embedder_url = web_contents()->GetURL();
1205 TabSpecificContentSettings* content_settings =
1206 TabSpecificContentSettings::FromWebContents(web_contents());
1207 const ContentSettingsUsagesState::StateMap& state_map =
1208 content_settings->midi_usages_state().state_map();
1209 HostContentSettingsMap* settings_map =
1210 profile()->GetHostContentSettingsMap();
1212 for (const std::pair<GURL, ContentSetting>& map_entry : state_map) {
1213 settings_map->SetContentSetting(
1214 ContentSettingsPattern::FromURLNoWildcard(map_entry.first),
1215 ContentSettingsPattern::FromURLNoWildcard(embedder_url),
1216 CONTENT_SETTINGS_TYPE_MIDI_SYSEX, std::string(),
1217 CONTENT_SETTING_DEFAULT);
1221 // static
1222 ContentSettingBubbleModel*
1223 ContentSettingBubbleModel::CreateContentSettingBubbleModel(
1224 Delegate* delegate,
1225 WebContents* web_contents,
1226 Profile* profile,
1227 ContentSettingsType content_type) {
1228 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES) {
1229 return new ContentSettingCookiesBubbleModel(delegate, web_contents,
1230 profile);
1232 if (content_type == CONTENT_SETTINGS_TYPE_POPUPS) {
1233 return new ContentSettingPopupBubbleModel(delegate, web_contents, profile);
1235 if (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
1236 return new ContentSettingDomainListBubbleModel(delegate, web_contents,
1237 profile, content_type);
1239 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM) {
1240 return new ContentSettingMediaStreamBubbleModel(delegate, web_contents,
1241 profile);
1243 if (content_type == CONTENT_SETTINGS_TYPE_PLUGINS) {
1244 return new ContentSettingPluginBubbleModel(delegate, web_contents, profile);
1246 if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT) {
1247 return new ContentSettingMixedScriptBubbleModel(delegate, web_contents,
1248 profile);
1250 if (content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS) {
1251 ProtocolHandlerRegistry* registry =
1252 ProtocolHandlerRegistryFactory::GetForBrowserContext(profile);
1253 return new ContentSettingRPHBubbleModel(delegate, web_contents, profile,
1254 registry);
1256 if (content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
1257 return new ContentSettingMidiSysExBubbleModel(delegate, web_contents,
1258 profile);
1260 return new ContentSettingSingleRadioGroup(delegate, web_contents, profile,
1261 content_type);
1264 ContentSettingBubbleModel::ContentSettingBubbleModel(
1265 WebContents* web_contents,
1266 Profile* profile,
1267 ContentSettingsType content_type)
1268 : web_contents_(web_contents),
1269 profile_(profile),
1270 content_type_(content_type),
1271 setting_is_managed_(false) {
1272 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
1273 content::Source<WebContents>(web_contents));
1274 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
1275 content::Source<Profile>(profile_));
1278 ContentSettingBubbleModel::~ContentSettingBubbleModel() {
1281 ContentSettingBubbleModel::RadioGroup::RadioGroup() : default_item(0) {}
1283 ContentSettingBubbleModel::RadioGroup::~RadioGroup() {}
1285 ContentSettingBubbleModel::DomainList::DomainList() {}
1287 ContentSettingBubbleModel::DomainList::~DomainList() {}
1289 ContentSettingBubbleModel::MediaMenu::MediaMenu() : disabled(false) {}
1291 ContentSettingBubbleModel::MediaMenu::~MediaMenu() {}
1293 ContentSettingBubbleModel::BubbleContent::BubbleContent()
1294 : radio_group_enabled(false),
1295 custom_link_enabled(false) {
1298 ContentSettingBubbleModel::BubbleContent::~BubbleContent() {}
1300 void ContentSettingBubbleModel::Observe(
1301 int type,
1302 const content::NotificationSource& source,
1303 const content::NotificationDetails& details) {
1304 if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) {
1305 DCHECK_EQ(web_contents_,
1306 content::Source<WebContents>(source).ptr());
1307 web_contents_ = NULL;
1308 } else {
1309 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
1310 DCHECK_EQ(profile_, content::Source<Profile>(source).ptr());
1311 profile_ = NULL;