Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/netwerk/base/nsTransportUtils.cpp
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#include "mozilla/Mutex.h"
6
#include "nsTransportUtils.h"
7
#include "nsITransport.h"
8
#include "nsProxyRelease.h"
9
#include "nsThreadUtils.h"
10
#include "nsAutoPtr.h"
11
#include "nsCOMPtr.h"
12
13
using namespace mozilla;
14
15
//-----------------------------------------------------------------------------
16
17
class nsTransportStatusEvent;
18
19
class nsTransportEventSinkProxy : public nsITransportEventSink
20
{
21
public:
22
    NS_DECL_THREADSAFE_ISUPPORTS
23
    NS_DECL_NSITRANSPORTEVENTSINK
24
25
    nsTransportEventSinkProxy(nsITransportEventSink *sink,
26
                              nsIEventTarget *target)
27
        : mSink(sink)
28
        , mTarget(target)
29
        , mLock("nsTransportEventSinkProxy.mLock")
30
        , mLastEvent(nullptr)
31
0
    {
32
0
        NS_ADDREF(mSink);
33
0
    }
34
35
private:
36
    virtual ~nsTransportEventSinkProxy()
37
0
    {
38
0
        // our reference to mSink could be the last, so be sure to release
39
0
        // it on the target thread.  otherwise, we could get into trouble.
40
0
        NS_ProxyRelease(
41
0
          "nsTransportEventSinkProxy::mSink", mTarget, dont_AddRef(mSink));
42
0
    }
43
44
public:
45
    nsITransportEventSink           *mSink;
46
    nsCOMPtr<nsIEventTarget>         mTarget;
47
    Mutex                            mLock;
48
    nsTransportStatusEvent          *mLastEvent;
49
};
50
51
class nsTransportStatusEvent : public Runnable
52
{
53
public:
54
    nsTransportStatusEvent(nsTransportEventSinkProxy *proxy,
55
                           nsITransport *transport,
56
                           nsresult status,
57
                           int64_t progress,
58
                           int64_t progressMax)
59
        : Runnable("nsTransportStatusEvent")
60
        , mProxy(proxy)
61
        , mTransport(transport)
62
        , mStatus(status)
63
        , mProgress(progress)
64
        , mProgressMax(progressMax)
65
0
    {}
66
67
0
    ~nsTransportStatusEvent() = default;
68
69
    NS_IMETHOD Run() override
70
0
    {
71
0
        // since this event is being handled, we need to clear the proxy's ref.
72
0
        // if not coalescing all, then last event may not equal self!
73
0
        {
74
0
            MutexAutoLock lock(mProxy->mLock);
75
0
            if (mProxy->mLastEvent == this)
76
0
                mProxy->mLastEvent = nullptr;
77
0
        }
78
0
79
0
        mProxy->mSink->OnTransportStatus(mTransport, mStatus, mProgress,
80
0
                                         mProgressMax);
81
0
        return NS_OK;
82
0
    }
83
84
    RefPtr<nsTransportEventSinkProxy> mProxy;
85
86
    // parameters to OnTransportStatus
87
    nsCOMPtr<nsITransport> mTransport;
88
    nsresult               mStatus;
89
    int64_t                mProgress;
90
    int64_t                mProgressMax;
91
};
92
93
NS_IMPL_ISUPPORTS(nsTransportEventSinkProxy, nsITransportEventSink)
94
95
NS_IMETHODIMP
96
nsTransportEventSinkProxy::OnTransportStatus(nsITransport *transport,
97
                                             nsresult status,
98
                                             int64_t progress,
99
                                             int64_t progressMax)
100
0
{
101
0
    nsresult rv = NS_OK;
102
0
    RefPtr<nsTransportStatusEvent> event;
103
0
    {
104
0
        MutexAutoLock lock(mLock);
105
0
106
0
        // try to coalesce events! ;-)
107
0
        if (mLastEvent && (mLastEvent->mStatus == status)) {
108
0
            mLastEvent->mStatus = status;
109
0
            mLastEvent->mProgress = progress;
110
0
            mLastEvent->mProgressMax = progressMax;
111
0
        }
112
0
        else {
113
0
            event = new nsTransportStatusEvent(this, transport, status,
114
0
                                               progress, progressMax);
115
0
            if (!event)
116
0
                rv = NS_ERROR_OUT_OF_MEMORY;
117
0
            mLastEvent = event;  // weak ref
118
0
        }
119
0
    }
120
0
    if (event) {
121
0
        rv = mTarget->Dispatch(event, NS_DISPATCH_NORMAL);
122
0
        if (NS_FAILED(rv)) {
123
0
            NS_WARNING("unable to post transport status event");
124
0
125
0
            MutexAutoLock lock(mLock); // cleanup.. don't reference anymore!
126
0
            mLastEvent = nullptr;
127
0
        }
128
0
    }
129
0
    return rv;
130
0
}
131
132
//-----------------------------------------------------------------------------
133
134
nsresult
135
net_NewTransportEventSinkProxy(nsITransportEventSink **result,
136
                               nsITransportEventSink *sink,
137
                               nsIEventTarget *target)
138
0
{
139
0
    *result = new nsTransportEventSinkProxy(sink, target);
140
0
    if (!*result)
141
0
        return NS_ERROR_OUT_OF_MEMORY;
142
0
    NS_ADDREF(*result);
143
0
    return NS_OK;
144
0
}