ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chrome / browser / ui / content_settings / content_setting_bubble_model.cc
blob23c1275dc23e89a735e617ad393253c835bc37dd
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 "net/base/net_util.h"
40 #include "ui/base/l10n/l10n_util.h"
41 #include "ui/base/resource/resource_bundle.h"
42 #include "ui/resources/grit/ui_resources.h"
44 using base::UserMetricsAction;
45 using content::WebContents;
46 using content_settings::SettingInfo;
47 using content_settings::SettingSource;
48 using content_settings::SETTING_SOURCE_USER;
49 using content_settings::SETTING_SOURCE_NONE;
51 namespace {
53 const int kAllowButtonIndex = 0;
55 // These states must match the order of appearance of the radio buttons
56 // in the XIB file for the Mac port.
57 enum RPHState {
58 RPH_ALLOW = 0,
59 RPH_BLOCK,
60 RPH_IGNORE,
63 struct ContentSettingsTypeIdEntry {
64 ContentSettingsType type;
65 int id;
68 int GetIdForContentType(const ContentSettingsTypeIdEntry* entries,
69 size_t num_entries,
70 ContentSettingsType type) {
71 for (size_t i = 0; i < num_entries; ++i) {
72 if (entries[i].type == type)
73 return entries[i].id;
75 return 0;
78 const content::MediaStreamDevice& GetMediaDeviceById(
79 const std::string& device_id,
80 const content::MediaStreamDevices& devices) {
81 DCHECK(!devices.empty());
82 for (content::MediaStreamDevices::const_iterator it = devices.begin();
83 it != devices.end(); ++it) {
84 if (it->id == device_id)
85 return *(it);
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 if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS && content_settings &&
118 content_settings->IsContentBlocked(content_type())) {
119 set_plugin_names(content_settings->GetBlockedPluginNames());
122 static const ContentSettingsTypeIdEntry kBlockedTitleIDs[] = {
123 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_TITLE},
124 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_TITLE},
125 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_TITLE},
126 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_TITLE},
127 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_TITLE},
128 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT,
129 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT},
130 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER,
131 IDS_BLOCKED_PPAPI_BROKER_TITLE},
132 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_TITLE},
134 // Fields as for kBlockedTitleIDs, above.
135 static const ContentSettingsTypeIdEntry kAccessedTitleIDs[] = {
136 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_ACCESSED_COOKIES_TITLE},
137 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_TITLE},
138 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_TITLE},
140 const ContentSettingsTypeIdEntry *title_ids = kBlockedTitleIDs;
141 size_t num_title_ids = arraysize(kBlockedTitleIDs);
142 if (content_settings && content_settings->IsContentAllowed(content_type()) &&
143 !content_settings->IsContentBlocked(content_type())) {
144 title_ids = kAccessedTitleIDs;
145 num_title_ids = arraysize(kAccessedTitleIDs);
147 int title_id =
148 GetIdForContentType(title_ids, num_title_ids, content_type());
149 if (title_id)
150 set_title(l10n_util::GetStringUTF8(title_id));
153 void ContentSettingTitleAndLinkModel::SetManageLink() {
154 static const ContentSettingsTypeIdEntry kLinkIDs[] = {
155 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_LINK},
156 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_LINK},
157 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_LINK},
158 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LINK},
159 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_LINK},
160 {CONTENT_SETTINGS_TYPE_GEOLOCATION, IDS_GEOLOCATION_BUBBLE_MANAGE_LINK},
161 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_LEARN_MORE},
162 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, IDS_HANDLERS_BUBBLE_MANAGE_LINK},
163 {CONTENT_SETTINGS_TYPE_MEDIASTREAM, IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK},
164 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_PPAPI_BROKER_BUBBLE_MANAGE_LINK},
165 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOADS_LINK},
166 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX, IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK},
168 set_manage_link(l10n_util::GetStringUTF8(
169 GetIdForContentType(kLinkIDs, arraysize(kLinkIDs), content_type())));
172 void ContentSettingTitleAndLinkModel::OnManageLinkClicked() {
173 if (delegate_)
174 delegate_->ShowContentSettingsPage(content_type());
177 void ContentSettingTitleAndLinkModel::SetLearnMoreLink() {
178 static const ContentSettingsTypeIdEntry kLearnMoreIDs[] = {
179 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_LEARN_MORE},
181 int learn_more_id =
182 GetIdForContentType(kLearnMoreIDs, arraysize(kLearnMoreIDs),
183 content_type());
184 if (learn_more_id)
185 set_learn_more_link(l10n_util::GetStringUTF8(learn_more_id));
188 void ContentSettingTitleAndLinkModel::OnLearnMoreLinkClicked() {
189 if (delegate_)
190 delegate_->ShowLearnMorePage(content_type());
193 class ContentSettingTitleLinkAndCustomModel
194 : public ContentSettingTitleAndLinkModel {
195 public:
196 ContentSettingTitleLinkAndCustomModel(Delegate* delegate,
197 WebContents* web_contents,
198 Profile* profile,
199 ContentSettingsType content_type);
200 ~ContentSettingTitleLinkAndCustomModel() override {}
202 private:
203 void SetCustomLink();
204 void OnCustomLinkClicked() override {}
207 ContentSettingTitleLinkAndCustomModel::ContentSettingTitleLinkAndCustomModel(
208 Delegate* delegate,
209 WebContents* web_contents,
210 Profile* profile,
211 ContentSettingsType content_type)
212 : ContentSettingTitleAndLinkModel(
213 delegate, web_contents, profile, content_type) {
214 SetCustomLink();
217 void ContentSettingTitleLinkAndCustomModel::SetCustomLink() {
218 static const ContentSettingsTypeIdEntry kCustomIDs[] = {
219 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_INFO},
220 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LOAD_ALL},
221 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_ALLOW_INSECURE_CONTENT_BUTTON},
223 int custom_link_id =
224 GetIdForContentType(kCustomIDs, arraysize(kCustomIDs), content_type());
225 if (custom_link_id)
226 set_custom_link(l10n_util::GetStringUTF8(custom_link_id));
229 class ContentSettingSingleRadioGroup
230 : public ContentSettingTitleLinkAndCustomModel {
231 public:
232 ContentSettingSingleRadioGroup(Delegate* delegate,
233 WebContents* web_contents,
234 Profile* profile,
235 ContentSettingsType content_type);
236 ~ContentSettingSingleRadioGroup() override;
238 protected:
239 bool settings_changed() const;
240 int selected_item() const { return selected_item_; }
242 private:
243 void SetRadioGroup();
244 void AddException(ContentSetting setting);
245 void OnRadioClicked(int radio_index) override;
247 ContentSetting block_setting_;
248 int selected_item_;
251 ContentSettingSingleRadioGroup::ContentSettingSingleRadioGroup(
252 Delegate* delegate,
253 WebContents* web_contents,
254 Profile* profile,
255 ContentSettingsType content_type)
256 : ContentSettingTitleLinkAndCustomModel(delegate, web_contents, profile,
257 content_type),
258 block_setting_(CONTENT_SETTING_BLOCK),
259 selected_item_(0) {
260 SetRadioGroup();
263 ContentSettingSingleRadioGroup::~ContentSettingSingleRadioGroup() {
264 if (settings_changed()) {
265 ContentSetting setting =
266 selected_item_ == kAllowButtonIndex ?
267 CONTENT_SETTING_ALLOW :
268 block_setting_;
269 AddException(setting);
273 bool ContentSettingSingleRadioGroup::settings_changed() const {
274 return selected_item_ != bubble_content().radio_group.default_item;
277 // Initialize the radio group by setting the appropriate labels for the
278 // content type and setting the default value based on the content setting.
279 void ContentSettingSingleRadioGroup::SetRadioGroup() {
280 GURL url = web_contents()->GetURL();
281 base::string16 display_host;
282 net::AppendFormattedHost(
283 url,
284 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
285 &display_host);
287 if (display_host.empty())
288 display_host = base::ASCIIToUTF16(url.spec());
290 TabSpecificContentSettings* content_settings =
291 TabSpecificContentSettings::FromWebContents(web_contents());
292 bool allowed =
293 !content_settings->IsContentBlocked(content_type());
294 DCHECK(!allowed ||
295 content_settings->IsContentAllowed(content_type()));
297 RadioGroup radio_group;
298 radio_group.url = url;
300 static const ContentSettingsTypeIdEntry kBlockedAllowIDs[] = {
301 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
302 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_UNBLOCK},
303 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_UNBLOCK},
304 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_UNBLOCK_ALL},
305 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_UNBLOCK},
306 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_UNBLOCK},
307 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_UNBLOCK},
309 // Fields as for kBlockedAllowIDs, above.
310 static const ContentSettingsTypeIdEntry kAllowedAllowIDs[] = {
311 // TODO(bauerb): The string shouldn't be "unblock" (they weren't blocked).
312 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
313 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_NO_ACTION},
314 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_NO_ACTION},
317 std::string radio_allow_label;
318 if (allowed) {
319 int resource_id = GetIdForContentType(kAllowedAllowIDs,
320 arraysize(kAllowedAllowIDs),
321 content_type());
322 radio_allow_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
323 l10n_util::GetStringFUTF8(resource_id, display_host) :
324 l10n_util::GetStringUTF8(resource_id);
325 } else {
326 radio_allow_label = l10n_util::GetStringFUTF8(
327 GetIdForContentType(kBlockedAllowIDs, arraysize(kBlockedAllowIDs),
328 content_type()),
329 display_host);
332 static const ContentSettingsTypeIdEntry kBlockedBlockIDs[] = {
333 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
334 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_NO_ACTION},
335 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_NO_ACTION},
336 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_NO_ACTION},
337 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_NO_ACTION},
338 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_NO_ACTION},
339 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_NO_ACTION},
341 static const ContentSettingsTypeIdEntry kAllowedBlockIDs[] = {
342 // TODO(bauerb): The string should say "block".
343 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
344 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_BLOCK},
345 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_BLOCK},
348 std::string radio_block_label;
349 if (allowed) {
350 int resource_id = GetIdForContentType(kAllowedBlockIDs,
351 arraysize(kAllowedBlockIDs),
352 content_type());
353 radio_block_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
354 l10n_util::GetStringUTF8(resource_id) :
355 l10n_util::GetStringFUTF8(resource_id, display_host);
356 } else {
357 radio_block_label = l10n_util::GetStringUTF8(
358 GetIdForContentType(kBlockedBlockIDs, arraysize(kBlockedBlockIDs),
359 content_type()));
362 radio_group.radio_items.push_back(radio_allow_label);
363 radio_group.radio_items.push_back(radio_block_label);
364 ContentSetting setting;
365 SettingSource setting_source = SETTING_SOURCE_NONE;
366 bool setting_is_wildcard = false;
368 if (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) {
369 CookieSettings* cookie_settings =
370 CookieSettings::Factory::GetForProfile(profile()).get();
371 setting = cookie_settings->GetCookieSetting(
372 url, url, true, &setting_source);
373 } else {
374 SettingInfo info;
375 HostContentSettingsMap* map = profile()->GetHostContentSettingsMap();
376 scoped_ptr<base::Value> value =
377 map->GetWebsiteSetting(url, url, content_type(), std::string(), &info);
378 setting = content_settings::ValueToContentSetting(value.get());
379 setting_source = info.source;
380 setting_is_wildcard =
381 info.primary_pattern == ContentSettingsPattern::Wildcard() &&
382 info.secondary_pattern == ContentSettingsPattern::Wildcard();
385 if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS &&
386 setting == CONTENT_SETTING_ALLOW &&
387 setting_is_wildcard) {
388 // In the corner case of unrecognized plugins (which are now blocked by
389 // default) we indicate the blocked state in the UI and allow the user to
390 // whitelist.
391 radio_group.default_item = 1;
392 } else if (setting == CONTENT_SETTING_ALLOW) {
393 radio_group.default_item = kAllowButtonIndex;
394 // |block_setting_| is already set to |CONTENT_SETTING_BLOCK|.
395 } else {
396 radio_group.default_item = 1;
397 block_setting_ = setting;
400 set_setting_is_managed(setting_source != SETTING_SOURCE_USER);
401 if (setting_source != SETTING_SOURCE_USER) {
402 set_radio_group_enabled(false);
403 } else {
404 set_radio_group_enabled(true);
406 selected_item_ = radio_group.default_item;
407 set_radio_group(radio_group);
410 void ContentSettingSingleRadioGroup::AddException(ContentSetting setting) {
411 if (profile()) {
412 profile()->GetHostContentSettingsMap()->AddExceptionForURL(
413 bubble_content().radio_group.url,
414 bubble_content().radio_group.url,
415 content_type(),
416 setting);
420 void ContentSettingSingleRadioGroup::OnRadioClicked(int radio_index) {
421 selected_item_ = radio_index;
424 class ContentSettingCookiesBubbleModel : public ContentSettingSingleRadioGroup {
425 public:
426 ContentSettingCookiesBubbleModel(Delegate* delegate,
427 WebContents* web_contents,
428 Profile* profile,
429 ContentSettingsType content_type);
431 ~ContentSettingCookiesBubbleModel() override;
433 private:
434 void OnCustomLinkClicked() override;
437 ContentSettingCookiesBubbleModel::ContentSettingCookiesBubbleModel(
438 Delegate* delegate,
439 WebContents* web_contents,
440 Profile* profile,
441 ContentSettingsType content_type)
442 : ContentSettingSingleRadioGroup(
443 delegate, web_contents, profile, content_type) {
444 DCHECK_EQ(CONTENT_SETTINGS_TYPE_COOKIES, content_type);
445 set_custom_link_enabled(true);
448 ContentSettingCookiesBubbleModel::~ContentSettingCookiesBubbleModel() {
449 // On some plattforms e.g. MacOS X it is possible to close a tab while the
450 // cookies settings bubble is open. This resets the web contents to NULL.
451 if (settings_changed() && web_contents()) {
452 CollectedCookiesInfoBarDelegate::Create(
453 InfoBarService::FromWebContents(web_contents()));
457 void ContentSettingCookiesBubbleModel::OnCustomLinkClicked() {
458 if (!web_contents())
459 return;
460 content::NotificationService::current()->Notify(
461 chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN,
462 content::Source<TabSpecificContentSettings>(
463 TabSpecificContentSettings::FromWebContents(web_contents())),
464 content::NotificationService::NoDetails());
465 delegate()->ShowCollectedCookiesDialog(web_contents());
468 class ContentSettingPluginBubbleModel : public ContentSettingSingleRadioGroup {
469 public:
470 ContentSettingPluginBubbleModel(Delegate* delegate,
471 WebContents* web_contents,
472 Profile* profile,
473 ContentSettingsType content_type);
475 ~ContentSettingPluginBubbleModel() override;
477 private:
478 void OnCustomLinkClicked() override;
481 ContentSettingPluginBubbleModel::ContentSettingPluginBubbleModel(
482 Delegate* delegate,
483 WebContents* web_contents,
484 Profile* profile,
485 ContentSettingsType content_type)
486 : ContentSettingSingleRadioGroup(
487 delegate, web_contents, profile, content_type) {
488 DCHECK_EQ(content_type, CONTENT_SETTINGS_TYPE_PLUGINS);
489 // Disable the "Run all plugins this time" link if the setting is managed and
490 // can't be controlled by the user or if the user already clicked on the link
491 // and ran all plugins.
492 set_custom_link_enabled(!setting_is_managed() &&
493 web_contents &&
494 TabSpecificContentSettings::FromWebContents(
495 web_contents)->load_plugins_link_enabled());
498 ContentSettingPluginBubbleModel::~ContentSettingPluginBubbleModel() {
499 if (settings_changed()) {
500 // If the user elected to allow all plugins then run plugins at this time.
501 if (selected_item() == kAllowButtonIndex)
502 OnCustomLinkClicked();
506 void ContentSettingPluginBubbleModel::OnCustomLinkClicked() {
507 content::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble"));
508 // Web contents can be NULL if the tab was closed while the plugins
509 // settings bubble is visible.
510 if (!web_contents())
511 return;
512 #if defined(ENABLE_PLUGINS)
513 // TODO(bauerb): We should send the identifiers of blocked plug-ins here.
514 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
515 web_contents(), true, std::string());
516 #endif
517 set_custom_link_enabled(false);
518 TabSpecificContentSettings::FromWebContents(web_contents())->
519 set_load_plugins_link_enabled(false);
522 class ContentSettingPopupBubbleModel : public ContentSettingSingleRadioGroup {
523 public:
524 ContentSettingPopupBubbleModel(Delegate* delegate,
525 WebContents* web_contents,
526 Profile* profile,
527 ContentSettingsType content_type);
528 ~ContentSettingPopupBubbleModel() override {}
530 private:
531 void SetPopups();
532 void OnPopupClicked(int index) override;
535 ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel(
536 Delegate* delegate,
537 WebContents* web_contents,
538 Profile* profile,
539 ContentSettingsType content_type)
540 : ContentSettingSingleRadioGroup(
541 delegate, web_contents, profile, content_type) {
542 SetPopups();
546 void ContentSettingPopupBubbleModel::SetPopups() {
547 std::map<int32, GURL> blocked_popups =
548 PopupBlockerTabHelper::FromWebContents(web_contents())
549 ->GetBlockedPopupRequests();
550 for (std::map<int32, GURL>::const_iterator iter = blocked_popups.begin();
551 iter != blocked_popups.end();
552 ++iter) {
553 std::string title(iter->second.spec());
554 // The popup may not have a valid URL.
555 if (title.empty())
556 title = l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE);
557 PopupItem popup_item(
558 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
559 IDR_DEFAULT_FAVICON),
560 title,
561 iter->first);
562 add_popup(popup_item);
566 void ContentSettingPopupBubbleModel::OnPopupClicked(int index) {
567 if (web_contents()) {
568 PopupBlockerTabHelper::FromWebContents(web_contents())->
569 ShowBlockedPopup(bubble_content().popup_items[index].popup_id);
573 // The model of the content settings bubble for media settings.
574 class ContentSettingMediaStreamBubbleModel
575 : public ContentSettingTitleAndLinkModel {
576 public:
577 ContentSettingMediaStreamBubbleModel(Delegate* delegate,
578 WebContents* web_contents,
579 Profile* profile);
581 ~ContentSettingMediaStreamBubbleModel() override;
583 private:
584 void SetTitle();
585 // Sets the data for the radio buttons of the bubble.
586 void SetRadioGroup();
587 // Sets the data for the media menus of the bubble.
588 void SetMediaMenus();
589 void SetCustomLink();
590 // Updates the camera and microphone setting with the passed |setting|.
591 void UpdateSettings(ContentSetting setting);
592 // Updates the camera and microphone default device with the passed |type|
593 // and device.
594 void UpdateDefaultDeviceForType(content::MediaStreamType type,
595 const std::string& device);
597 // ContentSettingBubbleModel implementation.
598 void OnRadioClicked(int radio_index) override;
599 void OnMediaMenuClicked(content::MediaStreamType type,
600 const std::string& selected_device) override;
602 // The index of the selected radio item.
603 int selected_item_;
604 // The content settings that are associated with the individual radio
605 // buttons.
606 ContentSetting radio_item_setting_[2];
607 // The state of the microphone and camera access.
608 TabSpecificContentSettings::MicrophoneCameraState state_;
611 ContentSettingMediaStreamBubbleModel::ContentSettingMediaStreamBubbleModel(
612 Delegate* delegate,
613 WebContents* web_contents,
614 Profile* profile)
615 : ContentSettingTitleAndLinkModel(
616 delegate, web_contents, profile, CONTENT_SETTINGS_TYPE_MEDIASTREAM),
617 selected_item_(0),
618 state_(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED) {
619 DCHECK(profile);
620 // Initialize the content settings associated with the individual radio
621 // buttons.
622 radio_item_setting_[0] = CONTENT_SETTING_ASK;
623 radio_item_setting_[1] = CONTENT_SETTING_BLOCK;
625 TabSpecificContentSettings* content_settings =
626 TabSpecificContentSettings::FromWebContents(web_contents);
627 state_ = content_settings->GetMicrophoneCameraState();
628 DCHECK(state_ & (TabSpecificContentSettings::MICROPHONE_ACCESSED |
629 TabSpecificContentSettings::CAMERA_ACCESSED));
631 SetTitle();
632 SetRadioGroup();
633 SetMediaMenus();
634 SetCustomLink();
637 ContentSettingMediaStreamBubbleModel::~ContentSettingMediaStreamBubbleModel() {
638 // On some platforms (e.g. MacOS X) it is possible to close a tab while the
639 // media stream bubble is open. This resets the web contents to NULL.
640 if (!web_contents())
641 return;
643 for (MediaMenuMap::const_iterator it = bubble_content().media_menus.begin();
644 it != bubble_content().media_menus.end(); ++it) {
645 if (it->second.selected_device.id != it->second.default_device.id) {
646 UpdateDefaultDeviceForType(it->first, it->second.selected_device.id);
650 // Update the media settings if the radio button selection was changed.
651 if (selected_item_ != bubble_content().radio_group.default_item) {
652 UpdateSettings(radio_item_setting_[selected_item_]);
656 void ContentSettingMediaStreamBubbleModel::SetTitle() {
657 DCHECK_NE(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED, state_);
658 int title_id = 0;
659 if (state_ & TabSpecificContentSettings::MICROPHONE_BLOCKED) {
660 title_id = (state_ & TabSpecificContentSettings::CAMERA_BLOCKED) ?
661 IDS_MICROPHONE_CAMERA_BLOCKED : IDS_MICROPHONE_BLOCKED;
662 } else if (state_ & TabSpecificContentSettings::CAMERA_BLOCKED) {
663 title_id = IDS_CAMERA_BLOCKED;
664 } else if (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) {
665 title_id = (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) ?
666 IDS_MICROPHONE_CAMERA_ALLOWED : IDS_MICROPHONE_ACCESSED;
667 } else if (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) {
668 title_id = IDS_CAMERA_ACCESSED;
670 set_title(l10n_util::GetStringUTF8(title_id));
673 void ContentSettingMediaStreamBubbleModel::SetRadioGroup() {
674 TabSpecificContentSettings* content_settings =
675 TabSpecificContentSettings::FromWebContents(web_contents());
676 GURL url = content_settings->media_stream_access_origin();
677 RadioGroup radio_group;
678 radio_group.url = url;
680 base::string16 display_host_utf16;
681 net::AppendFormattedHost(
682 url,
683 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
684 &display_host_utf16);
685 std::string display_host(base::UTF16ToUTF8(display_host_utf16));
686 if (display_host.empty())
687 display_host = url.spec();
689 bool is_mic = (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) != 0;
690 bool is_cam = (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) != 0;
691 DCHECK(is_mic || is_cam);
692 int radio_allow_label_id = 0;
693 int radio_block_label_id = 0;
694 if (state_ & (TabSpecificContentSettings::MICROPHONE_BLOCKED |
695 TabSpecificContentSettings::CAMERA_BLOCKED)) {
696 if (url.SchemeIsSecure()) {
697 radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
698 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW;
699 if (is_mic)
700 radio_allow_label_id = is_cam ?
701 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ALLOW :
702 IDS_BLOCKED_MEDIASTREAM_MIC_ALLOW;
703 } else {
704 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK;
705 if (is_mic)
706 radio_allow_label_id = is_cam ?
707 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ASK :
708 IDS_BLOCKED_MEDIASTREAM_MIC_ASK;
710 radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION;
711 if (is_mic)
712 radio_block_label_id = is_cam ?
713 IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION :
714 IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION;
715 } else {
716 if (is_mic && is_cam) {
717 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION;
718 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK;
719 } else if (is_mic) {
720 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION;
721 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK;
722 } else {
723 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION;
724 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK;
727 selected_item_ =
728 (is_mic && content_settings->IsContentBlocked(
729 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC)) ||
730 (is_cam && content_settings->IsContentBlocked(
731 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA)) ? 1 : 0;
733 std::string radio_allow_label = l10n_util::GetStringFUTF8(
734 radio_allow_label_id, base::UTF8ToUTF16(display_host));
735 std::string radio_block_label =
736 l10n_util::GetStringUTF8(radio_block_label_id);
738 radio_group.default_item = selected_item_;
739 radio_group.radio_items.push_back(radio_allow_label);
740 radio_group.radio_items.push_back(radio_block_label);
742 set_radio_group(radio_group);
743 set_radio_group_enabled(true);
746 void ContentSettingMediaStreamBubbleModel::UpdateSettings(
747 ContentSetting setting) {
748 if (profile()) {
749 HostContentSettingsMap* content_settings =
750 profile()->GetHostContentSettingsMap();
751 TabSpecificContentSettings* tab_content_settings =
752 TabSpecificContentSettings::FromWebContents(web_contents());
753 // The same patterns must be used as in other places (e.g. the infobar) in
754 // order to override the existing rule. Otherwise a new rule is created.
755 // TODO(markusheintz): Extract to a helper so that there is only a single
756 // place to touch.
757 ContentSettingsPattern primary_pattern =
758 ContentSettingsPattern::FromURLNoWildcard(
759 tab_content_settings->media_stream_access_origin());
760 ContentSettingsPattern secondary_pattern =
761 ContentSettingsPattern::Wildcard();
762 if (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) {
763 content_settings->SetContentSetting(
764 primary_pattern, secondary_pattern,
765 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string(), setting);
767 if (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) {
768 content_settings->SetContentSetting(
769 primary_pattern, secondary_pattern,
770 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string(), setting);
775 void ContentSettingMediaStreamBubbleModel::UpdateDefaultDeviceForType(
776 content::MediaStreamType type,
777 const std::string& device) {
778 PrefService* prefs = profile()->GetPrefs();
779 if (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
780 prefs->SetString(prefs::kDefaultAudioCaptureDevice, device);
781 } else {
782 DCHECK_EQ(content::MEDIA_DEVICE_VIDEO_CAPTURE, type);
783 prefs->SetString(prefs::kDefaultVideoCaptureDevice, device);
787 void ContentSettingMediaStreamBubbleModel::SetMediaMenus() {
788 TabSpecificContentSettings* content_settings =
789 TabSpecificContentSettings::FromWebContents(web_contents());
790 const std::string& requested_microphone =
791 content_settings->media_stream_requested_audio_device();
792 const std::string& requested_camera =
793 content_settings->media_stream_requested_video_device();
795 // Add microphone menu.
796 PrefService* prefs = profile()->GetPrefs();
797 MediaCaptureDevicesDispatcher* dispatcher =
798 MediaCaptureDevicesDispatcher::GetInstance();
799 const content::MediaStreamDevices& microphones =
800 dispatcher->GetAudioCaptureDevices();
802 if (state_ & TabSpecificContentSettings::MICROPHONE_ACCESSED) {
803 MediaMenu mic_menu;
804 mic_menu.label = l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_MIC_LABEL);
805 if (!microphones.empty()) {
806 std::string preferred_mic;
807 if (requested_microphone.empty()) {
808 preferred_mic = prefs->GetString(prefs::kDefaultAudioCaptureDevice);
809 mic_menu.disabled = false;
810 } else {
811 // Set the |disabled| to true in order to disable the device selection
812 // menu on the media settings bubble. This must be done if the website
813 // manages the microphone devices itself.
814 preferred_mic = requested_microphone;
815 mic_menu.disabled = true;
818 mic_menu.default_device = GetMediaDeviceById(preferred_mic, microphones);
819 mic_menu.selected_device = mic_menu.default_device;
821 add_media_menu(content::MEDIA_DEVICE_AUDIO_CAPTURE, mic_menu);
824 if (state_ & TabSpecificContentSettings::CAMERA_ACCESSED) {
825 const content::MediaStreamDevices& cameras =
826 dispatcher->GetVideoCaptureDevices();
827 MediaMenu camera_menu;
828 camera_menu.label =
829 l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_CAMERA_LABEL);
830 if (!cameras.empty()) {
831 std::string preferred_camera;
832 if (requested_camera.empty()) {
833 preferred_camera = prefs->GetString(prefs::kDefaultVideoCaptureDevice);
834 camera_menu.disabled = false;
835 } else {
836 // Disable the menu since the website is managing the camera devices
837 // itself.
838 preferred_camera = requested_camera;
839 camera_menu.disabled = true;
842 camera_menu.default_device =
843 GetMediaDeviceById(preferred_camera, cameras);
844 camera_menu.selected_device = camera_menu.default_device;
846 add_media_menu(content::MEDIA_DEVICE_VIDEO_CAPTURE, camera_menu);
850 void ContentSettingMediaStreamBubbleModel::SetCustomLink() {
851 TabSpecificContentSettings* content_settings =
852 TabSpecificContentSettings::FromWebContents(web_contents());
853 if (content_settings->IsMicrophoneCameraStateChanged()) {
854 set_custom_link(l10n_util::GetStringUTF8(
855 IDS_MEDIASTREAM_SETTING_CHANGED_MESSAGE));
859 void ContentSettingMediaStreamBubbleModel::OnRadioClicked(int radio_index) {
860 selected_item_ = radio_index;
863 void ContentSettingMediaStreamBubbleModel::OnMediaMenuClicked(
864 content::MediaStreamType type,
865 const std::string& selected_device_id) {
866 DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
867 type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
868 DCHECK_EQ(1U, bubble_content().media_menus.count(type));
869 MediaCaptureDevicesDispatcher* dispatcher =
870 MediaCaptureDevicesDispatcher::GetInstance();
871 const content::MediaStreamDevices& devices =
872 (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) ?
873 dispatcher->GetAudioCaptureDevices() :
874 dispatcher->GetVideoCaptureDevices();
875 set_selected_device(GetMediaDeviceById(selected_device_id, devices));
878 class ContentSettingDomainListBubbleModel
879 : public ContentSettingTitleAndLinkModel {
880 public:
881 ContentSettingDomainListBubbleModel(Delegate* delegate,
882 WebContents* web_contents,
883 Profile* profile,
884 ContentSettingsType content_type);
885 ~ContentSettingDomainListBubbleModel() override {}
887 private:
888 void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
889 void SetDomainsAndCustomLink();
890 void OnCustomLinkClicked() override;
893 ContentSettingDomainListBubbleModel::ContentSettingDomainListBubbleModel(
894 Delegate* delegate,
895 WebContents* web_contents,
896 Profile* profile,
897 ContentSettingsType content_type)
898 : ContentSettingTitleAndLinkModel(
899 delegate, web_contents, profile, content_type) {
900 DCHECK_EQ(CONTENT_SETTINGS_TYPE_GEOLOCATION, content_type) <<
901 "SetDomains currently only supports geolocation content type";
902 SetDomainsAndCustomLink();
905 void ContentSettingDomainListBubbleModel::MaybeAddDomainList(
906 const std::set<std::string>& hosts, int title_id) {
907 if (!hosts.empty()) {
908 DomainList domain_list;
909 domain_list.title = l10n_util::GetStringUTF8(title_id);
910 domain_list.hosts = hosts;
911 add_domain_list(domain_list);
915 void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() {
916 TabSpecificContentSettings* content_settings =
917 TabSpecificContentSettings::FromWebContents(web_contents());
918 const ContentSettingsUsagesState& usages =
919 content_settings->geolocation_usages_state();
920 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
921 unsigned int tab_state_flags = 0;
922 usages.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
923 // Divide the tab's current geolocation users into sets according to their
924 // permission state.
925 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
926 IDS_GEOLOCATION_BUBBLE_SECTION_ALLOWED);
928 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
929 IDS_GEOLOCATION_BUBBLE_SECTION_DENIED);
931 if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
932 set_custom_link(l10n_util::GetStringUTF8(
933 IDS_GEOLOCATION_BUBBLE_CLEAR_LINK));
934 set_custom_link_enabled(true);
935 } else if (tab_state_flags &
936 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
937 set_custom_link(l10n_util::GetStringUTF8(
938 IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
942 void ContentSettingDomainListBubbleModel::OnCustomLinkClicked() {
943 if (!web_contents())
944 return;
945 // Reset this embedder's entry to default for each of the requesting
946 // origins currently on the page.
947 const GURL& embedder_url = web_contents()->GetURL();
948 TabSpecificContentSettings* content_settings =
949 TabSpecificContentSettings::FromWebContents(web_contents());
950 const ContentSettingsUsagesState::StateMap& state_map =
951 content_settings->geolocation_usages_state().state_map();
952 HostContentSettingsMap* settings_map =
953 profile()->GetHostContentSettingsMap();
955 for (ContentSettingsUsagesState::StateMap::const_iterator it =
956 state_map.begin(); it != state_map.end(); ++it) {
957 settings_map->SetContentSetting(
958 ContentSettingsPattern::FromURLNoWildcard(it->first),
959 ContentSettingsPattern::FromURLNoWildcard(embedder_url),
960 CONTENT_SETTINGS_TYPE_GEOLOCATION,
961 std::string(),
962 CONTENT_SETTING_DEFAULT);
966 class ContentSettingMixedScriptBubbleModel
967 : public ContentSettingTitleLinkAndCustomModel {
968 public:
969 ContentSettingMixedScriptBubbleModel(Delegate* delegate,
970 WebContents* web_contents,
971 Profile* profile,
972 ContentSettingsType content_type);
974 ~ContentSettingMixedScriptBubbleModel() override {}
976 private:
977 void OnCustomLinkClicked() override;
980 ContentSettingMixedScriptBubbleModel::ContentSettingMixedScriptBubbleModel(
981 Delegate* delegate,
982 WebContents* web_contents,
983 Profile* profile,
984 ContentSettingsType content_type)
985 : ContentSettingTitleLinkAndCustomModel(
986 delegate, web_contents, profile, content_type) {
987 DCHECK_EQ(content_type, CONTENT_SETTINGS_TYPE_MIXEDSCRIPT);
988 content_settings::RecordMixedScriptAction(
989 content_settings::MIXED_SCRIPT_ACTION_DISPLAYED_BUBBLE);
990 set_custom_link_enabled(true);
993 void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
994 content_settings::RecordMixedScriptAction(
995 content_settings::MIXED_SCRIPT_ACTION_CLICKED_ALLOW);
996 DCHECK(web_contents());
997 web_contents()->SendToAllFrames(
998 new ChromeViewMsg_SetAllowRunningInsecureContent(MSG_ROUTING_NONE, true));
999 web_contents()->GetMainFrame()->Send(new ChromeViewMsg_ReloadFrame(
1000 web_contents()->GetMainFrame()->GetRoutingID()));
1003 ContentSettingRPHBubbleModel::ContentSettingRPHBubbleModel(
1004 Delegate* delegate,
1005 WebContents* web_contents,
1006 Profile* profile,
1007 ProtocolHandlerRegistry* registry,
1008 ContentSettingsType content_type)
1009 : ContentSettingTitleAndLinkModel(
1010 delegate, web_contents, profile, content_type),
1011 selected_item_(0),
1012 registry_(registry),
1013 pending_handler_(ProtocolHandler::EmptyProtocolHandler()),
1014 previous_handler_(ProtocolHandler::EmptyProtocolHandler()) {
1015 DCHECK_EQ(CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, content_type);
1017 TabSpecificContentSettings* content_settings =
1018 TabSpecificContentSettings::FromWebContents(web_contents);
1019 pending_handler_ = content_settings->pending_protocol_handler();
1020 previous_handler_ = content_settings->previous_protocol_handler();
1022 base::string16 protocol;
1023 if (pending_handler_.protocol() == "mailto") {
1024 protocol = l10n_util::GetStringUTF16(
1025 IDS_REGISTER_PROTOCOL_HANDLER_MAILTO_NAME);
1026 } else if (pending_handler_.protocol() == "webcal") {
1027 protocol = l10n_util::GetStringUTF16(
1028 IDS_REGISTER_PROTOCOL_HANDLER_WEBCAL_NAME);
1029 } else {
1030 protocol = base::UTF8ToUTF16(pending_handler_.protocol());
1033 // Note that we ignore the |title| parameter.
1034 if (previous_handler_.IsEmpty()) {
1035 set_title(l10n_util::GetStringFUTF8(
1036 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM,
1037 base::UTF8ToUTF16(pending_handler_.url().host()),
1038 protocol));
1039 } else {
1040 set_title(l10n_util::GetStringFUTF8(
1041 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM_REPLACE,
1042 base::UTF8ToUTF16(pending_handler_.url().host()),
1043 protocol,
1044 base::UTF8ToUTF16(previous_handler_.url().host())));
1047 std::string radio_allow_label =
1048 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_ACCEPT);
1049 std::string radio_deny_label =
1050 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_DENY);
1051 std::string radio_ignore_label =
1052 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_IGNORE);
1054 GURL url = web_contents->GetURL();
1055 RadioGroup radio_group;
1056 radio_group.url = url;
1058 radio_group.radio_items.push_back(radio_allow_label);
1059 radio_group.radio_items.push_back(radio_deny_label);
1060 radio_group.radio_items.push_back(radio_ignore_label);
1061 ContentSetting setting =
1062 content_settings->pending_protocol_handler_setting();
1063 if (setting == CONTENT_SETTING_ALLOW)
1064 radio_group.default_item = RPH_ALLOW;
1065 else if (setting == CONTENT_SETTING_BLOCK)
1066 radio_group.default_item = RPH_BLOCK;
1067 else
1068 radio_group.default_item = RPH_IGNORE;
1070 selected_item_ = radio_group.default_item;
1071 set_radio_group_enabled(true);
1072 set_radio_group(radio_group);
1075 void ContentSettingRPHBubbleModel::OnRadioClicked(int radio_index) {
1076 if (selected_item_ == radio_index)
1077 return;
1079 selected_item_ = radio_index;
1081 if (radio_index == RPH_ALLOW)
1082 RegisterProtocolHandler();
1083 else if (radio_index == RPH_BLOCK)
1084 UnregisterProtocolHandler();
1085 else if (radio_index == RPH_IGNORE)
1086 IgnoreProtocolHandler();
1087 else
1088 NOTREACHED();
1091 void ContentSettingRPHBubbleModel::OnDoneClicked() {
1092 // The user has one chance to deal with the RPH content setting UI,
1093 // then we remove it.
1094 TabSpecificContentSettings::FromWebContents(web_contents())->
1095 ClearPendingProtocolHandler();
1096 content::NotificationService::current()->Notify(
1097 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
1098 content::Source<WebContents>(web_contents()),
1099 content::NotificationService::NoDetails());
1102 void ContentSettingRPHBubbleModel::RegisterProtocolHandler() {
1103 // A no-op if the handler hasn't been ignored, but needed in case the user
1104 // selects sequences like register/ignore/register.
1105 registry_->RemoveIgnoredHandler(pending_handler_);
1107 registry_->OnAcceptRegisterProtocolHandler(pending_handler_);
1108 TabSpecificContentSettings::FromWebContents(web_contents())->
1109 set_pending_protocol_handler_setting(CONTENT_SETTING_ALLOW);
1112 void ContentSettingRPHBubbleModel::UnregisterProtocolHandler() {
1113 registry_->OnDenyRegisterProtocolHandler(pending_handler_);
1114 TabSpecificContentSettings::FromWebContents(web_contents())->
1115 set_pending_protocol_handler_setting(CONTENT_SETTING_BLOCK);
1116 ClearOrSetPreviousHandler();
1119 void ContentSettingRPHBubbleModel::IgnoreProtocolHandler() {
1120 registry_->OnIgnoreRegisterProtocolHandler(pending_handler_);
1121 TabSpecificContentSettings::FromWebContents(web_contents())->
1122 set_pending_protocol_handler_setting(CONTENT_SETTING_DEFAULT);
1123 ClearOrSetPreviousHandler();
1126 void ContentSettingRPHBubbleModel::ClearOrSetPreviousHandler() {
1127 if (previous_handler_.IsEmpty()) {
1128 registry_->ClearDefault(pending_handler_.protocol());
1129 } else {
1130 registry_->OnAcceptRegisterProtocolHandler(previous_handler_);
1134 class ContentSettingMidiSysExBubbleModel
1135 : public ContentSettingTitleAndLinkModel {
1136 public:
1137 ContentSettingMidiSysExBubbleModel(Delegate* delegate,
1138 WebContents* web_contents,
1139 Profile* profile,
1140 ContentSettingsType content_type);
1141 ~ContentSettingMidiSysExBubbleModel() override {}
1143 private:
1144 void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
1145 void SetDomainsAndCustomLink();
1146 void OnCustomLinkClicked() override;
1149 ContentSettingMidiSysExBubbleModel::ContentSettingMidiSysExBubbleModel(
1150 Delegate* delegate,
1151 WebContents* web_contents,
1152 Profile* profile,
1153 ContentSettingsType content_type)
1154 : ContentSettingTitleAndLinkModel(
1155 delegate, web_contents, profile, content_type) {
1156 DCHECK_EQ(CONTENT_SETTINGS_TYPE_MIDI_SYSEX, content_type);
1157 SetDomainsAndCustomLink();
1160 void ContentSettingMidiSysExBubbleModel::MaybeAddDomainList(
1161 const std::set<std::string>& hosts, int title_id) {
1162 if (!hosts.empty()) {
1163 DomainList domain_list;
1164 domain_list.title = l10n_util::GetStringUTF8(title_id);
1165 domain_list.hosts = hosts;
1166 add_domain_list(domain_list);
1170 void ContentSettingMidiSysExBubbleModel::SetDomainsAndCustomLink() {
1171 TabSpecificContentSettings* content_settings =
1172 TabSpecificContentSettings::FromWebContents(web_contents());
1173 const ContentSettingsUsagesState& usages_state =
1174 content_settings->midi_usages_state();
1175 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
1176 unsigned int tab_state_flags = 0;
1177 usages_state.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
1178 // Divide the tab's current MIDI sysex users into sets according to their
1179 // permission state.
1180 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
1181 IDS_MIDI_SYSEX_BUBBLE_ALLOWED);
1183 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
1184 IDS_MIDI_SYSEX_BUBBLE_DENIED);
1186 if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
1187 set_custom_link(l10n_util::GetStringUTF8(
1188 IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK));
1189 set_custom_link_enabled(true);
1190 } else if (tab_state_flags &
1191 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
1192 set_custom_link(l10n_util::GetStringUTF8(
1193 IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
1197 void ContentSettingMidiSysExBubbleModel::OnCustomLinkClicked() {
1198 if (!web_contents())
1199 return;
1200 // Reset this embedder's entry to default for each of the requesting
1201 // origins currently on the page.
1202 const GURL& embedder_url = web_contents()->GetURL();
1203 TabSpecificContentSettings* content_settings =
1204 TabSpecificContentSettings::FromWebContents(web_contents());
1205 const ContentSettingsUsagesState::StateMap& state_map =
1206 content_settings->midi_usages_state().state_map();
1207 HostContentSettingsMap* settings_map =
1208 profile()->GetHostContentSettingsMap();
1210 for (ContentSettingsUsagesState::StateMap::const_iterator it =
1211 state_map.begin(); it != state_map.end(); ++it) {
1212 settings_map->SetContentSetting(
1213 ContentSettingsPattern::FromURLNoWildcard(it->first),
1214 ContentSettingsPattern::FromURLNoWildcard(embedder_url),
1215 CONTENT_SETTINGS_TYPE_MIDI_SYSEX,
1216 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, profile,
1230 content_type);
1232 if (content_type == CONTENT_SETTINGS_TYPE_POPUPS) {
1233 return new ContentSettingPopupBubbleModel(delegate, web_contents, profile,
1234 content_type);
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,
1246 content_type);
1248 if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT) {
1249 return new ContentSettingMixedScriptBubbleModel(delegate, web_contents,
1250 profile, content_type);
1252 if (content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS) {
1253 ProtocolHandlerRegistry* registry =
1254 ProtocolHandlerRegistryFactory::GetForBrowserContext(profile);
1255 return new ContentSettingRPHBubbleModel(delegate, web_contents, profile,
1256 registry, content_type);
1258 if (content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
1259 return new ContentSettingMidiSysExBubbleModel(delegate, web_contents,
1260 profile, content_type);
1262 return new ContentSettingSingleRadioGroup(delegate, web_contents, profile,
1263 content_type);
1266 ContentSettingBubbleModel::ContentSettingBubbleModel(
1267 WebContents* web_contents,
1268 Profile* profile,
1269 ContentSettingsType content_type)
1270 : web_contents_(web_contents),
1271 profile_(profile),
1272 content_type_(content_type),
1273 setting_is_managed_(false) {
1274 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
1275 content::Source<WebContents>(web_contents));
1276 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
1277 content::Source<Profile>(profile_));
1280 ContentSettingBubbleModel::~ContentSettingBubbleModel() {
1283 ContentSettingBubbleModel::RadioGroup::RadioGroup() : default_item(0) {}
1285 ContentSettingBubbleModel::RadioGroup::~RadioGroup() {}
1287 ContentSettingBubbleModel::DomainList::DomainList() {}
1289 ContentSettingBubbleModel::DomainList::~DomainList() {}
1291 ContentSettingBubbleModel::MediaMenu::MediaMenu() : disabled(false) {}
1293 ContentSettingBubbleModel::MediaMenu::~MediaMenu() {}
1295 ContentSettingBubbleModel::BubbleContent::BubbleContent()
1296 : radio_group_enabled(false),
1297 custom_link_enabled(false) {
1300 ContentSettingBubbleModel::BubbleContent::~BubbleContent() {}
1302 void ContentSettingBubbleModel::Observe(
1303 int type,
1304 const content::NotificationSource& source,
1305 const content::NotificationDetails& details) {
1306 if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) {
1307 DCHECK_EQ(web_contents_,
1308 content::Source<WebContents>(source).ptr());
1309 web_contents_ = NULL;
1310 } else {
1311 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
1312 DCHECK_EQ(profile_, content::Source<Profile>(source).ptr());
1313 profile_ = NULL;