Elim cr-checkbox
[chromium-blink-merge.git] / ppapi / proxy / enter_proxy.h
blob4ad67b136c39dff211f25f152d24170b2be8bb86
1 // 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.
5 #ifndef PPAPI_PROXY_ENTER_PROXY_H_
6 #define PPAPI_PROXY_ENTER_PROXY_H_
8 #include "base/logging.h"
9 #include "ppapi/cpp/completion_callback.h"
10 #include "ppapi/proxy/host_dispatcher.h"
11 #include "ppapi/proxy/plugin_dispatcher.h"
12 #include "ppapi/proxy/plugin_globals.h"
13 #include "ppapi/proxy/plugin_resource_tracker.h"
14 #include "ppapi/thunk/enter.h"
16 namespace ppapi {
18 namespace proxy {
20 // Wrapper around EnterResourceNoLock that takes a host resource. This is used
21 // when handling messages in the plugin from the host and we need to convert to
22 // an object in the plugin side corresponding to that.
24 // This never locks since we assume the host Resource is coming from IPC, and
25 // never logs errors since we assume the host is doing reasonable things.
26 template<typename ResourceT>
27 class EnterPluginFromHostResource
28 : public thunk::EnterResourceNoLock<ResourceT> {
29 public:
30 explicit EnterPluginFromHostResource(const HostResource& host_resource)
31 : thunk::EnterResourceNoLock<ResourceT>(
32 PluginGlobals::Get()->plugin_resource_tracker()->
33 PluginResourceForHostResource(host_resource),
34 false) {
35 // Validate that we're in the plugin rather than the host. Otherwise this
36 // object will do the wrong thing. In the plugin, the instance should have
37 // a corresponding plugin dispatcher (assuming the resource is valid).
38 DCHECK(this->failed() ||
39 PluginDispatcher::GetForInstance(host_resource.instance()));
43 template<typename ResourceT>
44 class EnterHostFromHostResource
45 : public thunk::EnterResourceNoLock<ResourceT> {
46 public:
47 explicit EnterHostFromHostResource(const HostResource& host_resource)
48 : thunk::EnterResourceNoLock<ResourceT>(host_resource.host_resource(),
49 false) {
50 // Validate that we're in the host rather than the plugin. Otherwise this
51 // object will do the wrong thing. In the host, the instance should have
52 // a corresponding host disptacher (assuming the resource is valid).
53 DCHECK(this->failed() ||
54 HostDispatcher::GetForInstance(host_resource.instance()));
57 EnterHostFromHostResource(const HostResource& host_resource,
58 const pp::CompletionCallback& callback)
59 : thunk::EnterResourceNoLock<ResourceT>(host_resource.host_resource(),
60 callback.pp_completion_callback(),
61 false) {
62 // Validate that we're in the host rather than the plugin. Otherwise this
63 // object will do the wrong thing. In the host, the instance should have
64 // a corresponding host disptacher (assuming the resource is valid).
65 DCHECK(this->failed() ||
66 HostDispatcher::GetForInstance(host_resource.instance()));
70 // Enters a resource and forces a completion callback to be issued.
72 // This is used when implementing the host (renderer) side of a resource
73 // function that issues a completion callback. In all cases, we need to issue
74 // the callback to avoid hanging the plugin.
76 // This class automatically constructs a callback with the given factory
77 // calling the given method. The method will generally be the one that sends
78 // the message to trigger the completion callback in the plugin process.
80 // It will automatically issue the callback with PP_ERROR_NOINTERFACE if the
81 // host resource is invalid (i.e. failed() is set). In all other cases you
82 // should call SetResult(), which will issue the callback immediately if the
83 // result value isn't PP_OK_COMPLETIONPENDING. In the "completion pending"
84 // case, it's assumed the function the proxy is calling will take responsibility
85 // of executing the callback (returned by callback()).
87 // Example:
88 // EnterHostFromHostResourceForceCallback<PPB_Foo_API> enter(
89 // resource, callback_factory_, &MyClass::SendResult, resource);
90 // if (enter.failed())
91 // return; // SendResult automatically called with PP_ERROR_BADRESOURCE.
92 // enter.SetResult(enter.object()->DoFoo(enter.callback()));
94 // Where DoFoo's signature looks like this:
95 // int32_t DoFoo(PP_CompletionCallback callback);
96 // And SendResult's implementation looks like this:
97 // void MyClass::SendResult(int32_t result, const HostResource& res) {
98 // Send(new FooMsg_FooComplete(..., result, res));
99 // }
100 template<typename ResourceT>
101 class EnterHostFromHostResourceForceCallback
102 : public EnterHostFromHostResource<ResourceT> {
103 public:
104 EnterHostFromHostResourceForceCallback(
105 const HostResource& host_resource,
106 const pp::CompletionCallback& callback)
107 : EnterHostFromHostResource<ResourceT>(host_resource, callback),
108 needs_running_(true) {
111 // For callbacks that take no parameters except the "int32_t result". Most
112 // implementations will use the 1-extra-argument constructor below.
113 template<class CallbackFactory, typename Method>
114 EnterHostFromHostResourceForceCallback(
115 const HostResource& host_resource,
116 CallbackFactory& factory,
117 Method method)
118 : EnterHostFromHostResource<ResourceT>(host_resource,
119 factory.NewOptionalCallback(method)),
120 needs_running_(true) {
121 if (this->failed())
122 RunCallback(PP_ERROR_BADRESOURCE);
125 // For callbacks that take an extra parameter as a closure.
126 template<class CallbackFactory, typename Method, typename A>
127 EnterHostFromHostResourceForceCallback(
128 const HostResource& host_resource,
129 CallbackFactory& factory,
130 Method method,
131 const A& a)
132 : EnterHostFromHostResource<ResourceT>(host_resource,
133 factory.NewOptionalCallback(method, a)),
134 needs_running_(true) {
135 if (this->failed())
136 RunCallback(PP_ERROR_BADRESOURCE);
139 // For callbacks that take two extra parameters as a closure.
140 template<class CallbackFactory, typename Method, typename A, typename B>
141 EnterHostFromHostResourceForceCallback(
142 const HostResource& host_resource,
143 CallbackFactory& factory,
144 Method method,
145 const A& a,
146 const B& b)
147 : EnterHostFromHostResource<ResourceT>(host_resource,
148 factory.NewOptionalCallback(method, a, b)),
149 needs_running_(true) {
150 if (this->failed())
151 RunCallback(PP_ERROR_BADRESOURCE);
154 // For callbacks that take three extra parameters as a closure.
155 template<class CallbackFactory, typename Method, typename A, typename B,
156 typename C>
157 EnterHostFromHostResourceForceCallback(
158 const HostResource& host_resource,
159 CallbackFactory& factory,
160 Method method,
161 const A& a,
162 const B& b,
163 const C& c)
164 : EnterHostFromHostResource<ResourceT>(host_resource,
165 factory.NewOptionalCallback(method, a, b, c)),
166 needs_running_(true) {
167 if (this->failed())
168 RunCallback(PP_ERROR_BADRESOURCE);
171 ~EnterHostFromHostResourceForceCallback() {
172 if (needs_running_) {
173 NOTREACHED() << "Should always call SetResult except in the "
174 "initialization failed case.";
175 RunCallback(PP_ERROR_FAILED);
179 void SetResult(int32_t result) {
180 DCHECK(needs_running_) << "Don't call SetResult when there already is one.";
181 if (result != PP_OK_COMPLETIONPENDING)
182 RunCallback(result);
183 needs_running_ = false;
184 // Either we already ran the callback, or it will be run asynchronously. We
185 // clear the callback so it isn't accidentally run again (and because
186 // EnterBase checks that the callback has been cleared).
187 this->ClearCallback();
190 private:
191 void RunCallback(int32_t result) {
192 DCHECK(needs_running_);
193 needs_running_ = false;
194 this->callback()->Run(result);
195 this->ClearCallback();
198 bool needs_running_;
201 } // namespace proxy
202 } // namespace ppapi
204 #endif // PPAPI_PROXY_ENTER_PROXY_H_