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
);
73 PpapiHostMsg_PPBGraphics3D_GetTransferBuffer(
74 ppapi::API_ID_PPB_GRAPHICS_3D
,
78 scoped_ptr
<IPC::Message
> new_msg_ptr
;
79 EXPECT_NE(msg
.type(), FindPendingSyncMessage(test
, msg
));
80 test
.ScanUntrustedMessage(msg
, &new_msg_ptr
);
81 EXPECT_FALSE(new_msg_ptr
);
82 EXPECT_EQ(msg
.type(), FindPendingSyncMessage(test
, msg
));
84 // TODO(bbudge) Figure out how to put together a sync reply message.
87 TEST_F(NaClMessageScannerTest
, FileOpenClose
) {
88 NaClMessageScanner test
;
89 std::vector
<SerializedHandle
> unused_handles
;
90 ResourceMessageCallParams
fio_call_params(kFileIO
, 0);
91 ResourceMessageCallParams
fs_call_params(kFileSystem
, 0);
92 ResourceMessageReplyParams
fio_reply_params(kFileIO
, 0);
93 ResourceMessageReplyParams
fs_reply_params(kFileSystem
, 0);
94 scoped_ptr
<IPC::Message
> new_msg_ptr
;
96 EXPECT_EQ(NULL
, FindFileSystem(test
, kFileSystem
));
97 EXPECT_EQ(NULL
, FindFileIO(test
, kFileIO
));
99 // Open a file, not in a quota file system.
101 PpapiPluginMsg_ResourceReply(
103 PpapiPluginMsg_FileIO_OpenReply(kInvalidResource
, 0)),
106 EXPECT_FALSE(new_msg_ptr
);
107 EXPECT_FALSE(FindFileSystem(test
, kFileSystem
));
108 EXPECT_FALSE(FindFileIO(test
, kFileIO
));
110 // Open a file in a quota file system; info objects for it and its file system
111 // should be created.
112 OpenQuotaFile(&test
, kFileIO
, kFileSystem
);
113 NaClMessageScanner::FileSystem
* fs
= FindFileSystem(test
, kFileSystem
);
114 NaClMessageScanner::FileIO
* fio
= FindFileIO(test
, kFileIO
);
116 EXPECT_EQ(0, fs
->reserved_quota());
118 EXPECT_EQ(0, fio
->max_written_offset());
120 const int64_t kNewFileSize
= 10;
121 fio
->SetMaxWrittenOffset(kNewFileSize
);
123 // We should not be able to under-report max_written_offset when closing.
124 test
.ScanUntrustedMessage(
125 PpapiHostMsg_ResourceCall(
127 PpapiHostMsg_FileIO_Close(FileGrowth(0, 0))),
129 EXPECT_TRUE(new_msg_ptr
);
130 ResourceMessageCallParams call_params
;
131 IPC::Message nested_msg
;
132 FileGrowth file_growth
;
133 EXPECT_TRUE(UnpackMessage
<PpapiHostMsg_ResourceCall
>(
134 *new_msg_ptr
, &call_params
, &nested_msg
) &&
135 UnpackMessage
<PpapiHostMsg_FileIO_Close
>(
136 nested_msg
, &file_growth
));
138 EXPECT_EQ(kNewFileSize
, file_growth
.max_written_offset
);
139 EXPECT_FALSE(FindFileIO(test
, kFileIO
));
142 OpenQuotaFile(&test
, kFileIO
, kFileSystem
);
143 fio
= FindFileIO(test
, kFileIO
);
144 fio
->SetMaxWrittenOffset(kNewFileSize
);
146 // Close with correct max_written_offset.
147 test
.ScanUntrustedMessage(
148 PpapiHostMsg_ResourceCall(
150 PpapiHostMsg_FileIO_Close(FileGrowth(kNewFileSize
, 0))),
152 EXPECT_FALSE(new_msg_ptr
);
153 EXPECT_FALSE(FindFileIO(test
, kFileIO
));
155 // Destroy file system.
156 test
.ScanUntrustedMessage(
157 PpapiHostMsg_ResourceCall(
159 PpapiHostMsg_ResourceDestroyed(kFileSystem
)),
161 EXPECT_FALSE(FindFileSystem(test
, kFileSystem
));
164 TEST_F(NaClMessageScannerTest
, QuotaAuditing
) {
165 NaClMessageScanner test
;
166 std::vector
<SerializedHandle
> unused_handles
;
167 ResourceMessageCallParams
fio_call_params(kFileIO
, 0);
168 ResourceMessageCallParams
fs_call_params(kFileSystem
, 0);
169 ResourceMessageReplyParams
fio_reply_params(kFileIO
, 0);
170 ResourceMessageReplyParams
fs_reply_params(kFileSystem
, 0);
171 scoped_ptr
<IPC::Message
> new_msg_ptr
;
173 OpenQuotaFile(&test
, kFileIO
, kFileSystem
);
174 NaClMessageScanner::FileSystem
* fs
= FindFileSystem(test
, kFileSystem
);
175 NaClMessageScanner::FileIO
* fio
= FindFileIO(test
, kFileIO
);
177 EXPECT_EQ(0, fs
->reserved_quota());
179 EXPECT_EQ(0, fio
->max_written_offset());
181 // Without reserving quota, we should not be able to grow the file.
182 EXPECT_FALSE(fio
->Grow(1));
183 EXPECT_EQ(0, fs
->reserved_quota());
184 EXPECT_EQ(0, fio
->max_written_offset());
186 // Receive reserved quota, and updated file sizes.
187 const int64_t kNewFileSize
= 10;
188 FileSizeMap file_sizes
;
189 file_sizes
[kFileIO
] = kNewFileSize
;
191 PpapiPluginMsg_ResourceReply(
193 PpapiPluginMsg_FileSystem_ReserveQuotaReply(
194 kQuotaReservationAmount
,
198 EXPECT_FALSE(new_msg_ptr
);
199 EXPECT_EQ(kQuotaReservationAmount
, fs
->reserved_quota());
200 EXPECT_EQ(kNewFileSize
, fio
->max_written_offset());
202 // We should be able to grow the file within quota.
203 EXPECT_TRUE(fio
->Grow(1));
204 EXPECT_EQ(kQuotaReservationAmount
- 1, fs
->reserved_quota());
205 EXPECT_EQ(kNewFileSize
+ 1, fio
->max_written_offset());
207 // We should not be able to grow the file over quota.
208 EXPECT_FALSE(fio
->Grow(kQuotaReservationAmount
));
209 EXPECT_EQ(kQuotaReservationAmount
- 1, fs
->reserved_quota());
210 EXPECT_EQ(kNewFileSize
+ 1, fio
->max_written_offset());
212 // Plugin should not under-report max written offsets when reserving quota.
213 file_sizes
[kFileIO
] = 0; // should be kNewFileSize + 1.
214 test
.ScanUntrustedMessage(
215 PpapiHostMsg_ResourceCall(
217 PpapiHostMsg_FileSystem_ReserveQuota(
218 kQuotaReservationAmount
,
219 FileSizeMapToFileGrowthMapForTesting(file_sizes
))),
221 EXPECT_TRUE(new_msg_ptr
);
222 ResourceMessageCallParams call_params
;
223 IPC::Message nested_msg
;
225 FileGrowthMap new_file_growths
;
226 EXPECT_TRUE(UnpackMessage
<PpapiHostMsg_ResourceCall
>(
227 *new_msg_ptr
, &call_params
, &nested_msg
) &&
228 UnpackMessage
<PpapiHostMsg_FileSystem_ReserveQuota
>(
229 nested_msg
, &amount
, &new_file_growths
));
231 EXPECT_EQ(kQuotaReservationAmount
, amount
);
232 EXPECT_EQ(kNewFileSize
+ 1, new_file_growths
[kFileIO
].max_written_offset
);
235 TEST_F(NaClMessageScannerTest
, SetLength
) {
236 NaClMessageScanner test
;
237 std::vector
<SerializedHandle
> unused_handles
;
238 ResourceMessageCallParams
fio_call_params(kFileIO
, 0);
239 ResourceMessageCallParams
fs_call_params(kFileSystem
, 0);
240 ResourceMessageReplyParams
fio_reply_params(kFileIO
, 0);
241 ResourceMessageReplyParams
fs_reply_params(kFileSystem
, 0);
242 scoped_ptr
<IPC::Message
> new_msg_ptr
;
244 OpenQuotaFile(&test
, kFileIO
, kFileSystem
);
245 NaClMessageScanner::FileSystem
* fs
= FindFileSystem(test
, kFileSystem
);
246 NaClMessageScanner::FileIO
* fio
= FindFileIO(test
, kFileIO
);
248 // Receive reserved quota, and updated file sizes.
249 const int64_t kNewFileSize
= 10;
250 FileSizeMap file_sizes
;
251 file_sizes
[kFileIO
] = 0;
253 PpapiPluginMsg_ResourceReply(
255 PpapiPluginMsg_FileSystem_ReserveQuotaReply(
256 kQuotaReservationAmount
,
261 // We should be able to SetLength within quota.
262 test
.ScanUntrustedMessage(
263 PpapiHostMsg_ResourceCall(
265 PpapiHostMsg_FileIO_SetLength(kNewFileSize
)),
267 EXPECT_FALSE(new_msg_ptr
);
268 EXPECT_EQ(kQuotaReservationAmount
- kNewFileSize
, fs
->reserved_quota());
269 EXPECT_EQ(kNewFileSize
, fio
->max_written_offset());
271 // We shouldn't be able to SetLength beyond quota. The message should be
272 // rewritten to fail with length == -1.
273 test
.ScanUntrustedMessage(
274 PpapiHostMsg_ResourceCall(
276 PpapiHostMsg_FileIO_SetLength(kQuotaReservationAmount
+ 1)),
278 EXPECT_TRUE(new_msg_ptr
);
279 ResourceMessageCallParams call_params
;
280 IPC::Message nested_msg
;
282 EXPECT_TRUE(UnpackMessage
<PpapiHostMsg_ResourceCall
>(
283 *new_msg_ptr
, &call_params
, &nested_msg
) &&
284 UnpackMessage
<PpapiHostMsg_FileIO_SetLength
>(
285 nested_msg
, &length
));
287 EXPECT_EQ(-1, length
);
288 EXPECT_EQ(kQuotaReservationAmount
- kNewFileSize
, fs
->reserved_quota());
289 EXPECT_EQ(kNewFileSize
, fio
->max_written_offset());