Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / ui / content_settings / content_setting_bubble_model.cc
blobbdc7df799563be57ae400c71306f41395bd38395
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/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/common/chrome_switches.h"
25 #include "chrome/common/pref_names.h"
26 #include "chrome/common/render_messages.h"
27 #include "chrome/grit/generated_resources.h"
28 #include "components/content_settings/content/common/content_settings_messages.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 "content/public/common/origin_util.h"
39 #include "grit/components_strings.h"
40 #include "grit/theme_resources.h"
41 #include "net/base/net_util.h"
42 #include "ui/base/l10n/l10n_util.h"
43 #include "ui/base/resource/resource_bundle.h"
44 #include "ui/resources/grit/ui_resources.h"
46 using base::UserMetricsAction;
47 using content::WebContents;
48 using content_settings::SettingInfo;
49 using content_settings::SettingSource;
50 using content_settings::SETTING_SOURCE_USER;
51 using content_settings::SETTING_SOURCE_NONE;
53 namespace {
55 const int kAllowButtonIndex = 0;
57 // These states must match the order of appearance of the radio buttons
58 // in the XIB file for the Mac port.
59 enum RPHState {
60 RPH_ALLOW = 0,
61 RPH_BLOCK,
62 RPH_IGNORE,
65 struct ContentSettingsTypeIdEntry {
66 ContentSettingsType type;
67 int id;
70 int GetIdForContentType(const ContentSettingsTypeIdEntry* entries,
71 size_t num_entries,
72 ContentSettingsType type) {
73 for (size_t i = 0; i < num_entries; ++i) {
74 if (entries[i].type == type)
75 return entries[i].id;
77 return 0;
80 const content::MediaStreamDevice& GetMediaDeviceById(
81 const std::string& device_id,
82 const content::MediaStreamDevices& devices) {
83 DCHECK(!devices.empty());
84 for (const content::MediaStreamDevice& device : devices) {
85 if (device.id == device_id)
86 return device;
89 // A device with the |device_id| was not found. It is likely that the device
90 // has been unplugged from the OS. Return the first device as the default
91 // device.
92 return *devices.begin();
95 } // namespace
97 ContentSettingTitleAndLinkModel::ContentSettingTitleAndLinkModel(
98 Delegate* delegate,
99 WebContents* web_contents,
100 Profile* profile,
101 ContentSettingsType content_type)
102 : ContentSettingBubbleModel(web_contents, profile, content_type),
103 delegate_(delegate) {
104 // Notifications do not have a bubble.
105 DCHECK_NE(content_type, CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
106 SetTitle();
107 SetManageLink();
108 SetLearnMoreLink();
111 void ContentSettingTitleAndLinkModel::SetTitle() {
112 TabSpecificContentSettings* content_settings = NULL;
113 if (web_contents()) {
114 content_settings =
115 TabSpecificContentSettings::FromWebContents(web_contents());
118 static const ContentSettingsTypeIdEntry kBlockedTitleIDs[] = {
119 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_TITLE},
120 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_TITLE},
121 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_TITLE},
122 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_TITLE},
123 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_TITLE},
124 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT,
125 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT},
126 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER,
127 IDS_BLOCKED_PPAPI_BROKER_TITLE},
128 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_TITLE},
130 // Fields as for kBlockedTitleIDs, above.
131 static const ContentSettingsTypeIdEntry kAccessedTitleIDs[] = {
132 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_ACCESSED_COOKIES_TITLE},
133 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_TITLE},
134 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_TITLE},
136 const ContentSettingsTypeIdEntry *title_ids = kBlockedTitleIDs;
137 size_t num_title_ids = arraysize(kBlockedTitleIDs);
138 if (content_settings && content_settings->IsContentAllowed(content_type()) &&
139 !content_settings->IsContentBlocked(content_type())) {
140 title_ids = kAccessedTitleIDs;
141 num_title_ids = arraysize(kAccessedTitleIDs);
143 int title_id =
144 GetIdForContentType(title_ids, num_title_ids, content_type());
145 if (title_id)
146 set_title(l10n_util::GetStringUTF8(title_id));
149 void ContentSettingTitleAndLinkModel::SetManageLink() {
150 static const ContentSettingsTypeIdEntry kLinkIDs[] = {
151 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_LINK},
152 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_LINK},
153 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_LINK},
154 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LINK},
155 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_LINK},
156 {CONTENT_SETTINGS_TYPE_GEOLOCATION, IDS_GEOLOCATION_BUBBLE_MANAGE_LINK},
157 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_LEARN_MORE},
158 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, IDS_HANDLERS_BUBBLE_MANAGE_LINK},
159 {CONTENT_SETTINGS_TYPE_MEDIASTREAM, IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK},
160 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_PPAPI_BROKER_BUBBLE_MANAGE_LINK},
161 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOADS_LINK},
162 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX, IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK},
164 set_manage_link(l10n_util::GetStringUTF8(
165 GetIdForContentType(kLinkIDs, arraysize(kLinkIDs), content_type())));
168 void ContentSettingTitleAndLinkModel::OnManageLinkClicked() {
169 if (delegate_)
170 delegate_->ShowContentSettingsPage(content_type());
173 void ContentSettingTitleAndLinkModel::SetLearnMoreLink() {
174 static const ContentSettingsTypeIdEntry kLearnMoreIDs[] = {
175 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_LEARN_MORE},
177 int learn_more_id =
178 GetIdForContentType(kLearnMoreIDs, arraysize(kLearnMoreIDs),
179 content_type());
180 if (learn_more_id)
181 set_learn_more_link(l10n_util::GetStringUTF8(learn_more_id));
184 void ContentSettingTitleAndLinkModel::OnLearnMoreLinkClicked() {
185 if (delegate_)
186 delegate_->ShowLearnMorePage(content_type());
189 class ContentSettingTitleLinkAndCustomModel
190 : public ContentSettingTitleAndLinkModel {
191 public:
192 ContentSettingTitleLinkAndCustomModel(Delegate* delegate,
193 WebContents* web_contents,
194 Profile* profile,
195 ContentSettingsType content_type);
196 ~ContentSettingTitleLinkAndCustomModel() override {}
198 private:
199 void SetCustomLink();
200 void OnCustomLinkClicked() override {}
203 ContentSettingTitleLinkAndCustomModel::ContentSettingTitleLinkAndCustomModel(
204 Delegate* delegate,
205 WebContents* web_contents,
206 Profile* profile,
207 ContentSettingsType content_type)
208 : ContentSettingTitleAndLinkModel(
209 delegate, web_contents, profile, content_type) {
210 SetCustomLink();
213 void ContentSettingTitleLinkAndCustomModel::SetCustomLink() {
214 static const ContentSettingsTypeIdEntry kCustomIDs[] = {
215 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_INFO},
216 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LOAD_ALL},
217 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_ALLOW_INSECURE_CONTENT_BUTTON},
219 int custom_link_id =
220 GetIdForContentType(kCustomIDs, arraysize(kCustomIDs), content_type());
221 if (custom_link_id)
222 set_custom_link(l10n_util::GetStringUTF8(custom_link_id));
225 class ContentSettingSingleRadioGroup
226 : public ContentSettingTitleLinkAndCustomModel {
227 public:
228 ContentSettingSingleRadioGroup(Delegate* delegate,
229 WebContents* web_contents,
230 Profile* profile,
231 ContentSettingsType content_type);
232 ~ContentSettingSingleRadioGroup() override;
234 protected:
235 bool settings_changed() const;
236 int selected_item() const { return selected_item_; }
238 private:
239 void SetRadioGroup();
240 void AddException(ContentSetting setting);
241 void OnRadioClicked(int radio_index) override;
243 ContentSetting block_setting_;
244 int selected_item_;
247 ContentSettingSingleRadioGroup::ContentSettingSingleRadioGroup(
248 Delegate* delegate,
249 WebContents* web_contents,
250 Profile* profile,
251 ContentSettingsType content_type)
252 : ContentSettingTitleLinkAndCustomModel(delegate, web_contents, profile,
253 content_type),
254 block_setting_(CONTENT_SETTING_BLOCK),
255 selected_item_(0) {
256 SetRadioGroup();
259 ContentSettingSingleRadioGroup::~ContentSettingSingleRadioGroup() {
260 if (settings_changed()) {
261 ContentSetting setting =
262 selected_item_ == kAllowButtonIndex ?
263 CONTENT_SETTING_ALLOW :
264 block_setting_;
265 AddException(setting);
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 base::string16 display_host;
278 net::AppendFormattedHost(
279 url,
280 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
281 &display_host);
283 if (display_host.empty())
284 display_host = base::ASCIIToUTF16(url.spec());
286 TabSpecificContentSettings* content_settings =
287 TabSpecificContentSettings::FromWebContents(web_contents());
288 bool allowed =
289 !content_settings->IsContentBlocked(content_type());
290 DCHECK(!allowed ||
291 content_settings->IsContentAllowed(content_type()));
293 RadioGroup radio_group;
294 radio_group.url = url;
296 static const ContentSettingsTypeIdEntry kBlockedAllowIDs[] = {
297 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
298 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_UNBLOCK},
299 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_UNBLOCK},
300 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_UNBLOCK_ALL},
301 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_UNBLOCK},
302 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_UNBLOCK},
303 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_UNBLOCK},
305 // Fields as for kBlockedAllowIDs, above.
306 static const ContentSettingsTypeIdEntry kAllowedAllowIDs[] = {
307 // TODO(bauerb): The string shouldn't be "unblock" (they weren't blocked).
308 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
309 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_NO_ACTION},
310 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_NO_ACTION},
313 std::string radio_allow_label;
314 if (allowed) {
315 int resource_id = GetIdForContentType(kAllowedAllowIDs,
316 arraysize(kAllowedAllowIDs),
317 content_type());
318 radio_allow_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
319 l10n_util::GetStringFUTF8(resource_id, display_host) :
320 l10n_util::GetStringUTF8(resource_id);
321 } else {
322 radio_allow_label = l10n_util::GetStringFUTF8(
323 GetIdForContentType(kBlockedAllowIDs, arraysize(kBlockedAllowIDs),
324 content_type()),
325 display_host);
328 static const ContentSettingsTypeIdEntry kBlockedBlockIDs[] = {
329 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
330 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_NO_ACTION},
331 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_NO_ACTION},
332 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_NO_ACTION},
333 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_NO_ACTION},
334 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_NO_ACTION},
335 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_NO_ACTION},
337 static const ContentSettingsTypeIdEntry kAllowedBlockIDs[] = {
338 // TODO(bauerb): The string should say "block".
339 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
340 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_BLOCK},
341 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_BLOCK},
344 std::string radio_block_label;
345 if (allowed) {
346 int resource_id = GetIdForContentType(kAllowedBlockIDs,
347 arraysize(kAllowedBlockIDs),
348 content_type());
349 radio_block_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
350 l10n_util::GetStringUTF8(resource_id) :
351 l10n_util::GetStringFUTF8(resource_id, display_host);
352 } else {
353 radio_block_label = l10n_util::GetStringUTF8(
354 GetIdForContentType(kBlockedBlockIDs, arraysize(kBlockedBlockIDs),
355 content_type()));
358 radio_group.radio_items.push_back(radio_allow_label);
359 radio_group.radio_items.push_back(radio_block_label);
360 ContentSetting setting;
361 SettingSource setting_source = SETTING_SOURCE_NONE;
362 bool setting_is_wildcard = false;
364 if (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) {
365 CookieSettings* cookie_settings =
366 CookieSettings::Factory::GetForProfile(profile()).get();
367 setting = cookie_settings->GetCookieSetting(
368 url, url, true, &setting_source);
369 } else {
370 SettingInfo info;
371 HostContentSettingsMap* map = profile()->GetHostContentSettingsMap();
372 scoped_ptr<base::Value> value =
373 map->GetWebsiteSetting(url, url, content_type(), std::string(), &info);
374 setting = content_settings::ValueToContentSetting(value.get());
375 setting_source = info.source;
376 setting_is_wildcard =
377 info.primary_pattern == ContentSettingsPattern::Wildcard() &&
378 info.secondary_pattern == ContentSettingsPattern::Wildcard();
381 if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS &&
382 setting == CONTENT_SETTING_ALLOW &&
383 setting_is_wildcard) {
384 // In the corner case of unrecognized plugins (which are now blocked by
385 // default) we indicate the blocked state in the UI and allow the user to
386 // whitelist.
387 radio_group.default_item = 1;
388 } else if (setting == CONTENT_SETTING_ALLOW) {
389 radio_group.default_item = kAllowButtonIndex;
390 // |block_setting_| is already set to |CONTENT_SETTING_BLOCK|.
391 } else {
392 radio_group.default_item = 1;
393 block_setting_ = setting;
396 set_setting_is_managed(setting_source != SETTING_SOURCE_USER);
397 if (setting_source != SETTING_SOURCE_USER) {
398 set_radio_group_enabled(false);
399 } else {
400 set_radio_group_enabled(true);
402 selected_item_ = radio_group.default_item;
403 set_radio_group(radio_group);
406 void ContentSettingSingleRadioGroup::AddException(ContentSetting setting) {
407 if (profile()) {
408 profile()->GetHostContentSettingsMap()->AddExceptionForURL(
409 bubble_content().radio_group.url,
410 bubble_content().radio_group.url,
411 content_type(),
412 setting);
416 void ContentSettingSingleRadioGroup::OnRadioClicked(int radio_index) {
417 selected_item_ = radio_index;
420 class ContentSettingCookiesBubbleModel : public ContentSettingSingleRadioGroup {
421 public:
422 ContentSettingCookiesBubbleModel(Delegate* delegate,
423 WebContents* web_contents,
424 Profile* profile);
426 ~ContentSettingCookiesBubbleModel() override;
428 private:
429 void OnCustomLinkClicked() override;
432 ContentSettingCookiesBubbleModel::ContentSettingCookiesBubbleModel(
433 Delegate* delegate,
434 WebContents* web_contents,
435 Profile* profile)
436 : ContentSettingSingleRadioGroup(delegate,
437 web_contents,
438 profile,
439 CONTENT_SETTINGS_TYPE_COOKIES) {
440 set_custom_link_enabled(true);
443 ContentSettingCookiesBubbleModel::~ContentSettingCookiesBubbleModel() {
444 // On some plattforms e.g. MacOS X it is possible to close a tab while the
445 // cookies settings bubble is open. This resets the web contents to NULL.
446 if (settings_changed() && web_contents()) {
447 CollectedCookiesInfoBarDelegate::Create(
448 InfoBarService::FromWebContents(web_contents()));
452 void ContentSettingCookiesBubbleModel::OnCustomLinkClicked() {
453 if (!web_contents())
454 return;
455 content::NotificationService::current()->Notify(
456 chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN,
457 content::Source<TabSpecificContentSettings>(
458 TabSpecificContentSettings::FromWebContents(web_contents())),
459 content::NotificationService::NoDetails());
460 delegate()->ShowCollectedCookiesDialog(web_contents());
463 class ContentSettingPluginBubbleModel : public ContentSettingSingleRadioGroup {
464 public:
465 ContentSettingPluginBubbleModel(Delegate* delegate,
466 WebContents* web_contents,
467 Profile* profile);
469 ~ContentSettingPluginBubbleModel() override;
471 private:
472 void OnCustomLinkClicked() override;
475 ContentSettingPluginBubbleModel::ContentSettingPluginBubbleModel(
476 Delegate* delegate,
477 WebContents* web_contents,
478 Profile* profile)
479 : ContentSettingSingleRadioGroup(delegate,
480 web_contents,
481 profile,
482 CONTENT_SETTINGS_TYPE_PLUGINS) {
483 // Disable the "Run all plugins this time" link if the setting is managed and
484 // can't be controlled by the user or if the user already clicked on the link
485 // and ran all plugins.
486 set_custom_link_enabled(!setting_is_managed() &&
487 web_contents &&
488 TabSpecificContentSettings::FromWebContents(
489 web_contents)->load_plugins_link_enabled());
490 // Build blocked plugin list.
491 if (web_contents) {
492 TabSpecificContentSettings* content_settings =
493 TabSpecificContentSettings::FromWebContents(web_contents);
495 const std::vector<base::string16>& blocked_plugins =
496 content_settings->blocked_plugin_names();
497 for (const base::string16& blocked_plugin : blocked_plugins) {
498 ListItem plugin_item(
499 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
500 IDR_BLOCKED_PLUGINS),
501 base::UTF16ToUTF8(blocked_plugin), false, 0);
502 add_list_item(plugin_item);
507 ContentSettingPluginBubbleModel::~ContentSettingPluginBubbleModel() {
508 if (settings_changed()) {
509 // If the user elected to allow all plugins then run plugins at this time.
510 if (selected_item() == kAllowButtonIndex)
511 OnCustomLinkClicked();
515 void ContentSettingPluginBubbleModel::OnCustomLinkClicked() {
516 content::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble"));
517 // Web contents can be NULL if the tab was closed while the plugins
518 // settings bubble is visible.
519 if (!web_contents())
520 return;
521 #if defined(ENABLE_PLUGINS)
522 // TODO(bauerb): We should send the identifiers of blocked plugins here.
523 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
524 web_contents(), true, std::string());
525 #endif
526 set_custom_link_enabled(false);
527 TabSpecificContentSettings::FromWebContents(web_contents())->
528 set_load_plugins_link_enabled(false);
531 class ContentSettingPopupBubbleModel : public ContentSettingSingleRadioGroup {
532 public:
533 ContentSettingPopupBubbleModel(Delegate* delegate,
534 WebContents* web_contents,
535 Profile* profile);
536 ~ContentSettingPopupBubbleModel() override {}
538 private:
539 void OnListItemClicked(int index) override;
541 int32 item_id_from_item_index(int index) const {
542 return bubble_content().list_items[index].item_id;
546 ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel(
547 Delegate* delegate,
548 WebContents* web_contents,
549 Profile* profile)
550 : ContentSettingSingleRadioGroup(delegate,
551 web_contents,
552 profile,
553 CONTENT_SETTINGS_TYPE_POPUPS) {
554 if (web_contents) {
555 // Build blocked popup list.
556 std::map<int32, GURL> blocked_popups =
557 PopupBlockerTabHelper::FromWebContents(web_contents)
558 ->GetBlockedPopupRequests();
559 for (const std::pair<int32, GURL>& blocked_popup : blocked_popups) {
560 std::string title(blocked_popup.second.spec());
561 // The popup may not have a valid URL.
562 if (title.empty())
563 title = l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE);
564 ListItem popup_item(ui::ResourceBundle::GetSharedInstance().GetImageNamed(
565 IDR_DEFAULT_FAVICON),
566 title, true, blocked_popup.first);
567 add_list_item(popup_item);
572 void ContentSettingPopupBubbleModel::OnListItemClicked(int index) {
573 if (web_contents()) {
574 PopupBlockerTabHelper::FromWebContents(web_contents())
575 ->ShowBlockedPopup(item_id_from_item_index(index));
579 // The model of the content settings bubble for media settings.
580 class ContentSettingMediaStreamBubbleModel
581 : public ContentSettingTitleAndLinkModel {
582 public:
583 ContentSettingMediaStreamBubbleModel(Delegate* delegate,
584 WebContents* web_contents,
585 Profile* profile);
587 ~ContentSettingMediaStreamBubbleModel() override;
589 private:
590 void SetTitle();
591 // Sets the data for the radio buttons of the bubble.
592 void SetRadioGroup();
593 // Sets the data for the media menus of the bubble.
594 void SetMediaMenus();
595 void SetCustomLink();
596 // Updates the camera and microphone setting with the passed |setting|.
597 void UpdateSettings(ContentSetting setting);
598 // Updates the camera and microphone default device with the passed |type|
599 // and device.
600 void UpdateDefaultDeviceForType(content::MediaStreamType type,
601 const std::string& device);
603 // ContentSettingBubbleModel implementation.
604 void OnRadioClicked(int radio_index) override;
605 void OnMediaMenuClicked(content::MediaStreamType type,
606 const std::string& selected_device) override;
608 // The index of the selected radio item.
609 int selected_item_;
610 // The content settings that are associated with the individual radio
611 // buttons.
612 ContentSetting radio_item_setting_[2];
613 // The state of the microphone and camera access.
614 TabSpecificContentSettings::MicrophoneCameraState state_;
617 ContentSettingMediaStreamBubbleModel::ContentSettingMediaStreamBubbleModel(
618 Delegate* delegate,
619 WebContents* web_contents,
620 Profile* profile)
621 : ContentSettingTitleAndLinkModel(
622 delegate, web_contents, profile, CONTENT_SETTINGS_TYPE_MEDIASTREAM),
623 selected_item_(0),
624 state_(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED) {
625 DCHECK(profile);
626 // Initialize the content settings associated with the individual radio
627 // buttons.
628 radio_item_setting_[0] = CONTENT_SETTING_ASK;
629 radio_item_setting_[1] = CONTENT_SETTING_BLOCK;
631 TabSpecificContentSettings* content_settings =
632 TabSpecificContentSettings::FromWebContents(web_contents);
633 state_ = content_settings->GetMicrophoneCameraState();
634 DCHECK(state_ & (TabSpecificContentSettings::MICROPHONE_ACCESSED |
635 TabSpecificContentSettings::CAMERA_ACCESSED));
637 SetTitle();
638 SetRadioGroup();
639 SetMediaMenus();
640 SetCustomLink();
643 ContentSettingMediaStreamBubbleModel::~ContentSettingMediaStreamBubbleModel() {
644 // On some platforms (e.g. MacOS X) it is possible to close a tab while the
645 // media stream bubble is open. This resets the web contents to NULL.
646 if (!web_contents())
647 return;
649 for (const std::pair<content::MediaStreamType, MediaMenu>& media_menu :
650 bubble_content().media_menus) {
651 if (media_menu.second.selected_device.id !=
652 media_menu.second.default_device.id) {
653 UpdateDefaultDeviceForType(media_menu.first,
654 media_menu.second.selected_device.id);
658 // Update the media settings if the radio button selection was changed.
659 if (selected_item_ != bubble_content().radio_group.default_item) {
660 UpdateSettings(radio_item_setting_[selected_item_]);
664 void ContentSettingMediaStreamBubbleModel::SetTitle() {
665 DCHECK_NE(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED, state_);
666 int title_id = 0;
667 if (state_ & TabSpecificContentSettings::MICROPHONE_BLOCKED) {
668 title_id = (state_ & TabSpecificContentSettings::CAMERA_BLOCKED) ?
669 IDS_MICROPHONE_CAMERA_BLOCKED : IDS_MICROPHONE_BLOCKED;
670 } else if (state_ & TabSpecificContentSettings::CAMERA_BLOCKED) {
671 title_id = IDS_CAMERA_BLOCKED;
672 } else if (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) {
673 title_id = (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) ?
674 IDS_MICROPHONE_CAMERA_ALLOWED : IDS_MICROPHONE_ACCESSED;
675 } else if (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) {
676 title_id = IDS_CAMERA_ACCESSED;
678 set_title(l10n_util::GetStringUTF8(title_id));
681 void ContentSettingMediaStreamBubbleModel::SetRadioGroup() {
682 TabSpecificContentSettings* content_settings =
683 TabSpecificContentSettings::FromWebContents(web_contents());
684 GURL url = content_settings->media_stream_access_origin();
685 RadioGroup radio_group;
686 radio_group.url = url;
688 base::string16 display_host_utf16;
689 net::AppendFormattedHost(
690 url,
691 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
692 &display_host_utf16);
693 std::string display_host(base::UTF16ToUTF8(display_host_utf16));
694 if (display_host.empty())
695 display_host = url.spec();
697 bool is_mic = (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) != 0;
698 bool is_cam = (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) != 0;
699 DCHECK(is_mic || is_cam);
700 int radio_allow_label_id = 0;
701 int radio_block_label_id = 0;
702 if (state_ & (TabSpecificContentSettings::MICROPHONE_BLOCKED |
703 TabSpecificContentSettings::CAMERA_BLOCKED)) {
704 if (content::IsOriginSecure(url)) {
705 radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
706 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW;
707 if (is_mic)
708 radio_allow_label_id = is_cam ?
709 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ALLOW :
710 IDS_BLOCKED_MEDIASTREAM_MIC_ALLOW;
711 } else {
712 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK;
713 if (is_mic)
714 radio_allow_label_id = is_cam ?
715 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ASK :
716 IDS_BLOCKED_MEDIASTREAM_MIC_ASK;
718 radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION;
719 if (is_mic)
720 radio_block_label_id = is_cam ?
721 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION :
722 IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION;
723 } else {
724 if (is_mic && is_cam) {
725 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION;
726 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK;
727 } else if (is_mic) {
728 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION;
729 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK;
730 } else {
731 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION;
732 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK;
735 selected_item_ =
736 (is_mic && content_settings->IsContentBlocked(
737 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC)) ||
738 (is_cam && content_settings->IsContentBlocked(
739 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA)) ? 1 : 0;
741 std::string radio_allow_label = l10n_util::GetStringFUTF8(
742 radio_allow_label_id, base::UTF8ToUTF16(display_host));
743 std::string radio_block_label =
744 l10n_util::GetStringUTF8(radio_block_label_id);
746 radio_group.default_item = selected_item_;
747 radio_group.radio_items.push_back(radio_allow_label);
748 radio_group.radio_items.push_back(radio_block_label);
750 set_radio_group(radio_group);
751 set_radio_group_enabled(true);
754 void ContentSettingMediaStreamBubbleModel::UpdateSettings(
755 ContentSetting setting) {
756 if (profile()) {
757 HostContentSettingsMap* content_settings =
758 profile()->GetHostContentSettingsMap();
759 TabSpecificContentSettings* tab_content_settings =
760 TabSpecificContentSettings::FromWebContents(web_contents());
761 // The same patterns must be used as in other places (e.g. the infobar) in
762 // order to override the existing rule. Otherwise a new rule is created.
763 // TODO(markusheintz): Extract to a helper so that there is only a single
764 // place to touch.
765 ContentSettingsPattern primary_pattern =
766 ContentSettingsPattern::FromURLNoWildcard(
767 tab_content_settings->media_stream_access_origin());
768 ContentSettingsPattern secondary_pattern =
769 ContentSettingsPattern::Wildcard();
770 if (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) {
771 content_settings->SetContentSetting(
772 primary_pattern, secondary_pattern,
773 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string(), setting);
775 if (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) {
776 content_settings->SetContentSetting(
777 primary_pattern, secondary_pattern,
778 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string(), setting);
783 void ContentSettingMediaStreamBubbleModel::UpdateDefaultDeviceForType(
784 content::MediaStreamType type,
785 const std::string& device) {
786 PrefService* prefs = profile()->GetPrefs();
787 if (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
788 prefs->SetString(prefs::kDefaultAudioCaptureDevice, device);
789 } else {
790 DCHECK_EQ(content::MEDIA_DEVICE_VIDEO_CAPTURE, type);
791 prefs->SetString(prefs::kDefaultVideoCaptureDevice, device);
795 void ContentSettingMediaStreamBubbleModel::SetMediaMenus() {
796 TabSpecificContentSettings* content_settings =
797 TabSpecificContentSettings::FromWebContents(web_contents());
798 const std::string& requested_microphone =
799 content_settings->media_stream_requested_audio_device();
800 const std::string& requested_camera =
801 content_settings->media_stream_requested_video_device();
803 // Add microphone menu.
804 PrefService* prefs = profile()->GetPrefs();
805 MediaCaptureDevicesDispatcher* dispatcher =
806 MediaCaptureDevicesDispatcher::GetInstance();
807 const content::MediaStreamDevices& microphones =
808 dispatcher->GetAudioCaptureDevices();
810 if (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) {
811 MediaMenu mic_menu;
812 mic_menu.label = l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_MIC_LABEL);
813 if (!microphones.empty()) {
814 std::string preferred_mic;
815 if (requested_microphone.empty()) {
816 preferred_mic = prefs->GetString(prefs::kDefaultAudioCaptureDevice);
817 mic_menu.disabled = false;
818 } else {
819 // Set the |disabled| to true in order to disable the device selection
820 // menu on the media settings bubble. This must be done if the website
821 // manages the microphone devices itself.
822 preferred_mic = requested_microphone;
823 mic_menu.disabled = true;
826 mic_menu.default_device = GetMediaDeviceById(preferred_mic, microphones);
827 mic_menu.selected_device = mic_menu.default_device;
829 add_media_menu(content::MEDIA_DEVICE_AUDIO_CAPTURE, mic_menu);
832 if (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) {
833 const content::MediaStreamDevices& cameras =
834 dispatcher->GetVideoCaptureDevices();
835 MediaMenu camera_menu;
836 camera_menu.label =
837 l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_CAMERA_LABEL);
838 if (!cameras.empty()) {
839 std::string preferred_camera;
840 if (requested_camera.empty()) {
841 preferred_camera = prefs->GetString(prefs::kDefaultVideoCaptureDevice);
842 camera_menu.disabled = false;
843 } else {
844 // Disable the menu since the website is managing the camera devices
845 // itself.
846 preferred_camera = requested_camera;
847 camera_menu.disabled = true;
850 camera_menu.default_device =
851 GetMediaDeviceById(preferred_camera, cameras);
852 camera_menu.selected_device = camera_menu.default_device;
854 add_media_menu(content::MEDIA_DEVICE_VIDEO_CAPTURE, camera_menu);
858 void ContentSettingMediaStreamBubbleModel::SetCustomLink() {
859 TabSpecificContentSettings* content_settings =
860 TabSpecificContentSettings::FromWebContents(web_contents());
861 if (content_settings->IsMicrophoneCameraStateChanged()) {
862 set_custom_link(l10n_util::GetStringUTF8(
863 IDS_MEDIASTREAM_SETTING_CHANGED_MESSAGE));
867 void ContentSettingMediaStreamBubbleModel::OnRadioClicked(int radio_index) {
868 selected_item_ = radio_index;
871 void ContentSettingMediaStreamBubbleModel::OnMediaMenuClicked(
872 content::MediaStreamType type,
873 const std::string& selected_device_id) {
874 DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
875 type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
876 DCHECK_EQ(1U, bubble_content().media_menus.count(type));
877 MediaCaptureDevicesDispatcher* dispatcher =
878 MediaCaptureDevicesDispatcher::GetInstance();
879 const content::MediaStreamDevices& devices =
880 (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) ?
881 dispatcher->GetAudioCaptureDevices() :
882 dispatcher->GetVideoCaptureDevices();
883 set_selected_device(GetMediaDeviceById(selected_device_id, devices));
886 class ContentSettingDomainListBubbleModel
887 : public ContentSettingTitleAndLinkModel {
888 public:
889 ContentSettingDomainListBubbleModel(Delegate* delegate,
890 WebContents* web_contents,
891 Profile* profile,
892 ContentSettingsType content_type);
893 ~ContentSettingDomainListBubbleModel() override {}
895 private:
896 void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
897 void SetDomainsAndCustomLink();
898 void OnCustomLinkClicked() override;
901 ContentSettingDomainListBubbleModel::ContentSettingDomainListBubbleModel(
902 Delegate* delegate,
903 WebContents* web_contents,
904 Profile* profile,
905 ContentSettingsType content_type)
906 : ContentSettingTitleAndLinkModel(
907 delegate, web_contents, profile, content_type) {
908 DCHECK_EQ(CONTENT_SETTINGS_TYPE_GEOLOCATION, content_type) <<
909 "SetDomains currently only supports geolocation content type";
910 SetDomainsAndCustomLink();
913 void ContentSettingDomainListBubbleModel::MaybeAddDomainList(
914 const std::set<std::string>& hosts, int title_id) {
915 if (!hosts.empty()) {
916 DomainList domain_list;
917 domain_list.title = l10n_util::GetStringUTF8(title_id);
918 domain_list.hosts = hosts;
919 add_domain_list(domain_list);
923 void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() {
924 TabSpecificContentSettings* content_settings =
925 TabSpecificContentSettings::FromWebContents(web_contents());
926 const ContentSettingsUsagesState& usages =
927 content_settings->geolocation_usages_state();
928 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
929 unsigned int tab_state_flags = 0;
930 usages.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
931 // Divide the tab's current geolocation users into sets according to their
932 // permission state.
933 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
934 IDS_GEOLOCATION_BUBBLE_SECTION_ALLOWED);
936 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
937 IDS_GEOLOCATION_BUBBLE_SECTION_DENIED);
939 if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
940 set_custom_link(l10n_util::GetStringUTF8(
941 IDS_GEOLOCATION_BUBBLE_CLEAR_LINK));
942 set_custom_link_enabled(true);
943 } else if (tab_state_flags &
944 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
945 set_custom_link(l10n_util::GetStringUTF8(
946 IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
950 void ContentSettingDomainListBubbleModel::OnCustomLinkClicked() {
951 if (!web_contents())
952 return;
953 // Reset this embedder's entry to default for each of the requesting
954 // origins currently on the page.
955 const GURL& embedder_url = web_contents()->GetURL();
956 TabSpecificContentSettings* content_settings =
957 TabSpecificContentSettings::FromWebContents(web_contents());
958 const ContentSettingsUsagesState::StateMap& state_map =
959 content_settings->geolocation_usages_state().state_map();
960 HostContentSettingsMap* settings_map =
961 profile()->GetHostContentSettingsMap();
963 for (const std::pair<GURL, ContentSetting>& map_entry : state_map) {
964 settings_map->SetContentSetting(
965 ContentSettingsPattern::FromURLNoWildcard(map_entry.first),
966 ContentSettingsPattern::FromURLNoWildcard(embedder_url),
967 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string(),
968 CONTENT_SETTING_DEFAULT);
972 class ContentSettingMixedScriptBubbleModel
973 : public ContentSettingTitleLinkAndCustomModel {
974 public:
975 ContentSettingMixedScriptBubbleModel(Delegate* delegate,
976 WebContents* web_contents,
977 Profile* profile);
979 ~ContentSettingMixedScriptBubbleModel() override {}
981 private:
982 void OnCustomLinkClicked() override;
985 ContentSettingMixedScriptBubbleModel::ContentSettingMixedScriptBubbleModel(
986 Delegate* delegate,
987 WebContents* web_contents,
988 Profile* profile)
989 : ContentSettingTitleLinkAndCustomModel(delegate,
990 web_contents,
991 profile,
992 CONTENT_SETTINGS_TYPE_MIXEDSCRIPT) {
993 content_settings::RecordMixedScriptAction(
994 content_settings::MIXED_SCRIPT_ACTION_DISPLAYED_BUBBLE);
995 set_custom_link_enabled(true);
998 void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
999 content_settings::RecordMixedScriptAction(
1000 content_settings::MIXED_SCRIPT_ACTION_CLICKED_ALLOW);
1001 DCHECK(web_contents());
1002 web_contents()->SendToAllFrames(
1003 new ChromeViewMsg_SetAllowRunningInsecureContent(MSG_ROUTING_NONE, true));
1004 web_contents()->GetMainFrame()->Send(new ChromeViewMsg_ReloadFrame(
1005 web_contents()->GetMainFrame()->GetRoutingID()));
1008 ContentSettingRPHBubbleModel::ContentSettingRPHBubbleModel(
1009 Delegate* delegate,
1010 WebContents* web_contents,
1011 Profile* profile,
1012 ProtocolHandlerRegistry* registry)
1013 : ContentSettingTitleAndLinkModel(delegate,
1014 web_contents,
1015 profile,
1016 CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS),
1017 selected_item_(0),
1018 registry_(registry),
1019 pending_handler_(ProtocolHandler::EmptyProtocolHandler()),
1020 previous_handler_(ProtocolHandler::EmptyProtocolHandler()) {
1021 TabSpecificContentSettings* content_settings =
1022 TabSpecificContentSettings::FromWebContents(web_contents);
1023 pending_handler_ = content_settings->pending_protocol_handler();
1024 previous_handler_ = content_settings->previous_protocol_handler();
1026 base::string16 protocol;
1027 if (pending_handler_.protocol() == "mailto") {
1028 protocol = l10n_util::GetStringUTF16(
1029 IDS_REGISTER_PROTOCOL_HANDLER_MAILTO_NAME);
1030 } else if (pending_handler_.protocol() == "webcal") {
1031 protocol = l10n_util::GetStringUTF16(
1032 IDS_REGISTER_PROTOCOL_HANDLER_WEBCAL_NAME);
1033 } else {
1034 protocol = base::UTF8ToUTF16(pending_handler_.protocol());
1037 // Note that we ignore the |title| parameter.
1038 if (previous_handler_.IsEmpty()) {
1039 set_title(l10n_util::GetStringFUTF8(
1040 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM,
1041 base::UTF8ToUTF16(pending_handler_.url().host()),
1042 protocol));
1043 } else {
1044 set_title(l10n_util::GetStringFUTF8(
1045 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM_REPLACE,
1046 base::UTF8ToUTF16(pending_handler_.url().host()),
1047 protocol,
1048 base::UTF8ToUTF16(previous_handler_.url().host())));
1051 std::string radio_allow_label =
1052 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_ACCEPT);
1053 std::string radio_deny_label =
1054 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_DENY);
1055 std::string radio_ignore_label =
1056 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_IGNORE);
1058 GURL url = web_contents->GetURL();
1059 RadioGroup radio_group;
1060 radio_group.url = url;
1062 radio_group.radio_items.push_back(radio_allow_label);
1063 radio_group.radio_items.push_back(radio_deny_label);
1064 radio_group.radio_items.push_back(radio_ignore_label);
1065 ContentSetting setting =
1066 content_settings->pending_protocol_handler_setting();
1067 if (setting == CONTENT_SETTING_ALLOW)
1068 radio_group.default_item = RPH_ALLOW;
1069 else if (setting == CONTENT_SETTING_BLOCK)
1070 radio_group.default_item = RPH_BLOCK;
1071 else
1072 radio_group.default_item = RPH_IGNORE;
1074 selected_item_ = radio_group.default_item;
1075 set_radio_group_enabled(true);
1076 set_radio_group(radio_group);
1079 void ContentSettingRPHBubbleModel::OnRadioClicked(int radio_index) {
1080 if (selected_item_ == radio_index)
1081 return;
1083 selected_item_ = radio_index;
1085 if (radio_index == RPH_ALLOW)
1086 RegisterProtocolHandler();
1087 else if (radio_index == RPH_BLOCK)
1088 UnregisterProtocolHandler();
1089 else if (radio_index == RPH_IGNORE)
1090 IgnoreProtocolHandler();
1091 else
1092 NOTREACHED();
1095 void ContentSettingRPHBubbleModel::OnDoneClicked() {
1096 // The user has one chance to deal with the RPH content setting UI,
1097 // then we remove it.
1098 TabSpecificContentSettings::FromWebContents(web_contents())->
1099 ClearPendingProtocolHandler();
1100 content::NotificationService::current()->Notify(
1101 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
1102 content::Source<WebContents>(web_contents()),
1103 content::NotificationService::NoDetails());
1106 void ContentSettingRPHBubbleModel::RegisterProtocolHandler() {
1107 // A no-op if the handler hasn't been ignored, but needed in case the user
1108 // selects sequences like register/ignore/register.
1109 registry_->RemoveIgnoredHandler(pending_handler_);
1111 registry_->OnAcceptRegisterProtocolHandler(pending_handler_);
1112 TabSpecificContentSettings::FromWebContents(web_contents())->
1113 set_pending_protocol_handler_setting(CONTENT_SETTING_ALLOW);
1116 void ContentSettingRPHBubbleModel::UnregisterProtocolHandler() {
1117 registry_->OnDenyRegisterProtocolHandler(pending_handler_);
1118 TabSpecificContentSettings::FromWebContents(web_contents())->
1119 set_pending_protocol_handler_setting(CONTENT_SETTING_BLOCK);
1120 ClearOrSetPreviousHandler();
1123 void ContentSettingRPHBubbleModel::IgnoreProtocolHandler() {
1124 registry_->OnIgnoreRegisterProtocolHandler(pending_handler_);
1125 TabSpecificContentSettings::FromWebContents(web_contents())->
1126 set_pending_protocol_handler_setting(CONTENT_SETTING_DEFAULT);
1127 ClearOrSetPreviousHandler();
1130 void ContentSettingRPHBubbleModel::ClearOrSetPreviousHandler() {
1131 if (previous_handler_.IsEmpty()) {
1132 registry_->ClearDefault(pending_handler_.protocol());
1133 } else {
1134 registry_->OnAcceptRegisterProtocolHandler(previous_handler_);
1138 class ContentSettingMidiSysExBubbleModel
1139 : public ContentSettingTitleAndLinkModel {
1140 public:
1141 ContentSettingMidiSysExBubbleModel(Delegate* delegate,
1142 WebContents* web_contents,
1143 Profile* profile);
1144 ~ContentSettingMidiSysExBubbleModel() override {}
1146 private:
1147 void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
1148 void SetDomainsAndCustomLink();
1149 void OnCustomLinkClicked() override;
1152 ContentSettingMidiSysExBubbleModel::ContentSettingMidiSysExBubbleModel(
1153 Delegate* delegate,
1154 WebContents* web_contents,
1155 Profile* profile)
1156 : ContentSettingTitleAndLinkModel(delegate,
1157 web_contents,
1158 profile,
1159 CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
1160 SetDomainsAndCustomLink();
1163 void ContentSettingMidiSysExBubbleModel::MaybeAddDomainList(
1164 const std::set<std::string>& hosts, int title_id) {
1165 if (!hosts.empty()) {
1166 DomainList domain_list;
1167 domain_list.title = l10n_util::GetStringUTF8(title_id);
1168 domain_list.hosts = hosts;
1169 add_domain_list(domain_list);
1173 void ContentSettingMidiSysExBubbleModel::SetDomainsAndCustomLink() {
1174 TabSpecificContentSettings* content_settings =
1175 TabSpecificContentSettings::FromWebContents(web_contents());
1176 const ContentSettingsUsagesState& usages_state =
1177 content_settings->midi_usages_state();
1178 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
1179 unsigned int tab_state_flags = 0;
1180 usages_state.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
1181 // Divide the tab's current MIDI sysex users into sets according to their
1182 // permission state.
1183 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
1184 IDS_MIDI_SYSEX_BUBBLE_ALLOWED);
1186 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
1187 IDS_MIDI_SYSEX_BUBBLE_DENIED);
1189 if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
1190 set_custom_link(l10n_util::GetStringUTF8(
1191 IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK));
1192 set_custom_link_enabled(true);
1193 } else if (tab_state_flags &
1194 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
1195 set_custom_link(l10n_util::GetStringUTF8(
1196 IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
1200 void ContentSettingMidiSysExBubbleModel::OnCustomLinkClicked() {
1201 if (!web_contents())
1202 return;
1203 // Reset this embedder's entry to default for each of the requesting
1204 // origins currently on the page.
1205 const GURL& embedder_url = web_contents()->GetURL();
1206 TabSpecificContentSettings* content_settings =
1207 TabSpecificContentSettings::FromWebContents(web_contents());
1208 const ContentSettingsUsagesState::StateMap& state_map =
1209 content_settings->midi_usages_state().state_map();
1210 HostContentSettingsMap* settings_map =
1211 profile()->GetHostContentSettingsMap();
1213 for (const std::pair<GURL, ContentSetting>& map_entry : state_map) {
1214 settings_map->SetContentSetting(
1215 ContentSettingsPattern::FromURLNoWildcard(map_entry.first),
1216 ContentSettingsPattern::FromURLNoWildcard(embedder_url),
1217 CONTENT_SETTINGS_TYPE_MIDI_SYSEX, std::string(),
1218 CONTENT_SETTING_DEFAULT);
1222 // static
1223 ContentSettingBubbleModel*
1224 ContentSettingBubbleModel::CreateContentSettingBubbleModel(
1225 Delegate* delegate,
1226 WebContents* web_contents,
1227 Profile* profile,
1228 ContentSettingsType content_type) {
1229 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES) {
1230 return new ContentSettingCookiesBubbleModel(delegate, web_contents,
1231 profile);
1233 if (content_type == CONTENT_SETTINGS_TYPE_POPUPS) {
1234 return new ContentSettingPopupBubbleModel(delegate, web_contents, profile);
1236 if (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
1237 return new ContentSettingDomainListBubbleModel(delegate, web_contents,
1238 profile, content_type);
1240 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM) {
1241 return new ContentSettingMediaStreamBubbleModel(delegate, web_contents,
1242 profile);
1244 if (content_type == CONTENT_SETTINGS_TYPE_PLUGINS) {
1245 return new ContentSettingPluginBubbleModel(delegate, web_contents, profile);
1247 if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT) {
1248 return new ContentSettingMixedScriptBubbleModel(delegate, web_contents,
1249 profile);
1251 if (content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS) {
1252 ProtocolHandlerRegistry* registry =
1253 ProtocolHandlerRegistryFactory::GetForBrowserContext(profile);
1254 return new ContentSettingRPHBubbleModel(delegate, web_contents, profile,
1255 registry);
1257 if (content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
1258 return new ContentSettingMidiSysExBubbleModel(delegate, web_contents,
1259 profile);
1261 return new ContentSettingSingleRadioGroup(delegate, web_contents, profile,
1262 content_type);
1265 ContentSettingBubbleModel::ContentSettingBubbleModel(
1266 WebContents* web_contents,
1267 Profile* profile,
1268 ContentSettingsType content_type)
1269 : web_contents_(web_contents),
1270 profile_(profile),
1271 content_type_(content_type),
1272 setting_is_managed_(false) {
1273 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
1274 content::Source<WebContents>(web_contents));
1275 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
1276 content::Source<Profile>(profile_));
1279 ContentSettingBubbleModel::~ContentSettingBubbleModel() {
1282 ContentSettingBubbleModel::RadioGroup::RadioGroup() : default_item(0) {}
1284 ContentSettingBubbleModel::RadioGroup::~RadioGroup() {}
1286 ContentSettingBubbleModel::DomainList::DomainList() {}
1288 ContentSettingBubbleModel::DomainList::~DomainList() {}
1290 ContentSettingBubbleModel::MediaMenu::MediaMenu() : disabled(false) {}
1292 ContentSettingBubbleModel::MediaMenu::~MediaMenu() {}
1294 ContentSettingBubbleModel::BubbleContent::BubbleContent()
1295 : radio_group_enabled(false),
1296 custom_link_enabled(false) {
1299 ContentSettingBubbleModel::BubbleContent::~BubbleContent() {}
1301 void ContentSettingBubbleModel::Observe(
1302 int type,
1303 const content::NotificationSource& source,
1304 const content::NotificationDetails& details) {
1305 if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) {
1306 DCHECK_EQ(web_contents_,
1307 content::Source<WebContents>(source).ptr());
1308 web_contents_ = NULL;
1309 } else {
1310 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
1311 DCHECK_EQ(profile_, content::Source<Profile>(source).ptr());
1312 profile_ = NULL;