~ubuntu-branches/ubuntu/trusty/enigmail/trusty-updates

« back to all changes in this revision

Viewing changes to extensions/enigmail/ipc/src/nsPipeChannel.cpp

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2011-06-07 14:35:53 UTC
  • mfrom: (0.12.1 upstream)
  • Revision ID: package-import@ubuntu.com-20110607143553-fbgqhhvh8g8h6j1y
Tags: 2:1.2~a2~cvs20110606t2200-0ubuntu1
* Update to latest trunk snapshot for Thunderbird beta compat

* Remove build/pgo/profileserver.py from debian/clean. The new build
  system has a target depending on this
  - update debian/clean
* Drop debian/patches/autoconf.diff, just generate this at build time
* Refresh debian/patches/build_system_dont_link_libxul.diff
* libipc seems to be renamed to libipc-pipe. Fix genxpi and chrome.manifest
  to fix this 
  - add debian/patches/ipc-pipe_rename.diff
  - update debian/patches/series
* The makefiles in extensions/enigmail/ipc have an incorrect DEPTH
  attribute. Fix this so that they can find the rest of the build system
  - add debian/patches/makefile_depth.diff
  - update debian/patches/series
* Drop debian/patches/makefile-in-empty-xpcom-fix.diff - fixed in the
  current version
* Don't register a class ID multiple times, as this breaks enigmail entirely
  - add debian/patches/dont_register_cids_multiple_times.diff
  - update debian/patches/series
* Look for the Thunderbird 5 SDK
  - update debian/rules
  - update debian/control
* Run autoconf2.13 at build time
  - update debian/rules
  - update debian/control
* Add useless mesa-common-dev build-dep, just to satisfy the build system.
  We should just patch this out entirely really, but that's for another upload
  - update debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * The contents of this file are subject to the Mozilla Public
3
 
 * License Version 1.1 (the "MPL"); you may not use this file
4
 
 * except in compliance with the MPL. You may obtain a copy of
5
 
 * the MPL at http://www.mozilla.org/MPL/
6
 
 *
7
 
 * Software distributed under the MPL is distributed on an "AS
8
 
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9
 
 * implied. See the MPL for the specific language governing
10
 
 * rights and limitations under the MPL.
11
 
 *
12
 
 * The Original Code is protoZilla.
13
 
 *
14
 
 * The Initial Developer of the Original Code is Ramalingam Saravanan.
15
 
 * Portions created by Ramalingam Saravanan <svn@xmlterm.org> are
16
 
 * Copyright (C) 2000 Ramalingam Saravanan. All Rights Reserved.
17
 
 *
18
 
 * Contributor(s):
19
 
 * Patrick Brunschwig <patrick@mozilla-enigmail.org>
20
 
 *
21
 
 * Alternatively, the contents of this file may be used under the
22
 
 * terms of the GNU General Public License (the "GPL"), in which case
23
 
 * the provisions of the GPL are applicable instead of
24
 
 * those above. If you wish to allow use of your version of this
25
 
 * file only under the terms of the GPL and not to allow
26
 
 * others to use your version of this file under the MPL, indicate
27
 
 * your decision by deleting the provisions above and replace them
28
 
 * with the notice and other provisions required by the GPL.
29
 
 * If you do not delete the provisions above, a recipient
30
 
 * may use your version of this file under either the MPL or the
31
 
 * GPL.
32
 
 */
33
 
 
34
 
// NOTE: nsPipeChannel is not a thread-safe class
35
 
 
36
 
// Logging of debug output
37
 
// The following define statement should occur before any include statements
38
 
#define FORCE_PR_LOG       /* Allow logging even in release build */
39
 
 
40
 
#include "ipc.h"
41
 
#include "prlog.h"
42
 
#include "nsAutoLock.h"
43
 
#include "plstr.h"
44
 
 
45
 
#ifndef _IPC_FORCE_INTERNAL_API
46
 
#include "nsStringAPI.h"
47
 
#else
48
 
#include "nsString.h"
49
 
#endif
50
 
 
51
 
#include "nsIProxyObjectManager.h"
52
 
#include "nsIThread.h"
53
 
#include "nsIURI.h"
54
 
#include "nsIURL.h"
55
 
#include "nsIHttpChannel.h"
56
 
#include "nsIFile.h"
57
 
#include "nsNetUtil.h"
58
 
 
59
 
#include "nsMimeTypes.h"
60
 
#include "nsIMIMEService.h"
61
 
 
62
 
#include "nsXPCOMCIDInternal.h"
63
 
 
64
 
#include "nsPipeChannel.h"
65
 
 
66
 
#ifdef PR_LOGGING
67
 
PRLogModuleInfo* gPipeChannelLog = NULL;
68
 
#endif
69
 
 
70
 
#define ERROR_LOG(args)    PR_LOG(gPipeChannelLog,PR_LOG_ERROR,args)
71
 
#define WARNING_LOG(args)  PR_LOG(gPipeChannelLog,PR_LOG_WARNING,args)
72
 
#define DEBUG_LOG(args)    PR_LOG(gPipeChannelLog,PR_LOG_DEBUG,args)
73
 
 
74
 
 
75
 
