Home | History | Annotate | Download | only in system
      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