blob: 99497fb8fec98132eb6c947f952242cdf884aed4 [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,
base::MessageLoop::current()->task_runner(),
RespondWithCallback(), ReportLoadTimingInfo()) {}
FetchEvent::FetchEvent(
script::EnvironmentSettings* environment_settings, base::Token type,
const FetchEventInit& event_init_dict,
scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner,
RespondWithCallback respond_with_callback,
ReportLoadTimingInfo report_load_timing_info)
: ExtendableEvent(environment_settings, type, event_init_dict),
environment_settings_(environment_settings),
callback_task_runner_(callback_task_runner),
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());
respond_with_done_ = std::make_unique<script::ValuePromiseVoid::Reference>(
this, script_value_factory->CreateBasicPromise<void>());
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) {
callback_task_runner_->PostTask(
FROM_HERE, base::BindOnce(
[](ReportLoadTimingInfo report_load_timing_info,
const net::LoadTimingInfo& load_timing_info) {
std::move(report_load_timing_info).Run(load_timing_info);
},
std::move(report_load_timing_info_), load_timing_info_));
handled_property_->value().Resolve();
return web::cache_utils::OptionalPromise(
web::cache_utils::Call(response_promise->Result(), "text"));
}
void FetchEvent::RespondWithDone() { respond_with_done_->value().Resolve(); }
base::Optional<v8::Local<v8::Promise>> FetchEvent::DoRespondWith(
v8::Local<v8::Promise> text_promise) {
auto* isolate = text_promise->GetIsolate();
auto context = isolate->GetCurrentContext();
auto body = web::cache_utils::FromV8String(text_promise->GetIsolate(),
text_promise->Result());
auto callback =
base::BindOnce(&FetchEvent::RespondWithDone, base::Unretained(this));
web::get_context(environment_settings_)
->network_module()
->task_runner()
->PostTask(
FROM_HERE,
base::BindOnce(
[](scoped_refptr<base::SingleThreadTaskRunner>
callback_task_runner,
RespondWithCallback respond_with_callback, std::string body,
base::MessageLoop* loop, base::OnceClosure callback) {
callback_task_runner->PostTask(
FROM_HERE,
base::BindOnce(
[](RespondWithCallback respond_with_callback,
std::string body) {
std::move(respond_with_callback)
.Run(std::make_unique<std::string>(
std::move(body)));
},
std::move(respond_with_callback), std::move(body)));
loop->task_runner()->PostTask(FROM_HERE, std::move(callback));
},
callback_task_runner_, std::move(respond_with_callback_),
std::move(body), base::MessageLoop::current(),
std::move(callback)));
return respond_with_done_->value().promise();
}
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_, response, exception_state);
WaitUntil(environment_settings_, wait_promise, exception_state);
}
script::HandlePromiseVoid FetchEvent::handled() {
return script::HandlePromiseVoid(handled_property_->referenced_value());
}
} // namespace worker
} // namespace cobalt