// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/renderer/core/fetch/body.h"

#include <memory>
#include <utility>

#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
#include "third_party/blink/renderer/core/fetch/fetch_data_loader.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/forms/form_data.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
#include "third_party/blink/renderer/core/url/url_search_params.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
#include "third_party/blink/renderer/platform/heap/disallow_new_wrapper.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h"
#include "third_party/blink/renderer/platform/network/parsed_content_type.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"

namespace blink {

namespace {

class BodyConsumerBase : public GarbageCollected<BodyConsumerBase>,
                         public FetchDataLoader::Client {
 public:
  explicit BodyConsumerBase(ScriptPromiseResolver* resolver)
      : resolver_(resolver),
        task_runner_(ExecutionContext::From(resolver_->GetScriptState())
                         ->GetTaskRunner(TaskType::kNetworking)) {}
  ScriptPromiseResolver* Resolver() { return resolver_; }
  void DidFetchDataLoadFailed() override {
    ScriptState::Scope scope(Resolver()->GetScriptState());
    resolver_->Reject(V8ThrowException::CreateTypeError(
        Resolver()->GetScriptState()->GetIsolate(), "Failed to fetch"));
  }

  void Abort() override {
    resolver_->Reject(
        MakeGarbageCollected<DOMException>(DOMExceptionCode::kAbortError));
  }

  // Resource Timing event is not yet added, so delay the resolution timing
  // a bit. See https://crbug.com/507169.
  // TODO(yhirano): Fix this problem in a more sophisticated way.
  template <typename T>
  void ResolveLater(const T& object) {
    task_runner_->PostTask(FROM_HERE,
                           WTF::Bind(&BodyConsumerBase::ResolveNow<T>,
                                     WrapPersistent(this), object));
  }

  void Trace(Visitor* visitor) const override {
    visitor->Trace(resolver_);
    FetchDataLoader::Client::Trace(visitor);
  }

 private:
  template <typename T>
  void ResolveNow(const T& object) {
    resolver_->Resolve(object);
  }

  const Member<ScriptPromiseResolver> resolver_;
  const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  DISALLOW_COPY_AND_ASSIGN(BodyConsumerBase);
};

class BodyBlobConsumer final : public BodyConsumerBase {
 public:
  explicit BodyBlobConsumer(ScriptPromiseResolver* resolver)
      : BodyConsumerBase(resolver) {}

  void DidFetchDataLoadedBlobHandle(
      scoped_refptr<BlobDataHandle> blob_data_handle) override {
    ResolveLater(WrapPersistent(
        MakeGarbageCollected<Blob>(std::move(blob_data_handle))));
  }
  DISALLOW_COPY_AND_ASSIGN(BodyBlobConsumer);
};

class BodyArrayBufferConsumer final : public BodyConsumerBase {
 public:
  explicit BodyArrayBufferConsumer(ScriptPromiseResolver* resolver)
      : BodyConsumerBase(resolver) {}

  void DidFetchDataLoadedArrayBuffer(DOMArrayBuffer* array_buffer) override {
    ResolveLater(WrapPersistent(array_buffer));
  }
  DISALLOW_COPY_AND_ASSIGN(BodyArrayBufferConsumer);
};

class BodyFormDataConsumer final : public BodyConsumerBase {
 public:
  explicit BodyFormDataConsumer(ScriptPromiseResolver* resolver)
      : BodyConsumerBase(resolver) {}

  void DidFetchDataLoadedFormData(FormData* formData) override {
    ResolveLater(WrapPersistent(formData));
  }

  void DidFetchDataLoadedString(const String& string) override {
    auto* formData = MakeGarbageCollected<FormData>();
    for (const auto& pair : URLSearchParams::Create(string)->Params())
      formData->append(pair.first, pair.second);
    DidFetchDataLoadedFormData(formData);
  }
  DISALLOW_COPY_AND_ASSIGN(BodyFormDataConsumer);
};

class BodyTextConsumer final : public BodyConsumerBase {
 public:
  explicit BodyTextConsumer(ScriptPromiseResolver* resolver)
      : BodyConsumerBase(resolver) {}

  void DidFetchDataLoadedString(const String& string) override {
    ResolveLater(string);
  }
  DISALLOW_COPY_AND_ASSIGN(BodyTextConsumer);
};

class BodyJsonConsumer final : public BodyConsumerBase {
 public:
  explicit BodyJsonConsumer(ScriptPromiseResolver* resolver)
      : BodyConsumerBase(resolver) {}