#define NS_NET_STATUS_RECEIVING_FROM  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 6)
76
 
 
77
 
///////////////////////////////////////////////////////////////////////////////
78
 
 
79
 
nsPipeChannel::nsPipeChannel()
80
 
    : mFinalized(PR_FALSE),
81
 
      mRestricted(PR_FALSE),
82
 
      mChannelState(CHANNEL_NOT_YET_OPENED),
83
 
      mPostingData(PR_FALSE),
84
 
      mStatus(NS_OK),
85
 
 
86
 
      mNoMimeHeaders(PR_FALSE),
87
 
 
88
 
      mBufferSegmentSize(-1),
89
 
      mBufferMaxSize(-1),
90
 
 
91
 
      mLoadFlags(LOAD_NORMAL),
92
 
 
93
 
      mContentType(UNKNOWN_CONTENT_TYPE),
94
 
      mContentLength(-1),
95
 
 
96
 
      mHeaderContentType(UNKNOWN_CONTENT_TYPE),
97
 
      mHeaderContentLength(-1),
98
 
      mHeaderCharset(""),
99
 
 
100
 
      mContentReceived(0)
101
 
 
102
 
{
103
 
  NS_INIT_ISUPPORTS();
104
 
 
105
 
#ifdef PR_LOGGING
106
 
  if (gPipeChannelLog == nsnull) {
107
 
    gPipeChannelLog = PR_NewLogModule("nsPipeChannel");
108
 
  }
109
 
#endif
110
 
 
111
 
  DEBUG_LOG(("nsPipeChannel:: <<<<<<<<< CTOR(%p)\n", this));
112
 
 
113
 
}
114
 
 
115
 
nsPipeChannel::~nsPipeChannel()
116
 
{
117
 
 
118
 
  DEBUG_LOG(("nsPipeChannel:: >>>>>>>>> DTOR(%p)\n", this));
119
 
 
120
 
  Finalize(PR_TRUE);
121
 
}
122
 
 
123
 
nsresult
124
 
nsPipeChannel::Finalize(PRBool destructor)
125
 
{
126
 
  nsresult rv = NS_OK;
127
 
 
128
 
  DEBUG_LOG(("nsPipeChannel::Finalize:\n"));
129
 
 
130
 
  if (mFinalized)
131
 
    return NS_OK;
132
 
 
133
 
  mFinalized = PR_TRUE;
134
 
 
135
 
  mChannelState = CHANNEL_CLOSED;
136
 
 
137
 
  if (mStatus == NS_OK)
138
 
    mStatus = NS_BINDING_ABORTED;
139
 
 
140
 
  nsCOMPtr<nsIPipeChannel> self;
141
 
  if (!destructor) {
142
 
    // Hold a reference to ourselves to prevent our DTOR from being called
143
 
    // while finalizing. Automatically released upon returning.
144
 
    self = this;
145
 
  }
146
 
 
147
 
  if (mPipeTransport) {
148
 
    mPipeTransport->Terminate();
149
 
  }
150
 
 
151
 
  // Release owning refs
152
 
  mURI           = nsnull;
153
 
  mOriginalURI   = nsnull;
154
 
 
155
 
  mPipeTransport = nsnull;
156
 
  mPipeRequest   = nsnull;
157
 
 
158
 
  mListener      = nsnull;
159
 
  mContext       = nsnull;
160
 
 
161
 
  mLoadGroup = nsnull;
162
 
  mCallbacks = nsnull;
163
 
  mProgress = nsnull;
164
 
 
165
 
  return rv;
166
 
}
167
 
 
168
 
//
169
 
// --------------------------------------------------------------------------
170
 
// nsISupports implementation...
171
 
// --------------------------------------------------------------------------
172
 
//
173
 
 
174
 
NS_IMPL_THREADSAFE_ISUPPORTS5(nsPipeChannel,
175
 
                              nsIPipeChannel,
176
 
                              nsIChannel,
177
 
                              nsIRequest,
178
 
                              nsIStreamListener,
179
 
                              nsIPipeTransportHeaders)
180
 
 
181
 
///////////////////////////////////////////////////////////////////////////////
182
 
// nsIPipeChannel methods
183
 
///////////////////////////////////////////////////////////////////////////////
184
 
 
185
 
NS_IMETHODIMP
186
 
nsPipeChannel::Init(nsIURI* aURI,
187
 
                    nsIFile *executable,
188
 
                    const char **args,
189
 
                    PRUint32 argCount,
190
 
                    const char **env,
191
 
                    PRUint32 envCount,
192
 
                    PRUint32 timeoutMS,
193
 
                    const char *killString,
194
 
                    PRBool noMimeHeaders,
195
 
                    PRBool mergeStderr,
196
 
                    PRBool restricted,
197
 
                    nsIPipeListener* console)
198
 
