ICoreServiceHandler Interface
1. Overview
ICoreServiceHandler is the core service event handler interface, used to receive lifecycle events and common event callbacks from the browsing core service.
2. Interface Definition
interface ICoreServiceHandler : public WIUnknown {
// Called when context is initialized
virtual void OnContextInitialized() = 0;
// Called when service is disconnected
virtual void OnServiceDisconnected() = 0;
// Called when common event happens
virtual bool OnCommonEventHappened(
const char* event_name,
int32_t callback_id,
const char* data,
const unsigned int data_size
) = 0;
};
3. Method Details
3.1 OnContextInitialized
Called when the browsing core context initialization is complete. This indicates the runtime has started and is ready.
Function Signature
virtual void OnContextInitialized() = 0;
Call Timing
- After
InitializeBrowsingCoresucceeds - Runtime is ready
Code Example
class MyServiceHandler : public WIUnknownImpl {
public:
void OnContextInitialized() override {
std::cout << "Context initialized successfully" << std::endl;
std::cout << "Runtime server is ready" << std::endl;
// Can now safely query sub-interfaces and launch games
}
};
3.2 OnServiceDisconnected
Called when the connection to the runtime is disconnected.
Function Signature
virtual void OnServiceDisconnected() = 0;
Call Timing
- Runtime exits unexpectedly
- When
UninitializeBrowsingCoreis called
Code Example
class MyServiceHandler : public WIUnknownImpl {
public:
void OnServiceDisconnected() override {
std::cerr << "Service disconnected" << std::endl;
std::cerr << "Runtime connection lost" << std::endl;
// Handle disconnection (e.g., notify user, attempt reconnect, cleanup)
// Note: Do NOT call SDK methods here as service is disconnected
}
};
3.3 OnCommonEventHappened
Called when a common event occurs. Used for handling custom events and extended functionality.
Function Signature
virtual bool OnCommonEventHappened(
const char* event_name,
int32_t callback_id,
const char* data,
const unsigned int data_size
) = 0;
Parameter Description
- event_name (
const char*): Event name - callback_id (
int32_t): Callback ID (for response) - data (
const char*): Event data (usually JSON format) - data_size (
unsigned int): Data size (bytes)
Return Value
true: Event handled successfullyfalse: Event handling failed
Code Example
class MyServiceHandler : public WIUnknownImpl {
public:
bool OnCommonEventHappened(
const char* event_name,
int32_t callback_id,
const char* data,
const unsigned int data_size
) override {
std::cout << "[Common Event] " << event_name << std::endl;
std::cout << "[Callback ID] " << callback_id << std::endl;
if (data && data_size > 0) {
std::string eventData(data, data_size);
std::cout << "[Event Data] " << eventData << std::endl;
}
// Handle specific events
if (strcmp(event_name, "customEvent") == 0) {
// Process custom event
return true;
}
// Default: event handled
return true;
}
};
4. Implementation Examples
4.1 Basic Implementation
Use the WIUnknownImpl base class to simplify implementation:
#include "ICoreServiceHandler.h"
#include <iostream>
class MyServiceHandler : public WIUnknownImpl {
public:
void OnContextInitialized() override {
std::cout << "[Handler] Context initialized" << std::endl;
}
void OnServiceDisconnected() override {
std::cout << "[Handler] Service disconnected" << std::endl;
}
bool OnCommonEventHappened(
const char* event_name,
int32_t callback_id,
const char* data,
const unsigned int data_size
) override {
std::cout << "[Handler] Event: " << event_name << std::endl;
return true;
}
};
For more complex event handler implementations (such as with logging and state management), please refer to the demo.cpp file in the Demo Project.
4.2 Complete Implementation (Without Base Class)
class DemoCoreServiceHandler : public ICoreServiceHandler {
public:
// WIUnknown interface methods
virtual INT QueryInterface(const char* type, void** ppvObject) override {
return -1;
}
virtual ULONG AddRef(void) override { return 1; }
virtual ULONG Release(void) override { return 1; }
// ICoreServiceHandler methods
virtual void OnContextInitialized() override {
std::cout << "[CoreServiceHandler] Context initialized" << std::endl;
}
virtual void OnServiceDisconnected() override {
std::cout << "[CoreServiceHandler] Service disconnected" << std::endl;
}
virtual bool OnCommonEventHappened(const char* event_name, int32_t callback_id,
const char* data, const unsigned int data_size) override {
std::cout << "[CoreServiceHandler] Event: " << event_name << std::endl;
// Check for server process exit event
if (event_name && strcmp(event_name, "cservice_event_report_process") == 0) {
if (data && strstr(data, "\"event\":2")) {
std::cout << "[CoreServiceHandler] Server process exiting" << std::endl;
}
}
return true;
}
};
// Usage
DemoCoreServiceHandler handler;
service->InitializeBrowsingCore(config, runtimePath, &handler);
5. Lifecycle
Typical event call sequence:
1. Application calls InitializeBrowsingCore()
|
2. SDK starts runtime process
|
3. OnContextInitialized() called
|
4. Application can now use SDK features
|
5. [Application runs normally]
|
6. Application calls UninitializeBrowsingCore()
OR runtime crashes
|
7. OnServiceDisconnected() called
|
8. Cleanup complete
6. Thread Safety
Important: Event handler methods may be called from different threads:
OnContextInitialized: May be called from SDK internal worker threadOnServiceDisconnected: May be called from SDK internal threadOnCommonEventHappened: May be called from message processing thread
Use std::mutex to protect shared data if thread safety is needed.
7. Best Practices
7.1 Use WIUnknownImpl Base Class
// Good: Extends WIUnknownImpl
class MyHandler : public WIUnknownImpl {
// Implement only what you need
};
// Bad: Implements WIUnknown directly
class MyHandler : public WIUnknown {
// Must implement QueryInterface, AddRef, Release manually
};
7.2 Keep Handlers Lightweight
void OnContextInitialized() override {
// Good: Quick notification
std::cout << "Ready!" << std::endl;
readyFlag_ = true;
}
// Bad: Heavy processing blocks the SDK
void OnContextInitialized() override {
LoadLargeFiles(); // DON'T DO THIS
InitializeDatabase(); // DON'T DO THIS
}
7.3 Handler Lifecycle
int main() {
// Good: Stack-allocated handler with appropriate lifetime
MyServiceHandler handler;
IBrowsingService* service = GetBrowsingService();
service->InitializeBrowsingCore(config, "", &handler);
// handler remains valid until end of scope
// ...
service->UninitializeBrowsingCore();
// handler destroyed after service cleanup
}
7.4 Error Handling
bool OnCommonEventHappened(
const char* event_name,
int32_t callback_id,
const char* data,
const unsigned int data_size
) override {
try {
// Process event
ProcessEvent(event_name, data, data_size);
return true;
} catch (const std::exception& e) {
std::cerr << "Event processing error: " << e.what() << std::endl;
return false; // Indicate failure
}
}
8. Troubleshooting
8.1 Issue: OnContextInitialized Not Called
Possible Causes:
- Initialization failed (check
InitializeBrowsingCorereturn value) - Runtime path is incorrect
- Passed
nullptrinstead of handler object
Solution:
// Check initialization result
int result = service->InitializeBrowsingCore(config, "", &handler);
if (result != WMPF_ERRCODE_SUCCESS) {
std::cerr << "Init failed: " << result << std::endl;
}
8.2 Issue: OnServiceDisconnected Called Unexpectedly
Possible Causes:
- Runtime crashed
- Runtime was terminated externally
Solution:
- Check runtime logs
- Ensure runtime files are complete
- Check system resources (memory, etc.)
9. Important Notes
- Lifecycle: Handler object must remain valid throughout the SDK lifecycle
- Thread Safety: Callbacks may execute in different threads; use appropriate synchronization mechanisms
- Quick Return: Don't perform time-consuming operations in callbacks
- Don't Call SDK Methods: Don't call SDK methods in
OnServiceDisconnected - Exception Handling: Catch all exceptions; don't let exceptions propagate to the SDK