1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
// 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/memory/ptr_util.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/common/feature_switch.h"
#include "extensions/renderer/extension_bindings_system.h"
#include "extensions/renderer/js_extension_bindings_system.h"
#include "extensions/renderer/native_extension_bindings_system.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) {
// TODO(devlin): Using the RequestSender directly here won't work with
// NativeExtensionBindingsSystem (since there is no associated RequestSender
// in that case). We should instead be going
// ExtensionBindingsSystem::HandleResponse().
ServiceWorkerData* data = g_data_tls.Pointer()->Get();
WorkerThreadDispatcher::GetRequestSender()->HandleWorkerResponse(
request_id, data->service_worker_version_id(), succeeded, *response,
error);
}
ServiceWorkerData* GetServiceWorkerData() {
ServiceWorkerData* data = g_data_tls.Pointer()->Get();
DCHECK(data);
return data;
}
// Handler for sending IPCs with native extension bindings.
void SendRequestIPC(ScriptContext* context,
const ExtensionHostMsg_Request_Params& params) {
// TODO(devlin): This won't handle incrementing/decrementing service worker
// lifetime.
WorkerThreadDispatcher::Get()->Send(
new ExtensionHostMsg_RequestWorker(params));
}
void SendEventListenersIPC(binding::EventListenersChanged changed,
ScriptContext* context,
const std::string& event_name) {
// TODO(devlin/lazyboy): Wire this up once extension workers support events.
}
} // 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);
}
// static
ExtensionBindingsSystem* WorkerThreadDispatcher::GetBindingsSystem() {
return GetServiceWorkerData()->bindings_system();
}
// static
ServiceWorkerRequestSender* WorkerThreadDispatcher::GetRequestSender() {
return static_cast<ServiceWorkerRequestSender*>(
GetBindingsSystem()->GetRequestSender());
}
// static
V8SchemaRegistry* WorkerThreadDispatcher::GetV8SchemaRegistry() {
return GetServiceWorkerData()->v8_schema_registry();
}
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,
ResourceBundleSourceMap* source_map) {
ServiceWorkerData* data = g_data_tls.Pointer()->Get();
if (!data) {
std::unique_ptr<ExtensionBindingsSystem> bindings_system;
if (FeatureSwitch::native_crx_bindings()->IsEnabled()) {
bindings_system = base::MakeUnique<NativeExtensionBindingsSystem>(
base::Bind(&SendRequestIPC), base::Bind(&SendEventListenersIPC));
} else {
bindings_system = base::MakeUnique<JsExtensionBindingsSystem>(
source_map, base::MakeUnique<ServiceWorkerRequestSender>(
this, service_worker_version_id));
}
ServiceWorkerData* new_data = new ServiceWorkerData(
service_worker_version_id, std::move(bindings_system));
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
|