{
199
 
  nsresult rv;
200
 
 
201
 
  DEBUG_LOG(("nsPipeChannel::Init:\n"));
202
 
 
203
 
  mRestricted = restricted;
204
 
 
205
 
  mURI = aURI;
206
 
  mOriginalURI = aURI;
207
 
  mNoMimeHeaders = noMimeHeaders;
208
 
 
209
 
  // Try to get URL from URI.
210
 
  nsCOMPtr<nsIURL> url( do_QueryInterface( aURI, &rv ) );
211
 
 
212
 
  if (url) {
213
 
    // Try to get MIME content type from URL (i.e., from file extension)
214
 
    // Note: We don't try to get content type from URIs which are not URLs,
215
 
    // because we have a very loose interpretation of an URI
216
 
 
217
 
    nsCOMPtr<nsIMIMEService> MIMEService (do_GetService("@mozilla.org/mime;1", &rv));
218
 
    NS_ENSURE_SUCCESS(rv, rv);
219
 
 
220
 
    nsCString contentType;
221
 
    rv = MIMEService->GetTypeFromURI(url, contentType);
222
 
 
223
 
    if (NS_SUCCEEDED(rv) && (contentType.Length() > 0)) {
224
 
      mContentType.Assign(contentType);
225
 
    }
226
 
  }
227
 
 
228
 
  // Create an instance of pipe transport
229
 
  mPipeTransport = do_CreateInstance(NS_PIPETRANSPORT_CONTRACTID, &rv);
230
 
  if (NS_FAILED(rv)) {
231
 
 
232
 
    DEBUG_LOG(("nsPipeChannel::Init: Failed to create pipe transport instance\n"));
233
 
    return rv;
234
 
  }
235
 
 
236
 
  PRBool noProxy = PR_FALSE;
237
 
  rv = mPipeTransport->Init(executable, args, argCount, env, envCount,
238
 
                            timeoutMS, killString, noProxy,
239
 
                            mergeStderr, console);
240
 
  if (NS_FAILED(rv)) {
241
 
 
242
 
    DEBUG_LOG(("nsPipeChannel::Init: Failed to initialize pipe transport\n"));
243
 
    return rv;
244
 
  }
245
 
 
246
 
  // Close process STDIN
247
 
  rv = mPipeTransport->CloseStdin();
248
 
  NS_ENSURE_SUCCESS(rv, rv);
249
 
 
250
 
  mChannelState = CHANNEL_OPEN;
251
 
  return NS_OK;
252
 
}
253
 
 
254
 
///////////////////////////////////////////////////////////////////////////////
255
 
// nsIRequest methods
256
 
///////////////////////////////////////////////////////////////////////////////
257
 
 
258
 
NS_IMETHODIMP
259
 
nsPipeChannel::GetName(nsACString &result)
260
 
{
261
 
  DEBUG_LOG(("nsPipeChannel::GetName: \n"));
262
 
 
263
 
  if (!mURI)
264
 
    return NS_ERROR_FAILURE;
265
 
 
266
 
  return mURI->GetSpec(result);
267
 
}
268
 
 
269
 
NS_IMETHODIMP
270
 
nsPipeChannel::IsPending(PRBool *result)
271
 
{
272
 
 
273
 
  DEBUG_LOG(("nsPipeChannel::IsPending: \n"));
274
 
  *result = (mChannelState == CHANNEL_OPEN);
275
 
  return NS_OK;
276
 
}
277
 
 
278
 
NS_IMETHODIMP
279
 
nsPipeChannel::GetStatus(nsresult *status)
280
 
{
281
 
 
282
 
  DEBUG_LOG(("nsPipeChannel::GetStatus: \n"));
283
 
  *status = mStatus;
284
 
  return NS_OK;
285
 
}
286
 
 
287
 
NS_IMETHODIMP
288
 
nsPipeChannel::Cancel(nsresult status)
289
 
{
290
 
  DEBUG_LOG(("nsPipeChannel::Cancel: \n"));
291
 
  // Need a non-zero status code to cancel
292
 
  if (status == NS_OK)
293
 
    return NS_ERROR_FAILURE;
294
 
 
295
 
  if (mStatus == NS_OK)
296
 
    mStatus = status;
297
 
 
298
 
  if (mPipeRequest)
299
 
    mPipeRequest->Cancel(mStatus);
300
 
 
301
 
  return Finalize(PR_FALSE);
302
 
}
303
 
 
304
 
NS_IMETHODIMP
305
 
nsPipeChannel::Suspend(void)
306
 
{
307
 
 
308
 
  DEBUG_LOG(("nsPipeChannel::Suspend: \n"));
309
 
  return NS_OK;
310
 
}
311
 
 
312
 
 
313
 
NS_IMETHODIMP
314
 
nsPipeChannel::Resume(void)
315
 
{
316
 
 
317
 
  DEBUG_LOG(("nsPipeChannel::Resume: \n"));
318
 
  return NS_OK;
319
 
}
320
 
 
321
 
 
322
 
NS_IMETHODIMP
323
 
nsPipeChannel::GetLoadGroup(nsILoadGroup * *aLoadGroup)
324
 
{
325
 
 
326
 
  DEBUG_LOG(("nsPipeChannel::GetLoadGroup: \n"));
327
 
  NS_IF_ADDREF(*aLoadGroup = mLoadGroup);
328
 
  return NS_OK;
329
 
}
330
 
 
331
 
NS_IMETHODIMP
332
 
nsPipeChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
333
 
