blob: 8da4ad333e9fa93ef223f0c2c083b476166fe91f [file] [log] [blame]
lazyboyee4adef2016-05-24 00:55:161// Copyright 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "extensions/renderer/worker_thread_dispatcher.h"
6
fdorayba121422016-12-23 19:51:487#include "base/memory/ptr_util.h"
lazyboy8874f2d2017-05-08 15:07:088#include "base/threading/platform_thread.h"
lazyboyee4adef2016-05-24 00:55:169#include "base/threading/thread_local.h"
10#include "base/values.h"
11#include "content/public/child/worker_thread.h"
12#include "content/public/renderer/render_thread.h"
lazyboye7847242017-06-07 23:29:1813#include "extensions/common/constants.h"
lazyboyee4adef2016-05-24 00:55:1614#include "extensions/common/extension_messages.h"
rdevlin.cronin71d78789e2016-11-22 19:49:2715#include "extensions/common/feature_switch.h"
lazyboye7847242017-06-07 23:29:1816#include "extensions/renderer/dispatcher.h"
rdevlin.cronin9f338892016-11-21 19:37:0017#include "extensions/renderer/extension_bindings_system.h"
Devlin Cronin4607e322017-07-17 16:17:1818#include "extensions/renderer/ipc_message_sender.h"
rdevlin.cronin9f338892016-11-21 19:37:0019#include "extensions/renderer/js_extension_bindings_system.h"
rdevlin.cronin71d78789e2016-11-22 19:49:2720#include "extensions/renderer/native_extension_bindings_system.h"
lazyboyee4adef2016-05-24 00:55:1621#include "extensions/renderer/service_worker_data.h"
22
23namespace extensions {
24
25namespace {
26
scottmg5e65e3a2017-03-08 08:48:4627base::LazyInstance<WorkerThreadDispatcher>::DestructorAtExit g_instance =
lazyboyee4adef2016-05-24 00:55:1628 LAZY_INSTANCE_INITIALIZER;
scottmg5e65e3a2017-03-08 08:48:4629base::LazyInstance<base::ThreadLocalPointer<extensions::ServiceWorkerData>>::
30 DestructorAtExit g_data_tls = LAZY_INSTANCE_INITIALIZER;
lazyboyee4adef2016-05-24 00:55:1631
rdevlin.cronin9f338892016-11-21 19:37:0032ServiceWorkerData* GetServiceWorkerData() {
33 ServiceWorkerData* data = g_data_tls.Pointer()->Get();
34 DCHECK(data);
35 return data;
36}
37
rdevlin.croninea496fd2017-01-13 18:22:1438void SendEventListenersIPC(binding::EventListenersChanged changed,
39 ScriptContext* context,
rdevlin.croninddc50bcb2017-03-23 00:55:5240 const std::string& event_name,
rdevlin.cronin707b7322017-03-30 20:56:2641 const base::DictionaryValue* filter,
42 bool was_manual) {
rdevlin.croninea496fd2017-01-13 18:22:1443 // TODO(devlin/lazyboy): Wire this up once extension workers support events.
44}
45
lazyboyee4adef2016-05-24 00:55:1646} // namespace
47
48WorkerThreadDispatcher::WorkerThreadDispatcher() {}
49WorkerThreadDispatcher::~WorkerThreadDispatcher() {}
50
51WorkerThreadDispatcher* WorkerThreadDispatcher::Get() {
52 return g_instance.Pointer();
53}
54
55void WorkerThreadDispatcher::Init(content::RenderThread* render_thread) {
56 DCHECK(render_thread);
57 DCHECK_EQ(content::RenderThread::Get(), render_thread);
58 DCHECK(!message_filter_);
59 message_filter_ = render_thread->GetSyncMessageFilter();
60 render_thread->AddObserver(this);
61}
62
rdevlin.cronin9f338892016-11-21 19:37:0063// static
64ExtensionBindingsSystem* WorkerThreadDispatcher::GetBindingsSystem() {
65 return GetServiceWorkerData()->bindings_system();
lazyboyee4adef2016-05-24 00:55:1666}
67
68// static
rdevlin.cronin9f338892016-11-21 19:37:0069V8SchemaRegistry* WorkerThreadDispatcher::GetV8SchemaRegistry() {
70 return GetServiceWorkerData()->v8_schema_registry();
lazyboyee4adef2016-05-24 00:55:1671}
72
lazyboy8874f2d2017-05-08 15:07:0873// static
74bool WorkerThreadDispatcher::HandlesMessageOnWorkerThread(
75 const IPC::Message& message) {
lazyboye7847242017-06-07 23:29:1876 return message.type() == ExtensionMsg_ResponseWorker::ID ||
77 message.type() == ExtensionMsg_DispatchEvent::ID;
lazyboy8874f2d2017-05-08 15:07:0878}
79
80// static
81void WorkerThreadDispatcher::ForwardIPC(int worker_thread_id,
82 const IPC::Message& message) {
83 WorkerThreadDispatcher::Get()->OnMessageReceivedOnWorkerThread(
84 worker_thread_id, message);
85}
86
lazyboyee4adef2016-05-24 00:55:1687bool WorkerThreadDispatcher::OnControlMessageReceived(
88 const IPC::Message& message) {
lazyboy8874f2d2017-05-08 15:07:0889 if (HandlesMessageOnWorkerThread(message)) {
90 int worker_thread_id = base::kInvalidThreadId;
lazyboye7847242017-06-07 23:29:1891 // TODO(lazyboy): Route |message| directly to the child thread using routed
92 // IPC. Probably using mojo?
lazyboy8874f2d2017-05-08 15:07:0893 bool found = base::PickleIterator(message).ReadInt(&worker_thread_id);
lazyboye7847242017-06-07 23:29:1894 CHECK(found);
95 if (worker_thread_id == kNonWorkerThreadId)
96 return false;
lazyboy8874f2d2017-05-08 15:07:0897 base::TaskRunner* runner = GetTaskRunnerFor(worker_thread_id);
98 bool task_posted = runner->PostTask(
99 FROM_HERE, base::Bind(&WorkerThreadDispatcher::ForwardIPC,
100 worker_thread_id, message));
101 DCHECK(task_posted) << "Could not PostTask IPC to worker thread.";
102 return true;
103 }
104 return false;
105}
106
107void WorkerThreadDispatcher::OnMessageReceivedOnWorkerThread(
108 int worker_thread_id,
109 const IPC::Message& message) {
110 CHECK_EQ(content::WorkerThread::GetCurrentId(), worker_thread_id);
lazyboyee4adef2016-05-24 00:55:16111 bool handled = true;
112 IPC_BEGIN_MESSAGE_MAP(WorkerThreadDispatcher, message)
113 IPC_MESSAGE_HANDLER(ExtensionMsg_ResponseWorker, OnResponseWorker)
lazyboye7847242017-06-07 23:29:18114 IPC_MESSAGE_HANDLER(ExtensionMsg_DispatchEvent, OnDispatchEvent)
lazyboyee4adef2016-05-24 00:55:16115 IPC_MESSAGE_UNHANDLED(handled = false)
116 IPC_END_MESSAGE_MAP()
lazyboy8874f2d2017-05-08 15:07:08117 CHECK(handled);
118}
119
120base::TaskRunner* WorkerThreadDispatcher::GetTaskRunnerFor(
121 int worker_thread_id) {
122 base::AutoLock lock(task_runner_map_lock_);
123 return task_runner_map_[worker_thread_id];
lazyboyee4adef2016-05-24 00:55:16124}
125
126bool WorkerThreadDispatcher::Send(IPC::Message* message) {
127 return message_filter_->Send(message);
128}
129
130void WorkerThreadDispatcher::OnResponseWorker(int worker_thread_id,
131 int request_id,
132 bool succeeded,
133 const base::ListValue& response,
134 const std::string& error) {
lazyboy8874f2d2017-05-08 15:07:08135 ServiceWorkerData* data = g_data_tls.Pointer()->Get();
Devlin Cronin4607e322017-07-17 16:17:18136 data->bindings_system()->HandleResponse(request_id, succeeded, response,
137 error);
138 data->ipc_message_sender()->SendOnRequestResponseReceivedIPC(request_id);
lazyboyee4adef2016-05-24 00:55:16139}
140
lazyboye7847242017-06-07 23:29:18141void WorkerThreadDispatcher::OnDispatchEvent(
142 const ExtensionMsg_DispatchEvent_Params& params,
143 const base::ListValue& event_args) {
144 ServiceWorkerData* data = g_data_tls.Pointer()->Get();
145 DCHECK(data);
146 data->bindings_system()->DispatchEventInContext(
147 params.event_name, &event_args, &params.filtering_info, data->context());
148}
149
rdevlin.cronin9f338892016-11-21 19:37:00150void WorkerThreadDispatcher::AddWorkerData(
151 int64_t service_worker_version_id,
lazyboye7847242017-06-07 23:29:18152 ScriptContext* context,
rdevlin.cronin9f338892016-11-21 19:37:00153 ResourceBundleSourceMap* source_map) {
lazyboyee4adef2016-05-24 00:55:16154 ServiceWorkerData* data = g_data_tls.Pointer()->Get();
155 if (!data) {
rdevlin.cronin71d78789e2016-11-22 19:49:27156 std::unique_ptr<ExtensionBindingsSystem> bindings_system;
Devlin Cronin4607e322017-07-17 16:17:18157 // QUESTION(lazyboy): Why is passing the WorkerThreadDispatcher to the
158 // IPCMessageSender (previously the ServiceWorkerRequestSender) safe? The
159 // WorkerThreadDispatcher is a process-wide singleton, but the
160 // IPCMessageSender is per-context (thus potentially many per process).
161 std::unique_ptr<IPCMessageSender> ipc_message_sender =
162 IPCMessageSender::CreateWorkerThreadIPCMessageSender(
163 this, service_worker_version_id);
rdevlin.cronin71d78789e2016-11-22 19:49:27164 if (FeatureSwitch::native_crx_bindings()->IsEnabled()) {
Devlin Cronin4607e322017-07-17 16:17:18165 // The Unretained below is safe since the IPC message sender outlives the
166 // bindings system.
rdevlin.cronin71d78789e2016-11-22 19:49:27167 bindings_system = base::MakeUnique<NativeExtensionBindingsSystem>(
Devlin Cronin4607e322017-07-17 16:17:18168 base::Bind(&IPCMessageSender::SendRequestIPC,
169 base::Unretained(ipc_message_sender.get())),
170 base::Bind(&SendEventListenersIPC));
rdevlin.cronin71d78789e2016-11-22 19:49:27171 } else {
172 bindings_system = base::MakeUnique<JsExtensionBindingsSystem>(
Devlin Cronin4607e322017-07-17 16:17:18173 source_map,
174 base::MakeUnique<RequestSender>(ipc_message_sender.get()));
rdevlin.cronin71d78789e2016-11-22 19:49:27175 }
rdevlin.cronin9f338892016-11-21 19:37:00176 ServiceWorkerData* new_data = new ServiceWorkerData(
Devlin Cronin4607e322017-07-17 16:17:18177 service_worker_version_id, context, std::move(bindings_system),
178 std::move(ipc_message_sender));
lazyboyee4adef2016-05-24 00:55:16179 g_data_tls.Pointer()->Set(new_data);
180 }
lazyboy8874f2d2017-05-08 15:07:08181
182 int worker_thread_id = base::PlatformThread::CurrentId();
183 DCHECK_EQ(content::WorkerThread::GetCurrentId(), worker_thread_id);
184 {
185 base::AutoLock lock(task_runner_map_lock_);
186 auto* task_runner = base::ThreadTaskRunnerHandle::Get().get();
187 CHECK(task_runner);
188 task_runner_map_[worker_thread_id] = task_runner;
189 }
lazyboyee4adef2016-05-24 00:55:16190}
191
lazyboy4c82177a2016-10-18 00:04:09192void WorkerThreadDispatcher::RemoveWorkerData(
193 int64_t service_worker_version_id) {
lazyboyee4adef2016-05-24 00:55:16194 ServiceWorkerData* data = g_data_tls.Pointer()->Get();
195 if (data) {
lazyboy4c82177a2016-10-18 00:04:09196 DCHECK_EQ(service_worker_version_id, data->service_worker_version_id());
lazyboyee4adef2016-05-24 00:55:16197 delete data;
198 g_data_tls.Pointer()->Set(nullptr);
199 }
lazyboy8874f2d2017-05-08 15:07:08200
201 int worker_thread_id = base::PlatformThread::CurrentId();
202 DCHECK_EQ(content::WorkerThread::GetCurrentId(), worker_thread_id);
203 {
204 base::AutoLock lock(task_runner_map_lock_);
205 task_runner_map_.erase(worker_thread_id);
206 }
lazyboyee4adef2016-05-24 00:55:16207}
208
209} // namespace extensions