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

Side by Side Diff: content/browser/download/base_file.cc

Issue 9223019: Added net logging to BaseFile. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Minor cleanup Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/download/base_file.h" 5 #include "content/browser/download/base_file.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/format_macros.h" 8 #include "base/format_macros.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/pickle.h" 10 #include "base/pickle.h"
11 #include "base/stringprintf.h" 11 #include "base/stringprintf.h"
12 #include "base/threading/thread_restrictions.h" 12 #include "base/threading/thread_restrictions.h"
13 #include "base/utf_string_conversions.h" 13 #include "base/utf_string_conversions.h"
14 #include "content/browser/download/download_net_log_parameters.h"
14 #include "content/browser/download/download_stats.h" 15 #include "content/browser/download/download_stats.h"
15 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/content_browser_client.h" 17 #include "content/public/browser/content_browser_client.h"
17 #include "crypto/secure_hash.h" 18 #include "crypto/secure_hash.h"
18 #include "net/base/file_stream.h" 19 #include "net/base/file_stream.h"
19 #include "net/base/net_errors.h" 20 #include "net/base/net_errors.h"
20 21
21 #if defined(OS_WIN) 22 #if defined(OS_WIN)
22 #include <windows.h> 23 #include <windows.h>
23 #include <shellapi.h> 24 #include <shellapi.h>
24 25
25 #include "content/browser/safe_util_win.h" 26 #include "content/browser/safe_util_win.h"
26 #elif defined(OS_MACOSX) 27 #elif defined(OS_MACOSX)
27 #include "content/browser/file_metadata_mac.h" 28 #include "content/browser/file_metadata_mac.h"
28 #endif 29 #endif
29 30
30 using content::BrowserThread; 31 using content::BrowserThread;
31 32
32 namespace { 33 namespace {
33 34
34 #define LOG_ERROR(o, e) LogError(__FILE__, __LINE__, __FUNCTION__, o, e) 35 #define LOG_ERROR(o, e) \
36 LogError(__FILE__, __LINE__, __FUNCTION__, bound_net_log_, o, e)
35 37
36 // Logs the value and passes error on through, converting to a |net::Error|. 38 // Logs the value and passes error on through, converting to a |net::Error|.
37 // Returns |ERR_UNEXPECTED| if the value is not in the enum. 39 // Returns |ERR_UNEXPECTED| if the value is not in the enum.
38 net::Error LogError(const char* file, int line, const char* func, 40 net::Error LogError(const char* file,
39 const char* operation, int error) { 41 int line,
42 const char* func,
43 const net::BoundNetLog& bound_net_log,
44 const char* operation,
45 int error) {
40 const char* err_string = ""; 46 const char* err_string = "";
41 net::Error net_error = net::OK; 47 net::Error net_error = net::OK;
42 48
43 #define NET_ERROR(label, value) \ 49 #define NET_ERROR(label, value) \
44 case net::ERR_##label: \ 50 case net::ERR_##label: \
45 err_string = #label; \ 51 err_string = #label; \
46 net_error = net::ERR_##label; \ 52 net_error = net::ERR_##label; \
47 break; 53 break;
48 54
49 switch (error) { 55 switch (error) {
50 case net::OK: 56 case net::OK:
51 return net::OK; 57 return net::OK;
52 58
53 #include "net/base/net_error_list.h" 59 #include "net/base/net_error_list.h"
54 60
55 default: 61 default:
56 err_string = "Unexpected enum value"; 62 err_string = "Unexpected enum value";
57 net_error = net::ERR_UNEXPECTED; 63 net_error = net::ERR_UNEXPECTED;
58 break; 64 break;
59 } 65 }
60 66
61 #undef NET_ERROR 67 #undef NET_ERROR
62 68
63 VLOG(1) << " " << func << "(): " << operation 69 VLOG(1) << " " << func << "(): " << operation
64 << "() returned error " << error << " (" << err_string << ")"; 70 << "() returned error " << error << " (" << err_string << ")";
65 71
72 bound_net_log.AddEvent(
73 net::NetLog::TYPE_DOWNLOAD_FILE_ERROR,
74 make_scoped_refptr(
75 new download_net_logs::FileErrorParameters(operation, net_error)));
76
66 return net_error; 77 return net_error;
67 } 78 }
68 79
69 #if defined(OS_WIN) 80 #if defined(OS_WIN)
70 81
71 #define SHFILE_TO_NET_ERROR(symbol, value, mapping, description) \ 82 #define SHFILE_TO_NET_ERROR(symbol, value, mapping, description) \
72 case value: return net::ERR_##mapping; 83 case value: return net::ERR_##mapping;
73 84
74 // Maps the result of a call to |SHFileOperation()| onto a |net::Error|. 85 // Maps the result of a call to |SHFileOperation()| onto a |net::Error|.
75 // 86 //
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 200
190 // This will initialize the entire array to zero. 201 // This will initialize the entire array to zero.
191 const unsigned char BaseFile::kEmptySha256Hash[] = { 0 }; 202 const unsigned char BaseFile::kEmptySha256Hash[] = { 0 };
192 203
193 BaseFile::BaseFile(const FilePath& full_path, 204 BaseFile::BaseFile(const FilePath& full_path,
194 const GURL& source_url, 205 const GURL& source_url,
195 const GURL& referrer_url, 206 const GURL& referrer_url,
196 int64 received_bytes, 207 int64 received_bytes,
197 bool calculate_hash, 208 bool calculate_hash,
198 const std::string& hash_state, 209 const std::string& hash_state,
199 const linked_ptr<net::FileStream>& file_stream) 210 const linked_ptr<net::FileStream>& file_stream,
211 const net::BoundNetLog& bound_net_log)
200 : full_path_(full_path), 212 : full_path_(full_path),
201 source_url_(source_url), 213 source_url_(source_url),
202 referrer_url_(referrer_url), 214 referrer_url_(referrer_url),
203 file_stream_(file_stream), 215 file_stream_(file_stream),
204 bytes_so_far_(received_bytes), 216 bytes_so_far_(received_bytes),
205 start_tick_(base::TimeTicks::Now()), 217 start_tick_(base::TimeTicks::Now()),
206 power_save_blocker_(PowerSaveBlocker::kPowerSaveBlockPreventSystemSleep), 218 power_save_blocker_(PowerSaveBlocker::kPowerSaveBlockPreventSystemSleep),
207 calculate_hash_(calculate_hash), 219 calculate_hash_(calculate_hash),
208 detached_(false) { 220 detached_(false),
221 bound_net_log_(bound_net_log) {
209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 222 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
210 memcpy(sha256_hash_, kEmptySha256Hash, kSha256HashLen); 223 memcpy(sha256_hash_, kEmptySha256Hash, kSha256HashLen);
211 if (file_stream_.get()) 224 if (file_stream_.get()) {
225 file_stream_->SetBoundNetLogSource(bound_net_log_);
212 file_stream_->EnableErrorStatistics(); 226 file_stream_->EnableErrorStatistics();
227 }
213 228
214 if (calculate_hash_) { 229 if (calculate_hash_) {
215 secure_hash_.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256)); 230 secure_hash_.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256));
216 if ((bytes_so_far_ > 0) && // Not starting at the beginning. 231 if ((bytes_so_far_ > 0) && // Not starting at the beginning.
217 (hash_state != "") && // Reasonably sure we have a hash state. 232 (hash_state != "") && // Reasonably sure we have a hash state.
218 (!IsEmptyHash(hash_state))) { 233 (!IsEmptyHash(hash_state))) {
219 SetHashState(hash_state); 234 SetHashState(hash_state);
220 } 235 }
221 } 236 }
222 } 237 }
(...skipping 23 matching lines...) Expand all
246 261
247 return Open(); 262 return Open();
248 } 263 }
249 264
250 net::Error BaseFile::AppendDataToFile(const char* data, size_t data_len) { 265 net::Error BaseFile::AppendDataToFile(const char* data, size_t data_len) {
251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
252 DCHECK(!detached_); 267 DCHECK(!detached_);
253 268
254 // NOTE(benwells): The above DCHECK won't be present in release builds, 269 // NOTE(benwells): The above DCHECK won't be present in release builds,
255 // so we log any occurences to see how common this error is in the wild. 270 // so we log any occurences to see how common this error is in the wild.
256 if (detached_) 271 if (detached_) {
257 download_stats::RecordDownloadCount( 272 download_stats::RecordDownloadCount(
258 download_stats::APPEND_TO_DETACHED_FILE_COUNT); 273 download_stats::APPEND_TO_DETACHED_FILE_COUNT);
274 }
275
276 bound_net_log_.AddEvent(
mmenke1 2012/02/03 18:32:32 This should be wrapped in: if (bound_net_log_.IsL
ahendrickson 2012/02/04 05:27:14 Done.
277 net::NetLog::TYPE_DOWNLOAD_FILE_WRITTEN,
278 make_scoped_refptr(
279 new download_net_logs::FileWrittenParameters(
280 data_len, bytes_so_far_)));
259 281
260 if (!file_stream_.get()) 282 if (!file_stream_.get())
261 return LOG_ERROR("get", net::ERR_INVALID_HANDLE); 283 return LOG_ERROR("get", net::ERR_INVALID_HANDLE);
262 284
263 // TODO(phajdan.jr): get rid of this check. 285 // TODO(phajdan.jr): get rid of this check.
264 if (data_len == 0) 286 if (data_len == 0)
265 return net::OK; 287 return net::OK;
266 288
267 // The Write call below is not guaranteed to write all the data. 289 // The Write call below is not guaranteed to write all the data.
268 size_t write_count = 0; 290 size_t write_count = 0;
(...skipping 16 matching lines...) Expand all
285 } 307 }
286 308
287 // Update status. 309 // Update status.
288 size_t write_size = static_cast<size_t>(write_result); 310 size_t write_size = static_cast<size_t>(write_result);
289 DCHECK_LE(write_size, len); 311 DCHECK_LE(write_size, len);
290 len -= write_size; 312 len -= write_size;
291 current_data += write_size; 313 current_data += write_size;
292 bytes_so_far_ += write_size; 314 bytes_so_far_ += write_size;
293 } 315 }
294 316
295 // TODO(ahendrickson) -- Uncomment these when the functions are available. 317 download_stats::RecordDownloadWriteSize(data_len);
296 download_stats::RecordDownloadWriteSize(data_len); 318 download_stats::RecordDownloadWriteLoopCount(write_count);
297 download_stats::RecordDownloadWriteLoopCount(write_count);
298 319
299 if (calculate_hash_) 320 if (calculate_hash_)
300 secure_hash_->Update(data, data_len); 321 secure_hash_->Update(data, data_len);
301 322
302 return net::OK; 323 return net::OK;
303 } 324 }
304 325
305 net::Error BaseFile::Rename(const FilePath& new_path) { 326 net::Error BaseFile::Rename(const FilePath& new_path) {
306 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 327 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
307 328
308 // Save the information whether the download is in progress because 329 // Save the information whether the download is in progress because
309 // it will be overwritten by closing the file. 330 // it will be overwritten by closing the file.
310 bool saved_in_progress = in_progress(); 331 bool saved_in_progress = in_progress();
311 332
333 bound_net_log_.AddEvent(
334 net::NetLog::TYPE_DOWNLOAD_FILE_RENAMED,
335 make_scoped_refptr(
336 new download_net_logs::FileRenamedParameters(
337 full_path_.AsUTF8Unsafe(), new_path.AsUTF8Unsafe())));
338
312 // If the new path is same as the old one, there is no need to perform the 339 // If the new path is same as the old one, there is no need to perform the
313 // following renaming logic. 340 // following renaming logic.
314 if (new_path == full_path_) { 341 if (new_path == full_path_) {
315 // Don't close the file if we're not done (finished or canceled). 342 // Don't close the file if we're not done (finished or canceled).
316 if (!saved_in_progress) 343 if (!saved_in_progress)
317 Close(); 344 Close();
318 345
319 return net::OK; 346 return net::OK;
320 } 347 }
321 348
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 396
370 // We don't need to re-open the file if we're done (finished or canceled). 397 // We don't need to re-open the file if we're done (finished or canceled).
371 if (!saved_in_progress) 398 if (!saved_in_progress)
372 return net::OK; 399 return net::OK;
373 400
374 return Open(); 401 return Open();
375 } 402 }
376 403
377 void BaseFile::Detach() { 404 void BaseFile::Detach() {
378 detached_ = true; 405 detached_ = true;
406 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_FILE_DETACHED, NULL);
379 } 407 }
380 408
381 void BaseFile::Cancel() { 409 void BaseFile::Cancel() {
382 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 410 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
383 DCHECK(!detached_); 411 DCHECK(!detached_);
384 412
413 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_FILE_CANCELED, NULL);
mmenke1 2012/02/03 18:32:32 I'd suggest using the generic NetLog::TYPE_CANCELL
ahendrickson 2012/02/04 05:27:14 Done.
414
385 Close(); 415 Close();
386 416
387 if (!full_path_.empty()) 417 if (!full_path_.empty()) {
418 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_FILE_DELETED, NULL);
419
388 file_util::Delete(full_path_, false); 420 file_util::Delete(full_path_, false);
421 }
389 } 422 }
390 423
391 void BaseFile::Finish() { 424 void BaseFile::Finish() {
392 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 425 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
393 426
394 if (calculate_hash_) 427 if (calculate_hash_)
395 secure_hash_->Finish(sha256_hash_, kSha256HashLen); 428 secure_hash_->Finish(sha256_hash_, kSha256HashLen);
396 429
397 Close(); 430 Close();
398 } 431 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 UTF8ToWide(source_url_.spec())); 475 UTF8ToWide(source_url_.spec()));
443 #elif defined(OS_MACOSX) 476 #elif defined(OS_MACOSX)
444 file_metadata::AddQuarantineMetadataToFile(full_path_, source_url_, 477 file_metadata::AddQuarantineMetadataToFile(full_path_, source_url_,
445 referrer_url_); 478 referrer_url_);
446 file_metadata::AddOriginMetadataToFile(full_path_, source_url_, 479 file_metadata::AddOriginMetadataToFile(full_path_, source_url_,
447 referrer_url_); 480 referrer_url_);
448 #endif 481 #endif
449 } 482 }
450 483
451 void BaseFile::CreateFileStream() { 484 void BaseFile::CreateFileStream() {
452 file_stream_.reset(new net::FileStream(NULL)); 485 file_stream_.reset(new net::FileStream(bound_net_log_.net_log()));
486 file_stream_->SetBoundNetLogSource(bound_net_log_);
453 } 487 }
454 488
455 net::Error BaseFile::Open() { 489 net::Error BaseFile::Open() {
456 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 490 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
457 DCHECK(!detached_); 491 DCHECK(!detached_);
458 DCHECK(!full_path_.empty()); 492 DCHECK(!full_path_.empty());
459 493
494 bound_net_log_.BeginEvent(
495 net::NetLog::TYPE_DOWNLOAD_FILE_OPENED,
496 make_scoped_refptr(
497 new download_net_logs::FileOpenedParameters(
498 full_path_.AsUTF8Unsafe(), bytes_so_far_)));
499
460 // Create a new file stream if it is not provided. 500 // Create a new file stream if it is not provided.
461 if (!file_stream_.get()) { 501 if (!file_stream_.get()) {
462 CreateFileStream(); 502 CreateFileStream();
463 file_stream_->EnableErrorStatistics(); 503 file_stream_->EnableErrorStatistics();
464 int open_result = file_stream_->Open( 504 int open_result = file_stream_->Open(
465 full_path_, 505 full_path_,
466 base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE); 506 base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE);
467 if (open_result != net::OK) { 507 if (open_result != net::OK)
468 file_stream_.reset(); 508 return AbortOpen(LOG_ERROR("Open", open_result));
469 return LOG_ERROR("Open", open_result);
470 }
471 509
472 // We may be re-opening the file after rename. Always make sure we're 510 // We may be re-opening the file after rename. Always make sure we're
473 // writing at the end of the file. 511 // writing at the end of the file.
474 int64 seek_result = file_stream_->Seek(net::FROM_END, 0); 512 int64 seek_result = file_stream_->Seek(net::FROM_END, 0);
475 if (seek_result < 0) { 513 if (seek_result < 0)
476 file_stream_.reset(); 514 return AbortOpen(LOG_ERROR("Seek", seek_result));
477 return LOG_ERROR("Seek", seek_result); 515 } else {
478 } 516 file_stream_->SetBoundNetLogSource(bound_net_log_);
479 } 517 }
480 518
481 #if defined(OS_WIN) 519 #if defined(OS_WIN)
482 AnnotateWithSourceInformation(); 520 AnnotateWithSourceInformation();
483 #endif 521 #endif
522
484 return net::OK; 523 return net::OK;
485 } 524 }
486 525
526 net::Error BaseFile::AbortOpen(net::Error net_error) {
Randy Smith (Not in Mondays) 2012/02/02 20:05:54 nit: I don't think that there's particular value t
ahendrickson 2012/02/02 22:23:36 This function is called in 2 places (now 3, but I'
Randy Smith (Not in Mondays) 2012/02/03 17:02:17 This comment had two parts, and you only responded
ahendrickson 2012/02/03 17:29:32 Ah, sorry about not responding to the whitespace p
527 file_stream_.reset();
528
529 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_FILE_OPENED, NULL);
530
531 return net_error;
532 }
533
534
487 void BaseFile::Close() { 535 void BaseFile::Close() {
488 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 536 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
537
538 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_FILE_CLOSED, NULL);
539
489 if (file_stream_.get()) { 540 if (file_stream_.get()) {
490 #if defined(OS_CHROMEOS) 541 #if defined(OS_CHROMEOS)
491 // Currently we don't really care about the return value, since if it fails 542 // Currently we don't really care about the return value, since if it fails
492 // theres not much we can do. But we might in the future. 543 // theres not much we can do. But we might in the future.
493 file_stream_->Flush(); 544 file_stream_->Flush();
494 #endif 545 #endif
495 file_stream_->Close(); 546 file_stream_->Close();
496 file_stream_.reset(); 547 file_stream_.reset();
548
549 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_FILE_OPENED, NULL);
497 } 550 }
498 } 551 }
499 552
500 std::string BaseFile::DebugString() const { 553 std::string BaseFile::DebugString() const {
501 return base::StringPrintf("{ source_url_ = \"%s\"" 554 return base::StringPrintf("{ source_url_ = \"%s\""
502 " full_path_ = \"%" PRFilePath "\"" 555 " full_path_ = \"%" PRFilePath "\""
503 " bytes_so_far_ = %" PRId64 556 " bytes_so_far_ = %" PRId64
504 " detached_ = %c }", 557 " detached_ = %c }",
505 source_url_.spec().c_str(), 558 source_url_.spec().c_str(),
506 full_path_.value().c_str(), 559 full_path_.value().c_str(),
507 bytes_so_far_, 560 bytes_so_far_,
508 detached_ ? 'T' : 'F'); 561 detached_ ? 'T' : 'F');
509 } 562 }
510 563
511 int64 BaseFile::CurrentSpeedAtTime(base::TimeTicks current_time) const { 564 int64 BaseFile::CurrentSpeedAtTime(base::TimeTicks current_time) const {
512 base::TimeDelta diff = current_time - start_tick_; 565 base::TimeDelta diff = current_time - start_tick_;
513 int64 diff_ms = diff.InMilliseconds(); 566 int64 diff_ms = diff.InMilliseconds();
514 return diff_ms == 0 ? 0 : bytes_so_far() * 1000 / diff_ms; 567 return diff_ms == 0 ? 0 : bytes_so_far() * 1000 / diff_ms;
515 } 568 }
516 569
517 int64 BaseFile::CurrentSpeed() const { 570 int64 BaseFile::CurrentSpeed() const {
518 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 571 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
519 return CurrentSpeedAtTime(base::TimeTicks::Now()); 572 return CurrentSpeedAtTime(base::TimeTicks::Now());
520 } 573 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698