{
334
 
 
335
 
  DEBUG_LOG(("nsPipeChannel::SetLoadGroup: \n"));
336
 
  mLoadGroup = aLoadGroup;
337
 
  return NS_OK;
338
 
}
339
 
 
340
 
NS_IMETHODIMP
341
 
nsPipeChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
342
 
{
343
 
 
344
 
  DEBUG_LOG(("nsPipeChannel::GetLoadFlags: \n"));
345
 
  *aLoadFlags = mLoadFlags;
346
 
  return NS_OK;
347
 
}
348
 
 
349
 
NS_IMETHODIMP
350
 
nsPipeChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
351
 
{
352
 
 
353
 
  DEBUG_LOG(("nsPipeChannel::SetLoadFlags: \n"));
354
 
  mLoadFlags = aLoadFlags;
355
 
  return NS_OK;
356
 
}
357
 
 
358
 
///////////////////////////////////////////////////////////////////////////////
359
 
// nsIChannel methods:
360
 
///////////////////////////////////////////////////////////////////////////////
361
 
 
362
 
NS_IMETHODIMP
363
 
nsPipeChannel::GetOriginalURI(nsIURI* *aURI)
364
 
{
365
 
 
366
 
  DEBUG_LOG(("nsPipeChannel::GetOriginalURI: \n"));
367
 
  NS_IF_ADDREF(*aURI = mOriginalURI.get());
368
 
  return NS_OK;
369
 
}
370
 
 
371
 
NS_IMETHODIMP
372
 
nsPipeChannel::SetOriginalURI(nsIURI* aURI)
373
 
{
374
 
 
375
 
  DEBUG_LOG(("nsPipeChannel::SetOriginalURI: \n"));
376
 
  if (!mRestricted) {
377
 
    // Change original URI only for unrestricted channels
378
 
    mOriginalURI = aURI;
379
 
  }
380
 
  return NS_OK;
381
 
}
382
 
 
383
 
NS_IMETHODIMP
384
 
nsPipeChannel::GetURI(nsIURI* *aURI)
385
 
{
386
 
 
387
 
  DEBUG_LOG(("nsPipeChannel::GetURI: \n"));
388
 
  NS_IF_ADDREF(*aURI = mURI.get());
389
 
  return NS_OK;
390
 
}
391
 
 
392
 
NS_IMETHODIMP
393
 
nsPipeChannel::GetContentType(nsACString &aContentType)
394
 
{
395
 
  if (mContentType.IsEmpty() || mContentType.Equals(UNKNOWN_CONTENT_TYPE)) {
396
 
    aContentType = TEXT_PLAIN;
397
 
  } else {
398
 
    aContentType = mContentType;
399
 
  }
400
 
 
401
 
  DEBUG_LOG(("nsPipeChannel::GetContentType: content-type: %s\n", mContentType.get()));
402
 
  return NS_OK;
403
 
}
404
 
 
405
 
NS_IMETHODIMP
406
 
nsPipeChannel::SetContentType(const nsACString &aContentType)
407
 
{
408
 
 
409
 
  NS_ParseContentType(aContentType, mContentType, mContentCharset);
410
 
  DEBUG_LOG(("nsPipeChannel::SetContentType: %s\n", mContentType.get()));
411
 
  return NS_OK;
412
 
}
413
 
 
414
 
NS_IMETHODIMP
415
 
nsPipeChannel::GetContentCharset(nsACString &aContentCharset)
416
 
{
417
 
  aContentCharset = mContentCharset;
418
 
  DEBUG_LOG(("nsPipeChannel::GetContentCharset: content-type: %s\n", mContentCharset.get()));
419
 
  return NS_OK;
420
 
}
421
 
 
422
 
NS_IMETHODIMP
423
 
nsPipeChannel::SetContentCharset(const nsACString &aContentCharset)
424
 
{
425
 
 
426
 
  mContentCharset = aContentCharset;
427
 
  DEBUG_LOG(("nsPipeChannel::SetContentCharset: %s\n", mContentCharset.get()));
428
 
  return NS_OK;
429
 
}
430
 
 
431
 
NS_IMETHODIMP
432
 
nsPipeChannel::GetContentLength(PRInt32 *aContentLength)
433
 
{
434
 
  DEBUG_LOG(("nsPipeChannel::GetContentLength: \n"));
435
 
  *aContentLength = mContentLength;
436
 
  return NS_OK;
437
 
}
438
 
 
439
 
NS_IMETHODIMP
440
 
nsPipeChannel::SetContentLength(PRInt32 aContentLength)
441
 
{
442
 
  DEBUG_LOG(("nsPipeChannel::SetContentLength: %d\n", aContentLength));
443
 
  mContentLength = aContentLength;
444
 
  return NS_OK;
445
 
}
446
 
 
447
 
NS_IMETHODIMP
448
 
nsPipeChannel::GetOwner(nsISupports * *aOwner)
449
 
{
450
 
  DEBUG_LOG(("nsPipeChannel::GetOwner: \n"));
451
 
  NS_IF_ADDREF(*aOwner = mOwner);
452
 
  return NS_OK;
453
 
}
454
 
 
455
 
NS_IMETHODIMP
456
 
nsPipeChannel::SetOwner(nsISupports * aOwner)
457
 
