50 #include <nsIInputStream.h>
51 #include <nsIIOService.h>
52 #include <nsIResumableChannel.h>
55 #include <nsServiceManagerUtils.h>
56 #include <nsStringGlue.h>
67 static PRLogModuleInfo* gLog = PR_NewLogModule(
"sbSeekableChannel");
68 #define LOG(args) if (gLog) PR_LOG(gLog, PR_LOG_DEBUG, args)
109 nsCOMPtr<nsIRequest> pRequest;
110 nsresult result =
NS_OK;
113 if (!pChannel || !pListener)
114 result = NS_ERROR_NULL_POINTER;
117 if (NS_SUCCEEDED(result))
121 if (NS_SUCCEEDED(result))
123 mpChannel = pChannel;
124 mpListener = pListener;
128 mRestarting = PR_FALSE;
132 if (NS_SUCCEEDED(result))
134 pRequest = do_QueryInterface(mpChannel, &result);
135 if (NS_SUCCEEDED(result))
137 result = pRequest->SetLoadFlags
138 ( nsIRequest::INHIBIT_CACHING
139 | nsIRequest::INHIBIT_PERSISTENT_CACHING
140 | nsIRequest::LOAD_BYPASS_CACHE);
142 NS_ASSERTION(NS_SUCCEEDED(result),
143 "Setting load flags failed "
144 ":( Watch out, app will deadlock.");
148 if (NS_SUCCEEDED(result))
149 result = mpChannel->SetNotificationCallbacks(
this);
152 if (NS_SUCCEEDED(result))
153 result = mpChannel->AsyncOpen(
this, nsnull);
165 NS_IMETHODIMP sbSeekableChannel::Close()
167 DataSet::iterator dataSetIterator;
170 nsresult result =
NS_OK;
176 mpChannel->IsPending(&pending);
179 mpChannel->SetNotificationCallbacks(nsnull);
183 dataSetIterator = mChannelData.begin();
184 while (dataSetIterator != mChannelData.end())
186 pSegment = *dataSetIterator++;
187 mChannelData.erase(pSegment);
197 mRestarting = PR_FALSE;
212 NS_IMETHODIMP sbSeekableChannel::Skip(
215 nsresult result =
NS_OK;
233 NS_IMETHODIMP sbSeekableChannel::Read(
236 PRUint32 *pBytesRead)
238 PRUint32 readLength = length;
239 DataSet::iterator dataSetIterator;
241 Segment *pSegment = NULL;
242 nsresult result =
NS_OK;
246 result = NS_ERROR_NULL_POINTER;
249 if (NS_SUCCEEDED(result) && (mRestarting))
253 if (mPos >= mContentLength)
254 result = NS_ERROR_UNEXPECTED;
255 if (NS_SUCCEEDED(result) && ((mPos + readLength) > mContentLength))
256 readLength = (PRUint32)(mContentLength - mPos);
259 if (NS_SUCCEEDED(result))
261 findSegment.offset = mPos;
262 findSegment.length = 0;
263 dataSetIterator = mChannelData.find(&findSegment);
264 if (dataSetIterator == mChannelData.end())
270 if (NS_SUCCEEDED(result))
272 pSegment = *dataSetIterator;
273 if ((mPos + readLength) > (pSegment->offset + pSegment->length))
278 if (NS_SUCCEEDED(result))
281 pSegment->buffer + (mPos - pSegment->offset),
293 Restart(pSegment->offset + pSegment->length);
299 if (NS_SUCCEEDED(result))
300 *pBytesRead = readLength;
314 NS_IMETHODIMP sbSeekableChannel::ReadChar(
317 nsresult result =
NS_OK;
332 NS_IMETHODIMP sbSeekableChannel::ReadInt32(
335 nsresult result =
NS_OK;
350 NS_IMETHODIMP sbSeekableChannel::ReadInt64(
353 nsresult result =
NS_OK;
363 NS_IMETHODIMP sbSeekableChannel::GetPos(
366 nsresult result =
NS_OK;
370 result = NS_ERROR_NULL_POINTER;
373 if (NS_SUCCEEDED(result))
380 NS_IMETHODIMP sbSeekableChannel::SetPos(
383 DataSet::iterator dataSetIterator;
385 nsresult result =
NS_OK;
392 if (NS_SUCCEEDED(result) && (pos < mContentLength))
394 findSegment.offset =
pos;
395 findSegment.length = 0;
396 dataSetIterator = mChannelData.find(&findSegment);
397 if (dataSetIterator == mChannelData.end())
406 if (NS_SUCCEEDED(result))
413 NS_IMETHODIMP sbSeekableChannel::GetSize(
416 nsresult result =
NS_OK;
420 result = NS_ERROR_NULL_POINTER;
423 if (NS_SUCCEEDED(result))
424 *pSize = mContentLength;
441 NS_IMETHODIMP sbSeekableChannel::GetCompleted(
444 nsresult result =
NS_OK;
448 result = NS_ERROR_NULL_POINTER;
451 *pCompleted = mCompleted;
479 NS_IMETHODIMP sbSeekableChannel::OnDataAvailable(
480 nsIRequest *pRequest,
482 nsIInputStream *pStream,
486 nsresult result =
NS_OK;
495 mDataReceivedSinceStart = PR_TRUE;
496 ReadSegment(pStream, numBytes);
502 mpListener->OnChannelDataAvailable(
this);
524 NS_IMETHODIMP sbSeekableChannel::OnStartRequest(
525 nsIRequest *pRequest,
528 NS_ENSURE_STATE(mpChannel);
531 nsresult result =
NS_OK;
534 mRestarting = PR_FALSE;
538 mDataReceivedSinceStart = PR_FALSE;
543 result = mpChannel->GetContentLength(&contentLength);
544 if (NS_SUCCEEDED(result) && (contentLength > 0))
545 mContentLength = (PRInt64) contentLength;
564 NS_IMETHODIMP sbSeekableChannel::OnStopRequest(
565 nsIRequest *pRequest,
569 nsresult result =
NS_OK;
577 if (NS_FAILED(status) || !mDataReceivedSinceStart)
578 mCompleted = PR_TRUE;
582 mpListener->OnChannelDataAvailable(
this);
606 NS_IMETHODIMP sbSeekableChannel::OnChannelRedirect(
611 nsresult result =
NS_OK;
614 mpChannel = pRedirectedChannel;
636 NS_IMETHODIMP sbSeekableChannel::GetInterface(
640 void *pInterface = nsnull;
641 nsresult result =
NS_OK;
644 NS_ENSURE_ARG_POINTER(ppInterface);
650 *ppInterface = pInterface;
702 nsresult sbSeekableChannel::ReadSegment(
703 nsIInputStream *pStream,
706 Segment *pSegment = NULL;
708 PRUint64 readOffset = mBasePos;
710 nsresult result =
NS_OK;
713 buffer = (
char *) nsMemory::Alloc(numBytes);
715 result = NS_ERROR_OUT_OF_MEMORY;
718 if (NS_SUCCEEDED(result))
720 result = pStream->Read(buffer, numBytes, &bytesRead);
721 if (NS_SUCCEEDED(result))
723 mBasePos += bytesRead;
724 if (mBasePos > mContentLength)
725 mContentLength = mBasePos;
730 if (NS_SUCCEEDED(result))
732 pSegment =
new Segment();
735 pSegment->offset = readOffset;
736 pSegment->length = bytesRead;
737 pSegment->buffer = buffer;
742 result = NS_ERROR_UNEXPECTED;
747 if (NS_SUCCEEDED(result))
748 result = InsertSegment(pSegment);
749 if (NS_SUCCEEDED(result))
754 if (NS_FAILED(result) || AllDataRead())
755 mCompleted = PR_TRUE;
758 if (!NS_SUCCEEDED(result))
763 nsMemory::Free(buffer);
780 nsresult sbSeekableChannel::InsertSegment(
781 Segment *pInsertSegment)
783 DataSet::iterator dataSetIterator;
784 Segment *pSegment = NULL;
785 nsresult result =
NS_OK;
790 dataSetIterator = mChannelData.find(pInsertSegment);
791 if (dataSetIterator != mChannelData.end())
793 pSegment = *dataSetIterator;
794 mChannelData.erase(pSegment);
795 result = MergeSegments(pSegment, pInsertSegment, &pSegment);
796 InsertSegment(pSegment);
800 mChannelData.insert(pInsertSegment);
820 nsresult sbSeekableChannel::MergeSegments(
823 Segment **ppMergedSegment)
826 Segment *pFromSegment;
827 PRUint64 mergedLength;
828 PRUint64 mergeFromOffset;
829 nsresult result =
NS_OK;
832 if (pSegment1->offset <= pSegment2->offset)
834 pToSegment = pSegment1;
835 pFromSegment = pSegment2;
839 pToSegment = pSegment2;
840 pFromSegment = pSegment1;
844 mergeFromOffset = pToSegment->offset + pToSegment->length
845 - pFromSegment->offset;
849 if (mergeFromOffset < pFromSegment->length)
852 mergedLength = pFromSegment->offset + pFromSegment->length
853 - pToSegment->offset;
857 (
char *) nsMemory::Realloc(pToSegment->buffer, static_cast<PRSize>(mergedLength));
858 if (!pToSegment->buffer)
859 result = NS_ERROR_OUT_OF_MEMORY;
862 if (NS_SUCCEEDED(result))
864 memcpy(pToSegment->buffer + pToSegment->length,
865 pFromSegment->buffer + mergeFromOffset,
866 static_cast<PRSize>(pFromSegment->length - mergeFromOffset));
867 pToSegment->length = mergedLength;
872 delete(pFromSegment);
875 if (!NS_SUCCEEDED(result))
879 if (NS_SUCCEEDED(result))
880 *ppMergedSegment = pToSegment;
894 PRBool sbSeekableChannel::AllDataRead()
896 DataSet::iterator dataSetIterator;
897 Segment *pFirstSegment;
898 PRBool allDataRead = PR_FALSE;
902 dataSetIterator = mChannelData.begin();
903 if (dataSetIterator != mChannelData.end())
905 pFirstSegment = *dataSetIterator;
906 if ( (pFirstSegment->offset == 0)
907 && (pFirstSegment->length == mContentLength))
909 allDataRead = PR_TRUE;
913 return (allDataRead);
925 nsresult sbSeekableChannel::Restart(
928 nsCOMPtr<nsIResumableChannel>
930 nsCOMPtr<nsIURI> pURI;
931 nsCOMPtr<nsIIOService> pIOService;
932 nsCOMPtr<nsIRequest> pRequest;
933 nsresult result =
NS_OK;
937 if ((mRestarting) || (mBasePos == pos))
941 pResumableChannel = do_QueryInterface(mpChannel, &result);
944 if (NS_SUCCEEDED(result))
945 result = mpChannel->GetURI(getter_AddRefs(pURI));
948 if (NS_SUCCEEDED(result))
955 if (NS_SUCCEEDED(result))
957 pIOService = do_GetService(
"@mozilla.org/network/io-service;1",
960 if (NS_SUCCEEDED(result))
961 result = pIOService->NewChannelFromURI(pURI, getter_AddRefs(mpChannel));
964 if (NS_SUCCEEDED(result))
966 pRequest = do_QueryInterface(mpChannel, &result);
967 if (NS_SUCCEEDED(result))
969 result = pRequest->SetLoadFlags
970 ( nsIRequest::INHIBIT_CACHING
971 | nsIRequest::INHIBIT_PERSISTENT_CACHING
972 | nsIRequest::LOAD_BYPASS_CACHE);
974 NS_ASSERTION(NS_SUCCEEDED(result),
975 "Setting load flags failed "
976 ":( Watch out, app will deadlock.");
980 if (NS_SUCCEEDED(result))
981 pResumableChannel = do_QueryInterface(mpChannel, &result);
982 if (NS_SUCCEEDED(result))
983 pResumableChannel->ResumeAt(pos, NS_LITERAL_CSTRING(
""));
984 if (NS_SUCCEEDED(result))
985 mpChannel->AsyncOpen(
this, nsnull);
988 if (NS_SUCCEEDED(result))
991 mRestarting = PR_TRUE;
1004 void sbSeekableChannel::DumpChannelData()
1006 DataSet::iterator segmentIterator;
1009 for (segmentIterator = mChannelData.begin();
1010 segmentIterator != mChannelData.end();
1013 pSegment = *segmentIterator;
1014 LOG((
"Segment 0x%08x 0x%08x\n",
1015 (PRUint32) (pSegment->offset & 0xFFFFFFFF),
1016 (PRUint32) (pSegment->length & 0xFFFFFFFF)));
1017 LOG((
" 0x%08x\n", ((PRUint32 *) pSegment->buffer)[0]));
1035 sbSeekableChannel::Segment::Segment()
1050 sbSeekableChannel::Segment::~Segment()
1053 nsMemory::Free(buffer);
1071 bool sbSeekableChannel::Segment::operator()(
1072 const Segment *pSegment1,
1073 const Segment *pSegment2)
const
1075 return ( (pSegment1->offset + pSegment1->length)
1076 < pSegment2->offset);
virtual ~sbSeekableChannel()
sbDeviceFirmwareAutoCheckForUpdate prototype flags
sbOSDControlService prototype QueryInterface
A seekable wrapper for an nsIChannel.
NS_DECL_ISUPPORTS NS_DECL_SBISEEKABLECHANNEL NS_DECL_NSISTREAMLISTENER NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSICHANNELEVENTSINK NS_DECL_NSIINTERFACEREQUESTOR sbSeekableChannel()
NS_IMPL_THREADSAFE_ISUPPORTS5(sbSeekableChannel, sbISeekableChannel, nsIStreamListener, nsIRequestObserver, nsIChannelEventSink, nsIInterfaceRequestor) NS_IMETHODIMP sbSeekableChannel
attribute PRUInt64 pos
The current read position (for the read methods)
BogusChannel prototype contentLength
#define NS_ERROR_SONGBIRD_SEEKABLE_CHANNEL_RESTART
A listener interface for sbISeekableChannel.
Songbird Seekable Channel Component Definition.
const nsIInterfaceRequestor