blob: 7ebb2c43b6153fd488866ae15b24bf896cb8a728 [file] [log] [blame]
[email protected]eccf80312012-07-14 15:43:421// Copyright (c) 2012 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 "ppapi/proxy/plugin_resource.h"
6
[email protected]d84e9992012-11-08 22:13:287#include <limits>
8
[email protected]511c58e2013-12-12 12:25:339#include "ppapi/proxy/plugin_globals.h"
[email protected]eccf80312012-07-14 15:43:4210#include "ppapi/proxy/ppapi_messages.h"
[email protected]511c58e2013-12-12 12:25:3311#include "ppapi/shared_impl/ppapi_globals.h"
[email protected]eccf80312012-07-14 15:43:4212
13namespace ppapi {
14namespace proxy {
15
Daniel Bratelleb5dcde2018-10-25 08:39:5016void SafeRunCallback(scoped_refptr<TrackedCallback>* callback, int32_t error) {
17 if (TrackedCallback::IsPending(*callback)) {
18 scoped_refptr<TrackedCallback> temp;
19 callback->swap(temp);
20 temp->Run(error);
21 }
22}
23
[email protected]93df81e2012-08-10 22:22:4624PluginResource::PluginResource(Connection connection, PP_Instance instance)
[email protected]eccf80312012-07-14 15:43:4225 : Resource(OBJECT_IS_PROXY, instance),
[email protected]93df81e2012-08-10 22:22:4626 connection_(connection),
[email protected]d84e9992012-11-08 22:13:2827 next_sequence_number_(1),
[email protected]93df81e2012-08-10 22:22:4628 sent_create_to_browser_(false),
[email protected]511c58e2013-12-12 12:25:3329 sent_create_to_renderer_(false),
30 resource_reply_thread_registrar_(
31 PpapiGlobals::Get()->IsPluginGlobals() ?
32 PluginGlobals::Get()->resource_reply_thread_registrar() : NULL) {
[email protected]eccf80312012-07-14 15:43:4233}
34
35PluginResource::~PluginResource() {
[email protected]93df81e2012-08-10 22:22:4636 if (sent_create_to_browser_) {
Raymes Khoury982b7eb22017-07-26 09:40:2437 connection_.browser_sender()->Send(
[email protected]93df81e2012-08-10 22:22:4638 new PpapiHostMsg_ResourceDestroyed(pp_resource()));
39 }
40 if (sent_create_to_renderer_) {
Raymes Khoury982b7eb22017-07-26 09:40:2441 connection_.GetRendererSender()->Send(
[email protected]93df81e2012-08-10 22:22:4642 new PpapiHostMsg_ResourceDestroyed(pp_resource()));
43 }
[email protected]511c58e2013-12-12 12:25:3344
Daniel Cheng6d3ae972014-08-26 00:27:3845 if (resource_reply_thread_registrar_.get())
[email protected]511c58e2013-12-12 12:25:3346 resource_reply_thread_registrar_->Unregister(pp_resource());
[email protected]eccf80312012-07-14 15:43:4247}
48
[email protected]e1f5c9b2012-10-04 00:07:4449void PluginResource::OnReplyReceived(
50 const proxy::ResourceMessageReplyParams& params,
51 const IPC::Message& msg) {
Sami Kyostila0f5c1549e2021-02-08 20:17:5252 TRACE_EVENT2("ppapi_proxy", "PluginResource::OnReplyReceived", "Class",
53 IPC_MESSAGE_ID_CLASS(msg.type()), "Line",
54 IPC_MESSAGE_ID_LINE(msg.type()));
[email protected]e1f5c9b2012-10-04 00:07:4455 // Grab the callback for the reply sequence number and run it with |msg|.
56 CallbackMap::iterator it = callbacks_.find(params.sequence());
57 if (it == callbacks_.end()) {
58 DCHECK(false) << "Callback does not exist for an expected sequence number.";
59 } else {
Anand K Mistry9182c2a72021-03-17 04:40:0860 std::unique_ptr<PluginResourceCallbackBase> callback =
61 std::move(it->second);
[email protected]e1f5c9b2012-10-04 00:07:4462 callbacks_.erase(it);
63 callback->Run(params, msg);
64 }
65}
66
[email protected]28df6a02012-11-08 07:29:4567void PluginResource::NotifyLastPluginRefWasDeleted() {
68 Resource::NotifyLastPluginRefWasDeleted();
69
70 // The callbacks may hold referrences to this object. Normally, we will get
71 // reply messages from the host side and remove them. However, it is possible
72 // that some replies from the host never arrive, e.g., the corresponding
73 // renderer crashes. In that case, we have to clean up the callbacks,
74 // otherwise this object will live forever.
75 callbacks_.clear();
76}
77
78void PluginResource::NotifyInstanceWasDeleted() {
79 Resource::NotifyInstanceWasDeleted();
80
81 // Please see comments in NotifyLastPluginRefWasDeleted() about why we must
82 // clean up the callbacks.
83 // It is possible that NotifyLastPluginRefWasDeleted() is never called for a
84 // resource. For example, those singleton-style resources such as
85 // GamepadResource never expose references to the plugin and thus won't
86 // receive a NotifyLastPluginRefWasDeleted() call. For those resources, we
87 // need to clean up callbacks when the instance goes away.
88 callbacks_.clear();
89}
90
[email protected]9164da32012-10-16 03:40:5791void PluginResource::SendCreate(Destination dest, const IPC::Message& msg) {
Sami Kyostila0f5c1549e2021-02-08 20:17:5292 TRACE_EVENT2("ppapi_proxy", "PluginResource::SendCreate", "Class",
93 IPC_MESSAGE_ID_CLASS(msg.type()), "Line",
94 IPC_MESSAGE_ID_LINE(msg.type()));
[email protected]9164da32012-10-16 03:40:5795 if (dest == RENDERER) {
96 DCHECK(!sent_create_to_renderer_);
97 sent_create_to_renderer_ = true;
98 } else {
99 DCHECK(!sent_create_to_browser_);
100 sent_create_to_browser_ = true;
101 }
[email protected]d84e9992012-11-08 22:13:28102 ResourceMessageCallParams params(pp_resource(), GetNextSequence());
[email protected]9164da32012-10-16 03:40:57103 GetSender(dest)->Send(
[email protected]93df81e2012-08-10 22:22:46104 new PpapiHostMsg_ResourceCreated(params, pp_instance(), msg));
[email protected]eccf80312012-07-14 15:43:42105}
106
[email protected]db70c132012-12-05 00:41:20107void PluginResource::AttachToPendingHost(Destination dest,
108 int pending_host_id) {
109 // Connecting to a pending host is a replacement for "create".
110 if (dest == RENDERER) {
111 DCHECK(!sent_create_to_renderer_);
112 sent_create_to_renderer_ = true;
113 } else {
114 DCHECK(!sent_create_to_browser_);
115 sent_create_to_browser_ = true;
116 }
117 GetSender(dest)->Send(
118 new PpapiHostMsg_AttachToPendingHost(pp_resource(), pending_host_id));
119}
120
[email protected]9164da32012-10-16 03:40:57121void PluginResource::Post(Destination dest, const IPC::Message& msg) {
Sami Kyostila0f5c1549e2021-02-08 20:17:52122 TRACE_EVENT2("ppapi_proxy", "PluginResource::Post", "Class",
123 IPC_MESSAGE_ID_CLASS(msg.type()), "Line",
124 IPC_MESSAGE_ID_LINE(msg.type()));
[email protected]d84e9992012-11-08 22:13:28125 ResourceMessageCallParams params(pp_resource(), GetNextSequence());
[email protected]9164da32012-10-16 03:40:57126 SendResourceCall(dest, params, msg);
[email protected]93df81e2012-08-10 22:22:46127}
128
[email protected]e1f5c9b2012-10-04 00:07:44129bool PluginResource::SendResourceCall(
[email protected]9164da32012-10-16 03:40:57130 Destination dest,
[email protected]e1f5c9b2012-10-04 00:07:44131 const ResourceMessageCallParams& call_params,
132 const IPC::Message& nested_msg) {
[email protected]0d586af2013-07-31 21:58:06133 // For in-process plugins, we need to send the routing ID with the request.
134 // The browser then uses that routing ID when sending the reply so it will be
[email protected]fb44cb0a2013-12-04 00:45:55135 // routed back to the correct RenderFrameImpl.
Raymes Khoury982b7eb22017-07-26 09:40:24136 if (dest == BROWSER && connection_.in_process()) {
[email protected]0d586af2013-07-31 21:58:06137 return GetSender(dest)->Send(new PpapiHostMsg_InProcessResourceCall(
Raymes Khoury982b7eb22017-07-26 09:40:24138 connection_.browser_sender_routing_id(), call_params, nested_msg));
[email protected]0d586af2013-07-31 21:58:06139 } else {
140 return GetSender(dest)->Send(
141 new PpapiHostMsg_ResourceCall(call_params, nested_msg));
142 }
[email protected]eccf80312012-07-14 15:43:42143}
144
[email protected]0c92b0d2012-12-08 00:46:23145int32_t PluginResource::GenericSyncCall(
146 Destination dest,
147 const IPC::Message& msg,
148 IPC::Message* reply,
149 ResourceMessageReplyParams* reply_params) {
Sami Kyostila0f5c1549e2021-02-08 20:17:52150 TRACE_EVENT2("ppapi_proxy", "PluginResource::GenericSyncCall", "Class",
151 IPC_MESSAGE_ID_CLASS(msg.type()), "Line",
152 IPC_MESSAGE_ID_LINE(msg.type()));
[email protected]d84e9992012-11-08 22:13:28153 ResourceMessageCallParams params(pp_resource(), GetNextSequence());
[email protected]ff44fc12012-10-03 00:52:16154 params.set_has_callback();
[email protected]58786932012-10-13 10:16:08155 bool success = GetSender(dest)->Send(new PpapiHostMsg_ResourceSyncCall(
[email protected]0c92b0d2012-12-08 00:46:23156 params, msg, reply_params, reply));
[email protected]ff44fc12012-10-03 00:52:16157 if (success)
[email protected]0c92b0d2012-12-08 00:46:23158 return reply_params->result();
[email protected]ff44fc12012-10-03 00:52:16159 return PP_ERROR_FAILED;
160}
161
[email protected]d84e9992012-11-08 22:13:28162int32_t PluginResource::GetNextSequence() {
163 // Return the value with wraparound, making sure we don't make a sequence
164 // number with a 0 ID. Note that signed wraparound is undefined in C++ so we
165 // manually check.
166 int32_t ret = next_sequence_number_;
167 if (next_sequence_number_ == std::numeric_limits<int32_t>::max())
168 next_sequence_number_ = 1; // Skip 0 which is invalid.
169 else
170 next_sequence_number_++;
171 return ret;
172}
173
[email protected]eccf80312012-07-14 15:43:42174} // namespace proxy
175} // namespace ppapi