{
458
 
  DEBUG_LOG(("nsPipeChannel::SetOwner: \n"));
459
 
  mOwner = aOwner;
460
 
  return NS_OK;
461
 
}
462
 
 
463
 
NS_IMETHODIMP
464
 
nsPipeChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
465
 
{
466
 
  DEBUG_LOG(("nsPipeChannel::GetNotificationCallbacks: \n"));
467
 
  NS_IF_ADDREF(*aNotificationCallbacks = mCallbacks.get());
468
 
  return NS_OK;
469
 
}
470
 
 
471
 
NS_IMETHODIMP
472
 
nsPipeChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
473
 
{
474
 
 
475
 
  DEBUG_LOG(("nsPipeChannel::SetNotificationCallbacks: \n"));
476
 
  mCallbacks = aNotificationCallbacks;
477
 
 
478
 
  // Get a nsIProgressEventSink so that we can fire status/progress on it-
479
 
  if (mCallbacks) {
480
 
    nsCOMPtr<nsISupports> sink;
481
 
    nsresult rv = mCallbacks->GetInterface(NS_GET_IID(nsIProgressEventSink),
482
 
                                           getter_AddRefs(sink));
483
 
    if (NS_FAILED(rv)) return NS_OK;        // don't need a progress event sink
484
 
 
485
 
    // Now generate a proxied event sink
486
 
    nsCOMPtr<nsIProxyObjectManager> proxyMgr =
487
 
                                 do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv);
488
 
 
489
 
    NS_ENSURE_SUCCESS(rv, rv);
490
 
 
491
 
    rv = proxyMgr->GetProxyForObject(NS_PROXY_TO_MAIN_THREAD, // primordial thread
492
 
                                     NS_GET_IID(nsIProgressEventSink),
493
 
                                     sink,
494
 
                                     NS_PROXY_ASYNC | NS_PROXY_ALWAYS,
495
 
                                     getter_AddRefs(mProgress));
496
 
    // TODO: ignore rv value here on purpose??
497
 
  }
498
 
 
499
 
  return NS_OK;
500
 
}
501
 
 
502
 
 
503
 
NS_IMETHODIMP
504
 
nsPipeChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
505
 
{
506
 
 
507
 
  DEBUG_LOG(("nsPipeChannel:GetSecurityInfo:: \n"));
508
 
  *aSecurityInfo = nsnull;
509
 
  return NS_OK;
510
 
}
511
 
 
512
 
 
513
 
NS_IMETHODIMP
514
 
nsPipeChannel::Open(nsIInputStream **result)
515
 
{
516
 
 
517
 
  DEBUG_LOG(("nsPipeChannel::Open: \n"));
518
 
  return mPipeTransport->OpenInputStream(0, PRUint32(-1), 0, result);
519
 
}
520
 
 
521
 
 
522
 
NS_IMETHODIMP
523
 
nsPipeChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
524
 
{
525
 
  nsresult rv;
526
 
 
527
 
  DEBUG_LOG(("nsPipeChannel::AsyncOpen:\n"));
528
 
 
529
 
  if (listener) {
530
 
    nsCOMPtr<nsIProxyObjectManager> proxyMgr =
531
 
                                 do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv);
532
 
 
533
 
    NS_ENSURE_SUCCESS(rv, rv);
534
 
 
535
 
    rv = proxyMgr->GetProxyForObject(nsnull /* will that work?? */,
536
 
                                     NS_GET_IID(nsIStreamListener),
537
 
                                     listener,
538
 
                                     NS_PROXY_ASYNC | NS_PROXY_ALWAYS,
539
 
                                     getter_AddRefs(mListener));
540
 
    NS_ENSURE_SUCCESS(rv, rv);
541
 
  }
542
 
 
543
 
  rv = mPipeTransport->SetHeaderProcessor(mNoMimeHeaders ? nsnull : (nsIPipeTransportHeaders*) this);
544
 
  NS_ENSURE_SUCCESS(rv, rv);
545
 
 
546
 
  return mPipeTransport->AsyncRead(this, ctxt, 0, PRUint32(-1), 0,
547
 
                                   getter_AddRefs(mPipeRequest));
548
 
}
549
 
 
550
 
///////////////////////////////////////////////////////////////////////////////
551
 
// nsIRequestObserver methods
552
 
///////////////////////////////////////////////////////////////////////////////
553
 
 
554
 
NS_IMETHODIMP
555
 
nsPipeChannel::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
556
 
{
557
 
  nsresult rv = NS_OK;
558
 
 
559
 
#ifdef FORCE_PR_LOG
560
 
  nsCOMPtr<nsIThread> myThread;
561
 
  rv = IPC_GET_THREAD(myThread);
562
 
  DEBUG_LOG(("nsPipeChannel::OnStartRequest: myThread=%p\n", myThread.get()));
563
 
#endif
564
 
 
565
 
  if (!mPostingData) {
566
 
    // Not posting data
567
 
    if (mLoadGroup) {
568
 
 
569
 
      DEBUG_LOG(("nsPipeChannel::OnStartRequest: AddRequest\n"));
570
 
      rv = mLoadGroup->AddRequest(this, nsnull);
571
 
      NS_ENSURE_SUCCESS(rv, rv);
572
 
    }
573
 
 
574
 
    return mListener->OnStartRequest(this, aContext);
575
 
  } else {
576
 
    // Posting data; ignore OnStartRequest from AyncWrite
577
 
    return NS_OK;
578
 
  }
579
 
}
580
 
 
581
 
