blob: 0d7d72dc4b7b710c11cd11bc0c43bea2a1d47c20 [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/platform/loader/code_cache_loader.h"
#include "base/bind.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "mojo/public/cpp/base/big_buffer.h"
#include "third_party/blink/public/platform/platform.h"
namespace blink {
CodeCacheLoader::CodeCacheLoader() : CodeCacheLoader(nullptr) {}
CodeCacheLoader::CodeCacheLoader(base::WaitableEvent* terminate_sync_load_event)
: terminate_sync_load_event_(terminate_sync_load_event) {}
CodeCacheLoader::~CodeCacheLoader() = default;
void CodeCacheLoader::FetchFromCodeCacheSynchronously(
const WebURL& url,
base::Time* response_time_out,
mojo_base::BigBuffer* data_out) {
base::WaitableEvent fetch_code_cache_event(
base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED);
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
base::ThreadPool::CreateSingleThreadTaskRunner({});
// Also watch for terminate requests from the main thread when running on
// worker threads.
if (terminate_sync_load_event_) {
terminate_watcher_.StartWatching(
terminate_sync_load_event_,
base::BindOnce(&CodeCacheLoader::OnTerminate,
weak_ptr_factory_.GetWeakPtr(),
base::Unretained(&fetch_code_cache_event)),
task_runner);
}
FetchCodeCacheCallback callback =
base::BindOnce(&CodeCacheLoader::ReceiveDataForSynchronousFetch,
weak_ptr_factory_.GetWeakPtr());
// It is Ok to pass |fetch_code_cache_event| with base::Unretained. Since
// this thread is stalled, the fetch_code_cache_event will be kept alive.
task_runner->PostTask(
FROM_HERE, base::BindOnce(&CodeCacheLoader::FetchFromCodeCacheImpl,
weak_ptr_factory_.GetWeakPtr(),
mojom::CodeCacheType::kJavascript, url,
std::move(callback),
base::Unretained(&fetch_code_cache_event)));
// Wait for the fetch from code cache to finish.
fetch_code_cache_event.Wait();
// Set the output data
*response_time_out = response_time_for_sync_load_;
*data_out = std::move(data_for_sync_load_);
}
void CodeCacheLoader::FetchFromCodeCache(mojom::CodeCacheType cache_type,
const WebURL& url,
FetchCodeCacheCallback callback) {
FetchFromCodeCacheImpl(cache_type, url, std::move(callback), nullptr);
}
void CodeCacheLoader::FetchFromCodeCacheImpl(mojom::CodeCacheType cache_type,
const WebURL& url,
FetchCodeCacheCallback callback,
base::WaitableEvent* fetch_event) {
// This may run on a different thread for synchronous events. It is Ok to pass
// fetch_event, because the thread is stalled and it will keep the fetch_event
// alive.
Platform::Current()->FetchCachedCode(
cache_type, url,
base::BindOnce(&CodeCacheLoader::OnReceiveCachedCode,
weak_ptr_factory_.GetWeakPtr(), std::move(callback),
fetch_event));
}
void CodeCacheLoader::OnReceiveCachedCode(FetchCodeCacheCallback callback,
base::WaitableEvent* fetch_event,
base::Time response_time,
mojo_base::BigBuffer data) {
// The loader would be destroyed once the fetch has completed. On terminate
// the fetch event would be signalled and the fetch should complete and hence
// we should not see this callback anymore.
DCHECK(!terminated_);
std::move(callback).Run(response_time, std::move(data));
if (fetch_event)
fetch_event->Signal();
}
void CodeCacheLoader::ReceiveDataForSynchronousFetch(
base::Time response_time,
mojo_base::BigBuffer data) {
response_time_for_sync_load_ = response_time;
data_for_sync_load_ = std::move(data);
}
void CodeCacheLoader::OnTerminate(base::WaitableEvent* fetch_event,
base::WaitableEvent* terminate_event) {
DCHECK(!terminated_);
terminated_ = true;
DCHECK(fetch_event);
fetch_event->Signal();
}
// static
std::unique_ptr<WebCodeCacheLoader> WebCodeCacheLoader::Create(
base::WaitableEvent* terminate_sync_load_event) {
return std::make_unique<CodeCacheLoader>(terminate_sync_load_event);
}
} // namespace blink