  void DidFetchDataLoadedString(const String& string) override {
    if (!Resolver()->GetExecutionContext() ||
        Resolver()->GetExecutionContext()->IsContextDestroyed())
      return;
    ScriptState::Scope scope(Resolver()->GetScriptState());
    v8::Isolate* isolate = Resolver()->GetScriptState()->GetIsolate();
    v8::Local<v8::String> input_string = V8String(isolate, string);
    v8::TryCatch trycatch(isolate);
    v8::Local<v8::Value> parsed;
    if (v8::JSON::Parse(Resolver()->GetScriptState()->GetContext(),
                        input_string)
            .ToLocal(&parsed)) {
      ResolveLater(WrapPersistent(WrapDisallowNew(
          ScriptValue(Resolver()->GetScriptState()->GetIsolate(), parsed))));
    } else
      Resolver()->Reject(trycatch.Exception());
  }
  DISALLOW_COPY_AND_ASSIGN(BodyJsonConsumer);
};

}  // namespace

ScriptPromise Body::arrayBuffer(ScriptState* script_state,
                                ExceptionState& exception_state) {
  RejectInvalidConsumption(exception_state);
  if (exception_state.HadException())
    return ScriptPromise();

  // When the main thread sends a V8::TerminateExecution() signal to a worker
  // thread, any V8 API on the worker thread starts returning an empty
  // handle. This can happen in this function. To avoid the situation, we
  // first check the ExecutionContext and return immediately if it's already
  // gone (which means that the V8::TerminateExecution() signal has been sent
  // to this worker thread).
  if (!ExecutionContext::From(script_state))
    return ScriptPromise();

  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
  ScriptPromise promise = resolver->Promise();
  if (BodyBuffer()) {
    BodyBuffer()->StartLoading(
        FetchDataLoader::CreateLoaderAsArrayBuffer(),
        MakeGarbageCollected<BodyArrayBufferConsumer>(resolver),
        exception_state);
    if (exception_state.HadException()) {
      // Need to resolve the ScriptPromiseResolver to avoid a DCHECK().
      resolver->Resolve();
      return ScriptPromise();
    }
  } else {
    resolver->Resolve(DOMArrayBuffer::Create(size_t{0}, size_t{0}));
  }
  return promise;
}

ScriptPromise Body::blob(ScriptState* script_state,
                         ExceptionState& exception_state) {
  RejectInvalidConsumption(exception_state);
  if (exception_state.HadException())
    return ScriptPromise();

  // See above comment.
  if (!ExecutionContext::From(script_state))
    return ScriptPromise();

  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
  ScriptPromise promise = resolver->Promise();
  if (BodyBuffer()) {
    ExecutionContext* context = ExecutionContext::From(script_state);
    BodyBuffer()->StartLoading(
        FetchDataLoader::CreateLoaderAsBlobHandle(
            MimeType(), context->GetTaskRunner(TaskType::kNetworking)),
        MakeGarbageCollected<BodyBlobConsumer>(resolver), exception_state);
    if (exception_state.HadException()) {
      // Need to resolve the ScriptPromiseResolver to avoid a DCHECK().
      resolver->Resolve();
      return ScriptPromise();
    }
  } else {
    auto blob_data = std::make_unique<BlobData>();
    blob_data->SetContentType(MimeType());
    resolver->Resolve(MakeGarbageCollected<Blob>(
        BlobDataHandle::Create(std::move(blob_data), 0)));
  }
  return promise;
}

ScriptPromise Body::formData(ScriptState* script_state,
                             ExceptionState& exception_state) {
  RejectInvalidConsumption(exception_state);
  if (exception_state.HadException())
    return ScriptPromise();

  // See above comment.
  if (!ExecutionContext::From(script_state))
    return ScriptPromise();

  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
  const ParsedContentType parsedTypeWithParameters(ContentType());
  const String parsedType = parsedTypeWithParameters.MimeType().LowerASCII();
  ScriptPromise promise = resolver->Promise();
  if (parsedType == "multipart/form-data") {
    const String boundary =
        parsedTypeWithParameters.ParameterValueForName("boundary");
    auto* body_buffer = BodyBuffer();
    if (body_buffer && !boundary.IsEmpty()) {
      body_buffer->StartLoading(
          FetchDataLoader::CreateLoaderAsFormData(boundary),
          MakeGarbageCollected<BodyFormDataConsumer>(resolver),
          exception_state);
      if (exception_state.HadException()) {
        // Need to resolve the ScriptPromiseResolver to avoid a DCHECK().
        resolver->Resolve();
        return ScriptPromise();
      }
      return promise;
    }
  } else if (parsedType == "application/x-www-form-urlencoded") {
    if (BodyBuffer()) {
      // According to https://fetch.spec.whatwg.org/#concept-body-package-data
      // application/x-www-form-urlencoded FormData bytes are parsed using
      // https://url.spec.whatwg.org/#concept-urlencoded-parser
      // which does not decode BOM.
      BodyBuffer()->StartLoading(
          FetchDataLoader::CreateLoaderAsString(
              TextResourceDecoderOptions::CreateUTF8DecodeWithoutBOM()),
          MakeGarbageCollected<BodyFormDataConsumer>(resolver),
          exception_state);
      if (exception_state.HadException()) {
        // Need to resolve the ScriptPromiseResolver to avoid a DCHECK().
        resolver->Resolve();
        return ScriptPromise();
      }
    } else {
      resolver->Resolve(MakeGarbageCollected<FormData>());
    }
    return promise;
  } else {
    if (BodyBuffer()) {
      BodyBuffer()->StartLoading(
          FetchDataLoader::CreateLoaderAsFailure(),
          MakeGarbageCollected<BodyFormDataConsumer>(resolver),
          exception_state);
      if (exception_state.HadException()) {
        // Need to resolve the ScriptPromiseResolver to avoid a DCHECK().
        resolver->Resolve();
        return ScriptPromise();
      }
      return promise;
    }
  }

  resolver->Reject(V8ThrowException::CreateTypeError(script_state->GetIsolate(),
                                                     "Invalid MIME type"));
  return promise;
}

ScriptPromise Body::json(ScriptState* script_state,
                         ExceptionState& exception_state) {
  RejectInvalidConsumption(exception_state);
  if (exception_state.HadException())
    return ScriptPromise();

  // See above comment.
  if (!ExecutionContext::From(script_state))
    return ScriptPromise();

  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
  ScriptPromise promise = resolver->Promise();
  if (BodyBuffer()) {
    BodyBuffer()->StartLoading(
        FetchDataLoader::CreateLoaderAsString(
            TextResourceDecoderOptions::CreateUTF8Decode()),
        MakeGarbageCollected<BodyJsonConsumer>(resolver), exception_state);
    if (exception_state.HadException()) {
      // Need to resolve the ScriptPromiseResolver to avoid a DCHECK().
      resolver->Resolve();
      return ScriptPromise();
    }
  } else {
    resolver->Reject(V8ThrowException::CreateSyntaxError(
        script_state->GetIsolate(), "Unexpected end of input"));
  }
  return promise;
}

ScriptPromise Body::text(ScriptState* script_state,
                         ExceptionState& exception_state) {
  RejectInvalidConsumption(exception_state);
  if (exception_state.HadException())
    return ScriptPromise();

  // See above comment.
  if (!ExecutionContext::From(script_state))
    return ScriptPromise();

  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
  ScriptPromise promise = resolver->Promise();
  if (BodyBuffer()) {
    BodyBuffer()->StartLoading(
        FetchDataLoader::CreateLoaderAsString(
            TextResourceDecoderOptions::CreateUTF8Decode()),
        MakeGarbageCollected<BodyTextConsumer>(resolver), exception_state);
    if (exception_state.HadException()) {
      // Need to resolve the ScriptPromiseResolver to avoid a DCHECK().
      resolver->Resolve();
      return ScriptPromise();
    }
  } else {
    resolver->Resolve(String());
  }
  return promise;
}

ReadableStream* Body::body() {
  if (auto* execution_context = GetExecutionContext()) {
    if (execution_context->IsServiceWorkerGlobalScope()) {
      execution_context->CountUse(WebFeature::kFetchBodyStreamInServiceWorker);
    } else {
      execution_context->CountUse(
          WebFeature::kFetchBodyStreamOutsideServiceWorker);
    }
  }

  if (!BodyBuffer())
    return nullptr;
  return BodyBuffer()->Stream();
}

bool Body::IsBodyUsed() const {
  auto* body_buffer = BodyBuffer();
  return body_buffer && body_buffer->IsStreamDisturbed();
}

bool Body::IsBodyLocked() const {
  auto* body_buffer = BodyBuffer();
  return body_buffer && body_buffer->IsStreamLocked();
}

bool Body::HasPendingActivity() const {
  if (!GetExecutionContext() || GetExecutionContext()->IsContextDestroyed())
    return false;
  auto* body_buffer = BodyBuffer();
  if (!body_buffer)
    return false;
  return body_buffer->HasPendingActivity();
}

Body::Body(ExecutionContext* context) : ExecutionContextClient(context) {}

void Body::RejectInvalidConsumption(ExceptionState& exception_state) const {
  if (IsBodyLocked()) {
    exception_state.ThrowTypeError("body stream is locked");
  }

  if (IsBodyUsed()) {
    exception_state.ThrowTypeError("body stream already read");
  }
}

}  // namespace blink
