app_shell: Add version number in user agent
[chromium-blink-merge.git] / chrome / browser / ui / content_settings / content_setting_bubble_model.cc
blob0c2c8ef471fd1f1bcec965843e45e84f5fb9fc0f
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
7 #include "base/command_line.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/content_settings/content_settings_utils.h"
12 #include "chrome/browser/content_settings/cookie_settings.h"
13 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
14 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
15 #include "chrome/browser/favicon/favicon_tab_helper.h"
16 #include "chrome/browser/infobars/infobar_service.h"
17 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
18 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
21 #include "chrome/browser/ui/browser_navigator.h"
22 #include "chrome/browser/ui/collected_cookies_infobar_delegate.h"
23 #include "chrome/browser/ui/content_settings/content_setting_bubble_model_delegate.h"
24 #include "chrome/browser/ui/content_settings/media_setting_changed_infobar_delegate.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/content_settings.h"
27 #include "chrome/common/pref_names.h"
28 #include "chrome/common/render_messages.h"
29 #include "content/public/browser/notification_service.h"
30 #include "content/public/browser/render_frame_host.h"
31 #include "content/public/browser/render_process_host.h"
32 #include "content/public/browser/render_view_host.h"
33 #include "content/public/browser/user_metrics.h"
34 #include "content/public/browser/web_contents.h"
35 #include "content/public/browser/web_contents_delegate.h"
36 #include "grit/generated_resources.h"
37 #include "grit/theme_resources.h"
38 #include "net/base/net_util.h"
39 #include "ui/base/l10n/l10n_util.h"
40 #include "ui/base/resource/resource_bundle.h"
41 #include "ui/resources/grit/ui_resources.h"
43 using base::UserMetricsAction;
44 using content::WebContents;
45 using content_settings::SettingInfo;
46 using content_settings::SettingSource;
47 using content_settings::SETTING_SOURCE_USER;
48 using content_settings::SETTING_SOURCE_NONE;
50 namespace {
52 const int kAllowButtonIndex = 0;
54 struct ContentSettingsTypeIdEntry {
55 ContentSettingsType type;
56 int id;
59 int GetIdForContentType(const ContentSettingsTypeIdEntry* entries,
60 size_t num_entries,
61 ContentSettingsType type) {
62 for (size_t i = 0; i < num_entries; ++i) {
63 if (entries[i].type == type)
64 return entries[i].id;
66 return 0;
69 const content::MediaStreamDevice& GetMediaDeviceById(
70 const std::string& device_id,
71 const content::MediaStreamDevices& devices) {
72 DCHECK(!devices.empty());
73 for (content::MediaStreamDevices::const_iterator it = devices.begin();
74 it != devices.end(); ++it) {
75 if (it->id == device_id)
76 return *(it);
79 // A device with the |device_id| was not found. It is likely that the device
80 // has been unplugged from the OS. Return the first device as the default
81 // device.
82 return *devices.begin();
85 } // namespace
87 ContentSettingTitleAndLinkModel::ContentSettingTitleAndLinkModel(
88 Delegate* delegate,
89 WebContents* web_contents,
90 Profile* profile,
91 ContentSettingsType content_type)
92 : ContentSettingBubbleModel(web_contents, profile, content_type),
93 delegate_(delegate) {
94 // Notifications do not have a bubble.
95 DCHECK_NE(content_type, CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
96 SetTitle();
97 SetManageLink();
98 SetLearnMoreLink();
101 void ContentSettingTitleAndLinkModel::SetTitle() {
102 static const ContentSettingsTypeIdEntry kBlockedTitleIDs[] = {
103 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_TITLE},
104 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_TITLE},
105 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_TITLE},
106 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_MESSAGE},
107 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_TITLE},
108 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT,
109 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT},
110 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER,
111 IDS_BLOCKED_PPAPI_BROKER_TITLE},
112 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_TITLE},
114 // Fields as for kBlockedTitleIDs, above.
115 static const ContentSettingsTypeIdEntry kAccessedTitleIDs[] = {
116 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_ACCESSED_COOKIES_TITLE},
117 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_TITLE},
118 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_TITLE},
120 const ContentSettingsTypeIdEntry *title_ids = kBlockedTitleIDs;
121 size_t num_title_ids = arraysize(kBlockedTitleIDs);
122 if (web_contents() &&
123 TabSpecificContentSettings::FromWebContents(
124 web_contents())->IsContentAllowed(content_type()) &&
125 !TabSpecificContentSettings::FromWebContents(
126 web_contents())->IsContentBlocked(content_type())) {
127 title_ids = kAccessedTitleIDs;
128 num_title_ids = arraysize(kAccessedTitleIDs);
130 int title_id =
131 GetIdForContentType(title_ids, num_title_ids, content_type());
132 if (title_id)
133 set_title(l10n_util::GetStringUTF8(title_id));
136 void ContentSettingTitleAndLinkModel::SetManageLink() {
137 static const ContentSettingsTypeIdEntry kLinkIDs[] = {
138 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_LINK},
139 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_LINK},
140 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_LINK},
141 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LINK},
142 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_LINK},
143 {CONTENT_SETTINGS_TYPE_GEOLOCATION, IDS_GEOLOCATION_BUBBLE_MANAGE_LINK},
144 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_LEARN_MORE},
145 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, IDS_HANDLERS_BUBBLE_MANAGE_LINK},
146 {CONTENT_SETTINGS_TYPE_MEDIASTREAM, IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK},
147 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_PPAPI_BROKER_BUBBLE_MANAGE_LINK},
148 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOADS_LINK},
149 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX, IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK},
151 set_manage_link(l10n_util::GetStringUTF8(
152 GetIdForContentType(kLinkIDs, arraysize(kLinkIDs), content_type())));
155 void ContentSettingTitleAndLinkModel::OnManageLinkClicked() {
156 if (delegate_)
157 delegate_->ShowContentSettingsPage(content_type());
160 void ContentSettingTitleAndLinkModel::SetLearnMoreLink() {
161 static const ContentSettingsTypeIdEntry kLearnMoreIDs[] = {
162 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_LEARN_MORE},
164 int learn_more_id =
165 GetIdForContentType(kLearnMoreIDs, arraysize(kLearnMoreIDs),
166 content_type());
167 if (learn_more_id)
168 set_learn_more_link(l10n_util::GetStringUTF8(learn_more_id));
171 void ContentSettingTitleAndLinkModel::OnLearnMoreLinkClicked() {
172 if (delegate_)
173 delegate_->ShowLearnMorePage(content_type());
176 class ContentSettingTitleLinkAndCustomModel
177 : public ContentSettingTitleAndLinkModel {
178 public:
179 ContentSettingTitleLinkAndCustomModel(Delegate* delegate,
180 WebContents* web_contents,
181 Profile* profile,
182 ContentSettingsType content_type);
183 virtual ~ContentSettingTitleLinkAndCustomModel() {}
185 private:
186 void SetCustomLink();
187 virtual void OnCustomLinkClicked() OVERRIDE {}
190 ContentSettingTitleLinkAndCustomModel::ContentSettingTitleLinkAndCustomModel(
191 Delegate* delegate,
192 WebContents* web_contents,
193 Profile* profile,
194 ContentSettingsType content_type)
195 : ContentSettingTitleAndLinkModel(
196 delegate, web_contents, profile, content_type) {
197 SetCustomLink();
200 void ContentSettingTitleLinkAndCustomModel::SetCustomLink() {
201 static const ContentSettingsTypeIdEntry kCustomIDs[] = {
202 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_INFO},
203 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LOAD_ALL},
204 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_ALLOW_INSECURE_CONTENT_BUTTON},
206 int custom_link_id =
207 GetIdForContentType(kCustomIDs, arraysize(kCustomIDs), content_type());
208 if (custom_link_id)
209 set_custom_link(l10n_util::GetStringUTF8(custom_link_id));
212 class ContentSettingSingleRadioGroup
213 : public ContentSettingTitleLinkAndCustomModel {
214 public:
215 ContentSettingSingleRadioGroup(Delegate* delegate,
216 WebContents* web_contents,
217 Profile* profile,
218 ContentSettingsType content_type);
219 virtual ~ContentSettingSingleRadioGroup();
221 protected:
222 bool settings_changed() const;
223 int selected_item() const { return selected_item_; }
225 private:
226 void SetRadioGroup();
227 void AddException(ContentSetting setting);
228 virtual void OnRadioClicked(int radio_index) OVERRIDE;
230 ContentSetting block_setting_;
231 int selected_item_;
234 ContentSettingSingleRadioGroup::ContentSettingSingleRadioGroup(
235 Delegate* delegate,
236 WebContents* web_contents,
237 Profile* profile,
238 ContentSettingsType content_type)
239 : ContentSettingTitleLinkAndCustomModel(delegate, web_contents, profile,
240 content_type),
241 block_setting_(CONTENT_SETTING_BLOCK),
242 selected_item_(0) {
243 SetRadioGroup();
246 ContentSettingSingleRadioGroup::~ContentSettingSingleRadioGroup() {
247 if (settings_changed()) {
248 ContentSetting setting =
249 selected_item_ == kAllowButtonIndex ?
250 CONTENT_SETTING_ALLOW :
251 block_setting_;
252 AddException(setting);
256 bool ContentSettingSingleRadioGroup::settings_changed() const {
257 return selected_item_ != bubble_content().radio_group.default_item;
260 // Initialize the radio group by setting the appropriate labels for the
261 // content type and setting the default value based on the content setting.
262 void ContentSettingSingleRadioGroup::SetRadioGroup() {
263 GURL url = web_contents()->GetURL();
264 base::string16 display_host;
265 net::AppendFormattedHost(
266 url,
267 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
268 &display_host);
270 if (display_host.empty())
271 display_host = base::ASCIIToUTF16(url.spec());
273 TabSpecificContentSettings* content_settings =
274 TabSpecificContentSettings::FromWebContents(web_contents());
275 bool allowed =
276 !content_settings->IsContentBlocked(content_type());
277 DCHECK(!allowed ||
278 content_settings->IsContentAllowed(content_type()));
280 RadioGroup radio_group;
281 radio_group.url = url;
283 static const ContentSettingsTypeIdEntry kBlockedAllowIDs[] = {
284 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
285 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_UNBLOCK},
286 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_UNBLOCK},
287 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_UNBLOCK_ALL},
288 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_UNBLOCK},
289 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_UNBLOCK},
290 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_UNBLOCK},
292 // Fields as for kBlockedAllowIDs, above.
293 static const ContentSettingsTypeIdEntry kAllowedAllowIDs[] = {
294 // TODO(bauerb): The string shouldn't be "unblock" (they weren't blocked).
295 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
296 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_NO_ACTION},
297 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_NO_ACTION},
300 std::string radio_allow_label;
301 if (allowed) {
302 int resource_id = GetIdForContentType(kAllowedAllowIDs,
303 arraysize(kAllowedAllowIDs),
304 content_type());
305 radio_allow_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
306 l10n_util::GetStringFUTF8(resource_id, display_host) :
307 l10n_util::GetStringUTF8(resource_id);
308 } else {
309 radio_allow_label = l10n_util::GetStringFUTF8(
310 GetIdForContentType(kBlockedAllowIDs, arraysize(kBlockedAllowIDs),
311 content_type()),
312 display_host);
315 static const ContentSettingsTypeIdEntry kBlockedBlockIDs[] = {
316 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
317 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_NO_ACTION},
318 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_NO_ACTION},
319 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_NO_ACTION},
320 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_NO_ACTION},
321 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_NO_ACTION},
322 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_NO_ACTION},
324 static const ContentSettingsTypeIdEntry kAllowedBlockIDs[] = {
325 // TODO(bauerb): The string should say "block".
326 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
327 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_BLOCK},
328 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_BLOCK},
331 std::string radio_block_label;
332 if (allowed) {
333 int resource_id = GetIdForContentType(kAllowedBlockIDs,
334 arraysize(kAllowedBlockIDs),
335 content_type());
336 radio_block_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
337 l10n_util::GetStringUTF8(resource_id) :
338 l10n_util::GetStringFUTF8(resource_id, display_host);
339 } else {
340 radio_block_label = l10n_util::GetStringUTF8(
341 GetIdForContentType(kBlockedBlockIDs, arraysize(kBlockedBlockIDs),
342 content_type()));
345 radio_group.radio_items.push_back(radio_allow_label);
346 radio_group.radio_items.push_back(radio_block_label);
347 ContentSetting setting;
348 SettingSource setting_source = SETTING_SOURCE_NONE;
349 bool setting_is_wildcard = false;
351 if (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) {
352 CookieSettings* cookie_settings =
353 CookieSettings::Factory::GetForProfile(profile()).get();
354 setting = cookie_settings->GetCookieSetting(
355 url, url, true, &setting_source);
356 } else {
357 SettingInfo info;
358 HostContentSettingsMap* map = profile()->GetHostContentSettingsMap();
359 scoped_ptr<base::Value> value(map->GetWebsiteSetting(
360 url, url, content_type(), std::string(), &info));
361 setting = content_settings::ValueToContentSetting(value.get());
362 setting_source = info.source;
363 setting_is_wildcard =
364 info.primary_pattern == ContentSettingsPattern::Wildcard() &&
365 info.secondary_pattern == ContentSettingsPattern::Wildcard();
368 if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS &&
369 setting == CONTENT_SETTING_ALLOW &&
370 setting_is_wildcard) {
371 // In the corner case of unrecognized plugins (which are now blocked by
372 // default) we indicate the blocked state in the UI and allow the user to
373 // whitelist.
374 radio_group.default_item = 1;
375 } else if (setting == CONTENT_SETTING_ALLOW) {
376 radio_group.default_item = kAllowButtonIndex;
377 // |block_setting_| is already set to |CONTENT_SETTING_BLOCK|.
378 } else {
379 radio_group.default_item = 1;
380 block_setting_ = setting;
383 set_setting_is_managed(setting_source != SETTING_SOURCE_USER);
384 if (setting_source != SETTING_SOURCE_USER) {
385 set_radio_group_enabled(false);
386 } else {
387 set_radio_group_enabled(true);
389 selected_item_ = radio_group.default_item;
390 set_radio_group(radio_group);
393 void ContentSettingSingleRadioGroup::AddException(ContentSetting setting) {
394 if (profile()) {
395 profile()->GetHostContentSettingsMap()->AddExceptionForURL(
396 bubble_content().radio_group.url,
397 bubble_content().radio_group.url,
398 content_type(),
399 setting);
403 void ContentSettingSingleRadioGroup::OnRadioClicked(int radio_index) {
404 selected_item_ = radio_index;
407 class ContentSettingCookiesBubbleModel : public ContentSettingSingleRadioGroup {
408 public:
409 ContentSettingCookiesBubbleModel(Delegate* delegate,
410 WebContents* web_contents,
411 Profile* profile,
412 ContentSettingsType content_type);
414 virtual ~ContentSettingCookiesBubbleModel();
416 private:
417 virtual void OnCustomLinkClicked() OVERRIDE;
420 ContentSettingCookiesBubbleModel::ContentSettingCookiesBubbleModel(
421 Delegate* delegate,
422 WebContents* web_contents,
423 Profile* profile,
424 ContentSettingsType content_type)
425 : ContentSettingSingleRadioGroup(
426 delegate, web_contents, profile, content_type) {
427 DCHECK_EQ(CONTENT_SETTINGS_TYPE_COOKIES, content_type);
428 set_custom_link_enabled(true);
431 ContentSettingCookiesBubbleModel::~ContentSettingCookiesBubbleModel() {
432 // On some plattforms e.g. MacOS X it is possible to close a tab while the
433 // cookies settings bubble is open. This resets the web contents to NULL.
434 if (settings_changed() && web_contents()) {
435 CollectedCookiesInfoBarDelegate::Create(
436 InfoBarService::FromWebContents(web_contents()));
440 void ContentSettingCookiesBubbleModel::OnCustomLinkClicked() {
441 if (!web_contents())
442 return;
443 content::NotificationService::current()->Notify(
444 chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN,
445 content::Source<TabSpecificContentSettings>(
446 TabSpecificContentSettings::FromWebContents(web_contents())),
447 content::NotificationService::NoDetails());
448 delegate()->ShowCollectedCookiesDialog(web_contents());
451 class ContentSettingPluginBubbleModel : public ContentSettingSingleRadioGroup {
452 public:
453 ContentSettingPluginBubbleModel(Delegate* delegate,
454 WebContents* web_contents,
455 Profile* profile,
456 ContentSettingsType content_type);
458 virtual ~ContentSettingPluginBubbleModel();
460 private:
461 virtual void OnCustomLinkClicked() OVERRIDE;
464 ContentSettingPluginBubbleModel::ContentSettingPluginBubbleModel(
465 Delegate* delegate,
466 WebContents* web_contents,
467 Profile* profile,
468 ContentSettingsType content_type)
469 : ContentSettingSingleRadioGroup(
470 delegate, web_contents, profile, content_type) {
471 DCHECK_EQ(content_type, CONTENT_SETTINGS_TYPE_PLUGINS);
472 // Disable the "Run all plugins this time" link if the setting is managed and
473 // can't be controlled by the user or if the user already clicked on the link
474 // and ran all plugins.
475 set_custom_link_enabled(!setting_is_managed() &&
476 web_contents &&
477 TabSpecificContentSettings::FromWebContents(
478 web_contents)->load_plugins_link_enabled());
481 ContentSettingPluginBubbleModel::~ContentSettingPluginBubbleModel() {
482 if (settings_changed()) {
483 // If the user elected to allow all plugins then run plugins at this time.
484 if (selected_item() == kAllowButtonIndex)
485 OnCustomLinkClicked();
489 void ContentSettingPluginBubbleModel::OnCustomLinkClicked() {
490 content::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble"));
491 DCHECK(web_contents());
492 #if defined(ENABLE_PLUGINS)
493 // TODO(bauerb): We should send the identifiers of blocked plug-ins here.
494 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
495 web_contents(), true, std::string());
496 #endif
497 set_custom_link_enabled(false);
498 TabSpecificContentSettings::FromWebContents(web_contents())->
499 set_load_plugins_link_enabled(false);
502 class ContentSettingPopupBubbleModel : public ContentSettingSingleRadioGroup {
503 public:
504 ContentSettingPopupBubbleModel(Delegate* delegate,
505 WebContents* web_contents,
506 Profile* profile,
507 ContentSettingsType content_type);
508 virtual ~ContentSettingPopupBubbleModel() {}
510 private:
511 void SetPopups();
512 virtual void OnPopupClicked(int index) OVERRIDE;
515 ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel(
516 Delegate* delegate,
517 WebContents* web_contents,
518 Profile* profile,
519 ContentSettingsType content_type)
520 : ContentSettingSingleRadioGroup(
521 delegate, web_contents, profile, content_type) {
522 SetPopups();
526 void ContentSettingPopupBubbleModel::SetPopups() {
527 std::map<int32, GURL> blocked_popups =
528 PopupBlockerTabHelper::FromWebContents(web_contents())
529 ->GetBlockedPopupRequests();
530 for (std::map<int32, GURL>::const_iterator iter = blocked_popups.begin();
531 iter != blocked_popups.end();
532 ++iter) {
533 std::string title(iter->second.spec());
534 // The popup may not have a valid URL.
535 if (title.empty())
536 title = l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE);
537 PopupItem popup_item(
538 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
539 IDR_DEFAULT_FAVICON),
540 title,
541 iter->first);
542 add_popup(popup_item);
546 void ContentSettingPopupBubbleModel::OnPopupClicked(int index) {
547 if (web_contents()) {
548 PopupBlockerTabHelper::FromWebContents(web_contents())->
549 ShowBlockedPopup(bubble_content().popup_items[index].popup_id);
553 // The model of the content settings bubble for media settings.
554 class ContentSettingMediaStreamBubbleModel
555 : public ContentSettingTitleAndLinkModel {
556 public:
557 ContentSettingMediaStreamBubbleModel(Delegate* delegate,
558 WebContents* web_contents,
559 Profile* profile);
561 virtual ~ContentSettingMediaStreamBubbleModel();
563 private:
564 void SetTitle();
565 // Sets the data for the radio buttons of the bubble.
566 void SetRadioGroup();
567 // Sets the data for the media menus of the bubble.
568 void SetMediaMenus();
569 // Updates the camera and microphone setting with the passed |setting|.
570 void UpdateSettings(ContentSetting setting);
571 // Updates the camera and microphone default device with the passed |type|
572 // and device.
573 void UpdateDefaultDeviceForType(content::MediaStreamType type,
574 const std::string& device);
576 // ContentSettingBubbleModel implementation.
577 virtual void OnRadioClicked(int radio_index) OVERRIDE;
578 virtual void OnMediaMenuClicked(content::MediaStreamType type,
579 const std::string& selected_device) OVERRIDE;
581 // The index of the selected radio item.
582 int selected_item_;
583 // The content settings that are associated with the individual radio
584 // buttons.
585 ContentSetting radio_item_setting_[2];
586 // The state of the microphone and camera access.
587 TabSpecificContentSettings::MicrophoneCameraState state_;
590 ContentSettingMediaStreamBubbleModel::ContentSettingMediaStreamBubbleModel(
591 Delegate* delegate,
592 WebContents* web_contents,
593 Profile* profile)
594 : ContentSettingTitleAndLinkModel(
595 delegate, web_contents, profile, CONTENT_SETTINGS_TYPE_MEDIASTREAM),
596 selected_item_(0),
597 state_(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED) {
598 DCHECK(profile);
599 // Initialize the content settings associated with the individual radio
600 // buttons.
601 radio_item_setting_[0] = CONTENT_SETTING_ASK;
602 radio_item_setting_[1] = CONTENT_SETTING_BLOCK;
604 TabSpecificContentSettings* content_settings =
605 TabSpecificContentSettings::FromWebContents(web_contents);
606 state_ = content_settings->GetMicrophoneCameraState();
608 SetTitle();
609 SetRadioGroup();
610 SetMediaMenus();
613 ContentSettingMediaStreamBubbleModel::~ContentSettingMediaStreamBubbleModel() {
614 // On some platforms (e.g. MacOS X) it is possible to close a tab while the
615 // media stream bubble is open. This resets the web contents to NULL.
616 if (!web_contents())
617 return;
619 bool media_setting_changed = false;
620 for (MediaMenuMap::const_iterator it = bubble_content().media_menus.begin();
621 it != bubble_content().media_menus.end(); ++it) {
622 if (it->second.selected_device.id != it->second.default_device.id) {
623 UpdateDefaultDeviceForType(it->first, it->second.selected_device.id);
624 media_setting_changed = true;
628 // Update the media settings if the radio button selection was changed.
629 if (selected_item_ != bubble_content().radio_group.default_item) {
630 UpdateSettings(radio_item_setting_[selected_item_]);
631 media_setting_changed = true;
634 // Trigger the reload infobar if the media setting has been changed.
635 if (media_setting_changed) {
636 MediaSettingChangedInfoBarDelegate::Create(
637 InfoBarService::FromWebContents(web_contents()));
641 void ContentSettingMediaStreamBubbleModel::SetTitle() {
642 int title_id = 0;
643 switch (state_) {
644 case TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED:
645 // If neither microphone nor camera stream was accessed, then there is no
646 // icon didplayed in the omnibox and no settings bubble availbale. Hence
647 // there is no title.
648 NOTREACHED();
649 return;
650 case TabSpecificContentSettings::MICROPHONE_ACCESSED:
651 title_id = IDS_MICROPHONE_ACCESSED;
652 break;
653 case TabSpecificContentSettings::CAMERA_ACCESSED:
654 title_id = IDS_CAMERA_ACCESSED;
655 break;
656 case TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED:
657 title_id = IDS_MICROPHONE_CAMERA_ALLOWED;
658 break;
659 case TabSpecificContentSettings::MICROPHONE_BLOCKED:
660 title_id = IDS_MICROPHONE_BLOCKED;
661 break;
662 case TabSpecificContentSettings::CAMERA_BLOCKED:
663 title_id = IDS_CAMERA_BLOCKED;
664 break;
665 case TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED:
666 title_id = IDS_MICROPHONE_CAMERA_BLOCKED;
667 break;
669 set_title(l10n_util::GetStringUTF8(title_id));
672 void ContentSettingMediaStreamBubbleModel::SetRadioGroup() {
673 TabSpecificContentSettings* content_settings =
674 TabSpecificContentSettings::FromWebContents(web_contents());
675 GURL url = content_settings->media_stream_access_origin();
676 RadioGroup radio_group;
677 radio_group.url = url;
679 base::string16 display_host_utf16;
680 net::AppendFormattedHost(
681 url,
682 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
683 &display_host_utf16);
684 std::string display_host(base::UTF16ToUTF8(display_host_utf16));
685 if (display_host.empty())
686 display_host = url.spec();
688 int radio_allow_label_id = 0;
689 int radio_block_label_id = 0;
690 switch (state_) {
691 case TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED:
692 NOTREACHED();
693 return;
694 case TabSpecificContentSettings::MICROPHONE_ACCESSED:
695 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION;
696 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK;
697 selected_item_ = 0;
698 break;
699 case TabSpecificContentSettings::CAMERA_ACCESSED:
700 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION;
701 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK;
702 selected_item_ = 0;
703 break;
704 case TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED:
705 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION;
706 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK;
707 selected_item_ = 0;
708 break;
709 case TabSpecificContentSettings::MICROPHONE_BLOCKED:
710 if (url.SchemeIsSecure()) {
711 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_ALLOW;
712 radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
713 } else {
714 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_ASK;
717 radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION;
718 selected_item_ = 1;
719 break;
720 case TabSpecificContentSettings::CAMERA_BLOCKED:
721 if (url.SchemeIsSecure()) {
722 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW;
723 radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
724 } else {
725 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK;
728 radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION;
729 selected_item_ = 1;
730 break;
731 case TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED:
732 if (url.SchemeIsSecure()) {
733 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ALLOW;
734 radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
735 } else {
736 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ASK;
739 radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION;
740 selected_item_ = 1;
741 break;
744 std::string radio_allow_label = l10n_util::GetStringFUTF8(
745 radio_allow_label_id, base::UTF8ToUTF16(display_host));
746 std::string radio_block_label =
747 l10n_util::GetStringUTF8(radio_block_label_id);
749 radio_group.default_item = selected_item_;
750 radio_group.radio_items.push_back(radio_allow_label);
751 radio_group.radio_items.push_back(radio_block_label);
753 set_radio_group(radio_group);
754 set_radio_group_enabled(true);
757 void ContentSettingMediaStreamBubbleModel::UpdateSettings(
758 ContentSetting setting) {
759 if (profile()) {
760 HostContentSettingsMap* content_settings =
761 profile()->GetHostContentSettingsMap();
762 TabSpecificContentSettings* tab_content_settings =
763 TabSpecificContentSettings::FromWebContents(web_contents());
764 // The same patterns must be used as in other places (e.g. the infobar) in
765 // order to override the existing rule. Otherwise a new rule is created.
766 // TODO(markusheintz): Extract to a helper so that there is only a single
767 // place to touch.
768 ContentSettingsPattern primary_pattern =
769 ContentSettingsPattern::FromURLNoWildcard(
770 tab_content_settings->media_stream_access_origin());
771 ContentSettingsPattern secondary_pattern =
772 ContentSettingsPattern::Wildcard();
773 if (state_ == TabSpecificContentSettings::MICROPHONE_ACCESSED ||
774 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
775 state_ == TabSpecificContentSettings::MICROPHONE_BLOCKED ||
776 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED) {
777 content_settings->SetContentSetting(
778 primary_pattern, secondary_pattern,
779 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string(), setting);
781 if (state_ == TabSpecificContentSettings::CAMERA_ACCESSED ||
782 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
783 state_ == TabSpecificContentSettings::CAMERA_BLOCKED ||
784 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED) {
785 content_settings->SetContentSetting(
786 primary_pattern, secondary_pattern,
787 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string(), setting);
792 void ContentSettingMediaStreamBubbleModel::UpdateDefaultDeviceForType(
793 content::MediaStreamType type,
794 const std::string& device) {
795 PrefService* prefs = profile()->GetPrefs();
796 if (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
797 prefs->SetString(prefs::kDefaultAudioCaptureDevice, device);
798 } else {
799 DCHECK_EQ(content::MEDIA_DEVICE_VIDEO_CAPTURE, type);
800 prefs->SetString(prefs::kDefaultVideoCaptureDevice, device);
804 void ContentSettingMediaStreamBubbleModel::SetMediaMenus() {
805 TabSpecificContentSettings* content_settings =
806 TabSpecificContentSettings::FromWebContents(web_contents());
807 const std::string& requested_microphone =
808 content_settings->media_stream_requested_audio_device();
809 const std::string& requested_camera =
810 content_settings->media_stream_requested_video_device();
812 // Add microphone menu.
813 PrefService* prefs = profile()->GetPrefs();
814 MediaCaptureDevicesDispatcher* dispatcher =
815 MediaCaptureDevicesDispatcher::GetInstance();
816 const content::MediaStreamDevices& microphones =
817 dispatcher->GetAudioCaptureDevices();
819 bool show_mic_menu =
820 (state_ == TabSpecificContentSettings::MICROPHONE_ACCESSED ||
821 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
822 state_ == TabSpecificContentSettings::MICROPHONE_BLOCKED ||
823 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED);
824 bool show_camera_menu =
825 (state_ == TabSpecificContentSettings::CAMERA_ACCESSED ||
826 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
827 state_ == TabSpecificContentSettings::CAMERA_BLOCKED ||
828 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED);
829 DCHECK(show_mic_menu || show_camera_menu);
831 if (show_mic_menu) {
832 MediaMenu mic_menu;
833 mic_menu.label = l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_MIC_LABEL);
834 if (!microphones.empty()) {
835 std::string preferred_mic;
836 if (requested_microphone.empty()) {
837 preferred_mic = prefs->GetString(prefs::kDefaultAudioCaptureDevice);
838 mic_menu.disabled = false;
839 } else {
840 // Set the |disabled| to true in order to disable the device selection
841 // menu on the media settings bubble. This must be done if the website
842 // manages the microphone devices itself.
843 preferred_mic = requested_microphone;
844 mic_menu.disabled = true;
847 mic_menu.default_device = GetMediaDeviceById(preferred_mic, microphones);
848 mic_menu.selected_device = mic_menu.default_device;
850 add_media_menu(content::MEDIA_DEVICE_AUDIO_CAPTURE, mic_menu);
853 if (show_camera_menu) {
854 const content::MediaStreamDevices& cameras =
855 dispatcher->GetVideoCaptureDevices();
856 MediaMenu camera_menu;
857 camera_menu.label =
858 l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_CAMERA_LABEL);
859 if (!cameras.empty()) {
860 std::string preferred_camera;
861 if (requested_camera.empty()) {
862 preferred_camera = prefs->GetString(prefs::kDefaultVideoCaptureDevice);
863 camera_menu.disabled = false;
864 } else {
865 // Disable the menu since the website is managing the camera devices
866 // itself.
867 preferred_camera = requested_camera;
868 camera_menu.disabled = true;
871 camera_menu.default_device =
872 GetMediaDeviceById(preferred_camera, cameras);
873 camera_menu.selected_device = camera_menu.default_device;
875 add_media_menu(content::MEDIA_DEVICE_VIDEO_CAPTURE, camera_menu);
879 void ContentSettingMediaStreamBubbleModel::OnRadioClicked(int radio_index) {
880 selected_item_ = radio_index;
883 void ContentSettingMediaStreamBubbleModel::OnMediaMenuClicked(
884 content::MediaStreamType type,
885 const std::string& selected_device_id) {
886 DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
887 type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
888 DCHECK_EQ(1U, bubble_content().media_menus.count(type));
889 MediaCaptureDevicesDispatcher* dispatcher =
890 MediaCaptureDevicesDispatcher::GetInstance();
891 const content::MediaStreamDevices& devices =
892 (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) ?
893 dispatcher->GetAudioCaptureDevices() :
894 dispatcher->GetVideoCaptureDevices();
895 set_selected_device(GetMediaDeviceById(selected_device_id, devices));
898 class ContentSettingDomainListBubbleModel
899 : public ContentSettingTitleAndLinkModel {
900 public:
901 ContentSettingDomainListBubbleModel(Delegate* delegate,
902 WebContents* web_contents,
903 Profile* profile,
904 ContentSettingsType content_type);
905 virtual ~ContentSettingDomainListBubbleModel() {}
907 private:
908 void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
909 void SetDomainsAndCustomLink();
910 virtual void OnCustomLinkClicked() OVERRIDE;
913 ContentSettingDomainListBubbleModel::ContentSettingDomainListBubbleModel(
914 Delegate* delegate,
915 WebContents* web_contents,
916 Profile* profile,
917 ContentSettingsType content_type)
918 : ContentSettingTitleAndLinkModel(
919 delegate, web_contents, profile, content_type) {
920 DCHECK_EQ(CONTENT_SETTINGS_TYPE_GEOLOCATION, content_type) <<
921 "SetDomains currently only supports geolocation content type";
922 SetDomainsAndCustomLink();
925 void ContentSettingDomainListBubbleModel::MaybeAddDomainList(
926 const std::set<std::string>& hosts, int title_id) {
927 if (!hosts.empty()) {
928 DomainList domain_list;
929 domain_list.title = l10n_util::GetStringUTF8(title_id);
930 domain_list.hosts = hosts;
931 add_domain_list(domain_list);
935 void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() {
936 TabSpecificContentSettings* content_settings =
937 TabSpecificContentSettings::FromWebContents(web_contents());
938 const ContentSettingsUsagesState& usages =
939 content_settings->geolocation_usages_state();
940 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
941 unsigned int tab_state_flags = 0;
942 usages.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
943 // Divide the tab's current geolocation users into sets according to their
944 // permission state.
945 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
946 IDS_GEOLOCATION_BUBBLE_SECTION_ALLOWED);
948 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
949 IDS_GEOLOCATION_BUBBLE_SECTION_DENIED);
951 if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
952 set_custom_link(l10n_util::GetStringUTF8(
953 IDS_GEOLOCATION_BUBBLE_CLEAR_LINK));
954 set_custom_link_enabled(true);
955 } else if (tab_state_flags &
956 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
957 set_custom_link(l10n_util::GetStringUTF8(
958 IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
962 void ContentSettingDomainListBubbleModel::OnCustomLinkClicked() {
963 if (!web_contents())
964 return;
965 // Reset this embedder's entry to default for each of the requesting
966 // origins currently on the page.
967 const GURL& embedder_url = web_contents()->GetURL();
968 TabSpecificContentSettings* content_settings =
969 TabSpecificContentSettings::FromWebContents(web_contents());
970 const ContentSettingsUsagesState::StateMap& state_map =
971 content_settings->geolocation_usages_state().state_map();
972 HostContentSettingsMap* settings_map =
973 profile()->GetHostContentSettingsMap();
975 for (ContentSettingsUsagesState::StateMap::const_iterator it =
976 state_map.begin(); it != state_map.end(); ++it) {
977 settings_map->SetContentSetting(
978 ContentSettingsPattern::FromURLNoWildcard(it->first),
979 ContentSettingsPattern::FromURLNoWildcard(embedder_url),
980 CONTENT_SETTINGS_TYPE_GEOLOCATION,
981 std::string(),
982 CONTENT_SETTING_DEFAULT);
986 class ContentSettingMixedScriptBubbleModel
987 : public ContentSettingTitleLinkAndCustomModel {
988 public:
989 ContentSettingMixedScriptBubbleModel(Delegate* delegate,
990 WebContents* web_contents,
991 Profile* profile,
992 ContentSettingsType content_type);
994 virtual ~ContentSettingMixedScriptBubbleModel() {}
996 private:
997 virtual void OnCustomLinkClicked() OVERRIDE;
1000 ContentSettingMixedScriptBubbleModel::ContentSettingMixedScriptBubbleModel(
1001 Delegate* delegate,
1002 WebContents* web_contents,
1003 Profile* profile,
1004 ContentSettingsType content_type)
1005 : ContentSettingTitleLinkAndCustomModel(
1006 delegate, web_contents, profile, content_type) {
1007 DCHECK_EQ(content_type, CONTENT_SETTINGS_TYPE_MIXEDSCRIPT);
1008 set_custom_link_enabled(true);
1011 void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
1012 content::RecordAction(UserMetricsAction("MixedScript_LoadAnyway_Bubble"));
1013 DCHECK(web_contents());
1014 web_contents()->SendToAllFrames(
1015 new ChromeViewMsg_SetAllowRunningInsecureContent(MSG_ROUTING_NONE, true));
1016 web_contents()->GetMainFrame()->Send(new ChromeViewMsg_ReloadFrame(
1017 web_contents()->GetMainFrame()->GetRoutingID()));
1020 ContentSettingRPHBubbleModel::ContentSettingRPHBubbleModel(
1021 Delegate* delegate,
1022 WebContents* web_contents,
1023 Profile* profile,
1024 ProtocolHandlerRegistry* registry,
1025 ContentSettingsType content_type)
1026 : ContentSettingTitleAndLinkModel(
1027 delegate, web_contents, profile, content_type),
1028 selected_item_(0),
1029 registry_(registry),
1030 pending_handler_(ProtocolHandler::EmptyProtocolHandler()),
1031 previous_handler_(ProtocolHandler::EmptyProtocolHandler()) {
1033 DCHECK_EQ(CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, content_type);
1035 TabSpecificContentSettings* content_settings =
1036 TabSpecificContentSettings::FromWebContents(web_contents);
1037 pending_handler_ = content_settings->pending_protocol_handler();
1038 previous_handler_ = content_settings->previous_protocol_handler();
1040 base::string16 protocol;
1041 if (pending_handler_.protocol() == "mailto") {
1042 protocol = l10n_util::GetStringUTF16(
1043 IDS_REGISTER_PROTOCOL_HANDLER_MAILTO_NAME);
1044 } else if (pending_handler_.protocol() == "webcal") {
1045 protocol = l10n_util::GetStringUTF16(
1046 IDS_REGISTER_PROTOCOL_HANDLER_WEBCAL_NAME);
1047 } else {
1048 protocol = base::UTF8ToUTF16(pending_handler_.protocol());
1051 // Note that we ignore the |title| parameter.
1052 if (previous_handler_.IsEmpty()) {
1053 set_title(l10n_util::GetStringFUTF8(
1054 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM,
1055 base::UTF8ToUTF16(pending_handler_.url().host()),
1056 protocol));
1057 } else {
1058 set_title(l10n_util::GetStringFUTF8(
1059 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM_REPLACE,
1060 base::UTF8ToUTF16(pending_handler_.url().host()),
1061 protocol,
1062 base::UTF8ToUTF16(previous_handler_.url().host())));
1065 std::string radio_allow_label =
1066 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_ACCEPT);
1067 std::string radio_deny_label =
1068 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_DENY);
1069 std::string radio_ignore_label =
1070 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_IGNORE);
1072 GURL url = web_contents->GetURL();
1073 RadioGroup radio_group;
1074 radio_group.url = url;
1076 radio_group.radio_items.push_back(radio_allow_label);
1077 radio_group.radio_items.push_back(radio_deny_label);
1078 radio_group.radio_items.push_back(radio_ignore_label);
1079 ContentSetting setting =
1080 content_settings->pending_protocol_handler_setting();
1081 if (setting == CONTENT_SETTING_ALLOW)
1082 radio_group.default_item = RPH_ALLOW;
1083 else if (setting == CONTENT_SETTING_BLOCK)
1084 radio_group.default_item = RPH_BLOCK;
1085 else
1086 radio_group.default_item = RPH_IGNORE;
1088 selected_item_ = radio_group.default_item;
1089 set_radio_group_enabled(true);
1090 set_radio_group(radio_group);
1093 void ContentSettingRPHBubbleModel::OnRadioClicked(int radio_index) {
1094 if (selected_item_ == radio_index)
1095 return;
1097 selected_item_ = radio_index;
1099 if (radio_index == RPH_ALLOW)
1100 RegisterProtocolHandler();
1101 else if (radio_index == RPH_BLOCK)
1102 UnregisterProtocolHandler();
1103 else if (radio_index == RPH_IGNORE)
1104 IgnoreProtocolHandler();
1105 else
1106 NOTREACHED();
1109 void ContentSettingRPHBubbleModel::OnDoneClicked() {
1110 // The user has one chance to deal with the RPH content setting UI,
1111 // then we remove it.
1112 TabSpecificContentSettings::FromWebContents(web_contents())->
1113 ClearPendingProtocolHandler();
1114 content::NotificationService::current()->Notify(
1115 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
1116 content::Source<WebContents>(web_contents()),
1117 content::NotificationService::NoDetails());
1120 void ContentSettingRPHBubbleModel::RegisterProtocolHandler() {
1121 // A no-op if the handler hasn't been ignored, but needed in case the user
1122 // selects sequences like register/ignore/register.
1123 registry_->RemoveIgnoredHandler(pending_handler_);
1125 registry_->OnAcceptRegisterProtocolHandler(pending_handler_);
1126 TabSpecificContentSettings::FromWebContents(web_contents())->
1127 set_pending_protocol_handler_setting(CONTENT_SETTING_ALLOW);
1130 void ContentSettingRPHBubbleModel::UnregisterProtocolHandler() {
1131 registry_->OnDenyRegisterProtocolHandler(pending_handler_);
1132 TabSpecificContentSettings::FromWebContents(web_contents())->
1133 set_pending_protocol_handler_setting(CONTENT_SETTING_BLOCK);
1134 ClearOrSetPreviousHandler();
1137 void ContentSettingRPHBubbleModel::IgnoreProtocolHandler() {
1138 registry_->OnIgnoreRegisterProtocolHandler(pending_handler_);
1139 TabSpecificContentSettings::FromWebContents(web_contents())->
1140 set_pending_protocol_handler_setting(CONTENT_SETTING_DEFAULT);
1141 ClearOrSetPreviousHandler();
1144 void ContentSettingRPHBubbleModel::ClearOrSetPreviousHandler() {
1145 if (previous_handler_.IsEmpty()) {
1146 registry_->ClearDefault(pending_handler_.protocol());
1147 } else {
1148 registry_->OnAcceptRegisterProtocolHandler(previous_handler_);
1152 class ContentSettingMidiSysExBubbleModel
1153 : public ContentSettingTitleAndLinkModel {
1154 public:
1155 ContentSettingMidiSysExBubbleModel(Delegate* delegate,
1156 WebContents* web_contents,
1157 Profile* profile,
1158 ContentSettingsType content_type);
1159 virtual ~ContentSettingMidiSysExBubbleModel() {}
1161 private:
1162 void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
1163 void SetDomainsAndCustomLink();
1164 virtual void OnCustomLinkClicked() OVERRIDE;
1167 ContentSettingMidiSysExBubbleModel::ContentSettingMidiSysExBubbleModel(
1168 Delegate* delegate,
1169 WebContents* web_contents,
1170 Profile* profile,
1171 ContentSettingsType content_type)
1172 : ContentSettingTitleAndLinkModel(
1173 delegate, web_contents, profile, content_type) {
1174 DCHECK_EQ(CONTENT_SETTINGS_TYPE_MIDI_SYSEX, content_type);
1175 SetDomainsAndCustomLink();
1178 void ContentSettingMidiSysExBubbleModel::MaybeAddDomainList(
1179 const std::set<std::string>& hosts, int title_id) {
1180 if (!hosts.empty()) {
1181 DomainList domain_list;
1182 domain_list.title = l10n_util::GetStringUTF8(title_id);
1183 domain_list.hosts = hosts;
1184 add_domain_list(domain_list);
1188 void ContentSettingMidiSysExBubbleModel::SetDomainsAndCustomLink() {
1189 TabSpecificContentSettings* content_settings =
1190 TabSpecificContentSettings::FromWebContents(web_contents());
1191 const ContentSettingsUsagesState& usages_state =
1192 content_settings->midi_usages_state();
1193 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
1194 unsigned int tab_state_flags = 0;
1195 usages_state.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
1196 // Divide the tab's current MIDI sysex users into sets according to their
1197 // permission state.
1198 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
1199 IDS_MIDI_SYSEX_BUBBLE_ALLOWED);
1201 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
1202 IDS_MIDI_SYSEX_BUBBLE_DENIED);
1204 if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
1205 set_custom_link(l10n_util::GetStringUTF8(
1206 IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK));
1207 set_custom_link_enabled(true);
1208 } else if (tab_state_flags &
1209 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
1210 set_custom_link(l10n_util::GetStringUTF8(
1211 IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
1215 void ContentSettingMidiSysExBubbleModel::OnCustomLinkClicked() {
1216 if (!web_contents())
1217 return;
1218 // Reset this embedder's entry to default for each of the requesting
1219 // origins currently on the page.
1220 TabSpecificContentSettings* content_settings =
1221 TabSpecificContentSettings::FromWebContents(web_contents());
1222 const ContentSettingsUsagesState::StateMap& state_map =
1223 content_settings->midi_usages_state().state_map();
1224 HostContentSettingsMap* settings_map =
1225 profile()->GetHostContentSettingsMap();
1227 for (ContentSettingsUsagesState::StateMap::const_iterator it =
1228 state_map.begin(); it != state_map.end(); ++it) {
1229 settings_map->SetContentSetting(
1230 ContentSettingsPattern::FromURLNoWildcard(it->first),
1231 ContentSettingsPattern::Wildcard(),
1232 CONTENT_SETTINGS_TYPE_MIDI_SYSEX,
1233 std::string(),
1234 CONTENT_SETTING_DEFAULT);
1238 // static
1239 ContentSettingBubbleModel*
1240 ContentSettingBubbleModel::CreateContentSettingBubbleModel(
1241 Delegate* delegate,
1242 WebContents* web_contents,
1243 Profile* profile,
1244 ContentSettingsType content_type) {
1245 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES) {
1246 return new ContentSettingCookiesBubbleModel(delegate, web_contents, profile,
1247 content_type);
1249 if (content_type == CONTENT_SETTINGS_TYPE_POPUPS) {
1250 return new ContentSettingPopupBubbleModel(delegate, web_contents, profile,
1251 content_type);
1253 if (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
1254 return new ContentSettingDomainListBubbleModel(delegate, web_contents,
1255 profile, content_type);
1257 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM) {
1258 return new ContentSettingMediaStreamBubbleModel(delegate, web_contents,
1259 profile);
1261 if (content_type == CONTENT_SETTINGS_TYPE_PLUGINS) {
1262 return new ContentSettingPluginBubbleModel(delegate, web_contents, profile,
1263 content_type);
1265 if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT) {
1266 return new ContentSettingMixedScriptBubbleModel(delegate, web_contents,
1267 profile, content_type);
1269 if (content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS) {
1270 ProtocolHandlerRegistry* registry =
1271 ProtocolHandlerRegistryFactory::GetForBrowserContext(profile);
1272 return new ContentSettingRPHBubbleModel(delegate, web_contents, profile,
1273 registry, content_type);
1275 if (content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
1276 return new ContentSettingMidiSysExBubbleModel(delegate, web_contents,
1277 profile, content_type);
1279 return new ContentSettingSingleRadioGroup(delegate, web_contents, profile,
1280 content_type);
1283 ContentSettingBubbleModel::ContentSettingBubbleModel(
1284 WebContents* web_contents,
1285 Profile* profile,
1286 ContentSettingsType content_type)
1287 : web_contents_(web_contents),
1288 profile_(profile),
1289 content_type_(content_type),
1290 setting_is_managed_(false) {
1291 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
1292 content::Source<WebContents>(web_contents));
1293 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
1294 content::Source<Profile>(profile_));
1297 ContentSettingBubbleModel::~ContentSettingBubbleModel() {
1300 ContentSettingBubbleModel::RadioGroup::RadioGroup() : default_item(0) {}
1302 ContentSettingBubbleModel::RadioGroup::~RadioGroup() {}
1304 ContentSettingBubbleModel::DomainList::DomainList() {}
1306 ContentSettingBubbleModel::DomainList::~DomainList() {}
1308 ContentSettingBubbleModel::MediaMenu::MediaMenu() : disabled(false) {}
1310 ContentSettingBubbleModel::MediaMenu::~MediaMenu() {}
1312 ContentSettingBubbleModel::BubbleContent::BubbleContent()
1313 : radio_group_enabled(false),
1314 custom_link_enabled(false) {
1317 ContentSettingBubbleModel::BubbleContent::~BubbleContent() {}
1319 void ContentSettingBubbleModel::Observe(
1320 int type,
1321 const content::NotificationSource& source,
1322 const content::NotificationDetails& details) {
1323 if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) {
1324 DCHECK_EQ(web_contents_,
1325 content::Source<WebContents>(source).ptr());
1326 web_contents_ = NULL;
1327 } else {
1328 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
1329 DCHECK_EQ(profile_, content::Source<Profile>(source).ptr());
1330 profile_ = NULL;