NS_IMETHODIMP
582
 
nsPipeChannel::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
583
 
                            nsresult aStatus)
584
 
{
585
 
  nsresult rv = NS_OK;
586
 
 
587
 
#ifdef FORCE_PR_LOG
588
 
  nsCOMPtr<nsIThread> myThread;
589
 
  rv = IPC_GET_THREAD(myThread);
590
 
  DEBUG_LOG(("nsPipeChannel::OnStopRequest: myThread=%p\n", myThread.get()));
591
 
#endif
592
 
 
593
 
  if (mChannelState == CHANNEL_CLOSED)
594
 
    return NS_OK;
595
 
 
596
 
  if (NS_SUCCEEDED(aStatus) && mPostingData) {
597
 
    // Posting data; posting has been successfully completed
598
 
    mPostingData = PR_FALSE;
599
 
 
600
 
    return NS_OK;
601
 
  }
602
 
 
603
 
  // Close channel
604
 
  mChannelState = CHANNEL_CLOSED;
605
 
 
606
 
  // Error status or not posting data; stop request
607
 
  if (mLoadGroup && !mPostingData) {
608
 
 
609
 
    DEBUG_LOG(("nsPipeChannel::OnStopRequest: RemoveRequest\n"));
610
 
    rv = mLoadGroup->RemoveRequest(this, nsnull, aStatus);
611
 
    NS_ENSURE_SUCCESS(rv, rv);
612
 
  }
613
 
 
614
 
  rv = mListener->OnStopRequest(this, aContext, aStatus);
615
 
 
616
 
  if (mProgress && !(mLoadFlags & LOAD_BACKGROUND)) {
617
 
    nsAutoString statusStr;
618
 
    statusStr.Assign(NS_LITERAL_STRING(""));
619
 
    if (mURI) {
620
 
      nsCAutoString urlSpec;
621
 
      rv = mURI->GetSpec(urlSpec);
622
 
      if (NS_SUCCEEDED(rv))
623
 
        statusStr.Assign(NS_ConvertUTF8toUTF16(urlSpec));
624
 
    }
625
 
 
626
 
    rv = mProgress->OnStatus(this, mContext,
627
 
                             NS_NET_STATUS_RECEIVING_FROM,
628
 
                             statusStr.get());
629
 
    NS_ASSERTION(NS_SUCCEEDED(rv), "unexpected OnStopRequest failure");
630
 
  }
631
 
 
632
 
  // Release owning references to PipeTransport, PipeRequest, Listener,
633
 
  //   and Context
634
 
  // (Use Finalize instead?)
635
 
  mPipeTransport = nsnull;
636
 
  mPipeRequest   = nsnull;
637
 
  mListener      = nsnull;
638
 
  mContext       = nsnull;
639
 
 
640
 
  return rv;
641
 
}
642
 
 
643
 
///////////////////////////////////////////////////////////////////////////////
644
 
// nsIStreamListener method
645
 
///////////////////////////////////////////////////////////////////////////////
646
 
 
647
 
NS_IMETHODIMP
648
 
nsPipeChannel::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
649
 
                              nsIInputStream *aInputStream,
650
 
                              PRUint32 aSourceOffset,
651
 
                              PRUint32 aLength)
652
 
{
653
 
  nsresult rv = NS_OK;
654
 
 
655
 
  if (mChannelState != CHANNEL_OPEN)
656
 
    return NS_ERROR_FAILURE;
657
 
 
658
 
#ifdef FORCE_PR_LOG
659
 
  nsCOMPtr<nsIThread> myThread;
660
 
  rv = IPC_GET_THREAD(myThread);
661
 
  DEBUG_LOG(("nsPipeChannel::OnDataAvailable: myThread=%p, offset=%d, length=%d\n",
662
 
         myThread.get(), aSourceOffset, aLength));
663
 
#endif
664
 
 
665
 
  mContentReceived += aLength;
666
 
 
667
 
  if (mProgress && !(mLoadFlags & LOAD_BACKGROUND)) {
668
 
    PRUint32 contentMax = (mContentLength >= 0) ? mContentLength : 0;
669
 
    rv = mProgress->OnProgress(this, aContext,
670
 
                               mContentReceived, contentMax);
671
 
    NS_ASSERTION(NS_SUCCEEDED(rv), "unexpected OnProgress failure");
672
 
  }
673
 
 
674
 
  rv = mListener->OnDataAvailable(this, aContext, aInputStream,
675
 
                                  aSourceOffset, aLength);
676
 
 
677
 
  return rv;
678
 
}
679
 
 
680
 
///////////////////////////////////////////////////////////////////////////////
681
 
// nsIPipeTransportHeaders methods:
682
 
///////////////////////////////////////////////////////////////////////////////
683
 
 
684
 
NS_IMETHODIMP
685
 
