blob: 20a31fef33e96eac59933169e2b35f46b1d3ff80 [file] [log] [blame]
// Copyright 2018 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/modules/background_fetch/background_fetch_record.h"
#include "third_party/blink/renderer/core/fetch/request.h"
#include "third_party/blink/renderer/core/fetch/response.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
namespace blink {
BackgroundFetchRecord::BackgroundFetchRecord(Request* request,
ScriptState* script_state)
: request_(request), script_state_(script_state) {
DCHECK(request_);
DCHECK(script_state_);
response_ready_property_ = MakeGarbageCollected<ResponseReadyProperty>(
ExecutionContext::From(script_state), this,
ResponseReadyProperty::kResponseReady);
}
BackgroundFetchRecord::~BackgroundFetchRecord() = default;
void BackgroundFetchRecord::ResolveResponseReadyProperty(Response* response) {
if (response_ready_property_->GetState() !=
ScriptPromisePropertyBase::State::kPending) {
return;
}
switch (record_state_) {
case State::kPending:
return;
case State::kAborted:
response_ready_property_->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kAbortError,
"The fetch was aborted before the record was processed."));
return;
case State::kSettled:
if (response) {
response_ready_property_->Resolve(response);
return;
}
if (!script_state_->ContextIsValid())
return;
// TODO(crbug.com/875201): Per https://wicg.github.io/background-fetch/
// #background-fetch-response-exposed, this should be resolved with a
// TypeError. Figure out a way to do so.
// Rejecting this with a TypeError here doesn't work because the
// RejectedType is a DOMException. Update this with the correct error
// once confirmed, or change the RejectedType.
response_ready_property_->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kUnknownError, "The response is not available."));
}
}
ScriptPromise BackgroundFetchRecord::responseReady(ScriptState* script_state) {
return response_ready_property_->Promise(script_state->World());
}
Request* BackgroundFetchRecord::request() const {
return request_;
}
void BackgroundFetchRecord::UpdateState(
BackgroundFetchRecord::State updated_state) {
DCHECK_EQ(record_state_, State::kPending);
if (!script_state_->ContextIsValid())
return;
record_state_ = updated_state;
ResolveResponseReadyProperty(/* updated_response = */ nullptr);
}
void BackgroundFetchRecord::SetResponseAndUpdateState(
mojom::blink::FetchAPIResponsePtr& response) {
DCHECK(record_state_ == State::kPending);
DCHECK(!response.is_null());
if (!script_state_->ContextIsValid())
return;
record_state_ = State::kSettled;
ScriptState::Scope scope(script_state_);
ResolveResponseReadyProperty(Response::Create(script_state_, *response));
}
bool BackgroundFetchRecord::IsRecordPending() {
return record_state_ == State::kPending;
}
void BackgroundFetchRecord::OnRequestCompleted(
mojom::blink::FetchAPIResponsePtr response) {
if (!response.is_null())
SetResponseAndUpdateState(response);
else
UpdateState(State::kSettled);
}
const KURL& BackgroundFetchRecord::ObservedUrl() const {
return request_->url();
}
void BackgroundFetchRecord::Trace(blink::Visitor* visitor) {
visitor->Trace(request_);
visitor->Trace(response_ready_property_);
visitor->Trace(script_state_);
ScriptWrappable::Trace(visitor);
}
} // namespace blink