Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 ;*; */
2 : /* vim: set sw=2 ts=8 et tw=80 : */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "nsAutoPtr.h"
8 : #include "nsIObserverService.h"
9 : #include "nsIXULRuntime.h"
10 : #include "nsServiceManagerUtils.h"
11 : #include "nsThreadUtils.h"
12 : #include "RequestContextService.h"
13 :
14 : #include "mozilla/Atomics.h"
15 : #include "mozilla/Logging.h"
16 : #include "mozilla/Services.h"
17 :
18 : #include "mozilla/net/PSpdyPush.h"
19 :
20 : namespace mozilla {
21 : namespace net {
22 :
23 : LazyLogModule gRequestContextLog("RequestContext");
24 : #undef LOG
25 : #define LOG(args) MOZ_LOG(gRequestContextLog, LogLevel::Info, args)
26 :
27 : // nsIRequestContext
28 : class RequestContext final : public nsIRequestContext
29 : {
30 : public:
31 : NS_DECL_THREADSAFE_ISUPPORTS
32 : NS_DECL_NSIREQUESTCONTEXT
33 :
34 : explicit RequestContext(const uint64_t id);
35 : private:
36 : virtual ~RequestContext();
37 :
38 : uint64_t mID;
39 : Atomic<uint32_t> mBlockingTransactionCount;
40 : nsAutoPtr<SpdyPushCache> mSpdyCache;
41 : nsCString mUserAgentOverride;
42 : };
43 :
44 888 : NS_IMPL_ISUPPORTS(RequestContext, nsIRequestContext)
45 :
46 74 : RequestContext::RequestContext(const uint64_t aID)
47 : : mID(aID)
48 74 : , mBlockingTransactionCount(0)
49 : {
50 74 : LOG(("RequestContext::RequestContext this=%p id=%" PRIx64, this, mID));
51 74 : }
52 :
53 63 : RequestContext::~RequestContext()
54 : {
55 21 : LOG(("RequestContext::~RequestContext this=%p blockers=%u",
56 : this, static_cast<uint32_t>(mBlockingTransactionCount)));
57 63 : }
58 :
59 : NS_IMETHODIMP
60 1 : RequestContext::GetBlockingTransactionCount(uint32_t *aBlockingTransactionCount)
61 : {
62 1 : NS_ENSURE_ARG_POINTER(aBlockingTransactionCount);
63 1 : *aBlockingTransactionCount = mBlockingTransactionCount;
64 1 : return NS_OK;
65 : }
66 :
67 : NS_IMETHODIMP
68 0 : RequestContext::AddBlockingTransaction()
69 : {
70 0 : mBlockingTransactionCount++;
71 0 : LOG(("RequestContext::AddBlockingTransaction this=%p blockers=%u",
72 : this, static_cast<uint32_t>(mBlockingTransactionCount)));
73 0 : return NS_OK;
74 : }
75 :
76 : NS_IMETHODIMP
77 0 : RequestContext::RemoveBlockingTransaction(uint32_t *outval)
78 : {
79 0 : NS_ENSURE_ARG_POINTER(outval);
80 0 : mBlockingTransactionCount--;
81 0 : LOG(("RequestContext::RemoveBlockingTransaction this=%p blockers=%u",
82 : this, static_cast<uint32_t>(mBlockingTransactionCount)));
83 0 : *outval = mBlockingTransactionCount;
84 0 : return NS_OK;
85 : }
86 :
87 : NS_IMETHODIMP
88 0 : RequestContext::GetSpdyPushCache(mozilla::net::SpdyPushCache **aSpdyPushCache)
89 : {
90 0 : *aSpdyPushCache = mSpdyCache.get();
91 0 : return NS_OK;
92 : }
93 :
94 : NS_IMETHODIMP
95 0 : RequestContext::SetSpdyPushCache(mozilla::net::SpdyPushCache *aSpdyPushCache)
96 : {
97 0 : mSpdyCache = aSpdyPushCache;
98 0 : return NS_OK;
99 : }
100 :
101 : NS_IMETHODIMP
102 24 : RequestContext::GetID(uint64_t *outval)
103 : {
104 24 : NS_ENSURE_ARG_POINTER(outval);
105 24 : *outval = mID;
106 24 : return NS_OK;
107 : }
108 :
109 : NS_IMETHODIMP
110 0 : RequestContext::GetUserAgentOverride(nsACString& aUserAgentOverride)
111 : {
112 0 : aUserAgentOverride = mUserAgentOverride;
113 0 : return NS_OK;
114 : }
115 :
116 : NS_IMETHODIMP
117 1 : RequestContext::SetUserAgentOverride(const nsACString& aUserAgentOverride)
118 : {
119 1 : mUserAgentOverride = aUserAgentOverride;
120 1 : return NS_OK;
121 : }
122 :
123 :
124 : //nsIRequestContextService
125 : RequestContextService *RequestContextService::sSelf = nullptr;
126 :
127 190 : NS_IMPL_ISUPPORTS(RequestContextService, nsIRequestContextService, nsIObserver)
128 :
129 3 : RequestContextService::RequestContextService()
130 3 : : mNextRCID(1)
131 : {
132 3 : MOZ_ASSERT(!sSelf, "multiple rcs instances!");
133 3 : MOZ_ASSERT(NS_IsMainThread());
134 3 : sSelf = this;
135 :
136 6 : nsCOMPtr<nsIXULRuntime> runtime = do_GetService("@mozilla.org/xre/runtime;1");
137 3 : runtime->GetProcessID(&mRCIDNamespace);
138 3 : }
139 :
140 0 : RequestContextService::~RequestContextService()
141 : {
142 0 : MOZ_ASSERT(NS_IsMainThread());
143 0 : Shutdown();
144 0 : sSelf = nullptr;
145 0 : }
146 :
147 : nsresult
148 3 : RequestContextService::Init()
149 : {
150 3 : MOZ_ASSERT(NS_IsMainThread());
151 6 : nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
152 3 : if (!obs) {
153 0 : return NS_ERROR_NOT_AVAILABLE;
154 : }
155 :
156 3 : return obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
157 : }
158 :
159 : void
160 0 : RequestContextService::Shutdown()
161 : {
162 0 : MOZ_ASSERT(NS_IsMainThread());
163 0 : mTable.Clear();
164 0 : }
165 :
166 : /* static */ nsresult
167 0 : RequestContextService::Create(nsISupports *aOuter, const nsIID& aIID, void **aResult)
168 : {
169 0 : MOZ_ASSERT(NS_IsMainThread());
170 0 : if (aOuter != nullptr) {
171 0 : return NS_ERROR_NO_AGGREGATION;
172 : }
173 :
174 0 : RefPtr<RequestContextService> svc = new RequestContextService();
175 0 : nsresult rv = svc->Init();
176 0 : NS_ENSURE_SUCCESS(rv, rv);
177 :
178 0 : return svc->QueryInterface(aIID, aResult);
179 : }
180 :
181 : NS_IMETHODIMP
182 7 : RequestContextService::GetRequestContext(const uint64_t rcID, nsIRequestContext **rc)
183 : {
184 7 : MOZ_ASSERT(NS_IsMainThread());
185 7 : NS_ENSURE_ARG_POINTER(rc);
186 7 : *rc = nullptr;
187 :
188 7 : if (!mTable.Get(rcID, rc)) {
189 4 : nsCOMPtr<nsIRequestContext> newSC = new RequestContext(rcID);
190 2 : mTable.Put(rcID, newSC);
191 2 : newSC.swap(*rc);
192 : }
193 :
194 7 : return NS_OK;
195 : }
196 :
197 : NS_IMETHODIMP
198 72 : RequestContextService::NewRequestContext(nsIRequestContext **rc)
199 : {
200 72 : MOZ_ASSERT(NS_IsMainThread());
201 72 : NS_ENSURE_ARG_POINTER(rc);
202 72 : *rc = nullptr;
203 :
204 72 : uint64_t rcID = ((static_cast<uint64_t>(mRCIDNamespace) << 32) & 0xFFFFFFFF00000000LL) | mNextRCID++;
205 :
206 144 : nsCOMPtr<nsIRequestContext> newSC = new RequestContext(rcID);
207 72 : mTable.Put(rcID, newSC);
208 72 : newSC.swap(*rc);
209 :
210 72 : return NS_OK;
211 : }
212 :
213 : NS_IMETHODIMP
214 21 : RequestContextService::RemoveRequestContext(const uint64_t rcID)
215 : {
216 21 : MOZ_ASSERT(NS_IsMainThread());
217 21 : mTable.Remove(rcID);
218 21 : return NS_OK;
219 : }
220 :
221 : NS_IMETHODIMP
222 0 : RequestContextService::Observe(nsISupports *subject, const char *topic,
223 : const char16_t *data_unicode)
224 : {
225 0 : MOZ_ASSERT(NS_IsMainThread());
226 0 : if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, topic)) {
227 0 : Shutdown();
228 : }
229 :
230 0 : return NS_OK;
231 : }
232 :
233 : } // ::mozilla::net
234 9 : } // ::mozilla
235 :
236 : #undef LOG
|