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 "nsIUUIDGenerator.h"
10 #include "nsServiceManagerUtils.h"
11 #include "nsThreadUtils.h"
12 #include "RequestContextService.h"
13
14 #include "mozilla/Atomics.h"
15 #include "mozilla/Services.h"
16
17 #include "mozilla/net/PSpdyPush.h"
18
19 namespace mozilla {
20 namespace net {
21
22 // nsIRequestContext
23 class RequestContext final : public nsIRequestContext
24 {
25 public:
26 NS_DECL_THREADSAFE_ISUPPORTS
27 NS_DECL_NSIREQUESTCONTEXT
28
29 explicit RequestContext(const nsID& id);
30 private:
31 virtual ~RequestContext();
32
33 nsID mID;
34 char mCID[NSID_LENGTH];
35 Atomic<uint32_t> mBlockingTransactionCount;
36 nsAutoPtr<SpdyPushCache> mSpdyCache;
37 nsCString mUserAgentOverride;
38 };
39
NS_IMPL_ISUPPORTS(RequestContext,nsIRequestContext)40 NS_IMPL_ISUPPORTS(RequestContext, nsIRequestContext)
41
42 RequestContext::RequestContext(const nsID& aID)
43 : mBlockingTransactionCount(0)
44 {
45 mID = aID;
46 mID.ToProvidedString(mCID);
47 }
48
~RequestContext()49 RequestContext::~RequestContext()
50 {
51 }
52
53 NS_IMETHODIMP
GetBlockingTransactionCount(uint32_t * aBlockingTransactionCount)54 RequestContext::GetBlockingTransactionCount(uint32_t *aBlockingTransactionCount)
55 {
56 NS_ENSURE_ARG_POINTER(aBlockingTransactionCount);
57 *aBlockingTransactionCount = mBlockingTransactionCount;
58 return NS_OK;
59 }
60
61 NS_IMETHODIMP
AddBlockingTransaction()62 RequestContext::AddBlockingTransaction()
63 {
64 mBlockingTransactionCount++;
65 return NS_OK;
66 }
67
68 NS_IMETHODIMP
RemoveBlockingTransaction(uint32_t * outval)69 RequestContext::RemoveBlockingTransaction(uint32_t *outval)
70 {
71 NS_ENSURE_ARG_POINTER(outval);
72 mBlockingTransactionCount--;
73 *outval = mBlockingTransactionCount;
74 return NS_OK;
75 }
76
77 NS_IMETHODIMP
GetSpdyPushCache(mozilla::net::SpdyPushCache ** aSpdyPushCache)78 RequestContext::GetSpdyPushCache(mozilla::net::SpdyPushCache **aSpdyPushCache)
79 {
80 *aSpdyPushCache = mSpdyCache.get();
81 return NS_OK;
82 }
83
84 NS_IMETHODIMP
SetSpdyPushCache(mozilla::net::SpdyPushCache * aSpdyPushCache)85 RequestContext::SetSpdyPushCache(mozilla::net::SpdyPushCache *aSpdyPushCache)
86 {
87 mSpdyCache = aSpdyPushCache;
88 return NS_OK;
89 }
90
91 NS_IMETHODIMP
GetID(nsID * outval)92 RequestContext::GetID(nsID *outval)
93 {
94 NS_ENSURE_ARG_POINTER(outval);
95 *outval = mID;
96 return NS_OK;
97 }
98
99 NS_IMETHODIMP
GetUserAgentOverride(nsACString & aUserAgentOverride)100 RequestContext::GetUserAgentOverride(nsACString& aUserAgentOverride)
101 {
102 aUserAgentOverride = mUserAgentOverride;
103 return NS_OK;
104 }
105
106 NS_IMETHODIMP
SetUserAgentOverride(const nsACString & aUserAgentOverride)107 RequestContext::SetUserAgentOverride(const nsACString& aUserAgentOverride)
108 {
109 mUserAgentOverride = aUserAgentOverride;
110 return NS_OK;
111 }
112
113
114 //nsIRequestContextService
115 RequestContextService *RequestContextService::sSelf = nullptr;
116
NS_IMPL_ISUPPORTS(RequestContextService,nsIRequestContextService,nsIObserver)117 NS_IMPL_ISUPPORTS(RequestContextService, nsIRequestContextService, nsIObserver)
118
119 RequestContextService::RequestContextService()
120 {
121 MOZ_ASSERT(!sSelf, "multiple rcs instances!");
122 MOZ_ASSERT(NS_IsMainThread());
123 sSelf = this;
124 }
125
~RequestContextService()126 RequestContextService::~RequestContextService()
127 {
128 MOZ_ASSERT(NS_IsMainThread());
129 Shutdown();
130 sSelf = nullptr;
131 }
132
133 nsresult
Init()134 RequestContextService::Init()
135 {
136 MOZ_ASSERT(NS_IsMainThread());
137 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
138 if (!obs) {
139 return NS_ERROR_NOT_AVAILABLE;
140 }
141
142 return obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
143 }
144
145 void
Shutdown()146 RequestContextService::Shutdown()
147 {
148 MOZ_ASSERT(NS_IsMainThread());
149 mTable.Clear();
150 }
151
152 /* static */ nsresult
Create(nsISupports * aOuter,const nsIID & aIID,void ** aResult)153 RequestContextService::Create(nsISupports *aOuter, const nsIID& aIID, void **aResult)
154 {
155 MOZ_ASSERT(NS_IsMainThread());
156 if (aOuter != nullptr) {
157 return NS_ERROR_NO_AGGREGATION;
158 }
159
160 RefPtr<RequestContextService> svc = new RequestContextService();
161 nsresult rv = svc->Init();
162 NS_ENSURE_SUCCESS(rv, rv);
163
164 return svc->QueryInterface(aIID, aResult);
165 }
166
167 NS_IMETHODIMP
GetRequestContext(const nsID & rcID,nsIRequestContext ** rc)168 RequestContextService::GetRequestContext(const nsID& rcID, nsIRequestContext **rc)
169 {
170 MOZ_ASSERT(NS_IsMainThread());
171 NS_ENSURE_ARG_POINTER(rc);
172 *rc = nullptr;
173
174 if (!mTable.Get(rcID, rc)) {
175 nsCOMPtr<nsIRequestContext> newSC = new RequestContext(rcID);
176 mTable.Put(rcID, newSC);
177 newSC.swap(*rc);
178 }
179
180 return NS_OK;
181 }
182
183 NS_IMETHODIMP
NewRequestContextID(nsID * rcID)184 RequestContextService::NewRequestContextID(nsID *rcID)
185 {
186 MOZ_ASSERT(NS_IsMainThread());
187 if (!mUUIDGen) {
188 nsresult rv;
189 mUUIDGen = do_GetService("@mozilla.org/uuid-generator;1", &rv);
190 NS_ENSURE_SUCCESS(rv, rv);
191 }
192
193 return mUUIDGen->GenerateUUIDInPlace(rcID);
194 }
195
196 NS_IMETHODIMP
RemoveRequestContext(const nsID & rcID)197 RequestContextService::RemoveRequestContext(const nsID& rcID)
198 {
199 MOZ_ASSERT(NS_IsMainThread());
200 mTable.Remove(rcID);
201 return NS_OK;
202 }
203
204 NS_IMETHODIMP
Observe(nsISupports * subject,const char * topic,const char16_t * data_unicode)205 RequestContextService::Observe(nsISupports *subject, const char *topic,
206 const char16_t *data_unicode)
207 {
208 MOZ_ASSERT(NS_IsMainThread());
209 if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, topic)) {
210 Shutdown();
211 }
212
213 return NS_OK;
214 }
215
216 } // ::mozilla::net
217 } // ::mozilla
218