implement Milestone 11: Camera interface with permission and user gesture requirements

This commit is contained in:
2026-01-18 15:38:58 +01:00
parent 0c19247838
commit 5eb1113c1a
7 changed files with 1492 additions and 11 deletions

View File

@@ -14,6 +14,7 @@
#include "http_validator.h"
#include "network_manager.h"
#include "websocket_manager.h"
#include "camera_interface.h"
#include <filesystem>
#include <fstream>
#include <sstream>
@@ -1839,6 +1840,173 @@ bool Test_WebSocketLuaIntegration(std::string& error_msg) {
return true;
}
//=============================================================================
// MILESTONE 11: Camera
//=============================================================================
bool Test_CameraRequiresPermission(std::string& error_msg) {
// Create sandbox context WITHOUT camera permission
SandboxContext ctx;
ctx.app_id = "test.app";
ctx.permissions = {}; // No camera permission declared
ctx.is_system_app = false;
PermissionGate permissions(ctx);
mosis::CameraInterface camera("test.app", &permissions);
camera.SimulateUserGesture();
std::string err;
mosis::CameraConfig config;
auto session = camera.StartSession(config, err);
EXPECT_TRUE(session == nullptr);
EXPECT_TRUE(err.find("permission") != std::string::npos);
return true;
}
bool Test_CameraRequiresUserGesture(std::string& error_msg) {
// Create sandbox context WITH camera permission
SandboxContext ctx;
ctx.app_id = "test.app";
ctx.permissions = {"camera"};
ctx.is_system_app = false;
PermissionGate permissions(ctx);
permissions.GrantPermission("camera");
mosis::CameraInterface camera("test.app", &permissions);
// Note: NOT calling SimulateUserGesture()
std::string err;
mosis::CameraConfig config;
auto session = camera.StartSession(config, err);
EXPECT_TRUE(session == nullptr);
EXPECT_TRUE(err.find("gesture") != std::string::npos);
return true;
}
bool Test_CameraShowsIndicator(std::string& error_msg) {
SandboxContext ctx;
ctx.app_id = "test.app";
ctx.permissions = {"camera"};
ctx.is_system_app = false;
PermissionGate permissions(ctx);
permissions.GrantPermission("camera");
mosis::CameraInterface camera("test.app", &permissions);
camera.SimulateUserGesture();
EXPECT_FALSE(camera.IsIndicatorVisible());
std::string err;
mosis::CameraConfig config;
auto session = camera.StartSession(config, err);
EXPECT_TRUE(session != nullptr);
EXPECT_TRUE(camera.IsIndicatorVisible());
camera.StopSession();
EXPECT_FALSE(camera.IsIndicatorVisible());
return true;
}
bool Test_CameraSingleSession(std::string& error_msg) {
SandboxContext ctx;
ctx.app_id = "test.app";
ctx.permissions = {"camera"};
ctx.is_system_app = false;
PermissionGate permissions(ctx);
permissions.GrantPermission("camera");
mosis::CameraInterface camera("test.app", &permissions);
camera.SimulateUserGesture();
std::string err;
mosis::CameraConfig config;
// First session should succeed
auto session1 = camera.StartSession(config, err);
EXPECT_TRUE(session1 != nullptr);
// Second session should fail
camera.SimulateUserGesture();
auto session2 = camera.StartSession(config, err);
EXPECT_TRUE(session2 == nullptr);
EXPECT_TRUE(err.find("active") != std::string::npos ||
err.find("already") != std::string::npos);
return true;
}
bool Test_CameraStopsOnShutdown(std::string& error_msg) {
SandboxContext ctx;
ctx.app_id = "test.app";
ctx.permissions = {"camera"};
ctx.is_system_app = false;
PermissionGate permissions(ctx);
permissions.GrantPermission("camera");
mosis::CameraInterface camera("test.app", &permissions);
camera.SimulateUserGesture();
std::string err;
mosis::CameraConfig config;
auto session = camera.StartSession(config, err);
EXPECT_TRUE(session != nullptr);
EXPECT_TRUE(camera.HasActiveSession());
// Simulate app stop
camera.Shutdown();
EXPECT_FALSE(camera.HasActiveSession());
EXPECT_FALSE(camera.IsIndicatorVisible());
return true;
}
bool Test_CameraLuaIntegration(std::string& error_msg) {
SandboxContext ctx = TestContext();
ctx.permissions = {"camera"};
LuaSandbox sandbox(ctx);
PermissionGate permissions(ctx);
permissions.GrantPermission("camera");
mosis::CameraInterface camera("test.app", &permissions);
camera.SimulateUserGesture();
mosis::RegisterCameraAPI(sandbox.GetState(), &camera);
std::string script = R"lua(
-- Test that camera global exists
if not camera then
error("camera global not found")
end
if not camera.start then
error("camera.start not found")
end
if not camera.isActive then
error("camera.isActive not found")
end
-- isActive should be false initially
if camera.isActive() then
error("camera should not be active initially")
end
)lua";
bool ok = sandbox.LoadString(script, "camera_test");
if (!ok) {
error_msg = "Lua test failed: " + sandbox.GetLastError();
return false;
}
return true;
}
//=============================================================================
// MAIN
//=============================================================================
@@ -1980,6 +2148,14 @@ int main(int argc, char* argv[]) {
harness.AddTest("WebSocketCloseAll", Test_WebSocketCloseAll);
harness.AddTest("WebSocketLuaIntegration", Test_WebSocketLuaIntegration);
// Milestone 11: Camera
harness.AddTest("CameraRequiresPermission", Test_CameraRequiresPermission);
harness.AddTest("CameraRequiresUserGesture", Test_CameraRequiresUserGesture);
harness.AddTest("CameraShowsIndicator", Test_CameraShowsIndicator);
harness.AddTest("CameraSingleSession", Test_CameraSingleSession);
harness.AddTest("CameraStopsOnShutdown", Test_CameraStopsOnShutdown);
harness.AddTest("CameraLuaIntegration", Test_CameraLuaIntegration);
// Run tests
auto results = harness.Run(filter);