Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(711)

Side by Side Diff: content/browser/browsing_data/clear_site_data_throttle.cc

Issue 2025683003: First experimental implementation of the Clear-Site-Data header (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Moved channel IDs under 'cookies' Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 "content/browser/browsing_data/clear_site_data_throttle.h"
6
7 #include "base/json/json_reader.h"
8 #include "base/json/json_string_value_serializer.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/values.h"
11 #include "content/browser/frame_host/navigation_handle_impl.h"
12 #include "content/public/browser/browser_context.h"
13 #include "content/public/browser/content_browser_client.h"
14 #include "content/public/browser/navigation_handle.h"
15 #include "content/public/browser/web_contents.h"
16 #include "content/public/common/content_client.h"
17 #include "content/public/common/origin_util.h"
18 #include "net/http/http_response_headers.h"
19 #include "url/gurl.h"
20 #include "url/origin.h"
21
22 namespace content {
23
24 namespace {
25
26 static const char* kClearSiteDataHeader = "Clear-Site-Data";
27
28 static const char* kTypesKey = "types";
29
30 // Pretty-printed log output.
31 static const char* kConsoleMessageFormat =
32 "Clear-Site-Data header on '%s': %s";
33 static const char* kClearingOneType = "Clearing %s.";
34 static const char* kClearingTwoTypes = "Clearing %s and %s.";
35 static const char* kClearingThreeTypes = "Clearing %s, %s, and %s.";
36
37 // Console logging. Adds a |text| message with |level| to |messages|.
38 void ConsoleLog(std::vector<ClearSiteDataThrottle::ConsoleMessage>* messages,
clamy 2016/07/18 14:47:49 @mkwst: Didn't you have a patch that enables this
msramek 2016/07/18 17:03:20 For the record, it was this one: https://coderevie
39 const std::string& text, ConsoleMessageLevel level) {
40 messages->push_back({text, level});
41 }
42
43 } // namespace
44
45 // static
46 std::unique_ptr<NavigationThrottle>
47 ClearSiteDataThrottle::CreateThrottleFor(NavigationHandle* handle) {
48 return std::unique_ptr<NavigationThrottle>(new ClearSiteDataThrottle(handle));
49 }
50
51 ClearSiteDataThrottle::~ClearSiteDataThrottle() {}
52
53 ClearSiteDataThrottle::ThrottleCheckResult
54 ClearSiteDataThrottle::WillStartRequest() {
55 current_url_ = navigation_handle()->GetURL();
56 return PROCEED;
57 }
58
59 ClearSiteDataThrottle::ThrottleCheckResult
60 ClearSiteDataThrottle::WillRedirectRequest() {
61 // We are processing a redirect from url1 to url2. GetResponseHeaders()
62 // contains headers from url1, but GetURL() is already equal to url2. Handle
63 // the headers before updating the URL, so that |current_url_| corresponds
64 // to the URL that sent the headers.
65 HandleHeader();
66 current_url_ = navigation_handle()->GetURL();
67
68 return PROCEED;
69 }
70
71 ClearSiteDataThrottle::ThrottleCheckResult
72 ClearSiteDataThrottle::WillProcessResponse() {
73 HandleHeader();
74
75 // Now that RenderFrameHost is ready, output the console messages.
76 for (const ConsoleMessage& message : messages_) {
77 navigation_handle()->GetRenderFrameHost()->AddMessageToConsole(
clamy 2016/07/18 14:47:49 This won't work when the navigation is transferred
msramek 2016/07/18 17:03:20 My original solution was actually using WebContent
clamy 2016/07/19 13:27:54 WebContentsObserver::DidFinishNavigation will give
msramek 2016/07/19 16:44:33 Ok, then I guess it's better if we don't wait for
78 message.level,
79 base::StringPrintf(
80 kConsoleMessageFormat, navigation_handle()->GetURL().spec().c_str(),
81 message.text.c_str()));
82 }
83
84 return PROCEED;
85 }
86
87 ClearSiteDataThrottle::ClearSiteDataThrottle(NavigationHandle* handle)
88 : NavigationThrottle(handle) {}
89
90 void ClearSiteDataThrottle::HandleHeader() {
91 NavigationHandleImpl* handle =
92 static_cast<NavigationHandleImpl*>(navigation_handle());
93
94 // Ignore file URL navigations, as those have no response headers.
95 if (current_url_.SchemeIsFile())
96 return;
97
98 // Only accept the header on secure origins.
99 if (!IsOriginSecure(current_url_)) {
100 ConsoleLog(&messages_,
101 "Not supported for insecure origins.",
102 CONSOLE_MESSAGE_LEVEL_ERROR);
103 return;
104 }
105
106 // Extract the instances of the header and parse them.
107 size_t iter = 0;
108 std::string header_name;
109 std::string header_value;
110 while (handle->GetResponseHeaders()->EnumerateHeaderLines(
111 &iter, &header_name, &header_value)) {
112 if (header_name != kClearSiteDataHeader)
113 continue;
114
115 bool clear_cookies;
116 bool clear_storage;
117 bool clear_cache;
118
119 if (!ParseHeader(header_value, &clear_cookies, &clear_storage, &clear_cache,
120 &messages_)) {
121 continue;
122 }
123
124 // If the header is valid, clear the data for this browser context
125 // and origin.
126 BrowserContext* browser_context =
127 handle->GetWebContents()->GetBrowserContext();
128 url::Origin origin(current_url_);
129
130 GetContentClient()->browser()->ClearSiteData(
131 browser_context, origin, clear_cookies, clear_storage, clear_cache);
132 }
133 }
134
135 bool ClearSiteDataThrottle::ParseHeader(
136 const std::string& header,
137 bool* clear_cookies, bool* clear_storage, bool* clear_cache,
138 std::vector<ConsoleMessage>* messages) {
139 std::unique_ptr<base::Value> parsed_header =
140 base::JSONReader::Read(header);
141
142 if (!parsed_header) {
143 ConsoleLog(messages,
144 base::StringPrintf("%s is not a valid JSON.", header.c_str()),
145 CONSOLE_MESSAGE_LEVEL_ERROR);
146 return false;
147 }
148
149 const base::ListValue* types = nullptr;
150 if (!parsed_header->GetAsDictionary(nullptr) ||
151 !static_cast<base::DictionaryValue*>(parsed_header.get())
152 ->GetListWithoutPathExpansion(kTypesKey, &types)) {
153 ConsoleLog(messages,
154 base::StringPrintf(
155 "%s is not a JSON dictionary with a 'types' field.",
156 header.c_str()),
157 CONSOLE_MESSAGE_LEVEL_ERROR);
158 return false;
159 }
160
161 DCHECK(types);
162
163 *clear_cookies = false;
164 *clear_storage = false;
165 *clear_cache = false;
166
167 std::vector<std::string> type_names;
168 for (const std::unique_ptr<base::Value>& value : *types) {
169 std::string type;
170 value->GetAsString(&type);
171
172 bool* datatype = nullptr;
173
174 if (type == "cookies") {
175 datatype = clear_cookies;
176 } else if (type == "storage") {
177 datatype = clear_storage;
178 } else if (type == "cache") {
179 datatype = clear_cache;
180 } else {
181 std::string serialized_type;
182 JSONStringValueSerializer serializer(&serialized_type);
183 serializer.Serialize(*value);
184 ConsoleLog(messages,
185 base::StringPrintf("Invalid type: %s.",
186 serialized_type.c_str()),
187 CONSOLE_MESSAGE_LEVEL_ERROR);
188 continue;
189 }
190
191 // Each data type should only be processed once.
192 DCHECK(datatype);
193 if (*datatype)
194 continue;
195
196 *datatype = true;
197 type_names.push_back(type);
198 }
199
200 if (!*clear_cookies && !*clear_storage && !*clear_cache) {
201 ConsoleLog(messages,
202 base::StringPrintf(
203 "No valid types specified in %s.", header.c_str()),
204 CONSOLE_MESSAGE_LEVEL_ERROR);
205 return false;
206 }
207
208 // Pretty-print which types are to be cleared.
209 std::string output;
210 switch (type_names.size()) {
211 case 1:
212 output = base::StringPrintf(kClearingOneType, type_names[0].c_str());
213 break;
214 case 2:
215 output = base::StringPrintf(
216 kClearingTwoTypes, type_names[0].c_str(), type_names[1].c_str());
217 break;
218 case 3:
219 output = base::StringPrintf(
220 kClearingThreeTypes,
221 type_names[0].c_str(), type_names[1].c_str(), type_names[2].c_str());
222 break;
223 default:
224 NOTREACHED();
225 }
226 ConsoleLog(messages, output, CONSOLE_MESSAGE_LEVEL_LOG);
227
228 return true;
229 }
230
231 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698