forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcookie_settings.cc
186 lines (160 loc) · 6.35 KB
/
cookie_settings.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/network/cookie_settings.h"
#include <functional>
#include "base/bind.h"
#include "base/callback.h"
#include "net/base/net_errors.h"
#include "net/cookies/cookie_util.h"
#include "net/cookies/static_cookie_policy.h"
namespace network {
namespace {
bool IsDefaultSetting(const ContentSettingPatternSource& setting) {
return setting.primary_pattern.MatchesAllHosts() &&
setting.secondary_pattern.MatchesAllHosts();
}
} // namespace
CookieSettings::CookieSettings() = default;
CookieSettings::~CookieSettings() = default;
DeleteCookiePredicate CookieSettings::CreateDeleteCookieOnExitPredicate()
const {
if (!HasSessionOnlyOrigins())
return DeleteCookiePredicate();
return base::BindRepeating(&CookieSettings::ShouldDeleteCookieOnExit,
base::Unretained(this),
std::cref(content_settings_));
}
void CookieSettings::GetSettingForLegacyCookieAccess(
const std::string& cookie_domain,
ContentSetting* setting) const {
DCHECK(setting);
// Default to match what was registered in the ContentSettingsRegistry.
*setting = net::cookie_util::IsSameSiteByDefaultCookiesEnabled()
? CONTENT_SETTING_BLOCK
: CONTENT_SETTING_ALLOW;
if (settings_for_legacy_cookie_access_.empty())
return;
// If there are no domain-specific settings, return early to avoid the cost of
// constructing a GURL to match against.
bool has_non_wildcard_setting = false;
for (const auto& entry : settings_for_legacy_cookie_access_) {
if (!entry.primary_pattern.MatchesAllHosts()) {
has_non_wildcard_setting = true;
break;
}
}
if (!has_non_wildcard_setting) {
// Take the first entry because we know all entries match any host.
*setting = settings_for_legacy_cookie_access_[0].GetContentSetting();
DCHECK(IsValidSettingForLegacyAccess(*setting));
return;
}
// The content setting patterns are treated as domains, not URLs, so the
// scheme is irrelevant (so we can just arbitrarily pass false).
GURL cookie_domain_url = net::cookie_util::CookieOriginToURL(
cookie_domain, false /* secure scheme */);
for (const auto& entry : settings_for_legacy_cookie_access_) {
// TODO(crbug.com/1015611): This should ignore scheme and port, but
// currently takes them into account. It says in the policy description that
// specifying a scheme or port in the pattern may lead to undefined
// behavior, but this is not ideal.
if (entry.primary_pattern.Matches(cookie_domain_url)) {
*setting = entry.GetContentSetting();
DCHECK(IsValidSettingForLegacyAccess(*setting));
return;
}
}
}
bool CookieSettings::ShouldIgnoreSameSiteRestrictions(
const GURL& url,
const GURL& site_for_cookies) const {
return base::Contains(secure_origin_cookies_allowed_schemes_,
site_for_cookies.scheme()) &&
url.SchemeIsCryptographic();
}
bool CookieSettings::ShouldAlwaysAllowCookies(
const GURL& url,
const GURL& first_party_url) const {
if (base::Contains(secure_origin_cookies_allowed_schemes_,
first_party_url.scheme()) &&
url.SchemeIsCryptographic()) {
return true;
}
if (base::Contains(matching_scheme_cookies_allowed_schemes_, url.scheme()) &&
url.SchemeIs(first_party_url.scheme_piece())) {
return true;
}
return false;
}
void CookieSettings::GetCookieSettingInternal(
const GURL& url,
const GURL& first_party_url,
bool is_third_party_request,
content_settings::SettingSource* source,
ContentSetting* cookie_setting) const {
DCHECK(cookie_setting);
if (ShouldAlwaysAllowCookies(url, first_party_url)) {
*cookie_setting = CONTENT_SETTING_ALLOW;
return;
}
// Default to allowing cookies.
*cookie_setting = CONTENT_SETTING_ALLOW;
bool block_third = block_third_party_cookies_ &&
!base::Contains(third_party_cookies_allowed_schemes_,
first_party_url.scheme());
for (const auto& entry : content_settings_) {
if (entry.primary_pattern.Matches(url) &&
entry.secondary_pattern.Matches(first_party_url)) {
*cookie_setting = entry.GetContentSetting();
// Only continue to block third party cookies if there is not an explicit
// exception.
if (!IsDefaultSetting(entry))
block_third = false;
break;
}
}
bool block = block_third && is_third_party_request;
if (block) {
for (const auto& entry : storage_access_grants_) {
// If a valid entry exists that matches both our first party and request
// url this indicates a Storage Access API grant that may unblock
// storage access despite third party cookies being blocked.
// ContentSettingsType::STORAGE_ACCESS stores grants in the following
// manner:
// Primary Pattern: Embedded site requiring third party storage access
// Secondary Pattern: Top-Level site hosting embedded content
// Value: CONTENT_SETTING_[ALLOW/BLOCK] indicating grant
// status
if (!entry.IsExpired() && entry.primary_pattern.Matches(url) &&
entry.secondary_pattern.Matches(first_party_url)) {
ContentSetting storage_access_setting = entry.GetContentSetting();
// We'll only utilize the SAA grant if our value is set to
// CONTENT_SETTING_ALLOW as other values would indicate the user
// rejected a prompt to allow access.
if (storage_access_setting == CONTENT_SETTING_ALLOW) {
block = false;
FireStorageAccessHistogram(net::cookie_util::StorageAccessResult::
ACCESS_ALLOWED_STORAGE_ACCESS_GRANT);
}
break;
}
}
} else {
FireStorageAccessHistogram(
net::cookie_util::StorageAccessResult::ACCESS_ALLOWED);
}
if (block) {
*cookie_setting = CONTENT_SETTING_BLOCK;
FireStorageAccessHistogram(
net::cookie_util::StorageAccessResult::ACCESS_BLOCKED);
}
}
bool CookieSettings::HasSessionOnlyOrigins() const {
for (const auto& entry : content_settings_) {
if (entry.GetContentSetting() == CONTENT_SETTING_SESSION_ONLY)
return true;
}
return false;
}
} // namespace network