ipc_message_sender.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. // Copyright 2017 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. #include "extensions/renderer/ipc_message_sender.h"
  5. #include <map>
  6. #include "base/guid.h"
  7. #include "base/memory/weak_ptr.h"
  8. #include "base/metrics/histogram_macros.h"
  9. #include "content/public/renderer/render_frame.h"
  10. #include "content/public/renderer/render_thread.h"
  11. #include "content/public/renderer/worker_thread.h"
  12. #include "extensions/common/api/messaging/messaging_endpoint.h"
  13. #include "extensions/common/constants.h"
  14. #include "extensions/common/extension_messages.h"
  15. #include "extensions/common/features/feature.h"
  16. #include "extensions/common/mojom/event_router.mojom.h"
  17. #include "extensions/common/mojom/frame.mojom.h"
  18. #include "extensions/common/trace_util.h"
  19. #include "extensions/renderer/dispatcher.h"
  20. #include "extensions/renderer/extension_frame_helper.h"
  21. #include "extensions/renderer/extensions_renderer_client.h"
  22. #include "extensions/renderer/message_target.h"
  23. #include "extensions/renderer/native_extension_bindings_system.h"
  24. #include "extensions/renderer/script_context.h"
  25. #include "extensions/renderer/trace_util.h"
  26. #include "extensions/renderer/worker_thread_dispatcher.h"
  27. #include "ipc/ipc_sync_channel.h"
  28. #include "mojo/public/cpp/bindings/associated_remote.h"
  29. #include "third_party/abseil-cpp/absl/types/optional.h"
  30. #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h"
  31. namespace extensions {
  32. namespace {
  33. class MainThreadIPCMessageSender : public IPCMessageSender {
  34. public:
  35. MainThreadIPCMessageSender() : render_thread_(content::RenderThread::Get()) {}
  36. MainThreadIPCMessageSender(const MainThreadIPCMessageSender&) = delete;
  37. MainThreadIPCMessageSender& operator=(const MainThreadIPCMessageSender&) =
  38. delete;
  39. ~MainThreadIPCMessageSender() override {}
  40. void SendRequestIPC(ScriptContext* context,
  41. mojom::RequestParamsPtr params) override {
  42. content::RenderFrame* frame = context->GetRenderFrame();
  43. if (!frame)
  44. return;
  45. int request_id = params->request_id;
  46. ExtensionFrameHelper::Get(frame)->GetLocalFrameHost()->Request(
  47. std::move(params),
  48. base::BindOnce(&MainThreadIPCMessageSender::OnResponse,
  49. weak_ptr_factory_.GetWeakPtr(), request_id));
  50. }
  51. void SendOnRequestResponseReceivedIPC(int request_id) override {}
  52. mojom::EventListenerParamPtr GetEventListenerParam(ScriptContext* context) {
  53. return !context->GetExtensionID().empty()
  54. ? mojom::EventListenerParam::NewExtensionId(
  55. context->GetExtensionID())
  56. : mojom::EventListenerParam::NewListenerUrl(context->url());
  57. }
  58. void SendAddUnfilteredEventListenerIPC(
  59. ScriptContext* context,
  60. const std::string& event_name) override {
  61. DCHECK(!context->IsForServiceWorker());
  62. DCHECK_EQ(kMainThreadId, content::WorkerThread::GetCurrentId());
  63. GetEventRouter()->AddListenerForMainThread(GetEventListenerParam(context),
  64. event_name);
  65. }
  66. void SendRemoveUnfilteredEventListenerIPC(
  67. ScriptContext* context,
  68. const std::string& event_name) override {
  69. DCHECK(!context->IsForServiceWorker());
  70. DCHECK_EQ(kMainThreadId, content::WorkerThread::GetCurrentId());
  71. GetEventRouter()->RemoveListenerForMainThread(
  72. GetEventListenerParam(context), event_name);
  73. }
  74. void SendAddUnfilteredLazyEventListenerIPC(
  75. ScriptContext* context,
  76. const std::string& event_name) override {
  77. DCHECK(!context->IsForServiceWorker());
  78. DCHECK_EQ(kMainThreadId, content::WorkerThread::GetCurrentId());
  79. GetEventRouter()->AddLazyListenerForMainThread(context->GetExtensionID(),
  80. event_name);
  81. }
  82. void SendRemoveUnfilteredLazyEventListenerIPC(
  83. ScriptContext* context,
  84. const std::string& event_name) override {
  85. DCHECK(!context->IsForServiceWorker());
  86. DCHECK_EQ(kMainThreadId, content::WorkerThread::GetCurrentId());
  87. GetEventRouter()->RemoveLazyListenerForMainThread(context->GetExtensionID(),
  88. event_name);
  89. }
  90. void SendAddFilteredEventListenerIPC(ScriptContext* context,
  91. const std::string& event_name,
  92. const base::DictionaryValue& filter,
  93. bool is_lazy) override {
  94. DCHECK(!context->IsForServiceWorker());
  95. DCHECK_EQ(kMainThreadId, content::WorkerThread::GetCurrentId());
  96. GetEventRouter()->AddFilteredListenerForMainThread(
  97. GetEventListenerParam(context), event_name, filter.Clone(), is_lazy);
  98. }
  99. void SendRemoveFilteredEventListenerIPC(ScriptContext* context,
  100. const std::string& event_name,
  101. const base::DictionaryValue& filter,
  102. bool remove_lazy_listener) override {
  103. DCHECK(!context->IsForServiceWorker());
  104. DCHECK_EQ(kMainThreadId, content::WorkerThread::GetCurrentId());
  105. GetEventRouter()->RemoveFilteredListenerForMainThread(
  106. GetEventListenerParam(context), event_name, filter.Clone(),
  107. remove_lazy_listener);
  108. }
  109. void SendOpenMessageChannel(ScriptContext* script_context,
  110. const PortId& port_id,
  111. const MessageTarget& target,
  112. const std::string& channel_name) override {
  113. content::RenderFrame* render_frame = script_context->GetRenderFrame();
  114. DCHECK(render_frame);
  115. PortContext frame_context =
  116. PortContext::ForFrame(render_frame->GetRoutingID());
  117. const Extension* extension = script_context->extension();
  118. switch (target.type) {
  119. case MessageTarget::EXTENSION: {
  120. ExtensionMsg_ExternalConnectionInfo info;
  121. if (extension && !extension->is_hosted_app()) {
  122. info.source_endpoint =
  123. script_context->context_type() == Feature::CONTENT_SCRIPT_CONTEXT
  124. ? MessagingEndpoint::ForContentScript(extension->id())
  125. : MessagingEndpoint::ForExtension(extension->id());
  126. } else {
  127. info.source_endpoint = MessagingEndpoint::ForWebPage();
  128. }
  129. info.target_id = *target.extension_id;
  130. info.source_url = script_context->url();
  131. TRACE_RENDERER_EXTENSION_EVENT(
  132. "MainThreadIPCMessageSender::SendOpenMessageChannel/extension",
  133. *target.extension_id);
  134. render_thread_->Send(new ExtensionHostMsg_OpenChannelToExtension(
  135. frame_context, info, channel_name, port_id));
  136. break;
  137. }
  138. case MessageTarget::TAB: {
  139. DCHECK(extension);
  140. DCHECK_NE(script_context->context_type(),
  141. Feature::CONTENT_SCRIPT_CONTEXT);
  142. ExtensionMsg_TabTargetConnectionInfo info;
  143. info.tab_id = *target.tab_id;
  144. info.frame_id = *target.frame_id;
  145. if (target.document_id)
  146. info.document_id = *target.document_id;
  147. render_frame->Send(new ExtensionHostMsg_OpenChannelToTab(
  148. frame_context, info, extension->id(), channel_name, port_id));
  149. break;
  150. }
  151. case MessageTarget::NATIVE_APP:
  152. render_frame->Send(new ExtensionHostMsg_OpenChannelToNativeApp(
  153. frame_context, *target.native_application_name, port_id));
  154. break;
  155. }
  156. }
  157. void SendOpenMessagePort(int routing_id, const PortId& port_id) override {
  158. render_thread_->Send(new ExtensionHostMsg_OpenMessagePort(
  159. PortContext::ForFrame(routing_id), port_id));
  160. }
  161. void SendCloseMessagePort(int routing_id,
  162. const PortId& port_id,
  163. bool close_channel) override {
  164. render_thread_->Send(new ExtensionHostMsg_CloseMessagePort(
  165. PortContext::ForFrame(routing_id), port_id, close_channel));
  166. }
  167. void SendPostMessageToPort(const PortId& port_id,
  168. const Message& message) override {
  169. render_thread_->Send(new ExtensionHostMsg_PostMessage(port_id, message));
  170. }
  171. void SendMessageResponsePending(int routing_id,
  172. const PortId& port_id) override {
  173. render_thread_->Send(new ExtensionHostMsg_ResponsePending(
  174. PortContext::ForFrame(routing_id), port_id));
  175. }
  176. void SendActivityLogIPC(
  177. const ExtensionId& extension_id,
  178. ActivityLogCallType call_type,
  179. const ExtensionHostMsg_APIActionOrEvent_Params& params) override {
  180. switch (call_type) {
  181. case ActivityLogCallType::APICALL:
  182. render_thread_->Send(new ExtensionHostMsg_AddAPIActionToActivityLog(
  183. extension_id, params));
  184. break;
  185. case ActivityLogCallType::EVENT:
  186. render_thread_->Send(
  187. new ExtensionHostMsg_AddEventToActivityLog(extension_id, params));
  188. break;
  189. }
  190. }
  191. private:
  192. void OnResponse(int request_id,
  193. bool success,
  194. base::Value::List response,
  195. const std::string& error) {
  196. ExtensionsRendererClient::Get()
  197. ->GetDispatcher()
  198. ->bindings_system()
  199. ->HandleResponse(request_id, success, std::move(response), error);
  200. }
  201. mojom::EventRouter* GetEventRouter() {
  202. if (!event_router_remote_.is_bound()) {
  203. render_thread_->GetChannel()->GetRemoteAssociatedInterface(
  204. &event_router_remote_);
  205. }
  206. return event_router_remote_.get();
  207. }
  208. content::RenderThread* const render_thread_;
  209. mojo::AssociatedRemote<mojom::EventRouter> event_router_remote_;
  210. base::WeakPtrFactory<MainThreadIPCMessageSender> weak_ptr_factory_{this};
  211. };
  212. class WorkerThreadIPCMessageSender : public IPCMessageSender {
  213. public:
  214. WorkerThreadIPCMessageSender(WorkerThreadDispatcher* dispatcher,
  215. int64_t service_worker_version_id)
  216. : dispatcher_(dispatcher),
  217. service_worker_version_id_(service_worker_version_id) {}
  218. WorkerThreadIPCMessageSender(const WorkerThreadIPCMessageSender&) = delete;
  219. WorkerThreadIPCMessageSender& operator=(const WorkerThreadIPCMessageSender&) =
  220. delete;
  221. ~WorkerThreadIPCMessageSender() override {}
  222. void SendRequestIPC(ScriptContext* context,
  223. mojom::RequestParamsPtr params) override {
  224. DCHECK(!context->GetRenderFrame());
  225. DCHECK(context->IsForServiceWorker());
  226. DCHECK_NE(kMainThreadId, content::WorkerThread::GetCurrentId());
  227. int worker_thread_id = content::WorkerThread::GetCurrentId();
  228. params->worker_thread_id = worker_thread_id;
  229. params->service_worker_version_id = service_worker_version_id_;
  230. std::string guid = base::GenerateGUID();
  231. request_id_to_guid_[params->request_id] = guid;
  232. // Keeps the worker alive during extension function call. Balanced in
  233. // HandleWorkerResponse().
  234. dispatcher_->Send(new ExtensionHostMsg_IncrementServiceWorkerActivity(
  235. service_worker_version_id_, guid));
  236. dispatcher_->Send(new ExtensionHostMsg_RequestWorker(*params));
  237. }
  238. void SendOnRequestResponseReceivedIPC(int request_id) override {
  239. auto iter = request_id_to_guid_.find(request_id);
  240. DCHECK(iter != request_id_to_guid_.end());
  241. dispatcher_->Send(new ExtensionHostMsg_DecrementServiceWorkerActivity(
  242. service_worker_version_id_, iter->second));
  243. request_id_to_guid_.erase(iter);
  244. }
  245. void SendAddUnfilteredEventListenerIPC(
  246. ScriptContext* context,
  247. const std::string& event_name) override {
  248. DCHECK(context->IsForServiceWorker());
  249. DCHECK_NE(kMainThreadId, content::WorkerThread::GetCurrentId());
  250. DCHECK_NE(blink::mojom::kInvalidServiceWorkerVersionId,
  251. context->service_worker_version_id());
  252. dispatcher_->SendAddEventListener(
  253. context->GetExtensionID(), context->service_worker_scope(), event_name,
  254. context->service_worker_version_id(),
  255. content::WorkerThread::GetCurrentId());
  256. }
  257. void SendRemoveUnfilteredEventListenerIPC(
  258. ScriptContext* context,
  259. const std::string& event_name) override {
  260. DCHECK(context->IsForServiceWorker());
  261. DCHECK_NE(kMainThreadId, content::WorkerThread::GetCurrentId());
  262. DCHECK_NE(blink::mojom::kInvalidServiceWorkerVersionId,
  263. context->service_worker_version_id());
  264. dispatcher_->SendRemoveEventListener(
  265. context->GetExtensionID(), context->service_worker_scope(), event_name,
  266. context->service_worker_version_id(),
  267. content::WorkerThread::GetCurrentId());
  268. }
  269. void SendAddUnfilteredLazyEventListenerIPC(
  270. ScriptContext* context,
  271. const std::string& event_name) override {
  272. DCHECK(context->IsForServiceWorker());
  273. DCHECK_NE(kMainThreadId, content::WorkerThread::GetCurrentId());
  274. dispatcher_->SendAddEventLazyListener(
  275. context->GetExtensionID(), context->service_worker_scope(), event_name);
  276. }
  277. void SendRemoveUnfilteredLazyEventListenerIPC(
  278. ScriptContext* context,
  279. const std::string& event_name) override {
  280. DCHECK(context->IsForServiceWorker());
  281. DCHECK_NE(kMainThreadId, content::WorkerThread::GetCurrentId());
  282. dispatcher_->SendRemoveEventLazyListener(
  283. context->GetExtensionID(), context->service_worker_scope(), event_name);
  284. }
  285. void SendAddFilteredEventListenerIPC(ScriptContext* context,
  286. const std::string& event_name,
  287. const base::DictionaryValue& filter,
  288. bool is_lazy) override {
  289. DCHECK(context->IsForServiceWorker());
  290. DCHECK_NE(kMainThreadId, content::WorkerThread::GetCurrentId());
  291. DCHECK_NE(blink::mojom::kInvalidServiceWorkerVersionId,
  292. context->service_worker_version_id());
  293. dispatcher_->SendAddEventFilteredListener(
  294. context->GetExtensionID(), context->service_worker_scope(), event_name,
  295. context->service_worker_version_id(),
  296. content::WorkerThread::GetCurrentId(), filter.Clone(), is_lazy);
  297. }
  298. void SendRemoveFilteredEventListenerIPC(ScriptContext* context,
  299. const std::string& event_name,
  300. const base::DictionaryValue& filter,
  301. bool remove_lazy_listener) override {
  302. DCHECK(context->IsForServiceWorker());
  303. DCHECK_NE(kMainThreadId, content::WorkerThread::GetCurrentId());
  304. DCHECK_NE(blink::mojom::kInvalidServiceWorkerVersionId,
  305. context->service_worker_version_id());
  306. dispatcher_->SendRemoveEventFilteredListener(
  307. context->GetExtensionID(), context->service_worker_scope(), event_name,
  308. context->service_worker_version_id(),
  309. content::WorkerThread::GetCurrentId(), filter.Clone(),
  310. remove_lazy_listener);
  311. }
  312. void SendOpenMessageChannel(ScriptContext* script_context,
  313. const PortId& port_id,
  314. const MessageTarget& target,
  315. const std::string& channel_name) override {
  316. DCHECK(!script_context->GetRenderFrame());
  317. DCHECK(script_context->IsForServiceWorker());
  318. const Extension* extension = script_context->extension();
  319. switch (target.type) {
  320. case MessageTarget::EXTENSION: {
  321. ExtensionMsg_ExternalConnectionInfo info;
  322. if (extension && !extension->is_hosted_app()) {
  323. info.source_endpoint =
  324. MessagingEndpoint::ForExtension(extension->id());
  325. }
  326. info.target_id = *target.extension_id;
  327. info.source_url = script_context->url();
  328. TRACE_RENDERER_EXTENSION_EVENT(
  329. "WorkerThreadIPCMessageSender::SendOpenMessageChannel/extension",
  330. *target.extension_id);
  331. dispatcher_->Send(new ExtensionHostMsg_OpenChannelToExtension(
  332. PortContextForCurrentWorker(), info, channel_name, port_id));
  333. break;
  334. }
  335. case MessageTarget::TAB: {
  336. DCHECK(extension);
  337. ExtensionMsg_TabTargetConnectionInfo info;
  338. info.tab_id = *target.tab_id;
  339. info.frame_id = *target.frame_id;
  340. dispatcher_->Send(new ExtensionHostMsg_OpenChannelToTab(
  341. PortContextForCurrentWorker(), info, extension->id(), channel_name,
  342. port_id));
  343. break;
  344. }
  345. case MessageTarget::NATIVE_APP:
  346. dispatcher_->Send(new ExtensionHostMsg_OpenChannelToNativeApp(
  347. PortContextForCurrentWorker(), *target.native_application_name,
  348. port_id));
  349. break;
  350. }
  351. }
  352. void SendOpenMessagePort(int routing_id, const PortId& port_id) override {
  353. DCHECK_EQ(MSG_ROUTING_NONE, routing_id);
  354. dispatcher_->Send(new ExtensionHostMsg_OpenMessagePort(
  355. PortContextForCurrentWorker(), port_id));
  356. }
  357. void SendCloseMessagePort(int routing_id,
  358. const PortId& port_id,
  359. bool close_channel) override {
  360. DCHECK_EQ(MSG_ROUTING_NONE, routing_id);
  361. dispatcher_->Send(new ExtensionHostMsg_CloseMessagePort(
  362. PortContextForCurrentWorker(), port_id, close_channel));
  363. }
  364. void SendPostMessageToPort(const PortId& port_id,
  365. const Message& message) override {
  366. dispatcher_->Send(new ExtensionHostMsg_PostMessage(port_id, message));
  367. }
  368. void SendMessageResponsePending(int routing_id,
  369. const PortId& port_id) override {
  370. DCHECK_EQ(MSG_ROUTING_NONE, routing_id);
  371. dispatcher_->Send(new ExtensionHostMsg_ResponsePending(
  372. PortContextForCurrentWorker(), port_id));
  373. }
  374. void SendActivityLogIPC(
  375. const ExtensionId& extension_id,
  376. ActivityLogCallType call_type,
  377. const ExtensionHostMsg_APIActionOrEvent_Params& params) override {
  378. switch (call_type) {
  379. case ActivityLogCallType::APICALL:
  380. dispatcher_->Send(new ExtensionHostMsg_AddAPIActionToActivityLog(
  381. extension_id, params));
  382. break;
  383. case ActivityLogCallType::EVENT:
  384. dispatcher_->Send(
  385. new ExtensionHostMsg_AddEventToActivityLog(extension_id, params));
  386. break;
  387. }
  388. }
  389. private:
  390. const ExtensionId& GetExtensionId() {
  391. if (!extension_id_)
  392. extension_id_ = dispatcher_->GetScriptContext()->extension()->id();
  393. return *extension_id_;
  394. }
  395. PortContext PortContextForCurrentWorker() {
  396. return PortContext::ForWorker(content::WorkerThread::GetCurrentId(),
  397. service_worker_version_id_, GetExtensionId());
  398. }
  399. WorkerThreadDispatcher* const dispatcher_;
  400. const int64_t service_worker_version_id_;
  401. absl::optional<ExtensionId> extension_id_;
  402. // request id -> GUID map for each outstanding requests.
  403. std::map<int, std::string> request_id_to_guid_;
  404. };
  405. } // namespace
  406. IPCMessageSender::IPCMessageSender() {}
  407. IPCMessageSender::~IPCMessageSender() = default;
  408. // static
  409. std::unique_ptr<IPCMessageSender>
  410. IPCMessageSender::CreateMainThreadIPCMessageSender() {
  411. return std::make_unique<MainThreadIPCMessageSender>();
  412. }
  413. // static
  414. std::unique_ptr<IPCMessageSender>
  415. IPCMessageSender::CreateWorkerThreadIPCMessageSender(
  416. WorkerThreadDispatcher* dispatcher,
  417. int64_t service_worker_version_id) {
  418. return std::make_unique<WorkerThreadIPCMessageSender>(
  419. dispatcher, service_worker_version_id);
  420. }
  421. } // namespace extensions