// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "content/browser/browser_io_surface_manager_mac.h" #include "testing/gtest/include/gtest/gtest.h" namespace content { class BrowserIOSurfaceManagerTest : public testing::Test { public: void EnsureRunning() { io_surface_manager_.EnsureRunning(); } IOSurfaceManagerToken GenerateGpuProcessToken() { return io_surface_manager_.GenerateGpuProcessToken(); } void InvalidateGpuProcessToken() { io_surface_manager_.InvalidateGpuProcessToken(); } IOSurfaceManagerToken GenerateChildProcessToken(int child_process_id) { return io_surface_manager_.GenerateChildProcessToken(child_process_id); } void InvalidateChildProcessToken(const IOSurfaceManagerToken& token) { io_surface_manager_.InvalidateChildProcessToken(token); } bool HandleRegisterIOSurfaceRequest( const IOSurfaceManagerHostMsg_RegisterIOSurface& request, IOSurfaceManagerMsg_RegisterIOSurfaceReply* reply) { return io_surface_manager_.HandleRegisterIOSurfaceRequest(request, reply); } bool HandleUnregisterIOSurfaceRequest( const IOSurfaceManagerHostMsg_UnregisterIOSurface& request) { return io_surface_manager_.HandleUnregisterIOSurfaceRequest(request); } bool HandleAcquireIOSurfaceRequest( const IOSurfaceManagerHostMsg_AcquireIOSurface& request, IOSurfaceManagerMsg_AcquireIOSurfaceReply* reply) { return io_surface_manager_.HandleAcquireIOSurfaceRequest(request, reply); } // Helper function used to register an IOSurface for testing. void RegisterIOSurface(const IOSurfaceManagerToken& gpu_process_token, int io_surface_id, int client_id, mach_port_t io_surface_port) { IOSurfaceManagerHostMsg_RegisterIOSurface request = {{0}}; IOSurfaceManagerMsg_RegisterIOSurfaceReply reply = {{0}}; request.io_surface_id = io_surface_id; request.client_id = client_id; request.io_surface_port.name = io_surface_port; memcpy(request.token_name, gpu_process_token.name, sizeof(gpu_process_token.name)); ASSERT_TRUE(HandleRegisterIOSurfaceRequest(request, &reply)); ASSERT_TRUE(reply.result); } private: BrowserIOSurfaceManager io_surface_manager_; }; TEST_F(BrowserIOSurfaceManagerTest, EnsureRunning) { EnsureRunning(); base::mac::ScopedMachSendRight service_port = BrowserIOSurfaceManager::LookupServicePort(getpid()); EXPECT_TRUE(service_port.is_valid()); } TEST_F(BrowserIOSurfaceManagerTest, RegisterIOSurfaceSucceeds) { const int kIOSurfaceId = 1; const int kClientId = 1; IOSurfaceManagerToken gpu_process_token = GenerateGpuProcessToken(); IOSurfaceManagerHostMsg_RegisterIOSurface request = {{0}}; IOSurfaceManagerMsg_RegisterIOSurfaceReply reply = {{0}}; request.io_surface_id = kIOSurfaceId; request.client_id = kClientId; memcpy(request.token_name, gpu_process_token.name, sizeof(gpu_process_token.name)); EXPECT_TRUE(HandleRegisterIOSurfaceRequest(request, &reply)); EXPECT_TRUE(reply.result); } TEST_F(BrowserIOSurfaceManagerTest, RegisterIOSurfaceFailsWithInvalidToken) { const int kIOSurfaceId = 1; const int kClientId = 1; IOSurfaceManagerHostMsg_RegisterIOSurface request = {{0}}; IOSurfaceManagerMsg_RegisterIOSurfaceReply reply = {{0}}; request.io_surface_id = kIOSurfaceId; request.client_id = kClientId; // Fails as request doesn't contain a valid token. EXPECT_FALSE(HandleRegisterIOSurfaceRequest(request, &reply)); } TEST_F(BrowserIOSurfaceManagerTest, RegisterIOSurfaceFailsWithChildProcessToken) { const int kIOSurfaceId = 1; const int kClientId = 1; IOSurfaceManagerToken child_process_token = GenerateChildProcessToken(kClientId); IOSurfaceManagerHostMsg_RegisterIOSurface request = {{0}}; IOSurfaceManagerMsg_RegisterIOSurfaceReply reply = {{0}}; request.io_surface_id = kIOSurfaceId; request.client_id = kClientId; memcpy(request.token_name, child_process_token.name, sizeof(child_process_token.name)); // Fails as child process is not allowed to register IOSurfaces. EXPECT_FALSE(HandleRegisterIOSurfaceRequest(request, &reply)); } TEST_F(BrowserIOSurfaceManagerTest, UnregisterIOSurfaceSucceeds) { const int kIOSurfaceId = 1; const int kClientId = 1; IOSurfaceManagerToken gpu_process_token = GenerateGpuProcessToken(); RegisterIOSurface(gpu_process_token, kIOSurfaceId, kClientId, 0); IOSurfaceManagerHostMsg_UnregisterIOSurface request = {{0}}; request.io_surface_id = kIOSurfaceId; request.client_id = kClientId; memcpy(request.token_name, gpu_process_token.name, sizeof(gpu_process_token.name)); EXPECT_TRUE(HandleUnregisterIOSurfaceRequest(request)); } TEST_F(BrowserIOSurfaceManagerTest, UnregisterIOSurfaceFailsWithInvalidToken) { const int kIOSurfaceId = 1; const int kClientId = 1; IOSurfaceManagerToken gpu_process_token = GenerateGpuProcessToken(); RegisterIOSurface(gpu_process_token, kIOSurfaceId, kClientId, 0); IOSurfaceManagerHostMsg_UnregisterIOSurface request = {{0}}; request.io_surface_id = kIOSurfaceId; request.client_id = kClientId; // Fails as request doesn't contain valid GPU token. EXPECT_FALSE(HandleUnregisterIOSurfaceRequest(request)); } TEST_F(BrowserIOSurfaceManagerTest, UnregisterIOSurfaceFailsWithChildProcessToken) { const int kIOSurfaceId = 1; const int kClientId = 1; IOSurfaceManagerToken gpu_process_token = GenerateGpuProcessToken(); IOSurfaceManagerToken child_process_token = GenerateChildProcessToken(kClientId); RegisterIOSurface(gpu_process_token, kIOSurfaceId, kClientId, 0); IOSurfaceManagerHostMsg_UnregisterIOSurface request = {{0}}; request.io_surface_id = kIOSurfaceId; request.client_id = kClientId; memcpy(request.token_name, child_process_token.name, sizeof(child_process_token.name)); // Fails as child process is not allowed to unregister IOSurfaces. EXPECT_FALSE(HandleUnregisterIOSurfaceRequest(request)); } TEST_F(BrowserIOSurfaceManagerTest, AcquireIOSurfaceSucceeds) { const int kIOSurfaceId = 10; const int kClientId = 1; const mach_port_t kIOSurfacePortId = 100u; IOSurfaceManagerToken gpu_process_token = GenerateGpuProcessToken(); IOSurfaceManagerToken child_process_token = GenerateChildProcessToken(kClientId); RegisterIOSurface(gpu_process_token, kIOSurfaceId, kClientId, kIOSurfacePortId); IOSurfaceManagerHostMsg_AcquireIOSurface request = {{0}}; IOSurfaceManagerMsg_AcquireIOSurfaceReply reply = {{0}}; request.io_surface_id = kIOSurfaceId; memcpy(request.token_name, child_process_token.name, sizeof(child_process_token.name)); EXPECT_TRUE(HandleAcquireIOSurfaceRequest(request, &reply)); EXPECT_EQ(kIOSurfacePortId, reply.io_surface_port.name); } TEST_F(BrowserIOSurfaceManagerTest, AcquireIOSurfaceFailsWithInvalidToken) { const int kIOSurfaceId = 10; const int kClientId = 1; const mach_port_t kIOSurfacePortId = 100u; IOSurfaceManagerToken gpu_process_token = GenerateGpuProcessToken(); RegisterIOSurface(gpu_process_token, kIOSurfaceId, kClientId, kIOSurfacePortId); IOSurfaceManagerHostMsg_AcquireIOSurface request = {{0}}; IOSurfaceManagerMsg_AcquireIOSurfaceReply reply = {{0}}; request.io_surface_id = kIOSurfaceId; // Fails as request doesn't contain valid token. EXPECT_FALSE(HandleAcquireIOSurfaceRequest(request, &reply)); } TEST_F(BrowserIOSurfaceManagerTest, AcquireIOSurfaceFailsWithWrongChildProcessToken) { const int kIOSurfaceId = 10; const int kClientId1 = 1; const int kClientId2 = 2; const mach_port_t kIOSurfacePortId = 100u; IOSurfaceManagerToken gpu_process_token = GenerateGpuProcessToken(); IOSurfaceManagerToken child_process_token2 = GenerateChildProcessToken(kClientId2); RegisterIOSurface(gpu_process_token, kIOSurfaceId, kClientId1, kIOSurfacePortId); IOSurfaceManagerHostMsg_AcquireIOSurface request = {{0}}; IOSurfaceManagerMsg_AcquireIOSurfaceReply reply = {{0}}; request.io_surface_id = kIOSurfaceId; memcpy(request.token_name, child_process_token2.name, sizeof(child_process_token2.name)); EXPECT_TRUE(HandleAcquireIOSurfaceRequest(request, &reply)); // Fails as child process 2 is not allowed to acquire this IOSurface. EXPECT_EQ(static_cast(MACH_PORT_NULL), reply.io_surface_port.name); } TEST_F(BrowserIOSurfaceManagerTest, AcquireIOSurfaceFailsAfterInvalidatingChildProcessToken) { const int kIOSurfaceId = 10; const int kClientId = 1; const mach_port_t kIOSurfacePortId = 100u; IOSurfaceManagerToken gpu_process_token = GenerateGpuProcessToken(); IOSurfaceManagerToken child_process_token = GenerateChildProcessToken(kClientId); RegisterIOSurface(gpu_process_token, kIOSurfaceId, kClientId, kIOSurfacePortId); InvalidateChildProcessToken(child_process_token); IOSurfaceManagerHostMsg_AcquireIOSurface request = {{0}}; IOSurfaceManagerMsg_AcquireIOSurfaceReply reply = {{0}}; request.io_surface_id = kIOSurfaceId; memcpy(request.token_name, child_process_token.name, sizeof(child_process_token.name)); // Fails as token is no longer valid. EXPECT_FALSE(HandleAcquireIOSurfaceRequest(request, &reply)); } TEST_F(BrowserIOSurfaceManagerTest, AcquireIOSurfaceAfterInvalidatingGpuProcessToken) { const int kIOSurfaceId = 10; const int kClientId = 1; const mach_port_t kIOSurfacePortId = 100u; IOSurfaceManagerToken gpu_process_token = GenerateGpuProcessToken(); IOSurfaceManagerToken child_process_token = GenerateChildProcessToken(kClientId); RegisterIOSurface(gpu_process_token, kIOSurfaceId, kClientId, kIOSurfacePortId); InvalidateGpuProcessToken(); IOSurfaceManagerHostMsg_AcquireIOSurface request = {{0}}; IOSurfaceManagerMsg_AcquireIOSurfaceReply reply = {{0}}; request.io_surface_id = kIOSurfaceId; memcpy(request.token_name, child_process_token.name, sizeof(child_process_token.name)); EXPECT_TRUE(HandleAcquireIOSurfaceRequest(request, &reply)); // Should return invalid port. EXPECT_EQ(static_cast(MACH_PORT_NULL), reply.io_surface_port.name); } } // namespace content