1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef WEBKIT_GLUE_MEDIA_BUFFERED_RESOURCE_LOADER_H_
6#define WEBKIT_GLUE_MEDIA_BUFFERED_RESOURCE_LOADER_H_
7
8#include <string>
9
10#include "base/callback.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/timer.h"
13#include "googleurl/src/gurl.h"
14#include "media/base/seekable_buffer.h"
15#include "net/base/file_stream.h"
16#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
17#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoader.h"
18#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLLoaderClient.h"
19#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h"
20#include "webkit/glue/media/web_data_source.h"
21#include "webkit/glue/webmediaplayer_impl.h"
22
23namespace webkit_glue {
24
25const int64 kPositionNotSpecified = -1;
26
27const char kHttpScheme[] = "http";
28const char kHttpsScheme[] = "https";
29const char kDataScheme[] = "data";
30
31// This class works inside demuxer thread and render thread. It contains a
32// WebURLLoader and does the actual resource loading. This object does
33// buffering internally, it defers the resource loading if buffer is full
34// and un-defers the resource loading if it is under buffered.
35class BufferedResourceLoader :
36    public base::RefCountedThreadSafe<BufferedResourceLoader>,
37    public WebKit::WebURLLoaderClient {
38 public:
39  // kNeverDefer - Aggresively buffer; never defer loading while paused.
40  // kReadThenDefer - Request only enough data to fulfill read requests.
41  // kThresholdDefer - Try to keep amount of buffered data at a threshold.
42  enum DeferStrategy {
43    kNeverDefer,
44    kReadThenDefer,
45    kThresholdDefer,
46  };
47
48  typedef Callback0::Type NetworkEventCallback;
49
50  // |url| - URL for the resource to be loaded.
51  // |first_byte_position| - First byte to start loading from,
52  // |kPositionNotSpecified| for not specified.
53  // |last_byte_position| - Last byte to be loaded,
54  // |kPositionNotSpecified| for not specified.
55  BufferedResourceLoader(const GURL& url,
56                         int64 first_byte_position,
57                         int64 last_byte_position);
58
59  // Start the resource loading with the specified URL and range.
60  // This method operates in asynchronous mode. Once there's a response from the
61  // server, success or fail |callback| is called with the result.
62  // |callback| is called with the following values:
63  // - net::OK
64  //   The request has started successfully.
65  // - net::ERR_FAILED
66  //   The request has failed because of an error with the network.
67  // - net::ERR_INVALID_RESPONSE
68  //   An invalid response is received from the server.
69  // - (Anything else)
70  //   An error code that indicates the request has failed.
71  // |event_callback| is called when the response is completed, data is
72  // received, the request is suspended or resumed.
73  virtual void Start(net::CompletionCallback* callback,
74                     NetworkEventCallback* event_callback,
75                     WebKit::WebFrame* frame);
76
77  // Stop this loader, cancels and request and release internal buffer.
78  virtual void Stop();
79
80  // Reads the specified |read_size| from |position| into |buffer| and when
81  // the operation is done invoke |callback| with number of bytes read or an
82  // error code.
83  // |callback| is called with the following values:
84  // - (Anything greater than or equal 0)
85  //   Read was successful with the indicated number of bytes read.
86  // - net::ERR_FAILED
87  //   The read has failed because of an error with the network.
88  // - net::ERR_CACHE_MISS
89  //   The read was made too far away from the current buffered position.
90  virtual void Read(int64 position, int read_size,
91                    uint8* buffer, net::CompletionCallback* callback);
92
93  // Returns the position of the last byte buffered. Returns
94  // |kPositionNotSpecified| if such value is not available.
95  virtual int64 GetBufferedPosition();
96
97  // Gets the content length in bytes of the instance after this loader has been
98  // started. If this value is |kPositionNotSpecified|, then content length is
99  // unknown.
100  virtual int64 content_length();
101
102  // Gets the original size of the file requested. If this value is
103  // |kPositionNotSpecified|, then the size is unknown.
104  virtual int64 instance_size();
105
106  // Returns true if the server supports byte range requests.
107  virtual bool range_supported();
108
109  // Returns true if network is currently active.
110  virtual bool network_activity();
111
112  // Returns resulting URL.
113  virtual const GURL& url();
114
115  // Used to inject a mock used for unittests.
116  virtual void SetURLLoaderForTest(WebKit::WebURLLoader* mock_loader);
117
118  // WebKit::WebURLLoaderClient implementation.
119  virtual void willSendRequest(
120      WebKit::WebURLLoader* loader,
121      WebKit::WebURLRequest& newRequest,
122      const WebKit::WebURLResponse& redirectResponse);
123  virtual void didSendData(
124      WebKit::WebURLLoader* loader,
125      unsigned long long bytesSent,
126      unsigned long long totalBytesToBeSent);
127  virtual void didReceiveResponse(
128      WebKit::WebURLLoader* loader,
129      const WebKit::WebURLResponse& response);
130  virtual void didDownloadData(
131      WebKit::WebURLLoader* loader,
132      int data_length);
133  virtual void didReceiveData(
134      WebKit::WebURLLoader* loader,
135      const char* data,
136      int data_length,
137      int encoded_data_length);
138  virtual void didReceiveCachedMetadata(
139      WebKit::WebURLLoader* loader,
140      const char* data, int dataLength);
141  virtual void didFinishLoading(
142      WebKit::WebURLLoader* loader,
143      double finishTime);
144  virtual void didFail(
145      WebKit::WebURLLoader* loader,
146      const WebKit::WebURLError&);
147
148  bool HasSingleOrigin() const;
149
150  // Sets the defer strategy to the given value.
151  void UpdateDeferStrategy(DeferStrategy strategy);
152
153 protected:
154  friend class base::RefCountedThreadSafe<BufferedResourceLoader>;
155  virtual ~BufferedResourceLoader();
156
157 private:
158  friend class BufferedResourceLoaderTest;
159
160  // Toggles whether the resource loading is deferred or not.
161  // Returns true if a network event was fired.
162  bool ToggleDeferring();
163
164  // Returns true if we should defer resource loading, based
165  // on current buffering scheme.
166  bool ShouldEnableDefer();
167
168  // Returns true if we should enable resource loading, based
169  // on current buffering scheme.
170  bool ShouldDisableDefer();
171
172  // Updates deferring behavior based on current buffering scheme.
173  void UpdateDeferBehavior();
174
175  // Returns true if the current read request can be fulfilled by what is in
176  // the buffer.
177  bool CanFulfillRead();
178
179  // Returns true if the current read request will be fulfilled in the future.
180  bool WillFulfillRead();
181
182  // Method that does the actual read and calls the |read_callback_|, assuming
183  // the request range is in |buffer_|.
184  void ReadInternal();
185
186  // If we have made a range request, verify the response from the server.
187  bool VerifyPartialResponse(const WebKit::WebURLResponse& response);
188
189  // Returns the value for a range request header using parameters
190  // |first_byte_position| and |last_byte_position|. Negative numbers other
191  // than |kPositionNotSpecified| are not allowed for |first_byte_position| and
192  // |last_byte_position|. |first_byte_position| should always be less than or
193  // equal to |last_byte_position| if they are both not |kPositionNotSpecified|.
194  // Empty string is returned on invalid parameters.
195  std::string GenerateHeaders(int64 first_byte_position,
196                              int64 last_byte_position);
197
198  // Done with read. Invokes the read callback and reset parameters for the
199  // read request.
200  void DoneRead(int error);
201
202  // Done with start. Invokes the start callback and reset it.
203  void DoneStart(int error);
204
205  // Calls |event_callback_| in terms of a network event.
206  void NotifyNetworkEvent();
207
208  bool HasPendingRead() { return read_callback_.get() != NULL; }
209
210  // Helper function that returns true if a range request was specified.
211  bool IsRangeRequest() const;
212
213  // A sliding window of buffer.
214  scoped_ptr<media::SeekableBuffer> buffer_;
215
216  // True if resource loading was deferred.
217  bool deferred_;
218
219  // Current buffering algorithm in place for resource loading.
220  DeferStrategy defer_strategy_;
221
222  // True if resource loading has completed.
223  bool completed_;
224
225  // True if a range request was made.
226  bool range_requested_;
227
228  // True if Range header is supported.
229  bool range_supported_;
230
231  // Does the work of loading and sends data back to this client.
232  scoped_ptr<WebKit::WebURLLoader> url_loader_;
233
234  GURL url_;
235  int64 first_byte_position_;
236  int64 last_byte_position_;
237  bool single_origin_;
238
239  // Callback method that listens to network events.
240  scoped_ptr<NetworkEventCallback> event_callback_;
241
242  // Members used during request start.
243  scoped_ptr<net::CompletionCallback> start_callback_;
244  int64 offset_;
245  int64 content_length_;
246  int64 instance_size_;
247
248  // Members used during a read operation. They should be reset after each
249  // read has completed or failed.
250  scoped_ptr<net::CompletionCallback> read_callback_;
251  int64 read_position_;
252  int read_size_;
253  uint8* read_buffer_;
254
255  // Offsets of the requested first byte and last byte in |buffer_|. They are
256  // written by Read().
257  int first_offset_;
258  int last_offset_;
259
260  // Used to ensure mocks for unittests are used instead of reset in Start().
261  bool keep_test_loader_;
262
263  DISALLOW_COPY_AND_ASSIGN(BufferedResourceLoader);
264};
265
266}  // namespace webkit_glue
267
268#endif  // WEBKIT_GLUE_MEDIA_BUFFERED_RESOURCE_LOADER_H_
269