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.
4 
5 #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
6 
7 #include <stddef.h>
8 
9 #include <memory>
10 #include <utility>
11 
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/feature_list.h"
15 #include "base/metrics/user_metrics.h"
16 #include "base/stl_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/content_settings/chrome_content_settings_utils.h"
20 #include "chrome/browser/content_settings/cookie_settings_factory.h"
21 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
22 #include "chrome/browser/content_settings/mixed_content_settings_tab_helper.h"
23 #include "chrome/browser/content_settings/page_specific_content_settings_delegate.h"
24 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
25 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
26 #include "chrome/browser/download/download_request_limiter.h"
27 #include "chrome/browser/external_protocol/external_protocol_handler.h"
28 #include "chrome/browser/infobars/infobar_service.h"
29 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
30 #include "chrome/browser/media/webrtc/permission_bubble_media_access_handler.h"
31 #include "chrome/browser/media/webrtc/system_media_capture_permissions_mac.h"
32 #include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h"
33 #include "chrome/browser/permissions/quiet_notification_permission_ui_config.h"
34 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
35 #include "chrome/browser/plugins/plugin_utils.h"
36 #include "chrome/browser/profiles/profile.h"
37 #include "chrome/browser/ui/collected_cookies_infobar_delegate.h"
38 #include "chrome/browser/ui/content_settings/content_setting_bubble_model_delegate.h"
39 #include "chrome/common/chrome_features.h"
40 #include "chrome/common/chrome_switches.h"
41 #include "chrome/common/pref_names.h"
42 #include "chrome/grit/generated_resources.h"
43 #include "chrome/grit/theme_resources.h"
44 #include "components/blocked_content/popup_blocker_tab_helper.h"
45 #include "components/content_settings/browser/page_specific_content_settings.h"
46 #include "components/content_settings/common/content_settings_agent.mojom.h"
47 #include "components/content_settings/core/browser/content_settings_utils.h"
48 #include "components/content_settings/core/browser/cookie_settings.h"
49 #include "components/content_settings/core/common/content_settings.h"
50 #include "components/content_settings/core/common/content_settings_utils.h"
51 #include "components/permissions/permission_decision_auto_blocker.h"
52 #include "components/permissions/permission_manager.h"
53 #include "components/permissions/permission_request_manager.h"
54 #include "components/permissions/permission_result.h"
55 #include "components/permissions/permission_uma_util.h"
56 #include "components/permissions/permission_util.h"
57 #include "components/permissions/permissions_client.h"
58 #include "components/prefs/pref_service.h"
59 #include "components/strings/grit/components_strings.h"
60 #include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h"
61 #include "components/subresource_filter/core/browser/subresource_filter_constants.h"
62 #include "components/subresource_filter/core/browser/subresource_filter_features.h"
63 #include "components/url_formatter/elide_url.h"
64 #include "components/vector_icons/vector_icons.h"
65 #include "content/public/browser/notification_service.h"
66 #include "content/public/browser/render_frame_host.h"
67 #include "content/public/browser/render_process_host.h"
68 #include "content/public/browser/render_view_host.h"
69 #include "content/public/browser/web_contents.h"
70 #include "content/public/browser/web_contents_delegate.h"
71 #include "mojo/public/cpp/bindings/associated_remote.h"
72 #include "ppapi/buildflags/buildflags.h"
73 #include "services/device/public/cpp/device_features.h"
74 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
75 #include "third_party/blink/public/common/loader/network_utils.h"
76 #include "ui/base/l10n/l10n_util.h"
77 #include "ui/base/resource/resource_bundle.h"
78 #include "ui/base/window_open_disposition.h"
79 #include "ui/events/event.h"
80 #include "ui/gfx/vector_icon_types.h"
81 #include "ui/resources/grit/ui_resources.h"
82 
83 #if defined(OS_MAC)
84 #include "chrome/browser/browser_process_platform_part.h"
85 #include "chrome/browser/geolocation/geolocation_system_permission_mac.h"
86 #include "chrome/browser/media/webrtc/system_media_capture_permissions_mac.h"
87 #endif
88 
89 using base::UserMetricsAction;
90 using content::WebContents;
91 using content_settings::PageSpecificContentSettings;
92 using content_settings::SessionModel;
93 using content_settings::SETTING_SOURCE_NONE;
94 using content_settings::SETTING_SOURCE_USER;
95 using content_settings::SettingInfo;
96 using content_settings::SettingSource;
97 
98 namespace {
99 
100 using QuietUiReason = permissions::PermissionRequestManager::QuietUiReason;
101 
102 #if defined(OS_MAC)
103 static constexpr char kCameraSettingsURI[] =
104     "x-apple.systempreferences:com.apple.preference.security?Privacy_"
105     "Camera";
106 static constexpr char kMicSettingsURI[] =
107     "x-apple.systempreferences:com.apple.preference.security?Privacy_"
108     "Microphone";
109 static constexpr char kLocationSettingsURI[] =
110     "x-apple.systempreferences:com.apple.preference.security?Privacy_"
111     "LocationServices";
112 #endif  // defined(OS_MAC)
113 
114 // Returns a boolean indicating whether the setting should be managed by the
115 // user (i.e. it is not controlled by policy). Also takes a (nullable) out-param
116 // which is populated by the actual setting for the given URL.
GetSettingManagedByUser(const GURL & url,ContentSettingsType type,Profile * profile,ContentSetting * out_setting)117 bool GetSettingManagedByUser(const GURL& url,
118                              ContentSettingsType type,
119                              Profile* profile,
120                              ContentSetting* out_setting) {
121   HostContentSettingsMap* map =
122       HostContentSettingsMapFactory::GetForProfile(profile);
123   SettingSource source;
124   ContentSetting setting;
125   if (type == ContentSettingsType::COOKIES) {
126     CookieSettingsFactory::GetForProfile(profile)->GetCookieSetting(
127         url, url, &source, &setting);
128   } else {
129     SettingInfo info;
130     std::unique_ptr<base::Value> value =
131         map->GetWebsiteSetting(url, url, type, &info);
132     setting = content_settings::ValueToContentSetting(value.get());
133     source = info.source;
134   }
135 
136   if (out_setting)
137     *out_setting = setting;
138 
139   // Prevent creation of content settings for illegal urls like about:blank by
140   // disallowing user management.
141   return source == SETTING_SOURCE_USER &&
142          map->CanSetNarrowestContentSetting(url, url, type);
143 }
144 
CreateUrlListItem(int32_t id,const GURL & url)145 ContentSettingBubbleModel::ListItem CreateUrlListItem(int32_t id,
146                                                       const GURL& url) {
147   // Empty URLs should get a placeholder.
148   // TODO(csharrison): See if we can DCHECK that the URL will be valid here.
149   base::string16 title = url.spec().empty()
150                              ? l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE)
151                              : base::UTF8ToUTF16(url.spec());
152 
153   // Format the title to include the unicode single dot bullet code-point
154   // \u2022 and two spaces.
155   title = l10n_util::GetStringFUTF16(IDS_LIST_BULLET, title);
156   return ContentSettingBubbleModel::ListItem(nullptr, title, base::string16(),
157                                              true /* has_link */,
158                                              false /* has_blocked_badge */, id);
159 }
160 
161 struct ContentSettingsTypeIdEntry {
162   ContentSettingsType type;
163   int id;
164 };
165 
GetIdForContentType(const ContentSettingsTypeIdEntry * entries,size_t num_entries,ContentSettingsType type)166 int GetIdForContentType(const ContentSettingsTypeIdEntry* entries,
167                         size_t num_entries,
168                         ContentSettingsType type) {
169   for (size_t i = 0; i < num_entries; ++i) {
170     if (entries[i].type == type)
171       return entries[i].id;
172   }
173   return 0;
174 }
175 
SetAllowRunningInsecureContent(content::RenderFrameHost * frame)176 void SetAllowRunningInsecureContent(content::RenderFrameHost* frame) {
177   mojo::AssociatedRemote<content_settings::mojom::ContentSettingsAgent> agent;
178   frame->GetRemoteAssociatedInterfaces()->GetInterface(&agent);
179   agent->SetAllowRunningInsecureContent();
180 }
181 
182 }  // namespace
183 
184 // ContentSettingSimpleBubbleModel ---------------------------------------------
ListItem(const gfx::VectorIcon * image,const base::string16 & title,const base::string16 & description,bool has_link,bool has_blocked_badge,int32_t item_id)185 ContentSettingBubbleModel::ListItem::ListItem(const gfx::VectorIcon* image,
186                                               const base::string16& title,
187                                               const base::string16& description,
188                                               bool has_link,
189                                               bool has_blocked_badge,
190                                               int32_t item_id)
191     : image(image),
192       title(title),
193       description(description),
194       has_link(has_link),
195       has_blocked_badge(has_blocked_badge),
196       item_id(item_id) {}
197 
198 ContentSettingBubbleModel::ListItem::ListItem(const ListItem& other) = default;
199 ContentSettingBubbleModel::ListItem& ContentSettingBubbleModel::ListItem::
200 operator=(const ListItem& other) = default;
201 
ContentSettingSimpleBubbleModel(Delegate * delegate,WebContents * web_contents,ContentSettingsType content_type)202 ContentSettingSimpleBubbleModel::ContentSettingSimpleBubbleModel(
203     Delegate* delegate,
204     WebContents* web_contents,
205     ContentSettingsType content_type)
206     : ContentSettingBubbleModel(delegate, web_contents),
207       content_type_(content_type) {
208   SetTitle();
209   SetMessage();
210   SetManageText();
211   SetCustomLink();
212 }
213 
214 ContentSettingSimpleBubbleModel*
AsSimpleBubbleModel()215     ContentSettingSimpleBubbleModel::AsSimpleBubbleModel() {
216   return this;
217 }
218 
SetTitle()219 void ContentSettingSimpleBubbleModel::SetTitle() {
220   // TODO(https://crbug.com/1103176): Plumb the actual frame reference here
221   PageSpecificContentSettings* content_settings =
222       PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame());
223 
224   static const ContentSettingsTypeIdEntry kBlockedTitleIDs[] = {
225       {ContentSettingsType::COOKIES, IDS_BLOCKED_COOKIES_TITLE},
226       {ContentSettingsType::IMAGES, IDS_BLOCKED_IMAGES_TITLE},
227       {ContentSettingsType::JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_TITLE},
228       {ContentSettingsType::PLUGINS, IDS_BLOCKED_PLUGINS_TITLE},
229       {ContentSettingsType::MIXEDSCRIPT,
230        IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT_TITLE},
231       {ContentSettingsType::PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_TITLE},
232       {ContentSettingsType::SOUND, IDS_BLOCKED_SOUND_TITLE},
233       {ContentSettingsType::CLIPBOARD_READ_WRITE, IDS_BLOCKED_CLIPBOARD_TITLE},
234       {ContentSettingsType::GEOLOCATION, IDS_BLOCKED_GEOLOCATION_TITLE},
235       {ContentSettingsType::MIDI_SYSEX, IDS_BLOCKED_MIDI_SYSEX_TITLE},
236       {ContentSettingsType::SENSORS, IDS_BLOCKED_SENSORS_TITLE},
237   };
238   // Fields as for kBlockedTitleIDs, above.
239   static const ContentSettingsTypeIdEntry kAccessedTitleIDs[] = {
240       {ContentSettingsType::COOKIES, IDS_ACCESSED_COOKIES_TITLE},
241       {ContentSettingsType::PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_TITLE},
242       {ContentSettingsType::CLIPBOARD_READ_WRITE, IDS_ALLOWED_CLIPBOARD_TITLE},
243       {ContentSettingsType::GEOLOCATION, IDS_ALLOWED_GEOLOCATION_TITLE},
244       {ContentSettingsType::MIDI_SYSEX, IDS_ALLOWED_MIDI_SYSEX_TITLE},
245       {ContentSettingsType::SENSORS, IDS_ALLOWED_SENSORS_TITLE},
246   };
247   const ContentSettingsTypeIdEntry* title_ids = kBlockedTitleIDs;
248   size_t num_title_ids = base::size(kBlockedTitleIDs);
249   if (content_settings->IsContentAllowed(content_type()) &&
250       !content_settings->IsContentBlocked(content_type())) {
251     title_ids = kAccessedTitleIDs;
252     num_title_ids = base::size(kAccessedTitleIDs);
253   }
254   int title_id = GetIdForContentType(title_ids, num_title_ids, content_type());
255   if (title_id)
256     set_title(l10n_util::GetStringUTF16(title_id));
257 }
258 
SetMessage()259 void ContentSettingSimpleBubbleModel::SetMessage() {
260   PageSpecificContentSettings* content_settings =
261       PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame());
262 
263   // TODO(https://crbug.com/978882): Make the two arrays below static again once
264   // we no longer need to check base::FeatureList.
265   const ContentSettingsTypeIdEntry kBlockedMessageIDs[] = {
266       {ContentSettingsType::COOKIES, IDS_BLOCKED_COOKIES_MESSAGE},
267       {ContentSettingsType::IMAGES, IDS_BLOCKED_IMAGES_MESSAGE},
268       {ContentSettingsType::JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_MESSAGE},
269       // {ContentSettingsType::POPUPS, No message. intentionally left out},
270       {ContentSettingsType::MIXEDSCRIPT,
271        IDS_BLOCKED_DISPLAYING_INSECURE_CONTENT},
272       {ContentSettingsType::PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_MESSAGE},
273       {ContentSettingsType::GEOLOCATION, IDS_BLOCKED_GEOLOCATION_MESSAGE},
274       {ContentSettingsType::MIDI_SYSEX, IDS_BLOCKED_MIDI_SYSEX_MESSAGE},
275       {ContentSettingsType::CLIPBOARD_READ_WRITE,
276        IDS_BLOCKED_CLIPBOARD_MESSAGE},
277       {ContentSettingsType::SENSORS,
278        base::FeatureList::IsEnabled(features::kGenericSensorExtraClasses)
279            ? IDS_BLOCKED_SENSORS_MESSAGE
280            : IDS_BLOCKED_MOTION_SENSORS_MESSAGE},
281   };
282   // Fields as for kBlockedMessageIDs, above.
283   const ContentSettingsTypeIdEntry kAccessedMessageIDs[] = {
284       {ContentSettingsType::COOKIES, IDS_ACCESSED_COOKIES_MESSAGE},
285       {ContentSettingsType::PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_MESSAGE},
286       {ContentSettingsType::GEOLOCATION, IDS_ALLOWED_GEOLOCATION_MESSAGE},
287       {ContentSettingsType::MIDI_SYSEX, IDS_ALLOWED_MIDI_SYSEX_MESSAGE},
288       {ContentSettingsType::CLIPBOARD_READ_WRITE,
289        IDS_ALLOWED_CLIPBOARD_MESSAGE},
290       {ContentSettingsType::SENSORS,
291        base::FeatureList::IsEnabled(features::kGenericSensorExtraClasses)
292            ? IDS_ALLOWED_SENSORS_MESSAGE
293            : IDS_ALLOWED_MOTION_SENSORS_MESSAGE},
294   };
295   const ContentSettingsTypeIdEntry* message_ids = kBlockedMessageIDs;
296   size_t num_message_ids = base::size(kBlockedMessageIDs);
297   if (content_settings->IsContentAllowed(content_type()) &&
298       !content_settings->IsContentBlocked(content_type())) {
299     message_ids = kAccessedMessageIDs;
300     num_message_ids = base::size(kAccessedMessageIDs);
301   }
302   int message_id =
303       GetIdForContentType(message_ids, num_message_ids, content_type());
304   if (message_id)
305     set_message(l10n_util::GetStringUTF16(message_id));
306 }
307 
SetManageText()308 void ContentSettingSimpleBubbleModel::SetManageText() {
309   set_manage_text(l10n_util::GetStringUTF16(IDS_MANAGE));
310 }
311 
OnManageButtonClicked()312 void ContentSettingSimpleBubbleModel::OnManageButtonClicked() {
313   if (delegate())
314     delegate()->ShowContentSettingsPage(content_type());
315 
316   if (content_type() == ContentSettingsType::PLUGINS) {
317     content_settings::RecordPluginsAction(
318         content_settings::PLUGINS_ACTION_CLICKED_MANAGE_PLUGIN_BLOCKING);
319   }
320 
321   if (content_type() == ContentSettingsType::POPUPS) {
322     content_settings::RecordPopupsAction(
323         content_settings::POPUPS_ACTION_CLICKED_MANAGE_POPUPS_BLOCKING);
324   }
325 }
326 
SetCustomLink()327 void ContentSettingSimpleBubbleModel::SetCustomLink() {
328   static const ContentSettingsTypeIdEntry kCustomIDs[] = {
329       {ContentSettingsType::COOKIES, IDS_BLOCKED_COOKIES_INFO},
330       {ContentSettingsType::MIXEDSCRIPT, IDS_ALLOW_INSECURE_CONTENT_BUTTON},
331   };
332   int custom_link_id =
333       GetIdForContentType(kCustomIDs, base::size(kCustomIDs), content_type());
334   if (custom_link_id)
335     set_custom_link(l10n_util::GetStringUTF16(custom_link_id));
336 }
337 
OnCustomLinkClicked()338 void ContentSettingSimpleBubbleModel::OnCustomLinkClicked() {
339 }
340 
341 // ContentSettingMixedScriptBubbleModel ----------------------------------------
342 
343 class ContentSettingMixedScriptBubbleModel
344     : public ContentSettingSimpleBubbleModel {
345  public:
346   ContentSettingMixedScriptBubbleModel(Delegate* delegate,
347                                        WebContents* web_contents);
348 
~ContentSettingMixedScriptBubbleModel()349   ~ContentSettingMixedScriptBubbleModel() override {}
350 
351  private:
352   void SetManageText();
353 
354   // ContentSettingBubbleModel:
355   void OnLearnMoreClicked() override;
356   void OnCustomLinkClicked() override;
357 
358   DISALLOW_COPY_AND_ASSIGN(ContentSettingMixedScriptBubbleModel);
359 };
360 
ContentSettingMixedScriptBubbleModel(Delegate * delegate,WebContents * web_contents)361 ContentSettingMixedScriptBubbleModel::ContentSettingMixedScriptBubbleModel(
362     Delegate* delegate,
363     WebContents* web_contents)
364     : ContentSettingSimpleBubbleModel(delegate,
365                                       web_contents,
366                                       ContentSettingsType::MIXEDSCRIPT) {
367   set_custom_link_enabled(true);
368   set_show_learn_more(true);
369   SetManageText();
370 }
371 
OnLearnMoreClicked()372 void ContentSettingMixedScriptBubbleModel::OnLearnMoreClicked() {
373   if (delegate())
374     delegate()->ShowLearnMorePage(content_type());
375 }
376 
OnCustomLinkClicked()377 void ContentSettingMixedScriptBubbleModel::OnCustomLinkClicked() {
378   DCHECK(rappor_service());
379   MixedContentSettingsTabHelper* mixed_content_settings =
380       MixedContentSettingsTabHelper::FromWebContents(web_contents());
381   if (mixed_content_settings) {
382     // Update browser side settings to allow active mixed content.
383     mixed_content_settings->AllowRunningOfInsecureContent();
384   }
385 
386   // Update renderer side settings to allow active mixed content.
387   web_contents()->ForEachFrame(
388       base::BindRepeating(&::SetAllowRunningInsecureContent));
389 }
390 
391 // Don't set any manage text since none is displayed.
SetManageText()392 void ContentSettingMixedScriptBubbleModel::SetManageText() {
393   set_manage_text_style(ContentSettingBubbleModel::ManageTextStyle::kNone);
394 }
395 
396 // ContentSettingRPHBubbleModel ------------------------------------------------
397 
398 namespace {
399 
400 // These states must match the order of appearance of the radio buttons
401 // in the XIB file for the Mac port.
402 enum RPHState {
403   RPH_ALLOW = 0,
404   RPH_BLOCK,
405   RPH_IGNORE,
406 };
407 
408 }  // namespace
409 
ContentSettingRPHBubbleModel(Delegate * delegate,WebContents * web_contents,ProtocolHandlerRegistry * registry)410 ContentSettingRPHBubbleModel::ContentSettingRPHBubbleModel(
411     Delegate* delegate,
412     WebContents* web_contents,
413     ProtocolHandlerRegistry* registry)
414     : ContentSettingSimpleBubbleModel(delegate,
415                                       web_contents,
416                                       ContentSettingsType::PROTOCOL_HANDLERS),
417       registry_(registry),
418       pending_handler_(ProtocolHandler::EmptyProtocolHandler()),
419       previous_handler_(ProtocolHandler::EmptyProtocolHandler()) {
420   auto* content_settings =
421       chrome::PageSpecificContentSettingsDelegate::FromWebContents(
422           web_contents);
423   pending_handler_ = content_settings->pending_protocol_handler();
424   previous_handler_ = content_settings->previous_protocol_handler();
425 
426   base::string16 protocol = pending_handler_.GetProtocolDisplayName();
427 
428   // Note that we ignore the |title| parameter.
429   if (previous_handler_.IsEmpty()) {
430     set_title(l10n_util::GetStringFUTF16(
431         IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM,
432         base::UTF8ToUTF16(pending_handler_.url().host()), protocol));
433   } else {
434     set_title(l10n_util::GetStringFUTF16(
435         IDS_REGISTER_PROTOCOL_HANDLER_CONFIRM_REPLACE,
436         base::UTF8ToUTF16(pending_handler_.url().host()), protocol,
437         base::UTF8ToUTF16(previous_handler_.url().host())));
438   }
439 
440   base::string16 radio_allow_label =
441       l10n_util::GetStringUTF16(IDS_REGISTER_PROTOCOL_HANDLER_ACCEPT);
442   base::string16 radio_deny_label =
443       l10n_util::GetStringUTF16(IDS_REGISTER_PROTOCOL_HANDLER_DENY);
444   base::string16 radio_ignore_label =
445       l10n_util::GetStringUTF16(IDS_REGISTER_PROTOCOL_HANDLER_IGNORE);
446 
447   const GURL& url = web_contents->GetURL();
448   RadioGroup radio_group;
449   radio_group.url = url;
450 
451   radio_group.radio_items = {radio_allow_label, radio_deny_label,
452                              radio_ignore_label};
453   ContentSetting setting = content_settings->pending_protocol_handler_setting();
454   if (setting == CONTENT_SETTING_ALLOW)
455     radio_group.default_item = RPH_ALLOW;
456   else if (setting == CONTENT_SETTING_BLOCK)
457     radio_group.default_item = RPH_BLOCK;
458   else
459     radio_group.default_item = RPH_IGNORE;
460 
461   radio_group.user_managed = true;
462   set_radio_group(radio_group);
463 }
464 
~ContentSettingRPHBubbleModel()465 ContentSettingRPHBubbleModel::~ContentSettingRPHBubbleModel() {}
466 
CommitChanges()467 void ContentSettingRPHBubbleModel::CommitChanges() {
468   PerformActionForSelectedItem();
469 
470   // The user has one chance to deal with the RPH content setting UI,
471   // then we remove it.
472   chrome::PageSpecificContentSettingsDelegate::FromWebContents(web_contents())
473       ->ClearPendingProtocolHandler();
474   content_settings::UpdateLocationBarUiForWebContents(web_contents());
475 }
476 
RegisterProtocolHandler()477 void ContentSettingRPHBubbleModel::RegisterProtocolHandler() {
478   // A no-op if the handler hasn't been ignored, but needed in case the user
479   // selects sequences like register/ignore/register.
480   registry_->RemoveIgnoredHandler(pending_handler_);
481 
482   registry_->OnAcceptRegisterProtocolHandler(pending_handler_);
483   chrome::PageSpecificContentSettingsDelegate::FromWebContents(web_contents())
484       ->set_pending_protocol_handler_setting(CONTENT_SETTING_ALLOW);
485 }
486 
UnregisterProtocolHandler()487 void ContentSettingRPHBubbleModel::UnregisterProtocolHandler() {
488   registry_->OnDenyRegisterProtocolHandler(pending_handler_);
489   chrome::PageSpecificContentSettingsDelegate::FromWebContents(web_contents())
490       ->set_pending_protocol_handler_setting(CONTENT_SETTING_BLOCK);
491   ClearOrSetPreviousHandler();
492 }
493 
IgnoreProtocolHandler()494 void ContentSettingRPHBubbleModel::IgnoreProtocolHandler() {
495   registry_->OnIgnoreRegisterProtocolHandler(pending_handler_);
496   chrome::PageSpecificContentSettingsDelegate::FromWebContents(web_contents())
497       ->set_pending_protocol_handler_setting(CONTENT_SETTING_DEFAULT);
498   ClearOrSetPreviousHandler();
499 }
500 
ClearOrSetPreviousHandler()501 void ContentSettingRPHBubbleModel::ClearOrSetPreviousHandler() {
502   if (previous_handler_.IsEmpty()) {
503     registry_->ClearDefault(pending_handler_.protocol());
504   } else {
505     registry_->OnAcceptRegisterProtocolHandler(previous_handler_);
506   }
507 }
508 
PerformActionForSelectedItem()509 void ContentSettingRPHBubbleModel::PerformActionForSelectedItem() {
510   if (selected_item() == RPH_ALLOW)
511     RegisterProtocolHandler();
512   else if (selected_item() == RPH_BLOCK)
513     UnregisterProtocolHandler();
514   else if (selected_item() == RPH_IGNORE)
515     IgnoreProtocolHandler();
516   else
517     NOTREACHED();
518 }
519 
520 class ContentSettingPluginBubbleModel : public ContentSettingSimpleBubbleModel {
521  public:
522   ContentSettingPluginBubbleModel(Delegate* delegate,
523                                   WebContents* web_contents);
524 
525  private:
526   void OnLearnMoreClicked() override;
527   void OnCustomLinkClicked() override;
528 
529   void RunPluginsOnPage();
530 
531   DISALLOW_COPY_AND_ASSIGN(ContentSettingPluginBubbleModel);
532 };
533 
ContentSettingPluginBubbleModel(Delegate * delegate,WebContents * web_contents)534 ContentSettingPluginBubbleModel::ContentSettingPluginBubbleModel(
535     Delegate* delegate,
536     WebContents* web_contents)
537     : ContentSettingSimpleBubbleModel(delegate,
538                                       web_contents,
539                                       ContentSettingsType::PLUGINS) {
540   const GURL& url = web_contents->GetURL();
541   bool managed_by_user =
542       GetSettingManagedByUser(url, content_type(), GetProfile(), nullptr);
543   HostContentSettingsMap* map =
544       HostContentSettingsMapFactory::GetForProfile(GetProfile());
545   ContentSetting setting = PluginUtils::GetFlashPluginContentSetting(
546       map, url::Origin::Create(url), url, nullptr);
547 
548   // If the setting is not managed by the user, hide the "Manage" button.
549   if (!managed_by_user)
550     set_manage_text_style(ContentSettingBubbleModel::ManageTextStyle::kNone);
551 
552   // The user can only load Flash dynamically if not on the BLOCK setting.
553   if (setting != CONTENT_SETTING_BLOCK) {
554     set_custom_link(l10n_util::GetStringUTF16(IDS_BLOCKED_PLUGINS_LOAD_ALL));
555     // Disable the "Run all plugins this time" link if the user already clicked
556     // on the link and ran all plugins.
557     set_custom_link_enabled(
558         PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame())
559             ->load_plugins_link_enabled());
560   }
561 
562   set_show_learn_more(true);
563 
564   content_settings::RecordPluginsAction(
565       content_settings::PLUGINS_ACTION_DISPLAYED_BUBBLE);
566 }
567 
OnLearnMoreClicked()568 void ContentSettingPluginBubbleModel::OnLearnMoreClicked() {
569   if (delegate())
570     delegate()->ShowLearnMorePage(ContentSettingsType::PLUGINS);
571 
572   content_settings::RecordPluginsAction(
573       content_settings::PLUGINS_ACTION_CLICKED_LEARN_MORE);
574 }
575 
OnCustomLinkClicked()576 void ContentSettingPluginBubbleModel::OnCustomLinkClicked() {
577   base::RecordAction(UserMetricsAction("ClickToPlay_LoadAll_Bubble"));
578   content_settings::RecordPluginsAction(
579       content_settings::PLUGINS_ACTION_CLICKED_RUN_ALL_PLUGINS_THIS_TIME);
580 
581   RunPluginsOnPage();
582 }
583 
RunPluginsOnPage()584 void ContentSettingPluginBubbleModel::RunPluginsOnPage() {
585 #if BUILDFLAG(ENABLE_PLUGINS)
586   // TODO(bauerb): We should send the identifiers of blocked plugins here.
587   ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
588       web_contents(), true, std::string());
589 #endif
590   set_custom_link_enabled(false);
591   PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame())
592       ->set_load_plugins_link_enabled(false);
593 }
594 
595 // ContentSettingSingleRadioGroup ----------------------------------------------
596 
ContentSettingSingleRadioGroup(Delegate * delegate,WebContents * web_contents,ContentSettingsType content_type)597 ContentSettingSingleRadioGroup::ContentSettingSingleRadioGroup(
598     Delegate* delegate,
599     WebContents* web_contents,
600     ContentSettingsType content_type)
601     : ContentSettingSimpleBubbleModel(delegate,
602                                       web_contents,
603                                       content_type),
604       block_setting_(CONTENT_SETTING_BLOCK) {
605   SetRadioGroup();
606 }
607 
~ContentSettingSingleRadioGroup()608 ContentSettingSingleRadioGroup::~ContentSettingSingleRadioGroup() {}
609 
CommitChanges()610 void ContentSettingSingleRadioGroup::CommitChanges() {
611   if (settings_changed()) {
612     ContentSetting setting = selected_item() == kAllowButtonIndex
613                                  ? CONTENT_SETTING_ALLOW
614                                  : block_setting_;
615     SetNarrowestContentSetting(setting);
616   }
617 }
618 
settings_changed() const619 bool ContentSettingSingleRadioGroup::settings_changed() const {
620   return selected_item() != bubble_content().radio_group.default_item;
621 }
622 
623 // Initialize the radio group by setting the appropriate labels for the
624 // content type and setting the default value based on the content setting.
SetRadioGroup()625 void ContentSettingSingleRadioGroup::SetRadioGroup() {
626   const GURL& url = web_contents()->GetURL();
627   base::string16 display_host = url_formatter::FormatUrlForSecurityDisplay(url);
628 
629   PageSpecificContentSettings* content_settings =
630       PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame());
631   bool allowed = !content_settings->IsContentBlocked(content_type());
632 
633   // For the frame busting case the content is blocked but its content type is
634   // popup, and the popup PageSpecificContentSettings is unaware of the frame
635   // busting block. Since the popup bubble won't happen without blocking, it's
636   // safe to manually set this.
637   if (content_type() == ContentSettingsType::POPUPS)
638     allowed = false;
639 
640   DCHECK(!allowed || content_settings->IsContentAllowed(content_type()));
641 
642   RadioGroup radio_group;
643   radio_group.url = url;
644 
645   static const ContentSettingsTypeIdEntry kBlockedAllowIDs[] = {
646       {ContentSettingsType::COOKIES, IDS_BLOCKED_COOKIES_UNBLOCK},
647       {ContentSettingsType::IMAGES, IDS_BLOCKED_IMAGES_UNBLOCK},
648       {ContentSettingsType::JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_UNBLOCK},
649       {ContentSettingsType::POPUPS, IDS_BLOCKED_POPUPS_REDIRECTS_UNBLOCK},
650       {ContentSettingsType::PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_UNBLOCK},
651       {ContentSettingsType::SOUND, IDS_BLOCKED_SOUND_UNBLOCK},
652       {ContentSettingsType::GEOLOCATION, IDS_BLOCKED_GEOLOCATION_UNBLOCK},
653       {ContentSettingsType::MIDI_SYSEX, IDS_BLOCKED_MIDI_SYSEX_UNBLOCK},
654       {ContentSettingsType::CLIPBOARD_READ_WRITE,
655        IDS_BLOCKED_CLIPBOARD_UNBLOCK},
656       {ContentSettingsType::SENSORS, IDS_BLOCKED_SENSORS_UNBLOCK},
657   };
658   // Fields as for kBlockedAllowIDs, above.
659   static const ContentSettingsTypeIdEntry kAllowedAllowIDs[] = {
660       {ContentSettingsType::COOKIES, IDS_ALLOWED_COOKIES_NO_ACTION},
661       {ContentSettingsType::PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_NO_ACTION},
662       {ContentSettingsType::GEOLOCATION, IDS_ALLOWED_GEOLOCATION_NO_ACTION},
663       {ContentSettingsType::MIDI_SYSEX, IDS_ALLOWED_MIDI_SYSEX_NO_ACTION},
664       {ContentSettingsType::CLIPBOARD_READ_WRITE,
665        IDS_ALLOWED_CLIPBOARD_NO_ACTION},
666       {ContentSettingsType::SENSORS, IDS_ALLOWED_SENSORS_NO_ACTION},
667   };
668 
669   base::string16 radio_allow_label;
670   if (allowed) {
671     int resource_id = GetIdForContentType(
672         kAllowedAllowIDs, base::size(kAllowedAllowIDs), content_type());
673     radio_allow_label = l10n_util::GetStringUTF16(resource_id);
674   } else {
675     radio_allow_label = l10n_util::GetStringFUTF16(
676         GetIdForContentType(kBlockedAllowIDs, base::size(kBlockedAllowIDs),
677                             content_type()),
678         display_host);
679   }
680 
681   static const ContentSettingsTypeIdEntry kBlockedBlockIDs[] = {
682       {ContentSettingsType::COOKIES, IDS_BLOCKED_COOKIES_NO_ACTION},
683       {ContentSettingsType::IMAGES, IDS_BLOCKED_IMAGES_NO_ACTION},
684       {ContentSettingsType::JAVASCRIPT, IDS_BLOCKED_JAVASCRIPT_NO_ACTION},
685       {ContentSettingsType::POPUPS, IDS_BLOCKED_POPUPS_REDIRECTS_NO_ACTION},
686       {ContentSettingsType::PPAPI_BROKER, IDS_BLOCKED_PPAPI_BROKER_NO_ACTION},
687       {ContentSettingsType::SOUND, IDS_BLOCKED_SOUND_NO_ACTION},
688       {ContentSettingsType::GEOLOCATION, IDS_BLOCKED_GEOLOCATION_NO_ACTION},
689       {ContentSettingsType::MIDI_SYSEX, IDS_BLOCKED_MIDI_SYSEX_NO_ACTION},
690       {ContentSettingsType::CLIPBOARD_READ_WRITE,
691        IDS_BLOCKED_CLIPBOARD_NO_ACTION},
692       {ContentSettingsType::SENSORS, IDS_BLOCKED_SENSORS_NO_ACTION},
693   };
694   static const ContentSettingsTypeIdEntry kAllowedBlockIDs[] = {
695       {ContentSettingsType::COOKIES, IDS_ALLOWED_COOKIES_BLOCK},
696       {ContentSettingsType::PPAPI_BROKER, IDS_ALLOWED_PPAPI_BROKER_BLOCK},
697       {ContentSettingsType::GEOLOCATION, IDS_ALLOWED_GEOLOCATION_BLOCK},
698       {ContentSettingsType::MIDI_SYSEX, IDS_ALLOWED_MIDI_SYSEX_BLOCK},
699       {ContentSettingsType::CLIPBOARD_READ_WRITE, IDS_ALLOWED_CLIPBOARD_BLOCK},
700       {ContentSettingsType::SENSORS, IDS_ALLOWED_SENSORS_BLOCK},
701   };
702 
703   base::string16 radio_block_label;
704   if (allowed) {
705     int resource_id = GetIdForContentType(
706         kAllowedBlockIDs, base::size(kAllowedBlockIDs), content_type());
707     radio_block_label = l10n_util::GetStringFUTF16(resource_id, display_host);
708   } else {
709     radio_block_label = l10n_util::GetStringUTF16(GetIdForContentType(
710         kBlockedBlockIDs, base::size(kBlockedBlockIDs), content_type()));
711   }
712 
713   radio_group.radio_items = {radio_allow_label, radio_block_label};
714 
715   ContentSetting setting;
716   radio_group.user_managed =
717       GetSettingManagedByUser(url, content_type(), GetProfile(), &setting);
718   if (setting == CONTENT_SETTING_ALLOW) {
719     radio_group.default_item = kAllowButtonIndex;
720     // |block_setting_| is already set to |CONTENT_SETTING_BLOCK|.
721   } else {
722     radio_group.default_item = 1;
723     block_setting_ = setting;
724   }
725   set_radio_group(radio_group);
726 }
727 
SetNarrowestContentSetting(ContentSetting setting)728 void ContentSettingSingleRadioGroup::SetNarrowestContentSetting(
729     ContentSetting setting) {
730   if (!GetProfile())
731     return;
732 
733   auto* map = HostContentSettingsMapFactory::GetForProfile(GetProfile());
734   map->SetNarrowestContentSetting(bubble_content().radio_group.url,
735                                   bubble_content().radio_group.url,
736                                   content_type(), setting);
737 }
738 
739 // ContentSettingCookiesBubbleModel --------------------------------------------
740 
741 class ContentSettingCookiesBubbleModel : public ContentSettingSingleRadioGroup {
742  public:
743   ContentSettingCookiesBubbleModel(Delegate* delegate,
744                                    WebContents* web_contents);
745   ~ContentSettingCookiesBubbleModel() override;
746 
747   // ContentSettingBubbleModel:
748   void CommitChanges() override;
749 
750  private:
751   void OnCustomLinkClicked() override;
752 
753   DISALLOW_COPY_AND_ASSIGN(ContentSettingCookiesBubbleModel);
754 };
755 
ContentSettingCookiesBubbleModel(Delegate * delegate,WebContents * web_contents)756 ContentSettingCookiesBubbleModel::ContentSettingCookiesBubbleModel(
757     Delegate* delegate,
758     WebContents* web_contents)
759     : ContentSettingSingleRadioGroup(delegate,
760                                      web_contents,
761                                      ContentSettingsType::COOKIES) {
762   set_custom_link_enabled(true);
763 }
764 
~ContentSettingCookiesBubbleModel()765 ContentSettingCookiesBubbleModel::~ContentSettingCookiesBubbleModel() {}
766 
CommitChanges()767 void ContentSettingCookiesBubbleModel::CommitChanges() {
768   // On some plattforms e.g. MacOS X it is possible to close a tab while the
769   // cookies settings bubble is open. This resets the web contents to NULL.
770   if (settings_changed()) {
771     CollectedCookiesInfoBarDelegate::Create(
772         InfoBarService::FromWebContents(web_contents()));
773   }
774   ContentSettingSingleRadioGroup::CommitChanges();
775 }
776 
OnCustomLinkClicked()777 void ContentSettingCookiesBubbleModel::OnCustomLinkClicked() {
778   delegate()->ShowCollectedCookiesDialog(web_contents());
779 }
780 
781 // ContentSettingPopupBubbleModel ----------------------------------------------
782 
783 class ContentSettingPopupBubbleModel
784     : public ContentSettingSingleRadioGroup,
785       public blocked_content::UrlListManager::Observer {
786  public:
787   ContentSettingPopupBubbleModel(Delegate* delegate, WebContents* web_contents);
788   ~ContentSettingPopupBubbleModel() override;
789 
790   // ContentSettingBubbleModel:
791   void CommitChanges() override;
792 
793   // PopupBlockerTabHelper::Observer:
794   void BlockedUrlAdded(int32_t id, const GURL& url) override;
795 
796  private:
797   void OnListItemClicked(int index, const ui::Event& event) override;
798 
item_id_from_item_index(int index) const799   int32_t item_id_from_item_index(int index) const {
800     return bubble_content().list_items[index].item_id;
801   }
802 
803   ScopedObserver<blocked_content::UrlListManager,
804                  blocked_content::UrlListManager::Observer>
805       url_list_observer_;
806 
807   DISALLOW_COPY_AND_ASSIGN(ContentSettingPopupBubbleModel);
808 };
809 
ContentSettingPopupBubbleModel(Delegate * delegate,WebContents * web_contents)810 ContentSettingPopupBubbleModel::ContentSettingPopupBubbleModel(
811     Delegate* delegate,
812     WebContents* web_contents)
813     : ContentSettingSingleRadioGroup(delegate,
814                                      web_contents,
815                                      ContentSettingsType::POPUPS),
816       url_list_observer_(this) {
817   set_title(l10n_util::GetStringUTF16(IDS_BLOCKED_POPUPS_TITLE));
818 
819   // Build blocked popup list.
820   auto* helper =
821       blocked_content::PopupBlockerTabHelper::FromWebContents(web_contents);
822   std::map<int32_t, GURL> blocked_popups = helper->GetBlockedPopupRequests();
823   for (const auto& blocked_popup : blocked_popups)
824     AddListItem(CreateUrlListItem(blocked_popup.first, blocked_popup.second));
825 
826   url_list_observer_.Add(helper->manager());
827   content_settings::RecordPopupsAction(
828       content_settings::POPUPS_ACTION_DISPLAYED_BUBBLE);
829 }
830 
BlockedUrlAdded(int32_t id,const GURL & url)831 void ContentSettingPopupBubbleModel::BlockedUrlAdded(int32_t id,
832                                                      const GURL& url) {
833   AddListItem(CreateUrlListItem(id, url));
834 }
835 
OnListItemClicked(int index,const ui::Event & event)836 void ContentSettingPopupBubbleModel::OnListItemClicked(int index,
837                                                        const ui::Event& event) {
838   auto* helper =
839       blocked_content::PopupBlockerTabHelper::FromWebContents(web_contents());
840   helper->ShowBlockedPopup(item_id_from_item_index(index),
841                            ui::DispositionFromEventFlags(event.flags()));
842   RemoveListItem(index);
843   content_settings::RecordPopupsAction(
844       content_settings::POPUPS_ACTION_CLICKED_LIST_ITEM_CLICKED);
845 }
846 
CommitChanges()847 void ContentSettingPopupBubbleModel::CommitChanges() {
848   // User selected to always allow pop-ups from.
849   if (settings_changed() && selected_item() == kAllowButtonIndex) {
850     // Increases the counter.
851     content_settings::RecordPopupsAction(
852         content_settings::POPUPS_ACTION_SELECTED_ALWAYS_ALLOW_POPUPS_FROM);
853   }
854   ContentSettingSingleRadioGroup::CommitChanges();
855 }
856 
857 ContentSettingPopupBubbleModel::~ContentSettingPopupBubbleModel() = default;
858 
859 // ContentSettingMediaStreamBubbleModel ----------------------------------------
860 
861 namespace {
862 
GetMediaDeviceById(const std::string & device_id,const blink::MediaStreamDevices & devices)863 const blink::MediaStreamDevice& GetMediaDeviceById(
864     const std::string& device_id,
865     const blink::MediaStreamDevices& devices) {
866   DCHECK(!devices.empty());
867   for (const blink::MediaStreamDevice& device : devices) {
868     if (device.id == device_id)
869       return device;
870   }
871 
872   // A device with the |device_id| was not found. It is likely that the device
873   // has been unplugged from the OS. Return the first device as the default
874   // device.
875   return *devices.begin();
876 }
877 
878 }  // namespace
879 
ContentSettingMediaStreamBubbleModel(Delegate * delegate,WebContents * web_contents)880 ContentSettingMediaStreamBubbleModel::ContentSettingMediaStreamBubbleModel(
881     Delegate* delegate,
882     WebContents* web_contents)
883     : ContentSettingBubbleModel(delegate, web_contents),
884       state_(PageSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED) {
885   // TODO(msramek): The media bubble has three states - mic only, camera only,
886   // and both. There is a lot of duplicated code which does the same thing
887   // for camera and microphone separately. Consider refactoring it to avoid
888   // duplication.
889 
890   // Initialize the content settings associated with the individual radio
891   // buttons.
892   radio_item_setting_[0] = CONTENT_SETTING_ASK;
893   radio_item_setting_[1] = CONTENT_SETTING_BLOCK;
894 
895   PageSpecificContentSettings* content_settings =
896       PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame());
897   state_ = content_settings->GetMicrophoneCameraState();
898   DCHECK(CameraAccessed() || MicrophoneAccessed());
899 
900   // If the permission is turned off in MacOS system preferences, overwrite
901   // the bubble to enable the user to trigger the system dialog.
902   if (ShouldShowSystemMediaPermissions()) {
903 #if defined(OS_MAC)
904     InitializeSystemMediaPermissionBubble();
905     return;
906 #endif  // defined(OS_MAC)
907   }
908 
909   SetTitle();
910   SetMessage();
911   SetRadioGroup();
912   SetMediaMenus();
913   SetManageText();
914   SetCustomLink();
915 }
916 
~ContentSettingMediaStreamBubbleModel()917 ContentSettingMediaStreamBubbleModel::~ContentSettingMediaStreamBubbleModel() {}
918 
CommitChanges()919 void ContentSettingMediaStreamBubbleModel::CommitChanges() {
920   for (const auto& media_menu : bubble_content().media_menus) {
921     const MediaMenu& menu = media_menu.second;
922     if (menu.selected_device.id != menu.default_device.id)
923       UpdateDefaultDeviceForType(media_menu.first, menu.selected_device.id);
924   }
925 
926   // No need for radio group in the bubble UI shown when permission is blocked
927   // on a system level.
928   if (!ShouldShowSystemMediaPermissions()) {
929     // Update the media settings if the radio button selection was changed.
930     if (selected_item() != bubble_content().radio_group.default_item)
931       UpdateSettings(radio_item_setting_[selected_item()]);
932   }
933 }
934 
935 ContentSettingMediaStreamBubbleModel*
AsMediaStreamBubbleModel()936 ContentSettingMediaStreamBubbleModel::AsMediaStreamBubbleModel() {
937   return this;
938 }
939 
OnManageButtonClicked()940 void ContentSettingMediaStreamBubbleModel::OnManageButtonClicked() {
941   DCHECK(CameraAccessed() || MicrophoneAccessed());
942   if (!delegate())
943     return;
944 
945   if (MicrophoneAccessed() && CameraAccessed()) {
946     delegate()->ShowMediaSettingsPage();
947   } else {
948     delegate()->ShowContentSettingsPage(
949         CameraAccessed() ? ContentSettingsType::MEDIASTREAM_CAMERA
950                          : ContentSettingsType::MEDIASTREAM_MIC);
951   }
952 }
953 
OnDoneButtonClicked()954 void ContentSettingMediaStreamBubbleModel::OnDoneButtonClicked() {
955   if (ShouldShowSystemMediaPermissions()) {
956 #if defined(OS_MAC)
957     DCHECK(CameraAccessed() || MicrophoneAccessed());
958 
959     base::RecordAction(UserMetricsAction("Media.OpenPreferencesClicked"));
960     DCHECK(ShouldShowSystemMediaPermissions());
961 
962     if (CameraAccessed()) {
963       ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(
964           GURL(kCameraSettingsURI), web_contents());
965     } else if (MicrophoneAccessed()) {
966       ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(
967           GURL(kMicSettingsURI), web_contents());
968     }
969     return;
970 #endif  // defined(OS_MAC)
971   }
972 }
973 
MicrophoneAccessed() const974 bool ContentSettingMediaStreamBubbleModel::MicrophoneAccessed() const {
975   return (state_ & PageSpecificContentSettings::MICROPHONE_ACCESSED) != 0;
976 }
977 
CameraAccessed() const978 bool ContentSettingMediaStreamBubbleModel::CameraAccessed() const {
979   return (state_ & PageSpecificContentSettings::CAMERA_ACCESSED) != 0;
980 }
981 
MicrophoneBlocked() const982 bool ContentSettingMediaStreamBubbleModel::MicrophoneBlocked() const {
983   return (state_ & PageSpecificContentSettings::MICROPHONE_BLOCKED) != 0;
984 }
985 
CameraBlocked() const986 bool ContentSettingMediaStreamBubbleModel::CameraBlocked() const {
987   return (state_ & PageSpecificContentSettings::CAMERA_BLOCKED) != 0;
988 }
989 
SetTitle()990 void ContentSettingMediaStreamBubbleModel::SetTitle() {
991   DCHECK(CameraAccessed() || MicrophoneAccessed());
992   int title_id = 0;
993   if (MicrophoneBlocked() && CameraBlocked())
994     title_id = IDS_MICROPHONE_CAMERA_BLOCKED_TITLE;
995   else if (MicrophoneBlocked())
996     title_id = IDS_MICROPHONE_BLOCKED_TITLE;
997   else if (CameraBlocked())
998     title_id = IDS_CAMERA_BLOCKED_TITLE;
999   else if (MicrophoneAccessed() && CameraAccessed())
1000     title_id = IDS_MICROPHONE_CAMERA_ALLOWED_TITLE;
1001   else if (MicrophoneAccessed())
1002     title_id = IDS_MICROPHONE_ACCESSED_TITLE;
1003   else if (CameraAccessed())
1004     title_id = IDS_CAMERA_ACCESSED_TITLE;
1005   else
1006     NOTREACHED();
1007   set_title(l10n_util::GetStringUTF16(title_id));
1008 }
1009 
SetMessage()1010 void ContentSettingMediaStreamBubbleModel::SetMessage() {
1011   DCHECK(CameraAccessed() || MicrophoneAccessed());
1012   int message_id = 0;
1013   if (MicrophoneBlocked() && CameraBlocked())
1014     message_id = IDS_MICROPHONE_CAMERA_BLOCKED;
1015   else if (MicrophoneBlocked())
1016     message_id = IDS_MICROPHONE_BLOCKED;
1017   else if (CameraBlocked())
1018     message_id = IDS_CAMERA_BLOCKED;
1019   else if (MicrophoneAccessed() && CameraAccessed())
1020     message_id = IDS_MICROPHONE_CAMERA_ALLOWED;
1021   else if (MicrophoneAccessed())
1022     message_id = IDS_MICROPHONE_ACCESSED;
1023   else if (CameraAccessed())
1024     message_id = IDS_CAMERA_ACCESSED;
1025   else
1026     NOTREACHED();
1027   set_message(l10n_util::GetStringUTF16(message_id));
1028 }
1029 
SetRadioGroup()1030 void ContentSettingMediaStreamBubbleModel::SetRadioGroup() {
1031   PageSpecificContentSettings* content_settings =
1032       PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame());
1033   GURL url = content_settings->media_stream_access_origin();
1034   RadioGroup radio_group;
1035   radio_group.url = url;
1036 
1037   base::string16 display_host = url_formatter::FormatUrlForSecurityDisplay(url);
1038 
1039   DCHECK(CameraAccessed() || MicrophoneAccessed());
1040   int radio_allow_label_id = 0;
1041   int radio_block_label_id = 0;
1042   if (state_ & (PageSpecificContentSettings::MICROPHONE_BLOCKED |
1043                 PageSpecificContentSettings::CAMERA_BLOCKED)) {
1044     if (blink::network_utils::IsOriginSecure(url)) {
1045       radio_item_setting_[0] = CONTENT_SETTING_ALLOW;
1046       radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ALLOW;
1047       if (MicrophoneAccessed())
1048         radio_allow_label_id =
1049             CameraAccessed() ? IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ALLOW
1050                              : IDS_BLOCKED_MEDIASTREAM_MIC_ALLOW;
1051     } else {
1052       radio_allow_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_ASK;
1053       if (MicrophoneAccessed())
1054         radio_allow_label_id = CameraAccessed()
1055                                    ? IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_ASK
1056                                    : IDS_BLOCKED_MEDIASTREAM_MIC_ASK;
1057     }
1058     radio_block_label_id = IDS_BLOCKED_MEDIASTREAM_CAMERA_NO_ACTION;
1059     if (MicrophoneAccessed())
1060       radio_block_label_id =
1061           CameraAccessed() ? IDS_BLOCKED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION
1062                            : IDS_BLOCKED_MEDIASTREAM_MIC_NO_ACTION;
1063   } else {
1064     permissions::PermissionManager* permission_manager =
1065         permissions::PermissionsClient::Get()->GetPermissionManager(
1066             web_contents()->GetBrowserContext());
1067     permissions::PermissionResult pan_tilt_zoom_permission =
1068         permission_manager->GetPermissionStatusForFrame(
1069             ContentSettingsType::CAMERA_PAN_TILT_ZOOM,
1070             web_contents()->GetMainFrame(), url);
1071     bool has_pan_tilt_zoom_permission_granted =
1072         pan_tilt_zoom_permission.content_setting == CONTENT_SETTING_ALLOW;
1073     if (MicrophoneAccessed() && CameraAccessed()) {
1074       radio_allow_label_id =
1075           has_pan_tilt_zoom_permission_granted
1076               ? IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_PAN_TILT_ZOOM_NO_ACTION
1077               : IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_NO_ACTION;
1078       radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_AND_CAMERA_BLOCK;
1079     } else if (MicrophoneAccessed()) {
1080       radio_allow_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_NO_ACTION;
1081       radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_MIC_BLOCK;
1082     } else {
1083       radio_allow_label_id = has_pan_tilt_zoom_permission_granted
1084                                  ? IDS_ALLOWED_CAMERA_PAN_TILT_ZOOM_NO_ACTION
1085                                  : IDS_ALLOWED_MEDIASTREAM_CAMERA_NO_ACTION;
1086       radio_block_label_id = IDS_ALLOWED_MEDIASTREAM_CAMERA_BLOCK;
1087     }
1088   }
1089 
1090   base::string16 radio_allow_label =
1091       l10n_util::GetStringFUTF16(radio_allow_label_id, display_host);
1092   base::string16 radio_block_label =
1093       l10n_util::GetStringUTF16(radio_block_label_id);
1094 
1095   radio_group.default_item =
1096       (MicrophoneAccessed() && content_settings->IsContentBlocked(
1097                                    ContentSettingsType::MEDIASTREAM_MIC)) ||
1098               (CameraAccessed() && content_settings->IsContentBlocked(
1099                                        ContentSettingsType::MEDIASTREAM_CAMERA))
1100           ? 1
1101           : 0;
1102   radio_group.radio_items = {radio_allow_label, radio_block_label};
1103   radio_group.user_managed = true;
1104 
1105   set_radio_group(radio_group);
1106 }
1107 
UpdateSettings(ContentSetting setting)1108 void ContentSettingMediaStreamBubbleModel::UpdateSettings(
1109     ContentSetting setting) {
1110   PageSpecificContentSettings* page_content_settings =
1111       PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame());
1112   // The same urls must be used as in other places (e.g. the infobar) in
1113   // order to override the existing rule. Otherwise a new rule is created.
1114   // TODO(markusheintz): Extract to a helper so that there is only a single
1115   // place to touch.
1116   HostContentSettingsMap* map =
1117       HostContentSettingsMapFactory::GetForProfile(GetProfile());
1118   if (MicrophoneAccessed()) {
1119     permissions::PermissionUmaUtil::ScopedRevocationReporter
1120         scoped_revocation_reporter(
1121             GetProfile(), page_content_settings->media_stream_access_origin(),
1122             GURL(), ContentSettingsType::MEDIASTREAM_MIC,
1123             permissions::PermissionSourceUI::PAGE_ACTION);
1124     map->SetContentSettingDefaultScope(
1125         page_content_settings->media_stream_access_origin(), GURL(),
1126         ContentSettingsType::MEDIASTREAM_MIC, setting);
1127   }
1128   if (CameraAccessed()) {
1129     permissions::PermissionUmaUtil::ScopedRevocationReporter
1130         scoped_revocation_reporter(
1131             GetProfile(), page_content_settings->media_stream_access_origin(),
1132             GURL(), ContentSettingsType::MEDIASTREAM_CAMERA,
1133             permissions::PermissionSourceUI::PAGE_ACTION);
1134     map->SetContentSettingDefaultScope(
1135         page_content_settings->media_stream_access_origin(), GURL(),
1136         ContentSettingsType::MEDIASTREAM_CAMERA, setting);
1137   }
1138 }
1139 
1140 #if defined(OS_MAC)
1141 void ContentSettingMediaStreamBubbleModel::
InitializeSystemMediaPermissionBubble()1142     InitializeSystemMediaPermissionBubble() {
1143   DCHECK(CameraAccessed() || MicrophoneAccessed());
1144   base::RecordAction(
1145       base::UserMetricsAction("Media.ShowSystemMediaPermissionBubble"));
1146   int title_id = 0;
1147   if (MicrophoneAccessed() && CameraAccessed() &&
1148       (system_media_permissions::CheckSystemVideoCapturePermission() ==
1149            system_media_permissions::SystemPermission::kDenied ||
1150        system_media_permissions::CheckSystemAudioCapturePermission() ==
1151            system_media_permissions::SystemPermission::kDenied)) {
1152     title_id = IDS_CAMERA_MIC_TURNED_OFF_IN_MACOS;
1153     AddListItem(ContentSettingBubbleModel::ListItem(
1154         &vector_icons::kVideocamIcon, l10n_util::GetStringUTF16(IDS_CAMERA),
1155         l10n_util::GetStringUTF16(IDS_TURNED_OFF), false, true, 0));
1156     AddListItem(ContentSettingBubbleModel::ListItem(
1157         &vector_icons::kMicIcon, l10n_util::GetStringUTF16(IDS_MIC),
1158         l10n_util::GetStringUTF16(IDS_TURNED_OFF), false, true, 1));
1159   } else if (CameraAccessed() &&
1160              system_media_permissions::CheckSystemVideoCapturePermission() ==
1161                  system_media_permissions::SystemPermission::kDenied) {
1162     title_id = IDS_CAMERA_TURNED_OFF_IN_MACOS;
1163     AddListItem(ContentSettingBubbleModel::ListItem(
1164         &vector_icons::kVideocamIcon, l10n_util::GetStringUTF16(IDS_CAMERA),
1165         l10n_util::GetStringUTF16(IDS_TURNED_OFF), false, true, 0));
1166   } else if (MicrophoneAccessed() &&
1167              system_media_permissions::CheckSystemAudioCapturePermission() ==
1168                  system_media_permissions::SystemPermission::kDenied) {
1169     title_id = IDS_MIC_TURNED_OFF_IN_MACOS;
1170     AddListItem(ContentSettingBubbleModel::ListItem(
1171         &vector_icons::kMicIcon, l10n_util::GetStringUTF16(IDS_MIC),
1172         l10n_util::GetStringUTF16(IDS_TURNED_OFF), false, true, 1));
1173   }
1174 
1175   set_title(l10n_util::GetStringUTF16(title_id));
1176   set_manage_text_style(ContentSettingBubbleModel::ManageTextStyle::kNone);
1177   SetCustomLink();
1178   set_done_button_text(l10n_util::GetStringUTF16(IDS_OPEN_PREFERENCES_LINK));
1179 }
1180 #endif  // defined(OS_MAC)
1181 
ShouldShowSystemMediaPermissions()1182 bool ContentSettingMediaStreamBubbleModel::ShouldShowSystemMediaPermissions() {
1183 #if defined(OS_MAC)
1184   return (((system_media_permissions::CheckSystemVideoCapturePermission() ==
1185                 system_media_permissions::SystemPermission::kDenied &&
1186             CameraAccessed() && !CameraBlocked()) ||
1187            (system_media_permissions::CheckSystemAudioCapturePermission() ==
1188                 system_media_permissions::SystemPermission::kDenied &&
1189             MicrophoneAccessed() && !MicrophoneBlocked())) &&
1190           !(CameraAccessed() && CameraBlocked()) &&
1191           !(MicrophoneAccessed() && MicrophoneBlocked()) &&
1192           base::FeatureList::IsEnabled(
1193               ::features::kMacSystemMediaPermissionsInfoUi));
1194 #else
1195   return false;
1196 #endif  // defined(OS_MAC)
1197 }
1198 
UpdateDefaultDeviceForType(blink::mojom::MediaStreamType type,const std::string & device)1199 void ContentSettingMediaStreamBubbleModel::UpdateDefaultDeviceForType(
1200     blink::mojom::MediaStreamType type,
1201     const std::string& device) {
1202   PrefService* prefs = GetProfile()->GetPrefs();
1203   if (type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) {
1204     prefs->SetString(prefs::kDefaultAudioCaptureDevice, device);
1205   } else {
1206     DCHECK_EQ(blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE, type);
1207     prefs->SetString(prefs::kDefaultVideoCaptureDevice, device);
1208   }
1209 }
1210 
SetMediaMenus()1211 void ContentSettingMediaStreamBubbleModel::SetMediaMenus() {
1212   PageSpecificContentSettings* content_settings =
1213       PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame());
1214   const std::string& requested_microphone =
1215       content_settings->media_stream_requested_audio_device();
1216   const std::string& requested_camera =
1217       content_settings->media_stream_requested_video_device();
1218 
1219   // Add microphone menu.
1220   PrefService* prefs = GetProfile()->GetPrefs();
1221   MediaCaptureDevicesDispatcher* dispatcher =
1222       MediaCaptureDevicesDispatcher::GetInstance();
1223 
1224   if (MicrophoneAccessed()) {
1225     const blink::MediaStreamDevices& microphones =
1226         dispatcher->GetAudioCaptureDevices();
1227     MediaMenu mic_menu;
1228     mic_menu.label = l10n_util::GetStringUTF16(IDS_MEDIA_SELECTED_MIC_LABEL);
1229     if (!microphones.empty()) {
1230       std::string preferred_mic;
1231       if (requested_microphone.empty()) {
1232         preferred_mic = prefs->GetString(prefs::kDefaultAudioCaptureDevice);
1233         mic_menu.disabled = false;
1234       } else {
1235         // Set the |disabled| to true in order to disable the device selection
1236         // menu on the media settings bubble. This must be done if the website
1237         // manages the microphone devices itself.
1238         preferred_mic = requested_microphone;
1239         mic_menu.disabled = true;
1240       }
1241 
1242       mic_menu.default_device = GetMediaDeviceById(preferred_mic, microphones);
1243       mic_menu.selected_device = mic_menu.default_device;
1244     }
1245     add_media_menu(blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE,
1246                    mic_menu);
1247   }
1248 
1249   if (CameraAccessed()) {
1250     const blink::MediaStreamDevices& cameras =
1251         dispatcher->GetVideoCaptureDevices();
1252     MediaMenu camera_menu;
1253     camera_menu.label =
1254         l10n_util::GetStringUTF16(IDS_MEDIA_SELECTED_CAMERA_LABEL);
1255     if (!cameras.empty()) {
1256       std::string preferred_camera;
1257       if (requested_camera.empty()) {
1258         preferred_camera = prefs->GetString(prefs::kDefaultVideoCaptureDevice);
1259         camera_menu.disabled = false;
1260       } else {
1261         // Disable the menu since the website is managing the camera devices
1262         // itself.
1263         preferred_camera = requested_camera;
1264         camera_menu.disabled = true;
1265       }
1266 
1267       camera_menu.default_device =
1268           GetMediaDeviceById(preferred_camera, cameras);
1269       camera_menu.selected_device = camera_menu.default_device;
1270     }
1271     add_media_menu(blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE,
1272                    camera_menu);
1273   }
1274 }
1275 
SetManageText()1276 void ContentSettingMediaStreamBubbleModel::SetManageText() {
1277   DCHECK(CameraAccessed() || MicrophoneAccessed());
1278   set_manage_text(l10n_util::GetStringUTF16(IDS_MANAGE));
1279 }
1280 
SetCustomLink()1281 void ContentSettingMediaStreamBubbleModel::SetCustomLink() {
1282   PageSpecificContentSettings* content_settings =
1283       PageSpecificContentSettings::GetForFrame(web_contents()->GetMainFrame());
1284   if (content_settings->IsMicrophoneCameraStateChanged()) {
1285     set_custom_link(
1286         l10n_util::GetStringUTF16(IDS_MEDIASTREAM_SETTING_CHANGED_MESSAGE));
1287   }
1288 }
1289 
OnMediaMenuClicked(blink::mojom::MediaStreamType type,const std::string & selected_device_id)1290 void ContentSettingMediaStreamBubbleModel::OnMediaMenuClicked(
1291     blink::mojom::MediaStreamType type,
1292     const std::string& selected_device_id) {
1293   DCHECK(type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE ||
1294          type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE);
1295   DCHECK_EQ(1U, bubble_content().media_menus.count(type));
1296   MediaCaptureDevicesDispatcher* dispatcher =
1297       MediaCaptureDevicesDispatcher::GetInstance();
1298   const blink::MediaStreamDevices& devices =
1299       (type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE)
1300           ? dispatcher->GetAudioCaptureDevices()
1301           : dispatcher->GetVideoCaptureDevices();
1302   set_selected_device(GetMediaDeviceById(selected_device_id, devices));
1303 }
1304 
1305 // ContentSettingGeolocationBubbleModel --------------------------------------
1306 
ContentSettingGeolocationBubbleModel(Delegate * delegate,content::WebContents * web_contents)1307 ContentSettingGeolocationBubbleModel::ContentSettingGeolocationBubbleModel(
1308     Delegate* delegate,
1309     content::WebContents* web_contents)
1310     : ContentSettingSingleRadioGroup(delegate,
1311                                      web_contents,
1312                                      ContentSettingsType::GEOLOCATION) {
1313   SetCustomLink();
1314 #if defined(OS_MAC)
1315   if (base::FeatureList::IsEnabled(
1316           ::features::kMacCoreLocationImplementation)) {
1317     PageSpecificContentSettings* content_settings =
1318         PageSpecificContentSettings::GetForFrame(web_contents->GetMainFrame());
1319     if (!content_settings)
1320       return;
1321 
1322     bool is_allowed =
1323         content_settings->IsContentAllowed(ContentSettingsType::GEOLOCATION);
1324 
1325     GeolocationSystemPermissionManager* permission_delegate =
1326         g_browser_process->platform_part()->location_permission_manager();
1327     SystemPermissionStatus permission =
1328         permission_delegate->GetSystemPermission();
1329     if (permission != SystemPermissionStatus::kAllowed && is_allowed) {
1330       // If the permission is turned off in MacOS system preferences, overwrite
1331       // the bubble to enable the user to trigger the system dialog.
1332       InitializeSystemGeolocationPermissionBubble();
1333     }
1334   }
1335 #endif  // defined(OS_MAC)
1336 }
1337 
1338 ContentSettingGeolocationBubbleModel::~ContentSettingGeolocationBubbleModel() =
1339     default;
1340 
OnDoneButtonClicked()1341 void ContentSettingGeolocationBubbleModel::OnDoneButtonClicked() {
1342   if (show_system_geolocation_bubble_) {
1343 #if defined(OS_MAC)
1344     ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(
1345         GURL(kLocationSettingsURI), web_contents());
1346     return;
1347 #endif  // defined(OS_MAC)
1348   }
1349 }
1350 
OnManageButtonClicked()1351 void ContentSettingGeolocationBubbleModel::OnManageButtonClicked() {
1352   if (delegate())
1353     delegate()->ShowContentSettingsPage(ContentSettingsType::GEOLOCATION);
1354 }
1355 
CommitChanges()1356 void ContentSettingGeolocationBubbleModel::CommitChanges() {
1357   if (show_system_geolocation_bubble_)
1358     return;
1359   ContentSettingSingleRadioGroup::CommitChanges();
1360 }
1361 
1362 void ContentSettingGeolocationBubbleModel::
InitializeSystemGeolocationPermissionBubble()1363     InitializeSystemGeolocationPermissionBubble() {
1364 #if defined(OS_MAC)
1365   set_title(l10n_util::GetStringUTF16(IDS_GEOLOCATION_TURNED_OFF_IN_MACOS));
1366   clear_message();
1367   AddListItem(ContentSettingBubbleModel::ListItem(
1368       &vector_icons::kLocationOnIcon,
1369       l10n_util::GetStringUTF16(IDS_GEOLOCATION),
1370       l10n_util::GetStringUTF16(IDS_TURNED_OFF), false, true, 0));
1371   set_manage_text_style(ContentSettingBubbleModel::ManageTextStyle::kNone);
1372   set_done_button_text(l10n_util::GetStringUTF16(IDS_OPEN_PREFERENCES_LINK));
1373   set_radio_group(RadioGroup());
1374   show_system_geolocation_bubble_ = true;
1375 #endif  // defined(OS_MAC)
1376 }
1377 
SetCustomLink()1378 void ContentSettingGeolocationBubbleModel::SetCustomLink() {
1379   auto* map = HostContentSettingsMapFactory::GetForProfile(
1380       web_contents()->GetBrowserContext());
1381   SettingInfo info;
1382   const GURL url =
1383       web_contents()->GetMainFrame()->GetLastCommittedOrigin().GetURL();
1384   map->GetWebsiteSetting(url, url, ContentSettingsType::GEOLOCATION, &info);
1385   if (info.session_model == SessionModel::OneTime)
1386     set_custom_link(l10n_util::GetStringUTF16(IDS_GEOLOCATION_WILL_ASK_AGAIN));
1387 }
1388 
1389 // ContentSettingSubresourceFilterBubbleModel ----------------------------------
1390 
1391 ContentSettingSubresourceFilterBubbleModel::
ContentSettingSubresourceFilterBubbleModel(Delegate * delegate,WebContents * web_contents)1392     ContentSettingSubresourceFilterBubbleModel(Delegate* delegate,
1393                                                WebContents* web_contents)
1394     : ContentSettingBubbleModel(delegate, web_contents) {
1395   SetTitle();
1396   SetMessage();
1397   SetManageText();
1398   set_done_button_text(l10n_util::GetStringUTF16(IDS_OK));
1399   set_show_learn_more(true);
1400   subresource_filter::ContentSubresourceFilterThrottleManager::LogAction(
1401       subresource_filter::SubresourceFilterAction::kDetailsShown);
1402 }
1403 
1404 ContentSettingSubresourceFilterBubbleModel::
1405     ~ContentSettingSubresourceFilterBubbleModel() = default;
1406 
SetTitle()1407 void ContentSettingSubresourceFilterBubbleModel::SetTitle() {
1408   set_title(l10n_util::GetStringUTF16(IDS_BLOCKED_ADS_PROMPT_TITLE));
1409 }
1410 
SetManageText()1411 void ContentSettingSubresourceFilterBubbleModel::SetManageText() {
1412   set_manage_text(l10n_util::GetStringUTF16(IDS_ALWAYS_ALLOW_ADS));
1413   set_manage_text_style(ContentSettingBubbleModel::ManageTextStyle::kCheckbox);
1414 }
1415 
SetMessage()1416 void ContentSettingSubresourceFilterBubbleModel::SetMessage() {
1417   set_message(l10n_util::GetStringUTF16(IDS_BLOCKED_ADS_PROMPT_EXPLANATION));
1418 }
1419 
OnManageCheckboxChecked(bool is_checked)1420 void ContentSettingSubresourceFilterBubbleModel::OnManageCheckboxChecked(
1421     bool is_checked) {
1422   set_done_button_text(
1423       l10n_util::GetStringUTF16(is_checked ? IDS_APP_MENU_RELOAD : IDS_OK));
1424   is_checked_ = is_checked;
1425 }
1426 
OnLearnMoreClicked()1427 void ContentSettingSubresourceFilterBubbleModel::OnLearnMoreClicked() {
1428   DCHECK(delegate());
1429   subresource_filter::ContentSubresourceFilterThrottleManager::LogAction(
1430       subresource_filter::SubresourceFilterAction::kClickedLearnMore);
1431   delegate()->ShowLearnMorePage(ContentSettingsType::ADS);
1432 }
1433 
CommitChanges()1434 void ContentSettingSubresourceFilterBubbleModel::CommitChanges() {
1435   if (is_checked_) {
1436     subresource_filter::ContentSubresourceFilterThrottleManager::
1437         FromWebContents(web_contents())
1438             ->OnReloadRequested();
1439   }
1440 }
1441 
1442 ContentSettingSubresourceFilterBubbleModel*
AsSubresourceFilterBubbleModel()1443 ContentSettingSubresourceFilterBubbleModel::AsSubresourceFilterBubbleModel() {
1444   return this;
1445 }
1446 
1447 // ContentSettingDownloadsBubbleModel ------------------------------------------
1448 
ContentSettingDownloadsBubbleModel(Delegate * delegate,WebContents * web_contents)1449 ContentSettingDownloadsBubbleModel::ContentSettingDownloadsBubbleModel(
1450     Delegate* delegate,
1451     WebContents* web_contents)
1452     : ContentSettingBubbleModel(delegate, web_contents) {
1453   SetTitle();
1454   SetManageText();
1455   SetRadioGroup();
1456 }
1457 
~ContentSettingDownloadsBubbleModel()1458 ContentSettingDownloadsBubbleModel::~ContentSettingDownloadsBubbleModel() {}
1459 
CommitChanges()1460 void ContentSettingDownloadsBubbleModel::CommitChanges() {
1461   if (selected_item() != bubble_content().radio_group.default_item) {
1462     ContentSetting setting = selected_item() == kAllowButtonIndex
1463                                  ? CONTENT_SETTING_ALLOW
1464                                  : CONTENT_SETTING_BLOCK;
1465     auto* map = HostContentSettingsMapFactory::GetForProfile(GetProfile());
1466     map->SetNarrowestContentSetting(
1467         bubble_content().radio_group.url, bubble_content().radio_group.url,
1468         ContentSettingsType::AUTOMATIC_DOWNLOADS, setting);
1469   }
1470 }
1471 
1472 ContentSettingDownloadsBubbleModel*
AsDownloadsBubbleModel()1473 ContentSettingDownloadsBubbleModel::AsDownloadsBubbleModel() {
1474   return this;
1475 }
1476 
1477 // Initialize the radio group by setting the appropriate labels for the
1478 // content type and setting the default value based on the content setting.
SetRadioGroup()1479 void ContentSettingDownloadsBubbleModel::SetRadioGroup() {
1480   DownloadRequestLimiter* download_request_limiter =
1481       g_browser_process->download_request_limiter();
1482   const GURL& download_origin =
1483       download_request_limiter->GetDownloadOrigin(web_contents());
1484   base::string16 display_host =
1485       url_formatter::FormatUrlForSecurityDisplay(download_origin);
1486   DCHECK(download_request_limiter);
1487 
1488   RadioGroup radio_group;
1489   radio_group.url = download_origin;
1490   switch (download_request_limiter->GetDownloadUiStatus(web_contents())) {
1491     case DownloadRequestLimiter::DOWNLOAD_UI_ALLOWED:
1492       radio_group.radio_items = {
1493           l10n_util::GetStringUTF16(IDS_ALLOWED_DOWNLOAD_NO_ACTION),
1494           l10n_util::GetStringFUTF16(IDS_ALLOWED_DOWNLOAD_BLOCK, display_host)};
1495       radio_group.default_item = kAllowButtonIndex;
1496       break;
1497     case DownloadRequestLimiter::DOWNLOAD_UI_BLOCKED:
1498       radio_group.radio_items = {
1499           l10n_util::GetStringFUTF16(IDS_BLOCKED_DOWNLOAD_UNBLOCK,
1500                                      display_host),
1501           l10n_util::GetStringUTF16(IDS_BLOCKED_DOWNLOAD_NO_ACTION)};
1502       radio_group.default_item = 1;
1503       break;
1504     case DownloadRequestLimiter::DOWNLOAD_UI_DEFAULT:
1505       NOTREACHED();
1506       return;
1507   }
1508   radio_group.user_managed = GetSettingManagedByUser(
1509       download_origin, ContentSettingsType::AUTOMATIC_DOWNLOADS, GetProfile(),
1510       nullptr);
1511   set_radio_group(radio_group);
1512 }
1513 
SetTitle()1514 void ContentSettingDownloadsBubbleModel::SetTitle() {
1515   DownloadRequestLimiter* download_request_limiter =
1516       g_browser_process->download_request_limiter();
1517   DCHECK(download_request_limiter);
1518 
1519   switch (download_request_limiter->GetDownloadUiStatus(web_contents())) {
1520     case DownloadRequestLimiter::DOWNLOAD_UI_ALLOWED:
1521       set_title(l10n_util::GetStringUTF16(IDS_ALLOWED_DOWNLOAD_TITLE));
1522       return;
1523     case DownloadRequestLimiter::DOWNLOAD_UI_BLOCKED:
1524       set_title(l10n_util::GetStringUTF16(IDS_BLOCKED_DOWNLOAD_TITLE));
1525       return;
1526     case DownloadRequestLimiter::DOWNLOAD_UI_DEFAULT:
1527       // No title otherwise.
1528       return;
1529   }
1530 }
1531 
SetManageText()1532 void ContentSettingDownloadsBubbleModel::SetManageText() {
1533   set_manage_text(l10n_util::GetStringUTF16(IDS_MANAGE));
1534 }
1535 
OnManageButtonClicked()1536 void ContentSettingDownloadsBubbleModel::OnManageButtonClicked() {
1537   if (delegate())
1538     delegate()->ShowContentSettingsPage(
1539         ContentSettingsType::AUTOMATIC_DOWNLOADS);
1540 }
1541 
1542 // ContentSettingFramebustBlockBubbleModel -------------------------------------
1543 ContentSettingFramebustBlockBubbleModel::
ContentSettingFramebustBlockBubbleModel(Delegate * delegate,WebContents * web_contents)1544     ContentSettingFramebustBlockBubbleModel(Delegate* delegate,
1545                                             WebContents* web_contents)
1546     : ContentSettingSingleRadioGroup(delegate,
1547                                      web_contents,
1548                                      ContentSettingsType::POPUPS),
1549       url_list_observer_(this) {
1550   set_title(l10n_util::GetStringUTF16(IDS_REDIRECT_BLOCKED_MESSAGE));
1551   auto* helper = FramebustBlockTabHelper::FromWebContents(web_contents);
1552 
1553   // Build the blocked urls list.
1554   for (const auto& blocked_url : helper->blocked_urls())
1555     AddListItem(CreateUrlListItem(0 /* id */, blocked_url));
1556 
1557   url_list_observer_.Add(helper->manager());
1558 }
1559 
1560 ContentSettingFramebustBlockBubbleModel::
1561     ~ContentSettingFramebustBlockBubbleModel() = default;
1562 
OnListItemClicked(int index,const ui::Event & event)1563 void ContentSettingFramebustBlockBubbleModel::OnListItemClicked(
1564     int index,
1565     const ui::Event& event) {
1566   FramebustBlockTabHelper::FromWebContents(web_contents())
1567       ->OnBlockedUrlClicked(index);
1568 }
1569 
1570 ContentSettingFramebustBlockBubbleModel*
AsFramebustBlockBubbleModel()1571 ContentSettingFramebustBlockBubbleModel::AsFramebustBlockBubbleModel() {
1572   return this;
1573 }
1574 
BlockedUrlAdded(int32_t id,const GURL & blocked_url)1575 void ContentSettingFramebustBlockBubbleModel::BlockedUrlAdded(
1576     int32_t id,
1577     const GURL& blocked_url) {
1578   AddListItem(CreateUrlListItem(0 /* id */, blocked_url));
1579 }
1580 
1581 // ContentSettingNotificationsBubbleModel ----------------------------------
ContentSettingNotificationsBubbleModel(Delegate * delegate,WebContents * web_contents)1582 ContentSettingNotificationsBubbleModel::ContentSettingNotificationsBubbleModel(
1583     Delegate* delegate,
1584     WebContents* web_contents)
1585     : ContentSettingBubbleModel(delegate, web_contents) {
1586   set_title(l10n_util::GetStringUTF16(
1587       IDS_NOTIFICATIONS_QUIET_PERMISSION_BUBBLE_TITLE));
1588 
1589   // TODO(crbug.com/1030633): This block is more defensive than it needs to be
1590   // because ContentSettingImageModelBrowserTest exercises it without setting up
1591   // the correct PermissionRequestManager state. Fix that.
1592   permissions::PermissionRequestManager* manager =
1593       permissions::PermissionRequestManager::FromWebContents(web_contents);
1594   if (!manager->ShouldCurrentRequestUseQuietUI())
1595     return;
1596   switch (manager->ReasonForUsingQuietUi()) {
1597     case QuietUiReason::kEnabledInPrefs:
1598     case QuietUiReason::kPredictedVeryUnlikelyGrant:
1599       set_message(l10n_util::GetStringUTF16(
1600           IDS_NOTIFICATIONS_QUIET_PERMISSION_BUBBLE_DESCRIPTION));
1601       set_done_button_text(l10n_util::GetStringUTF16(
1602           IDS_NOTIFICATIONS_QUIET_PERMISSION_BUBBLE_ALLOW_BUTTON));
1603       set_show_learn_more(false);
1604       base::RecordAction(
1605           base::UserMetricsAction("Notifications.Quiet.AnimatedIconClicked"));
1606       break;
1607     case QuietUiReason::kTriggeredByCrowdDeny:
1608       set_message(l10n_util::GetStringUTF16(
1609           IDS_NOTIFICATIONS_QUIET_PERMISSION_BUBBLE_CROWD_DENY_DESCRIPTION));
1610       set_done_button_text(l10n_util::GetStringUTF16(
1611           IDS_NOTIFICATIONS_QUIET_PERMISSION_BUBBLE_ALLOW_BUTTON));
1612       set_show_learn_more(false);
1613       base::RecordAction(
1614           base::UserMetricsAction("Notifications.Quiet.StaticIconClicked"));
1615       break;
1616     case QuietUiReason::kTriggeredDueToAbusiveRequests:
1617     case QuietUiReason::kTriggeredDueToAbusiveContent:
1618       set_message(l10n_util::GetStringUTF16(
1619           IDS_NOTIFICATIONS_QUIET_PERMISSION_BUBBLE_ABUSIVE_DESCRIPTION));
1620       // TODO(crbug.com/1082738): It is rather confusing to have the `Cancel`
1621       // button allow the permission, but we want the primary to block.
1622       set_cancel_button_text(l10n_util::GetStringUTF16(
1623           IDS_NOTIFICATIONS_QUIET_PERMISSION_BUBBLE_COMPACT_ALLOW_BUTTON));
1624       set_done_button_text(l10n_util::GetStringUTF16(
1625           IDS_NOTIFICATIONS_QUIET_PERMISSION_BUBBLE_CONTINUE_BLOCKING_BUTTON));
1626       set_show_learn_more(true);
1627       set_manage_text_style(ManageTextStyle::kNone);
1628       base::RecordAction(
1629           base::UserMetricsAction("Notifications.Quiet.StaticIconClicked"));
1630       break;
1631   }
1632 }
1633 
1634 ContentSettingNotificationsBubbleModel::
1635     ~ContentSettingNotificationsBubbleModel() = default;
1636 
1637 ContentSettingNotificationsBubbleModel*
AsNotificationsBubbleModel()1638 ContentSettingNotificationsBubbleModel::AsNotificationsBubbleModel() {
1639   return this;
1640 }
1641 
OnManageButtonClicked()1642 void ContentSettingNotificationsBubbleModel::OnManageButtonClicked() {
1643   if (delegate())
1644     delegate()->ShowContentSettingsPage(ContentSettingsType::NOTIFICATIONS);
1645 
1646   base::RecordAction(
1647       base::UserMetricsAction("Notifications.Quiet.ManageClicked"));
1648 }
1649 
OnLearnMoreClicked()1650 void ContentSettingNotificationsBubbleModel::OnLearnMoreClicked() {
1651   if (delegate())
1652     delegate()->ShowLearnMorePage(ContentSettingsType::NOTIFICATIONS);
1653 }
1654 
OnDoneButtonClicked()1655 void ContentSettingNotificationsBubbleModel::OnDoneButtonClicked() {
1656   permissions::PermissionRequestManager* manager =
1657       permissions::PermissionRequestManager::FromWebContents(web_contents());
1658 
1659   DCHECK(manager->ShouldCurrentRequestUseQuietUI());
1660   switch (manager->ReasonForUsingQuietUi()) {
1661     case QuietUiReason::kEnabledInPrefs:
1662     case QuietUiReason::kTriggeredByCrowdDeny:
1663     case QuietUiReason::kPredictedVeryUnlikelyGrant:
1664       manager->Accept();
1665       base::RecordAction(
1666           base::UserMetricsAction("Notifications.Quiet.ShowForSiteClicked"));
1667       break;
1668     case QuietUiReason::kTriggeredDueToAbusiveRequests:
1669     case QuietUiReason::kTriggeredDueToAbusiveContent:
1670       manager->Deny();
1671       base::RecordAction(base::UserMetricsAction(
1672           "Notifications.Quiet.ContinueBlockingClicked"));
1673       break;
1674   }
1675 }
1676 
OnCancelButtonClicked()1677 void ContentSettingNotificationsBubbleModel::OnCancelButtonClicked() {
1678   permissions::PermissionRequestManager* manager =
1679       permissions::PermissionRequestManager::FromWebContents(web_contents());
1680 
1681   switch (manager->ReasonForUsingQuietUi()) {
1682     case QuietUiReason::kEnabledInPrefs:
1683     case QuietUiReason::kTriggeredByCrowdDeny:
1684     case QuietUiReason::kPredictedVeryUnlikelyGrant:
1685       // No-op.
1686       break;
1687     case QuietUiReason::kTriggeredDueToAbusiveRequests:
1688     case QuietUiReason::kTriggeredDueToAbusiveContent:
1689       manager->Accept();
1690       base::RecordAction(
1691           base::UserMetricsAction("Notifications.Quiet.ShowForSiteClicked"));
1692       break;
1693   }
1694 }
1695 
1696 // ContentSettingBubbleModel ---------------------------------------------------
1697 
1698 // This class must be placed last because it needs the definition of the other
1699 // classes declared in this file.
1700 
1701 const int ContentSettingBubbleModel::kAllowButtonIndex = 0;
1702 
1703 // static
1704 std::unique_ptr<ContentSettingBubbleModel>
CreateContentSettingBubbleModel(Delegate * delegate,WebContents * web_contents,ContentSettingsType content_type)1705 ContentSettingBubbleModel::CreateContentSettingBubbleModel(
1706     Delegate* delegate,
1707     WebContents* web_contents,
1708     ContentSettingsType content_type) {
1709   DCHECK(web_contents);
1710   if (content_type == ContentSettingsType::COOKIES) {
1711     return std::make_unique<ContentSettingCookiesBubbleModel>(delegate,
1712                                                               web_contents);
1713   }
1714   if (content_type == ContentSettingsType::POPUPS) {
1715     return std::make_unique<ContentSettingPopupBubbleModel>(delegate,
1716                                                             web_contents);
1717   }
1718 
1719   if (content_type == ContentSettingsType::PLUGINS) {
1720     return std::make_unique<ContentSettingPluginBubbleModel>(delegate,
1721                                                              web_contents);
1722   }
1723   if (content_type == ContentSettingsType::MIXEDSCRIPT) {
1724     return std::make_unique<ContentSettingMixedScriptBubbleModel>(delegate,
1725                                                                   web_contents);
1726   }
1727   if (content_type == ContentSettingsType::PROTOCOL_HANDLERS) {
1728     ProtocolHandlerRegistry* registry =
1729         ProtocolHandlerRegistryFactory::GetForBrowserContext(
1730             web_contents->GetBrowserContext());
1731     return std::make_unique<ContentSettingRPHBubbleModel>(
1732         delegate, web_contents, registry);
1733   }
1734   if (content_type == ContentSettingsType::AUTOMATIC_DOWNLOADS) {
1735     return std::make_unique<ContentSettingDownloadsBubbleModel>(delegate,
1736                                                                 web_contents);
1737   }
1738   if (content_type == ContentSettingsType::ADS) {
1739     return std::make_unique<ContentSettingSubresourceFilterBubbleModel>(
1740         delegate, web_contents);
1741   }
1742   if (content_type == ContentSettingsType::IMAGES ||
1743       content_type == ContentSettingsType::JAVASCRIPT ||
1744       content_type == ContentSettingsType::PPAPI_BROKER ||
1745       content_type == ContentSettingsType::SOUND ||
1746       content_type == ContentSettingsType::CLIPBOARD_READ_WRITE ||
1747       content_type == ContentSettingsType::MIDI_SYSEX ||
1748       content_type == ContentSettingsType::SENSORS) {
1749     return std::make_unique<ContentSettingSingleRadioGroup>(
1750         delegate, web_contents, content_type);
1751   }
1752   NOTREACHED() << "No bubble for the content type "
1753                << static_cast<int32_t>(content_type) << ".";
1754   return nullptr;
1755 }
1756 
ContentSettingBubbleModel(Delegate * delegate,WebContents * web_contents)1757 ContentSettingBubbleModel::ContentSettingBubbleModel(Delegate* delegate,
1758                                                      WebContents* web_contents)
1759     : web_contents_(web_contents),
1760       owner_(nullptr),
1761       delegate_(delegate),
1762       rappor_service_(g_browser_process->rappor_service()) {
1763   DCHECK(web_contents_);
1764 }
1765 
~ContentSettingBubbleModel()1766 ContentSettingBubbleModel::~ContentSettingBubbleModel() {
1767 }
1768 
RadioGroup()1769 ContentSettingBubbleModel::RadioGroup::RadioGroup() : default_item(0) {}
1770 
~RadioGroup()1771 ContentSettingBubbleModel::RadioGroup::~RadioGroup() {}
1772 
DomainList()1773 ContentSettingBubbleModel::DomainList::DomainList() {}
1774 
1775 ContentSettingBubbleModel::DomainList::DomainList(const DomainList& other) =
1776     default;
1777 
~DomainList()1778 ContentSettingBubbleModel::DomainList::~DomainList() {}
1779 
MediaMenu()1780 ContentSettingBubbleModel::MediaMenu::MediaMenu() : disabled(false) {}
1781 
1782 ContentSettingBubbleModel::MediaMenu::MediaMenu(const MediaMenu& other) =
1783     default;
1784 
~MediaMenu()1785 ContentSettingBubbleModel::MediaMenu::~MediaMenu() {}
1786 
BubbleContent()1787 ContentSettingBubbleModel::BubbleContent::BubbleContent() {}
1788 
~BubbleContent()1789 ContentSettingBubbleModel::BubbleContent::~BubbleContent() {}
1790 
1791 ContentSettingSimpleBubbleModel*
AsSimpleBubbleModel()1792     ContentSettingBubbleModel::AsSimpleBubbleModel() {
1793   // In general, bubble models might not inherit from the simple bubble model.
1794   return nullptr;
1795 }
1796 
1797 ContentSettingMediaStreamBubbleModel*
AsMediaStreamBubbleModel()1798     ContentSettingBubbleModel::AsMediaStreamBubbleModel() {
1799   // In general, bubble models might not inherit from the media bubble model.
1800   return nullptr;
1801 }
1802 
1803 ContentSettingNotificationsBubbleModel*
AsNotificationsBubbleModel()1804 ContentSettingBubbleModel::AsNotificationsBubbleModel() {
1805   return nullptr;
1806 }
1807 
1808 ContentSettingSubresourceFilterBubbleModel*
AsSubresourceFilterBubbleModel()1809 ContentSettingBubbleModel::AsSubresourceFilterBubbleModel() {
1810   return nullptr;
1811 }
1812 
1813 ContentSettingDownloadsBubbleModel*
AsDownloadsBubbleModel()1814 ContentSettingBubbleModel::AsDownloadsBubbleModel() {
1815   return nullptr;
1816 }
1817 
1818 ContentSettingFramebustBlockBubbleModel*
AsFramebustBlockBubbleModel()1819 ContentSettingBubbleModel::AsFramebustBlockBubbleModel() {
1820   return nullptr;
1821 }
1822 
GetProfile() const1823 Profile* ContentSettingBubbleModel::GetProfile() const {
1824   return Profile::FromBrowserContext(web_contents_->GetBrowserContext());
1825 }
1826 
AddListItem(const ListItem & item)1827 void ContentSettingBubbleModel::AddListItem(const ListItem& item) {
1828   bubble_content_.list_items.push_back(item);
1829   if (owner_)
1830     owner_->OnListItemAdded(item);
1831 }
1832 
RemoveListItem(int index)1833 void ContentSettingBubbleModel::RemoveListItem(int index) {
1834   if (owner_)
1835     owner_->OnListItemRemovedAt(index);
1836 
1837   bubble_content_.list_items.erase(bubble_content_.list_items.begin() + index);
1838 }
1839