blob: 2596ead94fb14fe031d7bc5094e26805deb43a73 [file] [log] [blame]
// Copyright 2017 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/service_worker/thread_safe_script_container.h"
#include "base/memory/ptr_util.h"
namespace blink {
ThreadSafeScriptContainer::RawScriptData::RawScriptData(
const String& encoding,
Vector<uint8_t> script_text,
Vector<uint8_t> meta_data)
: encoding_(encoding.IsolatedCopy()),
script_text_(std::move(script_text)),
meta_data_(std::move(meta_data)),
headers_(std::make_unique<CrossThreadHTTPHeaderMapData>()) {}
ThreadSafeScriptContainer::RawScriptData::~RawScriptData() = default;
void ThreadSafeScriptContainer::RawScriptData::AddHeader(const String& key,
const String& value) {
headers_->emplace_back(key.IsolatedCopy(), value.IsolatedCopy());
}
ThreadSafeScriptContainer::ThreadSafeScriptContainer()
: waiting_cv_(mutex_), are_all_data_added_(false) {}
void ThreadSafeScriptContainer::AddOnIOThread(
const KURL& url,
std::unique_ptr<RawScriptData> data) {
MutexLocker locker(mutex_);
DCHECK_EQ(script_data_.end(), script_data_.find(url));
ScriptStatus status = data ? ScriptStatus::kReceived : ScriptStatus::kFailed;
// |script_data_| is also accessed on the worker thread, so make a deep copy
// of |url| as key.
script_data_.Set(url.Copy(), std::make_pair(status, std::move(data)));
if (url == waiting_url_)
waiting_cv_.Signal();
}
ThreadSafeScriptContainer::ScriptStatus
ThreadSafeScriptContainer::GetStatusOnWorkerThread(const KURL& url) {
MutexLocker locker(mutex_);
auto it = script_data_.find(url);
if (it == script_data_.end())
return ScriptStatus::kPending;
return it->value.first;
}
void ThreadSafeScriptContainer::ResetOnWorkerThread(const KURL& url) {
MutexLocker locker(mutex_);
script_data_.erase(url);
}
bool ThreadSafeScriptContainer::WaitOnWorkerThread(const KURL& url) {
MutexLocker locker(mutex_);
DCHECK(!waiting_url_.IsValid())
<< "The script container is unexpectedly shared among worker threads.";
// |waiting_url_| is also accessed on the IO thread later, so make a deep copy
// of |url|.
waiting_url_ = url.Copy();
while (script_data_.find(url) == script_data_.end()) {
// If waiting script hasn't been added yet though all data are received,
// that means something went wrong.
if (are_all_data_added_) {
waiting_url_ = KURL();
return false;
}
// This is possible to be waken up spuriously, so that it's necessary to
// check if the entry is really added.
waiting_cv_.Wait();
}
waiting_url_ = KURL();
return true;
}
std::unique_ptr<ThreadSafeScriptContainer::RawScriptData>
ThreadSafeScriptContainer::TakeOnWorkerThread(const KURL& url) {
MutexLocker locker(mutex_);
auto it = script_data_.find(url);
DCHECK(it != script_data_.end())
<< "Script should have been received before calling Take";
std::pair<ScriptStatus, std::unique_ptr<RawScriptData>>& pair = it->value;
DCHECK_EQ(ScriptStatus::kReceived, pair.first);
pair.first = ScriptStatus::kTaken;
return std::move(pair.second);
}
void ThreadSafeScriptContainer::OnAllDataAddedOnIOThread() {
MutexLocker locker(mutex_);
are_all_data_added_ = true;
waiting_cv_.Broadcast();
}
ThreadSafeScriptContainer::~ThreadSafeScriptContainer() = default;
} // namespace blink