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
3 // found in the LICENSE file.
5 #include "chrome/browser/net/chrome_network_delegate.h"
11 #include "base/base_paths.h"
12 #include "base/debug/trace_event.h"
13 #include "base/logging.h"
14 #include "base/metrics/histogram.h"
15 #include "base/path_service.h"
16 #include "base/prefs/pref_member.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_split.h"
20 #include "base/time/time.h"
21 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/content_settings/cookie_settings.h"
23 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
24 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
25 #include "chrome/browser/extensions/api/proxy/proxy_api.h"
26 #include "chrome/browser/extensions/api/web_request/web_request_api.h"
27 #include "chrome/browser/extensions/event_router_forwarder.h"
28 #include "chrome/browser/google/google_util.h"
29 #include "chrome/browser/net/client_hints.h"
30 #include "chrome/browser/net/connect_interceptor.h"
31 #include "chrome/browser/net/spdyproxy/data_saving_metrics.h"
32 #include "chrome/browser/performance_monitor/performance_monitor.h"
33 #include "chrome/browser/profiles/profile_manager.h"
34 #include "chrome/browser/task_manager/task_manager.h"
35 #include "chrome/common/pref_names.h"
36 #include "chrome/common/url_constants.h"
37 #include "content/public/browser/browser_thread.h"
38 #include "content/public/browser/render_frame_host.h"
39 #include "content/public/browser/render_view_host.h"
40 #include "content/public/browser/resource_request_info.h"
41 #include "extensions/browser/extension_system.h"
42 #include "extensions/browser/info_map.h"
43 #include "extensions/browser/process_manager.h"
44 #include "extensions/common/constants.h"
45 #include "net/base/host_port_pair.h"
46 #include "net/base/net_errors.h"
47 #include "net/base/net_log.h"
48 #include "net/cookies/canonical_cookie.h"
49 #include "net/cookies/cookie_options.h"
50 #include "net/http/http_request_headers.h"
51 #include "net/http/http_response_headers.h"
52 #include "net/socket_stream/socket_stream.h"
53 #include "net/url_request/url_request.h"
55 #if defined(OS_CHROMEOS)
56 #include "base/command_line.h"
57 #include "base/sys_info.h"
58 #include "chrome/common/chrome_switches.h"
61 #if defined(ENABLE_CONFIGURATION_POLICY)
62 #include "components/policy/core/browser/url_blacklist_manager.h"
65 #if defined(OS_ANDROID)
66 #include "components/precache/content/precache_manager.h"
67 #include "components/precache/content/precache_manager_factory.h"
70 using content::BrowserThread
;
71 using content::RenderViewHost
;
72 using content::ResourceRequestInfo
;
74 // By default we don't allow access to all file:// urls on ChromeOS and
76 #if defined(OS_CHROMEOS) || defined(OS_ANDROID)
77 bool ChromeNetworkDelegate::g_allow_file_access_
= false;
79 bool ChromeNetworkDelegate::g_allow_file_access_
= true;
82 // This remains false unless the --disable-extensions-http-throttling
83 // flag is passed to the browser.
84 bool ChromeNetworkDelegate::g_never_throttle_requests_
= false;
88 const char kDNTHeader
[] = "DNT";
90 // If the |request| failed due to problems with a proxy, forward the error to
91 // the proxy extension API.
92 void ForwardProxyErrors(net::URLRequest
* request
,
93 extensions::EventRouterForwarder
* event_router
,
95 if (request
->status().status() == net::URLRequestStatus::FAILED
) {
96 switch (request
->status().error()) {
97 case net::ERR_PROXY_AUTH_UNSUPPORTED
:
98 case net::ERR_PROXY_CONNECTION_FAILED
:
99 case net::ERR_TUNNEL_CONNECTION_FAILED
:
100 extensions::ProxyEventRouter::GetInstance()->OnProxyError(
101 event_router
, profile
, request
->status().error());
106 // Returns whether a URL parameter, |first_parameter| (e.g. foo=bar), has the
107 // same key as the the |second_parameter| (e.g. foo=baz). Both parameters
108 // must be in key=value form.
109 bool HasSameParameterKey(const std::string
& first_parameter
,
110 const std::string
& second_parameter
) {
111 DCHECK(second_parameter
.find("=") != std::string::npos
);
112 // Prefix for "foo=bar" is "foo=".
113 std::string parameter_prefix
= second_parameter
.substr(
114 0, second_parameter
.find("=") + 1);
115 return StartsWithASCII(first_parameter
, parameter_prefix
, false);
118 // Examines the query string containing parameters and adds the necessary ones
119 // so that SafeSearch is active. |query| is the string to examine and the
120 // return value is the |query| string modified such that SafeSearch is active.
121 std::string
AddSafeSearchParameters(const std::string
& query
) {
122 std::vector
<std::string
> new_parameters
;
123 std::string safe_parameter
= chrome::kSafeSearchSafeParameter
;
124 std::string ssui_parameter
= chrome::kSafeSearchSsuiParameter
;
126 std::vector
<std::string
> parameters
;
127 base::SplitString(query
, '&', ¶meters
);
129 std::vector
<std::string
>::iterator it
;
130 for (it
= parameters
.begin(); it
< parameters
.end(); ++it
) {
131 if (!HasSameParameterKey(*it
, safe_parameter
) &&
132 !HasSameParameterKey(*it
, ssui_parameter
)) {
133 new_parameters
.push_back(*it
);
137 new_parameters
.push_back(safe_parameter
);
138 new_parameters
.push_back(ssui_parameter
);
139 return JoinString(new_parameters
, '&');
142 // If |request| is a request to Google Web Search the function
143 // enforces that the SafeSearch query parameters are set to active.
144 // Sets the query part of |new_url| with the new value of the parameters.
145 void ForceGoogleSafeSearch(net::URLRequest
* request
,
147 if (!google_util::IsGoogleSearchUrl(request
->url()) &&
148 !google_util::IsGoogleHomePageUrl(request
->url()))
151 std::string query
= request
->url().query();
152 std::string new_query
= AddSafeSearchParameters(query
);
153 if (query
== new_query
)
156 GURL::Replacements replacements
;
157 replacements
.SetQueryStr(new_query
);
158 *new_url
= request
->url().ReplaceComponents(replacements
);
161 // Gets called when the extensions finish work on the URL. If the extensions
162 // did not do a redirect (so |new_url| is empty) then we enforce the
163 // SafeSearch parameters. Otherwise we will get called again after the
164 // redirect and we enforce SafeSearch then.
165 void ForceGoogleSafeSearchCallbackWrapper(
166 const net::CompletionCallback
& callback
,
167 net::URLRequest
* request
,
170 if (rv
== net::OK
&& new_url
->is_empty())
171 ForceGoogleSafeSearch(request
, new_url
);
175 enum RequestStatus
{ REQUEST_STARTED
, REQUEST_DONE
};
177 // Notifies the extensions::ProcessManager that a request has started or stopped
178 // for a particular RenderFrame.
179 void NotifyEPMRequestStatus(RequestStatus status
,
182 int render_frame_id
) {
183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
184 Profile
* profile
= reinterpret_cast<Profile
*>(profile_id
);
185 if (!g_browser_process
->profile_manager()->IsValidProfile(profile
))
188 extensions::ProcessManager
* process_manager
=
189 extensions::ExtensionSystem::Get(profile
)->process_manager();
190 // This may be NULL in unit tests.
191 if (!process_manager
)
194 // Will be NULL if the request was not issued on behalf of a renderer (e.g. a
195 // system-level request).
196 content::RenderFrameHost
* render_frame_host
=
197 content::RenderFrameHost::FromID(process_id
, render_frame_id
);
198 if (render_frame_host
) {
199 if (status
== REQUEST_STARTED
) {
200 process_manager
->OnNetworkRequestStarted(render_frame_host
);
201 } else if (status
== REQUEST_DONE
) {
202 process_manager
->OnNetworkRequestDone(render_frame_host
);
209 void ForwardRequestStatus(
210 RequestStatus status
, net::URLRequest
* request
, void* profile_id
) {
211 const ResourceRequestInfo
* info
= ResourceRequestInfo::ForRequest(request
);
215 int process_id
, render_frame_id
;
216 if (info
->GetAssociatedRenderFrame(&process_id
, &render_frame_id
)) {
217 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
218 base::Bind(&NotifyEPMRequestStatus
,
219 status
, profile_id
, process_id
, render_frame_id
));
223 void UpdateContentLengthPrefs(
224 int received_content_length
,
225 int original_content_length
,
226 spdyproxy::DataReductionRequestType data_reduction_type
,
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
229 DCHECK_GE(received_content_length
, 0);
230 DCHECK_GE(original_content_length
, 0);
232 // Can be NULL in a unit test.
233 if (!g_browser_process
)
236 PrefService
* prefs
= g_browser_process
->local_state();
240 // Ignore off-the-record data.
241 if (!g_browser_process
->profile_manager()->IsValidProfile(profile
) ||
242 profile
->IsOffTheRecord()) {
245 #if defined(OS_ANDROID)
246 // If Android ever goes multi profile, the profile should be passed so that
247 // the browser preference will be taken.
248 bool with_data_reduction_proxy_enabled
=
249 ProfileManager::GetActiveUserProfile()->GetPrefs()->GetBoolean(
250 prefs::kSpdyProxyAuthEnabled
);
252 bool with_data_reduction_proxy_enabled
= false;
255 spdyproxy::UpdateContentLengthPrefs(received_content_length
,
256 original_content_length
,
257 with_data_reduction_proxy_enabled
,
258 data_reduction_type
, prefs
);
261 void StoreAccumulatedContentLength(
262 int received_content_length
,
263 int original_content_length
,
264 spdyproxy::DataReductionRequestType data_reduction_type
,
266 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
267 base::Bind(&UpdateContentLengthPrefs
,
268 received_content_length
, original_content_length
,
269 data_reduction_type
, profile
));
272 void RecordContentLengthHistograms(
273 int64 received_content_length
,
274 int64 original_content_length
,
275 const base::TimeDelta
& freshness_lifetime
) {
276 #if defined(OS_ANDROID)
277 // Add the current resource to these histograms only when a valid
278 // X-Original-Content-Length header is present.
279 if (original_content_length
>= 0) {
280 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthWithValidOCL",
281 received_content_length
);
282 UMA_HISTOGRAM_COUNTS("Net.HttpOriginalContentLengthWithValidOCL",
283 original_content_length
);
284 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthDifferenceWithValidOCL",
285 original_content_length
- received_content_length
);
287 // Presume the original content length is the same as the received content
288 // length if the X-Original-Content-Header is not present.
289 original_content_length
= received_content_length
;
291 UMA_HISTOGRAM_COUNTS("Net.HttpContentLength", received_content_length
);
292 UMA_HISTOGRAM_COUNTS("Net.HttpOriginalContentLength",
293 original_content_length
);
294 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthDifference",
295 original_content_length
- received_content_length
);
296 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpContentFreshnessLifetime",
297 freshness_lifetime
.InSeconds(),
298 base::TimeDelta::FromHours(1).InSeconds(),
299 base::TimeDelta::FromDays(30).InSeconds(),
301 if (freshness_lifetime
.InSeconds() <= 0)
303 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable",
304 received_content_length
);
305 if (freshness_lifetime
.InHours() < 4)
307 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable4Hours",
308 received_content_length
);
310 if (freshness_lifetime
.InHours() < 24)
312 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable24Hours",
313 received_content_length
);
314 #endif // defined(OS_ANDROID)
317 #if defined(OS_ANDROID)
318 void RecordPrecacheStatsOnUIThread(const GURL
& url
,
319 const base::Time
& fetch_time
, int64 size
,
320 bool was_cached
, void* profile_id
) {
321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
323 Profile
* profile
= reinterpret_cast<Profile
*>(profile_id
);
324 if (!g_browser_process
->profile_manager()->IsValidProfile(profile
)) {
328 precache::PrecacheManager
* precache_manager
=
329 precache::PrecacheManagerFactory::GetForBrowserContext(profile
);
330 if (!precache_manager
) {
331 // This could be NULL if the profile is off the record.
335 precache_manager
->RecordStatsForFetch(url
, fetch_time
, size
, was_cached
);
337 #endif // defined(OS_ANDROID)
341 ChromeNetworkDelegate::ChromeNetworkDelegate(
342 extensions::EventRouterForwarder
* event_router
,
343 BooleanPrefMember
* enable_referrers
)
344 : event_router_(event_router
),
346 enable_referrers_(enable_referrers
),
347 enable_do_not_track_(NULL
),
348 force_google_safe_search_(NULL
),
349 url_blacklist_manager_(NULL
),
350 received_content_length_(0),
351 original_content_length_(0) {
352 DCHECK(event_router
);
353 DCHECK(enable_referrers
);
356 ChromeNetworkDelegate::~ChromeNetworkDelegate() {}
358 void ChromeNetworkDelegate::set_extension_info_map(
359 extensions::InfoMap
* extension_info_map
) {
360 extension_info_map_
= extension_info_map
;
363 void ChromeNetworkDelegate::set_cookie_settings(
364 CookieSettings
* cookie_settings
) {
365 cookie_settings_
= cookie_settings
;
368 void ChromeNetworkDelegate::set_predictor(
369 chrome_browser_net::Predictor
* predictor
) {
370 connect_interceptor_
.reset(
371 new chrome_browser_net::ConnectInterceptor(predictor
));
374 void ChromeNetworkDelegate::SetEnableClientHints() {
375 client_hints_
.reset(new ClientHints());
376 client_hints_
->Init();
380 void ChromeNetworkDelegate::NeverThrottleRequests() {
381 g_never_throttle_requests_
= true;
385 void ChromeNetworkDelegate::InitializePrefsOnUIThread(
386 BooleanPrefMember
* enable_referrers
,
387 BooleanPrefMember
* enable_do_not_track
,
388 BooleanPrefMember
* force_google_safe_search
,
389 PrefService
* pref_service
) {
390 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
391 enable_referrers
->Init(prefs::kEnableReferrers
, pref_service
);
392 enable_referrers
->MoveToThread(
393 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO
));
394 if (enable_do_not_track
) {
395 enable_do_not_track
->Init(prefs::kEnableDoNotTrack
, pref_service
);
396 enable_do_not_track
->MoveToThread(
397 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO
));
399 if (force_google_safe_search
) {
400 force_google_safe_search
->Init(prefs::kForceSafeSearch
, pref_service
);
401 force_google_safe_search
->MoveToThread(
402 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO
));
407 void ChromeNetworkDelegate::AllowAccessToAllFiles() {
408 g_allow_file_access_
= true;
412 base::Value
* ChromeNetworkDelegate::HistoricNetworkStatsInfoToValue() {
413 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
414 PrefService
* prefs
= g_browser_process
->local_state();
415 int64 total_received
= prefs
->GetInt64(prefs::kHttpReceivedContentLength
);
416 int64 total_original
= prefs
->GetInt64(prefs::kHttpOriginalContentLength
);
418 base::DictionaryValue
* dict
= new base::DictionaryValue();
419 // Use strings to avoid overflow. base::Value only supports 32-bit integers.
420 dict
->SetString("historic_received_content_length",
421 base::Int64ToString(total_received
));
422 dict
->SetString("historic_original_content_length",
423 base::Int64ToString(total_original
));
427 base::Value
* ChromeNetworkDelegate::SessionNetworkStatsInfoToValue() const {
428 base::DictionaryValue
* dict
= new base::DictionaryValue();
429 // Use strings to avoid overflow. base::Value only supports 32-bit integers.
430 dict
->SetString("session_received_content_length",
431 base::Int64ToString(received_content_length_
));
432 dict
->SetString("session_original_content_length",
433 base::Int64ToString(original_content_length_
));
437 int ChromeNetworkDelegate::OnBeforeURLRequest(
438 net::URLRequest
* request
,
439 const net::CompletionCallback
& callback
,
441 #if defined(ENABLE_CONFIGURATION_POLICY)
442 // TODO(joaodasilva): This prevents extensions from seeing URLs that are
443 // blocked. However, an extension might redirect the request to another URL,
444 // which is not blocked.
445 if (url_blacklist_manager_
&&
446 url_blacklist_manager_
->IsRequestBlocked(*request
)) {
447 // URL access blocked by policy.
448 request
->net_log().AddEvent(
449 net::NetLog::TYPE_CHROME_POLICY_ABORTED_REQUEST
,
450 net::NetLog::StringCallback("url",
451 &request
->url().possibly_invalid_spec()));
452 return net::ERR_BLOCKED_BY_ADMINISTRATOR
;
456 ForwardRequestStatus(REQUEST_STARTED
, request
, profile_
);
458 if (!enable_referrers_
->GetValue())
459 request
->SetReferrer(std::string());
460 if (enable_do_not_track_
&& enable_do_not_track_
->GetValue())
461 request
->SetExtraRequestHeaderByName(kDNTHeader
, "1", true /* override */);
464 request
->SetExtraRequestHeaderByName(
465 ClientHints::kDevicePixelRatioHeader
,
466 client_hints_
->GetDevicePixelRatioHeader(), true);
469 bool force_safe_search
= force_google_safe_search_
&&
470 force_google_safe_search_
->GetValue();
472 net::CompletionCallback wrapped_callback
= callback
;
473 if (force_safe_search
) {
474 wrapped_callback
= base::Bind(&ForceGoogleSafeSearchCallbackWrapper
,
476 base::Unretained(request
),
477 base::Unretained(new_url
));
480 int rv
= ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRequest(
481 profile_
, extension_info_map_
.get(), request
, wrapped_callback
,
484 if (force_safe_search
&& rv
== net::OK
&& new_url
->is_empty())
485 ForceGoogleSafeSearch(request
, new_url
);
487 if (connect_interceptor_
)
488 connect_interceptor_
->WitnessURLRequest(request
);
493 int ChromeNetworkDelegate::OnBeforeSendHeaders(
494 net::URLRequest
* request
,
495 const net::CompletionCallback
& callback
,
496 net::HttpRequestHeaders
* headers
) {
497 TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request
, "SendRequest");
498 return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeSendHeaders(
499 profile_
, extension_info_map_
.get(), request
, callback
, headers
);
502 void ChromeNetworkDelegate::OnSendHeaders(
503 net::URLRequest
* request
,
504 const net::HttpRequestHeaders
& headers
) {
505 ExtensionWebRequestEventRouter::GetInstance()->OnSendHeaders(
506 profile_
, extension_info_map_
.get(), request
, headers
);
509 int ChromeNetworkDelegate::OnHeadersReceived(
510 net::URLRequest
* request
,
511 const net::CompletionCallback
& callback
,
512 const net::HttpResponseHeaders
* original_response_headers
,
513 scoped_refptr
<net::HttpResponseHeaders
>* override_response_headers
) {
514 return ExtensionWebRequestEventRouter::GetInstance()->OnHeadersReceived(
515 profile_
, extension_info_map_
.get(), request
, callback
,
516 original_response_headers
, override_response_headers
);
519 void ChromeNetworkDelegate::OnBeforeRedirect(net::URLRequest
* request
,
520 const GURL
& new_location
) {
521 ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRedirect(
522 profile_
, extension_info_map_
.get(), request
, new_location
);
526 void ChromeNetworkDelegate::OnResponseStarted(net::URLRequest
* request
) {
527 TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request
, "ResponseStarted");
528 ExtensionWebRequestEventRouter::GetInstance()->OnResponseStarted(
529 profile_
, extension_info_map_
.get(), request
);
530 ForwardProxyErrors(request
, event_router_
.get(), profile_
);
533 void ChromeNetworkDelegate::OnRawBytesRead(const net::URLRequest
& request
,
535 TRACE_EVENT_ASYNC_STEP_PAST1("net", "URLRequest", &request
, "DidRead",
536 "bytes_read", bytes_read
);
537 performance_monitor::PerformanceMonitor::GetInstance()->BytesReadOnIOThread(
538 request
, bytes_read
);
540 #if defined(ENABLE_TASK_MANAGER)
541 // This is not completely accurate, but as a first approximation ignore
542 // requests that are served from the cache. See bug 330931 for more info.
543 if (!request
.was_cached())
544 TaskManager::GetInstance()->model()->NotifyBytesRead(request
, bytes_read
);
545 #endif // defined(ENABLE_TASK_MANAGER)
548 void ChromeNetworkDelegate::OnCompleted(net::URLRequest
* request
,
550 TRACE_EVENT_ASYNC_END0("net", "URLRequest", request
);
551 if (request
->status().status() == net::URLRequestStatus::SUCCESS
) {
552 // For better accuracy, we use the actual bytes read instead of the length
553 // specified with the Content-Length header, which may be inaccurate,
554 // or missing, as is the case with chunked encoding.
555 int64 received_content_length
= request
->received_response_content_length();
557 #if defined(OS_ANDROID)
558 if (precache::PrecacheManager::IsPrecachingEnabled()) {
559 // Record precache metrics when a fetch is completed successfully, if
560 // precaching is enabled.
561 BrowserThread::PostTask(
562 BrowserThread::UI
, FROM_HERE
,
563 base::Bind(&RecordPrecacheStatsOnUIThread
, request
->url(),
564 base::Time::Now(), received_content_length
,
565 request
->was_cached(), profile_
));
567 #endif // defined(OS_ANDROID)
569 // Only record for http or https urls.
570 bool is_http
= request
->url().SchemeIs("http");
571 bool is_https
= request
->url().SchemeIs("https");
573 if (!request
->was_cached() && // Don't record cached content
574 received_content_length
&& // Zero-byte responses aren't useful.
575 (is_http
|| is_https
)) { // Only record for HTTP or HTTPS urls.
576 int64 original_content_length
=
577 request
->response_info().headers
->GetInt64HeaderValue(
578 "x-original-content-length");
579 spdyproxy::DataReductionRequestType data_reduction_type
=
580 spdyproxy::GetDataReductionRequestType(request
);
582 base::TimeDelta freshness_lifetime
=
583 request
->response_info().headers
->GetFreshnessLifetime(
584 request
->response_info().response_time
);
585 int64 adjusted_original_content_length
=
586 spdyproxy::GetAdjustedOriginalContentLength(
587 data_reduction_type
, original_content_length
,
588 received_content_length
);
589 AccumulateContentLength(received_content_length
,
590 adjusted_original_content_length
,
591 data_reduction_type
);
592 RecordContentLengthHistograms(received_content_length
,
593 original_content_length
,
595 DVLOG(2) << __FUNCTION__
596 << " received content length: " << received_content_length
597 << " original content length: " << original_content_length
598 << " url: " << request
->url();
601 bool is_redirect
= request
->response_headers() &&
602 net::HttpResponseHeaders::IsRedirectResponseCode(
603 request
->response_headers()->response_code());
605 ExtensionWebRequestEventRouter::GetInstance()->OnCompleted(
606 profile_
, extension_info_map_
.get(), request
);
608 } else if (request
->status().status() == net::URLRequestStatus::FAILED
||
609 request
->status().status() == net::URLRequestStatus::CANCELED
) {
610 ExtensionWebRequestEventRouter::GetInstance()->OnErrorOccurred(
611 profile_
, extension_info_map_
.get(), request
, started
);
615 ForwardProxyErrors(request
, event_router_
.get(), profile_
);
617 ForwardRequestStatus(REQUEST_DONE
, request
, profile_
);
620 void ChromeNetworkDelegate::OnURLRequestDestroyed(net::URLRequest
* request
) {
621 ExtensionWebRequestEventRouter::GetInstance()->OnURLRequestDestroyed(
625 void ChromeNetworkDelegate::OnPACScriptError(int line_number
,
626 const base::string16
& error
) {
627 extensions::ProxyEventRouter::GetInstance()->OnPACScriptError(
628 event_router_
.get(), profile_
, line_number
, error
);
631 net::NetworkDelegate::AuthRequiredResponse
632 ChromeNetworkDelegate::OnAuthRequired(
633 net::URLRequest
* request
,
634 const net::AuthChallengeInfo
& auth_info
,
635 const AuthCallback
& callback
,
636 net::AuthCredentials
* credentials
) {
637 return ExtensionWebRequestEventRouter::GetInstance()->OnAuthRequired(
638 profile_
, extension_info_map_
.get(), request
, auth_info
,
639 callback
, credentials
);
642 bool ChromeNetworkDelegate::OnCanGetCookies(
643 const net::URLRequest
& request
,
644 const net::CookieList
& cookie_list
) {
645 // NULL during tests, or when we're running in the system context.
646 if (!cookie_settings_
.get())
649 bool allow
= cookie_settings_
->IsReadingCookieAllowed(
650 request
.url(), request
.first_party_for_cookies());
652 int render_process_id
= -1;
653 int render_frame_id
= -1;
654 if (content::ResourceRequestInfo::GetRenderFrameForRequest(
655 &request
, &render_process_id
, &render_frame_id
)) {
656 BrowserThread::PostTask(
657 BrowserThread::UI
, FROM_HERE
,
658 base::Bind(&TabSpecificContentSettings::CookiesRead
,
659 render_process_id
, render_frame_id
,
660 request
.url(), request
.first_party_for_cookies(),
661 cookie_list
, !allow
));
667 bool ChromeNetworkDelegate::OnCanSetCookie(const net::URLRequest
& request
,
668 const std::string
& cookie_line
,
669 net::CookieOptions
* options
) {
670 // NULL during tests, or when we're running in the system context.
671 if (!cookie_settings_
.get())
674 bool allow
= cookie_settings_
->IsSettingCookieAllowed(
675 request
.url(), request
.first_party_for_cookies());
677 int render_process_id
= -1;
678 int render_frame_id
= -1;
679 if (content::ResourceRequestInfo::GetRenderFrameForRequest(
680 &request
, &render_process_id
, &render_frame_id
)) {
681 BrowserThread::PostTask(
682 BrowserThread::UI
, FROM_HERE
,
683 base::Bind(&TabSpecificContentSettings::CookieChanged
,
684 render_process_id
, render_frame_id
,
685 request
.url(), request
.first_party_for_cookies(),
686 cookie_line
, *options
, !allow
));
692 bool ChromeNetworkDelegate::OnCanAccessFile(const net::URLRequest
& request
,
693 const base::FilePath
& path
) const {
694 if (g_allow_file_access_
)
697 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
700 #if defined(OS_CHROMEOS)
701 // If we're running Chrome for ChromeOS on Linux, we want to allow file
703 if (!base::SysInfo::IsRunningOnChromeOS() ||
704 CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType
)) {
708 // Use a whitelist to only allow access to files residing in the list of
709 // directories below.
710 static const char* const kLocalAccessWhiteList
[] = {
711 "/home/chronos/user/Downloads",
712 "/home/chronos/user/log",
715 "/usr/share/chromeos-assets",
720 // The actual location of "/home/chronos/user/Downloads" is the Downloads
721 // directory under the profile path ("/home/chronos/user' is a hard link to
722 // current primary logged in profile.) For the support of multi-profile
723 // sessions, we are switching to use explicit "$PROFILE_PATH/Downloads" path
724 // and here whitelist such access.
725 if (!profile_path_
.empty()) {
726 const base::FilePath downloads
= profile_path_
.AppendASCII("Downloads");
727 if (downloads
== path
.StripTrailingSeparators() || downloads
.IsParent(path
))
730 #elif defined(OS_ANDROID)
731 // Access to files in external storage is allowed.
732 base::FilePath external_storage_path
;
733 PathService::Get(base::DIR_ANDROID_EXTERNAL_STORAGE
, &external_storage_path
);
734 if (external_storage_path
.IsParent(path
))
737 // Whitelist of other allowed directories.
738 static const char* const kLocalAccessWhiteList
[] = {
744 for (size_t i
= 0; i
< arraysize(kLocalAccessWhiteList
); ++i
) {
745 const base::FilePath
white_listed_path(kLocalAccessWhiteList
[i
]);
746 // base::FilePath::operator== should probably handle trailing separators.
747 if (white_listed_path
== path
.StripTrailingSeparators() ||
748 white_listed_path
.IsParent(path
)) {
753 DVLOG(1) << "File access denied - " << path
.value().c_str();
755 #endif // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
758 bool ChromeNetworkDelegate::OnCanThrottleRequest(
759 const net::URLRequest
& request
) const {
760 if (g_never_throttle_requests_
) {
764 return request
.first_party_for_cookies().scheme() ==
765 extensions::kExtensionScheme
;
768 bool ChromeNetworkDelegate::OnCanEnablePrivacyMode(
770 const GURL
& first_party_for_cookies
) const {
771 // NULL during tests, or when we're running in the system context.
772 if (!cookie_settings_
.get())
775 bool reading_cookie_allowed
= cookie_settings_
->IsReadingCookieAllowed(
776 url
, first_party_for_cookies
);
777 bool setting_cookie_allowed
= cookie_settings_
->IsSettingCookieAllowed(
778 url
, first_party_for_cookies
);
779 bool privacy_mode
= !(reading_cookie_allowed
&& setting_cookie_allowed
);
783 int ChromeNetworkDelegate::OnBeforeSocketStreamConnect(
784 net::SocketStream
* socket
,
785 const net::CompletionCallback
& callback
) {
786 #if defined(ENABLE_CONFIGURATION_POLICY)
787 if (url_blacklist_manager_
&&
788 url_blacklist_manager_
->IsURLBlocked(socket
->url())) {
789 // URL access blocked by policy.
790 socket
->net_log()->AddEvent(
791 net::NetLog::TYPE_CHROME_POLICY_ABORTED_REQUEST
,
792 net::NetLog::StringCallback("url",
793 &socket
->url().possibly_invalid_spec()));
794 return net::ERR_BLOCKED_BY_ADMINISTRATOR
;
800 void ChromeNetworkDelegate::AccumulateContentLength(
801 int64 received_content_length
,
802 int64 original_content_length
,
803 spdyproxy::DataReductionRequestType data_reduction_type
) {
804 DCHECK_GE(received_content_length
, 0);
805 DCHECK_GE(original_content_length
, 0);
806 StoreAccumulatedContentLength(received_content_length
,
807 original_content_length
,
809 reinterpret_cast<Profile
*>(profile_
));
810 received_content_length_
+= received_content_length
;
811 original_content_length_
+= original_content_length
;