Chromium Code Reviews| 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/proxy/ppb_flash_proxy.h" | 5 #include "ppapi/proxy/ppb_flash_proxy.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/time.h" | 9 #include "base/time.h" |
| 10 #include "ppapi/c/dev/ppb_font_dev.h" | 10 #include "ppapi/c/dev/ppb_font_dev.h" |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 #include "ppapi/thunk/enter.h" | 28 #include "ppapi/thunk/enter.h" |
| 29 #include "ppapi/thunk/ppb_instance_api.h" | 29 #include "ppapi/thunk/ppb_instance_api.h" |
| 30 #include "ppapi/thunk/ppb_url_request_info_api.h" | 30 #include "ppapi/thunk/ppb_url_request_info_api.h" |
| 31 #include "ppapi/thunk/resource_creation_api.h" | 31 #include "ppapi/thunk/resource_creation_api.h" |
| 32 | 32 |
| 33 using ppapi::thunk::EnterInstanceNoLock; | 33 using ppapi::thunk::EnterInstanceNoLock; |
| 34 | 34 |
| 35 namespace ppapi { | 35 namespace ppapi { |
| 36 namespace proxy { | 36 namespace proxy { |
| 37 | 37 |
| 38 namespace { | |
| 39 | |
| 40 IPC::PlatformFileForTransit PlatformFileToPlatformFileForTransit( | |
|
brettw
2012/04/24 22:48:47
This stuff was just moved from the file_proxy.cc
| |
| 41 Dispatcher* dispatcher, | |
| 42 int32_t* error, | |
| 43 base::PlatformFile file) { | |
| 44 if (*error != PP_OK) | |
| 45 return IPC::InvalidPlatformFileForTransit(); | |
| 46 IPC::PlatformFileForTransit out_handle = | |
| 47 dispatcher->ShareHandleWithRemote(file, true); | |
| 48 if (out_handle == IPC::InvalidPlatformFileForTransit()) | |
| 49 *error = PP_ERROR_NOACCESS; | |
| 50 return out_handle; | |
| 51 } | |
| 52 | |
| 53 // ModuleLocalThreadAdapter ---------------------------------------------------- | |
| 54 // TODO(yzshen): Refactor to use IPC::SyncMessageFilter. | |
| 55 class ModuleLocalThreadAdapter | |
| 56 : public base::RefCountedThreadSafe<ModuleLocalThreadAdapter> { | |
|
yzshen1
2012/04/25 20:50:47
Please include .h for things such as RefCountedThr
| |
| 57 class Filter; | |
| 58 public: | |
| 59 ModuleLocalThreadAdapter(); | |
| 60 | |
| 61 void AddInstanceRouting(PP_Instance instance, Dispatcher* dispatcher); | |
| 62 void ClearInstanceRouting(PP_Instance instance); | |
| 63 void ClearFilter(Dispatcher* dispatcher, Filter* filter); | |
| 64 | |
| 65 bool OnModuleLocalMessageReceived(const IPC::Message& msg); | |
| 66 | |
| 67 // Called on the I/O thread when the channel is being destroyed and the | |
| 68 // given message will never be issued a reply. | |
| 69 void OnModuleLocalMessageFailed(int message_id); | |
| 70 | |
| 71 bool Send(PP_Instance instance, IPC::Message* msg); | |
| 72 | |
| 73 private: | |
| 74 class Filter : public IPC::ChannelProxy::MessageFilter { | |
| 75 public: | |
| 76 explicit Filter(Dispatcher* dispatcher); | |
| 77 ~Filter(); | |
| 78 | |
| 79 void Send(IPC::Message* msg); | |
| 80 | |
| 81 virtual void OnFilterAdded(IPC::Channel* channel); | |
| 82 virtual void OnFilterRemoved(); | |
| 83 virtual bool OnMessageReceived(const IPC::Message& message); | |
| 84 | |
| 85 private: | |
| 86 // DO NOT DEREFERENCE! This is used only for tracking. | |
| 87 Dispatcher* dispatcher_; | |
| 88 | |
| 89 IPC::Channel* channel_; | |
| 90 | |
| 91 // Holds the IPC messages that were sent before the channel was connected. | |
| 92 // These will be sent ASAP. | |
| 93 std::vector<IPC::Message*> pre_connect_pending_messages_; | |
| 94 | |
| 95 // Holds the IDs of the sync messages we're currently waiting on for this | |
| 96 // channel. This tracking allows us to cancel those requests if the | |
| 97 // remote process crashes and we're cleaning up this filter (without just | |
| 98 // deadlocking the waiting thread(s). | |
| 99 std::set<int> pending_requests_for_filter_; | |
| 100 }; | |
| 101 | |
| 102 void SendFromIOThread(Dispatcher* dispatcher, IPC::Message* msg); | |
| 103 | |
| 104 // Internal version of OnModuleLocalMessageFailed which assumes the lock | |
| 105 // is already held. | |
| 106 void OnModuleLocalMessageFailedLocked(int message_id); | |
| 107 | |
| 108 base::Lock lock_; | |
| 109 | |
| 110 scoped_refptr<base::MessageLoopProxy> main_thread_; | |
| 111 | |
| 112 // Will be NULL before an instance routing is added. | |
| 113 scoped_refptr<base::MessageLoopProxy> io_thread_; | |
| 114 | |
| 115 typedef std::map<PP_Instance, Dispatcher*> InstanceToDispatcher; | |
| 116 InstanceToDispatcher instance_to_dispatcher_; | |
| 117 | |
| 118 // The filters are owned by the channel. | |
| 119 typedef std::map<Dispatcher*, Filter*> DispatcherToFilter; | |
| 120 DispatcherToFilter dispatcher_to_filter_; | |
| 121 | |
| 122 // Tracks all messages with currently waiting threads. This does not own | |
| 123 // the pointer, the pointer lifetime is managed by Send(). | |
| 124 typedef std::map<int, IPC::PendingSyncMsg*> SyncRequestMap; | |
| 125 SyncRequestMap pending_sync_requests_; | |
| 126 }; | |
| 127 | |
| 128 ModuleLocalThreadAdapter* g_module_local_thread_adapter = NULL; | |
| 129 | |
| 130 ModuleLocalThreadAdapter::Filter::Filter(Dispatcher* dispatcher) | |
| 131 : dispatcher_(dispatcher), channel_(NULL) { | |
| 132 } | |
| 133 | |
| 134 ModuleLocalThreadAdapter::Filter::~Filter() { | |
| 135 } | |
| 136 | |
| 137 void ModuleLocalThreadAdapter::Filter::Send(IPC::Message* msg) { | |
| 138 if (channel_) { | |
| 139 int message_id = IPC::SyncMessage::GetMessageId(*msg); | |
| 140 if (channel_->Send(msg)) | |
| 141 pending_requests_for_filter_.insert(message_id); | |
| 142 else // Message lost, notify adapter so it can unblock. | |
| 143 g_module_local_thread_adapter->OnModuleLocalMessageFailed(message_id); | |
| 144 } else { | |
| 145 // No channel, save this message for when it's connected. | |
| 146 pre_connect_pending_messages_.push_back(msg); | |
| 147 } | |
| 148 } | |
| 149 | |
| 150 void ModuleLocalThreadAdapter::Filter::OnFilterAdded(IPC::Channel* channel) { | |
| 151 DCHECK(!channel_); | |
| 152 channel_ = channel; | |
| 153 | |
| 154 // Now that we have a channel, process all pending messages. | |
| 155 for (size_t i = 0; i < pre_connect_pending_messages_.size(); i++) | |
| 156 Send(pre_connect_pending_messages_[i]); | |
| 157 pre_connect_pending_messages_.clear(); | |
| 158 } | |
| 159 | |
| 160 void ModuleLocalThreadAdapter::Filter::OnFilterRemoved() { | |
| 161 DCHECK(channel_); | |
| 162 channel_ = NULL; | |
| 163 g_module_local_thread_adapter->ClearFilter(dispatcher_, this); | |
| 164 | |
| 165 for (std::set<int>::iterator i = pending_requests_for_filter_.begin(); | |
| 166 i != pending_requests_for_filter_.end(); ++i) { | |
| 167 g_module_local_thread_adapter->OnModuleLocalMessageFailed(*i); | |
| 168 } | |
| 169 } | |
| 170 | |
| 171 bool ModuleLocalThreadAdapter::Filter::OnMessageReceived( | |
| 172 const IPC::Message& message) { | |
| 173 if (!message.is_reply() || | |
| 174 message.routing_id() != API_ID_PPB_FLASH) | |
| 175 return false; | |
| 176 | |
| 177 if (g_module_local_thread_adapter->OnModuleLocalMessageReceived(message)) { | |
| 178 // The message was consumed, this means we can remove the message ID from | |
| 179 // the list of messages this channel is waiting on. | |
| 180 pending_requests_for_filter_.erase(IPC::SyncMessage::GetMessageId(message)); | |
| 181 return true; | |
| 182 } | |
| 183 return false; | |
| 184 } | |
| 185 | |
| 186 ModuleLocalThreadAdapter::ModuleLocalThreadAdapter() | |
| 187 : main_thread_(base::MessageLoopProxy::current()) { | |
| 188 } | |
| 189 | |
| 190 void ModuleLocalThreadAdapter::AddInstanceRouting(PP_Instance instance, | |
| 191 Dispatcher* dispatcher) { | |
| 192 base::AutoLock lock(lock_); | |
| 193 | |
| 194 // Now that we've had contact with a dispatcher, we can set up the IO thread. | |
| 195 DCHECK(main_thread_->BelongsToCurrentThread()); | |
| 196 if (!io_thread_.get()) | |
| 197 io_thread_ = dispatcher->GetIPCMessageLoop(); | |
| 198 | |
| 199 // Set up the instance -> dispatcher routing. | |
| 200 DCHECK(instance_to_dispatcher_.find(instance) == | |
| 201 instance_to_dispatcher_.end()); | |
| 202 instance_to_dispatcher_[instance] = dispatcher; | |
| 203 | |
| 204 DispatcherToFilter::iterator found_filter = | |
| 205 dispatcher_to_filter_.find(dispatcher); | |
| 206 if (found_filter == dispatcher_to_filter_.end()) { | |
| 207 // Need to set up a filter for this dispatcher to intercept the messages. | |
| 208 Filter* filter = new Filter(dispatcher); | |
| 209 dispatcher_to_filter_[dispatcher] = filter; | |
| 210 dispatcher->AddIOThreadMessageFilter(filter); | |
| 211 } | |
| 212 } | |
| 213 | |
| 214 void ModuleLocalThreadAdapter::ClearInstanceRouting(PP_Instance instance) { | |
| 215 // The dispatcher->filter mapping is cleaned up by ClearFilter which is | |
| 216 // initiated by the channel. | |
| 217 instance_to_dispatcher_.erase(instance); | |
| 218 } | |
| 219 | |
| 220 void ModuleLocalThreadAdapter::ClearFilter(Dispatcher* dispatcher, | |
| 221 Filter* filter) { | |
| 222 // DANGER! Don't dereference the dispatcher, it's just used to identify | |
| 223 // which filter to remove. The dispatcher may not even exist any more. | |
| 224 // | |
| 225 // Since the dispatcher may be gone, there's a potential for ambiguity if | |
| 226 // another one is created on the main thread before this code runs on the | |
| 227 // I/O thread. So we check that the filter matches to avoid this rare case. | |
| 228 base::AutoLock lock(lock_); | |
| 229 if (dispatcher_to_filter_[dispatcher] == filter) | |
| 230 dispatcher_to_filter_.erase(dispatcher); | |
| 231 } | |
| 232 | |
| 233 bool ModuleLocalThreadAdapter::OnModuleLocalMessageReceived( | |
| 234 const IPC::Message& msg) { | |
| 235 base::AutoLock lock(lock_); | |
| 236 | |
| 237 int message_id = IPC::SyncMessage::GetMessageId(msg); | |
| 238 SyncRequestMap::iterator found = pending_sync_requests_.find(message_id); | |
| 239 if (found == pending_sync_requests_.end()) { | |
| 240 // Not waiting for this event. This will happen for sync messages to the | |
| 241 // main thread which use the "regular" sync channel code path. | |
| 242 return false; | |
| 243 } | |
| 244 | |
| 245 IPC::PendingSyncMsg& info = *found->second; | |
| 246 | |
| 247 if (!msg.is_reply_error()) | |
| 248 info.deserializer->SerializeOutputParameters(msg); | |
| 249 info.done_event->Signal(); | |
| 250 return true; | |
| 251 } | |
| 252 | |
| 253 void ModuleLocalThreadAdapter::OnModuleLocalMessageFailed(int message_id) { | |
| 254 base::AutoLock lock(lock_); | |
| 255 OnModuleLocalMessageFailedLocked(message_id); | |
| 256 } | |
| 257 | |
| 258 bool ModuleLocalThreadAdapter::Send(PP_Instance instance, IPC::Message* msg) { | |
| 259 // Compute the dispatcher corresponding to this message. | |
| 260 Dispatcher* dispatcher = NULL; | |
| 261 { | |
| 262 base::AutoLock lock(lock_); | |
| 263 InstanceToDispatcher::iterator found = | |
| 264 instance_to_dispatcher_.find(instance); | |
| 265 if (found == instance_to_dispatcher_.end()) { | |
| 266 NOTREACHED(); | |
| 267 delete msg; | |
| 268 return false; | |
| 269 } | |
| 270 dispatcher = found->second; | |
| 271 } | |
| 272 | |
| 273 if (main_thread_->BelongsToCurrentThread()) { | |
| 274 // Easy case: We're on the same thread as the dispatcher, so we don't need | |
| 275 // a lock to access it, and we can just use the normal sync channel stuff | |
| 276 // to handle the message. Actually, we MUST use the normal sync channel | |
| 277 // stuff since there may be incoming sync messages that need processing. | |
| 278 // The code below doesn't handle any nested message loops. | |
| 279 return dispatcher->Send(msg); | |
| 280 } | |
| 281 | |
| 282 // Background thread case | |
| 283 // ---------------------- | |
| 284 // 1. Generate tracking info, stick in pending_sync_messages_map. | |
| 285 // 2. Kick off the request. This is done on the I/O thread. | |
| 286 // 3. Filter on the I/O thread notices reply, writes the reply data and | |
| 287 // signals the event. We block on the event while this is happening. | |
| 288 // 4. Remove tracking info. | |
| 289 | |
| 290 // Generate the tracking info. and copied | |
| 291 IPC::SyncMessage* sync_msg = static_cast<IPC::SyncMessage*>(msg); | |
| 292 int message_id = IPC::SyncMessage::GetMessageId(*sync_msg); | |
| 293 base::WaitableEvent event(true, false); | |
| 294 scoped_ptr<IPC::MessageReplyDeserializer> deserializer( | |
| 295 sync_msg->GetReplyDeserializer()); // We own this pointer once retrieved. | |
| 296 IPC::PendingSyncMsg info(message_id, deserializer.get(), &event); | |
| 297 | |
| 298 // Add the tracking information to our map. | |
| 299 { | |
| 300 base::AutoLock lock(lock_); | |
| 301 pending_sync_requests_[message_id] = &info; | |
| 302 } | |
| 303 | |
| 304 // This is a bit dangerous. We use the dispatcher pointer as the routing | |
| 305 // ID for this message. While we don't dereference it, there is an | |
| 306 // exceedingly remote possibility that while this is going to the background | |
| 307 // thread the connection will be shut down and a new one will be created with | |
| 308 // a dispatcher at the same address. It could potentially get sent to a | |
| 309 // random place, but it should actually still work (since the Flash file | |
| 310 // operations are global). | |
| 311 io_thread_->PostTask(FROM_HERE, | |
| 312 base::Bind(&ModuleLocalThreadAdapter::SendFromIOThread, this, | |
| 313 dispatcher, msg)); | |
| 314 | |
| 315 // Now we block the current thread waiting for the reply. | |
| 316 event.Wait(); | |
| 317 | |
| 318 { | |
| 319 // Clear our tracking info for this message now that we're done. | |
| 320 base::AutoLock lock(lock_); | |
| 321 DCHECK(pending_sync_requests_.find(message_id) != | |
| 322 pending_sync_requests_.end()); | |
| 323 pending_sync_requests_.erase(message_id); | |
| 324 } | |
| 325 | |
| 326 return true; | |
| 327 } | |
| 328 | |
| 329 void ModuleLocalThreadAdapter::SendFromIOThread(Dispatcher* dispatcher, | |
| 330 IPC::Message* msg) { | |
| 331 // DO NOT DEREFERENCE DISPATCHER. Used as a lookup only. | |
| 332 base::AutoLock lock(lock_); | |
| 333 DispatcherToFilter::iterator found = dispatcher_to_filter_.find(dispatcher); | |
| 334 | |
| 335 // The dispatcher could have been destroyed by the time we got here since | |
| 336 // we're on another thread. Need to unblock the caller. | |
| 337 if (found == dispatcher_to_filter_.end()) { | |
| 338 OnModuleLocalMessageFailedLocked(IPC::SyncMessage::GetMessageId(*msg)); | |
| 339 delete msg; | |
| 340 return; | |
| 341 } | |
| 342 | |
| 343 // Takes ownership of pointer. | |
| 344 found->second->Send(msg); | |
| 345 } | |
| 346 | |
| 347 void ModuleLocalThreadAdapter::OnModuleLocalMessageFailedLocked( | |
| 348 int message_id) { | |
| 349 lock_.AssertAcquired(); | |
| 350 | |
| 351 // Unblock the thread waiting for the message that will never come. | |
| 352 SyncRequestMap::iterator found = pending_sync_requests_.find(message_id); | |
| 353 if (found == pending_sync_requests_.end()) { | |
| 354 NOTREACHED(); | |
| 355 return; | |
| 356 } | |
| 357 found->second->done_event->Signal(); | |
| 358 } | |
| 359 | |
| 360 } // namespace | |
| 361 | |
| 362 // ----------------------------------------------------------------------------- | |
| 363 | |
| 38 PPB_Flash_Proxy::PPB_Flash_Proxy(Dispatcher* dispatcher) | 364 PPB_Flash_Proxy::PPB_Flash_Proxy(Dispatcher* dispatcher) |
| 39 : InterfaceProxy(dispatcher) { | 365 : InterfaceProxy(dispatcher) { |
| 40 } | 366 } |
| 41 | 367 |
| 42 PPB_Flash_Proxy::~PPB_Flash_Proxy() { | 368 PPB_Flash_Proxy::~PPB_Flash_Proxy() { |
| 43 } | 369 } |
| 44 | 370 |
| 45 bool PPB_Flash_Proxy::OnMessageReceived(const IPC::Message& msg) { | 371 bool PPB_Flash_Proxy::OnMessageReceived(const IPC::Message& msg) { |
| 46 // Prevent the dispatcher from going away during a call to Navigate. | 372 // Prevent the dispatcher from going away during a call to Navigate. |
| 47 // This must happen OUTSIDE of OnMsgNavigate since the handling code use | 373 // This must happen OUTSIDE of OnMsgNavigate since the handling code use |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 68 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_FlashSetFullscreen, | 394 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_FlashSetFullscreen, |
| 69 OnHostMsgFlashSetFullscreen) | 395 OnHostMsgFlashSetFullscreen) |
| 70 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_FlashGetScreenSize, | 396 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_FlashGetScreenSize, |
| 71 OnHostMsgFlashGetScreenSize) | 397 OnHostMsgFlashGetScreenSize) |
| 72 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_IsClipboardFormatAvailable, | 398 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_IsClipboardFormatAvailable, |
| 73 OnHostMsgIsClipboardFormatAvailable) | 399 OnHostMsgIsClipboardFormatAvailable) |
| 74 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_ReadClipboardData, | 400 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_ReadClipboardData, |
| 75 OnHostMsgReadClipboardData) | 401 OnHostMsgReadClipboardData) |
| 76 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_WriteClipboardData, | 402 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_WriteClipboardData, |
| 77 OnHostMsgWriteClipboardData) | 403 OnHostMsgWriteClipboardData) |
| 404 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_OpenFile, | |
| 405 OnHostMsgOpenFile) | |
| 406 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_RenameFile, | |
| 407 OnHostMsgRenameFile) | |
| 408 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_DeleteFileOrDir, | |
| 409 OnHostMsgDeleteFileOrDir) | |
| 410 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_CreateDir, | |
| 411 OnHostMsgCreateDir) | |
| 412 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_QueryFile, | |
| 413 OnHostMsgQueryFile) | |
| 414 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_GetDirContents, | |
| 415 OnHostMsgGetDirContents) | |
| 416 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_OpenFileRef, | |
| 417 OnHostMsgOpenFileRef) | |
| 418 IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBFlash_QueryFileRef, | |
| 419 OnHostMsgQueryFileRef) | |
| 78 IPC_MESSAGE_UNHANDLED(handled = false) | 420 IPC_MESSAGE_UNHANDLED(handled = false) |
| 79 IPC_END_MESSAGE_MAP() | 421 IPC_END_MESSAGE_MAP() |
| 80 // TODO(brettw) handle bad messages! | 422 // TODO(brettw) handle bad messages! |
| 81 return handled; | 423 return handled; |
| 82 } | 424 } |
| 83 | 425 |
| 84 void PPB_Flash_Proxy::SetInstanceAlwaysOnTop(PP_Instance instance, | 426 void PPB_Flash_Proxy::SetInstanceAlwaysOnTop(PP_Instance instance, |
| 85 PP_Bool on_top) { | 427 PP_Bool on_top) { |
| 86 dispatcher()->Send(new PpapiHostMsg_PPBFlash_SetInstanceAlwaysOnTop( | 428 dispatcher()->Send(new PpapiHostMsg_PPBFlash_SetInstanceAlwaysOnTop( |
| 87 API_ID_PPB_FLASH, instance, on_top)); | 429 API_ID_PPB_FLASH, instance, on_top)); |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 261 dispatcher()->Send(new PpapiHostMsg_PPBFlash_WriteClipboardData( | 603 dispatcher()->Send(new PpapiHostMsg_PPBFlash_WriteClipboardData( |
| 262 API_ID_PPB_FLASH, | 604 API_ID_PPB_FLASH, |
| 263 instance, | 605 instance, |
| 264 static_cast<int>(clipboard_type), | 606 static_cast<int>(clipboard_type), |
| 265 formats_vector, | 607 formats_vector, |
| 266 data_items_vector)); | 608 data_items_vector)); |
| 267 // Assume success, since it allows us to avoid a sync IPC. | 609 // Assume success, since it allows us to avoid a sync IPC. |
| 268 return PP_OK; | 610 return PP_OK; |
| 269 } | 611 } |
| 270 | 612 |
| 613 bool PPB_Flash_Proxy::CreateThreadAdapterForInstance(PP_Instance instance) { | |
| 614 if (!g_module_local_thread_adapter) { | |
| 615 g_module_local_thread_adapter = new ModuleLocalThreadAdapter(); | |
| 616 g_module_local_thread_adapter->AddRef(); // Leaked, this object is global. | |
| 617 } | |
| 618 | |
| 619 PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance); | |
| 620 if (!dispatcher) { | |
| 621 NOTREACHED(); | |
| 622 return false; | |
| 623 } | |
| 624 g_module_local_thread_adapter->AddInstanceRouting(instance, dispatcher); | |
| 625 return true; | |
| 626 } | |
| 627 | |
| 628 void PPB_Flash_Proxy::ClearThreadAdapterForInstance(PP_Instance instance) { | |
| 629 if (g_module_local_thread_adapter) | |
| 630 g_module_local_thread_adapter->ClearInstanceRouting(instance); | |
| 631 } | |
| 632 | |
| 633 int32_t PPB_Flash_Proxy::OpenFile(PP_Instance instance, | |
| 634 const char* path, | |
| 635 int32_t mode, | |
| 636 PP_FileHandle* file) { | |
| 637 if (!g_module_local_thread_adapter) | |
| 638 return PP_ERROR_FAILED; | |
| 639 | |
| 640 int32_t result = PP_ERROR_FAILED; | |
| 641 IPC::PlatformFileForTransit transit; | |
| 642 g_module_local_thread_adapter->Send(instance, | |
| 643 new PpapiHostMsg_PPBFlash_OpenFile( | |
| 644 API_ID_PPB_FLASH, instance, path, mode, &transit, &result)); | |
| 645 *file = IPC::PlatformFileForTransitToPlatformFile(transit); | |
| 646 return result; | |
| 647 } | |
| 648 | |
| 649 int32_t PPB_Flash_Proxy::RenameFile(PP_Instance instance, | |
| 650 const char* path_from, | |
| 651 const char* path_to) { | |
| 652 if (!g_module_local_thread_adapter) | |
| 653 return PP_ERROR_FAILED; | |
| 654 | |
| 655 int32_t result = PP_ERROR_FAILED; | |
| 656 g_module_local_thread_adapter->Send(instance, | |
| 657 new PpapiHostMsg_PPBFlash_RenameFile( | |
| 658 API_ID_PPB_FLASH, instance, path_from, path_to, &result)); | |
| 659 return result; | |
| 660 } | |
| 661 | |
| 662 int32_t PPB_Flash_Proxy::DeleteFileOrDir(PP_Instance instance, | |
| 663 const char* path, | |
| 664 PP_Bool recursive) { | |
| 665 if (!g_module_local_thread_adapter) | |
| 666 return PP_ERROR_FAILED; | |
| 667 | |
| 668 int32_t result = PP_ERROR_FAILED; | |
| 669 g_module_local_thread_adapter->Send(instance, | |
| 670 new PpapiHostMsg_PPBFlash_DeleteFileOrDir( | |
| 671 API_ID_PPB_FLASH, instance, path, recursive, &result)); | |
| 672 return result; | |
| 673 } | |
| 674 | |
| 675 int32_t PPB_Flash_Proxy::CreateDir(PP_Instance instance, const char* path) { | |
| 676 if (!g_module_local_thread_adapter) | |
| 677 return PP_ERROR_FAILED; | |
| 678 | |
| 679 int32_t result = PP_ERROR_FAILED; | |
| 680 g_module_local_thread_adapter->Send(instance, | |
| 681 new PpapiHostMsg_PPBFlash_CreateDir( | |
| 682 API_ID_PPB_FLASH, instance, path, &result)); | |
| 683 return result; | |
| 684 } | |
| 685 | |
| 686 int32_t PPB_Flash_Proxy::QueryFile(PP_Instance instance, | |
| 687 const char* path, | |
| 688 PP_FileInfo* info) { | |
| 689 if (!g_module_local_thread_adapter) | |
| 690 return PP_ERROR_FAILED; | |
| 691 | |
| 692 int32_t result = PP_ERROR_FAILED; | |
| 693 g_module_local_thread_adapter->Send(instance, | |
| 694 new PpapiHostMsg_PPBFlash_QueryFile( | |
| 695 API_ID_PPB_FLASH, instance, path, info, &result)); | |
| 696 return result; | |
| 697 } | |
| 698 | |
| 699 int32_t PPB_Flash_Proxy::GetDirContents(PP_Instance instance, | |
| 700 const char* path, | |
| 701 PP_DirContents_Dev** contents) { | |
| 702 if (!g_module_local_thread_adapter) | |
| 703 return PP_ERROR_FAILED; | |
| 704 | |
| 705 int32_t result = PP_ERROR_FAILED; | |
| 706 std::vector<SerializedDirEntry> entries; | |
| 707 g_module_local_thread_adapter->Send(instance, | |
| 708 new PpapiHostMsg_PPBFlash_GetDirContents( | |
| 709 API_ID_PPB_FLASH, instance, path, &entries, &result)); | |
| 710 | |
| 711 if (result != PP_OK) | |
| 712 return result; | |
| 713 | |
| 714 // Copy the serialized dir entries to the output struct. | |
| 715 *contents = new PP_DirContents_Dev; | |
| 716 (*contents)->count = static_cast<int32_t>(entries.size()); | |
| 717 (*contents)->entries = new PP_DirEntry_Dev[entries.size()]; | |
| 718 for (size_t i = 0; i < entries.size(); i++) { | |
| 719 const SerializedDirEntry& source = entries[i]; | |
| 720 PP_DirEntry_Dev* dest = &(*contents)->entries[i]; | |
| 721 | |
| 722 char* name_copy = new char[source.name.size() + 1]; | |
| 723 memcpy(name_copy, source.name.c_str(), source.name.size() + 1); | |
| 724 dest->name = name_copy; | |
| 725 dest->is_dir = PP_FromBool(source.is_dir); | |
| 726 } | |
| 727 | |
| 728 return result; | |
| 729 } | |
| 730 | |
| 731 int32_t PPB_Flash_Proxy::OpenFileRef(PP_Instance instance, | |
| 732 PP_Resource file_ref_id, | |
| 733 int32_t mode, | |
| 734 PP_FileHandle* file) { | |
| 735 Resource* file_ref = | |
| 736 PpapiGlobals::Get()->GetResourceTracker()->GetResource(file_ref_id); | |
|
yzshen1
2012/04/25 20:50:47
Can we use EnterResourceNoLock? (And also line 757
| |
| 737 if (!file_ref) | |
| 738 return PP_ERROR_BADRESOURCE; | |
| 739 | |
| 740 PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(file_ref); | |
|
yzshen1
2012/04/25 20:50:47
Can we use dispatcher() here? (And also line 761.)
| |
| 741 if (!dispatcher) | |
| 742 return PP_ERROR_BADARGUMENT; | |
| 743 | |
| 744 int32_t result = PP_ERROR_FAILED; | |
| 745 IPC::PlatformFileForTransit transit; | |
| 746 dispatcher->Send(new PpapiHostMsg_PPBFlash_OpenFileRef( | |
| 747 API_ID_PPB_FLASH, instance, file_ref->host_resource(), mode, &transit, | |
| 748 &result)); | |
| 749 *file = IPC::PlatformFileForTransitToPlatformFile(transit); | |
| 750 return result; | |
| 751 } | |
| 752 | |
| 753 int32_t PPB_Flash_Proxy::QueryFileRef(PP_Instance instance, | |
| 754 PP_Resource file_ref_id, | |
| 755 PP_FileInfo* info) { | |
| 756 Resource* file_ref = | |
| 757 PpapiGlobals::Get()->GetResourceTracker()->GetResource(file_ref_id); | |
| 758 if (!file_ref) | |
| 759 return PP_ERROR_BADRESOURCE; | |
| 760 | |
| 761 PluginDispatcher* dispatcher = PluginDispatcher::GetForResource(file_ref); | |
| 762 if (!dispatcher) | |
| 763 return PP_ERROR_BADARGUMENT; | |
| 764 | |
| 765 int32_t result = PP_ERROR_FAILED; | |
| 766 dispatcher->Send(new PpapiHostMsg_PPBFlash_QueryFileRef( | |
| 767 API_ID_PPB_FLASH, instance, file_ref->host_resource(), info, &result)); | |
| 768 return result; | |
| 769 } | |
| 770 | |
| 271 PP_Bool PPB_Flash_Proxy::FlashIsFullscreen(PP_Instance instance) { | 771 PP_Bool PPB_Flash_Proxy::FlashIsFullscreen(PP_Instance instance) { |
| 272 InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())-> | 772 InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())-> |
| 273 GetInstanceData(instance); | 773 GetInstanceData(instance); |
| 274 if (!data) | 774 if (!data) |
| 275 return PP_FALSE; | 775 return PP_FALSE; |
| 276 return data->flash_fullscreen; | 776 return data->flash_fullscreen; |
| 277 } | 777 } |
| 278 | 778 |
| 279 PP_Bool PPB_Flash_Proxy::FlashSetFullscreen(PP_Instance instance, | 779 PP_Bool PPB_Flash_Proxy::FlashSetFullscreen(PP_Instance instance, |
| 280 PP_Bool fullscreen) { | 780 PP_Bool fullscreen) { |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 493 static_cast<PP_Flash_Clipboard_Type>(clipboard_type), | 993 static_cast<PP_Flash_Clipboard_Type>(clipboard_type), |
| 494 data_item_count, | 994 data_item_count, |
| 495 formats_array.get(), | 995 formats_array.get(), |
| 496 data_items_array); | 996 data_items_array); |
| 497 DLOG_IF(WARNING, result != PP_OK) | 997 DLOG_IF(WARNING, result != PP_OK) |
| 498 << "Write to clipboard failed unexpectedly."; | 998 << "Write to clipboard failed unexpectedly."; |
| 499 (void)result; // Prevent warning in release mode. | 999 (void)result; // Prevent warning in release mode. |
| 500 } | 1000 } |
| 501 } | 1001 } |
| 502 | 1002 |
| 1003 void PPB_Flash_Proxy::OnHostMsgOpenFile( | |
| 1004 PP_Instance instance, | |
| 1005 const std::string& path, | |
| 1006 int32_t mode, | |
| 1007 IPC::PlatformFileForTransit* file_handle, | |
| 1008 int32_t* result) { | |
| 1009 EnterInstanceNoLock enter(instance); | |
| 1010 if (enter.succeeded()) { | |
|
yzshen1
2012/04/25 20:50:47
Please set |result| if enter.failed() here and som
| |
| 1011 base::PlatformFile file; | |
| 1012 *result = enter.functions()->GetFlashAPI()->OpenFile( | |
| 1013 instance, path.c_str(), mode, &file); | |
| 1014 *file_handle = PlatformFileToPlatformFileForTransit( | |
| 1015 dispatcher(), result, file); | |
| 1016 } | |
| 1017 } | |
| 1018 | |
| 1019 void PPB_Flash_Proxy::OnHostMsgRenameFile(PP_Instance instance, | |
| 1020 const std::string& from_path, | |
| 1021 const std::string& to_path, | |
| 1022 int32_t* result) { | |
| 1023 EnterInstanceNoLock enter(instance); | |
| 1024 if (enter.succeeded()) { | |
| 1025 *result = enter.functions()->GetFlashAPI()->RenameFile( | |
| 1026 instance, from_path.c_str(), to_path.c_str()); | |
| 1027 } | |
| 1028 } | |
| 1029 | |
| 1030 void PPB_Flash_Proxy::OnHostMsgDeleteFileOrDir(PP_Instance instance, | |
| 1031 const std::string& path, | |
| 1032 PP_Bool recursive, | |
| 1033 int32_t* result) { | |
| 1034 EnterInstanceNoLock enter(instance); | |
| 1035 if (enter.succeeded()) { | |
| 1036 *result = enter.functions()->GetFlashAPI()->DeleteFileOrDir( | |
| 1037 instance, path.c_str(), recursive); | |
| 1038 } | |
| 1039 } | |
| 1040 | |
| 1041 void PPB_Flash_Proxy::OnHostMsgCreateDir(PP_Instance instance, | |
| 1042 const std::string& path, | |
| 1043 int32_t* result) { | |
| 1044 EnterInstanceNoLock enter(instance); | |
| 1045 if (enter.succeeded()) { | |
| 1046 *result = enter.functions()->GetFlashAPI()->CreateDir( | |
| 1047 instance, path.c_str()); | |
| 1048 } | |
| 1049 } | |
| 1050 | |
| 1051 void PPB_Flash_Proxy::OnHostMsgQueryFile(PP_Instance instance, | |
| 1052 const std::string& path, | |
| 1053 PP_FileInfo* info, | |
| 1054 int32_t* result) { | |
| 1055 EnterInstanceNoLock enter(instance); | |
| 1056 if (enter.succeeded()) { | |
| 1057 *result = enter.functions()->GetFlashAPI()->QueryFile( | |
| 1058 instance, path.c_str(), info); | |
| 1059 } | |
| 1060 } | |
| 1061 | |
| 1062 void PPB_Flash_Proxy::OnHostMsgGetDirContents( | |
| 1063 PP_Instance instance, | |
| 1064 const std::string& path, | |
| 1065 std::vector<SerializedDirEntry>* entries, | |
| 1066 int32_t* result) { | |
| 1067 EnterInstanceNoLock enter(instance); | |
| 1068 if (enter.failed()) | |
| 1069 return; | |
| 1070 | |
| 1071 PP_DirContents_Dev* contents = NULL; | |
| 1072 *result = enter.functions()->GetFlashAPI()->GetDirContents( | |
| 1073 instance, path.c_str(), &contents); | |
| 1074 if (*result != PP_OK) | |
| 1075 return; | |
| 1076 | |
| 1077 // Convert the list of entries to the serialized version. | |
| 1078 entries->resize(contents->count); | |
| 1079 for (int32_t i = 0; i < contents->count; i++) { | |
| 1080 (*entries)[i].name.assign(contents->entries[i].name); | |
| 1081 (*entries)[i].is_dir = PP_ToBool(contents->entries[i].is_dir); | |
| 1082 } | |
| 1083 enter.functions()->GetFlashAPI()->FreeDirContents(instance, contents); | |
| 1084 } | |
| 1085 | |
| 1086 void PPB_Flash_Proxy::OnHostMsgOpenFileRef( | |
| 1087 PP_Instance instance, | |
| 1088 const HostResource& host_resource, | |
| 1089 int32_t mode, | |
| 1090 IPC::PlatformFileForTransit* file_handle, | |
| 1091 int32_t* result) { | |
| 1092 EnterInstanceNoLock enter(instance); | |
| 1093 if (enter.failed()) { | |
| 1094 *result = PP_ERROR_BADARGUMENT; | |
| 1095 return; | |
| 1096 } | |
| 1097 | |
| 1098 base::PlatformFile file; | |
| 1099 *result = enter.functions()->GetFlashAPI()->OpenFileRef( | |
| 1100 instance, host_resource.host_resource(), mode, &file); | |
| 1101 *file_handle = PlatformFileToPlatformFileForTransit(dispatcher(), | |
| 1102 result, file); | |
| 1103 } | |
| 1104 | |
| 1105 void PPB_Flash_Proxy::OnHostMsgQueryFileRef( | |
| 1106 PP_Instance instance, | |
| 1107 const HostResource& host_resource, | |
| 1108 PP_FileInfo* info, | |
| 1109 int32_t* result) { | |
| 1110 EnterInstanceNoLock enter(instance); | |
| 1111 if (enter.failed()) { | |
| 1112 *result = PP_ERROR_BADARGUMENT; | |
| 1113 return; | |
| 1114 } | |
| 1115 *result = enter.functions()->GetFlashAPI()->QueryFileRef( | |
| 1116 instance, host_resource.host_resource(), info); | |
| 1117 } | |
| 1118 | |
| 503 } // namespace proxy | 1119 } // namespace proxy |
| 504 } // namespace ppapi | 1120 } // namespace ppapi |
| OLD | NEW |