blob: 0d189d44fbde279f860e3180b2e70771793c0fbd [file] [log] [blame]
// Copyright 2016 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_thread_dispatcher.h"
#include "base/threading/thread_local.h"
#include "base/values.h"
#include "content/public/child/worker_thread.h"
#include "content/public/renderer/render_thread.h"
#include "extensions/common/extension_messages.h"
#include "extensions/renderer/service_worker_data.h"
namespace extensions {
namespace {
base::LazyInstance<WorkerThreadDispatcher> g_instance =
LAZY_INSTANCE_INITIALIZER;
base::LazyInstance<base::ThreadLocalPointer<extensions::ServiceWorkerData>>
g_data_tls = LAZY_INSTANCE_INITIALIZER;
void OnResponseOnWorkerThread(int request_id,
bool succeeded,
const std::unique_ptr<base::ListValue>& response,
const std::string& error) {
ServiceWorkerData* data = g_data_tls.Pointer()->Get();
WorkerThreadDispatcher::GetRequestSender()->HandleWorkerResponse(
request_id, data->service_worker_version_id(), succeeded, *response,
error);
}
} // namespace
WorkerThreadDispatcher::WorkerThreadDispatcher() {}
WorkerThreadDispatcher::~WorkerThreadDispatcher() {}
WorkerThreadDispatcher* WorkerThreadDispatcher::Get() {
return g_instance.Pointer();
}
void WorkerThreadDispatcher::Init(content::RenderThread* render_thread) {
DCHECK(render_thread);
DCHECK_EQ(content::RenderThread::Get(), render_thread);
DCHECK(!message_filter_);
message_filter_ = render_thread->GetSyncMessageFilter();
render_thread->AddObserver(this);
}
V8SchemaRegistry* WorkerThreadDispatcher::GetV8SchemaRegistry() {
ServiceWorkerData* data = g_data_tls.Pointer()->Get();
DCHECK(data);
return data->v8_schema_registry();
}
// static
ServiceWorkerRequestSender* WorkerThreadDispatcher::GetRequestSender() {
ServiceWorkerData* data = g_data_tls.Pointer()->Get();
DCHECK(data);
return data->request_sender();
}
bool WorkerThreadDispatcher::OnControlMessageReceived(
const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(WorkerThreadDispatcher, message)
IPC_MESSAGE_HANDLER(ExtensionMsg_ResponseWorker, OnResponseWorker)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
bool WorkerThreadDispatcher::Send(IPC::Message* message) {
return message_filter_->Send(message);
}
void WorkerThreadDispatcher::OnResponseWorker(int worker_thread_id,
int request_id,
bool succeeded,
const base::ListValue& response,
const std::string& error) {
content::WorkerThread::PostTask(
worker_thread_id,
base::Bind(&OnResponseOnWorkerThread, request_id, succeeded,
// TODO(lazyboy): Can we avoid CreateDeepCopy()?
base::Passed(response.CreateDeepCopy()), error));
}
void WorkerThreadDispatcher::AddWorkerData(int64_t service_worker_version_id) {
ServiceWorkerData* data = g_data_tls.Pointer()->Get();
if (!data) {
ServiceWorkerData* new_data =
new ServiceWorkerData(this, service_worker_version_id);
g_data_tls.Pointer()->Set(new_data);
}
}
void WorkerThreadDispatcher::RemoveWorkerData(
int64_t service_worker_version_id) {
ServiceWorkerData* data = g_data_tls.Pointer()->Get();
if (data) {
DCHECK_EQ(service_worker_version_id, data->service_worker_version_id());
delete data;
g_data_tls.Pointer()->Set(nullptr);
}
}
} // namespace extensions