nsDownloader.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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. #include "nsDownloader.h"
  5. #include "nsIInputStream.h"
  6. #include "nsIOutputStream.h"
  7. #include "nsDirectoryServiceUtils.h"
  8. #include "nsDirectoryServiceDefs.h"
  9. #include "nsNetUtil.h"
  10. #include "nsCRTGlue.h"
  11. nsDownloader::~nsDownloader()
  12. {
  13. if (mLocation && mLocationIsTemp) {
  14. // release the sink first since it may still hold an open file
  15. // descriptor to mLocation. this needs to happen before the
  16. // file can be removed otherwise the Remove call will fail.
  17. if (mSink) {
  18. mSink->Close();
  19. mSink = nullptr;
  20. }
  21. nsresult rv = mLocation->Remove(false);
  22. if (NS_FAILED(rv))
  23. NS_ERROR("unable to remove temp file");
  24. }
  25. }
  26. NS_IMPL_ISUPPORTS(nsDownloader,
  27. nsIDownloader,
  28. nsIStreamListener,
  29. nsIRequestObserver)
  30. NS_IMETHODIMP
  31. nsDownloader::Init(nsIDownloadObserver *observer, nsIFile *location)
  32. {
  33. mObserver = observer;
  34. mLocation = location;
  35. return NS_OK;
  36. }
  37. NS_IMETHODIMP
  38. nsDownloader::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
  39. {
  40. nsresult rv;
  41. if (!mLocation) {
  42. nsCOMPtr<nsIFile> location;
  43. rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(location));
  44. if (NS_FAILED(rv)) return rv;
  45. char buf[13];
  46. NS_MakeRandomString(buf, 8);
  47. memcpy(buf+8, ".tmp", 5);
  48. rv = location->AppendNative(nsDependentCString(buf, 12));
  49. if (NS_FAILED(rv)) return rv;
  50. rv = location->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
  51. if (NS_FAILED(rv)) return rv;
  52. location.swap(mLocation);
  53. mLocationIsTemp = true;
  54. }
  55. rv = NS_NewLocalFileOutputStream(getter_AddRefs(mSink), mLocation);
  56. if (NS_FAILED(rv)) return rv;
  57. // we could wrap this output stream with a buffered output stream,
  58. // but it shouldn't be necessary since we will be writing large
  59. // chunks given to us via OnDataAvailable.
  60. return NS_OK;
  61. }
  62. NS_IMETHODIMP
  63. nsDownloader::OnStopRequest(nsIRequest *request,
  64. nsISupports *ctxt,
  65. nsresult status)
  66. {
  67. if (mSink) {
  68. mSink->Close();
  69. mSink = nullptr;
  70. }
  71. mObserver->OnDownloadComplete(this, request, ctxt, status, mLocation);
  72. mObserver = nullptr;
  73. return NS_OK;
  74. }
  75. nsresult
  76. nsDownloader::ConsumeData(nsIInputStream* in,
  77. void* closure,
  78. const char* fromRawSegment,
  79. uint32_t toOffset,
  80. uint32_t count,
  81. uint32_t *writeCount)
  82. {
  83. nsDownloader *self = (nsDownloader *) closure;
  84. if (self->mSink)
  85. return self->mSink->Write(fromRawSegment, count, writeCount);
  86. *writeCount = count;
  87. return NS_OK;
  88. }
  89. NS_IMETHODIMP
  90. nsDownloader::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
  91. nsIInputStream *inStr,
  92. uint64_t sourceOffset, uint32_t count)
  93. {
  94. uint32_t n;
  95. return inStr->ReadSegments(ConsumeData, this, count, &n);
  96. }