• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "android_webview/browser/net/input_stream_reader.h"
6 
7 #include "android_webview/browser/input_stream.h"
8 #include "base/message_loop/message_loop.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "net/base/net_errors.h"
11 #include "net/http/http_byte_range.h"
12 
13 using content::BrowserThread;
14 
15 namespace android_webview {
16 
InputStreamReader(android_webview::InputStream * stream)17 InputStreamReader::InputStreamReader(android_webview::InputStream* stream)
18     : stream_(stream) {
19   DCHECK(stream);
20 }
21 
~InputStreamReader()22 InputStreamReader::~InputStreamReader() {
23 }
24 
Seek(const net::HttpByteRange & byte_range)25 int InputStreamReader::Seek(const net::HttpByteRange& byte_range) {
26   int content_size = 0;
27   net::HttpByteRange verified_byte_range(byte_range);
28 
29   int error_code = VerifyRequestedRange(&verified_byte_range, &content_size);
30   if (error_code != net::OK)
31     return error_code;
32 
33   error_code = SkipToRequestedRange(verified_byte_range);
34   if (error_code != net::OK)
35     return error_code;
36 
37   DCHECK_GE(content_size, 0);
38   return content_size;
39 }
40 
ReadRawData(net::IOBuffer * dest,int dest_size)41 int InputStreamReader::ReadRawData(net::IOBuffer* dest, int dest_size) {
42   if (!dest_size)
43     return 0;
44 
45   DCHECK_GT(dest_size, 0);
46 
47   int bytes_read = 0;
48   if (!stream_->Read(dest, dest_size, &bytes_read))
49     return net::ERR_FAILED;
50   else
51     return bytes_read;
52 }
53 
VerifyRequestedRange(net::HttpByteRange * byte_range,int * content_size)54 int InputStreamReader::VerifyRequestedRange(net::HttpByteRange* byte_range,
55                                             int* content_size) {
56   DCHECK(content_size);
57   int32_t size = 0;
58   if (!stream_->BytesAvailable(&size))
59     return net::ERR_FAILED;
60 
61   if (size <= 0)
62     return net::OK;
63 
64   // Check that the requested range was valid.
65   if (!byte_range->ComputeBounds(size))
66     return net::ERR_REQUEST_RANGE_NOT_SATISFIABLE;
67 
68   size = byte_range->last_byte_position() -
69          byte_range->first_byte_position() + 1;
70   DCHECK_GE(size, 0);
71   *content_size = size;
72 
73   return net::OK;
74 }
75 
SkipToRequestedRange(const net::HttpByteRange & byte_range)76 int InputStreamReader::SkipToRequestedRange(
77     const net::HttpByteRange& byte_range) {
78   // Skip to the start of the requested data. This has to be done in a loop
79   // because the underlying InputStream is not guaranteed to skip the requested
80   // number of bytes.
81   if (byte_range.IsValid() && byte_range.first_byte_position() > 0) {
82     int64_t bytes_to_skip = byte_range.first_byte_position();
83     do {
84       int64_t skipped = 0;
85       if (!stream_->Skip(bytes_to_skip, &skipped))
86         return net::ERR_FAILED;
87 
88       if (skipped <= 0)
89         return net::ERR_REQUEST_RANGE_NOT_SATISFIABLE;
90       DCHECK_LE(skipped, bytes_to_skip);
91 
92       bytes_to_skip -= skipped;
93     } while (bytes_to_skip > 0);
94   }
95   return net::OK;
96 }
97 
98 } // namespace android_webview
99