Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / ui / content_settings / content_setting_bubble_model.cc
blob9806d92861a33b6c62dc1d8dafedd30c02fbb1ba
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 "grit/ui_resources.h"
39 #include "net/base/net_util.h"
40 #include "ui/base/l10n/l10n_util.h"
41 #include "ui/base/resource/resource_bundle.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();
100 void ContentSettingTitleAndLinkModel::SetTitle() {
101 static const ContentSettingsTypeIdEntry kBlockedTitleIDs[] = {
102 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_TITLE},
103 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_TITLE},
104 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_TITLE},
105 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_MESSAGE},
106 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_TITLE},
107 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT,
108 IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT},
109 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER,
110 IDS_BLOCKED_PPAPI_BROKER_TITLE},
111 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_TITLE},
113 // Fields as for kBlockedTitleIDs, above.
114 static const ContentSettingsTypeIdEntry kAccessedTitleIDs[] = {
115 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_ACCESSED_COOKIES_TITLE},
116 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_TITLE},
117 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_TITLE},
119 const ContentSettingsTypeIdEntry *title_ids = kBlockedTitleIDs;
120 size_t num_title_ids = arraysize(kBlockedTitleIDs);
121 if (web_contents() &&
122 TabSpecificContentSettings::FromWebContents(
123 web_contents())->IsContentAllowed(content_type()) &&
124 !TabSpecificContentSettings::FromWebContents(
125 web_contents())->IsContentBlocked(content_type())) {
126 title_ids = kAccessedTitleIDs;
127 num_title_ids = arraysize(kAccessedTitleIDs);
129 int title_id =
130 GetIdForContentType(title_ids, num_title_ids, content_type());
131 if (title_id)
132 set_title(l10n_util::GetStringUTF8(title_id));
135 void ContentSettingTitleAndLinkModel::SetManageLink() {
136 static const ContentSettingsTypeIdEntry kLinkIDs[] = {
137 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_LINK},
138 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_LINK},
139 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_LINK},
140 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LINK},
141 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_LINK},
142 {CONTENT_SETTINGS_TYPE_GEOLOCATION, IDS_GEOLOCATION_BUBBLE_MANAGE_LINK},
143 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_LEARN_MORE},
144 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, IDS_HANDLERS_BUBBLE_MANAGE_LINK},
145 {CONTENT_SETTINGS_TYPE_MEDIASTREAM, IDS_MEDIASTREAM_BUBBLE_MANAGE_LINK},
146 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_PPAPI_BROKER_BUBBLE_MANAGE_LINK},
147 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOADS_LINK},
148 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX, IDS_MIDI_SYSEX_BUBBLE_MANAGE_LINK},
150 set_manage_link(l10n_util::GetStringUTF8(
151 GetIdForContentType(kLinkIDs, arraysize(kLinkIDs), content_type())));
154 void ContentSettingTitleAndLinkModel::OnManageLinkClicked() {
155 if (delegate_)
156 delegate_->ShowContentSettingsPage(content_type());
159 class ContentSettingTitleLinkAndCustomModel
160 : public ContentSettingTitleAndLinkModel {
161 public:
162 ContentSettingTitleLinkAndCustomModel(Delegate* delegate,
163 WebContents* web_contents,
164 Profile* profile,
165 ContentSettingsType content_type);
166 virtual ~ContentSettingTitleLinkAndCustomModel() {}
168 private:
169 void SetCustomLink();
170 virtual void OnCustomLinkClicked() OVERRIDE {}
173 ContentSettingTitleLinkAndCustomModel::ContentSettingTitleLinkAndCustomModel(
174 Delegate* delegate,
175 WebContents* web_contents,
176 Profile* profile,
177 ContentSettingsType content_type)
178 : ContentSettingTitleAndLinkModel(
179 delegate, web_contents, profile, content_type) {
180 SetCustomLink();
183 void ContentSettingTitleLinkAndCustomModel::SetCustomLink() {
184 static const ContentSettingsTypeIdEntry kCustomIDs[] = {
185 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_INFO},
186 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_LOAD_ALL},
187 {CONTENT_SETTINGS_TYPE_MIXEDSCRIPT, IDS_ALLOW_INSECURE_CONTENT_BUTTON},
189 int custom_link_id =
190 GetIdForContentType(kCustomIDs, arraysize(kCustomIDs), content_type());
191 if (custom_link_id)
192 set_custom_link(l10n_util::GetStringUTF8(custom_link_id));
195 class ContentSettingSingleRadioGroup
196 : public ContentSettingTitleLinkAndCustomModel {
197 public:
198 ContentSettingSingleRadioGroup(Delegate* delegate,
199 WebContents* web_contents,
200 Profile* profile,
201 ContentSettingsType content_type);
202 virtual ~ContentSettingSingleRadioGroup();
204 protected:
205 bool settings_changed() const;
206 int selected_item() const { return selected_item_; }
208 private:
209 void SetRadioGroup();
210 void AddException(ContentSetting setting);
211 virtual void OnRadioClicked(int radio_index) OVERRIDE;
213 ContentSetting block_setting_;
214 int selected_item_;
217 ContentSettingSingleRadioGroup::ContentSettingSingleRadioGroup(
218 Delegate* delegate,
219 WebContents* web_contents,
220 Profile* profile,
221 ContentSettingsType content_type)
222 : ContentSettingTitleLinkAndCustomModel(delegate, web_contents, profile,
223 content_type),
224 block_setting_(CONTENT_SETTING_BLOCK),
225 selected_item_(0) {
226 SetRadioGroup();
229 ContentSettingSingleRadioGroup::~ContentSettingSingleRadioGroup() {
230 if (settings_changed()) {
231 ContentSetting setting =
232 selected_item_ == kAllowButtonIndex ?
233 CONTENT_SETTING_ALLOW :
234 block_setting_;
235 AddException(setting);
239 bool ContentSettingSingleRadioGroup::settings_changed() const {
240 return selected_item_ != bubble_content().radio_group.default_item;
243 // Initialize the radio group by setting the appropriate labels for the
244 // content type and setting the default value based on the content setting.
245 void ContentSettingSingleRadioGroup::SetRadioGroup() {
246 GURL url = web_contents()->GetURL();
247 base::string16 display_host;
248 net::AppendFormattedHost(
249 url,
250 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
251 &display_host);
253 if (display_host.empty())
254 display_host = base::ASCIIToUTF16(url.spec());
256 TabSpecificContentSettings* content_settings =
257 TabSpecificContentSettings::FromWebContents(web_contents());
258 bool allowed =
259 !content_settings->IsContentBlocked(content_type());
260 DCHECK(!allowed ||
261 content_settings->IsContentAllowed(content_type()));
263 RadioGroup radio_group;
264 radio_group.url = url;
266 static const ContentSettingsTypeIdEntry kBlockedAllowIDs[] = {
267 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
268 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_UNBLOCK},
269 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_UNBLOCK},
270 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_UNBLOCK_ALL},
271 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_UNBLOCK},
272 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_UNBLOCK},
273 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_UNBLOCK},
275 // Fields as for kBlockedAllowIDs, above.
276 static const ContentSettingsTypeIdEntry kAllowedAllowIDs[] = {
277 // TODO(bauerb): The string shouldn't be "unblock" (they weren't blocked).
278 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
279 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_NO_ACTION},
280 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_NO_ACTION},
283 std::string radio_allow_label;
284 if (allowed) {
285 int resource_id = GetIdForContentType(kAllowedAllowIDs,
286 arraysize(kAllowedAllowIDs),
287 content_type());
288 radio_allow_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
289 l10n_util::GetStringFUTF8(resource_id, display_host) :
290 l10n_util::GetStringUTF8(resource_id);
291 } else {
292 radio_allow_label = l10n_util::GetStringFUTF8(
293 GetIdForContentType(kBlockedAllowIDs, arraysize(kBlockedAllowIDs),
294 content_type()),
295 display_host);
298 static const ContentSettingsTypeIdEntry kBlockedBlockIDs[] = {
299 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
300 {CONTENT_SETTINGS_TYPE_IMAGES, IDS_BLOCKED_IMAGES_NO_ACTION},
301 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_NO_ACTION},
302 {CONTENT_SETTINGS_TYPE_PLUGINS, IDS_BLOCKED_PLUGINS_NO_ACTION},
303 {CONTENT_SETTINGS_TYPE_POPUPS, IDS_BLOCKED_POPUPS_NO_ACTION},
304 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_NO_ACTION},
305 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_BLOCKED_DOWNLOAD_NO_ACTION},
307 static const ContentSettingsTypeIdEntry kAllowedBlockIDs[] = {
308 // TODO(bauerb): The string should say "block".
309 {CONTENT_SETTINGS_TYPE_COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
310 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_BLOCK},
311 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, IDS_ALLOWED_DOWNLOAD_BLOCK},
314 std::string radio_block_label;
315 if (allowed) {
316 int resource_id = GetIdForContentType(kAllowedBlockIDs,
317 arraysize(kAllowedBlockIDs),
318 content_type());
319 radio_block_label = (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) ?
320 l10n_util::GetStringUTF8(resource_id) :
321 l10n_util::GetStringFUTF8(resource_id, display_host);
322 } else {
323 radio_block_label = l10n_util::GetStringUTF8(
324 GetIdForContentType(kBlockedBlockIDs, arraysize(kBlockedBlockIDs),
325 content_type()));
328 radio_group.radio_items.push_back(radio_allow_label);
329 radio_group.radio_items.push_back(radio_block_label);
330 ContentSetting setting;
331 SettingSource setting_source = SETTING_SOURCE_NONE;
332 bool setting_is_wildcard = false;
334 if (content_type() == CONTENT_SETTINGS_TYPE_COOKIES) {
335 CookieSettings* cookie_settings =
336 CookieSettings::Factory::GetForProfile(profile()).get();
337 setting = cookie_settings->GetCookieSetting(
338 url, url, true, &setting_source);
339 } else {
340 SettingInfo info;
341 HostContentSettingsMap* map = profile()->GetHostContentSettingsMap();
342 scoped_ptr<base::Value> value(map->GetWebsiteSetting(
343 url, url, content_type(), std::string(), &info));
344 setting = content_settings::ValueToContentSetting(value.get());
345 setting_source = info.source;
346 setting_is_wildcard =
347 info.primary_pattern == ContentSettingsPattern::Wildcard() &&
348 info.secondary_pattern == ContentSettingsPattern::Wildcard();
351 if (content_type() == CONTENT_SETTINGS_TYPE_PLUGINS &&
352 setting == CONTENT_SETTING_ALLOW &&
353 setting_is_wildcard) {
354 // In the corner case of unrecognized plugins (which are now blocked by
355 // default) we indicate the blocked state in the UI and allow the user to
356 // whitelist.
357 radio_group.default_item = 1;
358 } else if (setting == CONTENT_SETTING_ALLOW) {
359 radio_group.default_item = kAllowButtonIndex;
360 // |block_setting_| is already set to |CONTENT_SETTING_BLOCK|.
361 } else {
362 radio_group.default_item = 1;
363 block_setting_ = setting;
366 set_setting_is_managed(setting_source != SETTING_SOURCE_USER);
367 if (setting_source != SETTING_SOURCE_USER) {
368 set_radio_group_enabled(false);
369 } else {
370 set_radio_group_enabled(true);
372 selected_item_ = radio_group.default_item;
373 set_radio_group(radio_group);
376 void ContentSettingSingleRadioGroup::AddException(ContentSetting setting) {
377 if (profile()) {
378 profile()->GetHostContentSettingsMap()->AddExceptionForURL(
379 bubble_content().radio_group.url,
380 bubble_content().radio_group.url,
381 content_type(),
382 setting);
386 void ContentSettingSingleRadioGroup::OnRadioClicked(int radio_index) {
387 selected_item_ = radio_index;
390 class ContentSettingCookiesBubbleModel : public ContentSettingSingleRadioGroup {
391 public:
392 ContentSettingCookiesBubbleModel(Delegate* delegate,
393 WebContents* web_contents,
394 Profile* profile,
395 ContentSettingsType content_type);
397 virtual ~ContentSettingCookiesBubbleModel();
399 private:
400 virtual void OnCustomLinkClicked() OVERRIDE;
403 ContentSettingCookiesBubbleModel::ContentSettingCookiesBubbleModel(
404 Delegate* delegate,
405 WebContents* web_contents,
406 Profile* profile,
407 ContentSettingsType content_type)
408 : ContentSettingSingleRadioGroup(
409 delegate, web_contents, profile, content_type) {
410 DCHECK_EQ(CONTENT_SETTINGS_TYPE_COOKIES, content_type);
411 set_custom_link_enabled(true);
414 ContentSettingCookiesBubbleModel::~ContentSettingCookiesBubbleModel() {
415 // On some plattforms e.g. MacOS X it is possible to close a tab while the
416 // cookies settings bubble is open. This resets the web contents to NULL.
417 if (settings_changed() && web_contents()) {
418 CollectedCookiesInfoBarDelegate::Create(
419 InfoBarService::FromWebContents(web_contents()));
423 void ContentSettingCookiesBubbleModel::OnCustomLinkClicked() {
424 if (!web_contents())
425 return;
426 content::NotificationService::current()->Notify(
427 chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN,
428 content::Source<TabSpecificContentSettings>(
429 TabSpecificContentSettings::FromWebContents(web_contents())),
430 content::NotificationService::NoDetails());
431 delegate()->ShowCollectedCookiesDialog(web_contents());
434 class ContentSettingPluginBubbleModel : public ContentSettingSingleRadioGroup {
435 public:
436 ContentSettingPluginBubbleModel(Delegate* delegate,
437 WebContents* web_contents,
438 Profile* profile,
439 ContentSettingsType content_type);
441 virtual ~ContentSettingPluginBubbleModel();
443 private:
444 virtual void OnCustomLinkClicked() OVERRIDE;
447 ContentSettingPluginBubbleModel::ContentSettingPluginBubbleModel(
448 Delegate* delegate,
449 WebContents* web_contents,
450 Profile* profile,
451 ContentSettingsType content_type)
452 : ContentSettingSingleRadioGroup(
453 delegate, web_contents, profile, content_type) {
454 DCHECK_EQ(content_type, CONTENT_SETTINGS_TYPE_PLUGINS);
455 // Disable the "Run all plugins this time" link if the setting is managed and
456 // can't be controlled by the user or if the user already clicked on the link
457 // and ran all plugins.
458 set_custom_link_enabled(!setting_is_managed() &&
459 web_contents &&
460 TabSpecificContentSettings::FromWebContents(
461 web_contents)->load_plugins_link_enabled());
464 ContentSettingPluginBubbleModel::~ContentSettingPluginBubbleModel() {
465 if (settings_changed()) {
466 // If the user elected to allow all plugins then run plugins at this time.
467 if (selected_item() == kAllowButtonIndex)
468 OnCustomLinkClicked();
472 void ContentSettingPluginBubbleModel::OnCustomLinkClicked() {
473 content::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble"));
474 DCHECK(web_contents());
475 #if defined(ENABLE_PLUGINS)
476 // TODO(bauerb): We should send the identifiers of blocked plug-ins here.
477 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
478 web_contents(), true, std::string());
479 #endif
480 set_custom_link_enabled(false);
481 TabSpecificContentSettings::FromWebContents(web_contents())->
482 set_load_plugins_link_enabled(false);
485 class ContentSettingPopupBubbleModel : public ContentSettingSingleRadioGroup {
486 public:
487 ContentSettingPopupBubbleModel(Delegate* delegate,
488 WebContents* web_contents,
489 Profile* profile,
490 ContentSettingsType content_type);
491 virtual ~ContentSettingPopupBubbleModel() {}
493 private:
494 void SetPopups();
495 virtual void OnPopupClicked(int index) OVERRIDE;
498 ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel(
499 Delegate* delegate,
500 WebContents* web_contents,
501 Profile* profile,
502 ContentSettingsType content_type)
503 : ContentSettingSingleRadioGroup(
504 delegate, web_contents, profile, content_type) {
505 SetPopups();
509 void ContentSettingPopupBubbleModel::SetPopups() {
510 std::map<int32, GURL> blocked_popups =
511 PopupBlockerTabHelper::FromWebContents(web_contents())
512 ->GetBlockedPopupRequests();
513 for (std::map<int32, GURL>::const_iterator iter = blocked_popups.begin();
514 iter != blocked_popups.end();
515 ++iter) {
516 std::string title(iter->second.spec());
517 // The popup may not have a valid URL.
518 if (title.empty())
519 title = l10n_util::GetStringUTF8(IDS_TAB_LOADING_TITLE);
520 PopupItem popup_item(
521 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
522 IDR_DEFAULT_FAVICON),
523 title,
524 iter->first);
525 add_popup(popup_item);
529 void ContentSettingPopupBubbleModel::OnPopupClicked(int index) {
530 if (web_contents()) {
531 PopupBlockerTabHelper::FromWebContents(web_contents())->
532 ShowBlockedPopup(bubble_content().popup_items[index].popup_id);
536 // The model of the content settings bubble for media settings.
537 class ContentSettingMediaStreamBubbleModel
538 : public ContentSettingTitleAndLinkModel {
539 public:
540 ContentSettingMediaStreamBubbleModel(Delegate* delegate,
541 WebContents* web_contents,
542 Profile* profile);
544 virtual ~ContentSettingMediaStreamBubbleModel();
546 private:
547 void SetTitle();
548 // Sets the data for the radio buttons of the bubble.
549 void SetRadioGroup();
550 // Sets the data for the media menus of the bubble.
551 void SetMediaMenus();
552 // Updates the camera and microphone setting with the passed |setting|.
553 void UpdateSettings(ContentSetting setting);
554 // Updates the camera and microphone default device with the passed |type|
555 // and device.
556 void UpdateDefaultDeviceForType(content::MediaStreamType type,
557 const std::string& device);
559 // ContentSettingBubbleModel implementation.
560 virtual void OnRadioClicked(int radio_index) OVERRIDE;
561 virtual void OnMediaMenuClicked(content::MediaStreamType type,
562 const std::string& selected_device) OVERRIDE;
564 // The index of the selected radio item.
565 int selected_item_;
566 // The content settings that are associated with the individual radio
567 // buttons.
568 ContentSetting radio_item_setting_[2];
569 // The state of the microphone and camera access.
570 TabSpecificContentSettings::MicrophoneCameraState state_;
573 ContentSettingMediaStreamBubbleModel::ContentSettingMediaStreamBubbleModel(
574 Delegate* delegate,
575 WebContents* web_contents,
576 Profile* profile)
577 : ContentSettingTitleAndLinkModel(
578 delegate, web_contents, profile, CONTENT_SETTINGS_TYPE_MEDIASTREAM),
579 selected_item_(0),
580 state_(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED) {
581 DCHECK(profile);
582 // Initialize the content settings associated with the individual radio
583 // buttons.
584 radio_item_setting_[0] = CONTENT_SETTING_ASK;
585 radio_item_setting_[1] = CONTENT_SETTING_BLOCK;
587 TabSpecificContentSettings* content_settings =
588 TabSpecificContentSettings::FromWebContents(web_contents);
589 state_ = content_settings->GetMicrophoneCameraState();
591 SetTitle();
592 SetRadioGroup();
593 SetMediaMenus();
596 ContentSettingMediaStreamBubbleModel::~ContentSettingMediaStreamBubbleModel() {
597 // On some platforms (e.g. MacOS X) it is possible to close a tab while the
598 // media stream bubble is open. This resets the web contents to NULL.
599 if (!web_contents())
600 return;
602 bool media_setting_changed = false;
603 for (MediaMenuMap::const_iterator it = bubble_content().media_menus.begin();
604 it != bubble_content().media_menus.end(); ++it) {
605 if (it->second.selected_device.id != it->second.default_device.id) {
606 UpdateDefaultDeviceForType(it->first, it->second.selected_device.id);
607 media_setting_changed = true;
611 // Update the media settings if the radio button selection was changed.
612 if (selected_item_ != bubble_content().radio_group.default_item) {
613 UpdateSettings(radio_item_setting_[selected_item_]);
614 media_setting_changed = true;
617 // Trigger the reload infobar if the media setting has been changed.
618 if (media_setting_changed) {
619 MediaSettingChangedInfoBarDelegate::Create(
620 InfoBarService::FromWebContents(web_contents()));
624 void ContentSettingMediaStreamBubbleModel::SetTitle() {
625 int title_id = 0;
626 switch (state_) {
627 case TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED:
628 // If neither microphone nor camera stream was accessed, then there is no
629 // icon didplayed in the omnibox and no settings bubble availbale. Hence
630 // there is no title.
631 NOTREACHED();
632 return;
633 case TabSpecificContentSettings::MICROPHONE_ACCESSED:
634 title_id = IDS_MICROPHONE_ACCESSED;
635 break;
636 case TabSpecificContentSettings::CAMERA_ACCESSED:
637 title_id = IDS_CAMERA_ACCESSED;
638 break;
639 case TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED:
640 title_id = IDS_MICROPHONE_CAMERA_ALLOWED;
641 break;
642 case TabSpecificContentSettings::MICROPHONE_BLOCKED:
643 title_id = IDS_MICROPHONE_BLOCKED;
644 break;
645 case TabSpecificContentSettings::CAMERA_BLOCKED:
646 title_id = IDS_CAMERA_BLOCKED;
647 break;
648 case TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED:
649 title_id = IDS_MICROPHONE_CAMERA_BLOCKED;
650 break;
652 set_title(l10n_util::GetStringUTF8(title_id));
655 void ContentSettingMediaStreamBubbleModel::SetRadioGroup() {
656 TabSpecificContentSettings* content_settings =
657 TabSpecificContentSettings::FromWebContents(web_contents());
658 GURL url = content_settings->media_stream_access_origin();
659 RadioGroup radio_group;
660 radio_group.url = url;
662 base::string16 display_host_utf16;
663 net::AppendFormattedHost(
664 url,
665 profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
666 &display_host_utf16);
667 std::string display_host(base::UTF16ToUTF8(display_host_utf16));
668 if (display_host.empty())
669 display_host = url.spec();
671 int radio_allow_label_id = 0;
672 int radio_block_label_id = 0;
673 switch (state_) {
674 case TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED:
675 NOTREACHED();
676 return;
677 case TabSpecificContentSettings::MICROPHONE_ACCESSED:
678 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION;
679 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK;
680 selected_item_ = 0;
681 break;
682 case TabSpecificContentSettings::CAMERA_ACCESSED:
683 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION;
684 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK;
685 selected_item_ = 0;
686 break;
687 case TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED:
688 radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION;
689 radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK;
690 selected_item_ = 0;
691 break;
692 case TabSpecificContentSettings::MICROPHONE_BLOCKED:
693 if (url.SchemeIsSecure()) {
694 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_ALLOW;
695 radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
696 } else {
697 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_ASK;
700 radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION;
701 selected_item_ = 1;
702 break;
703 case TabSpecificContentSettings::CAMERA_BLOCKED:
704 if (url.SchemeIsSecure()) {
705 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW;
706 radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
707 } else {
708 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK;
711 radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION;
712 selected_item_ = 1;
713 break;
714 case TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED:
715 if (url.SchemeIsSecure()) {
716 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ALLOW;
717 radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
718 } else {
719 radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ASK;
722 radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION;
723 selected_item_ = 1;
724 break;
727 std::string radio_allow_label = l10n_util::GetStringFUTF8(
728 radio_allow_label_id, base::UTF8ToUTF16(display_host));
729 std::string radio_block_label =
730 l10n_util::GetStringUTF8(radio_block_label_id);
732 radio_group.default_item = selected_item_;
733 radio_group.radio_items.push_back(radio_allow_label);
734 radio_group.radio_items.push_back(radio_block_label);
736 set_radio_group(radio_group);
737 set_radio_group_enabled(true);
740 void ContentSettingMediaStreamBubbleModel::UpdateSettings(
741 ContentSetting setting) {
742 if (profile()) {
743 HostContentSettingsMap* content_settings =
744 profile()->GetHostContentSettingsMap();
745 TabSpecificContentSettings* tab_content_settings =
746 TabSpecificContentSettings::FromWebContents(web_contents());
747 // The same patterns must be used as in other places (e.g. the infobar) in
748 // order to override the existing rule. Otherwise a new rule is created.
749 // TODO(markusheintz): Extract to a helper so that there is only a single
750 // place to touch.
751 ContentSettingsPattern primary_pattern =
752 ContentSettingsPattern::FromURLNoWildcard(
753 tab_content_settings->media_stream_access_origin());
754 ContentSettingsPattern secondary_pattern =
755 ContentSettingsPattern::Wildcard();
756 if (state_ == TabSpecificContentSettings::MICROPHONE_ACCESSED ||
757 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
758 state_ == TabSpecificContentSettings::MICROPHONE_BLOCKED ||
759 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED) {
760 content_settings->SetContentSetting(
761 primary_pattern, secondary_pattern,
762 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string(), setting);
764 if (state_ == TabSpecificContentSettings::CAMERA_ACCESSED ||
765 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
766 state_ == TabSpecificContentSettings::CAMERA_BLOCKED ||
767 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED) {
768 content_settings->SetContentSetting(
769 primary_pattern, secondary_pattern,
770 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string(), setting);
775 void ContentSettingMediaStreamBubbleModel::UpdateDefaultDeviceForType(
776 content::MediaStreamType type,
777 const std::string& device) {
778 PrefService* prefs = profile()->GetPrefs();
779 if (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
780 prefs->SetString(prefs::kDefaultAudioCaptureDevice, device);
781 } else {
782 DCHECK_EQ(content::MEDIA_DEVICE_VIDEO_CAPTURE, type);
783 prefs->SetString(prefs::kDefaultVideoCaptureDevice, device);
787 void ContentSettingMediaStreamBubbleModel::SetMediaMenus() {
788 TabSpecificContentSettings* content_settings =
789 TabSpecificContentSettings::FromWebContents(web_contents());
790 const std::string& requested_microphone =
791 content_settings->media_stream_requested_audio_device();
792 const std::string& requested_camera =
793 content_settings->media_stream_requested_video_device();
795 // Add microphone menu.
796 PrefService* prefs = profile()->GetPrefs();
797 MediaCaptureDevicesDispatcher* dispatcher =
798 MediaCaptureDevicesDispatcher::GetInstance();
799 const content::MediaStreamDevices& microphones =
800 dispatcher->GetAudioCaptureDevices();
802 bool show_mic_menu =
803 (state_ == TabSpecificContentSettings::MICROPHONE_ACCESSED ||
804 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
805 state_ == TabSpecificContentSettings::MICROPHONE_BLOCKED ||
806 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED);
807 bool show_camera_menu =
808 (state_ == TabSpecificContentSettings::CAMERA_ACCESSED ||
809 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_ACCESSED ||
810 state_ == TabSpecificContentSettings::CAMERA_BLOCKED ||
811 state_ == TabSpecificContentSettings::MICROPHONE_CAMERA_BLOCKED);
812 DCHECK(show_mic_menu || show_camera_menu);
814 if (show_mic_menu) {
815 MediaMenu mic_menu;
816 mic_menu.label = l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_MIC_LABEL);
817 if (!microphones.empty()) {
818 std::string preferred_mic;
819 if (requested_microphone.empty()) {
820 preferred_mic = prefs->GetString(prefs::kDefaultAudioCaptureDevice);
821 mic_menu.disabled = false;
822 } else {
823 // Set the |disabled| to true in order to disable the device selection
824 // menu on the media settings bubble. This must be done if the website
825 // manages the microphone devices itself.
826 preferred_mic = requested_microphone;
827 mic_menu.disabled = true;
830 mic_menu.default_device = GetMediaDeviceById(preferred_mic, microphones);
831 mic_menu.selected_device = mic_menu.default_device;
833 add_media_menu(content::MEDIA_DEVICE_AUDIO_CAPTURE, mic_menu);
836 if (show_camera_menu) {
837 const content::MediaStreamDevices& cameras =
838 dispatcher->GetVideoCaptureDevices();
839 MediaMenu camera_menu;
840 camera_menu.label =
841 l10n_util::GetStringUTF8(IDS_MEDIA_SELECTED_CAMERA_LABEL);
842 if (!cameras.empty()) {
843 std::string preferred_camera;
844 if (requested_camera.empty()) {
845 preferred_camera = prefs->GetString(prefs::kDefaultVideoCaptureDevice);
846 camera_menu.disabled = false;
847 } else {
848 // Disable the menu since the website is managing the camera devices
849 // itself.
850 preferred_camera = requested_camera;
851 camera_menu.disabled = true;
854 camera_menu.default_device =
855 GetMediaDeviceById(preferred_camera, cameras);
856 camera_menu.selected_device = camera_menu.default_device;
858 add_media_menu(content::MEDIA_DEVICE_VIDEO_CAPTURE, camera_menu);
862 void ContentSettingMediaStreamBubbleModel::OnRadioClicked(int radio_index) {
863 selected_item_ = radio_index;
866 void ContentSettingMediaStreamBubbleModel::OnMediaMenuClicked(
867 content::MediaStreamType type,
868 const std::string& selected_device_id) {
869 DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
870 type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
871 DCHECK_EQ(1U, bubble_content().media_menus.count(type));
872 MediaCaptureDevicesDispatcher* dispatcher =
873 MediaCaptureDevicesDispatcher::GetInstance();
874 const content::MediaStreamDevices& devices =
875 (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) ?
876 dispatcher->GetAudioCaptureDevices() :
877 dispatcher->GetVideoCaptureDevices();
878 set_selected_device(GetMediaDeviceById(selected_device_id, devices));
881 class ContentSettingDomainListBubbleModel
882 : public ContentSettingTitleAndLinkModel {
883 public:
884 ContentSettingDomainListBubbleModel(Delegate* delegate,
885 WebContents* web_contents,
886 Profile* profile,
887 ContentSettingsType content_type);
888 virtual ~ContentSettingDomainListBubbleModel() {}
890 private:
891 void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
892 void SetDomainsAndCustomLink();
893 virtual void OnCustomLinkClicked() OVERRIDE;
896 ContentSettingDomainListBubbleModel::ContentSettingDomainListBubbleModel(
897 Delegate* delegate,
898 WebContents* web_contents,
899 Profile* profile,
900 ContentSettingsType content_type)
901 : ContentSettingTitleAndLinkModel(
902 delegate, web_contents, profile, content_type) {
903 DCHECK_EQ(CONTENT_SETTINGS_TYPE_GEOLOCATION, content_type) <<
904 "SetDomains currently only supports geolocation content type";
905 SetDomainsAndCustomLink();
908 void ContentSettingDomainListBubbleModel::MaybeAddDomainList(
909 const std::set<std::string>& hosts, int title_id) {
910 if (!hosts.empty()) {
911 DomainList domain_list;
912 domain_list.title = l10n_util::GetStringUTF8(title_id);
913 domain_list.hosts = hosts;
914 add_domain_list(domain_list);
918 void ContentSettingDomainListBubbleModel::SetDomainsAndCustomLink() {
919 TabSpecificContentSettings* content_settings =
920 TabSpecificContentSettings::FromWebContents(web_contents());
921 const ContentSettingsUsagesState& usages =
922 content_settings->geolocation_usages_state();
923 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
924 unsigned int tab_state_flags = 0;
925 usages.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
926 // Divide the tab's current geolocation users into sets according to their
927 // permission state.
928 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
929 IDS_GEOLOCATION_BUBBLE_SECTION_ALLOWED);
931 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
932 IDS_GEOLOCATION_BUBBLE_SECTION_DENIED);
934 if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
935 set_custom_link(l10n_util::GetStringUTF8(
936 IDS_GEOLOCATION_BUBBLE_CLEAR_LINK));
937 set_custom_link_enabled(true);
938 } else if (tab_state_flags &
939 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
940 set_custom_link(l10n_util::GetStringUTF8(
941 IDS_GEOLOCATION_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
945 void ContentSettingDomainListBubbleModel::OnCustomLinkClicked() {
946 if (!web_contents())
947 return;
948 // Reset this embedder's entry to default for each of the requesting
949 // origins currently on the page.
950 const GURL& embedder_url = web_contents()->GetURL();
951 TabSpecificContentSettings* content_settings =
952 TabSpecificContentSettings::FromWebContents(web_contents());
953 const ContentSettingsUsagesState::StateMap& state_map =
954 content_settings->geolocation_usages_state().state_map();
955 HostContentSettingsMap* settings_map =
956 profile()->GetHostContentSettingsMap();
958 for (ContentSettingsUsagesState::StateMap::const_iterator it =
959 state_map.begin(); it != state_map.end(); ++it) {
960 settings_map->SetContentSetting(
961 ContentSettingsPattern::FromURLNoWildcard(it->first),
962 ContentSettingsPattern::FromURLNoWildcard(embedder_url),
963 CONTENT_SETTINGS_TYPE_GEOLOCATION,
964 std::string(),
965 CONTENT_SETTING_DEFAULT);
969 class ContentSettingMixedScriptBubbleModel
970 : public ContentSettingTitleLinkAndCustomModel {
971 public:
972 ContentSettingMixedScriptBubbleModel(Delegate* delegate,
973 WebContents* web_contents,
974 Profile* profile,
975 ContentSettingsType content_type);
977 virtual ~ContentSettingMixedScriptBubbleModel() {}
979 private:
980 virtual void OnCustomLinkClicked() OVERRIDE;
983 ContentSettingMixedScriptBubbleModel::ContentSettingMixedScriptBubbleModel(
984 Delegate* delegate,
985 WebContents* web_contents,
986 Profile* profile,
987 ContentSettingsType content_type)
988 : ContentSettingTitleLinkAndCustomModel(
989 delegate, web_contents, profile, content_type) {
990 DCHECK_EQ(content_type, CONTENT_SETTINGS_TYPE_MIXEDSCRIPT);
991 set_custom_link_enabled(true);
994 void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
995 content::RecordAction(UserMetricsAction("MixedScript_LoadAnyway_Bubble"));
996 DCHECK(web_contents());
997 web_contents()->SendToAllFrames(
998 new ChromeViewMsg_SetAllowRunningInsecureContent(MSG_ROUTING_NONE, true));
999 web_contents()->GetMainFrame()->Send(new ChromeViewMsg_ReloadFrame(
1000 web_contents()->GetMainFrame()->GetRoutingID()));
1003 ContentSettingRPHBubbleModel::ContentSettingRPHBubbleModel(
1004 Delegate* delegate,
1005 WebContents* web_contents,
1006 Profile* profile,
1007 ProtocolHandlerRegistry* registry,
1008 ContentSettingsType content_type)
1009 : ContentSettingTitleAndLinkModel(
1010 delegate, web_contents, profile, content_type),
1011 selected_item_(0),
1012 registry_(registry),
1013 pending_handler_(ProtocolHandler::EmptyProtocolHandler()),
1014 previous_handler_(ProtocolHandler::EmptyProtocolHandler()) {
1016 DCHECK_EQ(CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, content_type);
1018 TabSpecificContentSettings* content_settings =
1019 TabSpecificContentSettings::FromWebContents(web_contents);
1020 pending_handler_ = content_settings->pending_protocol_handler();
1021 previous_handler_ = content_settings->previous_protocol_handler();
1023 base::string16 protocol;
1024 if (pending_handler_.protocol() == "mailto") {
1025 protocol = l10n_util::GetStringUTF16(
1026 IDS_REGISTER_PROTOCOL_HANDLER_MAILTO_NAME);
1027 } else if (pending_handler_.protocol() == "webcal") {
1028 protocol = l10n_util::GetStringUTF16(
1029 IDS_REGISTER_PROTOCOL_HANDLER_WEBCAL_NAME);
1030 } else {
1031 protocol = base::UTF8ToUTF16(pending_handler_.protocol());
1034 if (previous_handler_.IsEmpty()) {
1035 set_title(l10n_util::GetStringFUTF8(
1036 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM,
1037 pending_handler_.title(),
1038 base::UTF8ToUTF16(pending_handler_.url().host()),
1039 protocol));
1040 } else {
1041 set_title(l10n_util::GetStringFUTF8(
1042 IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM_REPLACE,
1043 pending_handler_.title(),
1044 base::UTF8ToUTF16(pending_handler_.url().host()),
1045 protocol, previous_handler_.title()));
1048 std::string radio_allow_label =
1049 l10n_util::GetStringFUTF8(IDS_REGISTER_PROTOCOL_HANDLER_ACCEPT,
1050 pending_handler_.title());
1051 std::string radio_deny_label =
1052 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_DENY);
1053 std::string radio_ignore_label =
1054 l10n_util::GetStringUTF8(IDS_REGISTER_PROTOCOL_HANDLER_IGNORE);
1056 GURL url = web_contents->GetURL();
1057 RadioGroup radio_group;
1058 radio_group.url = url;
1060 radio_group.radio_items.push_back(radio_allow_label);
1061 radio_group.radio_items.push_back(radio_deny_label);
1062 radio_group.radio_items.push_back(radio_ignore_label);
1063 ContentSetting setting =
1064 content_settings->pending_protocol_handler_setting();
1065 if (setting == CONTENT_SETTING_ALLOW)
1066 radio_group.default_item = RPH_ALLOW;
1067 else if (setting == CONTENT_SETTING_BLOCK)
1068 radio_group.default_item = RPH_BLOCK;
1069 else
1070 radio_group.default_item = RPH_IGNORE;
1072 selected_item_ = radio_group.default_item;
1073 set_radio_group_enabled(true);
1074 set_radio_group(radio_group);
1077 void ContentSettingRPHBubbleModel::OnRadioClicked(int radio_index) {
1078 if (selected_item_ == radio_index)
1079 return;
1081 selected_item_ = radio_index;
1083 if (radio_index == RPH_ALLOW)
1084 RegisterProtocolHandler();
1085 else if (radio_index == RPH_BLOCK)
1086 UnregisterProtocolHandler();
1087 else if (radio_index == RPH_IGNORE)
1088 IgnoreProtocolHandler();
1089 else
1090 NOTREACHED();
1093 void ContentSettingRPHBubbleModel::OnDoneClicked() {
1094 // The user has one chance to deal with the RPH content setting UI,
1095 // then we remove it.
1096 TabSpecificContentSettings::FromWebContents(web_contents())->
1097 ClearPendingProtocolHandler();
1098 content::NotificationService::current()->Notify(
1099 chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED,
1100 content::Source<WebContents>(web_contents()),
1101 content::NotificationService::NoDetails());
1104 void ContentSettingRPHBubbleModel::RegisterProtocolHandler() {
1105 // A no-op if the handler hasn't been ignored, but needed in case the user
1106 // selects sequences like register/ignore/register.
1107 registry_->RemoveIgnoredHandler(pending_handler_);
1109 registry_->OnAcceptRegisterProtocolHandler(pending_handler_);
1110 TabSpecificContentSettings::FromWebContents(web_contents())->
1111 set_pending_protocol_handler_setting(CONTENT_SETTING_ALLOW);
1114 void ContentSettingRPHBubbleModel::UnregisterProtocolHandler() {
1115 registry_->OnDenyRegisterProtocolHandler(pending_handler_);
1116 TabSpecificContentSettings::FromWebContents(web_contents())->
1117 set_pending_protocol_handler_setting(CONTENT_SETTING_BLOCK);
1118 ClearOrSetPreviousHandler();
1121 void ContentSettingRPHBubbleModel::IgnoreProtocolHandler() {
1122 registry_->OnIgnoreRegisterProtocolHandler(pending_handler_);
1123 TabSpecificContentSettings::FromWebContents(web_contents())->
1124 set_pending_protocol_handler_setting(CONTENT_SETTING_DEFAULT);
1125 ClearOrSetPreviousHandler();
1128 void ContentSettingRPHBubbleModel::ClearOrSetPreviousHandler() {
1129 if (previous_handler_.IsEmpty()) {
1130 registry_->ClearDefault(pending_handler_.protocol());
1131 } else {
1132 registry_->OnAcceptRegisterProtocolHandler(previous_handler_);
1136 class ContentSettingMidiSysExBubbleModel
1137 : public ContentSettingTitleAndLinkModel {
1138 public:
1139 ContentSettingMidiSysExBubbleModel(Delegate* delegate,
1140 WebContents* web_contents,
1141 Profile* profile,
1142 ContentSettingsType content_type);
1143 virtual ~ContentSettingMidiSysExBubbleModel() {}
1145 private:
1146 void MaybeAddDomainList(const std::set<std::string>& hosts, int title_id);
1147 void SetDomainsAndCustomLink();
1148 virtual void OnCustomLinkClicked() OVERRIDE;
1151 ContentSettingMidiSysExBubbleModel::ContentSettingMidiSysExBubbleModel(
1152 Delegate* delegate,
1153 WebContents* web_contents,
1154 Profile* profile,
1155 ContentSettingsType content_type)
1156 : ContentSettingTitleAndLinkModel(
1157 delegate, web_contents, profile, content_type) {
1158 DCHECK_EQ(CONTENT_SETTINGS_TYPE_MIDI_SYSEX, content_type);
1159 SetDomainsAndCustomLink();
1162 void ContentSettingMidiSysExBubbleModel::MaybeAddDomainList(
1163 const std::set<std::string>& hosts, int title_id) {
1164 if (!hosts.empty()) {
1165 DomainList domain_list;
1166 domain_list.title = l10n_util::GetStringUTF8(title_id);
1167 domain_list.hosts = hosts;
1168 add_domain_list(domain_list);
1172 void ContentSettingMidiSysExBubbleModel::SetDomainsAndCustomLink() {
1173 TabSpecificContentSettings* content_settings =
1174 TabSpecificContentSettings::FromWebContents(web_contents());
1175 const ContentSettingsUsagesState& usages_state =
1176 content_settings->midi_usages_state();
1177 ContentSettingsUsagesState::FormattedHostsPerState formatted_hosts_per_state;
1178 unsigned int tab_state_flags = 0;
1179 usages_state.GetDetailedInfo(&formatted_hosts_per_state, &tab_state_flags);
1180 // Divide the tab's current MIDI sysex users into sets according to their
1181 // permission state.
1182 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_ALLOW],
1183 IDS_MIDI_SYSEX_BUBBLE_ALLOWED);
1185 MaybeAddDomainList(formatted_hosts_per_state[CONTENT_SETTING_BLOCK],
1186 IDS_MIDI_SYSEX_BUBBLE_DENIED);
1188 if (tab_state_flags & ContentSettingsUsagesState::TABSTATE_HAS_EXCEPTION) {
1189 set_custom_link(l10n_util::GetStringUTF8(
1190 IDS_MIDI_SYSEX_BUBBLE_CLEAR_LINK));
1191 set_custom_link_enabled(true);
1192 } else if (tab_state_flags &
1193 ContentSettingsUsagesState::TABSTATE_HAS_CHANGED) {
1194 set_custom_link(l10n_util::GetStringUTF8(
1195 IDS_MIDI_SYSEX_BUBBLE_REQUIRE_RELOAD_TO_CLEAR));
1199 void ContentSettingMidiSysExBubbleModel::OnCustomLinkClicked() {
1200 if (!web_contents())
1201 return;
1202 // Reset this embedder's entry to default for each of the requesting
1203 // origins currently on the page.
1204 TabSpecificContentSettings* content_settings =
1205 TabSpecificContentSettings::FromWebContents(web_contents());
1206 const ContentSettingsUsagesState::StateMap& state_map =
1207 content_settings->midi_usages_state().state_map();
1208 HostContentSettingsMap* settings_map =
1209 profile()->GetHostContentSettingsMap();
1211 for (ContentSettingsUsagesState::StateMap::const_iterator it =
1212 state_map.begin(); it != state_map.end(); ++it) {
1213 settings_map->SetContentSetting(
1214 ContentSettingsPattern::FromURLNoWildcard(it->first),
1215 ContentSettingsPattern::Wildcard(),
1216 CONTENT_SETTINGS_TYPE_MIDI_SYSEX,
1217 std::string(),
1218 CONTENT_SETTING_DEFAULT);
1222 // static
1223 ContentSettingBubbleModel*
1224 ContentSettingBubbleModel::CreateContentSettingBubbleModel(
1225 Delegate* delegate,
1226 WebContents* web_contents,
1227 Profile* profile,
1228 ContentSettingsType content_type) {
1229 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES) {
1230 return new ContentSettingCookiesBubbleModel(delegate, web_contents, profile,
1231 content_type);
1233 if (content_type == CONTENT_SETTINGS_TYPE_POPUPS) {
1234 return new ContentSettingPopupBubbleModel(delegate, web_contents, profile,
1235 content_type);
1237 if (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
1238 return new ContentSettingDomainListBubbleModel(delegate, web_contents,
1239 profile, content_type);
1241 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM) {
1242 return new ContentSettingMediaStreamBubbleModel(delegate, web_contents,
1243 profile);
1245 if (content_type == CONTENT_SETTINGS_TYPE_PLUGINS) {
1246 return new ContentSettingPluginBubbleModel(delegate, web_contents, profile,
1247 content_type);
1249 if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT) {
1250 return new ContentSettingMixedScriptBubbleModel(delegate, web_contents,
1251 profile, content_type);
1253 if (content_type == CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS) {
1254 ProtocolHandlerRegistry* registry =
1255 ProtocolHandlerRegistryFactory::GetForProfile(profile);
1256 return new ContentSettingRPHBubbleModel(delegate, web_contents, profile,
1257 registry, content_type);
1259 if (content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
1260 return new ContentSettingMidiSysExBubbleModel(delegate, web_contents,
1261 profile, content_type);
1263 return new ContentSettingSingleRadioGroup(delegate, web_contents, profile,
1264 content_type);
1267 ContentSettingBubbleModel::ContentSettingBubbleModel(
1268 WebContents* web_contents,
1269 Profile* profile,
1270 ContentSettingsType content_type)
1271 : web_contents_(web_contents),
1272 profile_(profile),
1273 content_type_(content_type),
1274 setting_is_managed_(false) {
1275 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
1276 content::Source<WebContents>(web_contents));
1277 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
1278 content::Source<Profile>(profile_));
1281 ContentSettingBubbleModel::~ContentSettingBubbleModel() {
1284 ContentSettingBubbleModel::RadioGroup::RadioGroup() : default_item(0) {}
1286 ContentSettingBubbleModel::RadioGroup::~RadioGroup() {}
1288 ContentSettingBubbleModel::DomainList::DomainList() {}
1290 ContentSettingBubbleModel::DomainList::~DomainList() {}
1292 ContentSettingBubbleModel::MediaMenu::MediaMenu() : disabled(false) {}
1294 ContentSettingBubbleModel::MediaMenu::~MediaMenu() {}
1296 ContentSettingBubbleModel::BubbleContent::BubbleContent()
1297 : radio_group_enabled(false),
1298 custom_link_enabled(false) {
1301 ContentSettingBubbleModel::BubbleContent::~BubbleContent() {}
1303 void ContentSettingBubbleModel::Observe(
1304 int type,
1305 const content::NotificationSource& source,
1306 const content::NotificationDetails& details) {
1307 if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) {
1308 DCHECK_EQ(web_contents_,
1309 content::Source<WebContents>(source).ptr());
1310 web_contents_ = NULL;
1311 } else {
1312 DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type);
1313 DCHECK_EQ(profile_, content::Source<Profile>(source).ptr());
1314 profile_ = NULL;