summaryrefslogtreecommitdiff
path: root/chromium/content/browser/download/download_request_core.h
blob: 84eb2e0a935441a361727650040a137f56038cc0 (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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// 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.

#ifndef CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_REQUEST_CORE_H_
#define CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_REQUEST_CORE_H_

#include <stddef.h>
#include <stdint.h>

#include <memory>
#include <string>

#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/loader/resource_handler.h"
#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/download_save_info.h"
#include "content/public/browser/download_url_parameters.h"

namespace net {
class HttpResponseHeaders;
class URLRequest;
class URLRequestStatus;
}  // namespace net

namespace content {
class DownloadManagerImpl;
class ByteStreamReader;
class ByteStreamWriter;
class PowerSaveBlocker;
struct DownloadCreateInfo;

// This class encapsulates the core logic for reading data from a URLRequest and
// writing it into a ByteStream. It's common to both DownloadResourceHandler and
// UrlDownloader.
//
// Created, lives on and dies on the IO thread.
class CONTENT_EXPORT DownloadRequestCore
    : public base::SupportsWeakPtr<DownloadRequestCore> {
 public:
  class Delegate {
   public:
    virtual void OnReadyToRead() = 0;
    virtual void OnStart(
        std::unique_ptr<DownloadCreateInfo> download_create_info,
        std::unique_ptr<ByteStreamReader> stream_reader,
        const DownloadUrlParameters::OnStartedCallback& callback) = 0;
  };

  // All parameters are required. |request| and |delegate| must outlive
  // DownloadRequestCore.
  DownloadRequestCore(net::URLRequest* request, Delegate* delegate);
  ~DownloadRequestCore();

  // Should be called when the URLRequest::Delegate receives OnResponseStarted.
  // Invokes Delegate::OnStart() with download start parameters. The
  // |override_mime_type| is used as the MIME type for the download when
  // constructing a DownloadCreateInfo object.
  bool OnResponseStarted(const std::string& override_mime_type);

  // Should be called to handle a redirect. The caller should only allow the
  // redirect to be followed if the return value is true.
  bool OnRequestRedirected();

  // Starts a read cycle. Creates a new IOBuffer which can be passed into
  // URLRequest::Read(). Call OnReadCompleted() when the Read operation
  // completes.
  bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
                  int* buf_size,
                  int min_size);

  // Used to notify DownloadRequestCore that the caller is about to abort the
  // outer request. |reason| will be used as the final interrupt reason when
  // OnResponseCompleted() is called.
  void OnWillAbort(DownloadInterruptReason reason);

  // Should be called when the Read() operation completes. |defer| will be set
  // to true if reading is to be suspended. In the latter case, once more data
  // can be read, invokes the |on_ready_to_read_callback|.
  bool OnReadCompleted(int bytes_read, bool* defer);

  // Called to signal that the response is complete.
  //
  // It is expected that once this method is invoked, the DownloadRequestCore
  // object will be destroyed in short order without invoking any other methods
  // other than the destructor.
  void OnResponseCompleted(const net::URLRequestStatus& status);

  // Called if the request should suspend reading. A subsequent
  // OnReadCompleted() will result in |defer| being set to true.
  //
  // Each PauseRequest() must be balanced with a call to ResumeRequest().
  void PauseRequest();

  // Balances a call to PauseRequest(). If no more pauses are outstanding and
  // the reader end of the ByteStream is ready to receive more data,
  // DownloadRequestCore will invoke the |on_ready_to_read_callback| to signal
  // to the caller that the read cycles should commence.
  void ResumeRequest();

  std::string DebugString() const;

  static std::unique_ptr<net::URLRequest> CreateRequestOnIOThread(
      uint32_t download_id,
      DownloadUrlParameters* params);

  // Size of the buffer used between the DownloadRequestCore and the
  // downstream receiver of its output.
  static const int kDownloadByteStreamSize;

 protected:
  net::URLRequest* request() const { return request_; }

 private:
  static DownloadInterruptReason HandleRequestStatus(
      const net::URLRequestStatus& status);

  static DownloadInterruptReason HandleSuccessfulServerResponse(
      const net::HttpResponseHeaders& http_headers,
      DownloadSaveInfo* save_info);

  std::unique_ptr<DownloadCreateInfo> CreateDownloadCreateInfo(
      DownloadInterruptReason result);

  Delegate* delegate_;
  net::URLRequest* request_;

  // "Passthrough" fields. These are only kept here so that they can be used to
  // populate the DownloadCreateInfo when the time comes.
  std::unique_ptr<DownloadSaveInfo> save_info_;
  uint32_t download_id_;
  DownloadUrlParameters::OnStartedCallback on_started_callback_;

  // Data flow
  scoped_refptr<net::IOBuffer> read_buffer_;    // From URLRequest.
  std::unique_ptr<ByteStreamWriter> stream_writer_;  // To rest of system.

  // Keeps the system from sleeping while this is alive. If the
  // system enters power saving mode while a request is alive, it can cause the
  // request to fail and the associated download will be interrupted.
  std::unique_ptr<PowerSaveBlocker> power_save_blocker_;

  // The following are used to collect stats.
  base::TimeTicks download_start_time_;
  base::TimeTicks last_read_time_;
  base::TimeTicks last_stream_pause_time_;
  base::TimeDelta total_pause_time_;
  size_t last_buffer_size_;
  int64_t bytes_read_;

  int pause_count_;
  bool was_deferred_;
  bool is_partial_request_;
  bool started_;

  // When DownloadRequestCore initiates an abort (by blocking a redirect, for
  // example) it expects to eventually receive a OnResponseCompleted() with a
  // status indicating that the request was aborted. When this happens, the
  // interrupt reason in |abort_reason_| will be used instead of USER_CANCELED
  // which is vague.
  DownloadInterruptReason abort_reason_;

  // Each successful OnWillRead will yield a buffer of this size.
  static const int kReadBufSize = 32768;   // bytes

  DISALLOW_COPY_AND_ASSIGN(DownloadRequestCore);
};

}  // namespace content

#endif  // CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_REQUEST_CORE_H_