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

Side by Side Diff: extensions/browser/api/web_request/web_request_api.cc

Issue 2455393002: PS - Adjusting webRequest API for use in Public Sessions (Closed)
Patch Set: Fixed unittest error Created 4 years, 1 month 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/browser/api/web_request/web_request_api.h" 5 #include "extensions/browser/api/web_request/web_request_api.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <memory> 10 #include <memory>
11 #include <utility> 11 #include <utility>
12 #include <vector> 12 #include <vector>
13 13
14 #include "base/bind.h" 14 #include "base/bind.h"
15 #include "base/bind_helpers.h" 15 #include "base/bind_helpers.h"
16 #include "base/json/json_writer.h" 16 #include "base/json/json_writer.h"
17 #include "base/lazy_instance.h" 17 #include "base/lazy_instance.h"
18 #include "base/macros.h" 18 #include "base/macros.h"
19 #include "base/metrics/histogram.h" 19 #include "base/metrics/histogram.h"
20 #include "base/strings/string_number_conversions.h" 20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/string_util.h" 21 #include "base/strings/string_util.h"
22 #include "base/strings/utf_string_conversions.h" 22 #include "base/strings/utf_string_conversions.h"
23 #include "base/time/time.h" 23 #include "base/time/time.h"
24 #include "base/values.h" 24 #include "base/values.h"
25 #include "chromeos/login/login_state.h"
25 #include "content/public/browser/browser_thread.h" 26 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/resource_request_info.h" 27 #include "content/public/browser/resource_request_info.h"
27 #include "content/public/browser/user_metrics.h" 28 #include "content/public/browser/user_metrics.h"
28 #include "content/public/common/browser_side_navigation_policy.h" 29 #include "content/public/common/browser_side_navigation_policy.h"
29 #include "content/public/common/child_process_host.h" 30 #include "content/public/common/child_process_host.h"
30 #include "extensions/browser/api/activity_log/web_request_constants.h" 31 #include "extensions/browser/api/activity_log/web_request_constants.h"
31 #include "extensions/browser/api/declarative/rules_registry_service.h" 32 #include "extensions/browser/api/declarative/rules_registry_service.h"
32 #include "extensions/browser/api/declarative_webrequest/request_stage.h" 33 #include "extensions/browser/api/declarative_webrequest/request_stage.h"
33 #include "extensions/browser/api/declarative_webrequest/webrequest_constants.h" 34 #include "extensions/browser/api/declarative_webrequest/webrequest_constants.h"
34 #include "extensions/browser/api/declarative_webrequest/webrequest_rules_registr y.h" 35 #include "extensions/browser/api/declarative_webrequest/webrequest_rules_registr y.h"
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 // We hide events from the system context as well as sensitive requests. 332 // We hide events from the system context as well as sensitive requests.
332 bool ShouldHideEvent(void* browser_context, 333 bool ShouldHideEvent(void* browser_context,
333 const InfoMap* extension_info_map, 334 const InfoMap* extension_info_map,
334 const net::URLRequest* request, 335 const net::URLRequest* request,
335 ExtensionNavigationUIData* navigation_ui_data) { 336 ExtensionNavigationUIData* navigation_ui_data) {
336 return (!browser_context || 337 return (!browser_context ||
337 WebRequestPermissions::HideRequest(extension_info_map, request, 338 WebRequestPermissions::HideRequest(extension_info_map, request,
338 navigation_ui_data)); 339 navigation_ui_data));
339 } 340 }
340 341
342 // Returns true if we're in a Public Session.
343 bool IsPublicSession() {
344 #if defined(OS_CHROMEOS)
345 if (chromeos::LoginState::IsInitialized()) {
346 return chromeos::LoginState::Get()->IsPublicSessionUser();
347 }
348 #endif
349 return false;
350 }
351
341 } // namespace 352 } // namespace
342 353
343 WebRequestAPI::WebRequestAPI(content::BrowserContext* context) 354 WebRequestAPI::WebRequestAPI(content::BrowserContext* context)
344 : browser_context_(context) { 355 : browser_context_(context) {
345 EventRouter* event_router = EventRouter::Get(browser_context_); 356 EventRouter* event_router = EventRouter::Get(browser_context_);
346 for (size_t i = 0; i < arraysize(kWebRequestEvents); ++i) { 357 for (size_t i = 0; i < arraysize(kWebRequestEvents); ++i) {
347 // Observe the webRequest event. 358 // Observe the webRequest event.
348 std::string event_name = kWebRequestEvents[i]; 359 std::string event_name = kWebRequestEvents[i];
349 event_router->RegisterObserver(this, event_name); 360 event_router->RegisterObserver(this, event_name);
350 361
(...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after
1110 std::string event_name = 1121 std::string event_name =
1111 EventRouter::GetBaseEventName((*listener_ids)[0].sub_event_name); 1122 EventRouter::GetBaseEventName((*listener_ids)[0].sub_event_name);
1112 DCHECK(IsWebRequestEvent(event_name)); 1123 DCHECK(IsWebRequestEvent(event_name));
1113 1124
1114 Listeners& event_listeners = listeners_[browser_context][event_name]; 1125 Listeners& event_listeners = listeners_[browser_context][event_name];
1115 void* cross_browser_context = GetCrossBrowserContext(browser_context); 1126 void* cross_browser_context = GetCrossBrowserContext(browser_context);
1116 Listeners* cross_event_listeners = 1127 Listeners* cross_event_listeners =
1117 cross_browser_context ? &listeners_[cross_browser_context][event_name] 1128 cross_browser_context ? &listeners_[cross_browser_context][event_name]
1118 : nullptr; 1129 : nullptr;
1119 1130
1131 // In Public Sessions we want to restrict access to security or privacy
1132 // sensitive data.
1133 if (IsPublicSession()) {
1134 event_details = event_details->WhitelistedCopyForPublicSession();
Devlin 2016/11/14 17:44:38 This sanitizes the input for *all* listeners, not
Ivan Šandrk 2016/11/14 20:16:13 Yes. I guess I could also use some help here. I c
Devlin 2016/11/15 01:19:37 If we're okay with sanitizing for all listeners, w
Ivan Šandrk 2016/11/15 13:49:57 Sure, done.
1135 }
1136
1120 for (const EventListener::ID& id : *listener_ids) { 1137 for (const EventListener::ID& id : *listener_ids) {
1121 // It's possible that the listener is no longer present. Check to make sure 1138 // It's possible that the listener is no longer present. Check to make sure
1122 // it's still there. 1139 // it's still there.
1123 const EventListener* listener = 1140 const EventListener* listener =
1124 FindEventListenerInContainer(id, event_listeners); 1141 FindEventListenerInContainer(id, event_listeners);
1125 if (!listener && cross_event_listeners) { 1142 if (!listener && cross_event_listeners) {
1126 listener = FindEventListenerInContainer(id, *cross_event_listeners); 1143 listener = FindEventListenerInContainer(id, *cross_event_listeners);
1127 } 1144 }
1128 if (!listener) 1145 if (!listener)
1129 continue; 1146 continue;
(...skipping 990 matching lines...) Expand 10 before | Expand all | Expand 10 after
2120 APIPermission::kWebRequestBlocking)) { 2137 APIPermission::kWebRequestBlocking)) {
2121 return RespondNow(Error(keys::kBlockingPermissionRequired)); 2138 return RespondNow(Error(keys::kBlockingPermissionRequired));
2122 } 2139 }
2123 2140
2124 // We allow to subscribe to patterns that are broader than the host 2141 // We allow to subscribe to patterns that are broader than the host
2125 // permissions. E.g., we could subscribe to http://www.example.com/* 2142 // permissions. E.g., we could subscribe to http://www.example.com/*
2126 // while having host permissions for http://www.example.com/foo/* and 2143 // while having host permissions for http://www.example.com/foo/* and
2127 // http://www.example.com/bar/*. 2144 // http://www.example.com/bar/*.
2128 // For this reason we do only a coarse check here to warn the extension 2145 // For this reason we do only a coarse check here to warn the extension
2129 // developer if they do something obviously wrong. 2146 // developer if they do something obviously wrong.
2130 if (extension->permissions_data() 2147 // When we are in a Public Session, allow all URL's for webRequests
Devlin 2016/11/14 17:44:38 s/URL's/URLs
Ivan Šandrk 2016/11/14 20:16:13 Done.
2148 // initiated by a regular extension.
2149 if (!(IsPublicSession() && extension->is_extension()) &&
2150 extension->permissions_data()
2131 ->GetEffectiveHostPermissions() 2151 ->GetEffectiveHostPermissions()
2132 .is_empty() && 2152 .is_empty() &&
2133 extension->permissions_data() 2153 extension->permissions_data()
2134 ->withheld_permissions() 2154 ->withheld_permissions()
2135 .explicit_hosts() 2155 .explicit_hosts()
2136 .is_empty()) { 2156 .is_empty()) {
2137 return RespondNow(Error(keys::kHostPermissionsRequired)); 2157 return RespondNow(Error(keys::kHostPermissionsRequired));
2138 } 2158 }
2139 } 2159 }
2140 2160
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2202 if (value->size() != 1) { 2222 if (value->size() != 1) {
2203 OnError(event_name, sub_event_name, request_id, std::move(response)); 2223 OnError(event_name, sub_event_name, request_id, std::move(response));
2204 return RespondNow(Error(keys::kInvalidBlockingResponse)); 2224 return RespondNow(Error(keys::kInvalidBlockingResponse));
2205 } 2225 }
2206 2226
2207 bool cancel = false; 2227 bool cancel = false;
2208 EXTENSION_FUNCTION_VALIDATE(value->GetBoolean("cancel", &cancel)); 2228 EXTENSION_FUNCTION_VALIDATE(value->GetBoolean("cancel", &cancel));
2209 response->cancel = cancel; 2229 response->cancel = cancel;
2210 } 2230 }
2211 2231
2212 if (value->HasKey("redirectUrl")) { 2232 // In Public Session we only want to allow "cancel".
2213 std::string new_url_str; 2233 if (!IsPublicSession()) {
Devlin 2016/11/14 17:44:38 Could we instead have this be an early-out error?
Ivan Šandrk 2016/11/14 20:16:13 Agreed completely and done. But now I broke the re
Devlin 2016/11/15 01:19:37 The basic approach here will be that you'll need t
Ivan Šandrk 2016/11/15 13:49:57 That's the first approach which I tried, but could
2214 EXTENSION_FUNCTION_VALIDATE(value->GetString("redirectUrl", 2234 if (value->HasKey("redirectUrl")) {
2215 &new_url_str)); 2235 std::string new_url_str;
2216 response->new_url = GURL(new_url_str); 2236 EXTENSION_FUNCTION_VALIDATE(value->GetString("redirectUrl",
2217 if (!response->new_url.is_valid()) { 2237 &new_url_str));
2218 OnError(event_name, sub_event_name, request_id, std::move(response)); 2238 response->new_url = GURL(new_url_str);
2219 return RespondNow(Error(keys::kInvalidRedirectUrl, new_url_str)); 2239 if (!response->new_url.is_valid()) {
2220 } 2240 OnError(event_name, sub_event_name, request_id, std::move(response));
2221 } 2241 return RespondNow(Error(keys::kInvalidRedirectUrl, new_url_str));
2222 2242 }
2223 const bool has_request_headers = value->HasKey("requestHeaders");
2224 const bool has_response_headers = value->HasKey("responseHeaders");
2225 if (has_request_headers || has_response_headers) {
2226 if (has_request_headers && has_response_headers) {
2227 // Allow only one of the keys, not both.
2228 OnError(event_name, sub_event_name, request_id, std::move(response));
2229 return RespondNow(Error(keys::kInvalidHeaderKeyCombination));
2230 } 2243 }
2231 2244
2232 base::ListValue* headers_value = NULL; 2245 const bool has_request_headers = value->HasKey("requestHeaders");
2233 std::unique_ptr<net::HttpRequestHeaders> request_headers; 2246 const bool has_response_headers = value->HasKey("responseHeaders");
2234 std::unique_ptr<helpers::ResponseHeaders> response_headers; 2247 if (has_request_headers || has_response_headers) {
2235 if (has_request_headers) { 2248 if (has_request_headers && has_response_headers) {
2236 request_headers.reset(new net::HttpRequestHeaders()); 2249 // Allow only one of the keys, not both.
2237 EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kRequestHeadersKey, 2250 OnError(event_name, sub_event_name, request_id, std::move(response));
2238 &headers_value)); 2251 return RespondNow(Error(keys::kInvalidHeaderKeyCombination));
2239 } else { 2252 }
2240 response_headers.reset(new helpers::ResponseHeaders()); 2253
2241 EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kResponseHeadersKey, 2254 base::ListValue* headers_value = NULL;
2242 &headers_value)); 2255 std::unique_ptr<net::HttpRequestHeaders> request_headers;
2256 std::unique_ptr<helpers::ResponseHeaders> response_headers;
2257 if (has_request_headers) {
2258 request_headers.reset(new net::HttpRequestHeaders());
2259 EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kRequestHeadersKey,
2260 &headers_value));
2261 } else {
2262 response_headers.reset(new helpers::ResponseHeaders());
2263 EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kResponseHeadersKey,
2264 &headers_value));
2265 }
2266
2267 for (size_t i = 0; i < headers_value->GetSize(); ++i) {
2268 base::DictionaryValue* header_value = NULL;
2269 std::string name;
2270 std::string value;
2271 EXTENSION_FUNCTION_VALIDATE(
2272 headers_value->GetDictionary(i, &header_value));
2273 if (!FromHeaderDictionary(header_value, &name, &value)) {
2274 std::string serialized_header;
2275 base::JSONWriter::Write(*header_value, &serialized_header);
2276 OnError(event_name, sub_event_name, request_id,
2277 std::move(response));
2278 return RespondNow(Error(keys::kInvalidHeader, serialized_header));
2279 }
2280 if (!net::HttpUtil::IsValidHeaderName(name)) {
2281 OnError(event_name, sub_event_name, request_id,
2282 std::move(response));
2283 return RespondNow(Error(keys::kInvalidHeaderName));
2284 }
2285 if (!net::HttpUtil::IsValidHeaderValue(value)) {
2286 OnError(event_name, sub_event_name, request_id,
2287 std::move(response));
2288 return RespondNow(Error(keys::kInvalidHeaderValue, name));
2289 }
2290 if (has_request_headers)
2291 request_headers->SetHeader(name, value);
2292 else
2293 response_headers->push_back(helpers::ResponseHeader(name, value));
2294 }
2295 if (has_request_headers)
2296 response->request_headers.reset(request_headers.release());
2297 else
2298 response->response_headers.reset(response_headers.release());
2243 } 2299 }
2244 2300
2245 for (size_t i = 0; i < headers_value->GetSize(); ++i) { 2301 if (value->HasKey(keys::kAuthCredentialsKey)) {
2246 base::DictionaryValue* header_value = NULL; 2302 base::DictionaryValue* credentials_value = NULL;
2247 std::string name; 2303 EXTENSION_FUNCTION_VALIDATE(value->GetDictionary(
2248 std::string value; 2304 keys::kAuthCredentialsKey,
2305 &credentials_value));
2306 base::string16 username;
2307 base::string16 password;
2249 EXTENSION_FUNCTION_VALIDATE( 2308 EXTENSION_FUNCTION_VALIDATE(
2250 headers_value->GetDictionary(i, &header_value)); 2309 credentials_value->GetString(keys::kUsernameKey, &username));
2251 if (!FromHeaderDictionary(header_value, &name, &value)) { 2310 EXTENSION_FUNCTION_VALIDATE(
2252 std::string serialized_header; 2311 credentials_value->GetString(keys::kPasswordKey, &password));
2253 base::JSONWriter::Write(*header_value, &serialized_header); 2312 response->auth_credentials.reset(
2254 OnError(event_name, sub_event_name, request_id, std::move(response)); 2313 new net::AuthCredentials(username, password));
2255 return RespondNow(Error(keys::kInvalidHeader, serialized_header));
2256 }
2257 if (!net::HttpUtil::IsValidHeaderName(name)) {
2258 OnError(event_name, sub_event_name, request_id, std::move(response));
2259 return RespondNow(Error(keys::kInvalidHeaderName));
2260 }
2261 if (!net::HttpUtil::IsValidHeaderValue(value)) {
2262 OnError(event_name, sub_event_name, request_id, std::move(response));
2263 return RespondNow(Error(keys::kInvalidHeaderValue, name));
2264 }
2265 if (has_request_headers)
2266 request_headers->SetHeader(name, value);
2267 else
2268 response_headers->push_back(helpers::ResponseHeader(name, value));
2269 } 2314 }
2270 if (has_request_headers)
2271 response->request_headers.reset(request_headers.release());
2272 else
2273 response->response_headers.reset(response_headers.release());
2274 }
2275
2276 if (value->HasKey(keys::kAuthCredentialsKey)) {
2277 base::DictionaryValue* credentials_value = NULL;
2278 EXTENSION_FUNCTION_VALIDATE(value->GetDictionary(
2279 keys::kAuthCredentialsKey,
2280 &credentials_value));
2281 base::string16 username;
2282 base::string16 password;
2283 EXTENSION_FUNCTION_VALIDATE(
2284 credentials_value->GetString(keys::kUsernameKey, &username));
2285 EXTENSION_FUNCTION_VALIDATE(
2286 credentials_value->GetString(keys::kPasswordKey, &password));
2287 response->auth_credentials.reset(
2288 new net::AuthCredentials(username, password));
2289 } 2315 }
2290 } 2316 }
2291 2317
2292 ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled( 2318 ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled(
2293 profile_id(), extension_id_safe(), event_name, sub_event_name, request_id, 2319 profile_id(), extension_id_safe(), event_name, sub_event_name, request_id,
2294 response.release()); 2320 response.release());
2295 2321
2296 return RespondNow(NoArguments()); 2322 return RespondNow(NoArguments());
2297 } 2323 }
2298 2324
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2360 // Since EventListeners are segmented by browser_context, check that 2386 // Since EventListeners are segmented by browser_context, check that
2361 // last, as it is exceedingly unlikely to be different. 2387 // last, as it is exceedingly unlikely to be different.
2362 return extension_id == that.extension_id && 2388 return extension_id == that.extension_id &&
2363 sub_event_name == that.sub_event_name && 2389 sub_event_name == that.sub_event_name &&
2364 web_view_instance_id == that.web_view_instance_id && 2390 web_view_instance_id == that.web_view_instance_id &&
2365 embedder_process_id == that.embedder_process_id && 2391 embedder_process_id == that.embedder_process_id &&
2366 browser_context == that.browser_context; 2392 browser_context == that.browser_context;
2367 } 2393 }
2368 2394
2369 } // namespace extensions 2395 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698