nsPipeChannel::ParseMimeHeaders(const char* mimeHeaders, PRUint32 count,
686
 
                               PRInt32 *retval)
687
 
{
688
 
  nsresult rv;
689
 
 
690
 
  DEBUG_LOG(("nsPipeChannel::ParseMimeHeaders, count=%d\n", count));
691
 
  if (!mimeHeaders || !retval)
692
 
    return NS_ERROR_NULL_POINTER;
693
 
 
694
 
  // Create headers string
695
 
  nsCAutoString headers(mimeHeaders, count);
696
 
 
697
 
  PRBool foundStatusLine = PR_FALSE;
698
 
  if ((headers.Length() >= 5)
699
 
      && (PL_strncmp(headers.get(), "HTTP/", 5) == 0)) {
700
 
    // Look for possible HTTP header line preceding MIME headers
701
 
 
702
 
    PRInt32 lineEnd = headers.Find("\n");
703
 
 
704
 
    if (lineEnd != -1) {
705
 
      // Strip HTTP header line
706
 
      headers.Cut(0, lineEnd+1);
707
 
      foundStatusLine = PR_TRUE;
708
 
    }
709
 
  }
710
 
 
711
 
  // Replace CRLF with just LF
712
 
  PRInt32 lineIndex = 0;
713
 
 
714
 
  while (lineIndex != -1) {
715
 
    lineIndex = headers.Find("\r\n");
716
 
    if (lineIndex != -1) {
717
 
      headers.Replace(lineIndex, 2, "\n", 1);
718
 
    }
719
 
  }
720
 
 
721
 
  if (headers.Length() < 2)
722
 
    return NS_ERROR_FAILURE;
723
 
 
724
 
  PRBool noHeaders = PR_FALSE;
725
 
  if (headers.CharAt(0) == '\n') {
726
 
    // First line is empty; no headers
727
 
    noHeaders = PR_TRUE;
728
 
 
729
 
  } else if ( (headers.CharAt(headers.Length()-2) != '\n') ||
730
 
              (headers.CharAt(headers.Length()-1) != '\n') ) {
731
 
    // No empty line terminating header
732
 
    noHeaders = PR_TRUE;
733
 
  }
734
 
 
735
 
  // Eliminate all leading whitespace (including linefeeds)
736
 
  headers.Trim(" \t\n", PR_TRUE, PR_FALSE);
737
 
 
738
 
  if (mContentType.Equals(UNKNOWN_CONTENT_TYPE)) {
739
 
    // Use some heuristics to guess type of unknown content even before
740
 
    // trying to parse the headers
741
 
 
742
 
    if (headers.CharAt(0) == '<') {
743
 
      // Start of markup?
744
 
      if (headers.Find("<html>", PR_TRUE) == 0) {
745
 
        // Set content type to text/html
746
 
        mContentType = TEXT_HTML;
747
 
      }
748
 
      // TO BE IMPLEMENTED: Look for doctype, xml, ...
749
 
    }
750
 
  }
751
 
 
752
 
  if (mContentType.Equals(UNKNOWN_CONTENT_TYPE)) {
753
 
    // Still unknown content type; check if headers are all printable ASCII
754
 
    PRBool printableAscii = PR_TRUE;
755
 
 
756
 
    for (PRUint32 j=0; j<count; j++) {
757
 
      char ch = (char) mimeHeaders[j];
758
 
      if ( (ch < '\t') ||
759
 
           ((ch > '\r') && (ch < ' ')) ||
760
 
           (ch >= 0x7F) ) {
761
 
        printableAscii = PR_FALSE;
762
 
        break;
763
 
      }
764
 
    }
765
 
 
766
 
    if (printableAscii) {
767
 
      // Treat unknown content as plain text by default
768
 
      mContentType = TEXT_PLAIN;
769
 
    } else {
770
 
      // Treat unknown content as octet stream by default
771
 
      mContentType = APPLICATION_OCTET_STREAM;
772
 
    }
773
 
  }
774
 
 
775
 
  if (noHeaders)
776
 
    return NS_ERROR_FAILURE;
777
 
 
778
 
  // Handle continuation of MIME headers, i.e., newline followed by a space
779
 
  lineIndex = 0;
780
 
 
781
 
  while (lineIndex != -1) {
782
 
    lineIndex = headers.Find("\n");
783
 
    if (lineIndex != -1) {
784
 
      headers.Replace(lineIndex, 1, " ", 1);
785
 
    }
786
 
  }
787
 
 
788
 
  // Default values for header content type/length (to be overridden by header)
789
 
  mHeaderContentType   = UNKNOWN_CONTENT_TYPE;
790
 
  mHeaderContentLength = mContentLength;
791
 
  mHeaderCharset = "";
792
 
 
793
 
  PRUint32 offset = 0;
794
 
  while (offset < headers.Length()) {
795
 
    PRInt32 lineEnd = headers.Find("\n", offset);
796
 
 
797
 
    if (lineEnd == -1) {
798
 
      // Header line terminator not found
799
 
      NS_NOTREACHED("lineEnd == kNotFound");
800
 
      return NS_ERROR_FAILURE;
801
 
    }
802
 
 
803
 
    // Normal exit if empty header line
804
 
    if (lineEnd == (int)offset)
805
 
      break;
806
 
 
807
 
    // Parse header line
808
 
    rv = ParseHeader((headers.get())+offset, lineEnd - offset);
809
 
    NS_ENSURE_SUCCESS(rv, rv);
810
 
 
811
 
    offset = lineEnd+1;
812
 
  }
813
 
 
814
 
  // If content type not found, assume header not found
815
 
  if (mHeaderContentType.Equals(UNKNOWN_CONTENT_TYPE))
816
 
    return NS_ERROR_FAILURE;
817
 
 
818
 
  // Copy back content type/length after successful parsing of headers
819
 
  mContentType   = mHeaderContentType;
820
 
  mContentLength = mHeaderContentLength;
821
 
 
822
 
 
823
 
  DEBUG_LOG(("nsPipeChannel::ParseMimeHeaders END: cType=%s, clen=%d\n",
824
 
         mContentType.get(), mContentLength));
825
 
  return NS_OK;
826
 
}
827
 
 
828
 
