1// Copyright (c) 2013 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#ifndef PPAPI_PROXY_SERIALIZED_HANDLES_H_
6#define PPAPI_PROXY_SERIALIZED_HANDLES_H_
7
8#include <string>
9#include <vector>
10
11#include "base/atomicops.h"
12#include "base/basictypes.h"
13#include "base/logging.h"
14#include "base/memory/ref_counted.h"
15#include "base/memory/shared_memory.h"
16#include "build/build_config.h"
17#include "ipc/ipc_platform_file.h"
18#include "ppapi/c/pp_resource.h"
19#include "ppapi/proxy/ppapi_proxy_export.h"
20
21class Pickle;
22
23namespace ppapi {
24namespace proxy {
25
26// SerializedHandle is a unified structure for holding a handle (e.g., a shared
27// memory handle, socket descriptor, etc). This is useful for passing handles in
28// resource messages and also makes it easier to translate handles in
29// NaClIPCAdapter for use in NaCl.
30class PPAPI_PROXY_EXPORT SerializedHandle {
31 public:
32  enum Type { INVALID, SHARED_MEMORY, SOCKET, FILE };
33  // Header contains the fields that we send in IPC messages, apart from the
34  // actual handle. See comments on the SerializedHandle fields below.
35  struct Header {
36    Header() : type(INVALID), size(0), open_flags(0) {}
37    Header(Type type_arg,
38           uint32 size_arg,
39           int32 open_flags_arg,
40           PP_Resource file_io_arg)
41        : type(type_arg),
42          size(size_arg),
43          open_flags(open_flags_arg),
44          file_io(file_io_arg) {
45    }
46
47    Type type;
48    uint32 size;
49    int32 open_flags;
50    PP_Resource file_io;
51  };
52
53  SerializedHandle();
54  // Create an invalid handle of the given type.
55  explicit SerializedHandle(Type type);
56
57  // Create a shared memory handle.
58  SerializedHandle(const base::SharedMemoryHandle& handle, uint32 size);
59
60  // Create a socket or file handle.
61  SerializedHandle(const Type type,
62                   const IPC::PlatformFileForTransit& descriptor);
63
64  Type type() const { return type_; }
65  bool is_shmem() const { return type_ == SHARED_MEMORY; }
66  bool is_socket() const { return type_ == SOCKET; }
67  bool is_file() const { return type_ == FILE; }
68  const base::SharedMemoryHandle& shmem() const {
69    DCHECK(is_shmem());
70    return shm_handle_;
71  }
72  uint32 size() const {
73    DCHECK(is_shmem());
74    return size_;
75  }
76  const IPC::PlatformFileForTransit& descriptor() const {
77    DCHECK(is_socket() || is_file());
78    return descriptor_;
79  }
80  int32 open_flags() const {
81    return open_flags_;
82  }
83  PP_Resource file_io() const {
84    return file_io_;
85  }
86  void set_shmem(const base::SharedMemoryHandle& handle, uint32 size) {
87    type_ = SHARED_MEMORY;
88    shm_handle_ = handle;
89    size_ = size;
90
91    descriptor_ = IPC::InvalidPlatformFileForTransit();
92  }
93  void set_socket(const IPC::PlatformFileForTransit& socket) {
94    type_ = SOCKET;
95    descriptor_ = socket;
96
97    shm_handle_ = base::SharedMemory::NULLHandle();
98    size_ = 0;
99  }
100  void set_file_handle(const IPC::PlatformFileForTransit& descriptor,
101                       int32 open_flags,
102                       PP_Resource file_io) {
103    type_ = FILE;
104
105    descriptor_ = descriptor;
106    shm_handle_ = base::SharedMemory::NULLHandle();
107    size_ = 0;
108    open_flags_ = open_flags;
109    file_io_ = file_io;
110  }
111  void set_null_shmem() {
112    set_shmem(base::SharedMemory::NULLHandle(), 0);
113  }
114  void set_null_socket() {
115    set_socket(IPC::InvalidPlatformFileForTransit());
116  }
117  void set_null_file_handle() {
118    set_file_handle(IPC::InvalidPlatformFileForTransit(), 0, 0);
119  }
120  bool IsHandleValid() const;
121
122  Header header() const {
123    return Header(type_, size_, open_flags_, file_io_);
124  }
125
126  // Closes the handle and sets it to invalid.
127  void Close();
128
129  // Write/Read a Header, which contains all the data except the handle. This
130  // allows us to write the handle in a platform-specific way, as is necessary
131  // in NaClIPCAdapter to share handles with NaCl from Windows.
132  static bool WriteHeader(const Header& hdr, Pickle* pickle);
133  static bool ReadHeader(PickleIterator* iter, Header* hdr);
134
135 private:
136  // The kind of handle we're holding.
137  Type type_;
138
139  // We hold more members than we really need; we can't easily use a union,
140  // because we hold non-POD types. But these types are pretty light-weight. If
141  // we add more complex things later, we should come up with a more memory-
142  // efficient strategy.
143  // These are valid if type == SHARED_MEMORY.
144  base::SharedMemoryHandle shm_handle_;
145  uint32 size_;
146
147  // This is valid if type == SOCKET || type == FILE.
148  IPC::PlatformFileForTransit descriptor_;
149
150  // The following fields are valid if type == FILE.
151  int32 open_flags_;
152  // This is non-zero if file writes require quota checking.
153  PP_Resource file_io_;
154};
155
156}  // namespace proxy
157}  // namespace ppapi
158
159#endif  // PPAPI_PROXY_SERIALIZED_HANDLES_H_
160