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

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 if (bound_net_log_.IsLoggingAllEvents()) {
277 bound_net_log_.AddEvent(
278 net::NetLog::TYPE_DOWNLOAD_FILE_WRITTEN,
mmenke 2012/02/04 05:49:45 nit: Since this is logged before the write, which
ahendrickson 2012/02/04 19:27:56 I'd prefer not to.
279 make_scoped_refptr(new net::NetLogIntegerParameter(
280 "byte_count", data_len)));
281 }
259 282
260 if (!file_stream_.get()) 283 if (!file_stream_.get())
261 return LOG_ERROR("get", net::ERR_INVALID_HANDLE); 284 return LOG_ERROR("get", net::ERR_INVALID_HANDLE);
262 285
263 // TODO(phajdan.jr): get rid of this check. 286 // TODO(phajdan.jr): get rid of this check.
264 if (data_len == 0) 287 if (data_len == 0)
265 return net::OK; 288 return net::OK;
266 289
267 // The Write call below is not guaranteed to write all the data. 290 // The Write call below is not guaranteed to write all the data.
268 size_t write_count = 0; 291 size_t write_count = 0;
(...skipping 16 matching lines...) Expand all
285 } 308 }
286 309
287 // Update status. 310 // Update status.
288 size_t write_size = static_cast<size_t>(write_result); 311 size_t write_size = static_cast<size_t>(write_result);
289 DCHECK_LE(write_size, len); 312 DCHECK_LE(write_size, len);
290 len -= write_size; 313 len -= write_size;
291 current_data += write_size; 314 current_data += write_size;
292 bytes_so_far_ += write_size; 315 bytes_so_far_ += write_size;
293 } 316 }
294 317
295 // TODO(ahendrickson) -- Uncomment these when the functions are available. 318 download_stats::RecordDownloadWriteSize(data_len);
296 download_stats::RecordDownloadWriteSize(data_len); 319 download_stats::RecordDownloadWriteLoopCount(write_count);
297 download_stats::RecordDownloadWriteLoopCount(write_count);
298 320
299 if (calculate_hash_) 321 if (calculate_hash_)
300 secure_hash_->Update(data, data_len); 322 secure_hash_->Update(data, data_len);
301 323
302 return net::OK; 324 return net::OK;
303 } 325 }
304 326
305 net::Error BaseFile::Rename(const FilePath& new_path) { 327 net::Error BaseFile::Rename(const FilePath& new_path) {
306 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 328 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
307 329
308 // Save the information whether the download is in progress because 330 // Save the information whether the download is in progress because
309 // it will be overwritten by closing the file. 331 // it will be overwritten by closing the file.
310 bool saved_in_progress = in_progress(); 332 bool saved_in_progress = in_progress();
311 333
334 bound_net_log_.AddEvent(
335 net::NetLog::TYPE_DOWNLOAD_FILE_RENAMED,
336 make_scoped_refptr(
337 new download_net_logs::FileRenamedParameters(
338 full_path_.AsUTF8Unsafe(), new_path.AsUTF8Unsafe())));
339
312 // If the new path is same as the old one, there is no need to perform the 340 // If the new path is same as the old one, there is no need to perform the
313 // following renaming logic. 341 // following renaming logic.
314 if (new_path == full_path_) { 342 if (new_path == full_path_) {
315 // Don't close the file if we're not done (finished or canceled). 343 // Don't close the file if we're not done (finished or canceled).
316 if (!saved_in_progress) 344 if (!saved_in_progress)
317 Close(); 345 Close();
318 346
319 return net::OK; 347 return net::OK;
320 } 348 }
321 349
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 397
370 // We don't need to re-open the file if we're done (finished or canceled). 398 // We don't need to re-open the file if we're done (finished or canceled).
371 if (!saved_in_progress) 399 if (!saved_in_progress)
372 return net::OK; 400 return net::OK;
373 401
374 return Open(); 402 return Open();
375 } 403 }
376 404
377 void BaseFile::Detach() { 405 void BaseFile::Detach() {
378 detached_ = true; 406 detached_ = true;
407 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_FILE_DETACHED, NULL);
379 } 408 }
380 409
381 void BaseFile::Cancel() { 410 void BaseFile::Cancel() {
382 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 411 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
383 DCHECK(!detached_); 412 DCHECK(!detached_);
384 413
414 bound_net_log_.AddEvent(net::NetLog::TYPE_CANCELLED, NULL);
415
385 Close(); 416 Close();
386 417
387 if (!full_path_.empty()) 418 if (!full_path_.empty()) {
419 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_FILE_DELETED, NULL);
420
388 file_util::Delete(full_path_, false); 421 file_util::Delete(full_path_, false);
422 }
389 } 423 }
390 424
391 void BaseFile::Finish() { 425 void BaseFile::Finish() {
392 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 426 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
393 427
394 if (calculate_hash_) 428 if (calculate_hash_)
395 secure_hash_->Finish(sha256_hash_, kSha256HashLen); 429 secure_hash_->Finish(sha256_hash_, kSha256HashLen);
396 430
397 Close(); 431 Close();
398 } 432 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 UTF8ToWide(source_url_.spec())); 476 UTF8ToWide(source_url_.spec()));
443 #elif defined(OS_MACOSX) 477 #elif defined(OS_MACOSX)
444 file_metadata::AddQuarantineMetadataToFile(full_path_, source_url_, 478 file_metadata::AddQuarantineMetadataToFile(full_path_, source_url_,
445 referrer_url_); 479 referrer_url_);
446 file_metadata::AddOriginMetadataToFile(full_path_, source_url_, 480 file_metadata::AddOriginMetadataToFile(full_path_, source_url_,
447 referrer_url_); 481 referrer_url_);
448 #endif 482 #endif
449 } 483 }
450 484
451 void BaseFile::CreateFileStream() { 485 void BaseFile::CreateFileStream() {
452 file_stream_.reset(new net::FileStream(NULL)); 486 file_stream_.reset(new net::FileStream(bound_net_log_.net_log()));
487 file_stream_->SetBoundNetLogSource(bound_net_log_);
453 } 488 }
454 489
455 net::Error BaseFile::Open() { 490 net::Error BaseFile::Open() {
456 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 491 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
457 DCHECK(!detached_); 492 DCHECK(!detached_);
458 DCHECK(!full_path_.empty()); 493 DCHECK(!full_path_.empty());
459 494
495 bound_net_log_.BeginEvent(
496 net::NetLog::TYPE_DOWNLOAD_FILE_OPENED,
497 make_scoped_refptr(
498 new download_net_logs::FileOpenedParameters(
499 full_path_.AsUTF8Unsafe(), bytes_so_far_)));
500
460 // Create a new file stream if it is not provided. 501 // Create a new file stream if it is not provided.
461 if (!file_stream_.get()) { 502 if (!file_stream_.get()) {
462 CreateFileStream(); 503 CreateFileStream();
463 file_stream_->EnableErrorStatistics(); 504 file_stream_->EnableErrorStatistics();
464 int open_result = file_stream_->Open( 505 int open_result = file_stream_->Open(
465 full_path_, 506 full_path_,
466 base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE); 507 base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE);
467 if (open_result != net::OK) { 508 if (open_result != net::OK)
468 file_stream_.reset(); 509 return ClearStream(LOG_ERROR("Open", open_result));
469 return LOG_ERROR("Open", open_result);
470 }
471 510
472 // We may be re-opening the file after rename. Always make sure we're 511 // We may be re-opening the file after rename. Always make sure we're
473 // writing at the end of the file. 512 // writing at the end of the file.
474 int64 seek_result = file_stream_->Seek(net::FROM_END, 0); 513 int64 seek_result = file_stream_->Seek(net::FROM_END, 0);
475 if (seek_result < 0) { 514 if (seek_result < 0)
476 file_stream_.reset(); 515 return ClearStream(LOG_ERROR("Seek", seek_result));
477 return LOG_ERROR("Seek", seek_result); 516 } else {
478 } 517 file_stream_->SetBoundNetLogSource(bound_net_log_);
479 } 518 }
480 519
481 #if defined(OS_WIN) 520 #if defined(OS_WIN)
482 AnnotateWithSourceInformation(); 521 AnnotateWithSourceInformation();
483 #endif 522 #endif
523
484 return net::OK; 524 return net::OK;
485 } 525 }
486 526
487 void BaseFile::Close() { 527 void BaseFile::Close() {
488 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 528 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
529
530 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_FILE_CLOSED, NULL);
531
489 if (file_stream_.get()) { 532 if (file_stream_.get()) {
490 #if defined(OS_CHROMEOS) 533 #if defined(OS_CHROMEOS)
491 // Currently we don't really care about the return value, since if it fails 534 // 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. 535 // theres not much we can do. But we might in the future.
493 file_stream_->Flush(); 536 file_stream_->Flush();
494 #endif 537 #endif
495 file_stream_->Close(); 538 file_stream_->Close();
496 file_stream_.reset(); 539 ClearStream(net::OK);
497 } 540 }
498 } 541 }
499 542
543 net::Error BaseFile::ClearStream(net::Error net_error) {
544 // This should only be called when we have a stream.
545 DCHECK(file_stream_.get() != NULL);
546 file_stream_.reset();
547 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_FILE_OPENED, NULL);
548 return net_error;
549 }
550
500 std::string BaseFile::DebugString() const { 551 std::string BaseFile::DebugString() const {
501 return base::StringPrintf("{ source_url_ = \"%s\"" 552 return base::StringPrintf("{ source_url_ = \"%s\""
502 " full_path_ = \"%" PRFilePath "\"" 553 " full_path_ = \"%" PRFilePath "\""
503 " bytes_so_far_ = %" PRId64 554 " bytes_so_far_ = %" PRId64
504 " detached_ = %c }", 555 " detached_ = %c }",
505 source_url_.spec().c_str(), 556 source_url_.spec().c_str(),
506 full_path_.value().c_str(), 557 full_path_.value().c_str(),
507 bytes_so_far_, 558 bytes_so_far_,
508 detached_ ? 'T' : 'F'); 559 detached_ ? 'T' : 'F');
509 } 560 }
510 561
511 int64 BaseFile::CurrentSpeedAtTime(base::TimeTicks current_time) const { 562 int64 BaseFile::CurrentSpeedAtTime(base::TimeTicks current_time) const {
512 base::TimeDelta diff = current_time - start_tick_; 563 base::TimeDelta diff = current_time - start_tick_;
513 int64 diff_ms = diff.InMilliseconds(); 564 int64 diff_ms = diff.InMilliseconds();
514 return diff_ms == 0 ? 0 : bytes_so_far() * 1000 / diff_ms; 565 return diff_ms == 0 ? 0 : bytes_so_far() * 1000 / diff_ms;
515 } 566 }
516 567
517 int64 BaseFile::CurrentSpeed() const { 568 int64 BaseFile::CurrentSpeed() const {
518 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 569 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
519 return CurrentSpeedAtTime(base::TimeTicks::Now()); 570 return CurrentSpeedAtTime(base::TimeTicks::Now());
520 } 571 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698