Fix build break
[chromium-blink-merge.git] / ppapi / tests / test_broker.cc
blob0537b953a29abd47a560bba602e80b5ae3f7f4d2
1 // Copyright (c) 2012 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 "ppapi/tests/test_broker.h"
7 #if defined(_MSC_VER)
8 #define OS_WIN 1
9 #include <windows.h>
10 #else
11 #define OS_POSIX 1
12 #include <errno.h>
13 #include <unistd.h>
14 #endif
16 #include <cstdio>
17 #include <cstring>
18 #include <fstream>
19 #include <limits>
21 #include "ppapi/c/pp_errors.h"
22 #include "ppapi/c/trusted/ppp_broker.h"
23 #include "ppapi/c/trusted/ppb_broker_trusted.h"
24 #include "ppapi/tests/test_utils.h"
25 #include "ppapi/tests/testing_instance.h"
27 REGISTER_TEST_CASE(Broker);
29 namespace {
31 const char kHelloMessage[] = "Hello Plugin! This is Broker!";
32 // Message sent from broker to plugin if the broker is unsandboxed.
33 const char kBrokerUnsandboxed[] = "Broker is Unsandboxed!";
34 // Message sent from broker to plugin if the broker is sandboxed. This message
35 // needs to be longer than |kBrokerUnsandboxed| because the plugin is expecting
36 // |kBrokerUnsandboxed|. If it's shorter and the broker doesn't close its handle
37 // properly the plugin will hang waiting for all data of |kBrokerUnsandboxed| to
38 // be read.
39 const char kBrokerSandboxed[] = "Broker is Sandboxed! Verification failed!";
41 #if defined(OS_WIN)
42 typedef HANDLE PlatformFile;
43 const PlatformFile kInvalidPlatformFileValue = INVALID_HANDLE_VALUE;
44 const int32_t kInvalidHandle = static_cast<int32_t>(
45 reinterpret_cast<intptr_t>(INVALID_HANDLE_VALUE));
46 #elif defined(OS_POSIX)
47 typedef int PlatformFile;
48 const PlatformFile kInvalidPlatformFileValue = -1;
49 const int32_t kInvalidHandle = -1;
50 #endif
52 PlatformFile IntToPlatformFile(int32_t handle) {
53 #if defined(OS_WIN)
54 return reinterpret_cast<HANDLE>(static_cast<intptr_t>(handle));
55 #elif defined(OS_POSIX)
56 return handle;
57 #endif
60 #if defined(OS_POSIX)
61 #define HANDLE_EINTR(x) ({ \
62 typeof(x) __eintr_result__; \
63 do { \
64 __eintr_result__ = x; \
65 } while (__eintr_result__ == -1 && errno == EINTR); \
66 __eintr_result__;\
68 #endif
70 bool ReadMessage(PlatformFile file, size_t message_len, char* message) {
71 #if defined(OS_WIN)
72 assert(message_len < std::numeric_limits<DWORD>::max());
73 DWORD read = 0;
74 const DWORD size = static_cast<DWORD>(message_len);
75 return ::ReadFile(file, message, size, &read, NULL) && read == size;
76 #elif defined(OS_POSIX)
77 assert(message_len <
78 static_cast<size_t>(std::numeric_limits<ssize_t>::max()));
79 size_t total_read = 0;
80 while (total_read < message_len) {
81 ssize_t read = HANDLE_EINTR(::read(file, message + total_read,
82 message_len - total_read));
83 if (read <= 0)
84 break;
85 total_read += read;
87 return total_read == message_len;
88 #endif
91 bool WriteMessage(PlatformFile file, size_t message_len, const char* message) {
92 #if defined(OS_WIN)
93 assert(message_len < std::numeric_limits<DWORD>::max());
94 DWORD written = 0;
95 const DWORD size = static_cast<DWORD>(message_len);
96 return ::WriteFile(file, message, size, &written, NULL) && written == size;
97 #elif defined(OS_POSIX)
98 assert(message_len <
99 static_cast<size_t>(std::numeric_limits<ssize_t>::max()));
100 size_t total_written = 0;
101 while (total_written < message_len) {
102 ssize_t written = HANDLE_EINTR(::write(file, message + total_written,
103 message_len - total_written));
104 if (written <= 0)
105 break;
106 total_written += written;
108 return total_written == message_len;
109 #endif
112 bool VerifyMessage(PlatformFile file, size_t message_len, const char* message) {
113 char* message_received = new char[message_len];
114 bool success = ReadMessage(file, message_len, message_received) &&
115 !::strcmp(message_received, message);
116 delete [] message_received;
117 return success;
120 bool ClosePlatformFile(PlatformFile file) {
121 #if defined(OS_WIN)
122 return !!::CloseHandle(file);
123 #elif defined(OS_POSIX)
124 return !HANDLE_EINTR(::close(file));
125 #endif
128 bool VerifyIsUnsandboxed() {
129 #if defined(OS_WIN)
130 FILE* file = NULL;
131 wchar_t temp_path[MAX_PATH] = {'\0'};
132 wchar_t file_name[MAX_PATH] = {'\0'};
133 if (!::GetTempPath(MAX_PATH, temp_path) ||
134 !::GetTempFileName(temp_path, L"test_pepper_broker", 0, file_name) ||
135 ::_wfopen_s(&file, file_name, L"w"))
136 return false;
138 if (::fclose(file)) {
139 ::DeleteFile(file_name);
140 return false;
143 return !!::DeleteFile(file_name);
144 #elif defined(OS_POSIX)
145 char file_name[] = "/tmp/test_pepper_broker_XXXXXX";
146 int fd = ::mkstemp(file_name);
147 if (-1 == fd)
148 return false;
150 if (HANDLE_EINTR(::close(fd))) {
151 ::remove(file_name);
152 return false;
155 return !::remove(file_name);
156 #endif
159 // Callback in the broker when a new broker connection occurs.
160 int32_t OnInstanceConnected(PP_Instance instance, int32_t handle) {
161 PlatformFile file = IntToPlatformFile(handle);
162 if (file == kInvalidPlatformFileValue)
163 return PP_ERROR_FAILED;
165 // Send hello message.
166 if (!WriteMessage(file, sizeof(kHelloMessage), kHelloMessage)) {
167 ClosePlatformFile(file);
168 return PP_ERROR_FAILED;
171 // Verify broker is not sandboxed and send result to plugin over the pipe.
172 if (VerifyIsUnsandboxed()) {
173 if (!WriteMessage(file, sizeof(kBrokerUnsandboxed), kBrokerUnsandboxed)) {
174 ClosePlatformFile(file);
175 return PP_ERROR_FAILED;
177 } else {
178 if (!WriteMessage(file, sizeof(kBrokerSandboxed), kBrokerSandboxed)) {
179 ClosePlatformFile(file);
180 return PP_ERROR_FAILED;
184 if (!ClosePlatformFile(file))
185 return PP_ERROR_FAILED;
187 return PP_OK;
190 } // namespace
192 PP_EXPORT int32_t PPP_InitializeBroker(
193 PP_ConnectInstance_Func* connect_instance_func) {
194 *connect_instance_func = &OnInstanceConnected;
195 return PP_OK;
198 PP_EXPORT void PPP_ShutdownBroker() {}
200 TestBroker::TestBroker(TestingInstance* instance)
201 : TestCase(instance),
202 broker_interface_(NULL) {
205 bool TestBroker::Init() {
206 broker_interface_ = static_cast<const PPB_BrokerTrusted*>(
207 pp::Module::Get()->GetBrowserInterface(PPB_BROKER_TRUSTED_INTERFACE));
208 return !!broker_interface_;
211 void TestBroker::RunTests(const std::string& filter) {
212 RUN_TEST(Create, filter);
213 RUN_TEST(Create, filter);
214 RUN_TEST(GetHandleFailure, filter);
215 RUN_TEST_FORCEASYNC_AND_NOT(ConnectFailure, filter);
216 RUN_TEST_FORCEASYNC_AND_NOT(ConnectAndPipe, filter);
218 // The following tests require special setup, so only run them if they're
219 // explicitly specified by the filter.
220 if (!ShouldRunAllTests(filter)) {
221 RUN_TEST(ConnectPermissionDenied, filter);
222 RUN_TEST(ConnectPermissionGranted, filter);
223 RUN_TEST(IsAllowedPermissionDenied, filter);
224 RUN_TEST(IsAllowedPermissionGranted, filter);
228 std::string TestBroker::TestCreate() {
229 // Very simplistic test to make sure we can create a broker interface.
230 // TODO(raymes): All of the resources created in this file are leaked. Write
231 // a C++ wrapper for PPB_Broker_Trusted to avoid these leaks.
232 PP_Resource broker = broker_interface_->CreateTrusted(
233 instance_->pp_instance());
234 ASSERT_TRUE(broker);
236 ASSERT_FALSE(broker_interface_->IsBrokerTrusted(0));
237 ASSERT_TRUE(broker_interface_->IsBrokerTrusted(broker));
239 PASS();
242 // Test connection on invalid resource.
243 std::string TestBroker::TestConnectFailure() {
244 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
245 callback.WaitForResult(broker_interface_->Connect(0,
246 callback.GetCallback().pp_completion_callback()));
247 CHECK_CALLBACK_BEHAVIOR(callback);
248 ASSERT_EQ(PP_ERROR_BADRESOURCE, callback.result());
250 PASS();
253 std::string TestBroker::TestGetHandleFailure() {
254 int32_t handle = kInvalidHandle;
256 // Test getting the handle for an invalid resource.
257 ASSERT_EQ(PP_ERROR_BADRESOURCE, broker_interface_->GetHandle(0, &handle));
259 // Connect hasn't been called so this should fail.
260 PP_Resource broker = broker_interface_->CreateTrusted(
261 instance_->pp_instance());
262 ASSERT_TRUE(broker);
263 ASSERT_EQ(PP_ERROR_FAILED, broker_interface_->GetHandle(broker, &handle));
265 PASS();
268 std::string TestBroker::TestConnectAndPipe() {
269 PP_Resource broker = broker_interface_->CreateTrusted(
270 instance_->pp_instance());
271 ASSERT_TRUE(broker);
273 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
274 callback.WaitForResult(broker_interface_->Connect(broker,
275 callback.GetCallback().pp_completion_callback()));
276 CHECK_CALLBACK_BEHAVIOR(callback);
277 ASSERT_EQ(PP_OK, callback.result());
279 int32_t handle = kInvalidHandle;
280 ASSERT_EQ(PP_OK, broker_interface_->GetHandle(broker, &handle));
281 ASSERT_NE(kInvalidHandle, handle);
283 PlatformFile file = IntToPlatformFile(handle);
284 ASSERT_TRUE(VerifyMessage(file, sizeof(kHelloMessage), kHelloMessage));
285 ASSERT_TRUE(VerifyMessage(file, sizeof(kBrokerUnsandboxed),
286 kBrokerUnsandboxed));
288 ASSERT_TRUE(ClosePlatformFile(file));
290 PASS();
293 std::string TestBroker::TestConnectPermissionDenied() {
294 // This assumes that the browser side is set up to deny access to the broker.
295 PP_Resource broker = broker_interface_->CreateTrusted(
296 instance_->pp_instance());
297 ASSERT_TRUE(broker);
299 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
300 callback.WaitForResult(broker_interface_->Connect(broker,
301 callback.GetCallback().pp_completion_callback()));
302 CHECK_CALLBACK_BEHAVIOR(callback);
303 ASSERT_EQ(PP_ERROR_NOACCESS, callback.result());
305 PASS();
308 std::string TestBroker::TestConnectPermissionGranted() {
309 // This assumes that the browser side is set up to allow access to the broker.
310 PP_Resource broker = broker_interface_->CreateTrusted(
311 instance_->pp_instance());
312 ASSERT_TRUE(broker);
314 TestCompletionCallback callback(instance_->pp_instance(), callback_type());
315 callback.WaitForResult(broker_interface_->Connect(broker,
316 callback.GetCallback().pp_completion_callback()));
317 CHECK_CALLBACK_BEHAVIOR(callback);
318 ASSERT_EQ(PP_OK, callback.result());
320 PASS();
323 std::string TestBroker::TestIsAllowedPermissionDenied() {
324 PP_Resource broker = broker_interface_->CreateTrusted(
325 instance_->pp_instance());
326 ASSERT_TRUE(broker);
327 ASSERT_EQ(PP_FALSE, broker_interface_->IsAllowed(broker));
329 PASS();
332 std::string TestBroker::TestIsAllowedPermissionGranted() {
333 PP_Resource broker = broker_interface_->CreateTrusted(
334 instance_->pp_instance());
335 ASSERT_TRUE(broker);
336 ASSERT_EQ(PP_TRUE, broker_interface_->IsAllowed(broker));
338 PASS();