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 NaClMessageScanner::FileSystem
* FindFileSystem(
27 const NaClMessageScanner
& scanner
,
28 PP_Resource file_system
) {
29 NaClMessageScanner::FileSystemMap::const_iterator it
=
30 scanner
.file_systems_
.find(file_system
);
31 return (it
!= scanner
.file_systems_
.end()) ? it
->second
: NULL
;
34 NaClMessageScanner::FileIO
* FindFileIO(
35 const NaClMessageScanner
& scanner
,
36 PP_Resource file_io
) {
37 NaClMessageScanner::FileIOMap::const_iterator it
=
38 scanner
.files_
.find(file_io
);
39 return (it
!= scanner
.files_
.end()) ? it
->second
: NULL
;
42 void OpenQuotaFile(NaClMessageScanner
* scanner
,
44 PP_Resource file_system
) {
45 std::vector
<SerializedHandle
> unused_handles
;
46 ResourceMessageReplyParams
fio_reply_params(file_io
, 0);
47 scoped_ptr
<IPC::Message
> new_msg_ptr
;
49 PpapiPluginMsg_ResourceReply(
51 PpapiPluginMsg_FileIO_OpenReply(file_system
, 0)),
52 PpapiPluginMsg_ResourceReply::ID
,
55 EXPECT_FALSE(new_msg_ptr
);
59 TEST_F(NaClMessageScannerTest
, FileOpenClose
) {
60 NaClMessageScanner test
;
61 std::vector
<SerializedHandle
> unused_handles
;
62 ResourceMessageCallParams
fio_call_params(kFileIO
, 0);
63 ResourceMessageCallParams
fs_call_params(kFileSystem
, 0);
64 ResourceMessageReplyParams
fio_reply_params(kFileIO
, 0);
65 ResourceMessageReplyParams
fs_reply_params(kFileSystem
, 0);
66 scoped_ptr
<IPC::Message
> new_msg_ptr
;
68 EXPECT_EQ(NULL
, FindFileSystem(test
, kFileSystem
));
69 EXPECT_EQ(NULL
, FindFileIO(test
, kFileIO
));
71 // Open a file, not in a quota file system.
73 PpapiPluginMsg_ResourceReply(
75 PpapiPluginMsg_FileIO_OpenReply(kInvalidResource
, 0)),
76 PpapiPluginMsg_ResourceReply::ID
,
79 EXPECT_FALSE(new_msg_ptr
);
80 EXPECT_FALSE(FindFileSystem(test
, kFileSystem
));
81 EXPECT_FALSE(FindFileIO(test
, kFileIO
));
83 // Open a file in a quota file system; info objects for it and its file system
85 OpenQuotaFile(&test
, kFileIO
, kFileSystem
);
86 NaClMessageScanner::FileSystem
* fs
= FindFileSystem(test
, kFileSystem
);
87 NaClMessageScanner::FileIO
* fio
= FindFileIO(test
, kFileIO
);
89 EXPECT_EQ(0, fs
->reserved_quota());
91 EXPECT_EQ(0, fio
->max_written_offset());
93 const int64_t kNewFileSize
= 10;
94 fio
->SetMaxWrittenOffset(kNewFileSize
);
96 // We should not be able to under-report max_written_offset when closing.
97 test
.ScanUntrustedMessage(
98 PpapiHostMsg_ResourceCall(
100 PpapiHostMsg_FileIO_Close(FileGrowth(0, 0))),
102 EXPECT_TRUE(new_msg_ptr
);
103 ResourceMessageCallParams call_params
;
104 IPC::Message nested_msg
;
105 FileGrowth file_growth
;
106 EXPECT_TRUE(UnpackMessage
<PpapiHostMsg_ResourceCall
>(
107 *new_msg_ptr
, &call_params
, &nested_msg
) &&
108 UnpackMessage
<PpapiHostMsg_FileIO_Close
>(
109 nested_msg
, &file_growth
));
111 EXPECT_EQ(kNewFileSize
, file_growth
.max_written_offset
);
112 EXPECT_FALSE(FindFileIO(test
, kFileIO
));
115 OpenQuotaFile(&test
, kFileIO
, kFileSystem
);
116 fio
= FindFileIO(test
, kFileIO
);
117 fio
->SetMaxWrittenOffset(kNewFileSize
);
119 // Close with correct max_written_offset.
120 test
.ScanUntrustedMessage(
121 PpapiHostMsg_ResourceCall(
123 PpapiHostMsg_FileIO_Close(FileGrowth(kNewFileSize
, 0))),
125 EXPECT_FALSE(new_msg_ptr
);
126 EXPECT_FALSE(FindFileIO(test
, kFileIO
));
128 // Destroy file system.
129 test
.ScanUntrustedMessage(
130 PpapiHostMsg_ResourceCall(
132 PpapiHostMsg_ResourceDestroyed(kFileSystem
)),
134 EXPECT_FALSE(FindFileSystem(test
, kFileSystem
));
137 TEST_F(NaClMessageScannerTest
, QuotaAuditing
) {
138 NaClMessageScanner test
;
139 std::vector
<SerializedHandle
> unused_handles
;
140 ResourceMessageCallParams
fio_call_params(kFileIO
, 0);
141 ResourceMessageCallParams
fs_call_params(kFileSystem
, 0);
142 ResourceMessageReplyParams
fio_reply_params(kFileIO
, 0);
143 ResourceMessageReplyParams
fs_reply_params(kFileSystem
, 0);
144 scoped_ptr
<IPC::Message
> new_msg_ptr
;
146 OpenQuotaFile(&test
, kFileIO
, kFileSystem
);
147 NaClMessageScanner::FileSystem
* fs
= FindFileSystem(test
, kFileSystem
);
148 NaClMessageScanner::FileIO
* fio
= FindFileIO(test
, kFileIO
);
150 EXPECT_EQ(0, fs
->reserved_quota());
152 EXPECT_EQ(0, fio
->max_written_offset());
154 // Without reserving quota, we should not be able to grow the file.
155 EXPECT_FALSE(fio
->Grow(1));
156 EXPECT_EQ(0, fs
->reserved_quota());
157 EXPECT_EQ(0, fio
->max_written_offset());
159 // Receive reserved quota, and updated file sizes.
160 const int64_t kNewFileSize
= 10;
161 FileSizeMap file_sizes
;
162 file_sizes
[kFileIO
] = kNewFileSize
;
164 PpapiPluginMsg_ResourceReply(
166 PpapiPluginMsg_FileSystem_ReserveQuotaReply(
167 kQuotaReservationAmount
,
169 PpapiPluginMsg_ResourceReply::ID
,
172 EXPECT_FALSE(new_msg_ptr
);
173 EXPECT_EQ(kQuotaReservationAmount
, fs
->reserved_quota());
174 EXPECT_EQ(kNewFileSize
, fio
->max_written_offset());
176 // We should be able to grow the file within quota.
177 EXPECT_TRUE(fio
->Grow(1));
178 EXPECT_EQ(kQuotaReservationAmount
- 1, fs
->reserved_quota());
179 EXPECT_EQ(kNewFileSize
+ 1, fio
->max_written_offset());
181 // We should not be able to grow the file over quota.
182 EXPECT_FALSE(fio
->Grow(kQuotaReservationAmount
));
183 EXPECT_EQ(kQuotaReservationAmount
- 1, fs
->reserved_quota());
184 EXPECT_EQ(kNewFileSize
+ 1, fio
->max_written_offset());
186 // Plugin should not under-report max written offsets when reserving quota.
187 file_sizes
[kFileIO
] = 0; // should be kNewFileSize + 1.
188 test
.ScanUntrustedMessage(
189 PpapiHostMsg_ResourceCall(
191 PpapiHostMsg_FileSystem_ReserveQuota(
192 kQuotaReservationAmount
,
193 FileSizeMapToFileGrowthMapForTesting(file_sizes
))),
195 EXPECT_TRUE(new_msg_ptr
);
196 ResourceMessageCallParams call_params
;
197 IPC::Message nested_msg
;
199 FileGrowthMap new_file_growths
;
200 EXPECT_TRUE(UnpackMessage
<PpapiHostMsg_ResourceCall
>(
201 *new_msg_ptr
, &call_params
, &nested_msg
) &&
202 UnpackMessage
<PpapiHostMsg_FileSystem_ReserveQuota
>(
203 nested_msg
, &amount
, &new_file_growths
));
205 EXPECT_EQ(kQuotaReservationAmount
, amount
);
206 EXPECT_EQ(kNewFileSize
+ 1, new_file_growths
[kFileIO
].max_written_offset
);
209 TEST_F(NaClMessageScannerTest
, SetLength
) {
210 NaClMessageScanner test
;
211 std::vector
<SerializedHandle
> unused_handles
;
212 ResourceMessageCallParams
fio_call_params(kFileIO
, 0);
213 ResourceMessageCallParams
fs_call_params(kFileSystem
, 0);
214 ResourceMessageReplyParams
fio_reply_params(kFileIO
, 0);
215 ResourceMessageReplyParams
fs_reply_params(kFileSystem
, 0);
216 scoped_ptr
<IPC::Message
> new_msg_ptr
;
218 OpenQuotaFile(&test
, kFileIO
, kFileSystem
);
219 NaClMessageScanner::FileSystem
* fs
= FindFileSystem(test
, kFileSystem
);
220 NaClMessageScanner::FileIO
* fio
= FindFileIO(test
, kFileIO
);
222 // Receive reserved quota, and updated file sizes.
223 const int64_t kNewFileSize
= 10;
224 FileSizeMap file_sizes
;
225 file_sizes
[kFileIO
] = 0;
227 PpapiPluginMsg_ResourceReply(
229 PpapiPluginMsg_FileSystem_ReserveQuotaReply(
230 kQuotaReservationAmount
,
232 PpapiPluginMsg_ResourceReply::ID
,
236 // We should be able to SetLength within quota.
237 test
.ScanUntrustedMessage(
238 PpapiHostMsg_ResourceCall(
240 PpapiHostMsg_FileIO_SetLength(kNewFileSize
)),
242 EXPECT_FALSE(new_msg_ptr
);
243 EXPECT_EQ(kQuotaReservationAmount
- kNewFileSize
, fs
->reserved_quota());
244 EXPECT_EQ(kNewFileSize
, fio
->max_written_offset());
246 // We shouldn't be able to SetLength beyond quota. The message should be
247 // rewritten to fail with length == -1.
248 test
.ScanUntrustedMessage(
249 PpapiHostMsg_ResourceCall(
251 PpapiHostMsg_FileIO_SetLength(kQuotaReservationAmount
+ 1)),
253 EXPECT_TRUE(new_msg_ptr
);
254 ResourceMessageCallParams call_params
;
255 IPC::Message nested_msg
;
257 EXPECT_TRUE(UnpackMessage
<PpapiHostMsg_ResourceCall
>(
258 *new_msg_ptr
, &call_params
, &nested_msg
) &&
259 UnpackMessage
<PpapiHostMsg_FileIO_SetLength
>(
260 nested_msg
, &length
));
262 EXPECT_EQ(-1, length
);
263 EXPECT_EQ(kQuotaReservationAmount
- kNewFileSize
, fs
->reserved_quota());
264 EXPECT_EQ(kNewFileSize
, fio
->max_written_offset());