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