// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "mojo/system/platform_handle_dispatcher.h" #include #include "base/logging.h" namespace mojo { namespace system { namespace { const size_t kInvalidPlatformHandleIndex = static_cast(-1); struct SerializedPlatformHandleDispatcher { size_t platform_handle_index; // (Or |kInvalidPlatformHandleIndex|.) }; } // namespace PlatformHandleDispatcher::PlatformHandleDispatcher( embedder::ScopedPlatformHandle platform_handle) : platform_handle_(platform_handle.Pass()) { } embedder::ScopedPlatformHandle PlatformHandleDispatcher::PassPlatformHandle() { base::AutoLock locker(lock()); return platform_handle_.Pass(); } Dispatcher::Type PlatformHandleDispatcher::GetType() const { return kTypePlatformHandle; } // static scoped_refptr PlatformHandleDispatcher::Deserialize( Channel* channel, const void* source, size_t size, embedder::PlatformHandleVector* platform_handles) { if (size != sizeof(SerializedPlatformHandleDispatcher)) { LOG(ERROR) << "Invalid serialized platform handle dispatcher (bad size)"; return scoped_refptr(); } const SerializedPlatformHandleDispatcher* serialization = static_cast(source); size_t platform_handle_index = serialization->platform_handle_index; // Starts off invalid, which is what we want. embedder::PlatformHandle platform_handle; if (platform_handle_index != kInvalidPlatformHandleIndex) { if (!platform_handles || platform_handle_index >= platform_handles->size()) { LOG(ERROR) << "Invalid serialized platform handle dispatcher (missing handles)"; return scoped_refptr(); } // We take ownership of the handle, so we have to invalidate the one in // |platform_handles|. std::swap(platform_handle, (*platform_handles)[platform_handle_index]); } return scoped_refptr(new PlatformHandleDispatcher( embedder::ScopedPlatformHandle(platform_handle))); } PlatformHandleDispatcher::~PlatformHandleDispatcher() { } void PlatformHandleDispatcher::CloseImplNoLock() { lock().AssertAcquired(); platform_handle_.reset(); } scoped_refptr PlatformHandleDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { lock().AssertAcquired(); return scoped_refptr( new PlatformHandleDispatcher(platform_handle_.Pass())); } void PlatformHandleDispatcher::StartSerializeImplNoLock( Channel* /*channel*/, size_t* max_size, size_t* max_platform_handles) { DCHECK(HasOneRef()); // Only one ref => no need to take the lock. *max_size = sizeof(SerializedPlatformHandleDispatcher); *max_platform_handles = 1; } bool PlatformHandleDispatcher::EndSerializeAndCloseImplNoLock( Channel* /*channel*/, void* destination, size_t* actual_size, embedder::PlatformHandleVector* platform_handles) { DCHECK(HasOneRef()); // Only one ref => no need to take the lock. SerializedPlatformHandleDispatcher* serialization = static_cast(destination); if (platform_handle_.is_valid()) { serialization->platform_handle_index = platform_handles->size(); platform_handles->push_back(platform_handle_.release()); } else { serialization->platform_handle_index = kInvalidPlatformHandleIndex; } *actual_size = sizeof(SerializedPlatformHandleDispatcher); return true; } } // namespace system } // namespace mojo