blob: 5dee970bafd9d2cc670c2ac12431ecc61c2b6500 [file] [log] [blame]
[email protected]9045b8822012-01-13 20:35:351// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ac039522010-06-15 16:39:442// 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
[email protected]eac11e12013-03-19 22:04:327#include <stdlib.h>
8
[email protected]d1208ba32012-11-08 11:10:339#include <vector>
10
[email protected]d8e4f132012-09-06 04:28:0511#include "base/base_paths.h"
[email protected]7a299a92012-10-24 23:54:5012#include "base/logging.h"
13#include "base/metrics/histogram.h"
[email protected]d8e4f132012-09-06 04:28:0514#include "base/path_service.h"
[email protected]3853a4c2013-02-11 17:15:5715#include "base/prefs/pref_service.h"
[email protected]0abb67122012-12-12 11:36:0516#include "base/prefs/public/pref_member.h"
[email protected]3ea1b182013-02-08 22:38:4117#include "base/strings/string_number_conversions.h"
[email protected]1988e1c2013-02-28 20:27:4218#include "base/strings/string_split.h"
[email protected]6baff0b52012-03-06 01:30:1819#include "chrome/browser/browser_process.h"
[email protected]9c8ae8c2012-03-09 13:13:3520#include "chrome/browser/content_settings/cookie_settings.h"
21#include "chrome/browser/content_settings/tab_specific_content_settings.h"
[email protected]8523ba52011-05-22 19:00:5822#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
[email protected]aa84a7e2012-03-15 21:29:0623#include "chrome/browser/extensions/api/proxy/proxy_api.h"
[email protected]2b33dcd02012-03-18 01:34:1624#include "chrome/browser/extensions/api/web_request/web_request_api.h"
[email protected]5a38dfd2012-07-23 23:22:1025#include "chrome/browser/extensions/event_router_forwarder.h"
[email protected]c357acb42011-06-09 20:52:4226#include "chrome/browser/extensions/extension_info_map.h"
[email protected]6baff0b52012-03-06 01:30:1827#include "chrome/browser/extensions/extension_process_manager.h"
[email protected]be93bba02012-10-24 16:44:0328#include "chrome/browser/extensions/extension_system.h"
[email protected]d1208ba32012-11-08 11:10:3329#include "chrome/browser/google/google_util.h"
[email protected]f53b4802012-12-20 17:04:2330#include "chrome/browser/net/connect_interceptor.h"
[email protected]a9e0d1412012-08-20 22:13:0131#include "chrome/browser/net/load_time_stats.h"
[email protected]6f4b4b42012-08-27 21:59:0732#include "chrome/browser/performance_monitor/performance_monitor.h"
[email protected]eac11e12013-03-19 22:04:3233#include "chrome/browser/prefs/scoped_user_pref_update.h"
[email protected]6baff0b52012-03-06 01:30:1834#include "chrome/browser/profiles/profile_manager.h"
[email protected]8523ba52011-05-22 19:00:5835#include "chrome/browser/task_manager/task_manager.h"
[email protected]0a8db0d2011-04-13 15:15:4036#include "chrome/common/pref_names.h"
[email protected]a1d4ab072012-06-07 13:21:1537#include "chrome/common/url_constants.h"
[email protected]c38831a12011-10-28 12:44:4938#include "content/public/browser/browser_thread.h"
[email protected]9c1662b2012-03-06 15:44:3339#include "content/public/browser/render_view_host.h"
[email protected]9c8ae8c2012-03-09 13:13:3540#include "content/public/browser/resource_request_info.h"
[email protected]885c0e92012-11-13 20:27:4241#include "extensions/common/constants.h"
[email protected]82b42302011-04-20 16:28:1642#include "net/base/host_port_pair.h"
[email protected]8202d0c2011-02-23 08:31:1443#include "net/base/net_errors.h"
[email protected]6a5f77c32011-09-04 19:19:5944#include "net/base/net_log.h"
[email protected]5b9bc352012-07-18 13:13:3445#include "net/cookies/canonical_cookie.h"
46#include "net/cookies/cookie_options.h"
[email protected]ac039522010-06-15 16:39:4447#include "net/http/http_request_headers.h"
[email protected]48944382011-04-23 13:28:1648#include "net/http/http_response_headers.h"
[email protected]aa28181e2012-06-13 00:53:5849#include "net/socket_stream/socket_stream.h"
[email protected]d05ef99c2011-02-01 21:38:1650#include "net/url_request/url_request.h"
51
[email protected]4c219e22012-05-05 19:41:0452#if defined(OS_CHROMEOS)
53#include "base/chromeos/chromeos_version.h"
[email protected]288538482012-09-06 21:09:3554#include "base/command_line.h"
55#include "chrome/common/chrome_switches.h"
[email protected]4c219e22012-05-05 19:41:0456#endif
57
[email protected]3e598ff12011-09-06 11:22:3458#if defined(ENABLE_CONFIGURATION_POLICY)
59#include "chrome/browser/policy/url_blacklist_manager.h"
60#endif
61
[email protected]631bb742011-11-02 11:29:3962using content::BrowserThread;
[email protected]eaabba22012-03-07 15:02:1163using content::RenderViewHost;
[email protected]ea114722012-03-12 01:11:2564using content::ResourceRequestInfo;
[email protected]631bb742011-11-02 11:29:3965
[email protected]d8e4f132012-09-06 04:28:0566// By default we don't allow access to all file:// urls on ChromeOS and
67// Android.
68#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
[email protected]4c219e22012-05-05 19:41:0469bool ChromeNetworkDelegate::g_allow_file_access_ = false;
70#else
71bool ChromeNetworkDelegate::g_allow_file_access_ = true;
72#endif
73
[email protected]c4a7df82012-08-09 22:48:4674// This remains false unless the --disable-extensions-http-throttling
75// flag is passed to the browser.
76bool ChromeNetworkDelegate::g_never_throttle_requests_ = false;
77
[email protected]d05ef99c2011-02-01 21:38:1678namespace {
79
[email protected]9d8cfb682012-09-13 16:48:0480const char kDNTHeader[] = "DNT";
81
[email protected]8202d0c2011-02-23 08:31:1482// If the |request| failed due to problems with a proxy, forward the error to
83// the proxy extension API.
[email protected]0651b812011-02-24 00:22:5084void ForwardProxyErrors(net::URLRequest* request,
[email protected]5a38dfd2012-07-23 23:22:1085 extensions::EventRouterForwarder* event_router,
[email protected]673514522011-07-13 18:17:1886 void* profile) {
[email protected]8202d0c2011-02-23 08:31:1487 if (request->status().status() == net::URLRequestStatus::FAILED) {
[email protected]d0cc35b2011-09-08 12:02:0588 switch (request->status().error()) {
[email protected]8202d0c2011-02-23 08:31:1489 case net::ERR_PROXY_AUTH_UNSUPPORTED:
90 case net::ERR_PROXY_CONNECTION_FAILED:
91 case net::ERR_TUNNEL_CONNECTION_FAILED:
[email protected]c454fe672012-03-12 21:18:0192 extensions::ProxyEventRouter::GetInstance()->OnProxyError(
[email protected]d0cc35b2011-09-08 12:02:0593 event_router, profile, request->status().error());
[email protected]8202d0c2011-02-23 08:31:1494 }
95 }
96}
97
[email protected]d1208ba32012-11-08 11:10:3398// Returns whether a URL parameter, |first_parameter| (e.g. foo=bar), has the
99// same key as the the |second_parameter| (e.g. foo=baz). Both parameters
100// must be in key=value form.
101bool HasSameParameterKey(const std::string& first_parameter,
102 const std::string& second_parameter) {
103 DCHECK(second_parameter.find("=") != std::string::npos);
104 // Prefix for "foo=bar" is "foo=".
105 std::string parameter_prefix = second_parameter.substr(
106 0, second_parameter.find("=") + 1);
107 return StartsWithASCII(first_parameter, parameter_prefix, false);
108}
109
110// Examines the query string containing parameters and adds the necessary ones
111// so that SafeSearch is active. |query| is the string to examine and the
112// return value is the |query| string modified such that SafeSearch is active.
113std::string AddSafeSearchParameters(const std::string& query) {
114 std::vector<std::string> new_parameters;
115 std::string safe_parameter = chrome::kSafeSearchSafeParameter;
116 std::string ssui_parameter = chrome::kSafeSearchSsuiParameter;
117
118 std::vector<std::string> parameters;
119 base::SplitString(query, '&', &parameters);
120
121 std::vector<std::string>::iterator it;
122 for (it = parameters.begin(); it < parameters.end(); ++it) {
123 if (!HasSameParameterKey(*it, safe_parameter) &&
124 !HasSameParameterKey(*it, ssui_parameter)) {
125 new_parameters.push_back(*it);
126 }
127 }
128
129 new_parameters.push_back(safe_parameter);
130 new_parameters.push_back(ssui_parameter);
131 return JoinString(new_parameters, '&');
132}
133
134// If |request| is a request to Google Web Search the function
135// enforces that the SafeSearch query parameters are set to active.
136// Sets the query part of |new_url| with the new value of the parameters.
137void ForceGoogleSafeSearch(net::URLRequest* request,
138 GURL* new_url) {
139 if (!google_util::IsGoogleSearchUrl(request->url().spec()) &&
140 !google_util::IsGoogleHomePageUrl(request->url().spec()))
141 return;
142
143 std::string query = request->url().query();
144 std::string new_query = AddSafeSearchParameters(query);
145 if (query == new_query)
146 return;
147
148 GURL::Replacements replacements;
149 replacements.SetQueryStr(new_query);
150 *new_url = request->url().ReplaceComponents(replacements);
151}
152
153// Gets called when the extensions finish work on the URL. If the extensions
154// did not do a redirect (so |new_url| is empty) then we enforce the
155// SafeSearch parameters. Otherwise we will get called again after the
156// redirect and we enforce SafeSearch then.
157void ForceGoogleSafeSearchCallbackWrapper(
158 const net::CompletionCallback& callback,
159 net::URLRequest* request,
160 GURL* new_url,
161 int rv) {
162 if (rv == net::OK && new_url->is_empty())
163 ForceGoogleSafeSearch(request, new_url);
164 callback.Run(rv);
165}
166
[email protected]6baff0b52012-03-06 01:30:18167enum RequestStatus { REQUEST_STARTED, REQUEST_DONE };
168
169// Notifies the ExtensionProcessManager that a request has started or stopped
170// for a particular RenderView.
171void NotifyEPMRequestStatus(RequestStatus status,
172 void* profile_id,
173 int process_id,
174 int render_view_id) {
175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
176 Profile* profile = reinterpret_cast<Profile*>(profile_id);
177 if (!g_browser_process->profile_manager()->IsValidProfile(profile))
178 return;
179
[email protected]e5775a52012-03-17 04:59:57180 ExtensionProcessManager* extension_process_manager =
[email protected]be93bba02012-10-24 16:44:03181 extensions::ExtensionSystem::Get(profile)->process_manager();
[email protected]e5775a52012-03-17 04:59:57182 // This may be NULL in unit tests.
183 if (!extension_process_manager)
184 return;
185
[email protected]6baff0b52012-03-06 01:30:18186 // Will be NULL if the request was not issued on behalf of a renderer (e.g. a
187 // system-level request).
[email protected]d3e898e2012-03-14 03:45:08188 RenderViewHost* render_view_host =
189 RenderViewHost::FromID(process_id, render_view_id);
[email protected]e5775a52012-03-17 04:59:57190 if (render_view_host) {
[email protected]6baff0b52012-03-06 01:30:18191 if (status == REQUEST_STARTED) {
[email protected]d3e898e2012-03-14 03:45:08192 extension_process_manager->OnNetworkRequestStarted(render_view_host);
[email protected]6baff0b52012-03-06 01:30:18193 } else if (status == REQUEST_DONE) {
[email protected]d3e898e2012-03-14 03:45:08194 extension_process_manager->OnNetworkRequestDone(render_view_host);
[email protected]6baff0b52012-03-06 01:30:18195 } else {
196 NOTREACHED();
197 }
198 }
199}
200
201void ForwardRequestStatus(
202 RequestStatus status, net::URLRequest* request, void* profile_id) {
[email protected]ea114722012-03-12 01:11:25203 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
204 if (!info)
205 return;
206
[email protected]6baff0b52012-03-06 01:30:18207 int process_id, render_view_id;
[email protected]ea114722012-03-12 01:11:25208 if (info->GetAssociatedRenderView(&process_id, &render_view_id)) {
[email protected]6baff0b52012-03-06 01:30:18209 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
210 base::Bind(&NotifyEPMRequestStatus,
211 status, profile_id, process_id, render_view_id));
212 }
213}
214
[email protected]eac11e12013-03-19 22:04:32215#if defined(OS_ANDROID)
216// Increments an int64, stored as a string, in a ListPref at the specified
217// index. The value must already exist and be a string representation of a
218// number.
219void AddInt64ToListPref(size_t index, int64 length,
220 ListPrefUpdate& list_update) {
221 int64 value = 0;
222 std::string old_string_value;
223 bool rv = list_update->GetString(index, &old_string_value);
224 DCHECK(rv);
225 if (rv) {
226 rv = base::StringToInt64(old_string_value, &value);
227 DCHECK(rv);
228 }
229 value += length;
230 list_update->Set(index, Value::CreateStringValue(base::Int64ToString(value)));
231}
232#endif // defined(OS_ANDROID)
233
[email protected]7a299a92012-10-24 23:54:50234void UpdateContentLengthPrefs(int received_content_length,
235 int original_content_length) {
236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
237 DCHECK_GE(received_content_length, 0);
238 DCHECK_GE(original_content_length, 0);
239
[email protected]a09159a2012-11-29 12:51:48240 // Can be NULL in a unit test.
241 if (!g_browser_process)
242 return;
243
[email protected]7a299a92012-10-24 23:54:50244 PrefService* prefs = g_browser_process->local_state();
[email protected]a09159a2012-11-29 12:51:48245 if (!prefs)
246 return;
[email protected]7a299a92012-10-24 23:54:50247
248 int64 total_received = prefs->GetInt64(prefs::kHttpReceivedContentLength);
249 int64 total_original = prefs->GetInt64(prefs::kHttpOriginalContentLength);
250 total_received += received_content_length;
251 total_original += original_content_length;
252 prefs->SetInt64(prefs::kHttpReceivedContentLength, total_received);
253 prefs->SetInt64(prefs::kHttpOriginalContentLength, total_original);
[email protected]eac11e12013-03-19 22:04:32254
255#if defined(OS_ANDROID)
256 base::Time now = base::Time::Now().LocalMidnight();
257 const size_t kNumDaysInHistory = 60;
258
259 // Each day, we calculate the total number of bytes received and the total
260 // size of all corresponding resources before any data-reducing recompression
261 // is applied. These values are used to compute the data savings realized
262 // by applying our compression techniques. Totals for the last
263 // |kNumDaysInHistory| days are maintained.
264 ListPrefUpdate original_update(prefs, prefs::kDailyHttpOriginalContentLength);
265 ListPrefUpdate received_update(prefs, prefs::kDailyHttpReceivedContentLength);
266
267 // Determine how many days it has been since the last update.
268 int64 then_internal = prefs->GetInt64(
269 prefs::kDailyHttpContentLengthLastUpdateDate);
270 base::Time then = base::Time::FromInternalValue(then_internal);
271 int days_since_last_update = (now - then).InDays();
272
273 if (days_since_last_update) {
274 // Record the last update time.
275 prefs->SetInt64(prefs::kDailyHttpContentLengthLastUpdateDate,
276 now.ToInternalValue());
277
278 if (days_since_last_update == -1) {
279 // The system may go backwards in time by up to a day for legitimate
280 // reasons, such as with changes to the time zone. In such cases the
281 // history is likely still valid. Shift backwards one day and retain all
282 // values.
283 original_update->Remove(kNumDaysInHistory - 1, NULL);
284 received_update->Remove(kNumDaysInHistory - 1, NULL);
285 original_update->Insert(0, new StringValue(base::Int64ToString(0)));
286 received_update->Insert(0, new StringValue(base::Int64ToString(0)));
287 days_since_last_update = 0;
288
289 } else if (days_since_last_update < -1) {
290 // Erase all entries if the system went backwards in time by more than
291 // a day.
292 original_update->Clear();
293 days_since_last_update = kNumDaysInHistory;
294 }
295
296 // Add entries for days since last update.
297 for (int i = 0;
298 i < days_since_last_update && i < static_cast<int>(kNumDaysInHistory);
299 ++i) {
300 original_update->AppendString(base::Int64ToString(0));
301 received_update->AppendString(base::Int64ToString(0));
302 }
303
304 // Maintain the invariant that there should never be more than
305 // |kNumDaysInHistory| days in the histories.
306 while (original_update->GetSize() > kNumDaysInHistory)
307 original_update->Remove(0, NULL);
308 while (received_update->GetSize() > kNumDaysInHistory)
309 received_update->Remove(0, NULL);
310 }
311 DCHECK_EQ(kNumDaysInHistory, original_update->GetSize());
312 DCHECK_EQ(kNumDaysInHistory, received_update->GetSize());
313
314 // Update the counts for the current day.
315 AddInt64ToListPref(kNumDaysInHistory - 1,
316 original_content_length, original_update);
317 AddInt64ToListPref(kNumDaysInHistory - 1,
318 received_content_length, received_update);
319#endif
[email protected]7a299a92012-10-24 23:54:50320}
321
322void StoreAccumulatedContentLength(int received_content_length,
323 int original_content_length) {
324 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
325 base::Bind(&UpdateContentLengthPrefs,
326 received_content_length, original_content_length));
327}
328
329void RecordContentLengthHistograms(
330 int64 received_content_length, int64 original_content_length) {
331#if defined(OS_ANDROID)
332 // Add the current resource to these histograms only when a valid
333 // X-Original-Content-Length header is present.
334 if (original_content_length >= 0) {
335 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthWithValidOCL",
336 received_content_length);
337 UMA_HISTOGRAM_COUNTS("Net.HttpOriginalContentLengthWithValidOCL",
338 original_content_length);
339 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthDifferenceWithValidOCL",
340 original_content_length - received_content_length);
341 } else {
342 // Presume the original content length is the same as the received content
343 // length if the X-Original-Content-Header is not present.
344 original_content_length = received_content_length;
345 }
346 UMA_HISTOGRAM_COUNTS("Net.HttpContentLength", received_content_length);
347 UMA_HISTOGRAM_COUNTS("Net.HttpOriginalContentLength",
348 original_content_length);
349 UMA_HISTOGRAM_COUNTS("Net.HttpContentLengthDifference",
350 original_content_length - received_content_length);
351#endif
352}
353
[email protected]d05ef99c2011-02-01 21:38:16354} // namespace
[email protected]ac039522010-06-15 16:39:44355
[email protected]0651b812011-02-24 00:22:50356ChromeNetworkDelegate::ChromeNetworkDelegate(
[email protected]5a38dfd2012-07-23 23:22:10357 extensions::EventRouterForwarder* event_router,
[email protected]a09159a2012-11-29 12:51:48358 BooleanPrefMember* enable_referrers)
[email protected]3ce02412011-03-01 12:01:15359 : event_router_(event_router),
[email protected]a09159a2012-11-29 12:51:48360 profile_(NULL),
[email protected]6a5f77c32011-09-04 19:19:59361 enable_referrers_(enable_referrers),
[email protected]a09159a2012-11-29 12:51:48362 enable_do_not_track_(NULL),
363 force_google_safe_search_(NULL),
364 url_blacklist_manager_(NULL),
365 load_time_stats_(NULL),
[email protected]7a299a92012-10-24 23:54:50366 received_content_length_(0),
367 original_content_length_(0) {
[email protected]4b50cb52011-03-10 00:29:37368 DCHECK(event_router);
[email protected]0a8db0d2011-04-13 15:15:40369 DCHECK(enable_referrers);
[email protected]0651b812011-02-24 00:22:50370}
371
[email protected]ac039522010-06-15 16:39:44372ChromeNetworkDelegate::~ChromeNetworkDelegate() {}
373
[email protected]a09159a2012-11-29 12:51:48374void ChromeNetworkDelegate::set_extension_info_map(
375 ExtensionInfoMap* extension_info_map) {
376 extension_info_map_ = extension_info_map;
377}
378
379void ChromeNetworkDelegate::set_cookie_settings(
380 CookieSettings* cookie_settings) {
381 cookie_settings_ = cookie_settings;
382}
383
[email protected]f53b4802012-12-20 17:04:23384void ChromeNetworkDelegate::set_predictor(
385 chrome_browser_net::Predictor* predictor) {
386 connect_interceptor_.reset(
387 new chrome_browser_net::ConnectInterceptor(predictor));
388}
389
[email protected]c4a7df82012-08-09 22:48:46390// static
[email protected]a1d4ab072012-06-07 13:21:15391void ChromeNetworkDelegate::NeverThrottleRequests() {
[email protected]c4a7df82012-08-09 22:48:46392 g_never_throttle_requests_ = true;
[email protected]a1d4ab072012-06-07 13:21:15393}
394
[email protected]0a8db0d2011-04-13 15:15:40395// static
[email protected]9d8cfb682012-09-13 16:48:04396void ChromeNetworkDelegate::InitializePrefsOnUIThread(
[email protected]0a8db0d2011-04-13 15:15:40397 BooleanPrefMember* enable_referrers,
[email protected]9d8cfb682012-09-13 16:48:04398 BooleanPrefMember* enable_do_not_track,
[email protected]d1208ba32012-11-08 11:10:33399 BooleanPrefMember* force_google_safe_search,
[email protected]0a8db0d2011-04-13 15:15:40400 PrefService* pref_service) {
401 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]96a5c342012-12-04 18:14:02402 enable_referrers->Init(prefs::kEnableReferrers, pref_service);
[email protected]6a1c98e02012-10-24 21:49:43403 enable_referrers->MoveToThread(
404 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
[email protected]9d8cfb682012-09-13 16:48:04405 if (enable_do_not_track) {
[email protected]96a5c342012-12-04 18:14:02406 enable_do_not_track->Init(prefs::kEnableDoNotTrack, pref_service);
[email protected]6a1c98e02012-10-24 21:49:43407 enable_do_not_track->MoveToThread(
408 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
[email protected]9d8cfb682012-09-13 16:48:04409 }
[email protected]d1208ba32012-11-08 11:10:33410 if (force_google_safe_search) {
[email protected]96a5c342012-12-04 18:14:02411 force_google_safe_search->Init(prefs::kForceSafeSearch, pref_service);
[email protected]d1208ba32012-11-08 11:10:33412 force_google_safe_search->MoveToThread(
413 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
414 }
[email protected]0a8db0d2011-04-13 15:15:40415}
416
[email protected]4c219e22012-05-05 19:41:04417// static
418void ChromeNetworkDelegate::AllowAccessToAllFiles() {
419 g_allow_file_access_ = true;
420}
421
[email protected]7a299a92012-10-24 23:54:50422// static
423Value* ChromeNetworkDelegate::HistoricNetworkStatsInfoToValue() {
424 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
425 PrefService* prefs = g_browser_process->local_state();
426 int64 total_received = prefs->GetInt64(prefs::kHttpReceivedContentLength);
427 int64 total_original = prefs->GetInt64(prefs::kHttpOriginalContentLength);
428
429 DictionaryValue* dict = new DictionaryValue();
[email protected]ae638fbe22012-12-07 02:57:42430 // Use strings to avoid overflow. base::Value only supports 32-bit integers.
431 dict->SetString("historic_received_content_length",
432 base::Int64ToString(total_received));
433 dict->SetString("historic_original_content_length",
434 base::Int64ToString(total_original));
[email protected]7a299a92012-10-24 23:54:50435 return dict;
436}
437
438Value* ChromeNetworkDelegate::SessionNetworkStatsInfoToValue() const {
439 DictionaryValue* dict = new DictionaryValue();
[email protected]ae638fbe22012-12-07 02:57:42440 // Use strings to avoid overflow. base::Value only supports 32-bit integers.
441 dict->SetString("session_received_content_length",
442 base::Int64ToString(received_content_length_));
443 dict->SetString("session_original_content_length",
444 base::Int64ToString(original_content_length_));
[email protected]7a299a92012-10-24 23:54:50445 return dict;
446}
447
[email protected]4875ba12011-03-30 22:31:51448int ChromeNetworkDelegate::OnBeforeURLRequest(
[email protected]4c76d7c2011-04-15 19:14:12449 net::URLRequest* request,
[email protected]084262c2011-12-01 21:12:47450 const net::CompletionCallback& callback,
[email protected]4c76d7c2011-04-15 19:14:12451 GURL* new_url) {
[email protected]3e598ff12011-09-06 11:22:34452#if defined(ENABLE_CONFIGURATION_POLICY)
[email protected]6a5f77c32011-09-04 19:19:59453 // TODO(joaodasilva): This prevents extensions from seeing URLs that are
454 // blocked. However, an extension might redirect the request to another URL,
455 // which is not blocked.
456 if (url_blacklist_manager_ &&
[email protected]74575252013-03-12 19:58:21457 url_blacklist_manager_->IsRequestBlocked(*request)) {
[email protected]6a5f77c32011-09-04 19:19:59458 // URL access blocked by policy.
[email protected]6a5f77c32011-09-04 19:19:59459 request->net_log().AddEvent(
[email protected]2fa08912012-06-14 20:56:26460 net::NetLog::TYPE_CHROME_POLICY_ABORTED_REQUEST,
461 net::NetLog::StringCallback("url",
462 &request->url().possibly_invalid_spec()));
[email protected]91468a92013-03-06 17:21:55463 return net::ERR_BLOCKED_BY_ADMINISTRATOR;
[email protected]6a5f77c32011-09-04 19:19:59464 }
[email protected]3e598ff12011-09-06 11:22:34465#endif
[email protected]6a5f77c32011-09-04 19:19:59466
[email protected]6baff0b52012-03-06 01:30:18467 ForwardRequestStatus(REQUEST_STARTED, request, profile_);
468
[email protected]0a8db0d2011-04-13 15:15:40469 if (!enable_referrers_->GetValue())
470 request->set_referrer(std::string());
[email protected]9d8cfb682012-09-13 16:48:04471 if (enable_do_not_track_ && enable_do_not_track_->GetValue())
472 request->SetExtraRequestHeaderByName(kDNTHeader, "1", true /* override */);
[email protected]d1208ba32012-11-08 11:10:33473
474 bool force_safe_search = force_google_safe_search_ &&
475 force_google_safe_search_->GetValue();
476
477 net::CompletionCallback wrapped_callback = callback;
478 if (force_safe_search) {
479 wrapped_callback = base::Bind(&ForceGoogleSafeSearchCallbackWrapper,
480 callback,
481 base::Unretained(request),
482 base::Unretained(new_url));
483 }
484
485 int rv = ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRequest(
486 profile_, extension_info_map_.get(), request, wrapped_callback,
487 new_url);
488
489 if (force_safe_search && rv == net::OK && new_url->is_empty())
490 ForceGoogleSafeSearch(request, new_url);
491
[email protected]f53b4802012-12-20 17:04:23492 if (connect_interceptor_)
493 connect_interceptor_->WitnessURLRequest(request);
494
[email protected]d1208ba32012-11-08 11:10:33495 return rv;
[email protected]d05ef99c2011-02-01 21:38:16496}
497
[email protected]4875ba12011-03-30 22:31:51498int ChromeNetworkDelegate::OnBeforeSendHeaders(
[email protected]636eccd2011-06-28 12:28:01499 net::URLRequest* request,
[email protected]084262c2011-12-01 21:12:47500 const net::CompletionCallback& callback,
[email protected]4c76d7c2011-04-15 19:14:12501 net::HttpRequestHeaders* headers) {
[email protected]4875ba12011-03-30 22:31:51502 return ExtensionWebRequestEventRouter::GetInstance()->OnBeforeSendHeaders(
[email protected]673514522011-07-13 18:17:18503 profile_, extension_info_map_.get(), request, callback, headers);
[email protected]ac039522010-06-15 16:39:44504}
[email protected]8202d0c2011-02-23 08:31:14505
[email protected]5796dc942011-07-14 19:26:10506void ChromeNetworkDelegate::OnSendHeaders(
507 net::URLRequest* request,
[email protected]783573b2011-05-13 11:05:15508 const net::HttpRequestHeaders& headers) {
[email protected]5796dc942011-07-14 19:26:10509 ExtensionWebRequestEventRouter::GetInstance()->OnSendHeaders(
510 profile_, extension_info_map_.get(), request, headers);
[email protected]82b42302011-04-20 16:28:16511}
512
[email protected]ea8141e2011-10-05 13:12:51513int ChromeNetworkDelegate::OnHeadersReceived(
514 net::URLRequest* request,
[email protected]084262c2011-12-01 21:12:47515 const net::CompletionCallback& callback,
[email protected]507af8f2012-10-20 00:42:32516 const net::HttpResponseHeaders* original_response_headers,
[email protected]ea8141e2011-10-05 13:12:51517 scoped_refptr<net::HttpResponseHeaders>* override_response_headers) {
518 return ExtensionWebRequestEventRouter::GetInstance()->OnHeadersReceived(
519 profile_, extension_info_map_.get(), request, callback,
520 original_response_headers, override_response_headers);
521}
522
[email protected]31b2e5f2011-04-20 16:58:32523void ChromeNetworkDelegate::OnBeforeRedirect(net::URLRequest* request,
524 const GURL& new_location) {
525 ExtensionWebRequestEventRouter::GetInstance()->OnBeforeRedirect(
[email protected]673514522011-07-13 18:17:18526 profile_, extension_info_map_.get(), request, new_location);
[email protected]31b2e5f2011-04-20 16:58:32527}
528
529
[email protected]8202d0c2011-02-23 08:31:14530void ChromeNetworkDelegate::OnResponseStarted(net::URLRequest* request) {
[email protected]62fecae2011-04-21 11:08:24531 ExtensionWebRequestEventRouter::GetInstance()->OnResponseStarted(
[email protected]673514522011-07-13 18:17:18532 profile_, extension_info_map_.get(), request);
533 ForwardProxyErrors(request, event_router_.get(), profile_);
[email protected]8202d0c2011-02-23 08:31:14534}
535
[email protected]8523ba52011-05-22 19:00:58536void ChromeNetworkDelegate::OnRawBytesRead(const net::URLRequest& request,
537 int bytes_read) {
[email protected]6f4b4b42012-08-27 21:59:07538 performance_monitor::PerformanceMonitor::GetInstance()->BytesReadOnIOThread(
539 request, bytes_read);
540
[email protected]44879ed2012-04-06 01:11:02541#if defined(ENABLE_TASK_MANAGER)
[email protected]8523ba52011-05-22 19:00:58542 TaskManager::GetInstance()->model()->NotifyBytesRead(request, bytes_read);
[email protected]44879ed2012-04-06 01:11:02543#endif // defined(ENABLE_TASK_MANAGER)
[email protected]8523ba52011-05-22 19:00:58544}
545
[email protected]9045b8822012-01-13 20:35:35546void ChromeNetworkDelegate::OnCompleted(net::URLRequest* request,
547 bool started) {
[email protected]2756a8e2012-09-07 18:24:29548 if (request->status().status() == net::URLRequestStatus::SUCCESS) {
[email protected]7a299a92012-10-24 23:54:50549 // For better accuracy, we use the actual bytes read instead of the length
550 // specified with the Content-Length header, which may be inaccurate,
551 // or missing, as is the case with chunked encoding.
552 int64 received_content_length = request->received_response_content_length();
553
554 // Only record for http or https urls.
555 bool is_http = request->url().SchemeIs("http");
556 bool is_https = request->url().SchemeIs("https");
557
558 if (!request->was_cached() && // Don't record cached content
559 received_content_length && // Zero-byte responses aren't useful.
560 (is_http || is_https)) { // Only record for HTTP or HTTPS urls.
561 int64 original_content_length =
562 request->response_info().headers->GetInt64HeaderValue(
563 "x-original-content-length");
564 // Since there was no indication of the original content length, presume
565 // it is no different from the number of bytes read.
566 int64 adjusted_original_content_length = original_content_length;
567 if (adjusted_original_content_length == -1)
568 adjusted_original_content_length = received_content_length;
569 AccumulateContentLength(received_content_length,
570 adjusted_original_content_length);
571 RecordContentLengthHistograms(received_content_length,
572 original_content_length);
573 DVLOG(2) << __FUNCTION__
574 << " received content length: " << received_content_length
575 << " original content length: " << original_content_length
576 << " url: " << request->url();
577 }
578
[email protected]48944382011-04-23 13:28:16579 bool is_redirect = request->response_headers() &&
580 net::HttpResponseHeaders::IsRedirectResponseCode(
581 request->response_headers()->response_code());
582 if (!is_redirect) {
583 ExtensionWebRequestEventRouter::GetInstance()->OnCompleted(
[email protected]673514522011-07-13 18:17:18584 profile_, extension_info_map_.get(), request);
[email protected]48944382011-04-23 13:28:16585 }
[email protected]a83dd332011-07-13 10:41:01586 } else if (request->status().status() == net::URLRequestStatus::FAILED ||
587 request->status().status() == net::URLRequestStatus::CANCELED) {
[email protected]05b6ab42011-04-23 13:46:04588 ExtensionWebRequestEventRouter::GetInstance()->OnErrorOccurred(
[email protected]9045b8822012-01-13 20:35:35589 profile_, extension_info_map_.get(), request, started);
[email protected]a83dd332011-07-13 10:41:01590 } else {
591 NOTREACHED();
[email protected]48944382011-04-23 13:28:16592 }
[email protected]673514522011-07-13 18:17:18593 ForwardProxyErrors(request, event_router_.get(), profile_);
[email protected]6baff0b52012-03-06 01:30:18594
595 ForwardRequestStatus(REQUEST_DONE, request, profile_);
[email protected]8202d0c2011-02-23 08:31:14596}
[email protected]4b50cb52011-03-10 00:29:37597
[email protected]4875ba12011-03-30 22:31:51598void ChromeNetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) {
599 ExtensionWebRequestEventRouter::GetInstance()->OnURLRequestDestroyed(
[email protected]673514522011-07-13 18:17:18600 profile_, request);
[email protected]16d5c72b2012-09-14 20:42:37601 if (load_time_stats_)
602 load_time_stats_->OnURLRequestDestroyed(*request);
[email protected]4875ba12011-03-30 22:31:51603}
604
[email protected]82a37672011-05-03 12:02:41605void ChromeNetworkDelegate::OnPACScriptError(int line_number,
606 const string16& error) {
[email protected]c454fe672012-03-12 21:18:01607 extensions::ProxyEventRouter::GetInstance()->OnPACScriptError(
[email protected]673514522011-07-13 18:17:18608 event_router_.get(), profile_, line_number, error);
[email protected]82a37672011-05-03 12:02:41609}
[email protected]7efc582d2011-08-03 20:46:35610
[email protected]c2911d72011-10-03 22:16:36611net::NetworkDelegate::AuthRequiredResponse
612ChromeNetworkDelegate::OnAuthRequired(
[email protected]7efc582d2011-08-03 20:46:35613 net::URLRequest* request,
[email protected]c2911d72011-10-03 22:16:36614 const net::AuthChallengeInfo& auth_info,
615 const AuthCallback& callback,
616 net::AuthCredentials* credentials) {
[email protected]90449ab2011-10-11 15:36:45617 return ExtensionWebRequestEventRouter::GetInstance()->OnAuthRequired(
618 profile_, extension_info_map_.get(), request, auth_info,
619 callback, credentials);
[email protected]7efc582d2011-08-03 20:46:35620}
[email protected]9c8ae8c2012-03-09 13:13:35621
[email protected]4c219e22012-05-05 19:41:04622bool ChromeNetworkDelegate::OnCanGetCookies(
623 const net::URLRequest& request,
[email protected]9c8ae8c2012-03-09 13:13:35624 const net::CookieList& cookie_list) {
625 // NULL during tests, or when we're running in the system context.
626 if (!cookie_settings_)
627 return true;
628
629 bool allow = cookie_settings_->IsReadingCookieAllowed(
[email protected]4c219e22012-05-05 19:41:04630 request.url(), request.first_party_for_cookies());
[email protected]9c8ae8c2012-03-09 13:13:35631
632 int render_process_id = -1;
633 int render_view_id = -1;
634 if (content::ResourceRequestInfo::GetRenderViewForRequest(
[email protected]4c219e22012-05-05 19:41:04635 &request, &render_process_id, &render_view_id)) {
[email protected]9c8ae8c2012-03-09 13:13:35636 BrowserThread::PostTask(
637 BrowserThread::UI, FROM_HERE,
638 base::Bind(&TabSpecificContentSettings::CookiesRead,
639 render_process_id, render_view_id,
[email protected]4c219e22012-05-05 19:41:04640 request.url(), request.first_party_for_cookies(),
[email protected]fd473d12012-04-05 11:38:43641 cookie_list, !allow));
[email protected]9c8ae8c2012-03-09 13:13:35642 }
643
644 return allow;
645}
646
[email protected]4c219e22012-05-05 19:41:04647bool ChromeNetworkDelegate::OnCanSetCookie(const net::URLRequest& request,
648 const std::string& cookie_line,
649 net::CookieOptions* options) {
[email protected]9c8ae8c2012-03-09 13:13:35650 // NULL during tests, or when we're running in the system context.
651 if (!cookie_settings_)
652 return true;
653
654 bool allow = cookie_settings_->IsSettingCookieAllowed(
[email protected]4c219e22012-05-05 19:41:04655 request.url(), request.first_party_for_cookies());
[email protected]9c8ae8c2012-03-09 13:13:35656
[email protected]9c8ae8c2012-03-09 13:13:35657 int render_process_id = -1;
658 int render_view_id = -1;
659 if (content::ResourceRequestInfo::GetRenderViewForRequest(
[email protected]4c219e22012-05-05 19:41:04660 &request, &render_process_id, &render_view_id)) {
[email protected]9c8ae8c2012-03-09 13:13:35661 BrowserThread::PostTask(
662 BrowserThread::UI, FROM_HERE,
663 base::Bind(&TabSpecificContentSettings::CookieChanged,
664 render_process_id, render_view_id,
[email protected]4c219e22012-05-05 19:41:04665 request.url(), request.first_party_for_cookies(),
[email protected]fd473d12012-04-05 11:38:43666 cookie_line, *options, !allow));
[email protected]9c8ae8c2012-03-09 13:13:35667 }
668
669 return allow;
670}
[email protected]4c219e22012-05-05 19:41:04671
672bool ChromeNetworkDelegate::OnCanAccessFile(const net::URLRequest& request,
[email protected]650b2d52013-02-10 03:41:45673 const base::FilePath& path) const {
[email protected]4c219e22012-05-05 19:41:04674 if (g_allow_file_access_)
675 return true;
676
[email protected]d8e4f132012-09-06 04:28:05677#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
678 return true;
679#else
[email protected]4c219e22012-05-05 19:41:04680#if defined(OS_CHROMEOS)
[email protected]d8e4f132012-09-06 04:28:05681 // If we're running Chrome for ChromeOS on Linux, we want to allow file
682 // access.
[email protected]288538482012-09-06 21:09:35683 if (!base::chromeos::IsRunningOnChromeOS() ||
684 CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType)) {
[email protected]d8e4f132012-09-06 04:28:05685 return true;
[email protected]288538482012-09-06 21:09:35686 }
[email protected]d8e4f132012-09-06 04:28:05687
688 // Use a whitelist to only allow access to files residing in the list of
689 // directories below.
[email protected]4c219e22012-05-05 19:41:04690 static const char* const kLocalAccessWhiteList[] = {
691 "/home/chronos/user/Downloads",
692 "/home/chronos/user/log",
693 "/media",
694 "/opt/oem",
695 "/usr/share/chromeos-assets",
696 "/tmp",
697 "/var/log",
698 };
[email protected]d8e4f132012-09-06 04:28:05699#elif defined(OS_ANDROID)
700 // Access to files in external storage is allowed.
[email protected]650b2d52013-02-10 03:41:45701 base::FilePath external_storage_path;
[email protected]d8e4f132012-09-06 04:28:05702 PathService::Get(base::DIR_ANDROID_EXTERNAL_STORAGE, &external_storage_path);
703 if (external_storage_path.IsParent(path))
[email protected]4c219e22012-05-05 19:41:04704 return true;
705
[email protected]d8e4f132012-09-06 04:28:05706 // Whitelist of other allowed directories.
707 static const char* const kLocalAccessWhiteList[] = {
708 "/sdcard",
709 "/mnt/sdcard",
710 };
711#endif
712
[email protected]4c219e22012-05-05 19:41:04713 for (size_t i = 0; i < arraysize(kLocalAccessWhiteList); ++i) {
[email protected]650b2d52013-02-10 03:41:45714 const base::FilePath white_listed_path(kLocalAccessWhiteList[i]);
715 // base::FilePath::operator== should probably handle trailing separators.
[email protected]4c219e22012-05-05 19:41:04716 if (white_listed_path == path.StripTrailingSeparators() ||
717 white_listed_path.IsParent(path)) {
718 return true;
719 }
720 }
[email protected]d8e4f132012-09-06 04:28:05721
[email protected]288538482012-09-06 21:09:35722 DVLOG(1) << "File access denied - " << path.value().c_str();
[email protected]4c219e22012-05-05 19:41:04723 return false;
[email protected]d8e4f132012-09-06 04:28:05724#endif // !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
[email protected]4c219e22012-05-05 19:41:04725}
[email protected]a1d4ab072012-06-07 13:21:15726
727bool ChromeNetworkDelegate::OnCanThrottleRequest(
728 const net::URLRequest& request) const {
[email protected]c4a7df82012-08-09 22:48:46729 if (g_never_throttle_requests_) {
[email protected]a1d4ab072012-06-07 13:21:15730 return false;
731 }
732
[email protected]c4a7df82012-08-09 22:48:46733 return request.first_party_for_cookies().scheme() ==
[email protected]885c0e92012-11-13 20:27:42734 extensions::kExtensionScheme;
[email protected]a1d4ab072012-06-07 13:21:15735}
[email protected]aa28181e2012-06-13 00:53:58736
737int ChromeNetworkDelegate::OnBeforeSocketStreamConnect(
738 net::SocketStream* socket,
739 const net::CompletionCallback& callback) {
740#if defined(ENABLE_CONFIGURATION_POLICY)
741 if (url_blacklist_manager_ &&
742 url_blacklist_manager_->IsURLBlocked(socket->url())) {
743 // URL access blocked by policy.
[email protected]aa28181e2012-06-13 00:53:58744 socket->net_log()->AddEvent(
[email protected]2fa08912012-06-14 20:56:26745 net::NetLog::TYPE_CHROME_POLICY_ABORTED_REQUEST,
746 net::NetLog::StringCallback("url",
747 &socket->url().possibly_invalid_spec()));
[email protected]91468a92013-03-06 17:21:55748 return net::ERR_BLOCKED_BY_ADMINISTRATOR;
[email protected]aa28181e2012-06-13 00:53:58749 }
750#endif
751 return net::OK;
752}
[email protected]5a07c192012-07-30 20:18:22753
[email protected]a9e0d1412012-08-20 22:13:01754void ChromeNetworkDelegate::OnRequestWaitStateChange(
[email protected]5a07c192012-07-30 20:18:22755 const net::URLRequest& request,
[email protected]a9e0d1412012-08-20 22:13:01756 RequestWaitState state) {
757 if (load_time_stats_)
758 load_time_stats_->OnRequestWaitStateChange(request, state);
[email protected]5a07c192012-07-30 20:18:22759}
[email protected]7a299a92012-10-24 23:54:50760
761void ChromeNetworkDelegate::AccumulateContentLength(
762 int64 received_content_length, int64 original_content_length) {
763 DCHECK_GE(received_content_length, 0);
764 DCHECK_GE(original_content_length, 0);
765 StoreAccumulatedContentLength(received_content_length,
766 original_content_length);
767 received_content_length_ += received_content_length;
768 original_content_length_ += original_content_length;
769}