implement Milestone 18: inter-app MessageBus with intent system
This commit is contained in:
546
src/main/cpp/sandbox/message_bus.cpp
Normal file
546
src/main/cpp/sandbox/message_bus.cpp
Normal file
@@ -0,0 +1,546 @@
|
||||
// message_bus.cpp - Inter-app message bus implementation
|
||||
// Milestone 18: Kernel-mediated message passing between apps
|
||||
|
||||
#include "message_bus.h"
|
||||
#include <lua.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
namespace mosis {
|
||||
|
||||
// ============================================================================
|
||||
// MessageBus
|
||||
// ============================================================================
|
||||
|
||||
MessageBus::MessageBus() = default;
|
||||
MessageBus::~MessageBus() = default;
|
||||
|
||||
bool MessageBus::MatchesFilter(const Intent& intent, const IntentFilter& filter) const {
|
||||
// Action must match
|
||||
if (filter.action != intent.action) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If no types specified, accept all
|
||||
if (filter.types.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if intent type matches any filter type
|
||||
for (const auto& t : filter.types) {
|
||||
if (t == intent.type) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MessageBus::ValidateIntent(const Intent& intent, std::string& error) const {
|
||||
if (intent.action.empty()) {
|
||||
error = "intent action is required";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Note: Data size is checked separately to return DataTooLarge error
|
||||
return true;
|
||||
}
|
||||
|
||||
void MessageBus::RegisterReceiver(
|
||||
const std::string& app_id,
|
||||
const IntentFilter& filter,
|
||||
IntentHandler handler
|
||||
) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_receivers.push_back({app_id, filter, std::move(handler)});
|
||||
}
|
||||
|
||||
void MessageBus::UnregisterApp(const std::string& app_id) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_receivers.erase(
|
||||
std::remove_if(m_receivers.begin(), m_receivers.end(),
|
||||
[&app_id](const ReceiverEntry& e) { return e.app_id == app_id; }),
|
||||
m_receivers.end()
|
||||
);
|
||||
}
|
||||
|
||||
MessageError MessageBus::Send(
|
||||
const std::string& sender_app,
|
||||
const std::string& target_app,
|
||||
const Intent& intent,
|
||||
std::string& error
|
||||
) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
// Check if sender is blocked
|
||||
if (m_blocked_apps.count(sender_app)) {
|
||||
error = "sender app is blocked";
|
||||
return MessageError::SenderBlocked;
|
||||
}
|
||||
|
||||
// Validate intent
|
||||
if (!ValidateIntent(intent, error)) {
|
||||
return MessageError::InvalidIntent;
|
||||
}
|
||||
|
||||
// Check data size
|
||||
if (intent.data.size() > MAX_DATA_SIZE) {
|
||||
error = "intent data exceeds maximum size";
|
||||
return MessageError::DataTooLarge;
|
||||
}
|
||||
|
||||
// Find target receiver
|
||||
bool found = false;
|
||||
for (const auto& entry : m_receivers) {
|
||||
if (entry.app_id == target_app && MatchesFilter(intent, entry.filter)) {
|
||||
// Create intent with sender info
|
||||
Intent deliveredIntent = intent;
|
||||
deliveredIntent.from_app = sender_app;
|
||||
|
||||
// Deliver
|
||||
entry.handler(deliveredIntent);
|
||||
found = true;
|
||||
m_message_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
error = "no receiver found for target app with matching action";
|
||||
return MessageError::ReceiverNotFound;
|
||||
}
|
||||
|
||||
return MessageError::None;
|
||||
}
|
||||
|
||||
MessageError MessageBus::Broadcast(
|
||||
const std::string& sender_app,
|
||||
const Intent& intent,
|
||||
std::string& error
|
||||
) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
// Check if sender is blocked
|
||||
if (m_blocked_apps.count(sender_app)) {
|
||||
error = "sender app is blocked";
|
||||
return MessageError::SenderBlocked;
|
||||
}
|
||||
|
||||
// Validate intent
|
||||
if (!ValidateIntent(intent, error)) {
|
||||
return MessageError::InvalidIntent;
|
||||
}
|
||||
|
||||
// Check data size
|
||||
if (intent.data.size() > MAX_DATA_SIZE) {
|
||||
error = "intent data exceeds maximum size";
|
||||
return MessageError::DataTooLarge;
|
||||
}
|
||||
|
||||
// Collect matching handlers (avoid holding lock during callbacks)
|
||||
std::vector<IntentHandler> handlers;
|
||||
for (const auto& entry : m_receivers) {
|
||||
// Skip blocked receivers
|
||||
if (m_blocked_apps.count(entry.app_id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (MatchesFilter(intent, entry.filter)) {
|
||||
handlers.push_back(entry.handler);
|
||||
}
|
||||
}
|
||||
|
||||
if (handlers.empty()) {
|
||||
error = "no receivers registered for action: " + intent.action;
|
||||
return MessageError::NoReceivers;
|
||||
}
|
||||
|
||||
// Create intent with sender info
|
||||
Intent deliveredIntent = intent;
|
||||
deliveredIntent.from_app = sender_app;
|
||||
|
||||
// Deliver to all matching handlers
|
||||
for (const auto& handler : handlers) {
|
||||
handler(deliveredIntent);
|
||||
m_message_count++;
|
||||
}
|
||||
|
||||
return MessageError::None;
|
||||
}
|
||||
|
||||
bool MessageBus::HasReceiverFor(const std::string& action) const {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
for (const auto& entry : m_receivers) {
|
||||
if (entry.filter.action == action && !m_blocked_apps.count(entry.app_id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> MessageBus::GetReceiversFor(const std::string& action) const {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
std::vector<std::string> result;
|
||||
std::unordered_set<std::string> seen;
|
||||
|
||||
for (const auto& entry : m_receivers) {
|
||||
if (entry.filter.action == action &&
|
||||
!m_blocked_apps.count(entry.app_id) &&
|
||||
!seen.count(entry.app_id)) {
|
||||
result.push_back(entry.app_id);
|
||||
seen.insert(entry.app_id);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void MessageBus::SetAppPermission(const std::string& app_id, const std::string& permission, bool granted) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
if (granted) {
|
||||
m_permissions[app_id].insert(permission);
|
||||
} else {
|
||||
auto it = m_permissions.find(app_id);
|
||||
if (it != m_permissions.end()) {
|
||||
it->second.erase(permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MessageBus::HasPermission(const std::string& app_id, const std::string& permission) const {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
auto it = m_permissions.find(app_id);
|
||||
if (it == m_permissions.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return it->second.count(permission) > 0;
|
||||
}
|
||||
|
||||
void MessageBus::BlockApp(const std::string& app_id) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_blocked_apps.insert(app_id);
|
||||
}
|
||||
|
||||
void MessageBus::UnblockApp(const std::string& app_id) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_blocked_apps.erase(app_id);
|
||||
}
|
||||
|
||||
bool MessageBus::IsBlocked(const std::string& app_id) const {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
return m_blocked_apps.count(app_id) > 0;
|
||||
}
|
||||
|
||||
void MessageBus::Clear() {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_receivers.clear();
|
||||
m_permissions.clear();
|
||||
m_blocked_apps.clear();
|
||||
m_message_count = 0;
|
||||
}
|
||||
|
||||
size_t MessageBus::GetReceiverCount() const {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
return m_receivers.size();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Lua API
|
||||
// ============================================================================
|
||||
|
||||
// Helper to set a global in the real _G (bypassing any proxy)
|
||||
static void SetGlobalInRealG(lua_State* L, const char* name) {
|
||||
// Stack: value to set as global (at -1)
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
|
||||
|
||||
// Check if _G has a metatable with __index (sandbox proxy pattern)
|
||||
if (lua_getmetatable(L, -1)) {
|
||||
lua_getfield(L, -1, "__index");
|
||||
if (lua_istable(L, -1)) {
|
||||
// Found proxy, set in the real _G (__index table)
|
||||
lua_pushvalue(L, -4); // Copy value
|
||||
lua_setfield(L, -2, name);
|
||||
lua_pop(L, 4); // Pop __index, metatable, _G, original value
|
||||
return;
|
||||
}
|
||||
lua_pop(L, 2); // Pop nil/__index and metatable
|
||||
}
|
||||
|
||||
// No proxy, set in _G directly
|
||||
lua_pushvalue(L, -2); // Copy value
|
||||
lua_setfield(L, -2, name);
|
||||
lua_pop(L, 2); // Pop _G and original value
|
||||
}
|
||||
|
||||
static const char* MESSAGE_BUS_KEY = "mosis.message_bus";
|
||||
static const char* INTENTS_APP_ID_KEY = "mosis.intents_app_id";
|
||||
|
||||
static MessageBus* GetMessageBus(lua_State* L) {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, MESSAGE_BUS_KEY);
|
||||
auto* bus = static_cast<MessageBus*>(lua_touserdata(L, -1));
|
||||
lua_pop(L, 1);
|
||||
return bus;
|
||||
}
|
||||
|
||||
static std::string GetAppId(lua_State* L) {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, INTENTS_APP_ID_KEY);
|
||||
std::string app_id;
|
||||
if (lua_isstring(L, -1)) {
|
||||
app_id = lua_tostring(L, -1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
return app_id;
|
||||
}
|
||||
|
||||
// Read Intent from Lua table
|
||||
static Intent ReadIntent(lua_State* L, int index) {
|
||||
Intent intent;
|
||||
|
||||
if (lua_type(L, index) != LUA_TTABLE) {
|
||||
return intent;
|
||||
}
|
||||
|
||||
lua_getfield(L, index, "action");
|
||||
if (lua_isstring(L, -1)) {
|
||||
intent.action = lua_tostring(L, -1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "type");
|
||||
if (lua_isstring(L, -1)) {
|
||||
intent.type = lua_tostring(L, -1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, index, "data");
|
||||
if (lua_isstring(L, -1)) {
|
||||
intent.data = lua_tostring(L, -1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
// Push Intent as Lua table
|
||||
static void PushIntent(lua_State* L, const Intent& intent) {
|
||||
lua_createtable(L, 0, 4);
|
||||
|
||||
lua_pushstring(L, intent.action.c_str());
|
||||
lua_setfield(L, -2, "action");
|
||||
|
||||
lua_pushstring(L, intent.type.c_str());
|
||||
lua_setfield(L, -2, "type");
|
||||
|
||||
lua_pushstring(L, intent.data.c_str());
|
||||
lua_setfield(L, -2, "data");
|
||||
|
||||
lua_pushstring(L, intent.from_app.c_str());
|
||||
lua_setfield(L, -2, "from");
|
||||
}
|
||||
|
||||
// intents.on(action, handler, [options])
|
||||
static int lua_intents_on(lua_State* L) {
|
||||
auto* bus = GetMessageBus(L);
|
||||
if (!bus) {
|
||||
return luaL_error(L, "message bus not available");
|
||||
}
|
||||
|
||||
std::string app_id = GetAppId(L);
|
||||
if (app_id.empty()) {
|
||||
return luaL_error(L, "app id not set");
|
||||
}
|
||||
|
||||
const char* action = luaL_checkstring(L, 1);
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION);
|
||||
|
||||
IntentFilter filter;
|
||||
filter.action = action;
|
||||
|
||||
// Parse optional options table
|
||||
if (lua_gettop(L) >= 3 && lua_istable(L, 3)) {
|
||||
lua_getfield(L, 3, "types");
|
||||
if (lua_istable(L, -1)) {
|
||||
int len = static_cast<int>(lua_rawlen(L, -1));
|
||||
for (int i = 1; i <= len; i++) {
|
||||
lua_rawgeti(L, -1, i);
|
||||
if (lua_isstring(L, -1)) {
|
||||
filter.types.push_back(lua_tostring(L, -1));
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
// Store handler reference
|
||||
lua_pushvalue(L, 2); // Copy handler function
|
||||
int handler_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
// Register receiver with C++ callback that invokes Lua handler
|
||||
bus->RegisterReceiver(app_id, filter, [L, handler_ref](const Intent& intent) {
|
||||
// Get handler function
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, handler_ref);
|
||||
|
||||
// Push intent as argument
|
||||
PushIntent(L, intent);
|
||||
|
||||
// Call handler(intent)
|
||||
if (lua_pcall(L, 1, 0, 0) != LUA_OK) {
|
||||
// Log error but don't propagate
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// intents.send(target_app, intent) -> success, error
|
||||
static int lua_intents_send(lua_State* L) {
|
||||
auto* bus = GetMessageBus(L);
|
||||
if (!bus) {
|
||||
return luaL_error(L, "message bus not available");
|
||||
}
|
||||
|
||||
std::string app_id = GetAppId(L);
|
||||
if (app_id.empty()) {
|
||||
return luaL_error(L, "app id not set");
|
||||
}
|
||||
|
||||
const char* target = luaL_checkstring(L, 1);
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
|
||||
Intent intent = ReadIntent(L, 2);
|
||||
|
||||
std::string error;
|
||||
auto result = bus->Send(app_id, target, intent, error);
|
||||
|
||||
if (result == MessageError::None) {
|
||||
lua_pushboolean(L, 1);
|
||||
lua_pushnil(L);
|
||||
} else {
|
||||
lua_pushboolean(L, 0);
|
||||
lua_pushstring(L, error.c_str());
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
// intents.broadcast(intent) -> count
|
||||
static int lua_intents_broadcast(lua_State* L) {
|
||||
auto* bus = GetMessageBus(L);
|
||||
if (!bus) {
|
||||
return luaL_error(L, "message bus not available");
|
||||
}
|
||||
|
||||
std::string app_id = GetAppId(L);
|
||||
if (app_id.empty()) {
|
||||
return luaL_error(L, "app id not set");
|
||||
}
|
||||
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
|
||||
Intent intent = ReadIntent(L, 1);
|
||||
|
||||
// Get receiver count before broadcast
|
||||
auto receivers = bus->GetReceiversFor(intent.action);
|
||||
|
||||
std::string error;
|
||||
auto result = bus->Broadcast(app_id, intent, error);
|
||||
|
||||
if (result == MessageError::None) {
|
||||
lua_pushinteger(L, static_cast<int>(receivers.size()));
|
||||
} else if (result == MessageError::NoReceivers) {
|
||||
lua_pushinteger(L, 0);
|
||||
} else {
|
||||
return luaL_error(L, "%s", error.c_str());
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// intents.hasReceiver(action) -> boolean
|
||||
static int lua_intents_hasReceiver(lua_State* L) {
|
||||
auto* bus = GetMessageBus(L);
|
||||
if (!bus) {
|
||||
return luaL_error(L, "message bus not available");
|
||||
}
|
||||
|
||||
const char* action = luaL_checkstring(L, 1);
|
||||
lua_pushboolean(L, bus->HasReceiverFor(action));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// intents.getReceivers(action) -> array of app IDs
|
||||
static int lua_intents_getReceivers(lua_State* L) {
|
||||
auto* bus = GetMessageBus(L);
|
||||
if (!bus) {
|
||||
return luaL_error(L, "message bus not available");
|
||||
}
|
||||
|
||||
const char* action = luaL_checkstring(L, 1);
|
||||
auto receivers = bus->GetReceiversFor(action);
|
||||
|
||||
lua_createtable(L, static_cast<int>(receivers.size()), 0);
|
||||
for (size_t i = 0; i < receivers.size(); i++) {
|
||||
lua_pushstring(L, receivers[i].c_str());
|
||||
lua_rawseti(L, -2, static_cast<int>(i + 1));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// intents.unregisterAll()
|
||||
static int lua_intents_unregisterAll(lua_State* L) {
|
||||
auto* bus = GetMessageBus(L);
|
||||
if (!bus) {
|
||||
return luaL_error(L, "message bus not available");
|
||||
}
|
||||
|
||||
std::string app_id = GetAppId(L);
|
||||
if (!app_id.empty()) {
|
||||
bus->UnregisterApp(app_id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RegisterIntentsAPI(lua_State* L, MessageBus* bus, const std::string& app_id) {
|
||||
// Store bus pointer
|
||||
lua_pushlightuserdata(L, bus);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, MESSAGE_BUS_KEY);
|
||||
|
||||
// Store app ID
|
||||
lua_pushstring(L, app_id.c_str());
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, INTENTS_APP_ID_KEY);
|
||||
|
||||
// Create intents table
|
||||
lua_createtable(L, 0, 6);
|
||||
|
||||
lua_pushcfunction(L, lua_intents_on);
|
||||
lua_setfield(L, -2, "on");
|
||||
|
||||
lua_pushcfunction(L, lua_intents_send);
|
||||
lua_setfield(L, -2, "send");
|
||||
|
||||
lua_pushcfunction(L, lua_intents_broadcast);
|
||||
lua_setfield(L, -2, "broadcast");
|
||||
|
||||
lua_pushcfunction(L, lua_intents_hasReceiver);
|
||||
lua_setfield(L, -2, "hasReceiver");
|
||||
|
||||
lua_pushcfunction(L, lua_intents_getReceivers);
|
||||
lua_setfield(L, -2, "getReceivers");
|
||||
|
||||
lua_pushcfunction(L, lua_intents_unregisterAll);
|
||||
lua_setfield(L, -2, "unregisterAll");
|
||||
|
||||
// Set as global "intents" (bypassing sandbox proxy)
|
||||
SetGlobalInRealG(L, "intents");
|
||||
}
|
||||
|
||||
} // namespace mosis
|
||||
114
src/main/cpp/sandbox/message_bus.h
Normal file
114
src/main/cpp/sandbox/message_bus.h
Normal file
@@ -0,0 +1,114 @@
|
||||
// message_bus.h - Inter-app message bus for Lua sandbox
|
||||
// Milestone 18: Kernel-mediated message passing between apps
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
struct lua_State;
|
||||
|
||||
namespace mosis {
|
||||
|
||||
struct Intent {
|
||||
std::string action; // Intent action (e.g., "share", "view", "edit")
|
||||
std::string type; // MIME type (e.g., "text/plain", "image/png")
|
||||
std::string data; // Intent data/payload
|
||||
std::string from_app; // Sender app ID (set by kernel)
|
||||
};
|
||||
|
||||
struct IntentFilter {
|
||||
std::string action; // Required action
|
||||
std::vector<std::string> types; // Accepted MIME types (empty = all)
|
||||
};
|
||||
|
||||
enum class MessageError {
|
||||
None,
|
||||
NoReceivers,
|
||||
PermissionDenied,
|
||||
InvalidIntent,
|
||||
DataTooLarge,
|
||||
ReceiverNotFound,
|
||||
SenderBlocked
|
||||
};
|
||||
|
||||
class MessageBus {
|
||||
public:
|
||||
using IntentHandler = std::function<void(const Intent&)>;
|
||||
|
||||
MessageBus();
|
||||
~MessageBus();
|
||||
|
||||
// Register an app to receive intents
|
||||
void RegisterReceiver(
|
||||
const std::string& app_id,
|
||||
const IntentFilter& filter,
|
||||
IntentHandler handler
|
||||
);
|
||||
|
||||
// Unregister all handlers for an app
|
||||
void UnregisterApp(const std::string& app_id);
|
||||
|
||||
// Send intent to specific app (requires permission)
|
||||
MessageError Send(
|
||||
const std::string& sender_app,
|
||||
const std::string& target_app,
|
||||
const Intent& intent,
|
||||
std::string& error
|
||||
);
|
||||
|
||||
// Broadcast intent to all registered receivers
|
||||
MessageError Broadcast(
|
||||
const std::string& sender_app,
|
||||
const Intent& intent,
|
||||
std::string& error
|
||||
);
|
||||
|
||||
// Check if any app handles this action
|
||||
bool HasReceiverFor(const std::string& action) const;
|
||||
|
||||
// Get list of apps that handle an action
|
||||
std::vector<std::string> GetReceiversFor(const std::string& action) const;
|
||||
|
||||
// Permission management
|
||||
void SetAppPermission(const std::string& app_id, const std::string& permission, bool granted);
|
||||
bool HasPermission(const std::string& app_id, const std::string& permission) const;
|
||||
|
||||
// Block specific app from sending/receiving
|
||||
void BlockApp(const std::string& app_id);
|
||||
void UnblockApp(const std::string& app_id);
|
||||
bool IsBlocked(const std::string& app_id) const;
|
||||
|
||||
// Clear all registrations (for testing)
|
||||
void Clear();
|
||||
|
||||
// Statistics
|
||||
size_t GetReceiverCount() const;
|
||||
size_t GetMessageCount() const { return m_message_count; }
|
||||
|
||||
private:
|
||||
struct ReceiverEntry {
|
||||
std::string app_id;
|
||||
IntentFilter filter;
|
||||
IntentHandler handler;
|
||||
};
|
||||
|
||||
std::vector<ReceiverEntry> m_receivers;
|
||||
std::unordered_map<std::string, std::unordered_set<std::string>> m_permissions;
|
||||
std::unordered_set<std::string> m_blocked_apps;
|
||||
mutable std::mutex m_mutex;
|
||||
size_t m_message_count = 0;
|
||||
|
||||
static constexpr size_t MAX_DATA_SIZE = 1024 * 1024; // 1MB max
|
||||
|
||||
bool MatchesFilter(const Intent& intent, const IntentFilter& filter) const;
|
||||
bool ValidateIntent(const Intent& intent, std::string& error) const;
|
||||
};
|
||||
|
||||
// Register intents.* APIs as globals
|
||||
void RegisterIntentsAPI(lua_State* L, MessageBus* bus, const std::string& app_id);
|
||||
|
||||
} // namespace mosis
|
||||
Reference in New Issue
Block a user