summaryrefslogtreecommitdiffstats
path: root/ppapi/proxy/serialized_handle.h
blob: 252ffcb9f3ccd2549cb4f9454223315382f6522e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright (c) 2013 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.

#ifndef PPAPI_PROXY_SERIALIZED_HANDLES_H_
#define PPAPI_PROXY_SERIALIZED_HANDLES_H_

#include <string>
#include <vector>

#include "base/atomicops.h"
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/shared_memory.h"
#include "build/build_config.h"
#include "ipc/ipc_platform_file.h"
#include "ppapi/c/pp_resource.h"
#include "ppapi/proxy/ppapi_proxy_export.h"

class Pickle;

namespace ppapi {
namespace proxy {

// SerializedHandle is a unified structure for holding a handle (e.g., a shared
// memory handle, socket descriptor, etc). This is useful for passing handles in
// resource messages and also makes it easier to translate handles in
// NaClIPCAdapter for use in NaCl.
class PPAPI_PROXY_EXPORT SerializedHandle {
 public:
  enum Type { INVALID, SHARED_MEMORY, SOCKET, FILE };
  // Header contains the fields that we send in IPC messages, apart from the
  // actual handle. See comments on the SerializedHandle fields below.
  struct Header {
    Header() : type(INVALID), size(0), open_flags(0) {}
    Header(Type type_arg,
           uint32 size_arg,
           int32 open_flags_arg,
           PP_Resource file_io_arg)
        : type(type_arg),
          size(size_arg),
          open_flags(open_flags_arg),
          file_io(file_io_arg) {
    }

    Type type;
    uint32 size;
    int32 open_flags;
    PP_Resource file_io;
  };

  SerializedHandle();
  // Create an invalid handle of the given type.
  explicit SerializedHandle(Type type);

  // Create a shared memory handle.
  SerializedHandle(const base::SharedMemoryHandle& handle, uint32 size);

  // Create a socket or file handle.
  SerializedHandle(const Type type,
                   const IPC::PlatformFileForTransit& descriptor);

  Type type() const { return type_; }
  bool is_shmem() const { return type_ == SHARED_MEMORY; }
  bool is_socket() const { return type_ == SOCKET; }
  bool is_file() const { return type_ == FILE; }
  const base::SharedMemoryHandle& shmem() const {
    DCHECK(is_shmem());
    return shm_handle_;
  }
  uint32 size() const {
    DCHECK(is_shmem());
    return size_;
  }
  const IPC::PlatformFileForTransit& descriptor() const {
    DCHECK(is_socket() || is_file());
    return descriptor_;
  }
  int32 open_flags() const {
    return open_flags_;
  }
  PP_Resource file_io() const {
    return file_io_;
  }
  void set_shmem(const base::SharedMemoryHandle& handle, uint32 size) {
    type_ = SHARED_MEMORY;
    shm_handle_ = handle;
    size_ = size;

    descriptor_ = IPC::InvalidPlatformFileForTransit();
  }
  void set_socket(const IPC::PlatformFileForTransit& socket) {
    type_ = SOCKET;
    descriptor_ = socket;

    shm_handle_ = base::SharedMemory::NULLHandle();
    size_ = 0;
  }
  void set_file_handle(const IPC::PlatformFileForTransit& descriptor,
                       int32 open_flags,
                       PP_Resource file_io) {
    type_ = FILE;

    descriptor_ = descriptor;
    shm_handle_ = base::SharedMemory::NULLHandle();
    size_ = 0;
    open_flags_ = open_flags;
    file_io_ = file_io;
  }
  void set_null_shmem() {
    set_shmem(base::SharedMemory::NULLHandle(), 0);
  }
  void set_null_socket() {
    set_socket(IPC::InvalidPlatformFileForTransit());
  }
  void set_null_file_handle() {
    set_file_handle(IPC::InvalidPlatformFileForTransit(), 0, 0);
  }
  bool IsHandleValid() const;

  Header header() const {
    return Header(type_, size_, open_flags_, file_io_);
  }

  // Closes the handle and sets it to invalid.
  void Close();

  // Write/Read a Header, which contains all the data except the handle. This
  // allows us to write the handle in a platform-specific way, as is necessary
  // in NaClIPCAdapter to share handles with NaCl from Windows.
  static bool WriteHeader(const Header& hdr, Pickle* pickle);
  static bool ReadHeader(PickleIterator* iter, Header* hdr);

 private:
  // The kind of handle we're holding.
  Type type_;

  // We hold more members than we really need; we can't easily use a union,
  // because we hold non-POD types. But these types are pretty light-weight. If
  // we add more complex things later, we should come up with a more memory-
  // efficient strategy.
  // These are valid if type == SHARED_MEMORY.
  base::SharedMemoryHandle shm_handle_;
  uint32 size_;

  // This is valid if type == SOCKET || type == FILE.
  IPC::PlatformFileForTransit descriptor_;

  // The following fields are valid if type == FILE.
  int32 open_flags_;
  // This is non-zero if file writes require quota checking.
  PP_Resource file_io_;
};

}  // namespace proxy
}  // namespace ppapi

#endif  // PPAPI_PROXY_SERIALIZED_HANDLES_H_