| 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 "content/renderer/pepper/pepper_broker_impl.h" | 5 #include "content/renderer/pepper/pepper_broker_impl.h" |
| 6 | 6 |
| 7 #include "build/build_config.h" | 7 #include "build/build_config.h" |
| 8 #include "content/public/renderer/renderer_restrict_dispatch_group.h" | 8 #include "content/public/renderer/renderer_restrict_dispatch_group.h" |
| 9 #include "content/renderer/pepper/pepper_plugin_delegate_impl.h" | 9 #include "content/renderer/pepper/pepper_plugin_delegate_impl.h" |
| 10 #include "content/renderer/pepper/pepper_proxy_channel_delegate_impl.h" | 10 #include "content/renderer/pepper/pepper_proxy_channel_delegate_impl.h" |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 PepperPluginDelegateImpl* delegate) | 109 PepperPluginDelegateImpl* delegate) |
| 110 : plugin_module_(plugin_module), | 110 : plugin_module_(plugin_module), |
| 111 delegate_(delegate->AsWeakPtr()) { | 111 delegate_(delegate->AsWeakPtr()) { |
| 112 DCHECK(plugin_module_); | 112 DCHECK(plugin_module_); |
| 113 DCHECK(delegate_); | 113 DCHECK(delegate_); |
| 114 | 114 |
| 115 plugin_module_->SetBroker(this); | 115 plugin_module_->SetBroker(this); |
| 116 } | 116 } |
| 117 | 117 |
| 118 PepperBrokerImpl::~PepperBrokerImpl() { | 118 PepperBrokerImpl::~PepperBrokerImpl() { |
| 119 // Report failure to all clients that had pending operations. | 119 ReportFailureToClients(PP_ERROR_ABORTED); |
| 120 for (ClientMap::iterator i = pending_connects_.begin(); | |
| 121 i != pending_connects_.end(); ++i) { | |
| 122 base::WeakPtr<webkit::ppapi::PPB_Broker_Impl>& weak_ptr = i->second; | |
| 123 if (weak_ptr) { | |
| 124 weak_ptr->BrokerConnected( | |
| 125 ppapi::PlatformFileToInt(base::kInvalidPlatformFileValue), | |
| 126 PP_ERROR_ABORTED); | |
| 127 } | |
| 128 } | |
| 129 pending_connects_.clear(); | |
| 130 | |
| 131 plugin_module_->SetBroker(NULL); | 120 plugin_module_->SetBroker(NULL); |
| 132 plugin_module_ = NULL; | 121 plugin_module_ = NULL; |
| 133 } | 122 } |
| 134 | 123 |
| 135 // If the channel is not ready, queue the connection. | 124 // If the channel is not ready, queue the connection. |
| 136 void PepperBrokerImpl::Connect(webkit::ppapi::PPB_Broker_Impl* client) { | 125 void PepperBrokerImpl::AddPendingConnect( |
| 126 webkit::ppapi::PPB_Broker_Impl* client) { |
| 137 DCHECK(pending_connects_.find(client) == pending_connects_.end()) | 127 DCHECK(pending_connects_.find(client) == pending_connects_.end()) |
| 138 << "Connect was already called for this client"; | 128 << "Connect was already called for this client"; |
| 139 | 129 |
| 140 // Ensure this object and the associated broker exist as long as the | 130 // Ensure this object and the associated broker exist as long as the |
| 141 // client exists. There is a corresponding Release() call in Disconnect(), | 131 // client exists. There is a corresponding Release() call in Disconnect(), |
| 142 // which is called when the PPB_Broker_Impl is destroyed. The only other | 132 // which is called when the PPB_Broker_Impl is destroyed. The only other |
| 143 // possible reference is in pending_connect_broker_, which only holds a | 133 // possible reference is in pending_connect_broker_, which only holds a |
| 144 // transient reference. This ensures the broker is available as long as the | 134 // transient reference. This ensures the broker is available as long as the |
| 145 // plugin needs it and allows the plugin to release the broker when it is no | 135 // plugin needs it and allows the plugin to release the broker when it is no |
| 146 // longer using it. | 136 // longer using it. |
| 147 AddRef(); | 137 AddRef(); |
| 148 | 138 |
| 149 if (!dispatcher_.get()) { | 139 pending_connects_[client].client = client->AsWeakPtr(); |
| 150 pending_connects_[client] = client->AsWeakPtr(); | |
| 151 return; | |
| 152 } | |
| 153 DCHECK(pending_connects_.empty()); | |
| 154 | |
| 155 ConnectPluginToBroker(client); | |
| 156 } | 140 } |
| 157 | 141 |
| 158 void PepperBrokerImpl::Disconnect(webkit::ppapi::PPB_Broker_Impl* client) { | 142 void PepperBrokerImpl::Disconnect(webkit::ppapi::PPB_Broker_Impl* client) { |
| 159 // Remove the pending connect if one exists. This class will not call client's | 143 // Remove the pending connect if one exists. This class will not call client's |
| 160 // callback. | 144 // callback. |
| 161 pending_connects_.erase(client); | 145 pending_connects_.erase(client); |
| 162 | 146 |
| 163 // TODO(ddorwin): Send message disconnect message using dispatcher_. | 147 // TODO(ddorwin): Send message disconnect message using dispatcher_. |
| 164 | 148 |
| 165 if (pending_connects_.empty()) { | 149 if (pending_connects_.empty()) { |
| 166 // There are no more clients of this broker. Ensure it will be deleted even | 150 // There are no more clients of this broker. Ensure it will be deleted even |
| 167 // if the IPC response never comes and OnPepperBrokerChannelCreated is not | 151 // if the IPC response never comes and OnPepperBrokerChannelCreated is not |
| 168 // called to remove this object from pending_connect_broker_. | 152 // called to remove this object from pending_connect_broker_. |
| 169 // Before the broker is connected, clients must either be in | 153 // Before the broker is connected, clients must either be in |
| 170 // pending_connects_ or not yet associated with this object. Thus, if this | 154 // pending_connects_ or not yet associated with this object. Thus, if this |
| 171 // object is in pending_connect_broker_, there can be no associated clients | 155 // object is in pending_connect_broker_, there can be no associated clients |
| 172 // once pending_connects_ is empty and it is thus safe to remove this from | 156 // once pending_connects_ is empty and it is thus safe to remove this from |
| 173 // pending_connect_broker_. Doing so will cause this object to be deleted, | 157 // pending_connect_broker_. Doing so will cause this object to be deleted, |
| 174 // removing it from the PluginModule. Any new clients will create a new | 158 // removing it from the PluginModule. Any new clients will create a new |
| 175 // instance of this object. | 159 // instance of this object. |
| 176 // This doesn't solve all potential problems, but it helps with the ones | 160 // This doesn't solve all potential problems, but it helps with the ones |
| 177 // we can influence. | 161 // we can influence. |
| 178 if (delegate_) { | 162 if (delegate_) { |
| 179 bool stopped = delegate_->StopWaitingForBrokerConnection(this); | 163 bool stopped = delegate_->StopWaitingForBrokerConnection(this); |
| 180 | 164 |
| 181 // Verify the assumption that there are no references other than the one | 165 // Verify the assumption that there are no references other than the one |
| 182 // client holds, which will be released below. | 166 // |client| holds, which will be released below. |
| 183 DCHECK(!stopped || HasOneRef()); | 167 DCHECK(!stopped || HasOneRef()); |
| 184 } | 168 } |
| 185 } | 169 } |
| 186 | 170 |
| 187 // Release the reference added in Connect(). | 171 // Release the reference added in Connect(). |
| 188 // This must be the last statement because it may delete this object. | 172 // This must be the last statement because it may delete this object. |
| 189 Release(); | 173 Release(); |
| 190 } | 174 } |
| 191 | 175 |
| 192 void PepperBrokerImpl::OnBrokerChannelConnected( | 176 void PepperBrokerImpl::OnBrokerChannelConnected( |
| 193 const IPC::ChannelHandle& channel_handle) { | 177 const IPC::ChannelHandle& channel_handle) { |
| 194 scoped_ptr<PepperBrokerDispatcherWrapper> dispatcher( | 178 scoped_ptr<PepperBrokerDispatcherWrapper> dispatcher( |
| 195 new PepperBrokerDispatcherWrapper); | 179 new PepperBrokerDispatcherWrapper); |
| 196 if (dispatcher->Init(channel_handle)) { | 180 if (!dispatcher->Init(channel_handle)) { |
| 197 dispatcher_.reset(dispatcher.release()); | 181 ReportFailureToClients(PP_ERROR_FAILED); |
| 182 return; |
| 183 } |
| 198 | 184 |
| 199 // Process all pending channel requests from the plugins. | 185 dispatcher_.reset(dispatcher.release()); |
| 200 for (ClientMap::iterator i = pending_connects_.begin(); | 186 |
| 201 i != pending_connects_.end(); ++i) { | 187 // Process all pending channel requests from the plugins. |
| 202 base::WeakPtr<webkit::ppapi::PPB_Broker_Impl>& weak_ptr = i->second; | 188 for (ClientMap::iterator i = pending_connects_.begin(); |
| 203 if (weak_ptr) | 189 i != pending_connects_.end();) { |
| 204 ConnectPluginToBroker(weak_ptr); | 190 base::WeakPtr<webkit::ppapi::PPB_Broker_Impl>& weak_ptr = |
| 191 i->second.client; |
| 192 if (!i->second.is_authorized) { |
| 193 ++i; |
| 194 continue; |
| 205 } | 195 } |
| 206 } else { | 196 |
| 207 // Report failure to all clients. | 197 if (weak_ptr) |
| 208 for (ClientMap::iterator i = pending_connects_.begin(); | 198 ConnectPluginToBroker(weak_ptr); |
| 209 i != pending_connects_.end(); ++i) { | 199 |
| 210 base::WeakPtr<webkit::ppapi::PPB_Broker_Impl>& weak_ptr = i->second; | 200 pending_connects_.erase(i++); |
| 211 if (weak_ptr) { | 201 } |
| 212 weak_ptr->BrokerConnected( | 202 } |
| 213 ppapi::PlatformFileToInt(base::kInvalidPlatformFileValue), | 203 |
| 214 PP_ERROR_FAILED); | 204 void PepperBrokerImpl::OnBrokerPermissionResult( |
| 215 } | 205 webkit::ppapi::PPB_Broker_Impl* client, |
| 206 bool result) { |
| 207 ClientMap::iterator entry = pending_connects_.find(client); |
| 208 if (entry == pending_connects_.end()) |
| 209 return; |
| 210 |
| 211 if (!entry->second.client) { |
| 212 // Client has gone away. |
| 213 pending_connects_.erase(entry); |
| 214 return; |
| 215 } |
| 216 |
| 217 if (!result) { |
| 218 // Report failure. |
| 219 client->BrokerConnected( |
| 220 ppapi::PlatformFileToInt(base::kInvalidPlatformFileValue), |
| 221 PP_ERROR_NOACCESS); |
| 222 pending_connects_.erase(entry); |
| 223 return; |
| 224 } |
| 225 |
| 226 if (dispatcher_.get()) { |
| 227 ConnectPluginToBroker(client); |
| 228 pending_connects_.erase(entry); |
| 229 return; |
| 230 } |
| 231 |
| 232 // Mark the request as authorized, continue waiting for the broker |
| 233 // connection. |
| 234 DCHECK(!entry->second.is_authorized); |
| 235 entry->second.is_authorized = true; |
| 236 } |
| 237 |
| 238 PepperBrokerImpl::PendingConnection::PendingConnection() |
| 239 : is_authorized(false) { |
| 240 } |
| 241 |
| 242 PepperBrokerImpl::PendingConnection::~PendingConnection() { |
| 243 } |
| 244 |
| 245 void PepperBrokerImpl::ReportFailureToClients(int error_code) { |
| 246 DCHECK_NE(PP_OK, error_code); |
| 247 for (ClientMap::iterator i = pending_connects_.begin(); |
| 248 i != pending_connects_.end(); ++i) { |
| 249 base::WeakPtr<webkit::ppapi::PPB_Broker_Impl>& weak_ptr = |
| 250 i->second.client; |
| 251 if (weak_ptr) { |
| 252 weak_ptr->BrokerConnected( |
| 253 ppapi::PlatformFileToInt(base::kInvalidPlatformFileValue), |
| 254 error_code); |
| 216 } | 255 } |
| 217 } | 256 } |
| 218 pending_connects_.clear(); | 257 pending_connects_.clear(); |
| 219 } | 258 } |
| 220 | 259 |
| 221 void PepperBrokerImpl::ConnectPluginToBroker( | 260 void PepperBrokerImpl::ConnectPluginToBroker( |
| 222 webkit::ppapi::PPB_Broker_Impl* client) { | 261 webkit::ppapi::PPB_Broker_Impl* client) { |
| 223 base::SyncSocket::Handle plugin_handle = base::kInvalidPlatformFileValue; | 262 base::SyncSocket::Handle plugin_handle = base::kInvalidPlatformFileValue; |
| 224 int32_t result = PP_OK; | 263 int32_t result = PP_OK; |
| 225 | 264 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 241 | 280 |
| 242 // TOOD(ddorwin): Change the IPC to asynchronous: Queue an object containing | 281 // TOOD(ddorwin): Change the IPC to asynchronous: Queue an object containing |
| 243 // client and plugin_socket.release(), then return. | 282 // client and plugin_socket.release(), then return. |
| 244 // That message handler will then call client->BrokerConnected() with the | 283 // That message handler will then call client->BrokerConnected() with the |
| 245 // saved pipe handle. | 284 // saved pipe handle. |
| 246 // Temporarily, just call back. | 285 // Temporarily, just call back. |
| 247 client->BrokerConnected(ppapi::PlatformFileToInt(plugin_handle), result); | 286 client->BrokerConnected(ppapi::PlatformFileToInt(plugin_handle), result); |
| 248 } | 287 } |
| 249 | 288 |
| 250 } // namespace content | 289 } // namespace content |
| OLD | NEW |