blob: 82e092713d3a81566a56cfba4256b274ff20fb3d [file] [log] [blame]
// Copyright 2022 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/worker/fetch_event.h"
#include <memory>
#include <utility>
#include "cobalt/script/v8c/conversion_helpers.h"
#include "cobalt/script/v8c/v8c_value_handle.h"
#include "cobalt/web/cache_utils.h"
#include "cobalt/web/environment_settings_helper.h"
namespace cobalt {
namespace worker {
FetchEvent::FetchEvent(script::EnvironmentSettings* environment_settings,
const std::string& type,
const FetchEventInit& event_init_dict)
: FetchEvent(environment_settings, base::Token(type), event_init_dict,
RespondWithCallback(), ReportLoadTimingInfo()) {}
FetchEvent::FetchEvent(script::EnvironmentSettings* environment_settings,
base::Token type, const FetchEventInit& event_init_dict,
RespondWithCallback respond_with_callback,
ReportLoadTimingInfo report_load_timing_info)
: ExtendableEvent(type, event_init_dict),
environment_settings_(environment_settings),
respond_with_callback_(std::move(respond_with_callback)),
report_load_timing_info_(std::move(report_load_timing_info)) {
auto script_value_factory =
web::get_script_value_factory(environment_settings_);
handled_property_ = std::make_unique<script::ValuePromiseVoid::Reference>(
this, script_value_factory->CreateBasicPromise<void>());
request_ = std::make_unique<script::ValueHandleHolder::Reference>(
this, event_init_dict.request());
load_timing_info_.request_start = base::TimeTicks::Now();
load_timing_info_.request_start_time = base::Time::Now();
load_timing_info_.send_start = base::TimeTicks::Now();
load_timing_info_.send_end = base::TimeTicks::Now();
load_timing_info_.service_worker_start_time = base::TimeTicks::Now();
}
base::Optional<v8::Local<v8::Promise>> FetchEvent::GetText(
v8::Local<v8::Promise> response_promise) {
std::move(report_load_timing_info_).Run(load_timing_info_);
handled_property_->value().Resolve();
return web::cache_utils::OptionalPromise(
web::cache_utils::Call(response_promise->Result(), "text"));
}
base::Optional<v8::Local<v8::Promise>> FetchEvent::DoRespondWith(
v8::Local<v8::Promise> text_promise) {
auto* isolate = text_promise->GetIsolate();
auto context = isolate->GetCurrentContext();
auto resolver = v8::Promise::Resolver::New(context);
if (resolver.IsEmpty()) {
return base::nullopt;
}
auto body = web::cache_utils::FromV8String(text_promise->GetIsolate(),
text_promise->Result());
auto callback = base::BindOnce(
[](v8::Local<v8::Context> context,
v8::Local<v8::Promise::Resolver> resolver) {
DCHECK(resolver->Resolve(context, v8::Undefined(resolver->GetIsolate()))
.FromMaybe(false));
},
context, resolver.ToLocalChecked());
web::get_context(environment_settings_)
->network_module()
->task_runner()
->PostTask(
FROM_HERE,
base::BindOnce(
[](RespondWithCallback respond_with_callback, std::string body,
base::MessageLoop* loop, base::OnceClosure callback) {
std::move(respond_with_callback)
.Run(std::make_unique<std::string>(std::move(body)));
loop->task_runner()->PostTask(FROM_HERE, std::move(callback));
},
std::move(respond_with_callback_), std::move(body),
base::MessageLoop::current(), std::move(callback)));
return resolver.ToLocalChecked()->GetPromise();
}
void FetchEvent::RespondWith(
std::unique_ptr<script::Promise<script::ValueHandle*>>& response,
script::ExceptionState* exception_state) {
respond_with_called_ = true;
auto text_promise = web::cache_utils::Then(
response->promise(),
base::BindOnce(&FetchEvent::GetText, base::Unretained(this)));
if (!text_promise) {
return;
}
auto done_promise = web::cache_utils::Then(
text_promise.value(),
base::BindOnce(&FetchEvent::DoRespondWith, base::Unretained(this)));
if (!done_promise) {
return;
}
auto* isolate = response->promise()->GetIsolate();
std::unique_ptr<script::Promise<script::ValueHandle*>> wait_promise;
script::v8c::FromJSValue(isolate, done_promise.value(), 0, exception_state,
&wait_promise);
WaitUntil(environment_settings_, wait_promise, exception_state);
}
script::HandlePromiseVoid FetchEvent::handled() {
return script::HandlePromiseVoid(handled_property_->referenced_value());
}
} // namespace worker
} // namespace cobalt