1 // Copyright 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.
5 #include "ipc/ipc_message.h"
6 #include "ppapi/proxy/nacl_message_scanner.h"
7 #include "ppapi/proxy/ppapi_messages.h"
8 #include "ppapi/proxy/ppapi_proxy_test.h"
9 #include "ppapi/proxy/serialized_handle.h"
10 #include "ppapi/shared_impl/host_resource.h"
16 const PP_Resource kInvalidResource
= 0;
17 const PP_Resource kFileSystem
= 1;
18 const PP_Resource kFileIO
= 2;
19 const int64_t kQuotaReservationAmount
= 100;
22 class NaClMessageScannerTest
: public PluginProxyTest
{
24 NaClMessageScannerTest() {}
26 uint32
FindPendingSyncMessage(
27 const NaClMessageScanner
& scanner
,
28 const IPC::Message
& msg
) {
29 int msg_id
= IPC::SyncMessage::GetMessageId(msg
);
30 std::map
<int, uint32
>::const_iterator it
=
31 scanner
.pending_sync_msgs_
.find(msg_id
);
32 // O can signal that no message was found.
33 return (it
!= scanner
.pending_sync_msgs_
.end()) ? it
->second
: 0;
36 NaClMessageScanner::FileSystem
* FindFileSystem(
37 const NaClMessageScanner
& scanner
,
38 PP_Resource file_system
) {
39 NaClMessageScanner::FileSystemMap::const_iterator it
=
40 scanner
.file_systems_
.find(file_system
);
41 return (it
!= scanner
.file_systems_
.end()) ? it
->second
: NULL
;
44 NaClMessageScanner::FileIO
* FindFileIO(
45 const NaClMessageScanner
& scanner
,
46 PP_Resource file_io
) {
47 NaClMessageScanner::FileIOMap::const_iterator it
=
48 scanner
.files_
.find(file_io
);
49 return (it
!= scanner
.files_
.end()) ? it
->second
: NULL
;
52 void OpenQuotaFile(NaClMessageScanner
* scanner
,
54 PP_Resource file_system
) {
55 std::vector
<SerializedHandle
> unused_handles
;
56 ResourceMessageReplyParams
fio_reply_params(file_io
, 0);
57 scoped_ptr
<IPC::Message
> new_msg_ptr
;
59 PpapiPluginMsg_ResourceReply(
61 PpapiPluginMsg_FileIO_OpenReply(file_system
, 0)),
64 EXPECT_FALSE(new_msg_ptr
);
68 TEST_F(NaClMessageScannerTest
, SyncMessageAndReply
) {
69 NaClMessageScanner test
;
70 ppapi::proxy::SerializedHandle
handle(
71 ppapi::proxy::SerializedHandle::SHARED_MEMORY
);
74 PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer(
75 ppapi::API_ID_PPB_GRAPHICS_3D
,
80 scoped_ptr
<IPC::Message
> new_msg_ptr
;
81 EXPECT_NE(msg
.type(), FindPendingSyncMessage(test
, msg
));
82 test
.ScanUntrustedMessage(msg
, &new_msg_ptr
);
83 EXPECT_FALSE(new_msg_ptr
);
84 EXPECT_EQ(msg
.type(), FindPendingSyncMessage(test
, msg
));
86 // TODO(bbudge) Figure out how to put together a sync reply message.
89 TEST_F(NaClMessageScannerTest
, FileOpenClose
) {
90 NaClMessageScanner test
;
91 std::vector
<SerializedHandle
> unused_handles
;
92 ResourceMessageCallParams
fio_call_params(kFileIO
, 0);
93 ResourceMessageCallParams
fs_call_params(kFileSystem
, 0);
94 ResourceMessageReplyParams
fio_reply_params(kFileIO
, 0);
95 ResourceMessageReplyParams
fs_reply_params(kFileSystem
, 0);
96 scoped_ptr
<IPC::Message
> new_msg_ptr
;
98 EXPECT_EQ(NULL
, FindFileSystem(test
, kFileSystem
));
99 EXPECT_EQ(NULL
, FindFileIO(test
, kFileIO
));
101 // Open a file, not in a quota file system.
103 PpapiPluginMsg_ResourceReply(
105 PpapiPluginMsg_FileIO_OpenReply(kInvalidResource
, 0)),
108 EXPECT_FALSE(new_msg_ptr
);
109 EXPECT_FALSE(FindFileSystem(test
, kFileSystem
));
110 EXPECT_FALSE(FindFileIO(test
, kFileIO
));
112 // Open a file in a quota file system; info objects for it and its file system
113 // should be created.
114 OpenQuotaFile(&test
, kFileIO
, kFileSystem
);
115 NaClMessageScanner::FileSystem
* fs
= FindFileSystem(test
, kFileSystem
);
116 NaClMessageScanner::FileIO
* fio
= FindFileIO(test
, kFileIO
);
118 EXPECT_EQ(0, fs
->reserved_quota());
120 EXPECT_EQ(0, fio
->max_written_offset());
122 const int64_t kNewFileSize
= 10;
123 fio
->SetMaxWrittenOffset(kNewFileSize
);
125 // We should not be able to under-report max_written_offset when closing.
126 test
.ScanUntrustedMessage(
127 PpapiHostMsg_ResourceCall(
129 PpapiHostMsg_FileIO_Close(FileGrowth(0, 0))),
131 EXPECT_TRUE(new_msg_ptr
);
132 ResourceMessageCallParams call_params
;
133 IPC::Message nested_msg
;
134 FileGrowth file_growth
;
135 EXPECT_TRUE(UnpackMessage
<PpapiHostMsg_ResourceCall
>(
136 *new_msg_ptr
, &call_params
, &nested_msg
) &&
137 UnpackMessage
<PpapiHostMsg_FileIO_Close
>(
138 nested_msg
, &file_growth
));
140 EXPECT_EQ(kNewFileSize
, file_growth
.max_written_offset
);
141 EXPECT_FALSE(FindFileIO(test
, kFileIO
));
144 OpenQuotaFile(&test
, kFileIO
, kFileSystem
);
145 fio
= FindFileIO(test
, kFileIO
);
146 fio
->SetMaxWrittenOffset(kNewFileSize
);
148 // Close with correct max_written_offset.
149 test
.ScanUntrustedMessage(
150 PpapiHostMsg_ResourceCall(
152 PpapiHostMsg_FileIO_Close(FileGrowth(kNewFileSize
, 0))),
154 EXPECT_FALSE(new_msg_ptr
);
155 EXPECT_FALSE(FindFileIO(test
, kFileIO
));
157 // Destroy file system.
158 test
.ScanUntrustedMessage(
159 PpapiHostMsg_ResourceCall(
161 PpapiHostMsg_ResourceDestroyed(kFileSystem
)),
163 EXPECT_FALSE(FindFileSystem(test
, kFileSystem
));
166 TEST_F(NaClMessageScannerTest
, QuotaAuditing
) {
167 NaClMessageScanner test
;
168 std::vector
<SerializedHandle
> unused_handles
;
169 ResourceMessageCallParams
fio_call_params(kFileIO
, 0);
170 ResourceMessageCallParams
fs_call_params(kFileSystem
, 0);
171 ResourceMessageReplyParams
fio_reply_params(kFileIO
, 0);
172 ResourceMessageReplyParams
fs_reply_params(kFileSystem
, 0);
173 scoped_ptr
<IPC::Message
> new_msg_ptr
;
175 OpenQuotaFile(&test
, kFileIO
, kFileSystem
);
176 NaClMessageScanner::FileSystem
* fs
= FindFileSystem(test
, kFileSystem
);
177 NaClMessageScanner::FileIO
* fio
= FindFileIO(test
, kFileIO
);
179 EXPECT_EQ(0, fs
->reserved_quota());
181 EXPECT_EQ(0, fio
->max_written_offset());
183 // Without reserving quota, we should not be able to grow the file.
184 EXPECT_FALSE(fio
->Grow(1));
185 EXPECT_EQ(0, fs
->reserved_quota());
186 EXPECT_EQ(0, fio
->max_written_offset());
188 // Receive reserved quota, and updated file sizes.
189 const int64_t kNewFileSize
= 10;
190 FileSizeMap file_sizes
;
191 file_sizes
[kFileIO
] = kNewFileSize
;
193 PpapiPluginMsg_ResourceReply(
195 PpapiPluginMsg_FileSystem_ReserveQuotaReply(
196 kQuotaReservationAmount
,
200 EXPECT_FALSE(new_msg_ptr
);
201 EXPECT_EQ(kQuotaReservationAmount
, fs
->reserved_quota());
202 EXPECT_EQ(kNewFileSize
, fio
->max_written_offset());
204 // We should be able to grow the file within quota.
205 EXPECT_TRUE(fio
->Grow(1));
206 EXPECT_EQ(kQuotaReservationAmount
- 1, fs
->reserved_quota());
207 EXPECT_EQ(kNewFileSize
+ 1, fio
->max_written_offset());
209 // We should not be able to grow the file over quota.
210 EXPECT_FALSE(fio
->Grow(kQuotaReservationAmount
));
211 EXPECT_EQ(kQuotaReservationAmount
- 1, fs
->reserved_quota());
212 EXPECT_EQ(kNewFileSize
+ 1, fio
->max_written_offset());
214 // Plugin should not under-report max written offsets when reserving quota.
215 file_sizes
[kFileIO
] = 0; // should be kNewFileSize + 1.
216 test
.ScanUntrustedMessage(
217 PpapiHostMsg_ResourceCall(
219 PpapiHostMsg_FileSystem_ReserveQuota(
220 kQuotaReservationAmount
,
221 FileSizeMapToFileGrowthMapForTesting(file_sizes
))),
223 EXPECT_TRUE(new_msg_ptr
);
224 ResourceMessageCallParams call_params
;
225 IPC::Message nested_msg
;
227 FileGrowthMap new_file_growths
;
228 EXPECT_TRUE(UnpackMessage
<PpapiHostMsg_ResourceCall
>(
229 *new_msg_ptr
, &call_params
, &nested_msg
) &&
230 UnpackMessage
<PpapiHostMsg_FileSystem_ReserveQuota
>(
231 nested_msg
, &amount
, &new_file_growths
));
233 EXPECT_EQ(kQuotaReservationAmount
, amount
);
234 EXPECT_EQ(kNewFileSize
+ 1, new_file_growths
[kFileIO
].max_written_offset
);
237 TEST_F(NaClMessageScannerTest
, SetLength
) {
238 NaClMessageScanner test
;
239 std::vector
<SerializedHandle
> unused_handles
;
240 ResourceMessageCallParams
fio_call_params(kFileIO
, 0);
241 ResourceMessageCallParams
fs_call_params(kFileSystem
, 0);
242 ResourceMessageReplyParams
fio_reply_params(kFileIO
, 0);
243 ResourceMessageReplyParams
fs_reply_params(kFileSystem
, 0);
244 scoped_ptr
<IPC::Message
> new_msg_ptr
;
246 OpenQuotaFile(&test
, kFileIO
, kFileSystem
);
247 NaClMessageScanner::FileSystem
* fs
= FindFileSystem(test
, kFileSystem
);
248 NaClMessageScanner::FileIO
* fio
= FindFileIO(test
, kFileIO
);
250 // Receive reserved quota, and updated file sizes.
251 const int64_t kNewFileSize
= 10;
252 FileSizeMap file_sizes
;
253 file_sizes
[kFileIO
] = 0;
255 PpapiPluginMsg_ResourceReply(
257 PpapiPluginMsg_FileSystem_ReserveQuotaReply(
258 kQuotaReservationAmount
,
263 // We should be able to SetLength within quota.
264 test
.ScanUntrustedMessage(
265 PpapiHostMsg_ResourceCall(
267 PpapiHostMsg_FileIO_SetLength(kNewFileSize
)),
269 EXPECT_FALSE(new_msg_ptr
);
270 EXPECT_EQ(kQuotaReservationAmount
- kNewFileSize
, fs
->reserved_quota());
271 EXPECT_EQ(kNewFileSize
, fio
->max_written_offset());
273 // We shouldn't be able to SetLength beyond quota. The message should be
274 // rewritten to fail with length == -1.
275 test
.ScanUntrustedMessage(
276 PpapiHostMsg_ResourceCall(
278 PpapiHostMsg_FileIO_SetLength(kQuotaReservationAmount
+ 1)),
280 EXPECT_TRUE(new_msg_ptr
);
281 ResourceMessageCallParams call_params
;
282 IPC::Message nested_msg
;
284 EXPECT_TRUE(UnpackMessage
<PpapiHostMsg_ResourceCall
>(
285 *new_msg_ptr
, &call_params
, &nested_msg
) &&
286 UnpackMessage
<PpapiHostMsg_FileIO_SetLength
>(
287 nested_msg
, &length
));
289 EXPECT_EQ(-1, length
);
290 EXPECT_EQ(kQuotaReservationAmount
- kNewFileSize
, fs
->reserved_quota());
291 EXPECT_EQ(kNewFileSize
, fio
->max_written_offset());