Skip to main content

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 InitializeBrowsingCore succeeds
  • 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 UninitializeBrowsingCore is 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 successfully
  • false: 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;
}
};
Advanced Implementation

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 thread
  • OnServiceDisconnected: May be called from SDK internal thread
  • OnCommonEventHappened: 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:

  1. Initialization failed (check InitializeBrowsingCore return value)
  2. Runtime path is incorrect
  3. Passed nullptr instead 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:

  1. Runtime crashed
  2. Runtime was terminated externally

Solution:

  • Check runtime logs
  • Ensure runtime files are complete
  • Check system resources (memory, etc.)

9. Important Notes​

  1. Lifecycle: Handler object must remain valid throughout the SDK lifecycle
  2. Thread Safety: Callbacks may execute in different threads; use appropriate synchronization mechanisms
  3. Quick Return: Don't perform time-consuming operations in callbacks
  4. Don't Call SDK Methods: Don't call SDK methods in OnServiceDisconnected
  5. Exception Handling: Catch all exceptions; don't let exceptions propagate to the SDK