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/command_line.h"
13 #include "base/debug/alias.h"
14 #include "base/debug/dump_without_crashing.h"
15 #include "base/debug/stack_trace.h"
16 #include "base/logging.h"
17 #include "base/metrics/histogram.h"
18 #include "base/metrics/sparse_histogram.h"
19 #include "base/metrics/user_metrics.h"
20 #include "base/path_service.h"
21 #include "base/prefs/pref_member.h"
22 #include "base/prefs/pref_service.h"
23 #include "base/profiler/scoped_tracker.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_util.h"
26 #include "base/time/time.h"
27 #include "chrome/browser/browser_process.h"
28 #include "chrome/browser/content_settings/cookie_settings_factory.h"
29 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
30 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
31 #include "chrome/browser/net/chrome_extensions_network_delegate.h"
32 #include "chrome/browser/net/connect_interceptor.h"
33 #include "chrome/browser/net/request_source_bandwidth_histograms.h"
34 #include "chrome/browser/net/safe_search_util.h"
35 #include "chrome/browser/profiles/profile_manager.h"
36 #include "chrome/browser/task_manager/task_manager.h"
37 #include "chrome/common/pref_names.h"
38 #include "components/content_settings/core/browser/cookie_settings.h"
39 #include "components/domain_reliability/monitor.h"
40 #include "content/public/browser/browser_thread.h"
41 #include "content/public/browser/render_frame_host.h"
42 #include "content/public/browser/render_view_host.h"
43 #include "content/public/browser/resource_request_info.h"
44 #include "content/public/common/content_switches.h"
45 #include "content/public/common/process_type.h"
46 #include "net/base/host_port_pair.h"
47 #include "net/base/load_flags.h"
48 #include "net/base/net_errors.h"
49 #include "net/cookies/canonical_cookie.h"
50 #include "net/cookies/cookie_options.h"
51 #include "net/http/http_request_headers.h"
52 #include "net/http/http_response_headers.h"
53 #include "net/http/http_status_code.h"
54 #include "net/log/net_log.h"
55 #include "net/url_request/url_request.h"
57 #if defined(OS_ANDROID)
58 #include "chrome/browser/io_thread.h"
59 #include "chrome/browser/precache/precache_manager_factory.h"
60 #include "components/precache/content/precache_manager.h"
63 #if defined(OS_CHROMEOS)
64 #include "base/sys_info.h"
65 #include "chrome/common/chrome_switches.h"
68 #if defined(ENABLE_CONFIGURATION_POLICY)
69 #include "components/policy/core/browser/url_blacklist_manager.h"
72 #if defined(ENABLE_EXTENSIONS)
73 #include "extensions/common/constants.h"
76 using content::BrowserThread
;
77 using content::RenderViewHost
;
78 using content::ResourceRequestInfo
;
79 using content::ResourceType
;
81 // By default we don't allow access to all file:// urls on ChromeOS and
83 #if defined(OS_CHROMEOS) || defined(OS_ANDROID)
84 bool ChromeNetworkDelegate::g_allow_file_access_
= false;
86 bool ChromeNetworkDelegate::g_allow_file_access_
= true;
91 const char kDNTHeader
[] = "DNT";
93 // Gets called when the extensions finish work on the URL. If the extensions
94 // did not do a redirect (so |new_url| is empty) then we enforce the
95 // SafeSearch parameters. Otherwise we will get called again after the
96 // redirect and we enforce SafeSearch then.
97 void ForceGoogleSafeSearchCallbackWrapper(
98 const net::CompletionCallback
& callback
,
99 net::URLRequest
* request
,
102 if (rv
== net::OK
&& new_url
->is_empty())
103 safe_search_util::ForceGoogleSafeSearch(request
, new_url
);
107 #if defined(OS_ANDROID)
108 void RecordPrecacheStatsOnUIThread(const GURL
& url
,
109 const base::Time
& fetch_time
, int64 size
,
110 bool was_cached
, void* profile_id
) {
111 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
113 Profile
* profile
= reinterpret_cast<Profile
*>(profile_id
);
114 if (!g_browser_process
->profile_manager()->IsValidProfile(profile
)) {
118 precache::PrecacheManager
* precache_manager
=
119 precache::PrecacheManagerFactory::GetForBrowserContext(profile
);
120 if (!precache_manager
|| !precache_manager
->IsPrecachingAllowed()) {
121 // |precache_manager| could be NULL if the profile is off the record.
125 precache_manager
->RecordStatsForFetch(url
, fetch_time
, size
, was_cached
);
127 #endif // defined(OS_ANDROID)
129 void ReportInvalidReferrerSendOnUI() {
131 base::UserMetricsAction("Net.URLRequest_StartJob_InvalidReferrer"));
134 void ReportInvalidReferrerSend(const GURL
& target_url
,
135 const GURL
& referrer_url
) {
136 LOG(ERROR
) << "Cancelling request to " << target_url
137 << " with invalid referrer " << referrer_url
;
138 // Record information to help debug http://crbug.com/422871
139 if (!target_url
.SchemeIsHTTPOrHTTPS())
141 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
142 base::Bind(&ReportInvalidReferrerSendOnUI
));
143 base::debug::DumpWithoutCrashing();
147 // Record network errors that HTTP requests complete with, including OK and
149 void RecordNetworkErrorHistograms(const net::URLRequest
* request
) {
150 if (request
->url().SchemeIs("http")) {
151 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.HttpRequestCompletionErrorCodes",
152 std::abs(request
->status().error()));
154 if (request
->load_flags() & net::LOAD_MAIN_FRAME
) {
155 UMA_HISTOGRAM_SPARSE_SLOWLY(
156 "Net.HttpRequestCompletionErrorCodes.MainFrame",
157 std::abs(request
->status().error()));
162 // Returns whether |request| is likely to be eligible for delta-encoding.
163 // This is only a rough approximation right now, based on MIME type.
164 bool CanRequestBeDeltaEncoded(const net::URLRequest
* request
) {
168 } kEligibleMasks
[] = {
169 // All text/ types are eligible, even if not displayable.
171 // JSON (application/json and application/*+json) is eligible.
172 { "application/", "json" },
173 // Javascript is eligible.
174 { "application/", "javascript" },
175 // XML (application/xml and application/*+xml) is eligible.
176 { "application/", "xml" },
179 std::string mime_type
;
180 request
->GetMimeType(&mime_type
);
182 for (size_t i
= 0; i
< arraysize(kEligibleMasks
); i
++) {
183 const char *prefix
= kEligibleMasks
[i
].prefix
;
184 const char *suffix
= kEligibleMasks
[i
].suffix
;
186 !base::StartsWith(mime_type
, prefix
, base::CompareCase::SENSITIVE
))
189 !base::EndsWith(mime_type
, suffix
, base::CompareCase::SENSITIVE
))
196 // Returns whether |request| was issued by a renderer process, as opposed to
197 // the browser process or a plugin process.
198 bool IsRendererInitiatedRequest(const net::URLRequest
* request
) {
199 const ResourceRequestInfo
* info
= ResourceRequestInfo::ForRequest(request
);
200 return info
&& info
->GetProcessType() == content::PROCESS_TYPE_RENDERER
;
203 // Uploads UMA histograms for delta encoding eligibility. This method can only
204 // be safely called after the network stack has called both OnStarted and
205 // OnCompleted, since it needs the received response content length and the
207 void RecordCacheStateStats(const net::URLRequest
* request
) {
208 net::HttpRequestHeaders request_headers
;
209 if (!request
->GetFullRequestHeaders(&request_headers
)) {
210 // GetFullRequestHeaders is guaranteed to succeed if OnResponseStarted() has
211 // been called on |request|, so if GetFullRequestHeaders() fails,
212 // RecordCacheStateStats must have been called before
213 // OnResponseStarted().
217 if (!IsRendererInitiatedRequest(request
)) {
218 // Ignore browser-initiated requests. These are internal requests like safe
219 // browsing and sync, and so on. Some of these could be eligible for
220 // delta-encoding, but to be conservative this function ignores all of them.
224 const int kCacheAffectingFlags
= net::LOAD_BYPASS_CACHE
|
225 net::LOAD_DISABLE_CACHE
|
226 net::LOAD_PREFERRING_CACHE
;
228 if (request
->load_flags() & kCacheAffectingFlags
) {
229 // Ignore requests with cache-affecting flags, which would otherwise mess up
235 CACHE_STATE_FROM_CACHE
,
236 CACHE_STATE_STILL_VALID
,
237 CACHE_STATE_NO_LONGER_VALID
,
238 CACHE_STATE_NO_ENTRY
,
240 } state
= CACHE_STATE_NO_ENTRY
;
241 bool had_cache_headers
=
242 request_headers
.HasHeader(net::HttpRequestHeaders::kIfModifiedSince
) ||
243 request_headers
.HasHeader(net::HttpRequestHeaders::kIfNoneMatch
) ||
244 request_headers
.HasHeader(net::HttpRequestHeaders::kIfRange
);
245 if (request
->was_cached() && !had_cache_headers
) {
246 // Entry was served directly from cache.
247 state
= CACHE_STATE_FROM_CACHE
;
248 } else if (request
->was_cached() && had_cache_headers
) {
249 // Expired entry was present in cache, and server responded with NOT
250 // MODIFIED, indicating the expired entry is still valid.
251 state
= CACHE_STATE_STILL_VALID
;
252 } else if (!request
->was_cached() && had_cache_headers
) {
253 // Expired entry was present in cache, and server responded with something
254 // other than NOT MODIFIED, indicating the entry is no longer valid.
255 state
= CACHE_STATE_NO_LONGER_VALID
;
256 } else if (!request
->was_cached() && !had_cache_headers
) {
257 // Neither |was_cached| nor |had_cache_headers|, so there's no local cache
258 // entry for this content at all.
259 state
= CACHE_STATE_NO_ENTRY
;
262 UMA_HISTOGRAM_ENUMERATION("Net.CacheState.AllRequests", state
,
264 if (CanRequestBeDeltaEncoded(request
)) {
265 UMA_HISTOGRAM_ENUMERATION("Net.CacheState.EncodeableRequests", state
,
269 int64 size
= request
->received_response_content_length();
270 if (size
>= 0 && state
== CACHE_STATE_NO_LONGER_VALID
) {
271 UMA_HISTOGRAM_COUNTS("Net.CacheState.AllBytes", size
);
272 if (CanRequestBeDeltaEncoded(request
)) {
273 UMA_HISTOGRAM_COUNTS("Net.CacheState.EncodeableBytes", size
);
280 ChromeNetworkDelegate::ChromeNetworkDelegate(
281 extensions::EventRouterForwarder
* event_router
,
282 BooleanPrefMember
* enable_referrers
)
284 enable_referrers_(enable_referrers
),
285 enable_do_not_track_(NULL
),
286 force_google_safe_search_(NULL
),
287 force_youtube_safety_mode_(NULL
),
288 #if defined(ENABLE_CONFIGURATION_POLICY)
289 url_blacklist_manager_(NULL
),
291 domain_reliability_monitor_(NULL
),
292 experimental_web_platform_features_enabled_(
293 base::CommandLine::ForCurrentProcess()->HasSwitch(
294 switches::kEnableExperimentalWebPlatformFeatures
)) {
295 DCHECK(enable_referrers
);
296 extensions_delegate_
.reset(
297 ChromeExtensionsNetworkDelegate::Create(event_router
));
300 ChromeNetworkDelegate::~ChromeNetworkDelegate() {}
302 void ChromeNetworkDelegate::set_extension_info_map(
303 extensions::InfoMap
* extension_info_map
) {
304 extensions_delegate_
->set_extension_info_map(extension_info_map
);
307 void ChromeNetworkDelegate::set_profile(void* profile
) {
309 extensions_delegate_
->set_profile(profile
);
312 void ChromeNetworkDelegate::set_cookie_settings(
313 content_settings::CookieSettings
* cookie_settings
) {
314 cookie_settings_
= cookie_settings
;
317 void ChromeNetworkDelegate::set_predictor(
318 chrome_browser_net::Predictor
* predictor
) {
319 connect_interceptor_
.reset(
320 new chrome_browser_net::ConnectInterceptor(predictor
));
324 void ChromeNetworkDelegate::InitializePrefsOnUIThread(
325 BooleanPrefMember
* enable_referrers
,
326 BooleanPrefMember
* enable_do_not_track
,
327 BooleanPrefMember
* force_google_safe_search
,
328 BooleanPrefMember
* force_youtube_safety_mode
,
329 PrefService
* pref_service
) {
330 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
331 enable_referrers
->Init(prefs::kEnableReferrers
, pref_service
);
332 enable_referrers
->MoveToThread(
333 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO
));
334 if (enable_do_not_track
) {
335 enable_do_not_track
->Init(prefs::kEnableDoNotTrack
, pref_service
);
336 enable_do_not_track
->MoveToThread(
337 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO
));
339 if (force_google_safe_search
) {
340 force_google_safe_search
->Init(prefs::kForceGoogleSafeSearch
, pref_service
);
341 force_google_safe_search
->MoveToThread(
342 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO
));
344 if (force_youtube_safety_mode
) {
345 force_youtube_safety_mode
->Init(prefs::kForceYouTubeSafetyMode
,
347 force_youtube_safety_mode
->MoveToThread(
348 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO
));
353 void ChromeNetworkDelegate::AllowAccessToAllFiles() {
354 g_allow_file_access_
= true;
357 int ChromeNetworkDelegate::OnBeforeURLRequest(
358 net::URLRequest
* request
,
359 const net::CompletionCallback
& callback
,
361 // TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed.
362 tracked_objects::ScopedTracker
tracking_profile1(
363 FROM_HERE_WITH_EXPLICIT_FUNCTION(
364 "456327 URLRequest::ChromeNetworkDelegate::OnBeforeURLRequest"));
366 #if defined(ENABLE_CONFIGURATION_POLICY)
367 // TODO(joaodasilva): This prevents extensions from seeing URLs that are
368 // blocked. However, an extension might redirect the request to another URL,
369 // which is not blocked.
371 const ResourceRequestInfo
* info
= ResourceRequestInfo::ForRequest(request
);
372 int error
= net::ERR_BLOCKED_BY_ADMINISTRATOR
;
373 if (info
&& content::IsResourceTypeFrame(info
->GetResourceType()) &&
374 url_blacklist_manager_
&&
375 url_blacklist_manager_
->ShouldBlockRequestForFrame(
376 request
->url(), &error
)) {
377 // URL access blocked by policy.
378 request
->net_log().AddEvent(
379 net::NetLog::TYPE_CHROME_POLICY_ABORTED_REQUEST
,
380 net::NetLog::StringCallback("url",
381 &request
->url().possibly_invalid_spec()));
386 // TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed.
387 tracked_objects::ScopedTracker
tracking_profile2(
388 FROM_HERE_WITH_EXPLICIT_FUNCTION(
389 "456327 URLRequest::ChromeNetworkDelegate::OnBeforeURLRequest 2"));
391 extensions_delegate_
->ForwardStartRequestStatus(request
);
393 if (!enable_referrers_
->GetValue())
394 request
->SetReferrer(std::string());
395 if (enable_do_not_track_
&& enable_do_not_track_
->GetValue())
396 request
->SetExtraRequestHeaderByName(kDNTHeader
, "1", true /* override */);
398 // TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed.
399 tracked_objects::ScopedTracker
tracking_profile3(
400 FROM_HERE_WITH_EXPLICIT_FUNCTION(
401 "456327 URLRequest::ChromeNetworkDelegate::OnBeforeURLRequest 3"));
403 bool force_safe_search
=
404 (force_google_safe_search_
&& force_google_safe_search_
->GetValue());
406 net::CompletionCallback wrapped_callback
= callback
;
407 if (force_safe_search
) {
408 wrapped_callback
= base::Bind(&ForceGoogleSafeSearchCallbackWrapper
,
410 base::Unretained(request
),
411 base::Unretained(new_url
));
414 int rv
= extensions_delegate_
->OnBeforeURLRequest(
415 request
, wrapped_callback
, new_url
);
417 // TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed.
418 tracked_objects::ScopedTracker
tracking_profile4(
419 FROM_HERE_WITH_EXPLICIT_FUNCTION(
420 "456327 URLRequest::ChromeNetworkDelegate::OnBeforeURLRequest 4"));
422 if (force_safe_search
&& rv
== net::OK
&& new_url
->is_empty())
423 safe_search_util::ForceGoogleSafeSearch(request
, new_url
);
425 // TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed.
426 tracked_objects::ScopedTracker
tracking_profile5(
427 FROM_HERE_WITH_EXPLICIT_FUNCTION(
428 "456327 URLRequest::ChromeNetworkDelegate::OnBeforeURLRequest 5"));
430 if (connect_interceptor_
)
431 connect_interceptor_
->WitnessURLRequest(request
);
436 int ChromeNetworkDelegate::OnBeforeSendHeaders(
437 net::URLRequest
* request
,
438 const net::CompletionCallback
& callback
,
439 net::HttpRequestHeaders
* headers
) {
440 if (force_youtube_safety_mode_
&& force_youtube_safety_mode_
->GetValue())
441 safe_search_util::ForceYouTubeSafetyMode(request
, headers
);
443 return extensions_delegate_
->OnBeforeSendHeaders(request
, callback
, headers
);
446 void ChromeNetworkDelegate::OnSendHeaders(
447 net::URLRequest
* request
,
448 const net::HttpRequestHeaders
& headers
) {
449 extensions_delegate_
->OnSendHeaders(request
, headers
);
452 int ChromeNetworkDelegate::OnHeadersReceived(
453 net::URLRequest
* request
,
454 const net::CompletionCallback
& callback
,
455 const net::HttpResponseHeaders
* original_response_headers
,
456 scoped_refptr
<net::HttpResponseHeaders
>* override_response_headers
,
457 GURL
* allowed_unsafe_redirect_url
) {
458 return extensions_delegate_
->OnHeadersReceived(
461 original_response_headers
,
462 override_response_headers
,
463 allowed_unsafe_redirect_url
);
466 void ChromeNetworkDelegate::OnBeforeRedirect(net::URLRequest
* request
,
467 const GURL
& new_location
) {
468 if (domain_reliability_monitor_
)
469 domain_reliability_monitor_
->OnBeforeRedirect(request
);
470 extensions_delegate_
->OnBeforeRedirect(request
, new_location
);
474 void ChromeNetworkDelegate::OnResponseStarted(net::URLRequest
* request
) {
475 extensions_delegate_
->OnResponseStarted(request
);
478 void ChromeNetworkDelegate::OnRawBytesRead(const net::URLRequest
& request
,
480 #if defined(ENABLE_TASK_MANAGER)
481 // This is not completely accurate, but as a first approximation ignore
482 // requests that are served from the cache. See bug 330931 for more info.
483 if (!request
.was_cached())
484 TaskManager::GetInstance()->model()->NotifyBytesRead(request
, bytes_read
);
485 #endif // defined(ENABLE_TASK_MANAGER)
488 void ChromeNetworkDelegate::OnCompleted(net::URLRequest
* request
,
490 RecordNetworkErrorHistograms(request
);
492 // Only call in for requests that were started, to obey the precondition
493 // that RecordCacheStateStats can only be called on requests for which
494 // OnResponseStarted was called.
495 RecordCacheStateStats(request
);
498 if (request
->status().status() == net::URLRequestStatus::SUCCESS
) {
499 #if defined(OS_ANDROID)
500 // For better accuracy, we use the actual bytes read instead of the length
501 // specified with the Content-Length header, which may be inaccurate,
502 // or missing, as is the case with chunked encoding.
503 int64 received_content_length
= request
->received_response_content_length();
505 // Record precache metrics when a fetch is completed successfully.
506 BrowserThread::PostTask(
507 BrowserThread::UI
, FROM_HERE
,
508 base::Bind(&RecordPrecacheStatsOnUIThread
, request
->url(),
509 base::Time::Now(), received_content_length
,
510 request
->was_cached(), profile_
));
511 #endif // defined(OS_ANDROID)
512 extensions_delegate_
->OnCompleted(request
, started
);
513 } else if (request
->status().status() == net::URLRequestStatus::FAILED
||
514 request
->status().status() == net::URLRequestStatus::CANCELED
) {
515 extensions_delegate_
->OnCompleted(request
, started
);
519 if (domain_reliability_monitor_
)
520 domain_reliability_monitor_
->OnCompleted(request
, started
);
521 RecordRequestSourceBandwidth(request
, started
);
522 extensions_delegate_
->ForwardProxyErrors(request
);
523 extensions_delegate_
->ForwardDoneRequestStatus(request
);
526 void ChromeNetworkDelegate::OnURLRequestDestroyed(net::URLRequest
* request
) {
527 extensions_delegate_
->OnURLRequestDestroyed(request
);
530 void ChromeNetworkDelegate::OnPACScriptError(int line_number
,
531 const base::string16
& error
) {
532 extensions_delegate_
->OnPACScriptError(line_number
, error
);
535 net::NetworkDelegate::AuthRequiredResponse
536 ChromeNetworkDelegate::OnAuthRequired(
537 net::URLRequest
* request
,
538 const net::AuthChallengeInfo
& auth_info
,
539 const AuthCallback
& callback
,
540 net::AuthCredentials
* credentials
) {
541 return extensions_delegate_
->OnAuthRequired(
542 request
, auth_info
, callback
, credentials
);
545 bool ChromeNetworkDelegate::OnCanGetCookies(
546 const net::URLRequest
& request
,
547 const net::CookieList
& cookie_list
) {
548 // NULL during tests, or when we're running in the system context.
549 if (!cookie_settings_
.get())
552 bool allow
= cookie_settings_
->IsReadingCookieAllowed(
553 request
.url(), request
.first_party_for_cookies());
555 int render_process_id
= -1;
556 int render_frame_id
= -1;
557 if (content::ResourceRequestInfo::GetRenderFrameForRequest(
558 &request
, &render_process_id
, &render_frame_id
)) {
559 BrowserThread::PostTask(
560 BrowserThread::UI
, FROM_HERE
,
561 base::Bind(&TabSpecificContentSettings::CookiesRead
,
562 render_process_id
, render_frame_id
,
563 request
.url(), request
.first_party_for_cookies(),
564 cookie_list
, !allow
));
570 bool ChromeNetworkDelegate::OnCanSetCookie(const net::URLRequest
& request
,
571 const std::string
& cookie_line
,
572 net::CookieOptions
* options
) {
573 // NULL during tests, or when we're running in the system context.
574 if (!cookie_settings_
.get())
577 bool allow
= cookie_settings_
->IsSettingCookieAllowed(
578 request
.url(), request
.first_party_for_cookies());
580 int render_process_id
= -1;
581 int render_frame_id
= -1;
582 if (content::ResourceRequestInfo::GetRenderFrameForRequest(
583 &request
, &render_process_id
, &render_frame_id
)) {
584 BrowserThread::PostTask(
585 BrowserThread::UI
, FROM_HERE
,
586 base::Bind(&TabSpecificContentSettings::CookieChanged
,
587 render_process_id
, render_frame_id
,
588 request
.url(), request
.first_party_for_cookies(),
589 cookie_line
, *options
, !allow
));
595 bool ChromeNetworkDelegate::OnCanAccessFile(const net::URLRequest
& request
,
596 const base::FilePath
& path
) const {
597 if (g_allow_file_access_
)
600 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
603 #if defined(OS_CHROMEOS)
604 // If we're running Chrome for ChromeOS on Linux, we want to allow file
606 if (!base::SysInfo::IsRunningOnChromeOS() ||
607 base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType
)) {
611 // Use a whitelist to only allow access to files residing in the list of
612 // directories below.
613 static const char* const kLocalAccessWhiteList
[] = {
614 "/home/chronos/user/Downloads",
615 "/home/chronos/user/log",
616 "/home/chronos/user/WebRTC Logs",
619 "/usr/share/chromeos-assets",
624 // The actual location of "/home/chronos/user/Xyz" is the Xyz directory under
625 // the profile path ("/home/chronos/user' is a hard link to current primary
626 // logged in profile.) For the support of multi-profile sessions, we are
627 // switching to use explicit "$PROFILE_PATH/Xyz" path and here whitelist such
629 if (!profile_path_
.empty()) {
630 const base::FilePath downloads
= profile_path_
.AppendASCII("Downloads");
631 if (downloads
== path
.StripTrailingSeparators() || downloads
.IsParent(path
))
633 const base::FilePath webrtc_logs
= profile_path_
.AppendASCII("WebRTC Logs");
634 if (webrtc_logs
== path
.StripTrailingSeparators() ||
635 webrtc_logs
.IsParent(path
)) {
639 #elif defined(OS_ANDROID)
640 // Access to files in external storage is allowed.
641 base::FilePath external_storage_path
;
642 PathService::Get(base::DIR_ANDROID_EXTERNAL_STORAGE
, &external_storage_path
);
643 if (external_storage_path
.IsParent(path
))
646 // Whitelist of other allowed directories.
647 static const char* const kLocalAccessWhiteList
[] = {
653 for (size_t i
= 0; i
< arraysize(kLocalAccessWhiteList
); ++i
) {
654 const base::FilePath
white_listed_path(kLocalAccessWhiteList
[i
]);
655 // base::FilePath::operator== should probably handle trailing separators.
656 if (white_listed_path
== path
.StripTrailingSeparators() ||
657 white_listed_path
.IsParent(path
)) {
662 DVLOG(1) << "File access denied - " << path
.value().c_str();
664 #endif // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
667 bool ChromeNetworkDelegate::OnCanEnablePrivacyMode(
669 const GURL
& first_party_for_cookies
) const {
670 // NULL during tests, or when we're running in the system context.
671 if (!cookie_settings_
.get())
674 bool reading_cookie_allowed
= cookie_settings_
->IsReadingCookieAllowed(
675 url
, first_party_for_cookies
);
676 bool setting_cookie_allowed
= cookie_settings_
->IsSettingCookieAllowed(
677 url
, first_party_for_cookies
);
678 bool privacy_mode
= !(reading_cookie_allowed
&& setting_cookie_allowed
);
682 bool ChromeNetworkDelegate::OnFirstPartyOnlyCookieExperimentEnabled() const {
683 return experimental_web_platform_features_enabled_
;
686 bool ChromeNetworkDelegate::OnCancelURLRequestWithPolicyViolatingReferrerHeader(
687 const net::URLRequest
& request
,
688 const GURL
& target_url
,
689 const GURL
& referrer_url
) const {
690 ReportInvalidReferrerSend(target_url
, referrer_url
);