1 // Copyright 2014 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 "mojo/system/platform_handle_dispatcher.h" 6 7 #include <algorithm> 8 9 #include "base/logging.h" 10 11 namespace mojo { 12 namespace system { 13 14 namespace { 15 16 const size_t kInvalidPlatformHandleIndex = static_cast<size_t>(-1); 17 18 struct SerializedPlatformHandleDispatcher { 19 size_t platform_handle_index; // (Or |kInvalidPlatformHandleIndex|.) 20 }; 21 22 } // namespace 23 24 PlatformHandleDispatcher::PlatformHandleDispatcher( 25 embedder::ScopedPlatformHandle platform_handle) 26 : platform_handle_(platform_handle.Pass()) { 27 } 28 29 embedder::ScopedPlatformHandle PlatformHandleDispatcher::PassPlatformHandle() { 30 base::AutoLock locker(lock()); 31 return platform_handle_.Pass(); 32 } 33 34 Dispatcher::Type PlatformHandleDispatcher::GetType() const { 35 return kTypePlatformHandle; 36 } 37 38 // static 39 scoped_refptr<PlatformHandleDispatcher> PlatformHandleDispatcher::Deserialize( 40 Channel* channel, 41 const void* source, 42 size_t size, 43 embedder::PlatformHandleVector* platform_handles) { 44 if (size != sizeof(SerializedPlatformHandleDispatcher)) { 45 LOG(ERROR) << "Invalid serialized platform handle dispatcher (bad size)"; 46 return scoped_refptr<PlatformHandleDispatcher>(); 47 } 48 49 const SerializedPlatformHandleDispatcher* serialization = 50 static_cast<const SerializedPlatformHandleDispatcher*>(source); 51 size_t platform_handle_index = serialization->platform_handle_index; 52 53 // Starts off invalid, which is what we want. 54 embedder::PlatformHandle platform_handle; 55 56 if (platform_handle_index != kInvalidPlatformHandleIndex) { 57 if (!platform_handles || 58 platform_handle_index >= platform_handles->size()) { 59 LOG(ERROR) 60 << "Invalid serialized platform handle dispatcher (missing handles)"; 61 return scoped_refptr<PlatformHandleDispatcher>(); 62 } 63 64 // We take ownership of the handle, so we have to invalidate the one in 65 // |platform_handles|. 66 std::swap(platform_handle, (*platform_handles)[platform_handle_index]); 67 } 68 69 return scoped_refptr<PlatformHandleDispatcher>(new PlatformHandleDispatcher( 70 embedder::ScopedPlatformHandle(platform_handle))); 71 } 72 73 PlatformHandleDispatcher::~PlatformHandleDispatcher() { 74 } 75 76 void PlatformHandleDispatcher::CloseImplNoLock() { 77 lock().AssertAcquired(); 78 platform_handle_.reset(); 79 } 80 81 scoped_refptr<Dispatcher> 82 PlatformHandleDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { 83 lock().AssertAcquired(); 84 return scoped_refptr<Dispatcher>( 85 new PlatformHandleDispatcher(platform_handle_.Pass())); 86 } 87 88 void PlatformHandleDispatcher::StartSerializeImplNoLock( 89 Channel* /*channel*/, 90 size_t* max_size, 91 size_t* max_platform_handles) { 92 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. 93 *max_size = sizeof(SerializedPlatformHandleDispatcher); 94 *max_platform_handles = 1; 95 } 96 97 bool PlatformHandleDispatcher::EndSerializeAndCloseImplNoLock( 98 Channel* /*channel*/, 99 void* destination, 100 size_t* actual_size, 101 embedder::PlatformHandleVector* platform_handles) { 102 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. 103 104 SerializedPlatformHandleDispatcher* serialization = 105 static_cast<SerializedPlatformHandleDispatcher*>(destination); 106 if (platform_handle_.is_valid()) { 107 serialization->platform_handle_index = platform_handles->size(); 108 platform_handles->push_back(platform_handle_.release()); 109 } else { 110 serialization->platform_handle_index = kInvalidPlatformHandleIndex; 111 } 112 113 *actual_size = sizeof(SerializedPlatformHandleDispatcher); 114 return true; 115 } 116 117 } // namespace system 118 } // namespace mojo 119