blob: c928351985d4904592b4400ea90a0d301014d4f1 [file] [log] [blame]
// Copyright 2015 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 "extensions/renderer/worker_script_context_set.h"
#include <algorithm>
#include <utility>
#include "extensions/renderer/script_context.h"
namespace extensions {
using ContextVector = ScopedVector<ScriptContext>;
namespace {
// Returns an iterator to the ScriptContext associated with |v8_context| from
// |contexts|, or |contexts|->end() if not found.
ContextVector::iterator FindContext(ContextVector* contexts,
v8::Local<v8::Context> v8_context) {
auto context_matches = [&v8_context](ScriptContext* context) {
v8::HandleScope handle_scope(context->isolate());
v8::Context::Scope context_scope(context->v8_context());
return context->v8_context() == v8_context;
};
return std::find_if(contexts->begin(), contexts->end(), context_matches);
}
} // namespace
WorkerScriptContextSet::WorkerScriptContextSet() {}
WorkerScriptContextSet::~WorkerScriptContextSet() {}
void WorkerScriptContextSet::Insert(std::unique_ptr<ScriptContext> context) {
DCHECK_GT(content::WorkerThread::GetCurrentId(), 0)
<< "Must be called on a worker thread";
ContextVector* contexts = contexts_tls_.Get();
if (!contexts) {
// First context added for this thread. Create a new set, then wait for
// this thread's shutdown.
contexts = new ContextVector();
contexts_tls_.Set(contexts);
content::WorkerThread::AddObserver(this);
}
CHECK(FindContext(contexts, context->v8_context()) == contexts->end())
<< "Worker for " << context->url() << " is already in this set";
contexts->push_back(std::move(context));
}
void WorkerScriptContextSet::Remove(v8::Local<v8::Context> v8_context,
const GURL& url) {
DCHECK_GT(content::WorkerThread::GetCurrentId(), 0)
<< "Must be called on a worker thread";
ContextVector* contexts = contexts_tls_.Get();
if (!contexts) {
// Thread has already been torn down, and |v8_context| removed. I'm not
// sure this can actually happen (depends on in what order blink fires
// events), but SW lifetime has bitten us before, so be cautious.
return;
}
auto context_it = FindContext(contexts, v8_context);
CHECK(context_it != contexts->end()) << "Worker for " << url
<< " is not in this set";
ScriptContext* context = *context_it;
DCHECK_EQ(url, context->url());
context->Invalidate();
contexts->erase(context_it);
}
void WorkerScriptContextSet::WillStopCurrentWorkerThread() {
content::WorkerThread::RemoveObserver(this);
ContextVector* contexts = contexts_tls_.Get();
DCHECK(contexts);
for (ScriptContext* context : *contexts)
context->Invalidate();
contexts_tls_.Set(nullptr);
delete contexts;
}
} // namespace extensions