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 23 namespace webkit_glue { 24 25 const int64 kPositionNotSpecified = -1; 26 27 const char kHttpScheme[] = "http"; 28 const char kHttpsScheme[] = "https"; 29 const 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. 35 class 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