Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/netwerk/base/nsStreamLoader.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#include "nsStreamLoader.h"
7
#include "nsIInputStream.h"
8
#include "nsIChannel.h"
9
#include "nsError.h"
10
#include "GeckoProfiler.h"
11
12
#include <limits>
13
14
namespace mozilla {
15
namespace net {
16
17
nsStreamLoader::nsStreamLoader()
18
  : mData()
19
0
{
20
0
}
21
22
NS_IMETHODIMP
23
nsStreamLoader::Init(nsIStreamLoaderObserver* aStreamObserver,
24
                     nsIRequestObserver* aRequestObserver)
25
0
{
26
0
  NS_ENSURE_ARG_POINTER(aStreamObserver);
27
0
  mObserver = aStreamObserver;
28
0
  mRequestObserver = aRequestObserver;
29
0
  return NS_OK;
30
0
}
31
32
nsresult
33
nsStreamLoader::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
34
0
{
35
0
  if (aOuter) return NS_ERROR_NO_AGGREGATION;
36
0
37
0
  nsStreamLoader* it = new nsStreamLoader();
38
0
  if (it == nullptr)
39
0
    return NS_ERROR_OUT_OF_MEMORY;
40
0
  NS_ADDREF(it);
41
0
  nsresult rv = it->QueryInterface(aIID, aResult);
42
0
  NS_RELEASE(it);
43
0
  return rv;
44
0
}
45
46
NS_IMPL_ISUPPORTS(nsStreamLoader, nsIStreamLoader,
47
                  nsIRequestObserver, nsIStreamListener,
48
                  nsIThreadRetargetableStreamListener)
49
50
NS_IMETHODIMP
51
nsStreamLoader::GetNumBytesRead(uint32_t* aNumBytes)
52
0
{
53
0
  *aNumBytes = mData.length();
54
0
  return NS_OK;
55
0
}
56
57
NS_IMETHODIMP
58
nsStreamLoader::GetRequest(nsIRequest **aRequest)
59
0
{
60
0
  NS_IF_ADDREF(*aRequest = mRequest);
61
0
  return NS_OK;
62
0
}
63
64
NS_IMETHODIMP
65
nsStreamLoader::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
66
0
{
67
0
  nsCOMPtr<nsIChannel> chan( do_QueryInterface(request) );
68
0
  if (chan) {
69
0
    int64_t contentLength = -1;
70
0
    chan->GetContentLength(&contentLength);
71
0
    if (contentLength >= 0) {
72
0
      // On 64bit platforms size of uint64_t coincides with the size of size_t,
73
0
      // so we want to compare with the minimum from size_t and int64_t.
74
0
      if (static_cast<uint64_t>(contentLength) >
75
0
          std::min(std::numeric_limits<size_t>::max(),
76
0
                   static_cast<size_t>(std::numeric_limits<int64_t>::max()))) {
77
0
        // Too big to fit into size_t, so let's bail.
78
0
        return NS_ERROR_OUT_OF_MEMORY;
79
0
      }
80
0
      // preallocate buffer
81
0
      if (!mData.initCapacity(contentLength)) {
82
0
        return NS_ERROR_OUT_OF_MEMORY;
83
0
      }
84
0
    }
85
0
  }
86
0
  mContext = ctxt;
87
0
  if (mRequestObserver) {
88
0
    mRequestObserver->OnStartRequest(request, ctxt);
89
0
  }
90
0
  return NS_OK;
91
0
}
92
93
NS_IMETHODIMP
94
nsStreamLoader::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
95
                              nsresult aStatus)
96
0
{
97
0
  AUTO_PROFILER_LABEL("nsStreamLoader::OnStopRequest", NETWORK);
98
0
99
0
  if (mObserver) {
100
0
    // provide nsIStreamLoader::request during call to OnStreamComplete
101
0
    mRequest = request;
102
0
    size_t length = mData.length();
103
0
    uint8_t* elems = mData.extractOrCopyRawBuffer();
104
0
    nsresult rv = mObserver->OnStreamComplete(this, mContext, aStatus,
105
0
                                              length, elems);
106
0
    if (rv != NS_SUCCESS_ADOPTED_DATA) {
107
0
      // The observer didn't take ownership of the extracted data buffer, so
108
0
      // put it back into mData.
109
0
      mData.replaceRawBuffer(elems, length);
110
0
    }
111
0
    // done.. cleanup
112
0
    ReleaseData();
113
0
    mRequest = nullptr;
114
0
    mObserver = nullptr;
115
0
    mContext = nullptr;
116
0
  }
117
0
118
0
  if (mRequestObserver) {
119
0
    mRequestObserver->OnStopRequest(request, ctxt, aStatus);
120
0
    mRequestObserver = nullptr;
121
0
  }
122
0
123
0
  return NS_OK;
124
0
}
125
126
nsresult
127
nsStreamLoader::WriteSegmentFun(nsIInputStream *inStr,
128
                                void *closure,
129
                                const char *fromSegment,
130
                                uint32_t toOffset,
131
                                uint32_t count,
132
                                uint32_t *writeCount)
133
0
{
134
0
  nsStreamLoader *self = (nsStreamLoader *) closure;
135
0
136
0
  if (!self->mData.append(fromSegment, count)) {
137
0
    self->mData.clearAndFree();
138
0
    return NS_ERROR_OUT_OF_MEMORY;
139
0
  }
140
0
141
0
  *writeCount = count;
142
0
143
0
  return NS_OK;
144
0
}
145
146
NS_IMETHODIMP
147
nsStreamLoader::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
148
                                nsIInputStream *inStr,
149
                                uint64_t sourceOffset, uint32_t count)
150
0
{
151
0
  uint32_t countRead;
152
0
  return inStr->ReadSegments(WriteSegmentFun, this, count, &countRead);
153
0
}
154
155
void
156
nsStreamLoader::ReleaseData()
157
0
{
158
0
  mData.clearAndFree();
159
0
}
160
161
NS_IMETHODIMP
162
nsStreamLoader::CheckListenerChain()
163
0
{
164
0
  return NS_OK;
165
0
}
166
167
} // namespace net
168
} // namespace mozilla