Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / content_settings / content_setting_bubble_model.cc
blob3b58ae73287b1e888bdb5019f6c7636d2ae9cb43
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
7 #include "base/command_line.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/content_settings/content_settings_utils.h"
12 #include "chrome/browser/content_settings/cookie_settings.h"
13 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
14 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
15 #include "chrome/browser/favicon/favicon_tab_helper.h"
16 #include "chrome/browser/infobars/infobar_service.h"
17 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
18 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h"
21 #include "chrome/browser/ui/browser_navigator.h"
22 #include "chrome/browser/ui/collected_cookies_infobar_delegate.h"
23 #include "chrome/browser/ui/content_settings/content_setting_bubble_model_delegate.h"
24 #include "chrome/browser/ui/content_settings/media_setting_changed_infobar_delegate.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/content_settings.h"
27 #include "chrome/common/pref_names.h"
28 #include "chrome/common/render_messages.h"
29 #include "content/public/browser/notification_service.h"
30 #include "content/public/browser/render_process_host.h"
31 #include "content/public/browser/render_view_host.h"
32 #include "content/public/browser/user_metrics.h"
33 #include "content/public/browser/web_contents.h"
34 #include "content/public/browser/web_contents_delegate.h"
35 #include "grit/generated_resources.h"
36 #include "grit/theme_resources.h"
37 #include "grit/ui_resources.h"
38 #include "net/base/net_util.h"
39 #include "ui/base/l10n/l10n_util.h"
40 #include "ui/base/resource/resource_bundle.h"
42 using base::UserMetricsAction;
43 using content::WebContents;
44 using content_settings::SettingInfo;
45 using content_settings::SettingSource;
46 using content_settings::SETTING_SOURCE_USER;
47 using content_settings::SETTING_SOURCE_NONE;
49 namespace {
51 const int kAllowButtonIndex = 0;
53 struct ContentSettingsTypeIdEntry {
54 ContentSettingsType type;
55 int id;
58 int GetIdForContentType(const ContentSettingsTypeIdEntry* entries,
59 size_t num_entries,
60 ContentSettingsType type) {
61 for (size_t i = 0; i < num_entries; ++i) {
62 if (entries[i].type == type)
63 return entries[i].id;
65 return 0;
68 const content::MediaStreamDevice& GetMediaDeviceById(
69 const std::string& device_id,
70 const content::MediaStreamDevices& devices) {
71 DCHECK(!devices.empty());
72 for (content::MediaStreamDevices::const_iterator it = devices.begin();
73 it != devices.end(); ++it) {
74 if (it->id == device_id)
75 return *(it);
78 // A device with the |device_id| was not found. It is likely that the device
79 // has been unplugged from the OS. Return the first device as the default
80 // device.
81 return *devices.begin();
84 } // namespace
86 ContentSettingTitleAndLinkModel::ContentSettingTitleAndLinkModel(
87 Delegate* delegate,
88 WebContents* web_contents,
89 Profile* profile,
90 ContentSettingsType content_type)
91 : ContentSettingBubbleModel(web_contents, profile, content_type),
92 delegate_(delegate) {
93 // Notifications do not have a bubble.
94 DCHECK_NE(content_type, CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
95 SetTitle();
96 SetManageLink();
99 void ContentSettingTitleAndLinkModel::SetTitle() {
100 static const ContentSettingsTypeIdEntry kBlockedTitleIDs[] = {
101 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_TITLE},
102 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_TITLE},
103 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_TITLE},
104 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_MESSAGE},
105 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_TITLE},
106 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT,
107 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT},
108 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER,
109 IDS_BLOCKED_PPAPI_BROKER_TITLE},
110 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_TITLE},
112 // Fields as for kBlockedTitleIDs, above.
113 static const ContentSettingsTypeIdEntry kAccessedTitleIDs[] = {
114 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_ACCESSED_COOKIES_TITLE},
115 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_TITLE},
116 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_TITLE},
118 const ContentSettingsTypeIdEntry *title_ids = kBlockedTitleIDs;
119 size_t num_title_ids = arraysize(kBlockedTitleIDs);
120 if (web_contents() &&
121 TabSpecificContentSettings::FromWebContents(
122 web_contents())->IsContentAllowed(content_type()) &&
123 !TabSpecificContentSettings::FromWebContents(
124 web_contents())->IsContentBlocked(content_type())) {
125 title_ids = kAccessedTitleIDs;
126 num_title_ids = arraysize(kAccessedTitleIDs);
128 int title_id =
129 GetIdForContentType(title_ids, num_title_ids, content_type());
130 if (title_id)
131 set_title(l10n_util::GetStringUTF8(title_id));
134 void ContentSettingTitleAndLinkModel::SetManageLink() {
135 static const ContentSettingsTypeIdEntry kLinkIDs[] = {
136 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_LINK},
137 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_LINK},
138 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_LINK},
139 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LINK},
140 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_LINK},
141 {CONTENT_SETTINGS_TYPE_GEOLOCATION, IDS_GEOLOCATION_BUBBLE_MANAGE_LINK},
142 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_LEARN_MORE},
143 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, IDS_HANDLERS_BUBBLE_MANAGE_LINK},
144 {CONTENT_SETTINGS_TYPE_MEDIASTREAM, IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK},
145 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_PPAPI_BROKER_BUBBLE_MANAGE_LINK},
146 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOADS_LINK},
147 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX, IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK},
149 set_manage_link(l10n_util::GetStringUTF8(
150 GetIdForContentType(kLinkIDs, arraysize(kLinkIDs), content_type())));
153 void ContentSettingTitleAndLinkModel::OnManageLinkClicked() {
154 if (delegate_)
155 delegate_->ShowContentSettingsPage(content_type());
158 class ContentSettingTitleLinkAndCustomModel
159 : public ContentSettingTitleAndLinkModel {
160 public:
161 ContentSettingTitleLinkAndCustomModel(Delegate* delegate,
162 WebContents* web_contents,
163 Profile* profile,
164 ContentSettingsType content_type);
165 virtual ~ContentSettingTitleLinkAndCustomModel() {}
167 private:
168 void SetCustomLink();
169 virtual void OnCustomLinkClicked() OVERRIDE {}
172 ContentSettingTitleLinkAndCustomModel::ContentSettingTitleLinkAndCustomModel(
173 Delegate* delegate,
174 WebContents* web_contents,
175 Profile* profile,
176 ContentSettingsType content_type)
177 : ContentSettingTitleAndLinkModel(
178 delegate, web_contents, profile, content_type) {
179 SetCustomLink();
182 void ContentSettingTitleLinkAndCustomModel::SetCustomLink() {
183 static const ContentSettingsTypeIdEntry kCustomIDs[] = {
184 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_INFO},
185 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LOAD_ALL},
186 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_ALLOW_INSECURE_CONTENT_BUTTON},
188 int custom_link_id =
189 GetIdForContentType(kCustomIDs, arraysize(kCustomIDs), content_type());
190 if (custom_link_id)
191 set_custom_link(l10n_util::GetStringUTF8(custom_link_id));
194 class ContentSettingSingleRadioGroup
195 : public ContentSettingTitleLinkAndCustomModel {
196 public:
197 ContentSettingSingleRadioGroup(Delegate* delegate,
198 WebContents* web_contents,
199 Profile* profile,
200 ContentSettingsType content_type);
201 virtual ~ContentSettingSingleRadioGroup();
203 protected:
204 bool settings_changed() const;
205 int selected_item() const { return selected_item_; }
207 private:
208 void SetRadioGroup();
209 void AddException(ContentSetting setting);
210 virtual void OnRadioClicked(int radio_index) OVERRIDE;
212 ContentSetting block_setting_;
213 int selected_item_;
216 ContentSettingSingleRadioGroup::ContentSettingSingleRadioGroup(
217 Delegate* delegate,
218 WebContents* web_contents,
219 Profile* profile,
220 ContentSettingsType content_type)
221 : ContentSettingTitleLinkAndCustomModel(delegate, web_contents, profile,
222 content_type),
223 block_setting_(CONTENT_SETTING_BLOCK),
224 selected_item_(0) {
225 SetRadioGroup();
228 ContentSettingSingleRadioGroup::~ContentSettingSingleRadioGroup() {
229 if (settings_changed()) {
230 ContentSetting setting =
231 selected_item_ == kAllowButtonIndex ?
232 CONTENT_SETTING_ALLOW :
233 block_setting_;
234 AddException(setting);
238 bool ContentSettingSingleRadioGroup::settings_changed() const {
239 return selected_item_ != bubble_content().radio_group.default_item;
242 // Initialize the radio group by setting the appropriate labels for the
243 // content type and setting the default value based on the content setting.
244 void ContentSettingSingleRadioGroup::SetRadioGroup() {
245 GURL url = web_contents()->GetURL();
246 base::string16 display_host;
247 net::AppendFormattedHost(
248 url,
249 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
250 &display_host);
252 if (display_host.empty())
253 display_host = base::ASCIIToUTF16(url.spec());
255 TabSpecificContentSettings* content_settings =
256 TabSpecificContentSettings::FromWebContents(web_contents());
257 bool allowed =
258 !content_settings->IsContentBlocked(content_type());
259 DCHECK(!allowed ||
260 content_settings->IsContentAllowed(content_type()));
262 RadioGroup radio_group;
263 radio_group.url = url;
265 static const ContentSettingsTypeIdEntry kBlockedAllowIDs[] = {
266 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
267 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_UNBLOCK},
268 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_UNBLOCK},
269 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_UNBLOCK_ALL},
270 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_UNBLOCK},
271 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_UNBLOCK},
272 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_UNBLOCK},
274 // Fields as for kBlockedAllowIDs, above.
275 static const ContentSettingsTypeIdEntry kAllowedAllowIDs[] = {
276 // TODO(bauerb): The string shouldn't be "unblock" (they weren't blocked).
277 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
278 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_NO_ACTION},
279 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_NO_ACTION},
282 std::string radio_allow_label;
283 if (allowed) {
284 int resource_id = GetIdForContentType(kAllowedAllowIDs,
285 arraysize(kAllowedAllowIDs),
286 content_type());
287 radio_allow_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
288 l10n_util::GetStringFUTF8(resource_id, display_host) :
289 l10n_util::GetStringUTF8(resource_id);
290 } else {
291 radio_allow_label = l10n_util::GetStringFUTF8(
292 GetIdForContentType(kBlockedAllowIDs, arraysize(kBlockedAllowIDs),
293 content_type()),
294 display_host);
297 static const ContentSettingsTypeIdEntry kBlockedBlockIDs[] = {
298 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
299 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_NO_ACTION},
300 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_NO_ACTION},
301 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_NO_ACTION},
302 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_NO_ACTION},
303 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_NO_ACTION},
304 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_NO_ACTION},
306 static const ContentSettingsTypeIdEntry kAllowedBlockIDs[] = {
307 // TODO(bauerb): The string should say "block".
308 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
309 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_BLOCK},
310 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_BLOCK},
313 std::string radio_block_label;
314 if (allowed) {
315 int resource_id = GetIdForContentType(kAllowedBlockIDs,
316 arraysize(kAllowedBlockIDs),
317 content_type());
318 radio_block_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
319 l10n_util::GetStringUTF8(resource_id) :
320 l10n_util::GetStringFUTF8(resource_id, display_host);
321 } else {
322 radio_block_label = l10n_util::GetStringUTF8(
323 GetIdForContentType(kBlockedBlockIDs, arraysize(kBlockedBlockIDs),
324 content_type()));
327 radio_group.radio_items.push_back(radio_allow_label);
328 radio_group.radio_items.push_back(radio_block_label);
329 ContentSetting setting;
330 SettingSource setting_source = SETTING_SOURCE_NONE;
331 bool setting_is_wildcard = false;
333 if (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) {
334 CookieSettings* cookie_settings =
335 CookieSettings::Factory::GetForProfile(profile()).get();
336 setting = cookie_settings->GetCookieSetting(
337 url, url, true, &setting_source);
338 } else {
339 SettingInfo info;
340 HostContentSettingsMap* map = profile()->GetHostContentSettingsMap();
341 scoped_ptr<base::Value> value(map->GetWebsiteSetting(
342 url, url, content_type(), std::string(), &info));
343 setting = content_settings::ValueToContentSetting(value.get());
344 setting_source = info.source;
345 setting_is_wildcard =
346 info.primary_pattern == ContentSettingsPattern::Wildcard() &&
347 info.secondary_pattern == ContentSettingsPattern::Wildcard();
350 if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS &&
351 setting == CONTENT_SETTING_ALLOW &&
352 setting_is_wildcard) {
353 // In the corner case of unrecognized plugins (which are now blocked by
354 // default) we indicate the blocked state in the UI and allow the user to
355 // whitelist.
356 radio_group.default_item = 1;
357 } else if (setting == CONTENT_SETTING_ALLOW) {
358 radio_group.default_item = kAllowButtonIndex;
359 // |block_setting_| is already set to |CONTENT_SETTING_BLOCK|.
360 } else {
361 radio_group.default_item = 1;
362 block_setting_ = setting;
365 set_setting_is_managed(setting_source != SETTING_SOURCE_USER);
366 if (setting_source != SETTING_SOURCE_USER) {
367 set_radio_group_enabled(false);
368 } else {
369 set_radio_group_enabled(true);
371 selected_item_ = radio_group.default_item;
372 set_radio_group(radio_group);
375 void ContentSettingSingleRadioGroup::AddException(ContentSetting setting) {
376 if (profile()) {
377 profile()->GetHostContentSettingsMap()->AddExceptionForURL(
378 bubble_content().radio_group.url,
379 bubble_content().radio_group.url,
380 content_type(),
381 setting);
385 void ContentSettingSingleRadioGroup::OnRadioClicked(int radio_index) {
386 selected_item_ = radio_index;
389 class ContentSettingCookiesBubbleModel : public ContentSettingSingleRadioGroup {
390 public:
391 ContentSettingCookiesBubbleModel(Delegate* delegate,
392 WebContents* web_contents,
393 Profile* profile,
394 ContentSettingsType content_type);
396 virtual ~ContentSettingCookiesBubbleModel();
398 private:
399 virtual void OnCustomLinkClicked() OVERRIDE;
402 ContentSettingCookiesBubbleModel::ContentSettingCookiesBubbleModel(
403 Delegate* delegate,
404 WebContents* web_contents,
405 Profile* profile,
406 ContentSettingsType content_type)
407 : ContentSettingSingleRadioGroup(
408 delegate, web_contents, profile, content_type) {
409 DCHECK_EQ(CONTENT_SETTINGS_TYPE_COOKIES, content_type);
410 set_custom_link_enabled(true);
413 ContentSettingCookiesBubbleModel::~ContentSettingCookiesBubbleModel() {
414 // On some plattforms e.g. MacOS X it is possible to close a tab while the
415 // cookies settings bubble is open. This resets the web contents to NULL.
416 if (settings_changed() && web_contents()) {
417 CollectedCookiesInfoBarDelegate::Create(
418 InfoBarService::FromWebContents(web_contents()));
422 void ContentSettingCookiesBubbleModel::OnCustomLinkClicked() {
423 if (!web_contents())
424 return;
425 content::NotificationService::current()->Notify(
426 chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN,
427 content::Source<TabSpecificContentSettings>(
428 TabSpecificContentSettings::FromWebContents(web_contents())),
429 content::NotificationService::NoDetails());
430 delegate()->ShowCollectedCookiesDialog(web_contents());
433 class ContentSettingPluginBubbleModel : public ContentSettingSingleRadioGroup {
434 public:
435 ContentSettingPluginBubbleModel(Delegate* delegate,
436 WebContents* web_contents,
437 Profile* profile,
438 ContentSettingsType content_type);
440 virtual ~ContentSettingPluginBubbleModel();
442 private:
443 virtual void OnCustomLinkClicked() OVERRIDE;
446 ContentSettingPluginBubbleModel::ContentSettingPluginBubbleModel(
447 Delegate* delegate,
448 WebContents* web_contents,
449 Profile* profile,
450 ContentSettingsType content_type)
451 : ContentSettingSingleRadioGroup(
452 delegate, web_contents, profile, content_type) {
453 DCHECK_EQ(content_type, CONTENT_SETTINGS_TYPE_PLUGINS);
454 // Disable the "Run all plugins this time" link if the setting is managed and
455 // can't be controlled by the user or if the user already clicked on the link
456 // and ran all plugins.
457 set_custom_link_enabled(!setting_is_managed() &&
458 web_contents &&
459 TabSpecificContentSettings::FromWebContents(
460 web_contents)->load_plugins_link_enabled());
463 ContentSettingPluginBubbleModel::~ContentSettingPluginBubbleModel() {
464 if (settings_changed()) {
465 // If the user elected to allow all plugins then run plugins at this time.
466 if (selected_item() == kAllowButtonIndex)
467 OnCustomLinkClicked();
471 void ContentSettingPluginBubbleModel::OnCustomLinkClicked() {
472 content::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble"));
473 DCHECK(web_contents());
474 #if defined(ENABLE_PLUGINS)
475 // TODO(bauerb): We should send the identifiers of blocked plug-ins here.
476 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
477 web_contents(), true, std::string());
478 #endif
479 set_custom_link_enabled(false);
480 TabSpecificContentSettings::FromWebContents(web_contents())->
481 set_load_plugins_link_enabled(false);
484 class ContentSettingPopupBubbleModel : public ContentSettingSingleRadioGroup {
485 public:
486 ContentSettingPopupBubbleModel(Delegate* delegate,
487 WebContents* web_contents,
488 Profile* profile,
489 ContentSettingsType content_type);
490 virtual ~ContentSettingPopupBubbleModel() {}
492 private:
493 void SetPopups();
494 virtual void OnPopupClicked(int index) OVERRIDE;
497 ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel(
498 Delegate* delegate,
499 WebContents* web_contents,
500 Profile* profile,
501 ContentSettingsType content_type)
502 : ContentSettingSingleRadioGroup(
503 delegate, web_contents, profile, content_type) {
504 SetPopups();
508 void ContentSettingPopupBubbleModel::SetPopups() {
509 std::map<int32, GURL> blocked_popups =
510 PopupBlockerTabHelper::FromWebContents(web_contents())
511 ->GetBlockedPopupRequests();
512 for (std::map<int32, GURL>::const_iterator iter = blocked_popups.begin();
513 iter != blocked_popups.end();
514 ++iter) {
515 std::string title(iter->second.spec());
516 // The popup may not have a valid URL.
517 if (title.empty())
518 title = l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE);
519 PopupItem popup_item(
520 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
521 IDR_DEFAULT_FAVICON),
522 title,
523 iter->first);
524 add_popup(popup_item);
528 void ContentSettingPopupBubbleModel::OnPopupClicked(int index) {
529 if (web_contents()) {
530 PopupBlockerTabHelper::FromWebContents(web_contents())->
531 ShowBlockedPopup(bubble_content().popup_items[index].popup_id);
535 // The model of the content settings bubble for media settings.
536 class ContentSettingMediaStreamBubbleModel
537 : public ContentSettingTitleAndLinkModel {
538 public:
539 ContentSettingMediaStreamBubbleModel(Delegate* delegate,
540 WebContents* web_contents,
541 Profile* profile);
543 virtual ~ContentSettingMediaStreamBubbleModel();
545 private:
546 void SetTitle();
547 // Sets the data for the radio buttons of the bubble.
548 void SetRadioGroup();
549 // Sets the data for the media menus of the bubble.
550 void SetMediaMenus();
551 // Updates the camera and microphone setting with the passed |setting|.
552 void UpdateSettings(ContentSetting setting);
553 // Updates the camera and microphone default device with the passed |type|
554 // and device.
555 void UpdateDefaultDeviceForType(content::MediaStreamType type,
556 const std::string& device);
558 // ContentSettingBubbleModel implementation.
559 virtual void OnRadioClicked(int radio_index) OVERRIDE;
560 virtual void OnMediaMenuClicked(content::MediaStreamType type,
561 const std::string& selected_device) OVERRIDE;
563 // The index of the selected radio item.
564 int selected_item_;
565 // The content settings that are associated with the individual radio
566 // buttons.
567 ContentSetting radio_item_setting_[2];
568 // The state of the microphone and camera access.
569 TabSpecificContentSettings::MicrophoneCameraState state_;
572 ContentSettingMediaStreamBubbleModel::ContentSettingMediaStreamBubbleModel(
573 Delegate* delegate,
574 WebContents* web_contents,
575 Profile* profile)
576 : ContentSettingTitleAndLinkModel(
577 delegate, web_contents, profile, CONTENT_SETTINGS_TYPE_MEDIASTREAM),
578 selected_item_(0),
579 state_(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED) {
580 DCHECK(profile);
581 // Initialize the content settings associated with the individual radio
582 // buttons.
583 radio_item_setting_[0] = CONTENT_SETTING_ASK;
584 radio_item_setting_[1] = CONTENT_SETTING_BLOCK;
586 TabSpecificContentSettings* content_settings =
587 TabSpecificContentSettings::FromWebContents(web_contents);
588 state_ = content_settings->GetMicrophoneCameraState();
590 SetTitle();
591 SetRadioGroup();
592 SetMediaMenus();
595 ContentSettingMediaStreamBubbleModel::~ContentSettingMediaStreamBubbleModel() {
596 // On some platforms (e.g. MacOS X) it is possible to close a tab while the
597 // media stream bubble is open. This resets the web contents to NULL.
598 if (!web_contents())
599 return;
601 bool media_setting_changed = false;
602 for (MediaMenuMap::const_iterator it = bubble_content().media_menus.begin();
603 it != bubble_content().media_menus.end(); ++it) {
604 if (it->second.selected_device.id != it->second.default_device.id) {
605 UpdateDefaultDeviceForType(it->first, it->second.selected_device.id);
606 media_setting_changed = true;
610 // Update the media settings if the radio button selection was changed.
611 if (selected_item_ != bubble_content().radio_group.default_item) {
612 UpdateSettings(radio_item_setting_[selected_item_]);
613 media_setting_changed = true;
616 // Trigger the reload infobar if the media setting has been changed.
617 if (media_setting_changed) {
618 MediaSettingChangedInfoBarDelegate::Create(
619 InfoBarService::FromWebContents(web_contents()));
623 void ContentSettingMediaStreamBubbleModel::SetTitle() {
624 int title_id = 0;
625 switch (state_) {
626 case TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED:
627 // If neither microphone nor camera stream was accessed, then there is no
628 // icon didplayed in the omnibox and no settings bubble availbale. Hence
629 // there is no title.
630 NOTREACHED();
631 return;
632 case TabSpecificContentSettings::MICROPHONE_ACCESSED:
633 title_id = IDS_MICROPHONE_ACCESSED;
634 break;
635 case TabSpecificContentSettings::CAMERA_ACCESSED:
636 title_id = IDS_CAMERA_ACCESSED;
637 break;
638 case TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED:
639 title_id = IDS_MICROPHONE_CAMERA_ALLOWED;
640 break;
641 case TabSpecificContentSettings::MICROPHONE_BLOCKED:
642 title_id = IDS_MICROPHONE_BLOCKED;
643 break;
644 case TabSpecificContentSettings::CAMERA_BLOCKED:
645 title_id = IDS_CAMERA_BLOCKED;
646 break;
647 case TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED:
648 title_id = IDS_MICROPHONE_CAMERA_BLOCKED;
649 break;
651 set_title(l10n_util::GetStringUTF8(title_id));
654 void ContentSettingMediaStreamBubbleModel::SetRadioGroup() {
655 TabSpecificContentSettings* content_settings =
656 TabSpecificContentSettings::FromWebContents(web_contents());
657 GURL url = content_settings->media_stream_access_origin();
658 RadioGroup radio_group;
659 radio_group.url = url;
661 base::string16 display_host_utf16;
662 net::AppendFormattedHost(
663 url,
664 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
665 &display_host_utf16);
666 std::string display_host(base::UTF16ToUTF8(display_host_utf16));
667 if (display_host.empty())
668 display_host = url.spec();
670 int radio_allow_label_id = 0;
671 int radio_block_label_id = 0;
672 switch (state_) {
673 case TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED:
674 NOTREACHED();
675 return;
676 case TabSpecificContentSettings::MICROPHONE_ACCESSED:
677 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION;
678 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK;
679 selected_item_ = 0;
680 break;
681 case TabSpecificContentSettings::CAMERA_ACCESSED:
682 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION;
683 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK;
684 selected_item_ = 0;
685 break;
686 case TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED:
687 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION;
688 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK;
689 selected_item_ = 0;
690 break;
691 case TabSpecificContentSettings::MICROPHONE_BLOCKED:
692 if (url.SchemeIsSecure()) {
693 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_ALLOW;
694 radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
695 } else {
696 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_ASK;
699 radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION;
700 selected_item_ = 1;
701 break;
702 case TabSpecificContentSettings::CAMERA_BLOCKED:
703 if (url.SchemeIsSecure()) {
704 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW;
705 radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
706 } else {
707 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK;
710 radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION;
711 selected_item_ = 1;
712 break;
713 case TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED:
714 if (url.SchemeIsSecure()) {
715 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ALLOW;
716 radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
717 } else {
718 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ASK;
721 radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION;
722 selected_item_ = 1;
723 break;
726 std::string radio_allow_label = l10n_util::GetStringFUTF8(
727 radio_allow_label_id, base::UTF8ToUTF16(display_host));
728 std::string radio_block_label =
729 l10n_util::GetStringUTF8(radio_block_label_id);
731 radio_group.default_item = selected_item_;
732 radio_group.radio_items.push_back(radio_allow_label);
733 radio_group.radio_items.push_back(radio_block_label);
735 set_radio_group(radio_group);
736 set_radio_group_enabled(true);
739 void ContentSettingMediaStreamBubbleModel::UpdateSettings(
740 ContentSetting setting) {
741 if (profile()) {
742 HostContentSettingsMap* content_settings =
743 profile()->GetHostContentSettingsMap();
744 TabSpecificContentSettings* tab_content_settings =
745 TabSpecificContentSettings::FromWebContents(web_contents());
746 // The same patterns must be used as in other places (e.g. the infobar) in
747 // order to override the existing rule. Otherwise a new rule is created.
748 // TODO(markusheintz): Extract to a helper so that there is only a single
749 // place to touch.
750 ContentSettingsPattern primary_pattern =
751 ContentSettingsPattern::FromURLNoWildcard(
752 tab_content_settings->media_stream_access_origin());
753 ContentSettingsPattern secondary_pattern =
754 ContentSettingsPattern::Wildcard();
755 if (state_ == TabSpecificContentSettings::MICROPHONE_ACCESSED ||
756 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
757 state_ == TabSpecificContentSettings::MICROPHONE_BLOCKED ||
758 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED) {
759 content_settings->SetContentSetting(
760 primary_pattern, secondary_pattern,
761 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string(), setting);
763 if (state_ == TabSpecificContentSettings::CAMERA_ACCESSED ||
764 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
765 state_ == TabSpecificContentSettings::CAMERA_BLOCKED ||
766 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED) {
767 content_settings->SetContentSetting(
768 primary_pattern, secondary_pattern,
769 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string(), setting);
774 void ContentSettingMediaStreamBubbleModel::UpdateDefaultDeviceForType(
775 content::MediaStreamType type,
776 const std::string& device) {
777 PrefService* prefs = profile()->GetPrefs();
778 if (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
779 prefs->SetString(prefs::kDefaultAudioCaptureDevice, device);
780 } else {
781 DCHECK_EQ(content::MEDIA_DEVICE_VIDEO_CAPTURE, type);
782 prefs->SetString(prefs::kDefaultVideoCaptureDevice, device);
786 void ContentSettingMediaStreamBubbleModel::SetMediaMenus() {
787 TabSpecificContentSettings* content_settings =
788 TabSpecificContentSettings::FromWebContents(web_contents());
789 const std::string& requested_microphone =
790 content_settings->media_stream_requested_audio_device();
791 const std::string& requested_camera =
792 content_settings->media_stream_requested_video_device();
794 // Add microphone menu.
795 PrefService* prefs = profile()->GetPrefs();
796 MediaCaptureDevicesDispatcher* dispatcher =
797 MediaCaptureDevicesDispatcher::GetInstance();
798 const content::MediaStreamDevices& microphones =
799 dispatcher->GetAudioCaptureDevices();
801 bool show_mic_menu =
802 (state_ == TabSpecificContentSettings::MICROPHONE_ACCESSED ||
803 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
804 state_ == TabSpecificContentSettings::MICROPHONE_BLOCKED ||
805 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED);
806 bool show_camera_menu =
807 (state_ == TabSpecificContentSettings::CAMERA_ACCESSED ||
808 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
809 state_ == TabSpecificContentSettings::CAMERA_BLOCKED ||
810 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED);
811 DCHECK(show_mic_menu || show_camera_menu);
813 if (show_mic_menu) {
814 MediaMenu mic_menu;
815 mic_menu.label = l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_MIC_LABEL);
816 if (!microphones.empty()) {
817 std::string preferred_mic;
818 if (requested_microphone.empty()) {
819 preferred_mic = prefs->GetString(prefs::kDefaultAudioCaptureDevice);
820 mic_menu.disabled = false;
821 } else {
822 // Set the |disabled| to true in order to disable the device selection
823 // menu on the media settings bubble. This must be done if the website
824 // manages the microphone devices itself.
825 preferred_mic = requested_microphone;
826 mic_menu.disabled = true;
829 mic_menu.default_device = GetMediaDeviceById(preferred_mic, microphones);
830 mic_menu.selected_device = mic_menu.default_device;
832 add_media_menu(content::MEDIA_DEVICE_AUDIO_CAPTURE, mic_menu);
835 if (show_camera_menu) {
836 const content::MediaStreamDevices& cameras =
837 dispatcher->GetVideoCaptureDevices();
838 MediaMenu camera_menu;
839 camera_menu.label =
840 l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_CAMERA_LABEL);
841 if (!cameras.empty()) {
842 std::string preferred_camera;
843 if (requested_camera.empty()) {
844 preferred_camera = prefs->GetString(prefs::kDefaultVideoCaptureDevice);
845 camera_menu.disabled = false;
846 } else {
847 // Disable the menu since the website is managing the camera devices
848 // itself.
849 preferred_camera = requested_camera;
850 camera_menu.disabled = true;
853 camera_menu.default_device =
854 GetMediaDeviceById(preferred_camera, cameras);
855 camera_menu.selected_device = camera_menu.default_device;
857 add_media_menu(content::MEDIA_DEVICE_VIDEO_CAPTURE, camera_menu);
861 void ContentSettingMediaStreamBubbleModel::OnRadioClicked(int radio_index) {
862 selected_item_ = radio_index;
865 void ContentSettingMediaStreamBubbleModel::OnMediaMenuClicked(
866 content::MediaStreamType type,
867 const std::string& selected_device_id) {
868 DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
869 type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
870 DCHECK_EQ(1U, bubble_content().media_menus.count(type));
871 MediaCaptureDevicesDispatcher* dispatcher =
872 MediaCaptureDevicesDispatcher::GetInstance();
873 const content::MediaStreamDevices& devices =
874 (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) ?
875 dispatcher->GetAudioCaptureDevices() :
876 dispatcher->GetVideoCaptureDevices();
877 set_selected_device(GetMediaDeviceById(selected_device_id, devices));
880 class ContentSettingDomainListBubbleModel
881 : public ContentSettingTitleAndLinkModel {
882 public:
883 ContentSettingDomainListBubbleModel(Delegate* delegate,
884 WebContents* web_contents,
885 Profile* profile,
886 ContentSettingsType content_type);
887 virtual ~ContentSettingDomainListBubbleModel() {}
889 private:
890 void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
891 void SetDomainsAndCustomLink();
892 virtual void OnCustomLinkClicked() OVERRIDE;
895 ContentSettingDomainListBubbleModel::ContentSettingDomainListBubbleModel(
896 Delegate* delegate,
897 WebContents* web_contents,
898 Profile* profile,
899 ContentSettingsType content_type)
900 : ContentSettingTitleAndLinkModel(
901 delegate, web_contents, profile, content_type) {
902 DCHECK_EQ(CONTENT_SETTINGS_TYPE_GEOLOCATION, content_type) <<
903 "SetDomains currently only supports geolocation content type";
904 SetDomainsAndCustomLink();
907 void ContentSettingDomainListBubbleModel::MaybeAddDomainList(
908 const std::set<std::string>& hosts, int title_id) {
909 if (!hosts.empty()) {
910 DomainList domain_list;
911 domain_list.title = l10n_util::GetStringUTF8(title_id);
912 domain_list.hosts = hosts;
913 add_domain_list(domain_list);
917 void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() {
918 TabSpecificContentSettings* content_settings =
919 TabSpecificContentSettings::FromWebContents(web_contents());
920 const ContentSettingsUsagesState& usages =
921 content_settings->geolocation_usages_state();
922 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
923 unsigned int tab_state_flags = 0;
924 usages.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
925 // Divide the tab's current geolocation users into sets according to their
926 // permission state.
927 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
928 IDS_GEOLOCATION_BUBBLE_SECTION_ALLOWED);
930 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
931 IDS_GEOLOCATION_BUBBLE_SECTION_DENIED);
933 if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
934 set_custom_link(l10n_util::GetStringUTF8(
935 IDS_GEOLOCATION_BUBBLE_CLEAR_LINK));
936 set_custom_link_enabled(true);
937 } else if (tab_state_flags &
938 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
939 set_custom_link(l10n_util::GetStringUTF8(
940 IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
944 void ContentSettingDomainListBubbleModel::OnCustomLinkClicked() {
945 if (!web_contents())
946 return;
947 // Reset this embedder's entry to default for each of the requesting
948 // origins currently on the page.
949 const GURL& embedder_url = web_contents()->GetURL();
950 TabSpecificContentSettings* content_settings =
951 TabSpecificContentSettings::FromWebContents(web_contents());
952 const ContentSettingsUsagesState::StateMap& state_map =
953 content_settings->geolocation_usages_state().state_map();
954 HostContentSettingsMap* settings_map =
955 profile()->GetHostContentSettingsMap();
957 for (ContentSettingsUsagesState::StateMap::const_iterator it =
958 state_map.begin(); it != state_map.end(); ++it) {
959 settings_map->SetContentSetting(
960 ContentSettingsPattern::FromURLNoWildcard(it->first),
961 ContentSettingsPattern::FromURLNoWildcard(embedder_url),
962 CONTENT_SETTINGS_TYPE_GEOLOCATION,
963 std::string(),
964 CONTENT_SETTING_DEFAULT);
968 class ContentSettingMixedScriptBubbleModel
969 : public ContentSettingTitleLinkAndCustomModel {
970 public:
971 ContentSettingMixedScriptBubbleModel(Delegate* delegate,
972 WebContents* web_contents,
973 Profile* profile,
974 ContentSettingsType content_type);
976 virtual ~ContentSettingMixedScriptBubbleModel() {}
978 private:
979 virtual void OnCustomLinkClicked() OVERRIDE;
982 ContentSettingMixedScriptBubbleModel::ContentSettingMixedScriptBubbleModel(
983 Delegate* delegate,
984 WebContents* web_contents,
985 Profile* profile,
986 ContentSettingsType content_type)
987 : ContentSettingTitleLinkAndCustomModel(
988 delegate, web_contents, profile, content_type) {
989 DCHECK_EQ(content_type, CONTENT_SETTINGS_TYPE_MIXEDSCRIPT);
990 set_custom_link_enabled(true);
993 void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
994 content::RecordAction(UserMetricsAction("MixedScript_LoadAnyway_Bubble"));
995 DCHECK(web_contents());
996 content::RenderViewHost* host = web_contents()->GetRenderViewHost();
997 host->Send(new ChromeViewMsg_SetAllowRunningInsecureContent(
998 host->GetRoutingID(), true));
1001 ContentSettingRPHBubbleModel::ContentSettingRPHBubbleModel(
1002 Delegate* delegate,
1003 WebContents* web_contents,
1004 Profile* profile,
1005 ProtocolHandlerRegistry* registry,
1006 ContentSettingsType content_type)
1007 : ContentSettingTitleAndLinkModel(
1008 delegate, web_contents, profile, content_type),
1009 selected_item_(0),
1010 registry_(registry),
1011 pending_handler_(ProtocolHandler::EmptyProtocolHandler()),
1012 previous_handler_(ProtocolHandler::EmptyProtocolHandler()) {
1014 DCHECK_EQ(CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, content_type);
1016 TabSpecificContentSettings* content_settings =
1017 TabSpecificContentSettings::FromWebContents(web_contents);
1018 pending_handler_ = content_settings->pending_protocol_handler();
1019 previous_handler_ = content_settings->previous_protocol_handler();
1021 base::string16 protocol;
1022 if (pending_handler_.protocol() == "mailto") {
1023 protocol = l10n_util::GetStringUTF16(
1024 IDS_REGISTER_PROTOCOL_HANDLER_MAILTO_NAME);
1025 } else if (pending_handler_.protocol() == "webcal") {
1026 protocol = l10n_util::GetStringUTF16(
1027 IDS_REGISTER_PROTOCOL_HANDLER_WEBCAL_NAME);
1028 } else {
1029 protocol = base::UTF8ToUTF16(pending_handler_.protocol());
1032 if (previous_handler_.IsEmpty()) {
1033 set_title(l10n_util::GetStringFUTF8(
1034 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM,
1035 pending_handler_.title(),
1036 base::UTF8ToUTF16(pending_handler_.url().host()),
1037 protocol));
1038 } else {
1039 set_title(l10n_util::GetStringFUTF8(
1040 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM_REPLACE,
1041 pending_handler_.title(),
1042 base::UTF8ToUTF16(pending_handler_.url().host()),
1043 protocol, previous_handler_.title()));
1046 std::string radio_allow_label =
1047 l10n_util::GetStringFUTF8(IDS_REGISTER_PROTOCOL_HANDLER_ACCEPT,
1048 pending_handler_.title());
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 // TODO(toyoshim): Should share as many code with geolocation as possible.
1135 class ContentSettingMIDISysExBubbleModel
1136 : public ContentSettingTitleAndLinkModel {
1137 public:
1138 ContentSettingMIDISysExBubbleModel(Delegate* delegate,
1139 WebContents* web_contents,
1140 Profile* profile,
1141 ContentSettingsType content_type);
1142 virtual ~ContentSettingMIDISysExBubbleModel() {}
1144 private:
1145 void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
1146 void SetDomainsAndCustomLink();
1147 virtual void OnCustomLinkClicked() OVERRIDE;
1150 ContentSettingMIDISysExBubbleModel::ContentSettingMIDISysExBubbleModel(
1151 Delegate* delegate,
1152 WebContents* web_contents,
1153 Profile* profile,
1154 ContentSettingsType content_type)
1155 : ContentSettingTitleAndLinkModel(
1156 delegate, web_contents, profile, content_type) {
1157 DCHECK_EQ(CONTENT_SETTINGS_TYPE_MIDI_SYSEX, content_type);
1158 SetDomainsAndCustomLink();
1161 void ContentSettingMIDISysExBubbleModel::MaybeAddDomainList(
1162 const std::set<std::string>& hosts, int title_id) {
1163 if (!hosts.empty()) {
1164 DomainList domain_list;
1165 domain_list.title = l10n_util::GetStringUTF8(title_id);
1166 domain_list.hosts = hosts;
1167 add_domain_list(domain_list);
1171 void ContentSettingMIDISysExBubbleModel::SetDomainsAndCustomLink() {
1172 TabSpecificContentSettings* content_settings =
1173 TabSpecificContentSettings::FromWebContents(web_contents());
1174 const ContentSettingsUsagesState& usages_state =
1175 content_settings->midi_usages_state();
1176 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
1177 unsigned int tab_state_flags = 0;
1178 usages_state.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
1179 // Divide the tab's current MIDI sysex users into sets according to their
1180 // permission state.
1181 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
1182 IDS_MIDI_SYSEX_BUBBLE_ALLOWED);
1184 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
1185 IDS_MIDI_SYSEX_BUBBLE_DENIED);
1187 if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
1188 set_custom_link(l10n_util::GetStringUTF8(
1189 IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK));
1190 set_custom_link_enabled(true);
1191 } else if (tab_state_flags &
1192 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
1193 set_custom_link(l10n_util::GetStringUTF8(
1194 IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
1198 void ContentSettingMIDISysExBubbleModel::OnCustomLinkClicked() {
1199 if (!web_contents())
1200 return;
1201 // Reset this embedder's entry to default for each of the requesting
1202 // origins currently on the page.
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::Wildcard(),
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::GetForProfile(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;