nsBaseContentStream.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "nsBaseContentStream.h"
  6. #include "nsStreamUtils.h"
  7. //-----------------------------------------------------------------------------
  8. void
  9. nsBaseContentStream::DispatchCallback(bool async)
  10. {
  11. if (!mCallback)
  12. return;
  13. // It's important to clear mCallback and mCallbackTarget up-front because the
  14. // OnInputStreamReady implementation may call our AsyncWait method.
  15. nsCOMPtr<nsIInputStreamCallback> callback;
  16. if (async) {
  17. callback = NS_NewInputStreamReadyEvent(mCallback, mCallbackTarget);
  18. mCallback = nullptr;
  19. } else {
  20. callback.swap(mCallback);
  21. }
  22. mCallbackTarget = nullptr;
  23. callback->OnInputStreamReady(this);
  24. }
  25. //-----------------------------------------------------------------------------
  26. // nsBaseContentStream::nsISupports
  27. NS_IMPL_ADDREF(nsBaseContentStream)
  28. NS_IMPL_RELEASE(nsBaseContentStream)
  29. // We only support nsIAsyncInputStream when we are in non-blocking mode.
  30. NS_INTERFACE_MAP_BEGIN(nsBaseContentStream)
  31. NS_INTERFACE_MAP_ENTRY(nsIInputStream)
  32. NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAsyncInputStream, mNonBlocking)
  33. NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
  34. NS_INTERFACE_MAP_END_THREADSAFE
  35. //-----------------------------------------------------------------------------
  36. // nsBaseContentStream::nsIInputStream
  37. NS_IMETHODIMP
  38. nsBaseContentStream::Close()
  39. {
  40. return IsClosed() ? NS_OK : CloseWithStatus(NS_BASE_STREAM_CLOSED);
  41. }
  42. NS_IMETHODIMP
  43. nsBaseContentStream::Available(uint64_t *result)
  44. {
  45. *result = 0;
  46. return mStatus;
  47. }
  48. NS_IMETHODIMP
  49. nsBaseContentStream::Read(char *buf, uint32_t count, uint32_t *result)
  50. {
  51. return ReadSegments(NS_CopySegmentToBuffer, buf, count, result);
  52. }
  53. NS_IMETHODIMP
  54. nsBaseContentStream::ReadSegments(nsWriteSegmentFun fun, void *closure,
  55. uint32_t count, uint32_t *result)
  56. {
  57. *result = 0;
  58. if (mStatus == NS_BASE_STREAM_CLOSED)
  59. return NS_OK;
  60. // No data yet
  61. if (!IsClosed() && IsNonBlocking())
  62. return NS_BASE_STREAM_WOULD_BLOCK;
  63. return mStatus;
  64. }
  65. NS_IMETHODIMP
  66. nsBaseContentStream::IsNonBlocking(bool *result)
  67. {
  68. *result = mNonBlocking;
  69. return NS_OK;
  70. }
  71. //-----------------------------------------------------------------------------
  72. // nsBaseContentStream::nsIAsyncInputStream
  73. NS_IMETHODIMP
  74. nsBaseContentStream::CloseWithStatus(nsresult status)
  75. {
  76. if (IsClosed())
  77. return NS_OK;
  78. NS_ENSURE_ARG(NS_FAILED(status));
  79. mStatus = status;
  80. DispatchCallback();
  81. return NS_OK;
  82. }
  83. NS_IMETHODIMP
  84. nsBaseContentStream::AsyncWait(nsIInputStreamCallback *callback,
  85. uint32_t flags, uint32_t requestedCount,
  86. nsIEventTarget *target)
  87. {
  88. // Our _only_ consumer is nsInputStreamPump, so we simplify things here by
  89. // making assumptions about how we will be called.
  90. NS_ASSERTION(target, "unexpected parameter");
  91. NS_ASSERTION(flags == 0, "unexpected parameter");
  92. NS_ASSERTION(requestedCount == 0, "unexpected parameter");
  93. #ifdef DEBUG
  94. bool correctThread;
  95. target->IsOnCurrentThread(&correctThread);
  96. NS_ASSERTION(correctThread, "event target must be on the current thread");
  97. #endif
  98. mCallback = callback;
  99. mCallbackTarget = target;
  100. if (!mCallback)
  101. return NS_OK;
  102. // If we're already closed, then dispatch this callback immediately.
  103. if (IsClosed()) {
  104. DispatchCallback();
  105. return NS_OK;
  106. }
  107. OnCallbackPending();
  108. return NS_OK;
  109. }