Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F36624157
nsIPCBuffer.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
21 KB
Subscribers
None
nsIPCBuffer.cpp
View Options
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "MPL"); you may not use this file
* except in compliance with the MPL. You may obtain a copy of
* the MPL at http://www.mozilla.org/MPL/
*
* Software distributed under the MPL is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the MPL for the specific language governing
* rights and limitations under the MPL.
*
* The Original Code is protoZilla.
*
* The Initial Developer of the Original Code is Ramalingam Saravanan.
* Portions created by Ramalingam Saravanan <svn@xmlterm.org> are
* Copyright (C) 2000 Ramalingam Saravanan. All Rights Reserved.
*
* Contributor(s):
* Patrick Brunschwig <patrick@mozilla-enigmail.org>
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License (the "GPL"), in which case
* the provisions of the GPL are applicable instead of
* those above. If you wish to allow use of your version of this
* file only under the terms of the GPL and not to allow
* others to use your version of this file under the MPL, indicate
* your decision by deleting the provisions above and replace them
* with the notice and other provisions required by the GPL.
* If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
// Logging of debug output
// The following define statement should occur before any include statements
#define FORCE_PR_LOG
/* Allow logging even in release build */
#include
"ipc.h"
#include
"prlog.h"
#include
"nsCOMPtr.h"
#include
"nsAutoLock.h"
#include
"nsIInputStream.h"
#include
"nsIThread.h"
#include
"nsIHttpChannel.h"
#include
"nsNetUtil.h"
#include
"nsDirectoryServiceUtils.h"
#include
"nsDirectoryServiceDefs.h"
#include
"nsNetCID.h"
#ifndef _IPC_FORCE_INTERNAL_API
#include
"nsStringAPI.h"
#else
#include
"nsString.h"
#endif
#include
"nsIPCBuffer.h"
#ifdef PR_LOGGING
PRLogModuleInfo
*
gIPCBufferLog
=
NULL
;
#endif
#define ERROR_LOG(args) PR_LOG(gIPCBufferLog,PR_LOG_ERROR,args)
#define WARNING_LOG(args) PR_LOG(gIPCBufferLog,PR_LOG_WARNING,args)
#define DEBUG_LOG(args) PR_LOG(gIPCBufferLog,PR_LOG_DEBUG,args)
#define NS_PIPE_CONSOLE_BUFFER_SIZE (1024)
static
const
PRUint32
kCharMax
=
NS_PIPE_CONSOLE_BUFFER_SIZE
;
///////////////////////////////////////////////////////////////////////////////
// nsIPCBuffer implementation
// nsISupports implementation
NS_IMPL_THREADSAFE_ISUPPORTS5
(
nsIPCBuffer
,
nsIStreamListener
,
nsIPipeListener
,
nsIIPCBuffer
,
nsIInputStream
,
nsIRunnable
)
// nsIPCBuffer implementation
nsIPCBuffer
::
nsIPCBuffer
()
:
mFinalized
(
PR_FALSE
),
mThreadJoined
(
PR_FALSE
),
mOverflowed
(
PR_FALSE
),
mOverflowFile
(
PR_FALSE
),
mRequestStarted
(
PR_FALSE
),
mRequestStopped
(
PR_FALSE
),
mLock
(
nsnull
),
mMaxBytes
(
0
),
mByteCount
(
0
),
mByteBuf
(
""
),
mPipeWrite
(
IPC_NULL_HANDLE
),
mPipeRead
(
IPC_NULL_HANDLE
),
mTempFile
(
nsnull
),
mTempOutStream
(
nsnull
),
mTempInStream
(
nsnull
),
mPipeThread
(
nsnull
),
mObserver
(
nsnull
),
mObserverContext
(
nsnull
)
{
NS_INIT_ISUPPORTS
();
#ifdef PR_LOGGING
if
(
gIPCBufferLog
==
nsnull
)
{
gIPCBufferLog
=
PR_NewLogModule
(
"nsIPCBuffer"
);
}
#endif
#ifdef FORCE_PR_LOG
nsresult
rv
;
nsCOMPtr
<
nsIThread
>
myThread
;
rv
=
IPC_GET_THREAD
(
myThread
);
DEBUG_LOG
((
"nsIPCBuffer:: <<<<<<<<< CTOR(%p): myThread=%p
\n
"
,
this
,
myThread
.
get
()));
#endif
}
nsIPCBuffer
::~
nsIPCBuffer
()
{
nsresult
rv
;
#ifdef FORCE_PR_LOG
nsCOMPtr
<
nsIThread
>
myThread
;
rv
=
IPC_GET_THREAD
(
myThread
);
DEBUG_LOG
((
"nsIPCBuffer:: >>>>>>>>> DTOR(%p): myThread=%p
\n
"
,
this
,
myThread
.
get
()));
#endif
Finalize
(
PR_TRUE
);
if
(
mLock
)
PR_DestroyLock
(
mLock
);
}
///////////////////////////////////////////////////////////////////////////////
// nsIPCBuffer methods:
///////////////////////////////////////////////////////////////////////////////
nsresult
nsIPCBuffer
::
Finalize
(
PRBool
destructor
)
{
DEBUG_LOG
((
"nsIPCBuffer::Finalize:
\n
"
));
if
(
mFinalized
)
return
NS_OK
;
mFinalized
=
PR_TRUE
;
nsCOMPtr
<
nsIIPCBuffer
>
self
;
if
(
!
destructor
)
{
// Hold a reference to ourselves to prevent our DTOR from being called
// while finalizing. Automatically released upon returning.
self
=
this
;
}
// Close write pipe
if
(
mPipeWrite
)
{
IPC_Close
(
mPipeWrite
);
mPipeWrite
=
IPC_NULL_HANDLE
;
}
// Release owning refs
mPipeThread
=
nsnull
;
mObserver
=
nsnull
;
mObserverContext
=
nsnull
;
RemoveTempFile
();
// Clear console
mByteBuf
.
Assign
(
""
);
return
NS_OK
;
}
nsresult
nsIPCBuffer
::
Init
()
{
DEBUG_LOG
((
"nsIPCBuffer::Init:
\n
"
));
if
(
mLock
==
nsnull
)
{
mLock
=
PR_NewLock
();
if
(
mLock
==
nsnull
)
return
NS_ERROR_OUT_OF_MEMORY
;
}
return
NS_OK
;
}
NS_IMETHODIMP
nsIPCBuffer
::
Open
(
PRUint32
maxBytes
,
PRBool
overflowFile
)
{
nsresult
rv
;
DEBUG_LOG
((
"nsIPCBuffer::Open: %d, %d
\n
"
,
maxBytes
,
(
int
)
overflowFile
));
rv
=
Init
();
NS_ENSURE_SUCCESS
(
rv
,
rv
);
if
(
maxBytes
==
-1
)
{
mMaxBytes
=
PR_INT32_MAX
;
}
else
{
mMaxBytes
=
maxBytes
;
}
mOverflowFile
=
overflowFile
;
return
NS_OK
;
}
NS_IMETHODIMP
nsIPCBuffer
::
OpenURI
(
nsIURI
*
aURI
,
PRInt32
maxBytes
,
PRBool
synchronous
,
nsIRequestObserver
*
observer
,
nsISupports
*
context
)
{
DEBUG_LOG
((
"nsIPCBuffer::OpenURI:
\n
"
));
nsresult
rv
;
rv
=
Init
();
NS_ENSURE_SUCCESS
(
rv
,
rv
);
mMaxBytes
=
maxBytes
;
mObserver
=
observer
;
mObserverContext
=
context
;
nsCOMPtr
<
nsIIOService
>
ioService
(
do_GetService
(
NS_IOSERVICE_CONTRACTID
,
&
rv
));
NS_ENSURE_SUCCESS
(
rv
,
rv
);
nsCOMPtr
<
nsIChannel
>
channel
;
rv
=
ioService
->
NewChannelFromURI
(
aURI
,
getter_AddRefs
(
channel
));
NS_ENSURE_SUCCESS
(
rv
,
rv
);
nsCOMPtr
<
nsISupports
>
ctxt
=
do_QueryInterface
(
aURI
);
if
(
!
synchronous
)
{
// Initiate asynchronous loading of URI
rv
=
channel
->
AsyncOpen
(
(
nsIStreamListener
*
)
this
,
ctxt
);
NS_ENSURE_SUCCESS
(
rv
,
rv
);
DEBUG_LOG
((
"nsIPCBuffer::OpenURI: Starting asynchronous load ...
\n
"
));
return
NS_OK
;
}
// Synchronous loading (DOESN'T USUALLY WORK!!!)
DEBUG_LOG
((
"nsIPCBuffer::OpenURI: Starting synchronous load ...
\n
"
));
nsCOMPtr
<
nsIInputStream
>
inputStream
;
rv
=
channel
->
Open
(
getter_AddRefs
(
inputStream
));
NS_ENSURE_SUCCESS
(
rv
,
rv
);
OnStartRequest
(
nsnull
,
mObserverContext
);
PRUint32
readCount
;
char
buf
[
1024
];
while
(
1
)
{
// Read and append output until end-of-file
rv
=
inputStream
->
Read
((
char
*
)
buf
,
1024
,
&
readCount
);
NS_ENSURE_SUCCESS
(
rv
,
rv
);
if
(
!
readCount
)
break
;
rv
=
WriteBuf
(
buf
,
readCount
);
NS_ENSURE_SUCCESS
(
rv
,
rv
);
}
// Close input stream
inputStream
->
Close
();
OnStopRequest
(
nsnull
,
mObserverContext
,
0
);
return
NS_OK
;
}
NS_IMETHODIMP
nsIPCBuffer
::
GetStopped
(
PRBool
*
_retval
)
{
NS_ENSURE_ARG
(
_retval
);
*
_retval
=
mRequestStopped
;
return
NS_OK
;
}
NS_IMETHODIMP
nsIPCBuffer
::
GetTotalBytes
(
PRUint32
*
_retval
)
{
NS_ENSURE_ARG
(
_retval
);
*
_retval
=
mByteCount
;
return
NS_OK
;
}
NS_IMETHODIMP
nsIPCBuffer
::
OpenInputStream
(
nsIInputStream
**
result
)
{
nsresult
rv
;
DEBUG_LOG
((
"nsIPCBuffer::OpenInputStream:
\n
"
));
if
(
!
mRequestStopped
)
{
ERROR_LOG
((
"nsIPCBuffer::OpenInputStream: ERROR - request not stopped
\n
"
));
return
NS_ERROR_NOT_INITIALIZED
;
}
mStreamOffset
=
0
;
if
(
mByteCount
&&
mTempFile
)
{
rv
=
OpenTempInStream
();
NS_ENSURE_SUCCESS
(
rv
,
rv
);
}
return
this
->
QueryInterface
(
NS_GET_IID
(
nsIInputStream
),
(
void
**
)
result
);
}
#define SAFE_TMP_FILENAME "nsenig.tmp"
NS_IMETHODIMP
nsIPCBuffer
::
CreateTempFile
()
{
nsresult
rv
;
DEBUG_LOG
((
"nsIPCBuffer::CreateTempFile:
\n
"
));
if
(
mTempFile
)
return
NS_ERROR_FAILURE
;
nsCOMPtr
<
nsIProperties
>
directoryService
=
do_GetService
(
NS_DIRECTORY_SERVICE_CONTRACTID
,
&
rv
);
directoryService
->
Get
(
NS_OS_TEMP_DIR
,
NS_GET_IID
(
nsIFile
),
getter_AddRefs
(
mTempFile
));
if
(
!
mTempFile
)
return
NS_ERROR_OUT_OF_MEMORY
;
mTempFile
->
AppendNative
(
nsDependentCString
(
SAFE_TMP_FILENAME
));
if
(
NS_FAILED
(
mTempFile
->
CreateUnique
(
nsIFile
::
NORMAL_FILE_TYPE
,
00600
)))
{
return
NS_ERROR_FAILURE
;
}
nsCAutoString
nativePath
;
mTempFile
->
GetNativePath
(
nativePath
);
DEBUG_LOG
((
"nsIPCBuffer::CreateTempFile: %s
\n
"
,
nativePath
.
get
()));
mTempOutStream
=
do_CreateInstance
(
"@mozilla.org/network/file-output-stream;1"
,
&
rv
);
NS_ENSURE_SUCCESS
(
rv
,
rv
);
rv
=
mTempOutStream
->
Init
(
mTempFile
,
PR_WRONLY
|
PR_CREATE_FILE
|
PR_TRUNCATE
,
00600
,
0
);
return
rv
;
}
NS_IMETHODIMP
nsIPCBuffer
::
WriteTempOutStream
(
const
char
*
buf
,
PRUint32
count
)
{
if
(
!
mTempOutStream
)
return
NS_ERROR_FAILURE
;
if
(
!
count
)
return
NS_OK
;
PRUint32
writeCount
;
nsresult
rv
=
mTempOutStream
->
Write
(
buf
,
count
,
&
writeCount
);
if
(
writeCount
!=
count
)
return
NS_ERROR_FAILURE
;
return
rv
;
}
NS_IMETHODIMP
nsIPCBuffer
::
CloseTempOutStream
()
{
nsresult
rv
=
NS_OK
;
DEBUG_LOG
((
"nsIPCBuffer::CloseTempOutStream:
\n
"
));
if
(
mTempOutStream
)
{
if
(
NS_FAILED
(
mTempOutStream
->
Flush
()))
{
rv
=
NS_ERROR_FAILURE
;
}
if
(
NS_FAILED
(
mTempOutStream
->
Close
()))
{
rv
=
NS_ERROR_FAILURE
;
}
mTempOutStream
=
nsnull
;
}
return
rv
;
}
NS_IMETHODIMP
nsIPCBuffer
::
OpenTempInStream
()
{
nsresult
rv
;
DEBUG_LOG
((
"nsIPCBuffer::OpenTempInStream:
\n
"
));
if
(
!
mTempFile
)
return
NS_ERROR_FAILURE
;
if
(
mTempOutStream
)
{
ERROR_LOG
((
"nsIPCBuffer::OpenTempInStream: ERROR - TempOutStream still open!
\n
"
));
return
NS_ERROR_FAILURE
;
}
mTempInStream
=
do_CreateInstance
(
"@mozilla.org/network/file-input-stream;1"
,
&
rv
);
NS_ENSURE_SUCCESS
(
rv
,
rv
);
rv
=
mTempInStream
->
Init
(
mTempFile
,
PR_RDONLY
,
00600
,
0
);
return
rv
;
}
NS_IMETHODIMP
nsIPCBuffer
::
CloseTempInStream
()
{
DEBUG_LOG
((
"nsIPCBuffer::CloseTempInStream:
\n
"
));
nsresult
rv
=
NS_OK
;
if
(
mTempInStream
)
{
rv
=
mTempInStream
->
Close
();
//delete mTempInStream;
mTempInStream
=
nsnull
;
}
return
rv
;
}
NS_IMETHODIMP
nsIPCBuffer
::
RemoveTempFile
()
{
DEBUG_LOG
((
"nsIPCBuffer::RemoveTempFile:
\n
"
));
if
(
mTempOutStream
)
{
// Close overflow file
CloseTempOutStream
();
}
if
(
mTempInStream
)
{
// Close overflow file
CloseTempInStream
();
}
if
(
mTempFile
)
{
// delete temp file
nsCAutoString
nativePath
;
mTempFile
->
GetNativePath
(
nativePath
);
DEBUG_LOG
((
"nsIPCBuffer::RemoveTempFile: Removing %s
\n
"
,
nativePath
.
get
()));
if
(
NS_FAILED
(
mTempFile
->
Remove
(
PR_FALSE
)))
{
return
NS_ERROR_FAILURE
;
}
mTempFile
=
nsnull
;
}
return
NS_OK
;
}
NS_IMETHODIMP
nsIPCBuffer
::
GetData
(
char
**
_retval
)
{
nsAutoLock
lock
(
mLock
);
if
(
!
_retval
)
return
NS_ERROR_NULL_POINTER
;
// Copy portion of console data to be returned
nsCAutoString
bufCopy
(
mByteBuf
);
// Replace any NULs with '0'
PRInt32
nulIndex
=
0
;
while
(
nulIndex
!=
-1
)
{
nulIndex
=
bufCopy
.
FindChar
(
char
(
0
));
if
(
nulIndex
!=
-1
)
{
bufCopy
.
Replace
(
nulIndex
,
1
,
"0"
,
1
);
}
}
// Duplicate new C string
*
_retval
=
ToNewCString
(
bufCopy
);
if
(
!*
_retval
)
return
NS_ERROR_OUT_OF_MEMORY
;
return
NS_OK
;
}
///////////////////////////////////////////////////////////////////////////////
// nsIPipeListener methods (thread-safe)
///////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsIPCBuffer
::
Observe
(
nsIRequestObserver
*
observer
,
nsISupports
*
context
)
{
nsAutoLock
lock
(
mLock
);
DEBUG_LOG
((
"nsIPCBuffer::Observe: %p, %p
\n
"
,
observer
,
context
));
mObserver
=
observer
;
mObserverContext
=
context
;
return
NS_OK
;
}
NS_IMETHODIMP
nsIPCBuffer
::
GetJoinable
(
PRBool
*
_retval
)
{
DEBUG_LOG
((
"nsIPCBuffer::GetJoinable: 1
\n
"
));
*
_retval
=
PR_TRUE
;
return
NS_OK
;
}
NS_IMETHODIMP
nsIPCBuffer
::
Shutdown
()
{
nsAutoLock
lock
(
mLock
);
DEBUG_LOG
((
"nsIPCBuffer::Shutdown:
\n
"
));
Finalize
(
PR_FALSE
);
return
NS_OK
;
}
NS_IMETHODIMP
nsIPCBuffer
::
GetByteData
(
PRUint32
*
count
,
char
**
data
)
{
nsAutoLock
lock
(
mLock
);
DEBUG_LOG
((
"nsIPCBuffer::GetByteData:
\n
"
));
if
(
!
count
||
!
data
)
return
NS_ERROR_NULL_POINTER
;
// Copy bytes
*
count
=
mByteBuf
.
Length
();
*
data
=
reinterpret_cast
<
char
*>
(
nsMemory
::
Alloc
((
*
count
)
+
1
));
if
(
!*
data
)
return
NS_ERROR_OUT_OF_MEMORY
;
memcpy
(
*
data
,
mByteBuf
.
get
(),
*
count
);
// NUL terminate byte array (just to be safe!)
(
*
data
)[
*
count
]
=
'\0'
;
return
NS_OK
;
}
NS_IMETHODIMP
nsIPCBuffer
::
GetOverflowed
(
PRBool
*
_retval
)
{
nsAutoLock
lock
(
mLock
);
DEBUG_LOG
((
"nsIPCBuffer::GetOverflowed: %d
\n
"
,
(
int
)
mOverflowed
));
*
_retval
=
mOverflowed
;
return
NS_OK
;
}
NS_IMETHODIMP
nsIPCBuffer
::
Write
(
const
char
*
str
)
{
// Note: Locking occurs in WriteBuf
DEBUG_LOG
((
"nsIPCBuffer::Write: %s
\n
"
,
str
));
PRUint32
len
=
strlen
(
str
);
if
(
!
len
)
return
NS_OK
;
return
WriteBuf
(
str
,
len
);
}
NS_IMETHODIMP
nsIPCBuffer
::
WriteBuf
(
const
char
*
buf
,
PRUint32
count
)
{
nsresult
rv
;
nsAutoLock
lock
(
mLock
);
DEBUG_LOG
((
"nsIPCBuffer::WriteBuf: %d (%d)
\n
"
,
count
,
mByteCount
));
if
(
count
<=
0
)
return
NS_OK
;
mByteCount
+=
count
;
if
(
mOverflowed
)
{
if
(
!
mOverflowFile
)
return
NS_OK
;
rv
=
WriteTempOutStream
(
buf
,
count
);
return
rv
;
}
// Find space available in buffer
PRInt32
nAvail
=
mMaxBytes
-
mByteBuf
.
Length
();
if
(
nAvail
>=
(
int
)
count
)
{
mByteBuf
.
Append
(
buf
,
count
);
return
NS_OK
;
}
if
(
nAvail
>
0
)
{
mByteBuf
.
Append
(
buf
,
nAvail
);
}
mOverflowed
=
PR_TRUE
;
DEBUG_LOG
((
"nsIPCBuffer::WriteBuf: buffer overflow
\n
"
));
if
(
!
mOverflowFile
)
return
NS_OK
;
CreateTempFile
();
// Write out previously buffered data first
rv
=
WriteTempOutStream
(
mByteBuf
.
get
(),
mByteBuf
.
Length
());
NS_ENSURE_SUCCESS
(
rv
,
rv
);
rv
=
WriteTempOutStream
(
buf
+
nAvail
,
count
-
nAvail
);
return
rv
;
}
NS_IMETHODIMP
nsIPCBuffer
::
Join
()
{
nsresult
rv
;
{
// Nested lock to avoid deadlock while waiting for Join
nsAutoLock
lock
(
mLock
);
DEBUG_LOG
((
"nsIPCBuffer::Join:
\n
"
));
if
(
mThreadJoined
||
!
mPipeThread
)
return
NS_OK
;
if
(
mPipeWrite
)
{
// Close write pipe before joining
IPC_Close
(
mPipeWrite
);
mPipeWrite
=
IPC_NULL_HANDLE
;
}
}
rv
=
mPipeThread
->
Shutdown
();
NS_ENSURE_SUCCESS
(
rv
,
rv
);
mThreadJoined
=
PR_TRUE
;
return
NS_OK
;
}
NS_IMETHODIMP
nsIPCBuffer
::
GetFileDesc
(
IPCFileDesc
*
*
_retval
)
{
nsresult
rv
;
nsAutoLock
lock
(
mLock
);
DEBUG_LOG
((
"nsIPCBuffer::GetFileDesc:
\n
"
));
if
(
!
_retval
)
return
NS_ERROR_NULL_POINTER
;
if
(
!
mFinalized
&&
!
mPipeThread
)
{
// Create pipe pair
PRStatus
status
=
IPC_CreateInheritablePipe
(
&
mPipeRead
,
&
mPipeWrite
,
PR_FALSE
,
PR_TRUE
);
if
(
status
!=
PR_SUCCESS
)
{
ERROR_LOG
((
"nsIPCBuffer::GetFileDesc: IPC_CreateInheritablePipe failed
\n
"
));
return
NS_ERROR_FAILURE
;
}
// Spin up a new thread to handle STDOUT polling
rv
=
NS_NewThread
(
getter_AddRefs
(
mPipeThread
),
this
);
NS_ENSURE_SUCCESS
(
rv
,
rv
);
}
if
(
mPipeWrite
==
IPC_NULL_HANDLE
)
return
NS_ERROR_FAILURE
;
*
_retval
=
mPipeWrite
;
return
NS_OK
;
}
///////////////////////////////////////////////////////////////////////////////
// nsIRequestObserver methods
///////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsIPCBuffer
::
OnStartRequest
(
nsIRequest
*
aRequest
,
nsISupports
*
aContext
)
{
DEBUG_LOG
((
"nsIPCBuffer::OnStartRequest:
\n
"
));
nsCOMPtr
<
nsIRequestObserver
>
observer
;
nsCOMPtr
<
nsISupports
>
observerContext
;
{
nsAutoLock
lock
(
mLock
);
mRequestStarted
=
PR_TRUE
;
if
(
!
mObserver
)
return
NS_OK
;
observer
=
mObserver
;
observerContext
=
mObserverContext
;
}
return
observer
->
OnStartRequest
(
aRequest
,
observerContext
);
}
NS_IMETHODIMP
nsIPCBuffer
::
OnStopRequest
(
nsIRequest
*
aRequest
,
nsISupports
*
aContext
,
nsresult
aStatus
)
{
DEBUG_LOG
((
"nsIPCBuffer::OnStopRequest:
\n
"
));
nsCOMPtr
<
nsIRequestObserver
>
observer
;
nsCOMPtr
<
nsISupports
>
observerContext
;
{
nsAutoLock
lock
(
mLock
);
mRequestStopped
=
PR_TRUE
;
CloseTempOutStream
();
if
(
!
mObserver
)
return
NS_OK
;
observer
=
mObserver
;
observerContext
=
mObserverContext
;
}
return
observer
->
OnStopRequest
(
aRequest
,
observerContext
,
aStatus
);
}
///////////////////////////////////////////////////////////////////////////////
// nsIStreamListener method
///////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsIPCBuffer
::
OnDataAvailable
(
nsIRequest
*
aRequest
,
nsISupports
*
aContext
,
nsIInputStream
*
aInputStream
,
PRUint32
aSourceOffset
,
PRUint32
aLength
)
{
nsresult
rv
=
NS_OK
;
DEBUG_LOG
((
"nsIPCBuffer::OnDataAVailable: %d
\n
"
,
aLength
));
char
buf
[
kCharMax
];
PRUint32
readCount
,
readMax
;
while
(
aLength
>
0
)
{
readMax
=
(
aLength
<
kCharMax
)
?
aLength
:
kCharMax
;
rv
=
aInputStream
->
Read
((
char
*
)
buf
,
readMax
,
&
readCount
);
if
(
NS_FAILED
(
rv
)){
ERROR_LOG
((
"nsIPCBuffer::OnDataAvailable: Error in reading from input stream, %x
\n
"
,
rv
));
return
rv
;
}
if
(
readCount
<=
0
)
return
NS_OK
;
rv
=
WriteBuf
(
buf
,
readCount
);
if
(
NS_FAILED
(
rv
))
return
rv
;
aLength
-=
readCount
;
}
return
NS_OK
;
}
///////////////////////////////////////////////////////////////////////////////
// nsIRunnable methods:
// (runs as a new thread)
///////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsIPCBuffer
::
Run
()
{
nsresult
rv
=
NS_OK
;
#ifdef FORCE_PR_LOG
nsCOMPtr
<
nsIThread
>
myThread
;
rv
=
IPC_GET_THREAD
(
myThread
);
DEBUG_LOG
((
"nsIPCBuffer::Run: myThread=%p
\n
"
,
myThread
.
get
()));
#endif
// Blocked read loop
while
(
1
)
{
char
buf
[
kCharMax
];
PRInt32
readCount
;
// Read data from pipe (blocking)
readCount
=
IPC_Read
(
mPipeRead
,
(
char
*
)
buf
,
kCharMax
);
DEBUG_LOG
((
"nsIPCBuffer::Run: Read %d chars
\n
"
,
readCount
));
if
(
readCount
<=
0
)
break
;
#if 0
// Debugging code
if (readCount < (int) kCharMax) {
buf[readCount] = '\0';
DEBUG_LOG(("nsIPCBuffer::Run: buf='%s'\n", buf));
}
#endif
// Append data read to console
WriteBuf
(
buf
,
readCount
);
}
// Clear any NSPR interrupt
PR_ClearInterrupt
();
// Close read pipe
IPC_Close
(
mPipeRead
);
mPipeRead
=
IPC_NULL_HANDLE
;
return
NS_OK
;
}
///////////////////////////////////////////////////////////////////////////////
// nsIInputStream methods
///////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsIPCBuffer
::
Available
(
PRUint32
*
_retval
)
{
if
(
!
_retval
)
return
NS_ERROR_NULL_POINTER
;
*
_retval
=
(
mByteCount
>
mStreamOffset
)
?
mByteCount
-
mStreamOffset
:
0
;
DEBUG_LOG
((
"nsIPCBuffer::Available: %d (%d)
\n
"
,
*
_retval
,
mByteCount
));
return
NS_OK
;
}
NS_IMETHODIMP
nsIPCBuffer
::
Read
(
char
*
buf
,
PRUint32
count
,
PRUint32
*
readCount
)
{
DEBUG_LOG
((
"nsIPCBuffer::Read: %d
\n
"
,
count
));
nsresult
rv
;
if
(
!
buf
||
!
readCount
)
return
NS_ERROR_NULL_POINTER
;
PRInt32
avail
=
(
mByteCount
>
mStreamOffset
)
?
mByteCount
-
mStreamOffset
:
0
;
PRUint32
readyCount
=
((
PRUint32
)
avail
>
count
)
?
count
:
avail
;
if
(
readyCount
)
{
if
(
mTempInStream
)
{
rv
=
mTempInStream
->
Read
((
char
*
)
buf
,
readyCount
,
readCount
);
NS_ENSURE_SUCCESS
(
rv
,
rv
);
}
else
{
memcpy
(
buf
,
mByteBuf
.
get
()
+
mStreamOffset
,
readyCount
);
*
readCount
=
readyCount
;
}
}
mStreamOffset
+=
*
readCount
;
if
(
mStreamOffset
>=
mByteCount
)
{
Close
();
}
return
NS_OK
;
}
NS_IMETHODIMP
nsIPCBuffer
::
ReadSegments
(
nsWriteSegmentFun
writer
,
void
*
aClosure
,
PRUint32
count
,
PRUint32
*
readCount
)
{
nsresult
rv
;
DEBUG_LOG
((
"nsIPCBuffer::ReadSegments: %d
\n
"
,
count
));
if
(
!
readCount
)
return
NS_ERROR_NULL_POINTER
;
PRUint32
avail
,
readyCount
,
writeCount
;
*
readCount
=
0
;
if
(
!
mTempInStream
)
{
while
((
count
>
0
)
&&
(
mStreamOffset
<
mByteCount
))
{
avail
=
mByteCount
-
mStreamOffset
;
readyCount
=
((
PRUint32
)
avail
>
count
)
?
count
:
avail
;
rv
=
writer
((
nsIInputStream
*
)(
this
),
aClosure
,
mByteBuf
.
get
()
+
mStreamOffset
,
mStreamOffset
,
readyCount
,
&
writeCount
);
NS_ENSURE_SUCCESS
(
rv
,
rv
);
if
(
!
writeCount
)
return
(
NS_ERROR_FAILURE
);
DEBUG_LOG
((
"nsIPCBuffer::ReadSegments: writer %d
\n
"
,
writeCount
));
*
readCount
+=
writeCount
;
mStreamOffset
+=
writeCount
;
count
-=
writeCount
;
}
}
else
{
char
buf
[
kCharMax
];
while
((
count
>
0
)
&&
(
mStreamOffset
<
mByteCount
))
{
avail
=
(
count
<
kCharMax
)
?
count
:
kCharMax
;
rv
=
mTempInStream
->
Read
((
char
*
)
buf
,
avail
,
&
readyCount
);
NS_ENSURE_SUCCESS
(
rv
,
rv
);
if
(
!
readyCount
)
{
ERROR_LOG
((
"nsIPCBuffer::ReadSegments: Error in reading from TempInputStream
\n
"
));
return
NS_ERROR_FAILURE
;
}
rv
=
writer
((
nsIInputStream
*
)(
this
),
aClosure
,
buf
,
mStreamOffset
,
readyCount
,
&
writeCount
);
NS_ENSURE_SUCCESS
(
rv
,
rv
);
if
(
!
writeCount
)
return
NS_ERROR_FAILURE
;
DEBUG_LOG
((
"nsIPCBuffer::ReadSegments: writer %d (Temp)
\n
"
,
writeCount
));
*
readCount
+=
writeCount
;
mStreamOffset
+=
writeCount
;
count
-=
writeCount
;
}
}
if
(
mStreamOffset
>=
mByteCount
)
{
// End-of-file
Close
();
}
return
NS_OK
;
}
NS_IMETHODIMP
nsIPCBuffer
::
IsNonBlocking
(
PRBool
*
aNonBlocking
)
{
DEBUG_LOG
((
"nsIPCBuffer::IsNonBlocking:
\n
"
));
*
aNonBlocking
=
(
mTempInStream
==
nsnull
);
return
NS_OK
;
}
NS_IMETHODIMP
nsIPCBuffer
::
Close
()
{
DEBUG_LOG
((
"nsIPCBuffer::Close:
\n
"
));
mStreamOffset
=
0
;
mByteCount
=
0
;
mByteBuf
.
Assign
(
""
);
RemoveTempFile
();
return
NS_OK
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Thu, Feb 26, 7:15 PM (5 h, 13 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
b0/c4/ce5e92679a0e6d7a131140738c91
Attached To
rENIG Enigmail
Event Timeline
Log In to Comment