• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 class Pickle;
22 
23 namespace ppapi {
24 namespace 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.
30 class 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 {
HeaderHeader36     Header() : type(INVALID), size(0), open_flags(0) {}
HeaderHeader37     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 
type()64   Type type() const { return type_; }
is_shmem()65   bool is_shmem() const { return type_ == SHARED_MEMORY; }
is_socket()66   bool is_socket() const { return type_ == SOCKET; }
is_file()67   bool is_file() const { return type_ == FILE; }
shmem()68   const base::SharedMemoryHandle& shmem() const {
69     DCHECK(is_shmem());
70     return shm_handle_;
71   }
size()72   uint32 size() const {
73     DCHECK(is_shmem());
74     return size_;
75   }
descriptor()76   const IPC::PlatformFileForTransit& descriptor() const {
77     DCHECK(is_socket() || is_file());
78     return descriptor_;
79   }
open_flags()80   int32 open_flags() const {
81     return open_flags_;
82   }
file_io()83   PP_Resource file_io() const {
84     return file_io_;
85   }
set_shmem(const base::SharedMemoryHandle & handle,uint32 size)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   }
set_socket(const IPC::PlatformFileForTransit & socket)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   }
set_file_handle(const IPC::PlatformFileForTransit & descriptor,int32 open_flags,PP_Resource file_io)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   }
set_null_shmem()111   void set_null_shmem() {
112     set_shmem(base::SharedMemory::NULLHandle(), 0);
113   }
set_null_socket()114   void set_null_socket() {
115     set_socket(IPC::InvalidPlatformFileForTransit());
116   }
set_null_file_handle()117   void set_null_file_handle() {
118     set_file_handle(IPC::InvalidPlatformFileForTransit(), 0, 0);
119   }
120   bool IsHandleValid() const;
121 
header()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