nsresult
829
 
nsPipeChannel::ParseHeader(const char* header, PRUint32 count)
830
 
{
831
 
 
832
 
  DEBUG_LOG(("nsPipeChannel::ParseHeader, count=%d\n", count));
833
 
 
834
 
  if (!header || (count <= 0) )
835
 
    return NS_OK;
836
 
 
837
 
  // Create header string
838
 
  nsCAutoString headerStr(header, count);
839
 
 
840
 
  PRInt32 colonOffset;
841
 
  colonOffset = headerStr.Find(":");
842
 
  if (colonOffset == -1) {
843
 
    // Malformed headerStr ... simulate NS4.x/IE behaviour trying SPC/TAB as delimiters
844
 
 
845
 
    colonOffset = headerStr.Find(" ");
846
 
    if (colonOffset == -1) {
847
 
 
848
 
      colonOffset = headerStr.Find("\t");
849
 
      if (colonOffset == -1) {
850
 
        return NS_ERROR_FAILURE;
851
 
      }
852
 
    }
853
 
  }
854
 
 
855
 
  // Null header key not allowed
856
 
  if (colonOffset == 0)
857
 
    return NS_ERROR_FAILURE;
858
 
 
859
 
  // Extract header key (not case-sensitive)
860
 
  nsCAutoString headerKey;
861
 
  // headerStr.Left(headerKey, colonOffset);
862
 
  headerStr = Substring(headerStr, 0, colonOffset);
863
 
 
864
 
  ToLowerCase(headerKey);
865
 
 
866
 
  // Extract header value, trimming leading/trailing whitespace
867
 
  nsCAutoString headerValue;
868
 
  // headerStr.Right(headerValue, headerStr.Length() - colonOffset - 1);
869
 
  headerValue = Substring(headerStr, colonOffset + 1, headerStr.Length());
870
 
  headerValue.Trim(" ");
871
 
 
872
 
 
873
 
  DEBUG_LOG(("nsPipeChannel::ParseHeader, key='%s', value='%s'\n",
874
 
         headerKey.get(), headerValue.get()));
875
 
 
876
 
  if (headerKey.Equals("content-type")) {
877
 
    // Ignore comments
878
 
    PRInt32 parenOffset = headerValue.Find("(");
879
 
    if (parenOffset > -1) {
880
 
      // headerValue.Truncate(parenOffset);
881
 
      headerValue = Substring(headerValue, 0, parenOffset);
882
 
      headerValue.Trim(" ", PR_FALSE);
883
 
    }
884
 
 
885
 
    if (!headerValue.IsEmpty()) {
886
 
      PRInt32 semicolonOffset = headerValue.Find(";");
887
 
      if (semicolonOffset == -1) {
888
 
        // No charset stuff
889
 
        mHeaderContentType = headerValue.get();
890
 
 
891
 
      } else {
892
 
        nsCAutoString buf;
893
 
        // headerValue.Left(buf, semicolonOffset);
894
 
        // mHeaderContentType = buf.get();
895
 
 
896
 
        mHeaderContentType = Substring(headerValue, semicolonOffset);
897
 
 
898
 
        // Look for charset
899
 
        // headerValue.Right(buf, headerValue.Length() - semicolonOffset - 1);
900
 
        buf = Substring(headerValue, semicolonOffset + 1, headerValue.Length());
901
 
        buf.Trim(" ");
902
 
        if (buf.Find("charset=", PR_TRUE) == 0) {
903
 
          // Charset found
904
 
          buf.Cut(0, 8);
905
 
          mHeaderCharset = buf.get();
906
 
        }
907
 
      }
908
 
    }
909
 
  }
910
 
 
911
 
  if (headerKey.Equals("content-length")) {
912
 
#if _IPC_FORCE_INTERNAL_API
913
 
    PRInt32 status;
914
 
#else
915
 
    PRUint32 status;
916
 
#endif
917
 
    mHeaderContentLength = headerValue.ToInteger(&status);
918
 
    if (NS_FAILED((nsresult) status))
919
 
      return NS_ERROR_FAILURE;
920
 
  }
921
 
 
922
 
  return NS_OK;
923
 
}