summaryrefslogtreecommitdiff
path: root/chromium/content/browser/download/save_item.cc
blob: edea26328044adbc7d319587f0a7956e08b015ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/download/save_item.h"

#include "base/logging.h"
#include "base/strings/string_util.h"
#include "content/browser/download/save_file.h"
#include "content/browser/download/save_file_manager.h"
#include "content/browser/download/save_package.h"
#include "content/public/browser/browser_thread.h"

namespace content {

namespace {

SaveItemId GetNextSaveItemId() {
  static int g_next_save_item_id = 1;
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  return SaveItemId::FromUnsafeValue(g_next_save_item_id++);
}

}  // namespace

// Constructor for SaveItem when creating each saving job.
SaveItem::SaveItem(const GURL& url,
                   const Referrer& referrer,
                   SavePackage* package,
                   SaveFileCreateInfo::SaveFileSource save_source)
    : save_item_id_(GetNextSaveItemId()),
      url_(url),
      referrer_(referrer),
      total_bytes_(0),
      received_bytes_(0),
      state_(WAIT_START),
      has_final_name_(false),
      is_success_(false),
      save_source_(save_source),
      package_(package) {
  DCHECK(package);
}

SaveItem::~SaveItem() {
}

// Set start state for save item.
void SaveItem::Start() {
  DCHECK(state_ == WAIT_START);
  state_ = IN_PROGRESS;
}

// If we've received more data than we were expecting (bad server info?),
// revert to 'unknown size mode'.
void SaveItem::UpdateSize(int64_t bytes_so_far) {
  received_bytes_ = bytes_so_far;
  if (received_bytes_ >= total_bytes_)
    total_bytes_ = 0;
}

// Updates from the file thread may have been posted while this saving job
// was being canceled in the UI thread, so we'll accept them unless we're
// complete.
void SaveItem::Update(int64_t bytes_so_far) {
  if (state_ != IN_PROGRESS) {
    NOTREACHED();
    return;
  }
  UpdateSize(bytes_so_far);
}

// Cancel this saving item job. If the job is not in progress, ignore
// this command. The SavePackage will each in-progress SaveItem's cancel
// when canceling whole saving page job.
void SaveItem::Cancel() {
  // If item is in WAIT_START mode, which means no request has been sent.
  // So we need not to cancel it.
  if (state_ != IN_PROGRESS) {
    // Small downloads might be complete before method has a chance to run.
    return;
  }
  state_ = CANCELED;
  is_success_ = false;
  Finish(received_bytes_, false);
  package_->SaveCanceled(this);
}

// Set finish state for a save item
void SaveItem::Finish(int64_t size, bool is_success) {
  DCHECK(has_final_name() || !is_success_);
  state_ = COMPLETE;
  is_success_ = is_success;
  UpdateSize(size);
}

// Calculate the percentage of the save item
int SaveItem::PercentComplete() const {
  switch (state_) {
    case COMPLETE:
    case CANCELED:
      return 100;
    case WAIT_START:
      return 0;
    case IN_PROGRESS: {
      int percent = 0;
      if (total_bytes_ > 0)
        percent = static_cast<int>(received_bytes_ * 100.0 / total_bytes_);
      return percent;
    }
    default: {
      NOTREACHED();
      return -1;
    }
  }
}

// Rename the save item with new path.
void SaveItem::Rename(const base::FilePath& full_path) {
  DCHECK(!full_path.empty() && !has_final_name());
  full_path_ = full_path;
  file_name_ = full_path_.BaseName();
  has_final_name_ = true;
}

void SaveItem::SetTotalBytes(int64_t total_bytes) {
  DCHECK_EQ(0, total_bytes_);
  total_bytes_ = total_bytes;
}

}  // namespace content