blob: fa5ec250758b8d40029e3ed8ffdcf2c09dc6119c [file] [log] [blame]
Maks Orlovich710d5e32019-07-09 20:16:451// Copyright 2019 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/extensions/chrome_extension_cookies.h"
6
7#include "base/task/post_task.h"
8#include "base/threading/sequenced_task_runner_handle.h"
9#include "chrome/browser/content_settings/cookie_settings_factory.h"
10#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
11#include "chrome/browser/extensions/chrome_extension_cookies_factory.h"
12#include "chrome/browser/net/profile_network_context_service.h"
13#include "chrome/browser/profiles/profile.h"
14#include "chrome/common/chrome_constants.h"
15#include "components/cookie_config/cookie_store_util.h"
16#include "content/public/browser/browser_task_traits.h"
17#include "content/public/browser/browser_thread.h"
18#include "content/public/browser/cookie_store_factory.h"
19#include "extensions/common/constants.h"
20#include "services/network/cookie_manager.h"
21#include "services/network/restricted_cookie_manager.h"
22
23namespace extensions {
24
25ChromeExtensionCookies::ChromeExtensionCookies(Profile* profile)
26 : profile_(profile), cookie_settings_observer_(this) {
27 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
28 cookie_settings_ = CookieSettingsFactory::GetForProfile(profile);
29 cookie_settings_observer_.Add(cookie_settings_.get());
30 HostContentSettingsMapFactory::GetForProfile(profile_)->AddObserver(this);
31
32 std::unique_ptr<content::CookieStoreConfig> creation_config;
33 if (profile_->IsIncognitoProfile() || profile_->AsTestingProfile()) {
34 creation_config = std::make_unique<content::CookieStoreConfig>();
35 } else {
36 creation_config = std::make_unique<content::CookieStoreConfig>(
37 profile_->GetPath().Append(chrome::kExtensionsCookieFilename),
38 profile_->ShouldRestoreOldSessionCookies(),
39 profile_->ShouldPersistSessionCookies(), nullptr /* storage_policy */);
40 creation_config->crypto_delegate = cookie_config::GetCookieCryptoDelegate();
41 }
42 creation_config->cookieable_schemes.push_back(extensions::kExtensionScheme);
43
44 network::mojom::CookieManagerParamsPtr initial_settings =
45 ProfileNetworkContextService::CreateCookieManagerParams(
46 profile_, *cookie_settings_);
47
48 io_data_ = std::make_unique<IOData>(std::move(creation_config),
49 std::move(initial_settings));
50}
51
52ChromeExtensionCookies::~ChromeExtensionCookies() {
53 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
54 DCHECK(!io_data_);
55}
56
57// static
58ChromeExtensionCookies* ChromeExtensionCookies::Get(
59 content::BrowserContext* context) {
60 return ChromeExtensionCookiesFactory::GetForBrowserContext(context);
61}
62
63void ChromeExtensionCookies::CreateRestrictedCookieManager(
64 const url::Origin& origin,
65 network::mojom::RestrictedCookieManagerRequest request) {
66 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
67 if (!io_data_)
68 return;
69
70 // Safe since |io_data_| is non-null so no IOData deletion is queued.
Sami Kyostila5db196cf2019-08-01 17:46:1271 base::PostTask(FROM_HERE, {content::BrowserThread::IO},
72 base::BindOnce(&IOData::CreateRestrictedCookieManager,
73 base::Unretained(io_data_.get()), origin,
74 std::move(request)));
Maks Orlovich710d5e32019-07-09 20:16:4575}
76
77void ChromeExtensionCookies::ClearCookies(const GURL& origin) {
78 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
79 if (!io_data_) // null after shutdown.
80 return;
81
82 // Safe since |io_data_| is non-null so no IOData deletion is queued.
Sami Kyostila5db196cf2019-08-01 17:46:1283 base::PostTask(FROM_HERE, {content::BrowserThread::IO},
84 base::BindOnce(&IOData::ClearCookies,
85 base::Unretained(io_data_.get()), origin));
Maks Orlovich710d5e32019-07-09 20:16:4586}
87
88net::CookieStore* ChromeExtensionCookies::GetCookieStoreForTesting() {
89 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
90 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
91
92 if (!io_data_) // null after shutdown.
93 return nullptr;
94
95 return io_data_->GetOrCreateCookieStore();
96}
97
98ChromeExtensionCookies::IOData::IOData(
99 std::unique_ptr<content::CookieStoreConfig> creation_config,
100 network::mojom::CookieManagerParamsPtr initial_mojo_cookie_settings)
101 : creation_config_(std::move(creation_config)),
102 mojo_cookie_settings_(std::move(initial_mojo_cookie_settings)) {
103 UpdateNetworkCookieSettings();
104}
105
106ChromeExtensionCookies::IOData::~IOData() {
107 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
108}
109
110void ChromeExtensionCookies::IOData::CreateRestrictedCookieManager(
111 const url::Origin& origin,
112 network::mojom::RestrictedCookieManagerRequest request) {
113 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
114
115 restricted_cookie_managers_.AddBinding(
116 std::make_unique<network::RestrictedCookieManager>(
Maks Orloviche7db7a22019-07-25 01:47:46117 network::mojom::RestrictedCookieManagerRole::SCRIPT,
Maks Orlovich710d5e32019-07-09 20:16:45118 GetOrCreateCookieStore(), &network_cookie_settings_, origin,
119 /* null network_context_client disables logging, making later
120 arguments irrelevant */
121 nullptr, false, -1, -1),
122 std::move(request));
123}
124
125void ChromeExtensionCookies::IOData::ClearCookies(const GURL& origin) {
126 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
127
128 net::CookieDeletionInfo delete_info;
129 delete_info.host = origin.host();
130 GetOrCreateCookieStore()->DeleteAllMatchingInfoAsync(
131 std::move(delete_info), net::CookieStore::DeleteCallback());
132}
133
134void ChromeExtensionCookies::IOData::OnContentSettingChanged(
135 ContentSettingsForOneType settings) {
136 mojo_cookie_settings_->settings = std::move(settings);
137 UpdateNetworkCookieSettings();
138}
139
140void ChromeExtensionCookies::IOData::OnThirdPartyCookieBlockingChanged(
141 bool block_third_party_cookies) {
142 mojo_cookie_settings_->block_third_party_cookies = block_third_party_cookies;
143 UpdateNetworkCookieSettings();
144}
145
146net::CookieStore* ChromeExtensionCookies::IOData::GetOrCreateCookieStore() {
147 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
148 if (!cookie_store_) {
149 cookie_store_ =
150 content::CreateCookieStore(*creation_config_, nullptr /* netlog */);
151 }
152 return cookie_store_.get();
153}
154
155void ChromeExtensionCookies::IOData::UpdateNetworkCookieSettings() {
156 network::CookieManager::ConfigureCookieSettings(*mojo_cookie_settings_,
157 &network_cookie_settings_);
158}
159
160void ChromeExtensionCookies::OnContentSettingChanged(
161 const ContentSettingsPattern& primary_pattern,
162 const ContentSettingsPattern& secondary_pattern,
163 ContentSettingsType content_type,
164 const std::string& resource_identifier) {
165 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
166 if (!io_data_) // null after shutdown.
167 return;
168
169 if (content_type != CONTENT_SETTINGS_TYPE_COOKIES &&
170 content_type != CONTENT_SETTINGS_TYPE_DEFAULT) {
171 return;
172 }
173
174 ContentSettingsForOneType settings;
175 HostContentSettingsMapFactory::GetForProfile(profile_)->GetSettingsForOneType(
176 CONTENT_SETTINGS_TYPE_COOKIES, std::string(), &settings);
177
178 // Safe since |io_data_| is non-null so no IOData deletion is queued.
Sami Kyostila5db196cf2019-08-01 17:46:12179 base::PostTask(
Maks Orlovich710d5e32019-07-09 20:16:45180 FROM_HERE, {content::BrowserThread::IO},
181 base::BindOnce(&IOData::OnContentSettingChanged,
182 base::Unretained(io_data_.get()), std::move(settings)));
183}
184
185void ChromeExtensionCookies::OnThirdPartyCookieBlockingChanged(
186 bool block_third_party_cookies) {
187 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
188 if (!io_data_) // null after shutdown.
189 return;
190
191 // Safe since |io_data_| is non-null so no IOData deletion is queued.
Sami Kyostila5db196cf2019-08-01 17:46:12192 base::PostTask(FROM_HERE, {content::BrowserThread::IO},
193 base::BindOnce(&IOData::OnThirdPartyCookieBlockingChanged,
194 base::Unretained(io_data_.get()),
195 block_third_party_cookies));
Maks Orlovich710d5e32019-07-09 20:16:45196}
197
198void ChromeExtensionCookies::Shutdown() {
199 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
200 // Async delete on IO thread, sequencing it after any previously posted
201 // operations.
202 //
203 // Note: during tests this may be called with IO thread == UI thread. If this
204 // were to use unique_ptr<.., DeleteOnIOThread> that case would result in
205 // unwanted synchronous deletion; hence DeleteSoon is used by hand.
206 content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE,
207 std::move(io_data_));
208 profile_ = nullptr;
209}
210
211} // namespace extensions