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