1 // Copyright 2016 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/webui/settings/site_settings_handler.h"
6
7 #include <algorithm>
8 #include <set>
9 #include <utility>
10 #include <vector>
11
12 #include "base/barrier_closure.h"
13 #include "base/bind.h"
14 #include "base/feature_list.h"
15 #include "base/i18n/number_formatting.h"
16 #include "base/macros.h"
17 #include "base/metrics/histogram_macros.h"
18 #include "base/metrics/user_metrics.h"
19 #include "base/stl_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/values.h"
22 #include "chrome/browser/bluetooth/bluetooth_chooser_context.h"
23 #include "chrome/browser/bluetooth/bluetooth_chooser_context_factory.h"
24 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
25 #include "chrome/browser/engagement/site_engagement_service.h"
26 #include "chrome/browser/hid/hid_chooser_context.h"
27 #include "chrome/browser/hid/hid_chooser_context_factory.h"
28 #include "chrome/browser/infobars/infobar_service.h"
29 #include "chrome/browser/media/unified_autoplay_config.h"
30 #include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h"
31 #include "chrome/browser/serial/serial_chooser_context.h"
32 #include "chrome/browser/serial/serial_chooser_context_factory.h"
33 #include "chrome/browser/ui/browser.h"
34 #include "chrome/browser/ui/browser_list.h"
35 #include "chrome/browser/ui/page_info/page_info_infobar_delegate.h"
36 #include "chrome/browser/ui/tabs/tab_strip_model.h"
37 #include "chrome/browser/ui/webui/recent_site_settings_helper.h"
38 #include "chrome/browser/ui/webui/site_settings_helper.h"
39 #include "chrome/browser/usb/usb_chooser_context.h"
40 #include "chrome/browser/usb/usb_chooser_context_factory.h"
41 #include "chrome/browser/web_applications/web_app_provider.h"
42 #include "chrome/browser/web_applications/web_app_registrar.h"
43 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
44 #include "chrome/common/pref_names.h"
45 #include "chrome/grit/generated_resources.h"
46 #include "components/content_settings/core/browser/cookie_settings.h"
47 #include "components/content_settings/core/browser/uma_util.h"
48 #include "components/content_settings/core/browser/website_settings_registry.h"
49 #include "components/content_settings/core/common/content_settings_types.h"
50 #include "components/content_settings/core/common/content_settings_utils.h"
51 #include "components/content_settings/core/common/features.h"
52 #include "components/content_settings/core/common/pref_names.h"
53 #include "components/crx_file/id_util.h"
54 #include "components/permissions/chooser_context_base.h"
55 #include "components/permissions/permission_decision_auto_blocker.h"
56 #include "components/permissions/permission_uma_util.h"
57 #include "components/permissions/permission_util.h"
58 #include "components/prefs/pref_change_registrar.h"
59 #include "components/prefs/pref_service.h"
60 #include "content/public/browser/browser_thread.h"
61 #include "content/public/browser/web_contents.h"
62 #include "content/public/browser/web_ui.h"
63 #include "content/public/common/content_features.h"
64 #include "content/public/common/origin_util.h"
65 #include "content/public/common/url_constants.h"
66 #include "extensions/browser/extension_registry.h"
67 #include "extensions/common/permissions/api_permission.h"
68 #include "extensions/common/permissions/permissions_data.h"
69 #include "third_party/blink/public/common/page/page_zoom.h"
70 #include "ui/base/l10n/l10n_util.h"
71 #include "ui/base/text/bytes_formatting.h"
72
73 #if defined(OS_CHROMEOS)
74 #include "components/user_manager/user_manager.h"
75 #endif
76
77 namespace settings {
78
79 namespace {
80
81 // Keys of the dictionary returned by HandleIsPatternValidForType.
82 constexpr char kIsValidKey[] = "isValid";
83 constexpr char kReasonKey[] = "reason";
84
85 constexpr char kEffectiveTopLevelDomainPlus1Name[] = "etldPlus1";
86 constexpr char kOriginList[] = "origins";
87 constexpr char kNumCookies[] = "numCookies";
88 constexpr char kHasPermissionSettings[] = "hasPermissionSettings";
89 constexpr char kHasInstalledPWA[] = "hasInstalledPWA";
90 constexpr char kIsInstalled[] = "isInstalled";
91 constexpr char kZoom[] = "zoom";
92 // Placeholder value for ETLD+1 until a valid origin is added. If an ETLD+1
93 // only has placeholder, then create an ETLD+1 origin.
94 constexpr char kPlaceholder[] = "placeholder";
95
96 // These values are persisted to logs. Entries should not be renumbered and
97 // numeric values should never be reused.
98 enum class AllSitesAction {
99 kLoadPage = 0,
100 kResetPermissions = 1,
101 kClearData = 2,
102 kEnterSiteDetails = 3,
103 kMaxValue = kEnterSiteDetails,
104 };
105
106 enum class AllSitesAction2 {
107 kLoadPage = 0,
108 kResetSiteGroupPermissions = 1,
109 kResetOriginPermissions = 2,
110 kClearAllData = 3,
111 kClearSiteGroupData = 4,
112 kClearOriginData = 5,
113 kEnterSiteDetails = 6,
114 kMaxValue = kEnterSiteDetails,
115 };
116
117 // Return an appropriate API Permission ID for the given string name.
APIPermissionFromGroupName(std::string type)118 extensions::APIPermission::APIPermission::ID APIPermissionFromGroupName(
119 std::string type) {
120 // Once there are more than two groups to consider, this should be changed to
121 // something better than if's.
122
123 if (site_settings::ContentSettingsTypeFromGroupName(type) ==
124 ContentSettingsType::GEOLOCATION)
125 return extensions::APIPermission::APIPermission::kGeolocation;
126
127 if (site_settings::ContentSettingsTypeFromGroupName(type) ==
128 ContentSettingsType::NOTIFICATIONS)
129 return extensions::APIPermission::APIPermission::kNotifications;
130
131 return extensions::APIPermission::APIPermission::kInvalid;
132 }
133
134 // Asks the |profile| for hosted apps which have the |permission| set, and
135 // adds their web extent and launch URL to the |exceptions| list.
AddExceptionsGrantedByHostedApps(content::BrowserContext * context,extensions::APIPermission::APIPermission::ID permission,base::ListValue * exceptions)136 void AddExceptionsGrantedByHostedApps(
137 content::BrowserContext* context,
138 extensions::APIPermission::APIPermission::ID permission,
139 base::ListValue* exceptions) {
140 const extensions::ExtensionSet& extensions =
141 extensions::ExtensionRegistry::Get(context)->enabled_extensions();
142 for (extensions::ExtensionSet::const_iterator extension = extensions.begin();
143 extension != extensions.end(); ++extension) {
144 if (!(*extension)->is_hosted_app() ||
145 !(*extension)->permissions_data()->HasAPIPermission(permission))
146 continue;
147
148 const extensions::URLPatternSet& web_extent = (*extension)->web_extent();
149 // Add patterns from web extent.
150 for (auto pattern = web_extent.begin(); pattern != web_extent.end();
151 ++pattern) {
152 std::string url_pattern = pattern->GetAsString();
153 site_settings::AddExceptionForHostedApp(url_pattern, *extension->get(),
154 exceptions);
155 }
156 // Retrieve the launch URL.
157 GURL launch_url =
158 extensions::AppLaunchInfo::GetLaunchWebURL(extension->get());
159 // Skip adding the launch URL if it is part of the web extent.
160 if (web_extent.MatchesURL(launch_url))
161 continue;
162 site_settings::AddExceptionForHostedApp(launch_url.spec(),
163 *extension->get(), exceptions);
164 }
165 }
166
GetInstalledAppOrigins(Profile * profile,const web_app::AppRegistrar & registrar)167 base::flat_set<std::string> GetInstalledAppOrigins(
168 Profile* profile,
169 const web_app::AppRegistrar& registrar) {
170 base::flat_set<std::string> origins;
171 for (const web_app::AppId& app : registrar.GetAppIds())
172 origins.insert(registrar.GetAppScope(app).GetOrigin().spec());
173 return origins;
174 }
175
176 // Groups |url| into sets of eTLD+1s in |site_group_map|, assuming |url| is an
177 // origin.
178 // There are three cases:
179 // 1. The ETLD+1 of |url| is not yet in |site_group_map|. We add the ETLD+1
180 // to |site_group_map|. If the |url| is an ETLD+1 cookie origin, put a
181 // placeholder origin for the ETLD+1.
182 // 2. The ETLD+1 of |url| is in |site_group_map|, and is equal to host of
183 // |url|. This means case 1 has already happened and nothing more needs to
184 // be done.
185 // 3. The ETLD+1 of |url| is in |site_group_map| and is different to host of
186 // |url|. For a cookies url, if a https origin with same host exists,
187 // nothing more needs to be done.
188 // In case 3, we try to add |url| to the set of origins for the ETLD+1. If an
189 // existing origin is a placeholder, delete it, because the placeholder is no
190 // longer needed.
CreateOrAppendSiteGroupEntry(std::map<std::string,std::set<std::string>> * site_group_map,const GURL & url,bool url_is_origin_with_cookies=false)191 void CreateOrAppendSiteGroupEntry(
192 std::map<std::string, std::set<std::string>>* site_group_map,
193 const GURL& url,
194 bool url_is_origin_with_cookies = false) {
195 std::string etld_plus1_string =
196 net::registry_controlled_domains::GetDomainAndRegistry(
197 url, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
198 auto entry = site_group_map->find(etld_plus1_string);
199 bool etld_plus1_cookie_url =
200 url_is_origin_with_cookies && url.host() == etld_plus1_string;
201
202 if (entry == site_group_map->end()) {
203 // Case 1:
204 std::string origin = etld_plus1_cookie_url ? kPlaceholder : url.spec();
205 site_group_map->emplace(etld_plus1_string, std::set<std::string>({origin}));
206 return;
207 }
208 // Case 2:
209 if (etld_plus1_cookie_url)
210 return;
211 // Case 3:
212 if (url_is_origin_with_cookies) {
213 // Cookies ignore schemes, so try and see if a https schemed version
214 // already exists in the origin list, if not, then add the http schemed
215 // version into the map.
216 std::string https_url = std::string(url::kHttpsScheme) +
217 url::kStandardSchemeSeparator + url.host() + "/";
218 if (entry->second.find(https_url) != entry->second.end())
219 return;
220 }
221 entry->second.insert(url.spec());
222 auto placeholder = entry->second.find(kPlaceholder);
223 if (placeholder != entry->second.end())
224 entry->second.erase(placeholder);
225 }
226
227 // Update the storage data in |origin_size_map|.
UpdateDataForOrigin(const GURL & url,const int64_t size,std::map<std::string,int64_t> * origin_size_map)228 void UpdateDataForOrigin(const GURL& url,
229 const int64_t size,
230 std::map<std::string, int64_t>* origin_size_map) {
231 if (size > 0)
232 (*origin_size_map)[url.spec()] += size;
233 }
234
235 // Converts a given |site_group_map| to a list of base::DictionaryValues, adding
236 // the site engagement score for each origin.
ConvertSiteGroupMapToListValue(const std::map<std::string,std::set<std::string>> & site_group_map,const std::set<std::string> & origin_permission_set,base::Value * list_value,Profile * profile,const web_app::AppRegistrar & registrar)237 void ConvertSiteGroupMapToListValue(
238 const std::map<std::string, std::set<std::string>>& site_group_map,
239 const std::set<std::string>& origin_permission_set,
240 base::Value* list_value,
241 Profile* profile,
242 const web_app::AppRegistrar& registrar) {
243 DCHECK_EQ(base::Value::Type::LIST, list_value->type());
244 DCHECK(profile);
245 base::flat_set<std::string> installed_origins =
246 GetInstalledAppOrigins(profile, registrar);
247 SiteEngagementService* engagement_service =
248 SiteEngagementService::Get(profile);
249 for (const auto& entry : site_group_map) {
250 // eTLD+1 is the effective top level domain + 1.
251 base::Value site_group(base::Value::Type::DICTIONARY);
252 site_group.SetKey(kEffectiveTopLevelDomainPlus1Name,
253 base::Value(entry.first));
254 bool has_installed_pwa = false;
255 base::Value origin_list(base::Value::Type::LIST);
256 for (const std::string& origin : entry.second) {
257 base::Value origin_object(base::Value::Type::DICTIONARY);
258 // If origin is placeholder, create a http ETLD+1 origin for it.
259 if (origin == kPlaceholder) {
260 origin_object.SetKey(
261 "origin",
262 base::Value(std::string(url::kHttpScheme) +
263 url::kStandardSchemeSeparator + entry.first + "/"));
264 } else {
265 origin_object.SetKey("origin", base::Value(origin));
266 }
267 origin_object.SetKey(
268 "engagement",
269 base::Value(engagement_service->GetScore(GURL(origin))));
270 origin_object.SetKey("usage", base::Value(0));
271 origin_object.SetKey(kNumCookies, base::Value(0));
272
273 bool is_installed = installed_origins.contains(origin);
274 if (is_installed)
275 has_installed_pwa = true;
276 origin_object.SetKey(kIsInstalled, base::Value(is_installed));
277
278 origin_object.SetKey(
279 kHasPermissionSettings,
280 base::Value(base::Contains(origin_permission_set, origin)));
281 origin_list.Append(std::move(origin_object));
282 }
283 site_group.SetKey(kHasInstalledPWA, base::Value(has_installed_pwa));
284 site_group.SetKey(kNumCookies, base::Value(0));
285 site_group.SetKey(kOriginList, std::move(origin_list));
286 list_value->Append(std::move(site_group));
287 }
288 }
289
IsPatternValidForType(const std::string & pattern_string,const std::string & type,Profile * profile,std::string * out_error)290 bool IsPatternValidForType(const std::string& pattern_string,
291 const std::string& type,
292 Profile* profile,
293 std::string* out_error) {
294 ContentSettingsType content_type =
295 site_settings::ContentSettingsTypeFromGroupName(type);
296
297 ContentSettingsPattern pattern =
298 ContentSettingsPattern::FromString(pattern_string);
299
300 HostContentSettingsMap* map =
301 HostContentSettingsMapFactory::GetForProfile(profile);
302
303 // Don't allow an input of '*', even though it's a valid pattern. This
304 // changes the default setting.
305 if (!pattern.IsValid() || pattern == ContentSettingsPattern::Wildcard()) {
306 *out_error = l10n_util::GetStringUTF8(IDS_SETTINGS_NOT_VALID_WEB_ADDRESS);
307 return false;
308 }
309
310 // Check if a setting can be set for this url and setting type, and if not,
311 // return false with a string saying why.
312 GURL url(pattern_string);
313 if (url.is_valid() && map->IsRestrictedToSecureOrigins(content_type) &&
314 !content::IsOriginSecure(url)) {
315 *out_error = l10n_util::GetStringUTF8(
316 IDS_SETTINGS_NOT_VALID_WEB_ADDRESS_FOR_CONTENT_TYPE);
317 return false;
318 }
319
320 // The pattern is valid.
321 return true;
322 }
323
UpdateDataFromCookiesTree(std::map<std::string,std::set<std::string>> * all_sites_map,std::map<std::string,int64_t> * origin_size_map,const GURL & origin,int64_t size)324 void UpdateDataFromCookiesTree(
325 std::map<std::string, std::set<std::string>>* all_sites_map,
326 std::map<std::string, int64_t>* origin_size_map,
327 const GURL& origin,
328 int64_t size) {
329 UpdateDataForOrigin(origin, size, origin_size_map);
330 CreateOrAppendSiteGroupEntry(all_sites_map, origin);
331 }
332
LogAllSitesAction(AllSitesAction2 action)333 void LogAllSitesAction(AllSitesAction2 action) {
334 UMA_HISTOGRAM_ENUMERATION("WebsiteSettings.AllSitesAction2", action);
335 }
336
GetNumCookieExceptionsOfTypes(HostContentSettingsMap * map,const std::set<ContentSetting> types)337 int GetNumCookieExceptionsOfTypes(HostContentSettingsMap* map,
338 const std::set<ContentSetting> types) {
339 ContentSettingsForOneType output;
340 map->GetSettingsForOneType(ContentSettingsType::COOKIES, std::string(),
341 &output);
342 return std::count_if(
343 output.begin(), output.end(),
344 [types](const ContentSettingPatternSource setting) {
345 return types.count(
346 content_settings::ValueToContentSetting(&setting.setting_value));
347 });
348 }
349
GetCookieSettingDescription(Profile * profile)350 std::string GetCookieSettingDescription(Profile* profile) {
351 HostContentSettingsMap* map =
352 HostContentSettingsMapFactory::GetForProfile(profile);
353 auto content_setting =
354 map->GetDefaultContentSetting(ContentSettingsType::COOKIES, nullptr);
355
356 bool block_third_party =
357 profile->GetPrefs()->GetBoolean(prefs::kBlockThirdPartyCookies);
358 auto control_mode = static_cast<content_settings::CookieControlsMode>(
359 profile->GetPrefs()->GetInteger(prefs::kCookieControlsMode));
360
361 // Determine what the effective cookie setting is. These conditions are not
362 // mutually exclusive and rely on ordering.
363 if (content_setting == ContentSetting::CONTENT_SETTING_BLOCK) {
364 return l10n_util::GetPluralStringFUTF8(
365 IDS_SETTINGS_SITE_SETTINGS_COOKIES_BLOCK,
366 GetNumCookieExceptionsOfTypes(
367 map, {ContentSetting::CONTENT_SETTING_ALLOW,
368 ContentSetting::CONTENT_SETTING_SESSION_ONLY}));
369 } else if (block_third_party) {
370 return l10n_util::GetStringUTF8(
371 IDS_SETTINGS_SITE_SETTINGS_COOKIES_BLOCK_THIRD_PARTY);
372 } else if (base::FeatureList::IsEnabled(
373 content_settings::kImprovedCookieControls) &&
374 control_mode ==
375 content_settings::CookieControlsMode::kIncognitoOnly) {
376 return l10n_util::GetStringUTF8(
377 IDS_SETTINGS_SITE_SETTINGS_COOKIES_BLOCK_THIRD_PARTY_INCOGNITO);
378 } else {
379 // We do not make a distinction between allow and clear on exit.
380 return l10n_util::GetPluralStringFUTF8(
381 IDS_SETTINGS_SITE_SETTINGS_COOKIES_ALLOW,
382 GetNumCookieExceptionsOfTypes(map,
383 {ContentSetting::CONTENT_SETTING_BLOCK}));
384 }
385 }
386
387 } // namespace
388
SiteSettingsHandler(Profile * profile,web_app::AppRegistrar & app_registrar)389 SiteSettingsHandler::SiteSettingsHandler(Profile* profile,
390 web_app::AppRegistrar& app_registrar)
391 : profile_(profile), app_registrar_(app_registrar) {}
392
~SiteSettingsHandler()393 SiteSettingsHandler::~SiteSettingsHandler() {
394 if (cookies_tree_model_)
395 cookies_tree_model_->RemoveCookiesTreeObserver(this);
396 }
397
RegisterMessages()398 void SiteSettingsHandler::RegisterMessages() {
399 web_ui()->RegisterMessageCallback(
400 "fetchUsageTotal",
401 base::BindRepeating(&SiteSettingsHandler::HandleFetchUsageTotal,
402 base::Unretained(this)));
403 web_ui()->RegisterMessageCallback(
404 "clearUsage", base::BindRepeating(&SiteSettingsHandler::HandleClearUsage,
405 base::Unretained(this)));
406 web_ui()->RegisterMessageCallback(
407 "setDefaultValueForContentType",
408 base::BindRepeating(
409 &SiteSettingsHandler::HandleSetDefaultValueForContentType,
410 base::Unretained(this)));
411 web_ui()->RegisterMessageCallback(
412 "getDefaultValueForContentType",
413 base::BindRepeating(
414 &SiteSettingsHandler::HandleGetDefaultValueForContentType,
415 base::Unretained(this)));
416 web_ui()->RegisterMessageCallback(
417 "getAllSites",
418 base::BindRepeating(&SiteSettingsHandler::HandleGetAllSites,
419 base::Unretained(this)));
420 web_ui()->RegisterMessageCallback(
421 "getCookieControlsManagedState",
422 base::BindRepeating(
423 &SiteSettingsHandler::HandleGetCookieControlsManagedState,
424 base::Unretained(this)));
425 web_ui()->RegisterMessageCallback(
426 "getCookieSettingDescription",
427 base::BindRepeating(
428 &SiteSettingsHandler::HandleGetCookieSettingDescription,
429 base::Unretained(this)));
430 web_ui()->RegisterMessageCallback(
431 "getRecentSitePermissions",
432 base::BindRepeating(&SiteSettingsHandler::HandleGetRecentSitePermissions,
433 base::Unretained(this)));
434 web_ui()->RegisterMessageCallback(
435 "getFormattedBytes",
436 base::BindRepeating(&SiteSettingsHandler::HandleGetFormattedBytes,
437 base::Unretained(this)));
438 web_ui()->RegisterMessageCallback(
439 "getExceptionList",
440 base::BindRepeating(&SiteSettingsHandler::HandleGetExceptionList,
441 base::Unretained(this)));
442 web_ui()->RegisterMessageCallback(
443 "getChooserExceptionList",
444 base::BindRepeating(&SiteSettingsHandler::HandleGetChooserExceptionList,
445 base::Unretained(this)));
446 web_ui()->RegisterMessageCallback(
447 "getOriginPermissions",
448 base::BindRepeating(&SiteSettingsHandler::HandleGetOriginPermissions,
449 base::Unretained(this)));
450 web_ui()->RegisterMessageCallback(
451 "setOriginPermissions",
452 base::BindRepeating(&SiteSettingsHandler::HandleSetOriginPermissions,
453 base::Unretained(this)));
454 web_ui()->RegisterMessageCallback(
455 "clearFlashPref",
456 base::BindRepeating(&SiteSettingsHandler::HandleClearFlashPref,
457 base::Unretained(this)));
458 web_ui()->RegisterMessageCallback(
459 "resetCategoryPermissionForPattern",
460 base::BindRepeating(
461 &SiteSettingsHandler::HandleResetCategoryPermissionForPattern,
462 base::Unretained(this)));
463 web_ui()->RegisterMessageCallback(
464 "setCategoryPermissionForPattern",
465 base::BindRepeating(
466 &SiteSettingsHandler::HandleSetCategoryPermissionForPattern,
467 base::Unretained(this)));
468 web_ui()->RegisterMessageCallback(
469 "resetChooserExceptionForSite",
470 base::BindRepeating(
471 &SiteSettingsHandler::HandleResetChooserExceptionForSite,
472 base::Unretained(this)));
473 web_ui()->RegisterMessageCallback(
474 "isOriginValid",
475 base::BindRepeating(&SiteSettingsHandler::HandleIsOriginValid,
476 base::Unretained(this)));
477 web_ui()->RegisterMessageCallback(
478 "isPatternValidForType",
479 base::BindRepeating(&SiteSettingsHandler::HandleIsPatternValidForType,
480 base::Unretained(this)));
481 web_ui()->RegisterMessageCallback(
482 "updateIncognitoStatus",
483 base::BindRepeating(&SiteSettingsHandler::HandleUpdateIncognitoStatus,
484 base::Unretained(this)));
485 web_ui()->RegisterMessageCallback(
486 "fetchZoomLevels",
487 base::BindRepeating(&SiteSettingsHandler::HandleFetchZoomLevels,
488 base::Unretained(this)));
489 web_ui()->RegisterMessageCallback(
490 "removeZoomLevel",
491 base::BindRepeating(&SiteSettingsHandler::HandleRemoveZoomLevel,
492 base::Unretained(this)));
493 web_ui()->RegisterMessageCallback(
494 "setBlockAutoplayEnabled",
495 base::BindRepeating(&SiteSettingsHandler::HandleSetBlockAutoplayEnabled,
496 base::Unretained(this)));
497 web_ui()->RegisterMessageCallback(
498 "fetchBlockAutoplayStatus",
499 base::BindRepeating(&SiteSettingsHandler::HandleFetchBlockAutoplayStatus,
500 base::Unretained(this)));
501 web_ui()->RegisterMessageCallback(
502 "clearEtldPlus1DataAndCookies",
503 base::BindRepeating(
504 &SiteSettingsHandler::HandleClearEtldPlus1DataAndCookies,
505 base::Unretained(this)));
506 web_ui()->RegisterMessageCallback(
507 "recordAction",
508 base::BindRepeating(&SiteSettingsHandler::HandleRecordAction,
509 base::Unretained(this)));
510 }
511
OnJavascriptAllowed()512 void SiteSettingsHandler::OnJavascriptAllowed() {
513 ObserveSourcesForProfile(profile_);
514 if (profile_->HasOffTheRecordProfile())
515 ObserveSourcesForProfile(profile_->GetOffTheRecordProfile());
516
517 // Here we only subscribe to the HostZoomMap for the default storage partition
518 // since we don't allow the user to manage the zoom levels for apps.
519 // We're only interested in zoom-levels that are persisted, since the user
520 // is given the opportunity to view/delete these in the content-settings page.
521 host_zoom_map_subscription_ =
522 content::HostZoomMap::GetDefaultForBrowserContext(profile_)
523 ->AddZoomLevelChangedCallback(
524 base::BindRepeating(&SiteSettingsHandler::OnZoomLevelChanged,
525 base::Unretained(this)));
526
527 pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
528 pref_change_registrar_->Init(profile_->GetPrefs());
529
530 // If the block autoplay pref changes send the new status.
531 pref_change_registrar_->Add(
532 prefs::kBlockAutoplayEnabled,
533 base::Bind(&SiteSettingsHandler::SendBlockAutoplayStatus,
534 base::Unretained(this)));
535
536 // Listen for prefs that impact the effective cookie setting
537 pref_change_registrar_->Add(
538 prefs::kBlockThirdPartyCookies,
539 base::Bind(&SiteSettingsHandler::SendCookieSettingDescription,
540 base::Unretained(this)));
541 pref_change_registrar_->Add(
542 prefs::kCookieControlsMode,
543 base::Bind(&SiteSettingsHandler::SendCookieSettingDescription,
544 base::Unretained(this)));
545
546 #if defined(OS_CHROMEOS)
547 pref_change_registrar_->Add(
548 prefs::kEnableDRM,
549 base::Bind(&SiteSettingsHandler::OnPrefEnableDrmChanged,
550 base::Unretained(this)));
551 #endif
552 }
553
OnJavascriptDisallowed()554 void SiteSettingsHandler::OnJavascriptDisallowed() {
555 observer_.RemoveAll();
556 chooser_observer_.RemoveAll();
557 host_zoom_map_subscription_.reset();
558 pref_change_registrar_->Remove(prefs::kBlockAutoplayEnabled);
559 pref_change_registrar_->Remove(prefs::kBlockThirdPartyCookies);
560 pref_change_registrar_->Remove(prefs::kCookieControlsMode);
561 #if defined(OS_CHROMEOS)
562 pref_change_registrar_->Remove(prefs::kEnableDRM);
563 #endif
564 observed_profiles_.RemoveAll();
565 }
566
OnGetUsageInfo()567 void SiteSettingsHandler::OnGetUsageInfo() {
568 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
569 // Site Details Page does not display the number of cookies for the origin.
570 const CookieTreeNode* root = cookies_tree_model_->GetRoot();
571 std::string usage_string = "";
572 std::string cookie_string = "";
573 for (const auto& site : root->children()) {
574 std::string title = base::UTF16ToUTF8(site->GetTitle());
575 if (title != usage_host_)
576 continue;
577 int64_t size = site->InclusiveSize();
578 if (size != 0)
579 usage_string = base::UTF16ToUTF8(ui::FormatBytes(size));
580 int num_cookies = site->NumberOfCookies();
581 if (num_cookies != 0) {
582 cookie_string = base::UTF16ToUTF8(l10n_util::GetPluralStringFUTF16(
583 IDS_SETTINGS_SITE_SETTINGS_NUM_COOKIES, num_cookies));
584 }
585 break;
586 }
587 FireWebUIListener("usage-total-changed", base::Value(usage_host_),
588 base::Value(usage_string), base::Value(cookie_string));
589 }
590
591 #if defined(OS_CHROMEOS)
OnPrefEnableDrmChanged()592 void SiteSettingsHandler::OnPrefEnableDrmChanged() {
593 FireWebUIListener("prefEnableDrmChanged");
594 }
595 #endif
596
OnContentSettingChanged(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type,const std::string & resource_identifier)597 void SiteSettingsHandler::OnContentSettingChanged(
598 const ContentSettingsPattern& primary_pattern,
599 const ContentSettingsPattern& secondary_pattern,
600 ContentSettingsType content_type,
601 const std::string& resource_identifier) {
602 if (!site_settings::HasRegisteredGroupName(content_type))
603 return;
604
605 if (primary_pattern.ToString().empty()) {
606 FireWebUIListener("contentSettingCategoryChanged",
607 base::Value(site_settings::ContentSettingsTypeToGroupName(
608 content_type)));
609 } else {
610 FireWebUIListener(
611 "contentSettingSitePermissionChanged",
612 base::Value(
613 site_settings::ContentSettingsTypeToGroupName(content_type)),
614 base::Value(primary_pattern.ToString()),
615 base::Value(secondary_pattern == ContentSettingsPattern::Wildcard()
616 ? ""
617 : secondary_pattern.ToString()));
618 }
619
620 // If the default sound content setting changed then we should send block
621 // autoplay status.
622 if (primary_pattern == ContentSettingsPattern() &&
623 secondary_pattern == ContentSettingsPattern() &&
624 content_type == ContentSettingsType::SOUND) {
625 SendBlockAutoplayStatus();
626 }
627
628 // If the default cookie setting changed we should update the effective
629 // setting description.
630 if (content_type == ContentSettingsType::COOKIES) {
631 SendCookieSettingDescription();
632 }
633 }
634
OnOffTheRecordProfileCreated(Profile * off_the_record)635 void SiteSettingsHandler::OnOffTheRecordProfileCreated(
636 Profile* off_the_record) {
637 FireWebUIListener("onIncognitoStatusChanged", base::Value(true));
638 ObserveSourcesForProfile(off_the_record);
639 }
640
OnProfileWillBeDestroyed(Profile * profile)641 void SiteSettingsHandler::OnProfileWillBeDestroyed(Profile* profile) {
642 if (profile->IsOffTheRecord())
643 FireWebUIListener("onIncognitoStatusChanged", base::Value(false));
644 StopObservingSourcesForProfile(profile);
645 }
646
OnChooserObjectPermissionChanged(ContentSettingsType guard_content_settings_type,ContentSettingsType data_content_settings_type)647 void SiteSettingsHandler::OnChooserObjectPermissionChanged(
648 ContentSettingsType guard_content_settings_type,
649 ContentSettingsType data_content_settings_type) {
650 if (!site_settings::HasRegisteredGroupName(guard_content_settings_type) ||
651 !site_settings::HasRegisteredGroupName(data_content_settings_type)) {
652 return;
653 }
654
655 FireWebUIListener("contentSettingChooserPermissionChanged",
656 base::Value(site_settings::ContentSettingsTypeToGroupName(
657 guard_content_settings_type)),
658 base::Value(site_settings::ContentSettingsTypeToGroupName(
659 data_content_settings_type)));
660 }
661
OnZoomLevelChanged(const content::HostZoomMap::ZoomLevelChange & change)662 void SiteSettingsHandler::OnZoomLevelChanged(
663 const content::HostZoomMap::ZoomLevelChange& change) {
664 SendZoomLevels();
665 }
666
HandleFetchUsageTotal(const base::ListValue * args)667 void SiteSettingsHandler::HandleFetchUsageTotal(const base::ListValue* args) {
668 AllowJavascript();
669 CHECK_EQ(1U, args->GetSize());
670 std::string host;
671 CHECK(args->GetString(0, &host));
672 usage_host_ = host;
673
674 update_site_details_ = true;
675 if (cookies_tree_model_ && !send_sites_list_) {
676 cookies_tree_model_->RemoveCookiesTreeObserver(this);
677 cookies_tree_model_.reset();
678 }
679 EnsureCookiesTreeModelCreated();
680 }
681
HandleClearUsage(const base::ListValue * args)682 void SiteSettingsHandler::HandleClearUsage(const base::ListValue* args) {
683 CHECK_EQ(1U, args->GetSize());
684 std::string origin;
685 CHECK(args->GetString(0, &origin));
686 GURL url(origin);
687 if (!url.is_valid())
688 return;
689 AllowJavascript();
690 for (const auto& node : cookies_tree_model_->GetRoot()->children()) {
691 if (origin == node->GetDetailedInfo().origin.GetURL().spec()) {
692 cookies_tree_model_->DeleteCookieNode(node.get());
693 return;
694 }
695 }
696 }
697
HandleSetDefaultValueForContentType(const base::ListValue * args)698 void SiteSettingsHandler::HandleSetDefaultValueForContentType(
699 const base::ListValue* args) {
700 CHECK_EQ(2U, args->GetSize());
701 std::string content_type;
702 CHECK(args->GetString(0, &content_type));
703 std::string setting;
704 CHECK(args->GetString(1, &setting));
705 ContentSetting default_setting;
706 CHECK(content_settings::ContentSettingFromString(setting, &default_setting));
707 ContentSettingsType type =
708 site_settings::ContentSettingsTypeFromGroupName(content_type);
709
710 Profile* profile = profile_;
711 #if defined(OS_CHROMEOS)
712 // ChromeOS special case: in Guest mode, settings are opened in Incognito
713 // mode so we need the original profile to actually modify settings.
714 if (user_manager::UserManager::Get()->IsLoggedInAsGuest())
715 profile = profile->GetOriginalProfile();
716 #endif
717 HostContentSettingsMap* map =
718 HostContentSettingsMapFactory::GetForProfile(profile);
719 ContentSetting previous_setting =
720 map->GetDefaultContentSetting(type, nullptr);
721 map->SetDefaultContentSetting(type, default_setting);
722
723 if (type == ContentSettingsType::SOUND &&
724 previous_setting != default_setting) {
725 if (default_setting == CONTENT_SETTING_BLOCK) {
726 base::RecordAction(
727 base::UserMetricsAction("SoundContentSetting.MuteBy.DefaultSwitch"));
728 } else {
729 base::RecordAction(base::UserMetricsAction(
730 "SoundContentSetting.UnmuteBy.DefaultSwitch"));
731 }
732 }
733 }
734
HandleGetDefaultValueForContentType(const base::ListValue * args)735 void SiteSettingsHandler::HandleGetDefaultValueForContentType(
736 const base::ListValue* args) {
737 AllowJavascript();
738
739 CHECK_EQ(2U, args->GetSize());
740 const base::Value* callback_id;
741 CHECK(args->Get(0, &callback_id));
742 std::string type;
743 CHECK(args->GetString(1, &type));
744
745 ContentSettingsType content_type =
746 site_settings::ContentSettingsTypeFromGroupName(type);
747 HostContentSettingsMap* map =
748 HostContentSettingsMapFactory::GetForProfile(profile_);
749
750 base::DictionaryValue category;
751 site_settings::GetContentCategorySetting(map, content_type, &category);
752 ResolveJavascriptCallback(*callback_id, category);
753 }
754
HandleGetAllSites(const base::ListValue * args)755 void SiteSettingsHandler::HandleGetAllSites(const base::ListValue* args) {
756 AllowJavascript();
757
758 CHECK_EQ(2U, args->GetList().size());
759 std::string callback_id = args->GetList()[0].GetString();
760 auto types = args->GetList()[1].GetList();
761
762 all_sites_map_.clear();
763 origin_permission_set_.clear();
764
765 auto content_types = site_settings::ContentSettingsTypesFromGroupNames(types);
766
767 // Incognito contains incognito content settings plus non-incognito content
768 // settings. Thus if it exists, just get exceptions for the incognito profile.
769 Profile* profile = profile_;
770 if (profile_->HasOffTheRecordProfile() &&
771 profile_->GetOffTheRecordProfile() != profile_) {
772 profile = profile_->GetOffTheRecordProfile();
773 }
774 DCHECK(profile);
775 HostContentSettingsMap* map =
776 HostContentSettingsMapFactory::GetForProfile(profile);
777
778 // Retrieve a list of embargoed settings to check separately. This ensures
779 // that only settings included in |content_types| will be listed in all sites.
780 auto* autoblocker =
781 PermissionDecisionAutoBlockerFactory::GetForProfile(profile_);
782 for (auto& url : autoblocker->GetEmbargoedOrigins(content_types)) {
783 // Add |url| to the set if there are any embargo settings.
784 CreateOrAppendSiteGroupEntry(&all_sites_map_, url);
785 origin_permission_set_.insert(url.spec());
786 }
787
788 // Get permission exceptions which apply to a single site
789 for (auto content_type : content_types) {
790 auto exceptions =
791 site_settings::GetSiteExceptionsForContentType(map, content_type);
792 for (const auto& e : exceptions) {
793 GURL url = GURL(e.primary_pattern.ToString());
794 CreateOrAppendSiteGroupEntry(&all_sites_map_, url);
795 origin_permission_set_.insert(url.spec());
796 }
797 }
798
799 // Recreate the cookies tree model to refresh the usage information.
800 // This happens in the background and will call TreeModelEndBatch() when
801 // finished. At that point we send usage data to the page.
802 if (cookies_tree_model_)
803 cookies_tree_model_->RemoveCookiesTreeObserver(this);
804 cookies_tree_model_.reset();
805 EnsureCookiesTreeModelCreated();
806
807 base::Value result(base::Value::Type::LIST);
808
809 // Respond with currently available data.
810 ConvertSiteGroupMapToListValue(all_sites_map_, origin_permission_set_,
811 &result, profile, app_registrar_);
812
813 LogAllSitesAction(AllSitesAction2::kLoadPage);
814
815 send_sites_list_ = true;
816
817 ResolveJavascriptCallback(base::Value(callback_id), result);
818 }
819
HandleGetCookieControlsManagedState(const base::ListValue * args)820 void SiteSettingsHandler::HandleGetCookieControlsManagedState(
821 const base::ListValue* args) {
822 AllowJavascript();
823 CHECK_EQ(1U, args->GetList().size());
824 std::string callback_id = args->GetList()[0].GetString();
825
826 auto managed_states = site_settings::GetCookieControlsManagedState(profile_);
827
828 base::Value result(base::Value::Type::DICTIONARY);
829 result.SetKey(
830 site_settings::kAllowAll,
831 site_settings::GetValueForManagedState(managed_states.allow_all));
832 result.SetKey(site_settings::kBlockThirdPartyIncognito,
833 site_settings::GetValueForManagedState(
834 managed_states.block_third_party_incognito));
835 result.SetKey(
836 site_settings::kBlockThirdParty,
837 site_settings::GetValueForManagedState(managed_states.block_third_party));
838 result.SetKey(
839 site_settings::kBlockAll,
840 site_settings::GetValueForManagedState(managed_states.block_all));
841 result.SetKey(
842 site_settings::kSessionOnly,
843 site_settings::GetValueForManagedState(managed_states.session_only));
844
845 ResolveJavascriptCallback(base::Value(callback_id), result);
846 }
847
HandleGetCookieSettingDescription(const base::ListValue * args)848 void SiteSettingsHandler::HandleGetCookieSettingDescription(
849 const base::ListValue* args) {
850 AllowJavascript();
851 CHECK_EQ(1U, args->GetList().size());
852 std::string callback_id = args->GetList()[0].GetString();
853 ResolveJavascriptCallback(base::Value(callback_id),
854 base::Value(GetCookieSettingDescription(profile_)));
855 }
856
HandleGetRecentSitePermissions(const base::ListValue * args)857 void SiteSettingsHandler::HandleGetRecentSitePermissions(
858 const base::ListValue* args) {
859 AllowJavascript();
860
861 CHECK_EQ(3U, args->GetList().size());
862 std::string callback_id = args->GetList()[0].GetString();
863 auto types = args->GetList()[1].GetList();
864 size_t max_sources = base::checked_cast<size_t>(args->GetList()[2].GetInt());
865
866 auto content_types = site_settings::ContentSettingsTypesFromGroupNames(types);
867 auto recent_site_permissions = site_settings::GetRecentSitePermissions(
868 profile_, content_types, max_sources);
869
870 // Convert groups of TimestampedPermissions for consumption by JS
871 base::Value result(base::Value::Type::LIST);
872 for (const auto& site_permissions : recent_site_permissions) {
873 DCHECK(!site_permissions.settings.empty());
874 base::Value recent_site(base::Value::Type::DICTIONARY);
875 recent_site.SetKey(site_settings::kOrigin,
876 base::Value(site_permissions.origin.spec()));
877 recent_site.SetKey(site_settings::kIncognito,
878 base::Value(site_permissions.incognito));
879
880 base::Value permissions_list(base::Value::Type::LIST);
881 for (const auto& p : site_permissions.settings) {
882 base::Value recent_permission(base::Value::Type::DICTIONARY);
883 recent_permission.SetKey(
884 site_settings::kType,
885 base::Value(
886 site_settings::ContentSettingsTypeToGroupName(p.content_type)));
887 recent_permission.SetKey(
888 site_settings::kSetting,
889 base::Value(
890 content_settings::ContentSettingToString(p.content_setting)));
891 recent_permission.SetKey(
892 site_settings::kSource,
893 base::Value(
894 site_settings::SiteSettingSourceToString(p.setting_source)));
895 permissions_list.Append(std::move(recent_permission));
896 }
897 recent_site.SetKey(site_settings::kRecentPermissions,
898 std::move(permissions_list));
899 result.Append(std::move(recent_site));
900 }
901 ResolveJavascriptCallback(base::Value(callback_id), result);
902 }
903
PopulateCookiesAndUsageData(Profile * profile)904 base::Value SiteSettingsHandler::PopulateCookiesAndUsageData(Profile* profile) {
905 std::map<std::string, int64_t> origin_size_map;
906 std::map<std::string, int> origin_cookie_map;
907 base::Value list_value(base::Value::Type::LIST);
908
909 GetOriginStorage(&all_sites_map_, &origin_size_map);
910 GetOriginCookies(&all_sites_map_, &origin_cookie_map);
911 ConvertSiteGroupMapToListValue(all_sites_map_, origin_permission_set_,
912 &list_value, profile, app_registrar_);
913
914 // Merge the origin usage and cookies number into |list_value|.
915 for (base::Value& site_group : list_value.GetList()) {
916 base::Value* origin_list = site_group.FindKey(kOriginList);
917 int cookie_num = 0;
918 const std::string& etld_plus1 =
919 site_group.FindKey(kEffectiveTopLevelDomainPlus1Name)->GetString();
920 const auto& etld_plus1_cookie_num_it = origin_cookie_map.find(etld_plus1);
921 // Add the number of eTLD+1 scoped cookies.
922 if (etld_plus1_cookie_num_it != origin_cookie_map.end())
923 cookie_num = etld_plus1_cookie_num_it->second;
924 // Iterate over the origins for the ETLD+1, and set their usage and cookie
925 // numbers.
926 for (base::Value& origin_info : origin_list->GetList()) {
927 const std::string& origin = origin_info.FindKey("origin")->GetString();
928 const auto& size_info_it = origin_size_map.find(origin);
929 if (size_info_it != origin_size_map.end())
930 origin_info.SetKey(
931 "usage", base::Value(static_cast<double>(size_info_it->second)));
932 GURL origin_url(origin);
933 const auto& origin_cookie_num_it =
934 origin_cookie_map.find(origin_url.host());
935 if (origin_cookie_num_it != origin_cookie_map.end()) {
936 origin_info.SetKey(kNumCookies,
937 base::Value(origin_cookie_num_it->second));
938 // Add cookies numbers for origins that isn't an eTLD+1.
939 if (origin_url.host() != etld_plus1)
940 cookie_num += origin_cookie_num_it->second;
941 }
942 }
943 site_group.SetKey(kNumCookies, base::Value(cookie_num));
944 }
945 return list_value;
946 }
947
OnStorageFetched()948 void SiteSettingsHandler::OnStorageFetched() {
949 AllowJavascript();
950 FireWebUIListener("onStorageListFetched",
951 PopulateCookiesAndUsageData(profile_));
952 }
953
HandleGetFormattedBytes(const base::ListValue * args)954 void SiteSettingsHandler::HandleGetFormattedBytes(const base::ListValue* args) {
955 AllowJavascript();
956
957 CHECK_EQ(2U, args->GetSize());
958 const base::Value* callback_id;
959 CHECK(args->Get(0, &callback_id));
960 double num_bytes;
961 CHECK(args->GetDouble(1, &num_bytes));
962
963 const base::string16 string = ui::FormatBytes(int64_t(num_bytes));
964 ResolveJavascriptCallback(*callback_id, base::Value(string));
965 }
966
HandleGetExceptionList(const base::ListValue * args)967 void SiteSettingsHandler::HandleGetExceptionList(const base::ListValue* args) {
968 AllowJavascript();
969
970 CHECK_EQ(2U, args->GetSize());
971 const base::Value* callback_id;
972 CHECK(args->Get(0, &callback_id));
973 std::string type;
974 CHECK(args->GetString(1, &type));
975 ContentSettingsType content_type =
976 site_settings::ContentSettingsTypeFromGroupName(type);
977
978 std::unique_ptr<base::ListValue> exceptions(new base::ListValue);
979
980 HostContentSettingsMap* map =
981 HostContentSettingsMapFactory::GetForProfile(profile_);
982 const auto* extension_registry = extensions::ExtensionRegistry::Get(profile_);
983 AddExceptionsGrantedByHostedApps(profile_, APIPermissionFromGroupName(type),
984 exceptions.get());
985 site_settings::GetExceptionsFromHostContentSettingsMap(
986 map, content_type, extension_registry, web_ui(), /*incognito=*/false,
987 /*filter=*/nullptr, exceptions.get());
988
989 Profile* incognito = profile_->HasOffTheRecordProfile()
990 ? profile_->GetOffTheRecordProfile()
991 : nullptr;
992 // On Chrome OS in Guest mode the incognito profile is the primary profile,
993 // so do not fetch an extra copy of the same exceptions.
994 if (incognito && incognito != profile_) {
995 map = HostContentSettingsMapFactory::GetForProfile(incognito);
996 extension_registry = extensions::ExtensionRegistry::Get(incognito);
997 site_settings::GetExceptionsFromHostContentSettingsMap(
998 map, content_type, extension_registry, web_ui(), /*incognito=*/true,
999 /*filter=*/nullptr, exceptions.get());
1000 }
1001
1002 ResolveJavascriptCallback(*callback_id, *exceptions.get());
1003 }
1004
HandleGetChooserExceptionList(const base::ListValue * args)1005 void SiteSettingsHandler::HandleGetChooserExceptionList(
1006 const base::ListValue* args) {
1007 AllowJavascript();
1008
1009 CHECK_EQ(2U, args->GetSize());
1010 const base::Value* callback_id;
1011 CHECK(args->Get(0, &callback_id));
1012 std::string type;
1013 CHECK(args->GetString(1, &type));
1014 const site_settings::ChooserTypeNameEntry* chooser_type =
1015 site_settings::ChooserTypeFromGroupName(type);
1016 CHECK(chooser_type);
1017
1018 base::Value exceptions = site_settings::GetChooserExceptionListFromProfile(
1019 profile_, *chooser_type);
1020 ResolveJavascriptCallback(*callback_id, std::move(exceptions));
1021 }
1022
HandleGetOriginPermissions(const base::ListValue * args)1023 void SiteSettingsHandler::HandleGetOriginPermissions(
1024 const base::ListValue* args) {
1025 AllowJavascript();
1026
1027 CHECK_EQ(3U, args->GetSize());
1028 const base::Value* callback_id;
1029 CHECK(args->Get(0, &callback_id));
1030 std::string origin;
1031 CHECK(args->GetString(1, &origin));
1032 const base::ListValue* types;
1033 CHECK(args->GetList(2, &types));
1034
1035 // Note: Invalid URLs will just result in default settings being shown.
1036 const GURL origin_url(origin);
1037 auto exceptions = std::make_unique<base::ListValue>();
1038 for (size_t i = 0; i < types->GetSize(); ++i) {
1039 std::string type;
1040 types->GetString(i, &type);
1041 ContentSettingsType content_type =
1042 site_settings::ContentSettingsTypeFromGroupName(type);
1043 HostContentSettingsMap* map =
1044 HostContentSettingsMapFactory::GetForProfile(profile_);
1045 const auto* extension_registry =
1046 extensions::ExtensionRegistry::Get(profile_);
1047
1048 std::string source_string, display_name;
1049 ContentSetting content_setting = site_settings::GetContentSettingForOrigin(
1050 profile_, map, origin_url, content_type, &source_string,
1051 extension_registry, &display_name);
1052 std::string content_setting_string =
1053 content_settings::ContentSettingToString(content_setting);
1054
1055 auto raw_site_exception = std::make_unique<base::DictionaryValue>();
1056 raw_site_exception->SetString(site_settings::kEmbeddingOrigin, origin);
1057 raw_site_exception->SetBoolean(site_settings::kIncognito,
1058 profile_->IsOffTheRecord());
1059 raw_site_exception->SetString(site_settings::kOrigin, origin);
1060 raw_site_exception->SetString(site_settings::kDisplayName, display_name);
1061 raw_site_exception->SetString(site_settings::kSetting,
1062 content_setting_string);
1063 raw_site_exception->SetString(site_settings::kSource, source_string);
1064 exceptions->Append(std::move(raw_site_exception));
1065 }
1066
1067 ResolveJavascriptCallback(*callback_id, *exceptions);
1068 }
1069
HandleSetOriginPermissions(const base::ListValue * args)1070 void SiteSettingsHandler::HandleSetOriginPermissions(
1071 const base::ListValue* args) {
1072 CHECK_EQ(3U, args->GetSize());
1073 std::string origin_string;
1074 CHECK(args->GetString(0, &origin_string));
1075 const base::ListValue* types;
1076 CHECK(args->GetList(1, &types));
1077 std::string value;
1078 CHECK(args->GetString(2, &value));
1079
1080 const GURL origin(origin_string);
1081 if (!origin.is_valid())
1082 return;
1083
1084 ContentSetting setting;
1085 CHECK(content_settings::ContentSettingFromString(value, &setting));
1086 for (size_t i = 0; i < types->GetSize(); ++i) {
1087 std::string type;
1088 types->GetString(i, &type);
1089
1090 ContentSettingsType content_type =
1091 site_settings::ContentSettingsTypeFromGroupName(type);
1092 HostContentSettingsMap* map =
1093 HostContentSettingsMapFactory::GetForProfile(profile_);
1094
1095 permissions::PermissionUmaUtil::ScopedRevocationReporter
1096 scoped_revocation_reporter(
1097 profile_, origin, origin, content_type,
1098 permissions::PermissionSourceUI::SITE_SETTINGS);
1099
1100 // Clear any existing embargo status if the new setting isn't block.
1101 if (setting != CONTENT_SETTING_BLOCK) {
1102 PermissionDecisionAutoBlockerFactory::GetForProfile(profile_)
1103 ->RemoveEmbargoByUrl(origin, content_type);
1104 }
1105 map->SetContentSettingDefaultScope(origin, origin, content_type,
1106 std::string(), setting);
1107 if (content_type == ContentSettingsType::SOUND) {
1108 ContentSetting default_setting =
1109 map->GetDefaultContentSetting(ContentSettingsType::SOUND, nullptr);
1110 bool mute = (setting == CONTENT_SETTING_BLOCK) ||
1111 (setting == CONTENT_SETTING_DEFAULT &&
1112 default_setting == CONTENT_SETTING_BLOCK);
1113 if (mute) {
1114 base::RecordAction(
1115 base::UserMetricsAction("SoundContentSetting.MuteBy.SiteSettings"));
1116 } else {
1117 base::RecordAction(base::UserMetricsAction(
1118 "SoundContentSetting.UnmuteBy.SiteSettings"));
1119 }
1120 }
1121 content_settings::LogWebSiteSettingsPermissionChange(content_type, setting);
1122 }
1123
1124 // Show an infobar reminding the user to reload tabs where their site
1125 // permissions have been updated.
1126 for (auto* it : *BrowserList::GetInstance()) {
1127 TabStripModel* tab_strip = it->tab_strip_model();
1128 for (int i = 0; i < tab_strip->count(); ++i) {
1129 content::WebContents* web_contents = tab_strip->GetWebContentsAt(i);
1130 GURL tab_url = web_contents->GetLastCommittedURL();
1131 if (url::IsSameOriginWith(origin, tab_url)) {
1132 InfoBarService* infobar_service =
1133 InfoBarService::FromWebContents(web_contents);
1134 PageInfoInfoBarDelegate::Create(infobar_service);
1135 }
1136 }
1137 }
1138 }
1139
HandleClearFlashPref(const base::ListValue * args)1140 void SiteSettingsHandler::HandleClearFlashPref(const base::ListValue* args) {
1141 CHECK_EQ(1U, args->GetSize());
1142 std::string origin_string;
1143 CHECK(args->GetString(0, &origin_string));
1144
1145 HostContentSettingsMap* map =
1146 HostContentSettingsMapFactory::GetForProfile(profile_);
1147 const GURL origin(origin_string);
1148 map->SetWebsiteSettingDefaultScope(origin, origin,
1149 ContentSettingsType::PLUGINS_DATA,
1150 std::string(), nullptr);
1151 }
1152
HandleResetCategoryPermissionForPattern(const base::ListValue * args)1153 void SiteSettingsHandler::HandleResetCategoryPermissionForPattern(
1154 const base::ListValue* args) {
1155 CHECK_EQ(4U, args->GetSize());
1156 std::string primary_pattern_string;
1157 CHECK(args->GetString(0, &primary_pattern_string));
1158 std::string secondary_pattern_string;
1159 CHECK(args->GetString(1, &secondary_pattern_string));
1160 std::string type;
1161 CHECK(args->GetString(2, &type));
1162 bool incognito;
1163 CHECK(args->GetBoolean(3, &incognito));
1164
1165 ContentSettingsType content_type =
1166 site_settings::ContentSettingsTypeFromGroupName(type);
1167
1168 Profile* profile = nullptr;
1169 if (incognito) {
1170 if (!profile_->HasOffTheRecordProfile())
1171 return;
1172 profile = profile_->GetOffTheRecordProfile();
1173 } else {
1174 profile = profile_;
1175 }
1176
1177 HostContentSettingsMap* map =
1178 HostContentSettingsMapFactory::GetForProfile(profile);
1179
1180 ContentSettingsPattern primary_pattern =
1181 ContentSettingsPattern::FromString(primary_pattern_string);
1182 ContentSettingsPattern secondary_pattern =
1183 secondary_pattern_string.empty()
1184 ? ContentSettingsPattern::Wildcard()
1185 : ContentSettingsPattern::FromString(secondary_pattern_string);
1186 permissions::PermissionUmaUtil::ScopedRevocationReporter
1187 scoped_revocation_reporter(
1188 profile, primary_pattern, secondary_pattern, content_type,
1189 permissions::PermissionSourceUI::SITE_SETTINGS);
1190
1191 map->SetContentSettingCustomScope(primary_pattern, secondary_pattern,
1192 content_type, "", CONTENT_SETTING_DEFAULT);
1193
1194 if (content_type == ContentSettingsType::SOUND) {
1195 ContentSetting default_setting =
1196 map->GetDefaultContentSetting(ContentSettingsType::SOUND, nullptr);
1197 if (default_setting == CONTENT_SETTING_BLOCK) {
1198 base::RecordAction(base::UserMetricsAction(
1199 "SoundContentSetting.MuteBy.PatternException"));
1200 } else {
1201 base::RecordAction(base::UserMetricsAction(
1202 "SoundContentSetting.UnmuteBy.PatternException"));
1203 }
1204 }
1205 content_settings::LogWebSiteSettingsPermissionChange(
1206 content_type, ContentSetting::CONTENT_SETTING_DEFAULT);
1207 }
1208
HandleSetCategoryPermissionForPattern(const base::ListValue * args)1209 void SiteSettingsHandler::HandleSetCategoryPermissionForPattern(
1210 const base::ListValue* args) {
1211 CHECK_EQ(5U, args->GetSize());
1212 std::string primary_pattern_string;
1213 CHECK(args->GetString(0, &primary_pattern_string));
1214 std::string secondary_pattern_string;
1215 CHECK(args->GetString(1, &secondary_pattern_string));
1216 std::string type;
1217 CHECK(args->GetString(2, &type));
1218 std::string value;
1219 CHECK(args->GetString(3, &value));
1220 bool incognito;
1221 CHECK(args->GetBoolean(4, &incognito));
1222
1223 ContentSettingsType content_type =
1224 site_settings::ContentSettingsTypeFromGroupName(type);
1225 ContentSetting setting;
1226 CHECK(content_settings::ContentSettingFromString(value, &setting));
1227
1228 Profile* profile = nullptr;
1229 if (incognito) {
1230 if (!profile_->HasOffTheRecordProfile())
1231 return;
1232 profile = profile_->GetOffTheRecordProfile();
1233 } else {
1234 profile = profile_;
1235 }
1236
1237 HostContentSettingsMap* map =
1238 HostContentSettingsMapFactory::GetForProfile(profile);
1239
1240 ContentSettingsPattern primary_pattern =
1241 ContentSettingsPattern::FromString(primary_pattern_string);
1242 ContentSettingsPattern secondary_pattern =
1243 secondary_pattern_string.empty()
1244 ? ContentSettingsPattern::Wildcard()
1245 : ContentSettingsPattern::FromString(secondary_pattern_string);
1246
1247 permissions::PermissionUmaUtil::ScopedRevocationReporter
1248 scoped_revocation_reporter(
1249 profile, primary_pattern, secondary_pattern, content_type,
1250 permissions::PermissionSourceUI::SITE_SETTINGS);
1251
1252 map->SetContentSettingCustomScope(primary_pattern, secondary_pattern,
1253 content_type, "", setting);
1254
1255 if (content_type == ContentSettingsType::SOUND) {
1256 ContentSetting default_setting =
1257 map->GetDefaultContentSetting(ContentSettingsType::SOUND, nullptr);
1258 bool mute = (setting == CONTENT_SETTING_BLOCK) ||
1259 (setting == CONTENT_SETTING_DEFAULT &&
1260 default_setting == CONTENT_SETTING_BLOCK);
1261 if (mute) {
1262 base::RecordAction(base::UserMetricsAction(
1263 "SoundContentSetting.MuteBy.PatternException"));
1264 } else {
1265 base::RecordAction(base::UserMetricsAction(
1266 "SoundContentSetting.UnmuteBy.PatternException"));
1267 }
1268 }
1269 content_settings::LogWebSiteSettingsPermissionChange(content_type, setting);
1270 }
1271
HandleResetChooserExceptionForSite(const base::ListValue * args)1272 void SiteSettingsHandler::HandleResetChooserExceptionForSite(
1273 const base::ListValue* args) {
1274 CHECK_EQ(4U, args->GetSize());
1275
1276 std::string chooser_type_str;
1277 CHECK(args->GetString(0, &chooser_type_str));
1278 const site_settings::ChooserTypeNameEntry* chooser_type =
1279 site_settings::ChooserTypeFromGroupName(chooser_type_str);
1280 CHECK(chooser_type);
1281
1282 std::string origin_str;
1283 CHECK(args->GetString(1, &origin_str));
1284 GURL requesting_origin(origin_str);
1285 CHECK(requesting_origin.is_valid());
1286
1287 std::string embedding_origin_str;
1288 CHECK(args->GetString(2, &embedding_origin_str));
1289 GURL embedding_origin(embedding_origin_str);
1290 CHECK(embedding_origin.is_valid());
1291
1292 permissions::ChooserContextBase* chooser_context =
1293 chooser_type->get_context(profile_);
1294 chooser_context->RevokeObjectPermission(
1295 url::Origin::Create(requesting_origin),
1296 url::Origin::Create(embedding_origin), args->GetList()[3]);
1297 }
1298
HandleIsOriginValid(const base::ListValue * args)1299 void SiteSettingsHandler::HandleIsOriginValid(const base::ListValue* args) {
1300 AllowJavascript();
1301 CHECK_EQ(2U, args->GetSize());
1302 const base::Value* callback_id;
1303 CHECK(args->Get(0, &callback_id));
1304 std::string origin_string;
1305 CHECK(args->GetString(1, &origin_string));
1306
1307 ResolveJavascriptCallback(*callback_id,
1308 base::Value(GURL(origin_string).is_valid()));
1309 }
1310
HandleIsPatternValidForType(const base::ListValue * args)1311 void SiteSettingsHandler::HandleIsPatternValidForType(
1312 const base::ListValue* args) {
1313 AllowJavascript();
1314 CHECK_EQ(3U, args->GetSize());
1315 const base::Value* callback_id;
1316 CHECK(args->Get(0, &callback_id));
1317 std::string pattern_string;
1318 CHECK(args->GetString(1, &pattern_string));
1319 std::string type;
1320 CHECK(args->GetString(2, &type));
1321
1322 std::string reason = "";
1323 bool is_valid =
1324 IsPatternValidForType(pattern_string, type, profile_, &reason);
1325
1326 base::Value return_value(base::Value::Type::DICTIONARY);
1327 return_value.SetKey(kIsValidKey, base::Value(is_valid));
1328 return_value.SetKey(kReasonKey, base::Value(std::move(reason)));
1329 ResolveJavascriptCallback(*callback_id, return_value);
1330 }
1331
HandleUpdateIncognitoStatus(const base::ListValue * args)1332 void SiteSettingsHandler::HandleUpdateIncognitoStatus(
1333 const base::ListValue* args) {
1334 AllowJavascript();
1335 FireWebUIListener("onIncognitoStatusChanged",
1336 base::Value(profile_->HasOffTheRecordProfile()));
1337 }
1338
HandleFetchZoomLevels(const base::ListValue * args)1339 void SiteSettingsHandler::HandleFetchZoomLevels(const base::ListValue* args) {
1340 AllowJavascript();
1341 SendZoomLevels();
1342 }
1343
SendZoomLevels()1344 void SiteSettingsHandler::SendZoomLevels() {
1345 if (!IsJavascriptAllowed())
1346 return;
1347
1348 base::ListValue zoom_levels_exceptions;
1349
1350 content::HostZoomMap* host_zoom_map =
1351 content::HostZoomMap::GetDefaultForBrowserContext(profile_);
1352 content::HostZoomMap::ZoomLevelVector zoom_levels(
1353 host_zoom_map->GetAllZoomLevels());
1354
1355 const auto* extension_registry = extensions::ExtensionRegistry::Get(profile_);
1356
1357 // Sort ZoomLevelChanges by host and scheme
1358 // (a.com < http://a.com < https://a.com < b.com).
1359 std::sort(zoom_levels.begin(), zoom_levels.end(),
1360 [](const content::HostZoomMap::ZoomLevelChange& a,
1361 const content::HostZoomMap::ZoomLevelChange& b) {
1362 return a.host == b.host ? a.scheme < b.scheme : a.host < b.host;
1363 });
1364 for (const auto& zoom_level : zoom_levels) {
1365 std::unique_ptr<base::DictionaryValue> exception(new base::DictionaryValue);
1366 switch (zoom_level.mode) {
1367 case content::HostZoomMap::ZOOM_CHANGED_FOR_HOST: {
1368 std::string host = zoom_level.host;
1369 if (host == content::kUnreachableWebDataURL) {
1370 host =
1371 l10n_util::GetStringUTF8(IDS_ZOOMLEVELS_CHROME_ERROR_PAGES_LABEL);
1372 }
1373 exception->SetString(site_settings::kOrigin, host);
1374
1375 std::string display_name = host;
1376 std::string origin_for_favicon = host;
1377 // As an optimization, only check hosts that could be an extension.
1378 if (crx_file::id_util::IdIsValid(host)) {
1379 // Look up the host as an extension, if found then it is an extension.
1380 const extensions::Extension* extension =
1381 extension_registry->GetExtensionById(
1382 host, extensions::ExtensionRegistry::EVERYTHING);
1383 if (extension) {
1384 origin_for_favicon = extension->url().spec();
1385 display_name = extension->name();
1386 }
1387 }
1388 exception->SetString(site_settings::kDisplayName, display_name);
1389 exception->SetString(site_settings::kOriginForFavicon,
1390 origin_for_favicon);
1391 break;
1392 }
1393 case content::HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST:
1394 // These are not stored in preferences and get cleared on next browser
1395 // start. Therefore, we don't care for them.
1396 continue;
1397 case content::HostZoomMap::PAGE_SCALE_IS_ONE_CHANGED:
1398 continue;
1399 case content::HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM:
1400 NOTREACHED();
1401 }
1402
1403 std::string setting_string =
1404 content_settings::ContentSettingToString(CONTENT_SETTING_DEFAULT);
1405 DCHECK(!setting_string.empty());
1406
1407 exception->SetString(site_settings::kSetting, setting_string);
1408
1409 // Calculate the zoom percent from the factor. Round up to the nearest whole
1410 // number.
1411 int zoom_percent = static_cast<int>(
1412 blink::PageZoomLevelToZoomFactor(zoom_level.zoom_level) * 100 + 0.5);
1413 exception->SetString(kZoom, base::FormatPercent(zoom_percent));
1414 exception->SetString(site_settings::kSource,
1415 site_settings::SiteSettingSourceToString(
1416 site_settings::SiteSettingSource::kPreference));
1417 // Append the new entry to the list and map.
1418 zoom_levels_exceptions.Append(std::move(exception));
1419 }
1420
1421 FireWebUIListener("onZoomLevelsChanged", zoom_levels_exceptions);
1422 }
1423
HandleRemoveZoomLevel(const base::ListValue * args)1424 void SiteSettingsHandler::HandleRemoveZoomLevel(const base::ListValue* args) {
1425 CHECK_EQ(1U, args->GetSize());
1426
1427 std::string origin;
1428 CHECK(args->GetString(0, &origin));
1429
1430 if (origin ==
1431 l10n_util::GetStringUTF8(IDS_ZOOMLEVELS_CHROME_ERROR_PAGES_LABEL)) {
1432 origin = content::kUnreachableWebDataURL;
1433 }
1434
1435 content::HostZoomMap* host_zoom_map;
1436 host_zoom_map = content::HostZoomMap::GetDefaultForBrowserContext(profile_);
1437 double default_level = host_zoom_map->GetDefaultZoomLevel();
1438 host_zoom_map->SetZoomLevelForHost(origin, default_level);
1439 }
1440
HandleFetchBlockAutoplayStatus(const base::ListValue * args)1441 void SiteSettingsHandler::HandleFetchBlockAutoplayStatus(
1442 const base::ListValue* args) {
1443 AllowJavascript();
1444 SendBlockAutoplayStatus();
1445 }
1446
SendBlockAutoplayStatus()1447 void SiteSettingsHandler::SendBlockAutoplayStatus() {
1448 if (!IsJavascriptAllowed())
1449 return;
1450
1451 base::DictionaryValue status;
1452
1453 // Whether the block autoplay toggle should be checked.
1454 base::DictionaryValue pref;
1455 pref.SetKey(
1456 "value",
1457 base::Value(
1458 UnifiedAutoplayConfig::ShouldBlockAutoplay(profile_) &&
1459 UnifiedAutoplayConfig::IsBlockAutoplayUserModifiable(profile_)));
1460 status.SetKey("pref", std::move(pref));
1461
1462 // Whether the block autoplay toggle should be enabled.
1463 status.SetKey(
1464 "enabled",
1465 base::Value(
1466 UnifiedAutoplayConfig::IsBlockAutoplayUserModifiable(profile_)));
1467
1468 FireWebUIListener("onBlockAutoplayStatusChanged", status);
1469 }
1470
HandleSetBlockAutoplayEnabled(const base::ListValue * args)1471 void SiteSettingsHandler::HandleSetBlockAutoplayEnabled(
1472 const base::ListValue* args) {
1473 AllowJavascript();
1474
1475 if (!UnifiedAutoplayConfig::IsBlockAutoplayUserModifiable(profile_))
1476 return;
1477
1478 CHECK_EQ(1U, args->GetSize());
1479 bool value;
1480 CHECK(args->GetBoolean(0, &value));
1481
1482 profile_->GetPrefs()->SetBoolean(prefs::kBlockAutoplayEnabled, value);
1483 }
1484
EnsureCookiesTreeModelCreated()1485 void SiteSettingsHandler::EnsureCookiesTreeModelCreated() {
1486 if (cookies_tree_model_)
1487 return;
1488 cookies_tree_model_ = CookiesTreeModel::CreateForProfile(profile_);
1489 cookies_tree_model_->AddCookiesTreeObserver(this);
1490 }
1491
ObserveSourcesForProfile(Profile * profile)1492 void SiteSettingsHandler::ObserveSourcesForProfile(Profile* profile) {
1493 auto* map = HostContentSettingsMapFactory::GetForProfile(profile);
1494 if (!observer_.IsObserving(map))
1495 observer_.Add(map);
1496
1497 auto* usb_context = UsbChooserContextFactory::GetForProfile(profile);
1498 if (!chooser_observer_.IsObserving(usb_context))
1499 chooser_observer_.Add(usb_context);
1500
1501 auto* serial_context = SerialChooserContextFactory::GetForProfile(profile);
1502 if (!chooser_observer_.IsObserving(serial_context))
1503 chooser_observer_.Add(serial_context);
1504
1505 auto* hid_context = HidChooserContextFactory::GetForProfile(profile);
1506 if (!chooser_observer_.IsObserving(hid_context))
1507 chooser_observer_.Add(hid_context);
1508
1509 if (base::FeatureList::IsEnabled(
1510 features::kWebBluetoothNewPermissionsBackend)) {
1511 auto* bluetooth_context =
1512 BluetoothChooserContextFactory::GetForProfile(profile);
1513 if (!chooser_observer_.IsObserving(bluetooth_context))
1514 chooser_observer_.Add(bluetooth_context);
1515 }
1516
1517 observed_profiles_.Add(profile);
1518 }
1519
StopObservingSourcesForProfile(Profile * profile)1520 void SiteSettingsHandler::StopObservingSourcesForProfile(Profile* profile) {
1521 auto* map = HostContentSettingsMapFactory::GetForProfile(profile);
1522 if (observer_.IsObserving(map))
1523 observer_.Remove(map);
1524
1525 auto* usb_context = UsbChooserContextFactory::GetForProfile(profile);
1526 if (chooser_observer_.IsObserving(usb_context))
1527 chooser_observer_.Remove(usb_context);
1528
1529 auto* serial_context = SerialChooserContextFactory::GetForProfile(profile);
1530 if (chooser_observer_.IsObserving(serial_context))
1531 chooser_observer_.Remove(serial_context);
1532
1533 auto* hid_context = HidChooserContextFactory::GetForProfile(profile);
1534 if (chooser_observer_.IsObserving(hid_context))
1535 chooser_observer_.Remove(hid_context);
1536
1537 if (base::FeatureList::IsEnabled(
1538 features::kWebBluetoothNewPermissionsBackend)) {
1539 auto* bluetooth_context =
1540 BluetoothChooserContextFactory::GetForProfile(profile);
1541 if (chooser_observer_.IsObserving(bluetooth_context))
1542 chooser_observer_.Remove(bluetooth_context);
1543 }
1544
1545 observed_profiles_.Remove(profile);
1546 }
1547
TreeNodesAdded(ui::TreeModel * model,ui::TreeModelNode * parent,size_t start,size_t count)1548 void SiteSettingsHandler::TreeNodesAdded(ui::TreeModel* model,
1549 ui::TreeModelNode* parent,
1550 size_t start,
1551 size_t count) {}
1552
TreeNodesRemoved(ui::TreeModel * model,ui::TreeModelNode * parent,size_t start,size_t count)1553 void SiteSettingsHandler::TreeNodesRemoved(ui::TreeModel* model,
1554 ui::TreeModelNode* parent,
1555 size_t start,
1556 size_t count) {}
1557
TreeNodeChanged(ui::TreeModel * model,ui::TreeModelNode * node)1558 void SiteSettingsHandler::TreeNodeChanged(ui::TreeModel* model,
1559 ui::TreeModelNode* node) {}
1560
TreeModelEndBatch(CookiesTreeModel * model)1561 void SiteSettingsHandler::TreeModelEndBatch(CookiesTreeModel* model) {
1562 // The WebUI may have shut down before we get the data.
1563 if (!IsJavascriptAllowed())
1564 return;
1565 if (send_sites_list_)
1566 OnStorageFetched();
1567 if (update_site_details_)
1568 OnGetUsageInfo();
1569 send_sites_list_ = false;
1570 update_site_details_ = false;
1571 }
1572
GetOriginStorage(std::map<std::string,std::set<std::string>> * all_sites_map,std::map<std::string,int64_t> * origin_size_map)1573 void SiteSettingsHandler::GetOriginStorage(
1574 std::map<std::string, std::set<std::string>>* all_sites_map,
1575 std::map<std::string, int64_t>* origin_size_map) {
1576 CHECK(cookies_tree_model_.get());
1577
1578 for (const auto& site : cookies_tree_model_->GetRoot()->children()) {
1579 int64_t size = site->InclusiveSize();
1580 if (size == 0)
1581 continue;
1582 UpdateDataFromCookiesTree(all_sites_map, origin_size_map,
1583 site->GetDetailedInfo().origin.GetURL(), size);
1584 }
1585 }
1586
GetOriginCookies(std::map<std::string,std::set<std::string>> * all_sites_map,std::map<std::string,int> * origin_cookie_map)1587 void SiteSettingsHandler::GetOriginCookies(
1588 std::map<std::string, std::set<std::string>>* all_sites_map,
1589 std::map<std::string, int>* origin_cookie_map) {
1590 CHECK(cookies_tree_model_.get());
1591 // Get sites that don't have data but have cookies.
1592 for (const auto& site : cookies_tree_model_->GetRoot()->children()) {
1593 GURL url = site->GetDetailedInfo().origin.GetURL();
1594 (*origin_cookie_map)[url.host()] = site->NumberOfCookies();
1595 CreateOrAppendSiteGroupEntry(all_sites_map, url,
1596 /*url_is_origin_with_cookies = */ true);
1597 }
1598 }
1599
HandleClearEtldPlus1DataAndCookies(const base::ListValue * args)1600 void SiteSettingsHandler::HandleClearEtldPlus1DataAndCookies(
1601 const base::ListValue* args) {
1602 CHECK_EQ(1U, args->GetSize());
1603 std::string etld_plus1_string;
1604 CHECK(args->GetString(0, &etld_plus1_string));
1605
1606 AllowJavascript();
1607 CookieTreeNode* parent = cookies_tree_model_->GetRoot();
1608
1609 // Find all the nodes that contain the given etld+1.
1610 std::vector<CookieTreeNode*> nodes_to_delete;
1611 for (const auto& node : parent->children()) {
1612 std::string cookie_node_etld_plus1 =
1613 net::registry_controlled_domains::GetDomainAndRegistry(
1614 base::UTF16ToUTF8(node->GetTitle()),
1615 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
1616 if (etld_plus1_string == cookie_node_etld_plus1)
1617 nodes_to_delete.push_back(node.get());
1618 }
1619 for (auto* node : nodes_to_delete)
1620 cookies_tree_model_->DeleteCookieNode(node);
1621 }
1622
HandleRecordAction(const base::ListValue * args)1623 void SiteSettingsHandler::HandleRecordAction(const base::ListValue* args) {
1624 CHECK_EQ(1U, args->GetSize());
1625 int action;
1626 CHECK(args->GetInteger(0, &action));
1627 DCHECK_LE(action, static_cast<int>(AllSitesAction2::kMaxValue));
1628 DCHECK_GE(action, static_cast<int>(AllSitesAction2::kLoadPage));
1629
1630 LogAllSitesAction(static_cast<AllSitesAction2>(action));
1631 }
1632
SetCookiesTreeModelForTesting(std::unique_ptr<CookiesTreeModel> cookies_tree_model)1633 void SiteSettingsHandler::SetCookiesTreeModelForTesting(
1634 std::unique_ptr<CookiesTreeModel> cookies_tree_model) {
1635 cookies_tree_model_ = std::move(cookies_tree_model);
1636 }
1637
ClearAllSitesMapForTesting()1638 void SiteSettingsHandler::ClearAllSitesMapForTesting() {
1639 all_sites_map_.clear();
1640 }
1641
SendCookieSettingDescription()1642 void SiteSettingsHandler::SendCookieSettingDescription() {
1643 FireWebUIListener("cookieSettingDescriptionChanged",
1644 base::Value(GetCookieSettingDescription(profile_)));
1645 }
1646
1647 } // namespace settings
1648