Coverage Report

Created: 2018-09-25 14:53

/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