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