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