/src/mozilla-central/netwerk/protocol/wyciwyg/WyciwygChannelChild.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 "nsWyciwyg.h" |
6 | | |
7 | | #include "base/compiler_specific.h" |
8 | | |
9 | | #include "mozilla/net/ChannelEventQueue.h" |
10 | | #include "WyciwygChannelChild.h" |
11 | | #include "mozilla/dom/TabChild.h" |
12 | | #include "mozilla/dom/ContentChild.h" |
13 | | #include "mozilla/net/NeckoChild.h" |
14 | | |
15 | | #include "nsCharsetSource.h" |
16 | | #include "nsContentUtils.h" |
17 | | #include "nsStringStream.h" |
18 | | #include "nsNetUtil.h" |
19 | | #include "nsISerializable.h" |
20 | | #include "nsSerializationHelper.h" |
21 | | #include "nsIProgressEventSink.h" |
22 | | #include "mozilla/ipc/URIUtils.h" |
23 | | #include "SerializedLoadContext.h" |
24 | | #include "mozilla/ipc/BackgroundUtils.h" |
25 | | #include "nsProxyRelease.h" |
26 | | #include "nsContentSecurityManager.h" |
27 | | |
28 | | using namespace mozilla::ipc; |
29 | | using namespace mozilla::dom; |
30 | | |
31 | | namespace mozilla { |
32 | | namespace net { |
33 | | |
34 | | NS_IMPL_ISUPPORTS(WyciwygChannelChild, |
35 | | nsIRequest, |
36 | | nsIChannel, |
37 | | nsIWyciwygChannel, |
38 | | nsIPrivateBrowsingChannel) |
39 | | |
40 | | |
41 | | WyciwygChannelChild::WyciwygChannelChild(nsIEventTarget *aNeckoTarget) |
42 | | : NeckoTargetHolder(aNeckoTarget) |
43 | | , mStatus(NS_OK) |
44 | | , mIsPending(false) |
45 | | , mCanceled(false) |
46 | | , mLoadFlags(LOAD_NORMAL) |
47 | | , mContentLength(-1) |
48 | | , mCharsetSource(kCharsetUninitialized) |
49 | | , mState(WCC_NEW) |
50 | | , mIPCOpen(false) |
51 | | , mSentAppData(false) |
52 | 0 | { |
53 | 0 | LOG(("Creating WyciwygChannelChild @%p\n", this)); |
54 | 0 | mEventQ = new ChannelEventQueue(NS_ISUPPORTS_CAST(nsIWyciwygChannel*, this)); |
55 | 0 |
|
56 | 0 | if (mNeckoTarget) { |
57 | 0 | gNeckoChild->SetEventTargetForActor(this, mNeckoTarget); |
58 | 0 | } |
59 | 0 |
|
60 | 0 | gNeckoChild->SendPWyciwygChannelConstructor(this); |
61 | 0 | // IPDL holds a reference until IPDL channel gets destroyed |
62 | 0 | AddIPDLReference(); |
63 | 0 | } |
64 | | |
65 | | WyciwygChannelChild::~WyciwygChannelChild() |
66 | 0 | { |
67 | 0 | LOG(("Destroying WyciwygChannelChild @%p\n", this)); |
68 | 0 | if (mLoadInfo) { |
69 | 0 | NS_ReleaseOnMainThreadSystemGroup( |
70 | 0 | "WyciwygChannelChild::mLoadInfo", mLoadInfo.forget()); |
71 | 0 | } |
72 | 0 | } |
73 | | |
74 | | void |
75 | | WyciwygChannelChild::AddIPDLReference() |
76 | 0 | { |
77 | 0 | MOZ_ASSERT(!mIPCOpen, "Attempt to retain more than one IPDL reference"); |
78 | 0 | mIPCOpen = true; |
79 | 0 | AddRef(); |
80 | 0 | } |
81 | | |
82 | | void |
83 | | WyciwygChannelChild::ReleaseIPDLReference() |
84 | 0 | { |
85 | 0 | MOZ_ASSERT(mIPCOpen, "Attempt to release nonexistent IPDL reference"); |
86 | 0 | mIPCOpen = false; |
87 | 0 | Release(); |
88 | 0 | } |
89 | | |
90 | | nsresult |
91 | | WyciwygChannelChild::Init(nsIURI* uri) |
92 | 0 | { |
93 | 0 | NS_ENSURE_ARG_POINTER(uri); |
94 | 0 |
|
95 | 0 | mState = WCC_INIT; |
96 | 0 |
|
97 | 0 | mURI = uri; |
98 | 0 | mOriginalURI = uri; |
99 | 0 |
|
100 | 0 | URIParams serializedUri; |
101 | 0 | SerializeURI(uri, serializedUri); |
102 | 0 |
|
103 | 0 | // propagate loadInfo |
104 | 0 | mozilla::ipc::PrincipalInfo requestingPrincipalInfo; |
105 | 0 | mozilla::ipc::PrincipalInfo triggeringPrincipalInfo; |
106 | 0 | mozilla::ipc::PrincipalInfo principalToInheritInfo; |
107 | 0 | uint32_t securityFlags; |
108 | 0 | uint32_t policyType; |
109 | 0 | if (mLoadInfo) { |
110 | 0 | mozilla::ipc::PrincipalToPrincipalInfo(mLoadInfo->LoadingPrincipal(), |
111 | 0 | &requestingPrincipalInfo); |
112 | 0 | mozilla::ipc::PrincipalToPrincipalInfo(mLoadInfo->TriggeringPrincipal(), |
113 | 0 | &triggeringPrincipalInfo); |
114 | 0 | mozilla::ipc::PrincipalToPrincipalInfo(mLoadInfo->PrincipalToInherit(), |
115 | 0 | &principalToInheritInfo); |
116 | 0 | securityFlags = mLoadInfo->GetSecurityFlags(); |
117 | 0 | policyType = mLoadInfo->InternalContentPolicyType(); |
118 | 0 | } |
119 | 0 | else { |
120 | 0 | // use default values if no loadInfo is provided |
121 | 0 | mozilla::ipc::PrincipalToPrincipalInfo(nsContentUtils::GetSystemPrincipal(), |
122 | 0 | &requestingPrincipalInfo); |
123 | 0 | mozilla::ipc::PrincipalToPrincipalInfo(nsContentUtils::GetSystemPrincipal(), |
124 | 0 | &triggeringPrincipalInfo); |
125 | 0 | mozilla::ipc::PrincipalToPrincipalInfo(nsContentUtils::GetSystemPrincipal(), |
126 | 0 | &principalToInheritInfo); |
127 | 0 | securityFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL; |
128 | 0 | policyType = nsIContentPolicy::TYPE_OTHER; |
129 | 0 | } |
130 | 0 |
|
131 | 0 | SendInit(serializedUri, |
132 | 0 | requestingPrincipalInfo, |
133 | 0 | triggeringPrincipalInfo, |
134 | 0 | principalToInheritInfo, |
135 | 0 | securityFlags, |
136 | 0 | policyType); |
137 | 0 | return NS_OK; |
138 | 0 | } |
139 | | |
140 | | //----------------------------------------------------------------------------- |
141 | | // WyciwygChannelChild::PWyciwygChannelChild |
142 | | //----------------------------------------------------------------------------- |
143 | | |
144 | | class WyciwygStartRequestEvent |
145 | | : public NeckoTargetChannelEvent<WyciwygChannelChild> |
146 | | { |
147 | | public: |
148 | | WyciwygStartRequestEvent(WyciwygChannelChild* child, |
149 | | const nsresult& statusCode, |
150 | | const int64_t& contentLength, |
151 | | const int32_t& source, |
152 | | const nsCString& charset, |
153 | | const nsCString& securityInfo) |
154 | | : NeckoTargetChannelEvent<WyciwygChannelChild>(child) |
155 | | , mStatusCode(statusCode) |
156 | | , mContentLength(contentLength) |
157 | | , mSource(source) |
158 | | , mCharset(charset) |
159 | 0 | , mSecurityInfo(securityInfo) {} |
160 | | |
161 | 0 | void Run() override { mChild->OnStartRequest(mStatusCode, mContentLength, |
162 | 0 | mSource, mCharset, |
163 | 0 | mSecurityInfo); } |
164 | | |
165 | | private: |
166 | | nsresult mStatusCode; |
167 | | int64_t mContentLength; |
168 | | int32_t mSource; |
169 | | nsCString mCharset; |
170 | | nsCString mSecurityInfo; |
171 | | }; |
172 | | |
173 | | mozilla::ipc::IPCResult |
174 | | WyciwygChannelChild::RecvOnStartRequest(const nsresult& statusCode, |
175 | | const int64_t& contentLength, |
176 | | const int32_t& source, |
177 | | const nsCString& charset, |
178 | | const nsCString& securityInfo) |
179 | 0 | { |
180 | 0 | mEventQ->RunOrEnqueue(new WyciwygStartRequestEvent(this, statusCode, |
181 | 0 | contentLength, source, |
182 | 0 | charset, securityInfo)); |
183 | 0 | return IPC_OK(); |
184 | 0 | } |
185 | | |
186 | | void |
187 | | WyciwygChannelChild::OnStartRequest(const nsresult& statusCode, |
188 | | const int64_t& contentLength, |
189 | | const int32_t& source, |
190 | | const nsCString& charset, |
191 | | const nsCString& securityInfo) |
192 | 0 | { |
193 | 0 | LOG(("WyciwygChannelChild::RecvOnStartRequest [this=%p]\n", this)); |
194 | 0 |
|
195 | 0 | mState = WCC_ONSTART; |
196 | 0 |
|
197 | 0 | if (!mCanceled && NS_SUCCEEDED(mStatus)) { |
198 | 0 | mStatus = statusCode; |
199 | 0 | } |
200 | 0 | mContentLength = contentLength; |
201 | 0 | mCharsetSource = source; |
202 | 0 | mCharset = charset; |
203 | 0 |
|
204 | 0 | if (!securityInfo.IsEmpty()) { |
205 | 0 | NS_DeserializeObject(securityInfo, getter_AddRefs(mSecurityInfo)); |
206 | 0 | } |
207 | 0 |
|
208 | 0 | AutoEventEnqueuer ensureSerialDispatch(mEventQ); |
209 | 0 |
|
210 | 0 | nsresult rv = mListener->OnStartRequest(this, mListenerContext); |
211 | 0 | if (NS_FAILED(rv)) |
212 | 0 | Cancel(rv); |
213 | 0 | } |
214 | | |
215 | | class WyciwygDataAvailableEvent |
216 | | : public NeckoTargetChannelEvent<WyciwygChannelChild> |
217 | | { |
218 | | public: |
219 | | WyciwygDataAvailableEvent(WyciwygChannelChild* child, |
220 | | const nsCString& data, |
221 | | const uint64_t& offset) |
222 | | : NeckoTargetChannelEvent<WyciwygChannelChild>(child) |
223 | | , mData(data) |
224 | 0 | , mOffset(offset) {} |
225 | | |
226 | 0 | void Run() override { mChild->OnDataAvailable(mData, mOffset); } |
227 | | |
228 | | private: |
229 | | nsCString mData; |
230 | | uint64_t mOffset; |
231 | | }; |
232 | | |
233 | | mozilla::ipc::IPCResult |
234 | | WyciwygChannelChild::RecvOnDataAvailable(const nsCString& data, |
235 | | const uint64_t& offset) |
236 | 0 | { |
237 | 0 | mEventQ->RunOrEnqueue(new WyciwygDataAvailableEvent(this, data, offset)); |
238 | 0 | return IPC_OK(); |
239 | 0 | } |
240 | | |
241 | | void |
242 | | WyciwygChannelChild::OnDataAvailable(const nsCString& data, |
243 | | const uint64_t& offset) |
244 | 0 | { |
245 | 0 | LOG(("WyciwygChannelChild::RecvOnDataAvailable [this=%p]\n", this)); |
246 | 0 |
|
247 | 0 | if (mCanceled) |
248 | 0 | return; |
249 | 0 | |
250 | 0 | mState = WCC_ONDATA; |
251 | 0 |
|
252 | 0 | // NOTE: the OnDataAvailable contract requires the client to read all the data |
253 | 0 | // in the inputstream. This code relies on that ('data' will go away after |
254 | 0 | // this function). Apparently the previous, non-e10s behavior was to actually |
255 | 0 | // support only reading part of the data, allowing later calls to read the |
256 | 0 | // rest. |
257 | 0 | nsCOMPtr<nsIInputStream> stringStream; |
258 | 0 | nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream), |
259 | 0 | data.get(), |
260 | 0 | data.Length(), |
261 | 0 | NS_ASSIGNMENT_DEPEND); |
262 | 0 | if (NS_FAILED(rv)) { |
263 | 0 | Cancel(rv); |
264 | 0 | return; |
265 | 0 | } |
266 | 0 | |
267 | 0 | AutoEventEnqueuer ensureSerialDispatch(mEventQ); |
268 | 0 |
|
269 | 0 | rv = mListener->OnDataAvailable(this, mListenerContext, |
270 | 0 | stringStream, offset, data.Length()); |
271 | 0 | if (NS_FAILED(rv)) |
272 | 0 | Cancel(rv); |
273 | 0 |
|
274 | 0 | if (mProgressSink && NS_SUCCEEDED(rv)) { |
275 | 0 | mProgressSink->OnProgress(this, nullptr, offset + data.Length(), |
276 | 0 | mContentLength); |
277 | 0 | } |
278 | 0 | } |
279 | | |
280 | | class WyciwygStopRequestEvent |
281 | | : public NeckoTargetChannelEvent<WyciwygChannelChild> |
282 | | { |
283 | | public: |
284 | | WyciwygStopRequestEvent(WyciwygChannelChild* child, |
285 | | const nsresult& statusCode) |
286 | | : NeckoTargetChannelEvent<WyciwygChannelChild>(child) |
287 | 0 | , mStatusCode(statusCode) {} |
288 | | |
289 | 0 | void Run() override { mChild->OnStopRequest(mStatusCode); } |
290 | | |
291 | | private: |
292 | | nsresult mStatusCode; |
293 | | }; |
294 | | |
295 | | mozilla::ipc::IPCResult |
296 | | WyciwygChannelChild::RecvOnStopRequest(const nsresult& statusCode) |
297 | 0 | { |
298 | 0 | mEventQ->RunOrEnqueue(new WyciwygStopRequestEvent(this, statusCode)); |
299 | 0 | return IPC_OK(); |
300 | 0 | } |
301 | | |
302 | | void |
303 | | WyciwygChannelChild::OnStopRequest(const nsresult& statusCode) |
304 | 0 | { |
305 | 0 | LOG(("WyciwygChannelChild::RecvOnStopRequest [this=%p status=%" PRIu32 "]\n", |
306 | 0 | this, static_cast<uint32_t>(statusCode))); |
307 | 0 |
|
308 | 0 | { // We need to ensure that all IPDL message dispatching occurs |
309 | 0 | // before we delete the protocol below |
310 | 0 | AutoEventEnqueuer ensureSerialDispatch(mEventQ); |
311 | 0 |
|
312 | 0 | mState = WCC_ONSTOP; |
313 | 0 |
|
314 | 0 | mIsPending = false; |
315 | 0 |
|
316 | 0 | if (!mCanceled) |
317 | 0 | mStatus = statusCode; |
318 | 0 |
|
319 | 0 | mListener->OnStopRequest(this, mListenerContext, statusCode); |
320 | 0 |
|
321 | 0 | mListener = nullptr; |
322 | 0 | mListenerContext = nullptr; |
323 | 0 |
|
324 | 0 | if (mLoadGroup) |
325 | 0 | mLoadGroup->RemoveRequest(this, nullptr, mStatus); |
326 | 0 |
|
327 | 0 | mCallbacks = nullptr; |
328 | 0 | mProgressSink = nullptr; |
329 | 0 | } |
330 | 0 |
|
331 | 0 | if (mIPCOpen) |
332 | 0 | PWyciwygChannelChild::Send__delete__(this); |
333 | 0 | } |
334 | | |
335 | | class WyciwygCancelEvent : public NeckoTargetChannelEvent<WyciwygChannelChild> |
336 | | { |
337 | | public: |
338 | | WyciwygCancelEvent(WyciwygChannelChild* child, const nsresult& status) |
339 | | : NeckoTargetChannelEvent<WyciwygChannelChild>(child) |
340 | 0 | , mStatus(status) {} |
341 | | |
342 | 0 | void Run() override { mChild->CancelEarly(mStatus); } |
343 | | |
344 | | private: |
345 | | nsresult mStatus; |
346 | | }; |
347 | | |
348 | | mozilla::ipc::IPCResult |
349 | | WyciwygChannelChild::RecvCancelEarly(const nsresult& statusCode) |
350 | 0 | { |
351 | 0 | mEventQ->RunOrEnqueue(new WyciwygCancelEvent(this, statusCode)); |
352 | 0 | return IPC_OK(); |
353 | 0 | } |
354 | | |
355 | | void WyciwygChannelChild::CancelEarly(const nsresult& statusCode) |
356 | 0 | { |
357 | 0 | LOG(("WyciwygChannelChild::CancelEarly [this=%p]\n", this)); |
358 | 0 |
|
359 | 0 | if (mCanceled) |
360 | 0 | return; |
361 | 0 | |
362 | 0 | mCanceled = true; |
363 | 0 | mStatus = statusCode; |
364 | 0 |
|
365 | 0 | mIsPending = false; |
366 | 0 | if (mLoadGroup) |
367 | 0 | mLoadGroup->RemoveRequest(this, nullptr, mStatus); |
368 | 0 |
|
369 | 0 | if (mListener) { |
370 | 0 | mListener->OnStartRequest(this, mListenerContext); |
371 | 0 | mListener->OnStopRequest(this, mListenerContext, mStatus); |
372 | 0 | } |
373 | 0 | mListener = nullptr; |
374 | 0 | mListenerContext = nullptr; |
375 | 0 |
|
376 | 0 | if (mIPCOpen) |
377 | 0 | PWyciwygChannelChild::Send__delete__(this); |
378 | 0 | } |
379 | | |
380 | | //----------------------------------------------------------------------------- |
381 | | // nsIRequest |
382 | | //----------------------------------------------------------------------------- |
383 | | |
384 | | NS_IMETHODIMP |
385 | | WyciwygChannelChild::GetName(nsACString & aName) |
386 | 0 | { |
387 | 0 | return mURI->GetSpec(aName); |
388 | 0 | } |
389 | | |
390 | | NS_IMETHODIMP |
391 | | WyciwygChannelChild::IsPending(bool *aIsPending) |
392 | 0 | { |
393 | 0 | *aIsPending = mIsPending; |
394 | 0 | return NS_OK; |
395 | 0 | } |
396 | | |
397 | | NS_IMETHODIMP |
398 | | WyciwygChannelChild::GetStatus(nsresult *aStatus) |
399 | 0 | { |
400 | 0 | *aStatus = mStatus; |
401 | 0 | return NS_OK; |
402 | 0 | } |
403 | | |
404 | | NS_IMETHODIMP |
405 | | WyciwygChannelChild::Cancel(nsresult aStatus) |
406 | 0 | { |
407 | 0 | if (mCanceled) |
408 | 0 | return NS_OK; |
409 | 0 | |
410 | 0 | mCanceled = true; |
411 | 0 | mStatus = aStatus; |
412 | 0 | if (mIPCOpen) |
413 | 0 | SendCancel(aStatus); |
414 | 0 | return NS_OK; |
415 | 0 | } |
416 | | |
417 | | NS_IMETHODIMP |
418 | | WyciwygChannelChild::Suspend() |
419 | 0 | { |
420 | 0 | return NS_ERROR_NOT_IMPLEMENTED; |
421 | 0 | } |
422 | | |
423 | | NS_IMETHODIMP |
424 | | WyciwygChannelChild::Resume() |
425 | 0 | { |
426 | 0 | return NS_ERROR_NOT_IMPLEMENTED; |
427 | 0 | } |
428 | | |
429 | | NS_IMETHODIMP |
430 | | WyciwygChannelChild::GetLoadGroup(nsILoadGroup * *aLoadGroup) |
431 | 0 | { |
432 | 0 | *aLoadGroup = mLoadGroup; |
433 | 0 | NS_IF_ADDREF(*aLoadGroup); |
434 | 0 | return NS_OK; |
435 | 0 | } |
436 | | NS_IMETHODIMP |
437 | | WyciwygChannelChild::SetLoadGroup(nsILoadGroup * aLoadGroup) |
438 | 0 | { |
439 | 0 | if (!CanSetLoadGroup(aLoadGroup)) { |
440 | 0 | return NS_ERROR_FAILURE; |
441 | 0 | } |
442 | 0 | |
443 | 0 | mLoadGroup = aLoadGroup; |
444 | 0 | NS_QueryNotificationCallbacks(mCallbacks, |
445 | 0 | mLoadGroup, |
446 | 0 | NS_GET_IID(nsIProgressEventSink), |
447 | 0 | getter_AddRefs(mProgressSink)); |
448 | 0 |
|
449 | 0 | UpdatePrivateBrowsing(); |
450 | 0 | return NS_OK; |
451 | 0 | } |
452 | | |
453 | | NS_IMETHODIMP |
454 | | WyciwygChannelChild::GetLoadFlags(nsLoadFlags *aLoadFlags) |
455 | 0 | { |
456 | 0 | *aLoadFlags = mLoadFlags; |
457 | 0 | return NS_OK; |
458 | 0 | } |
459 | | NS_IMETHODIMP |
460 | | WyciwygChannelChild::SetLoadFlags(nsLoadFlags aLoadFlags) |
461 | 0 | { |
462 | 0 | mLoadFlags = aLoadFlags; |
463 | 0 | return NS_OK; |
464 | 0 | } |
465 | | |
466 | | |
467 | | //----------------------------------------------------------------------------- |
468 | | // nsIChannel |
469 | | //----------------------------------------------------------------------------- |
470 | | |
471 | | NS_IMETHODIMP |
472 | | WyciwygChannelChild::GetOriginalURI(nsIURI * *aOriginalURI) |
473 | 0 | { |
474 | 0 | *aOriginalURI = mOriginalURI; |
475 | 0 | NS_ADDREF(*aOriginalURI); |
476 | 0 | return NS_OK; |
477 | 0 | } |
478 | | NS_IMETHODIMP |
479 | | WyciwygChannelChild::SetOriginalURI(nsIURI * aOriginalURI) |
480 | 0 | { |
481 | 0 | NS_ENSURE_TRUE(mState == WCC_INIT, NS_ERROR_UNEXPECTED); |
482 | 0 |
|
483 | 0 | NS_ENSURE_ARG_POINTER(aOriginalURI); |
484 | 0 | mOriginalURI = aOriginalURI; |
485 | 0 | return NS_OK; |
486 | 0 | } |
487 | | |
488 | | NS_IMETHODIMP |
489 | | WyciwygChannelChild::GetURI(nsIURI * *aURI) |
490 | 0 | { |
491 | 0 | *aURI = mURI; |
492 | 0 | NS_IF_ADDREF(*aURI); |
493 | 0 | return NS_OK; |
494 | 0 | } |
495 | | |
496 | | NS_IMETHODIMP |
497 | | WyciwygChannelChild::GetOwner(nsISupports * *aOwner) |
498 | 0 | { |
499 | 0 | NS_IF_ADDREF(*aOwner = mOwner); |
500 | 0 | return NS_OK; |
501 | 0 | } |
502 | | NS_IMETHODIMP |
503 | | WyciwygChannelChild::SetOwner(nsISupports * aOwner) |
504 | 0 | { |
505 | 0 | mOwner = aOwner; |
506 | 0 | return NS_OK; |
507 | 0 | } |
508 | | |
509 | | NS_IMETHODIMP |
510 | | WyciwygChannelChild::GetLoadInfo(nsILoadInfo **aLoadInfo) |
511 | 0 | { |
512 | 0 | NS_IF_ADDREF(*aLoadInfo = mLoadInfo); |
513 | 0 | return NS_OK; |
514 | 0 | } |
515 | | |
516 | | NS_IMETHODIMP |
517 | | WyciwygChannelChild::SetLoadInfo(nsILoadInfo* aLoadInfo) |
518 | 0 | { |
519 | 0 | mLoadInfo = aLoadInfo; |
520 | 0 | return NS_OK; |
521 | 0 | } |
522 | | |
523 | | NS_IMETHODIMP |
524 | | WyciwygChannelChild::GetIsDocument(bool *aIsDocument) |
525 | 0 | { |
526 | 0 | return NS_GetIsDocumentChannel(this, aIsDocument); |
527 | 0 | } |
528 | | |
529 | | NS_IMETHODIMP |
530 | | WyciwygChannelChild::GetNotificationCallbacks(nsIInterfaceRequestor * *aCallbacks) |
531 | 0 | { |
532 | 0 | *aCallbacks = mCallbacks; |
533 | 0 | NS_IF_ADDREF(*aCallbacks); |
534 | 0 | return NS_OK; |
535 | 0 | } |
536 | | NS_IMETHODIMP |
537 | | WyciwygChannelChild::SetNotificationCallbacks(nsIInterfaceRequestor * aCallbacks) |
538 | 0 | { |
539 | 0 | if (!CanSetCallbacks(aCallbacks)) { |
540 | 0 | return NS_ERROR_FAILURE; |
541 | 0 | } |
542 | 0 | |
543 | 0 | mCallbacks = aCallbacks; |
544 | 0 | NS_QueryNotificationCallbacks(mCallbacks, |
545 | 0 | mLoadGroup, |
546 | 0 | NS_GET_IID(nsIProgressEventSink), |
547 | 0 | getter_AddRefs(mProgressSink)); |
548 | 0 | UpdatePrivateBrowsing(); |
549 | 0 | return NS_OK; |
550 | 0 | } |
551 | | |
552 | | NS_IMETHODIMP |
553 | | WyciwygChannelChild::GetSecurityInfo(nsISupports * *aSecurityInfo) |
554 | 0 | { |
555 | 0 | NS_IF_ADDREF(*aSecurityInfo = mSecurityInfo); |
556 | 0 |
|
557 | 0 | return NS_OK; |
558 | 0 | } |
559 | | |
560 | | NS_IMETHODIMP |
561 | | WyciwygChannelChild::GetContentType(nsACString & aContentType) |
562 | 0 | { |
563 | 0 | aContentType.AssignLiteral(WYCIWYG_TYPE); |
564 | 0 | return NS_OK; |
565 | 0 | } |
566 | | NS_IMETHODIMP |
567 | | WyciwygChannelChild::SetContentType(const nsACString & aContentType) |
568 | 0 | { |
569 | 0 | return NS_ERROR_NOT_IMPLEMENTED; |
570 | 0 | } |
571 | | |
572 | | NS_IMETHODIMP |
573 | | WyciwygChannelChild::GetContentCharset(nsACString & aContentCharset) |
574 | 0 | { |
575 | 0 | aContentCharset.AssignLiteral("UTF-16LE"); |
576 | 0 | return NS_OK; |
577 | 0 | } |
578 | | NS_IMETHODIMP |
579 | | WyciwygChannelChild::SetContentCharset(const nsACString & aContentCharset) |
580 | 0 | { |
581 | 0 | return NS_ERROR_NOT_IMPLEMENTED; |
582 | 0 | } |
583 | | |
584 | | NS_IMETHODIMP |
585 | | WyciwygChannelChild::GetContentDisposition(uint32_t *aContentDisposition) |
586 | 0 | { |
587 | 0 | return NS_ERROR_NOT_AVAILABLE; |
588 | 0 | } |
589 | | |
590 | | NS_IMETHODIMP |
591 | | WyciwygChannelChild::SetContentDisposition(uint32_t aContentDisposition) |
592 | 0 | { |
593 | 0 | return NS_ERROR_NOT_AVAILABLE; |
594 | 0 | } |
595 | | |
596 | | NS_IMETHODIMP |
597 | | WyciwygChannelChild::GetContentDispositionFilename(nsAString &aContentDispositionFilename) |
598 | 0 | { |
599 | 0 | return NS_ERROR_NOT_AVAILABLE; |
600 | 0 | } |
601 | | |
602 | | NS_IMETHODIMP |
603 | | WyciwygChannelChild::SetContentDispositionFilename(const nsAString &aContentDispositionFilename) |
604 | 0 | { |
605 | 0 | return NS_ERROR_NOT_AVAILABLE; |
606 | 0 | } |
607 | | |
608 | | NS_IMETHODIMP |
609 | | WyciwygChannelChild::GetContentDispositionHeader(nsACString &aContentDispositionHeader) |
610 | 0 | { |
611 | 0 | return NS_ERROR_NOT_AVAILABLE; |
612 | 0 | } |
613 | | |
614 | | NS_IMETHODIMP |
615 | | WyciwygChannelChild::GetContentLength(int64_t *aContentLength) |
616 | 0 | { |
617 | 0 | return NS_ERROR_NOT_IMPLEMENTED; |
618 | 0 | } |
619 | | NS_IMETHODIMP |
620 | | WyciwygChannelChild::SetContentLength(int64_t aContentLength) |
621 | 0 | { |
622 | 0 | return NS_ERROR_NOT_IMPLEMENTED; |
623 | 0 | } |
624 | | |
625 | | NS_IMETHODIMP |
626 | | WyciwygChannelChild::Open(nsIInputStream **_retval) |
627 | 0 | { |
628 | 0 | return NS_ERROR_NOT_IMPLEMENTED; |
629 | 0 | } |
630 | | |
631 | | NS_IMETHODIMP |
632 | | WyciwygChannelChild::Open2(nsIInputStream** aStream) |
633 | 0 | { |
634 | 0 | nsCOMPtr<nsIStreamListener> listener; |
635 | 0 | nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener); |
636 | 0 | NS_ENSURE_SUCCESS(rv, rv); |
637 | 0 | return Open(aStream); |
638 | 0 | } |
639 | | |
640 | | static mozilla::dom::TabChild* |
641 | | GetTabChild(nsIChannel* aChannel) |
642 | 0 | { |
643 | 0 | nsCOMPtr<nsITabChild> iTabChild; |
644 | 0 | NS_QueryNotificationCallbacks(aChannel, iTabChild); |
645 | 0 | return iTabChild ? static_cast<mozilla::dom::TabChild*>(iTabChild.get()) : nullptr; |
646 | 0 | } |
647 | | |
648 | | NS_IMETHODIMP |
649 | | WyciwygChannelChild::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext) |
650 | 0 | { |
651 | 0 | MOZ_ASSERT(!mLoadInfo || |
652 | 0 | mLoadInfo->GetSecurityMode() == 0 || |
653 | 0 | mLoadInfo->GetInitialSecurityCheckDone() || |
654 | 0 | (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL && |
655 | 0 | nsContentUtils::IsSystemPrincipal(mLoadInfo->LoadingPrincipal())), |
656 | 0 | "security flags in loadInfo but asyncOpen2() not called"); |
657 | 0 |
|
658 | 0 | LOG(("WyciwygChannelChild::AsyncOpen [this=%p]\n", this)); |
659 | 0 |
|
660 | 0 | // The only places creating wyciwyg: channels should be |
661 | 0 | // HTMLDocument::OpenCommon and session history. Both should be setting an |
662 | 0 | // owner or loadinfo. |
663 | 0 | MOZ_ASSERT(mOwner || mLoadInfo, "Must have a principal"); |
664 | 0 | NS_ENSURE_STATE(mOwner || mLoadInfo); |
665 | 0 |
|
666 | 0 | NS_ENSURE_ARG_POINTER(aListener); |
667 | 0 | NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); |
668 | 0 |
|
669 | 0 | mListener = aListener; |
670 | 0 | mListenerContext = aContext; |
671 | 0 | mIsPending = true; |
672 | 0 |
|
673 | 0 | if (mLoadGroup) { |
674 | 0 | mLoadGroup->AddRequest(this, nullptr); |
675 | 0 | } |
676 | 0 |
|
677 | 0 | URIParams originalURI; |
678 | 0 | SerializeURI(mOriginalURI, originalURI); |
679 | 0 |
|
680 | 0 | mozilla::dom::TabChild* tabChild = GetTabChild(this); |
681 | 0 | if (MissingRequiredTabChild(tabChild, "wyciwyg")) { |
682 | 0 | mCallbacks = nullptr; |
683 | 0 | return NS_ERROR_ILLEGAL_VALUE; |
684 | 0 | } |
685 | 0 | |
686 | 0 | PBrowserOrId browser = static_cast<ContentChild*>(Manager()->Manager()) |
687 | 0 | ->GetBrowserOrId(tabChild); |
688 | 0 |
|
689 | 0 | SendAsyncOpen(originalURI, mLoadFlags, IPC::SerializedLoadContext(this), browser); |
690 | 0 |
|
691 | 0 | mSentAppData = true; |
692 | 0 | mState = WCC_OPENED; |
693 | 0 |
|
694 | 0 | return NS_OK; |
695 | 0 | } |
696 | | |
697 | | NS_IMETHODIMP |
698 | | WyciwygChannelChild::AsyncOpen2(nsIStreamListener *aListener) |
699 | 0 | { |
700 | 0 | nsCOMPtr<nsIStreamListener> listener = aListener; |
701 | 0 | nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener); |
702 | 0 | if (NS_FAILED(rv)) { |
703 | 0 | mCallbacks = nullptr; |
704 | 0 | return rv; |
705 | 0 | } |
706 | 0 | return AsyncOpen(listener, nullptr); |
707 | 0 | } |
708 | | |
709 | | //----------------------------------------------------------------------------- |
710 | | // nsIWyciwygChannel |
711 | | //----------------------------------------------------------------------------- |
712 | | |
713 | | NS_IMETHODIMP |
714 | | WyciwygChannelChild::WriteToCacheEntry(const nsAString & aData) |
715 | 0 | { |
716 | 0 | NS_ENSURE_TRUE((mState == WCC_INIT) || |
717 | 0 | (mState == WCC_ONWRITE), NS_ERROR_UNEXPECTED); |
718 | 0 |
|
719 | 0 | if (!mSentAppData) { |
720 | 0 | mozilla::dom::TabChild* tabChild = GetTabChild(this); |
721 | 0 |
|
722 | 0 | PBrowserOrId browser = static_cast<ContentChild*>(Manager()->Manager()) |
723 | 0 | ->GetBrowserOrId(tabChild); |
724 | 0 |
|
725 | 0 | SendAppData(IPC::SerializedLoadContext(this), browser); |
726 | 0 | mSentAppData = true; |
727 | 0 | } |
728 | 0 |
|
729 | 0 | mState = WCC_ONWRITE; |
730 | 0 |
|
731 | 0 | // Give ourselves a megabyte of headroom for the message size. Convert bytes |
732 | 0 | // to wide chars. |
733 | 0 | static const size_t kMaxMessageSize = (IPC::Channel::kMaximumMessageSize - 1024) / 2; |
734 | 0 |
|
735 | 0 | size_t curIndex = 0; |
736 | 0 | size_t charsRemaining = aData.Length(); |
737 | 0 | do { |
738 | 0 | size_t chunkSize = std::min(charsRemaining, kMaxMessageSize); |
739 | 0 | SendWriteToCacheEntry(Substring(aData, curIndex, chunkSize)); |
740 | 0 |
|
741 | 0 | charsRemaining -= chunkSize; |
742 | 0 | curIndex += chunkSize; |
743 | 0 | } while (charsRemaining != 0); |
744 | 0 |
|
745 | 0 | return NS_OK; |
746 | 0 | } |
747 | | |
748 | | NS_IMETHODIMP |
749 | | WyciwygChannelChild::CloseCacheEntry(nsresult reason) |
750 | 0 | { |
751 | 0 | NS_ENSURE_TRUE(mState == WCC_ONWRITE, NS_ERROR_UNEXPECTED); |
752 | 0 |
|
753 | 0 | SendCloseCacheEntry(reason); |
754 | 0 | mState = WCC_ONCLOSED; |
755 | 0 |
|
756 | 0 | if (mIPCOpen) |
757 | 0 | PWyciwygChannelChild::Send__delete__(this); |
758 | 0 |
|
759 | 0 | return NS_OK; |
760 | 0 | } |
761 | | |
762 | | NS_IMETHODIMP |
763 | | WyciwygChannelChild::SetSecurityInfo(nsISupports *aSecurityInfo) |
764 | 0 | { |
765 | 0 | mSecurityInfo = aSecurityInfo; |
766 | 0 |
|
767 | 0 | if (mSecurityInfo) { |
768 | 0 | nsCOMPtr<nsISerializable> serializable = do_QueryInterface(mSecurityInfo); |
769 | 0 | if (serializable) { |
770 | 0 | nsCString secInfoStr; |
771 | 0 | NS_SerializeToString(serializable, secInfoStr); |
772 | 0 | SendSetSecurityInfo(secInfoStr); |
773 | 0 | } |
774 | 0 | else { |
775 | 0 | NS_WARNING("Can't serialize security info"); |
776 | 0 | } |
777 | 0 | } |
778 | 0 |
|
779 | 0 | return NS_OK; |
780 | 0 | } |
781 | | |
782 | | NS_IMETHODIMP |
783 | | WyciwygChannelChild::SetCharsetAndSource(int32_t aSource, const nsACString & aCharset) |
784 | 0 | { |
785 | 0 | // mState == WCC_ONSTART when reading from the channel |
786 | 0 | // mState == WCC_INIT when writing to the cache |
787 | 0 | NS_ENSURE_TRUE((mState == WCC_ONSTART) || |
788 | 0 | (mState == WCC_INIT), NS_ERROR_UNEXPECTED); |
789 | 0 |
|
790 | 0 | mCharsetSource = aSource; |
791 | 0 | mCharset = aCharset; |
792 | 0 |
|
793 | 0 | // TODO ensure that nsWyciwygChannel in the parent has still the cache entry |
794 | 0 | SendSetCharsetAndSource(mCharsetSource, mCharset); |
795 | 0 | return NS_OK; |
796 | 0 | } |
797 | | |
798 | | NS_IMETHODIMP |
799 | | WyciwygChannelChild::GetCharsetAndSource(int32_t *aSource, nsACString & _retval) |
800 | 0 | { |
801 | 0 | NS_ENSURE_TRUE((mState == WCC_ONSTART) || |
802 | 0 | (mState == WCC_ONDATA) || |
803 | 0 | (mState == WCC_ONSTOP), NS_ERROR_NOT_AVAILABLE); |
804 | 0 |
|
805 | 0 | if (mCharsetSource == kCharsetUninitialized) |
806 | 0 | return NS_ERROR_NOT_AVAILABLE; |
807 | 0 | |
808 | 0 | *aSource = mCharsetSource; |
809 | 0 | _retval = mCharset; |
810 | 0 | return NS_OK; |
811 | 0 | } |
812 | | |
813 | | //------------------------------------------------------------------------------ |
814 | | } // namespace net |
815 | | } // namespace mozilla |