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
13using content::BrowserThread;
14
15namespace android_webview {
16
17InputStreamReader::InputStreamReader(android_webview::InputStream* stream)
18    : stream_(stream) {
19  DCHECK(stream);
20}
21
22InputStreamReader::~InputStreamReader() {
23}
24
25int 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
41int 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
54int 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
76int 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