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. 4 5 #include "chrome/browser/net/chrome_network_delegate.h" 6 7 #include <stdlib.h> 8 9 #include <vector> 10 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/net/chrome_extensions_network_delegate.h" 26 #include "chrome/browser/net/client_hints.h" 27 #include "chrome/browser/net/connect_interceptor.h" 28 #include "chrome/browser/performance_monitor/performance_monitor.h" 29 #include "chrome/browser/prerender/prerender_tracker.h" 30 #include "chrome/browser/profiles/profile_manager.h" 31 #include "chrome/browser/task_manager/task_manager.h" 32 #include "chrome/common/pref_names.h" 33 #include "chrome/common/url_constants.h" 34 #include "components/data_reduction_proxy/browser/data_reduction_proxy_metrics.h" 35 #include "components/data_reduction_proxy/browser/data_reduction_proxy_params.h" 36 #include "components/data_reduction_proxy/browser/data_reduction_proxy_protocol.h" 37 #include "components/domain_reliability/monitor.h" 38 #include "components/google/core/browser/google_util.h" 39 #include "content/public/browser/browser_thread.h" 40 #include "content/public/browser/render_frame_host.h" 41 #include "content/public/browser/render_view_host.h" 42 #include "content/public/browser/resource_request_info.h" 43 #include "extensions/common/constants.h" 44 #include "net/base/host_port_pair.h" 45 #include "net/base/net_errors.h" 46 #include "net/base/net_log.h" 47 #include "net/cookies/canonical_cookie.h" 48 #include "net/cookies/cookie_options.h" 49 #include "net/http/http_request_headers.h" 50 #include "net/http/http_response_headers.h" 51 #include "net/socket_stream/socket_stream.h" 52 #include "net/url_request/url_request.h" 53 #include "net/url_request/url_request_context.h" 54 55 #if defined(OS_ANDROID) 56 #include "chrome/browser/io_thread.h" 57 #include "components/precache/content/precache_manager.h" 58 #include "components/precache/content/precache_manager_factory.h" 59 #endif 60 61 #if defined(OS_CHROMEOS) 62 #include "base/command_line.h" 63 #include "base/sys_info.h" 64 #include "chrome/common/chrome_switches.h" 65 #endif 66 67 #if defined(ENABLE_CONFIGURATION_POLICY) 68 #include "components/policy/core/browser/url_blacklist_manager.h" 69 #endif 70 71 using content::BrowserThread; 72 using content::RenderViewHost; 73 using content::ResourceRequestInfo; 74 75 // By default we don't allow access to all file:// urls on ChromeOS and 76 // Android. 77 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) 78 bool ChromeNetworkDelegate::g_allow_file_access_ = false; 79 #else 80 bool ChromeNetworkDelegate::g_allow_file_access_ = true; 81 #endif 82 83 // This remains false unless the --disable-extensions-http-throttling 84 // flag is passed to the browser. 85 bool ChromeNetworkDelegate::g_never_throttle_requests_ = false; 86 87 namespace { 88 89 const char kDNTHeader[] = "DNT"; 90 91 // Returns whether a URL parameter, |first_parameter| (e.g. foo=bar), has the 92 // same key as the the |second_parameter| (e.g. foo=baz). Both parameters 93 // must be in key=value form. 94 bool HasSameParameterKey(const std::string& first_parameter, 95 const std::string& second_parameter) { 96 DCHECK(second_parameter.find("=") != std::string::npos); 97 // Prefix for "foo=bar" is "foo=". 98 std::string parameter_prefix = second_parameter.substr( 99 0, second_parameter.find("=") + 1); 100 return StartsWithASCII(first_parameter, parameter_prefix, false); 101 } 102 103 // Examines the query string containing parameters and adds the necessary ones 104 // so that SafeSearch is active. |query| is the string to examine and the 105 // return value is the |query| string modified such that SafeSearch is active. 106 std::string AddSafeSearchParameters(const std::string& query) { 107 std::vector<std::string> new_parameters; 108 std::string safe_parameter = chrome::kSafeSearchSafeParameter; 109 std::string ssui_parameter = chrome::kSafeSearchSsuiParameter; 110 111 std::vector<std::string> parameters; 112 base::SplitString(query, '&', ¶meters); 113 114 std::vector<std::string>::iterator it; 115 for (it = parameters.begin(); it < parameters.end(); ++it) { 116 if (!HasSameParameterKey(*it, safe_parameter) && 117 !HasSameParameterKey(*it, ssui_parameter)) { 118 new_parameters.push_back(*it); 119 } 120 } 121 122 new_parameters.push_back(safe_parameter); 123 new_parameters.push_back(ssui_parameter); 124 return JoinString(new_parameters, '&'); 125 } 126 127 // If |request| is a request to Google Web Search the function 128 // enforces that the SafeSearch query parameters are set to active. 129 // Sets the query part of |new_url| with the new value of the parameters. 130 void ForceGoogleSafeSearch(net::URLRequest* request, 131 GURL* new_url) { 132 if (!google_util::IsGoogleSearchUrl(request->url()) && 133 !google_util::IsGoogleHomePageUrl(request->url())) 134 return; 135 136 std::string query = request->url().query(); 137 std::string new_query = AddSafeSearchParameters(query); 138 if (query == new_query) 139 return; 140 141 GURL::Replacements replacements; 142 replacements.SetQueryStr(new_query); 143 *new_url = request->url().ReplaceComponents(replacements); 144 } 145 146 // Gets called when the extensions finish work on the URL. If the extensions 147 // did not do a redirect (so |new_url| is empty) then we enforce the 148 // SafeSearch parameters. Otherwise we will get called again after the 149 // redirect and we enforce SafeSearch then. 150 void ForceGoogleSafeSearchCallbackWrapper( 151 const net::CompletionCallback& callback, 152 net::URLRequest* request, 153 GURL* new_url, 154 int rv) { 155 if (rv == net::OK && new_url->is_empty()) 156 ForceGoogleSafeSearch(request, new_url); 157 callback.Run(rv); 158 } 159 160 void UpdateContentLengthPrefs( 161 int received_content_length, 162 int original_content_length, 163 data_reduction_proxy::DataReductionProxyRequestType request_type, 164 Profile* profile) { 165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 166 DCHECK_GE(received_content_length, 0); 167 DCHECK_GE(original_content_length, 0); 168 169 // Can be NULL in a unit test. 170 if (!g_browser_process) 171 return; 172 173 PrefService* prefs = g_browser_process->local_state(); 174 if (!prefs) 175 return; 176 177 // Ignore off-the-record data. 178 if (!g_browser_process->profile_manager()->IsValidProfile(profile) || 179 profile->IsOffTheRecord()) { 180 return; 181 } 182 #if defined(OS_ANDROID) 183 // If Android ever goes multi profile, the profile should be passed so that 184 // the browser preference will be taken. 185 bool with_data_reduction_proxy_enabled = 186 ProfileManager::GetActiveUserProfile()->GetPrefs()->GetBoolean( 187 data_reduction_proxy::prefs::kDataReductionProxyEnabled); 188 #else 189 bool with_data_reduction_proxy_enabled = false; 190 #endif 191 192 data_reduction_proxy::UpdateContentLengthPrefs(received_content_length, 193 original_content_length, 194 with_data_reduction_proxy_enabled, 195 request_type, prefs); 196 } 197 198 void StoreAccumulatedContentLength( 199 int received_content_length, 200 int original_content_length, 201 data_reduction_proxy::DataReductionProxyRequestType request_type, 202 Profile* profile) { 203 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 204 base::Bind(&UpdateContentLengthPrefs, 205 received_content_length, original_content_length, 206 request_type, profile)); 207 } 208 209 void RecordContentLengthHistograms( 210 int64 received_content_length, 211 int64 original_content_length, 212 const base::TimeDelta& freshness_lifetime) { 213 // Add the current resource to these histograms only when a valid 214 // X-Original-Content-Length header is present. 215 if (original_content_length >= 0) { 216 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthWithValidOCL", 217 received_content_length); 218 UMA_HISTOGRAM_COUNTS("Net.HttpOriginalContentLengthWithValidOCL", 219 original_content_length); 220 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthDifferenceWithValidOCL", 221 original_content_length - received_content_length); 222 } else { 223 // Presume the original content length is the same as the received content 224 // length if the X-Original-Content-Header is not present. 225 original_content_length = received_content_length; 226 } 227 UMA_HISTOGRAM_COUNTS("Net.HttpContentLength", received_content_length); 228 UMA_HISTOGRAM_COUNTS("Net.HttpOriginalContentLength", 229 original_content_length); 230 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthDifference", 231 original_content_length - received_content_length); 232 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpContentFreshnessLifetime", 233 freshness_lifetime.InSeconds(), 234 base::TimeDelta::FromHours(1).InSeconds(), 235 base::TimeDelta::FromDays(30).InSeconds(), 236 100); 237 if (freshness_lifetime.InSeconds() <= 0) 238 return; 239 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable", 240 received_content_length); 241 if (freshness_lifetime.InHours() < 4) 242 return; 243 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable4Hours", 244 received_content_length); 245 246 if (freshness_lifetime.InHours() < 24) 247 return; 248 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthCacheable24Hours", 249 received_content_length); 250 } 251 252 #if defined(OS_ANDROID) 253 void RecordPrecacheStatsOnUIThread(const GURL& url, 254 const base::Time& fetch_time, int64 size, 255 bool was_cached, void* profile_id) { 256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 257 258 Profile* profile = reinterpret_cast<Profile*>(profile_id); 259 if (!g_browser_process->profile_manager()->IsValidProfile(profile)) { 260 return; 261 } 262 263 precache::PrecacheManager* precache_manager = 264 precache::PrecacheManagerFactory::GetForBrowserContext(profile); 265 if (!precache_manager) { 266 // This could be NULL if the profile is off the record. 267 return; 268 } 269 270 precache_manager->RecordStatsForFetch(url, fetch_time, size, was_cached); 271 } 272 273 void RecordIOThreadToRequestStartOnUIThread( 274 const base::TimeTicks& request_start) { 275 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 276 base::TimeDelta request_lag = request_start - 277 g_browser_process->io_thread()->creation_time(); 278 UMA_HISTOGRAM_TIMES("Net.IOThreadCreationToHTTPRequestStart", request_lag); 279 } 280 #endif // defined(OS_ANDROID) 281 282 } // namespace 283 284 ChromeNetworkDelegate::ChromeNetworkDelegate( 285 extensions::EventRouterForwarder* event_router, 286 BooleanPrefMember* enable_referrers) 287 : profile_(NULL), 288 enable_referrers_(enable_referrers), 289 enable_do_not_track_(NULL), 290 force_google_safe_search_(NULL), 291 #if defined(ENABLE_CONFIGURATION_POLICY) 292 url_blacklist_manager_(NULL), 293 #endif 294 domain_reliability_monitor_(NULL), 295 received_content_length_(0), 296 original_content_length_(0), 297 first_request_(true), 298 prerender_tracker_(NULL), 299 data_reduction_proxy_params_(NULL) { 300 DCHECK(enable_referrers); 301 extensions_delegate_.reset( 302 ChromeExtensionsNetworkDelegate::Create(event_router)); 303 } 304 305 ChromeNetworkDelegate::~ChromeNetworkDelegate() {} 306 307 void ChromeNetworkDelegate::set_extension_info_map( 308 extensions::InfoMap* extension_info_map) { 309 extensions_delegate_->set_extension_info_map(extension_info_map); 310 } 311 312 void ChromeNetworkDelegate::set_profile(void* profile) { 313 profile_ = profile; 314 extensions_delegate_->set_profile(profile); 315 } 316 317 void ChromeNetworkDelegate::set_cookie_settings( 318 CookieSettings* cookie_settings) { 319 cookie_settings_ = cookie_settings; 320 } 321 322 void ChromeNetworkDelegate::set_predictor( 323 chrome_browser_net::Predictor* predictor) { 324 connect_interceptor_.reset( 325 new chrome_browser_net::ConnectInterceptor(predictor)); 326 } 327 328 void ChromeNetworkDelegate::SetEnableClientHints() { 329 client_hints_.reset(new ClientHints()); 330 client_hints_->Init(); 331 } 332 333 // static 334 void ChromeNetworkDelegate::NeverThrottleRequests() { 335 g_never_throttle_requests_ = true; 336 } 337 338 // static 339 void ChromeNetworkDelegate::InitializePrefsOnUIThread( 340 BooleanPrefMember* enable_referrers, 341 BooleanPrefMember* enable_do_not_track, 342 BooleanPrefMember* force_google_safe_search, 343 PrefService* pref_service) { 344 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 345 enable_referrers->Init(prefs::kEnableReferrers, pref_service); 346 enable_referrers->MoveToThread( 347 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); 348 if (enable_do_not_track) { 349 enable_do_not_track->Init(prefs::kEnableDoNotTrack, pref_service); 350 enable_do_not_track->MoveToThread( 351 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); 352 } 353 if (force_google_safe_search) { 354 force_google_safe_search->Init(prefs::kForceSafeSearch, pref_service); 355 force_google_safe_search->MoveToThread( 356 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); 357 } 358 } 359 360 // static 361 void ChromeNetworkDelegate::AllowAccessToAllFiles() { 362 g_allow_file_access_ = true; 363 } 364 365 // static 366 base::Value* ChromeNetworkDelegate::HistoricNetworkStatsInfoToValue() { 367 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 368 PrefService* prefs = g_browser_process->local_state(); 369 int64 total_received = prefs->GetInt64( 370 data_reduction_proxy::prefs::kHttpReceivedContentLength); 371 int64 total_original = prefs->GetInt64( 372 data_reduction_proxy::prefs::kHttpOriginalContentLength); 373 374 base::DictionaryValue* dict = new base::DictionaryValue(); 375 // Use strings to avoid overflow. base::Value only supports 32-bit integers. 376 dict->SetString("historic_received_content_length", 377 base::Int64ToString(total_received)); 378 dict->SetString("historic_original_content_length", 379 base::Int64ToString(total_original)); 380 return dict; 381 } 382 383 base::Value* ChromeNetworkDelegate::SessionNetworkStatsInfoToValue() const { 384 base::DictionaryValue* dict = new base::DictionaryValue(); 385 // Use strings to avoid overflow. base::Value only supports 32-bit integers. 386 dict->SetString("session_received_content_length", 387 base::Int64ToString(received_content_length_)); 388 dict->SetString("session_original_content_length", 389 base::Int64ToString(original_content_length_)); 390 return dict; 391 } 392 393 int ChromeNetworkDelegate::OnBeforeURLRequest( 394 net::URLRequest* request, 395 const net::CompletionCallback& callback, 396 GURL* new_url) { 397 #if defined(OS_ANDROID) 398 // This UMA tracks the time to the first user-initiated request start, so 399 // only non-null profiles are considered. 400 if (first_request_ && profile_) { 401 bool record_timing = true; 402 if (data_reduction_proxy_params_) { 403 record_timing = 404 (request->url() != data_reduction_proxy_params_->probe_url()) && 405 (request->url() != data_reduction_proxy_params_->warmup_url()); 406 } 407 if (record_timing) { 408 first_request_ = false; 409 net::LoadTimingInfo timing_info; 410 request->GetLoadTimingInfo(&timing_info); 411 BrowserThread::PostTask( 412 BrowserThread::UI, FROM_HERE, 413 base::Bind(&RecordIOThreadToRequestStartOnUIThread, 414 timing_info.request_start)); 415 } 416 } 417 #endif // defined(OS_ANDROID) 418 419 #if defined(ENABLE_CONFIGURATION_POLICY) 420 // TODO(joaodasilva): This prevents extensions from seeing URLs that are 421 // blocked. However, an extension might redirect the request to another URL, 422 // which is not blocked. 423 int error = net::ERR_BLOCKED_BY_ADMINISTRATOR; 424 if (url_blacklist_manager_ && 425 url_blacklist_manager_->IsRequestBlocked(*request, &error)) { 426 // URL access blocked by policy. 427 request->net_log().AddEvent( 428 net::NetLog::TYPE_CHROME_POLICY_ABORTED_REQUEST, 429 net::NetLog::StringCallback("url", 430 &request->url().possibly_invalid_spec())); 431 return error; 432 } 433 #endif 434 435 extensions_delegate_->ForwardStartRequestStatus(request); 436 437 if (!enable_referrers_->GetValue()) 438 request->SetReferrer(std::string()); 439 if (enable_do_not_track_ && enable_do_not_track_->GetValue()) 440 request->SetExtraRequestHeaderByName(kDNTHeader, "1", true /* override */); 441 442 if (client_hints_) { 443 request->SetExtraRequestHeaderByName( 444 ClientHints::kDevicePixelRatioHeader, 445 client_hints_->GetDevicePixelRatioHeader(), true); 446 } 447 448 bool force_safe_search = force_google_safe_search_ && 449 force_google_safe_search_->GetValue(); 450 451 net::CompletionCallback wrapped_callback = callback; 452 if (force_safe_search) { 453 wrapped_callback = base::Bind(&ForceGoogleSafeSearchCallbackWrapper, 454 callback, 455 base::Unretained(request), 456 base::Unretained(new_url)); 457 } 458 459 int rv = extensions_delegate_->OnBeforeURLRequest( 460 request, wrapped_callback, new_url); 461 462 if (force_safe_search && rv == net::OK && new_url->is_empty()) 463 ForceGoogleSafeSearch(request, new_url); 464 465 if (connect_interceptor_) 466 connect_interceptor_->WitnessURLRequest(request); 467 468 return rv; 469 } 470 471 int ChromeNetworkDelegate::OnBeforeSendHeaders( 472 net::URLRequest* request, 473 const net::CompletionCallback& callback, 474 net::HttpRequestHeaders* headers) { 475 TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request, "SendRequest"); 476 return extensions_delegate_->OnBeforeSendHeaders(request, callback, headers); 477 } 478 479 void ChromeNetworkDelegate::OnSendHeaders( 480 net::URLRequest* request, 481 const net::HttpRequestHeaders& headers) { 482 extensions_delegate_->OnSendHeaders(request, headers); 483 } 484 485 int ChromeNetworkDelegate::OnHeadersReceived( 486 net::URLRequest* request, 487 const net::CompletionCallback& callback, 488 const net::HttpResponseHeaders* original_response_headers, 489 scoped_refptr<net::HttpResponseHeaders>* override_response_headers, 490 GURL* allowed_unsafe_redirect_url) { 491 if (data_reduction_proxy::MaybeBypassProxyAndPrepareToRetry( 492 data_reduction_proxy_params_, 493 request, 494 original_response_headers, 495 override_response_headers)) { 496 return net::OK; 497 } 498 499 return extensions_delegate_->OnHeadersReceived( 500 request, 501 callback, 502 original_response_headers, 503 override_response_headers, 504 allowed_unsafe_redirect_url); 505 } 506 507 void ChromeNetworkDelegate::OnBeforeRedirect(net::URLRequest* request, 508 const GURL& new_location) { 509 if (domain_reliability_monitor_) 510 domain_reliability_monitor_->OnBeforeRedirect(request); 511 extensions_delegate_->OnBeforeRedirect(request, new_location); 512 } 513 514 515 void ChromeNetworkDelegate::OnResponseStarted(net::URLRequest* request) { 516 TRACE_EVENT_ASYNC_STEP_PAST0("net", "URLRequest", request, "ResponseStarted"); 517 extensions_delegate_->OnResponseStarted(request); 518 } 519 520 void ChromeNetworkDelegate::OnRawBytesRead(const net::URLRequest& request, 521 int bytes_read) { 522 TRACE_EVENT_ASYNC_STEP_PAST1("net", "URLRequest", &request, "DidRead", 523 "bytes_read", bytes_read); 524 performance_monitor::PerformanceMonitor::GetInstance()->BytesReadOnIOThread( 525 request, bytes_read); 526 527 #if defined(ENABLE_TASK_MANAGER) 528 // This is not completely accurate, but as a first approximation ignore 529 // requests that are served from the cache. See bug 330931 for more info. 530 if (!request.was_cached()) 531 TaskManager::GetInstance()->model()->NotifyBytesRead(request, bytes_read); 532 #endif // defined(ENABLE_TASK_MANAGER) 533 } 534 535 void ChromeNetworkDelegate::OnCompleted(net::URLRequest* request, 536 bool started) { 537 TRACE_EVENT_ASYNC_END0("net", "URLRequest", request); 538 if (request->status().status() == net::URLRequestStatus::SUCCESS) { 539 // For better accuracy, we use the actual bytes read instead of the length 540 // specified with the Content-Length header, which may be inaccurate, 541 // or missing, as is the case with chunked encoding. 542 int64 received_content_length = request->received_response_content_length(); 543 544 #if defined(OS_ANDROID) 545 if (precache::PrecacheManager::IsPrecachingEnabled()) { 546 // Record precache metrics when a fetch is completed successfully, if 547 // precaching is enabled. 548 BrowserThread::PostTask( 549 BrowserThread::UI, FROM_HERE, 550 base::Bind(&RecordPrecacheStatsOnUIThread, request->url(), 551 base::Time::Now(), received_content_length, 552 request->was_cached(), profile_)); 553 } 554 #endif // defined(OS_ANDROID) 555 556 // Only record for http or https urls. 557 bool is_http = request->url().SchemeIs("http"); 558 bool is_https = request->url().SchemeIs("https"); 559 560 if (!request->was_cached() && // Don't record cached content 561 received_content_length && // Zero-byte responses aren't useful. 562 (is_http || is_https)) { // Only record for HTTP or HTTPS urls. 563 int64 original_content_length = 564 request->response_info().headers->GetInt64HeaderValue( 565 "x-original-content-length"); 566 data_reduction_proxy::DataReductionProxyRequestType request_type = 567 data_reduction_proxy::GetDataReductionProxyRequestType(request); 568 569 base::TimeDelta freshness_lifetime = 570 request->response_info().headers->GetFreshnessLifetime( 571 request->response_info().response_time); 572 int64 adjusted_original_content_length = 573 data_reduction_proxy::GetAdjustedOriginalContentLength( 574 request_type, original_content_length, 575 received_content_length); 576 AccumulateContentLength(received_content_length, 577 adjusted_original_content_length, 578 request_type); 579 RecordContentLengthHistograms(received_content_length, 580 original_content_length, 581 freshness_lifetime); 582 DVLOG(2) << __FUNCTION__ 583 << " received content length: " << received_content_length 584 << " original content length: " << original_content_length 585 << " url: " << request->url(); 586 } 587 588 extensions_delegate_->OnCompleted(request, started); 589 } else if (request->status().status() == net::URLRequestStatus::FAILED || 590 request->status().status() == net::URLRequestStatus::CANCELED) { 591 extensions_delegate_->OnCompleted(request, started); 592 } else { 593 NOTREACHED(); 594 } 595 if (domain_reliability_monitor_) 596 domain_reliability_monitor_->OnCompleted(request, started); 597 extensions_delegate_->ForwardProxyErrors(request); 598 extensions_delegate_->ForwardDoneRequestStatus(request); 599 } 600 601 void ChromeNetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) { 602 extensions_delegate_->OnURLRequestDestroyed(request); 603 } 604 605 void ChromeNetworkDelegate::OnPACScriptError(int line_number, 606 const base::string16& error) { 607 extensions_delegate_->OnPACScriptError(line_number, error); 608 } 609 610 net::NetworkDelegate::AuthRequiredResponse 611 ChromeNetworkDelegate::OnAuthRequired( 612 net::URLRequest* request, 613 const net::AuthChallengeInfo& auth_info, 614 const AuthCallback& callback, 615 net::AuthCredentials* credentials) { 616 return extensions_delegate_->OnAuthRequired( 617 request, auth_info, callback, credentials); 618 } 619 620 bool ChromeNetworkDelegate::OnCanGetCookies( 621 const net::URLRequest& request, 622 const net::CookieList& cookie_list) { 623 // NULL during tests, or when we're running in the system context. 624 if (!cookie_settings_.get()) 625 return true; 626 627 bool allow = cookie_settings_->IsReadingCookieAllowed( 628 request.url(), request.first_party_for_cookies()); 629 630 int render_process_id = -1; 631 int render_frame_id = -1; 632 633 // |is_for_blocking_resource| indicates whether the cookies read were for a 634 // blocking resource (eg script, css). It is only temporarily added for 635 // diagnostic purposes, per bug 353678. Will be removed again once data 636 // collection is finished. 637 bool is_for_blocking_resource = false; 638 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(&request); 639 if (info && ((!info->IsAsync()) || 640 info->GetResourceType() == ResourceType::STYLESHEET || 641 info->GetResourceType() == ResourceType::SCRIPT)) { 642 is_for_blocking_resource = true; 643 } 644 645 if (content::ResourceRequestInfo::GetRenderFrameForRequest( 646 &request, &render_process_id, &render_frame_id)) { 647 BrowserThread::PostTask( 648 BrowserThread::UI, FROM_HERE, 649 base::Bind(&TabSpecificContentSettings::CookiesRead, 650 render_process_id, render_frame_id, 651 request.url(), request.first_party_for_cookies(), 652 cookie_list, !allow, is_for_blocking_resource)); 653 } 654 655 return allow; 656 } 657 658 bool ChromeNetworkDelegate::OnCanSetCookie(const net::URLRequest& request, 659 const std::string& cookie_line, 660 net::CookieOptions* options) { 661 // NULL during tests, or when we're running in the system context. 662 if (!cookie_settings_.get()) 663 return true; 664 665 bool allow = cookie_settings_->IsSettingCookieAllowed( 666 request.url(), request.first_party_for_cookies()); 667 668 int render_process_id = -1; 669 int render_frame_id = -1; 670 if (content::ResourceRequestInfo::GetRenderFrameForRequest( 671 &request, &render_process_id, &render_frame_id)) { 672 BrowserThread::PostTask( 673 BrowserThread::UI, FROM_HERE, 674 base::Bind(&TabSpecificContentSettings::CookieChanged, 675 render_process_id, render_frame_id, 676 request.url(), request.first_party_for_cookies(), 677 cookie_line, *options, !allow)); 678 } 679 680 if (prerender_tracker_) { 681 prerender_tracker_->OnCookieChangedForURL( 682 render_process_id, 683 request.context()->cookie_store()->GetCookieMonster(), 684 request.url()); 685 } 686 687 return allow; 688 } 689 690 bool ChromeNetworkDelegate::OnCanAccessFile(const net::URLRequest& request, 691 const base::FilePath& path) const { 692 if (g_allow_file_access_) 693 return true; 694 695 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) 696 return true; 697 #else 698 #if defined(OS_CHROMEOS) 699 // If we're running Chrome for ChromeOS on Linux, we want to allow file 700 // access. 701 if (!base::SysInfo::IsRunningOnChromeOS() || 702 CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType)) { 703 return true; 704 } 705 706 // Use a whitelist to only allow access to files residing in the list of 707 // directories below. 708 static const char* const kLocalAccessWhiteList[] = { 709 "/home/chronos/user/Downloads", 710 "/home/chronos/user/log", 711 "/home/chronos/user/WebRTC Logs", 712 "/media", 713 "/opt/oem", 714 "/usr/share/chromeos-assets", 715 "/tmp", 716 "/var/log", 717 }; 718 719 // The actual location of "/home/chronos/user/Xyz" is the Xyz directory under 720 // the profile path ("/home/chronos/user' is a hard link to current primary 721 // logged in profile.) For the support of multi-profile sessions, we are 722 // switching to use explicit "$PROFILE_PATH/Xyz" path and here whitelist such 723 // access. 724 if (!profile_path_.empty()) { 725 const base::FilePath downloads = profile_path_.AppendASCII("Downloads"); 726 if (downloads == path.StripTrailingSeparators() || downloads.IsParent(path)) 727 return true; 728 const base::FilePath webrtc_logs = profile_path_.AppendASCII("WebRTC Logs"); 729 if (webrtc_logs == path.StripTrailingSeparators() || 730 webrtc_logs.IsParent(path)) { 731 return true; 732 } 733 } 734 #elif defined(OS_ANDROID) 735 // Access to files in external storage is allowed. 736 base::FilePath external_storage_path; 737 PathService::Get(base::DIR_ANDROID_EXTERNAL_STORAGE, &external_storage_path); 738 if (external_storage_path.IsParent(path)) 739 return true; 740 741 // Whitelist of other allowed directories. 742 static const char* const kLocalAccessWhiteList[] = { 743 "/sdcard", 744 "/mnt/sdcard", 745 }; 746 #endif 747 748 for (size_t i = 0; i < arraysize(kLocalAccessWhiteList); ++i) { 749 const base::FilePath white_listed_path(kLocalAccessWhiteList[i]); 750 // base::FilePath::operator== should probably handle trailing separators. 751 if (white_listed_path == path.StripTrailingSeparators() || 752 white_listed_path.IsParent(path)) { 753 return true; 754 } 755 } 756 757 DVLOG(1) << "File access denied - " << path.value().c_str(); 758 return false; 759 #endif // !defined(OS_CHROMEOS) && !defined(OS_ANDROID) 760 } 761 762 bool ChromeNetworkDelegate::OnCanThrottleRequest( 763 const net::URLRequest& request) const { 764 if (g_never_throttle_requests_) 765 return false; 766 return request.first_party_for_cookies().scheme() == 767 extensions::kExtensionScheme; 768 } 769 770 bool ChromeNetworkDelegate::OnCanEnablePrivacyMode( 771 const GURL& url, 772 const GURL& first_party_for_cookies) const { 773 // NULL during tests, or when we're running in the system context. 774 if (!cookie_settings_.get()) 775 return false; 776 777 bool reading_cookie_allowed = cookie_settings_->IsReadingCookieAllowed( 778 url, first_party_for_cookies); 779 bool setting_cookie_allowed = cookie_settings_->IsSettingCookieAllowed( 780 url, first_party_for_cookies); 781 bool privacy_mode = !(reading_cookie_allowed && setting_cookie_allowed); 782 return privacy_mode; 783 } 784 785 int ChromeNetworkDelegate::OnBeforeSocketStreamConnect( 786 net::SocketStream* socket, 787 const net::CompletionCallback& callback) { 788 #if defined(ENABLE_CONFIGURATION_POLICY) 789 if (url_blacklist_manager_ && 790 url_blacklist_manager_->IsURLBlocked(socket->url())) { 791 // URL access blocked by policy. 792 socket->net_log()->AddEvent( 793 net::NetLog::TYPE_CHROME_POLICY_ABORTED_REQUEST, 794 net::NetLog::StringCallback("url", 795 &socket->url().possibly_invalid_spec())); 796 return net::ERR_BLOCKED_BY_ADMINISTRATOR; 797 } 798 #endif 799 return net::OK; 800 } 801 802 void ChromeNetworkDelegate::AccumulateContentLength( 803 int64 received_content_length, 804 int64 original_content_length, 805 data_reduction_proxy::DataReductionProxyRequestType request_type) { 806 DCHECK_GE(received_content_length, 0); 807 DCHECK_GE(original_content_length, 0); 808 StoreAccumulatedContentLength(received_content_length, 809 original_content_length, 810 request_type, 811 reinterpret_cast<Profile*>(profile_)); 812 received_content_length_ += received_content_length; 813 original_content_length_ += original_content_length; 814 } 815