OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ppapi/thunk/enter.h" | 5 #include "ppapi/thunk/enter.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 retval_ = callback_->BlockUntilComplete(); | 80 retval_ = callback_->BlockUntilComplete(); |
81 } else { | 81 } else { |
82 // The callback is not blocking and the operation will complete | 82 // The callback is not blocking and the operation will complete |
83 // asynchronously, so there's nothing to do. | 83 // asynchronously, so there's nothing to do. |
84 retval_ = result; | 84 retval_ = result; |
85 } | 85 } |
86 } else { | 86 } else { |
87 // The function completed synchronously. | 87 // The function completed synchronously. |
88 if (callback_->is_required()) { | 88 if (callback_->is_required()) { |
89 // This is a required callback, so we must issue it asynchronously. | 89 // This is a required callback, so we must issue it asynchronously. |
90 // TODO(dmichael) make this work so that a call from a background thread | |
91 // goes back to that thread. | |
92 callback_->PostRun(result); | 90 callback_->PostRun(result); |
93 retval_ = PP_OK_COMPLETIONPENDING; | 91 retval_ = PP_OK_COMPLETIONPENDING; |
94 } else { | 92 } else { |
95 // The callback is blocking or optional, so all we need to do is mark | 93 // The callback is blocking or optional, so all we need to do is mark |
96 // the callback as completed so that it won't be issued later. | 94 // the callback as completed so that it won't be issued later. |
97 callback_->MarkAsCompleted(); | 95 callback_->MarkAsCompleted(); |
98 retval_ = result; | 96 retval_ = result; |
99 } | 97 } |
100 } | 98 } |
101 callback_ = NULL; | 99 callback_ = NULL; |
102 return retval_; | 100 return retval_; |
103 } | 101 } |
104 | 102 |
105 // static | 103 // static |
106 Resource* EnterBase::GetResource(PP_Resource resource) { | 104 Resource* EnterBase::GetResource(PP_Resource resource) { |
107 return PpapiGlobals::Get()->GetResourceTracker()->GetResource(resource); | 105 return PpapiGlobals::Get()->GetResourceTracker()->GetResource(resource); |
108 } | 106 } |
109 | 107 |
110 void EnterBase::SetStateForCallbackError(bool report_error) { | 108 void EnterBase::SetStateForCallbackError(bool report_error) { |
111 if (!CallbackIsValid()) { | 109 if (PpapiGlobals::Get()->IsHostGlobals()) { |
112 callback_->MarkAsCompleted(); | 110 // In-process plugins can't make PPAPI calls off the main thread. |
113 callback_ = NULL; | 111 CHECK(IsMainThread()); |
114 retval_ = PP_ERROR_BLOCKS_MAIN_THREAD; | 112 } |
115 if (report_error) { | 113 if (callback_) { |
116 std::string message( | 114 if (callback_->is_blocking() && IsMainThread()) { |
117 "Blocking callbacks are not allowed on the main thread."); | 115 // Blocking callbacks are never allowed on the main thread. |
118 PpapiGlobals::Get()->BroadcastLogWithSource(0, PP_LOGLEVEL_ERROR, | 116 callback_->MarkAsCompleted(); |
119 std::string(), message); | 117 callback_ = NULL; |
| 118 retval_ = PP_ERROR_BLOCKS_MAIN_THREAD; |
| 119 if (report_error) { |
| 120 std::string message( |
| 121 "Blocking callbacks are not allowed on the main thread."); |
| 122 PpapiGlobals::Get()->BroadcastLogWithSource(0, PP_LOGLEVEL_ERROR, |
| 123 std::string(), message); |
| 124 } |
| 125 } else if (!IsMainThread() && |
| 126 callback_->has_null_target_loop() && |
| 127 !callback_->is_blocking()) { |
| 128 // On a non-main thread, there must be a valid target loop for non- |
| 129 // blocking callbacks, or we will have no place to run them. |
| 130 |
| 131 // If the callback is required, there's no nice way to tell the plugin. |
| 132 // We can't run their callback asynchronously without a message loop, and |
| 133 // the plugin won't expect any return code other than |
| 134 // PP_OK_COMPLETIONPENDING. So we crash to make the problem more obvious. |
| 135 if (callback_->is_required()) { |
| 136 std::string message("Attempted to use a required callback, but there" |
| 137 "is no attached message loop on which to run the" |
| 138 "callback."); |
| 139 PpapiGlobals::Get()->BroadcastLogWithSource(0, PP_LOGLEVEL_ERROR, |
| 140 std::string(), message); |
| 141 LOG(FATAL) << message; |
| 142 } |
| 143 |
| 144 callback_->MarkAsCompleted(); |
| 145 callback_ = NULL; |
| 146 retval_ = PP_ERROR_NO_MESSAGE_LOOP; |
| 147 if (report_error) { |
| 148 std::string message( |
| 149 "The calling thread must have a message loop attached."); |
| 150 PpapiGlobals::Get()->BroadcastLogWithSource(0, PP_LOGLEVEL_ERROR, |
| 151 std::string(), message); |
| 152 } |
120 } | 153 } |
121 } | 154 } |
122 } | 155 } |
123 | 156 |
124 bool EnterBase::CallbackIsValid() const { | |
125 // A callback is only considered invalid if it is blocking and we're on the | |
126 // main thread. | |
127 return !callback_ || !callback_->is_blocking() || !IsMainThread(); | |
128 } | |
129 | |
130 void EnterBase::ClearCallback() { | 157 void EnterBase::ClearCallback() { |
131 callback_ = NULL; | 158 callback_ = NULL; |
132 } | 159 } |
133 | 160 |
134 void EnterBase::SetStateForResourceError(PP_Resource pp_resource, | 161 void EnterBase::SetStateForResourceError(PP_Resource pp_resource, |
135 Resource* resource_base, | 162 Resource* resource_base, |
136 void* object, | 163 void* object, |
137 bool report_error) { | 164 bool report_error) { |
138 // Check for callback errors. If we get any, SetStateForCallbackError will | 165 // Check for callback errors. If we get any, SetStateForCallbackError will |
139 // emit a log message. But we also want to check for resource errors. If there | 166 // emit a log message. But we also want to check for resource errors. If there |
140 // are both kinds of errors, we'll emit two log messages and return | 167 // are both kinds of errors, we'll emit two log messages and return |
141 // PP_ERROR_BADRESOURCE. | 168 // PP_ERROR_BADRESOURCE. |
142 SetStateForCallbackError(report_error); | 169 SetStateForCallbackError(report_error); |
143 | 170 |
144 if (object) | 171 if (object) |
145 return; // Everything worked. | 172 return; // Everything worked. |
146 | 173 |
147 if (callback_ && callback_->is_required()) { | 174 if (callback_ && callback_->is_required()) { |
148 // TODO(dmichael) make this work so that a call from a background thread | |
149 // goes back to that thread. | |
150 callback_->PostRun(static_cast<int32_t>(PP_ERROR_BADRESOURCE)); | 175 callback_->PostRun(static_cast<int32_t>(PP_ERROR_BADRESOURCE)); |
151 callback_ = NULL; | 176 callback_ = NULL; |
152 retval_ = PP_OK_COMPLETIONPENDING; | 177 retval_ = PP_OK_COMPLETIONPENDING; |
153 } else { | 178 } else { |
154 if (callback_) | 179 if (callback_) |
155 callback_->MarkAsCompleted(); | 180 callback_->MarkAsCompleted(); |
156 callback_ = NULL; | 181 callback_ = NULL; |
157 retval_ = PP_ERROR_BADRESOURCE; | 182 retval_ = PP_ERROR_BADRESOURCE; |
158 } | 183 } |
159 | 184 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 : EnterBase(), | 290 : EnterBase(), |
266 functions_(PpapiGlobals::Get()->GetResourceCreationAPI(instance)) { | 291 functions_(PpapiGlobals::Get()->GetResourceCreationAPI(instance)) { |
267 SetStateForFunctionError(instance, functions_, true); | 292 SetStateForFunctionError(instance, functions_, true); |
268 } | 293 } |
269 | 294 |
270 EnterResourceCreationNoLock::~EnterResourceCreationNoLock() { | 295 EnterResourceCreationNoLock::~EnterResourceCreationNoLock() { |
271 } | 296 } |
272 | 297 |
273 } // namespace thunk | 298 } // namespace thunk |
274 } // namespace ppapi | 299 } // namespace ppapi |
OLD | NEW |