#include "Registrar.h"
#include <stdio.h>
#include <string.h>
#include <exception>
#include <Application.h>
#include <Clipboard.h>
#include <Message.h>
#include <MessengerPrivate.h>
#include <OS.h>
#include <RegistrarDefs.h>
#include <RosterPrivate.h>
#include <system_info.h>
#include "AuthenticationManager.h"
#include "ClipboardHandler.h"
#include "Debug.h"
#include "EventQueue.h"
#include "MessageDeliverer.h"
#include "MessageEvent.h"
#include "MessageRunnerManager.h"
#include "MessagingService.h"
#include "MIMEManager.h"
#include "PackageWatchingManager.h"
#include "ShutdownProcess.h"
#include "TRoster.h"
using std::nothrow;
using namespace BPrivate;
static const char *kEventQueueName = "timer_thread";
Registrar::Registrar(status_t* _error)
:
BServer(B_REGISTRAR_SIGNATURE, B_REGISTRAR_PORT_NAME, -1, false, _error),
fRoster(NULL),
fClipboardHandler(NULL),
fMIMEManager(NULL),
fEventQueue(NULL),
fMessageRunnerManager(NULL),
fShutdownProcess(NULL),
fAuthenticationManager(NULL),
fPackageWatchingManager(NULL)
{
FUNCTION_START();
set_thread_priority(find_thread(NULL), B_NORMAL_PRIORITY + 1);
}
Registrar::~Registrar()
{
FUNCTION_START();
Lock();
fEventQueue->Die();
delete fAuthenticationManager;
delete fPackageWatchingManager;
delete fMessageRunnerManager;
delete fEventQueue;
fMIMEManager->Lock();
fMIMEManager->Quit();
RemoveHandler(fClipboardHandler);
delete fClipboardHandler;
delete fRoster;
BRoster::Private().SetTo(BMessenger(), BMessenger());
FUNCTION_END();
}
void
Registrar::MessageReceived(BMessage *message)
{
try {
_MessageReceived(message);
} catch (std::exception& exception) {
char buffer[1024];
snprintf(buffer, sizeof(buffer),
"Registrar::MessageReceived() caught exception: %s",
exception.what());
debugger(buffer);
} catch (...) {
debugger("Registrar::MessageReceived() caught unknown exception");
}
}
void
Registrar::ReadyToRun()
{
FUNCTION_START();
status_t error = MessageDeliverer::CreateDefault();
if (error != B_OK) {
FATAL("Registrar::ReadyToRun(): Failed to create the message "
"deliverer: %s\n", strerror(error));
}
fEventQueue = new EventQueue(kEventQueueName);
fAuthenticationManager = new AuthenticationManager;
fAuthenticationManager->Init();
fRoster = new TRoster;
fRoster->Init();
fClipboardHandler = new ClipboardHandler;
AddHandler(fClipboardHandler);
fMIMEManager = new MIMEManager;
fMIMEManager->Run();
fMessageRunnerManager = new MessageRunnerManager(fEventQueue);
BRoster::Private().SetTo(be_app_messenger, BMessenger(NULL, fMIMEManager));
error = MessagingService::CreateDefault();
if (error != B_OK) {
ERROR("Registrar::ReadyToRun(): Failed to init messaging service "
"(that's by design when running under R5): %s\n", strerror(error));
}
fPackageWatchingManager = new PackageWatchingManager;
BMessenger target(this);
BMessenger::Private messengerPrivate(target);
port_id port = messengerPrivate.Port();
int32 token = messengerPrivate.Token();
__start_watching_system(-1, B_WATCH_SYSTEM_TEAM_DELETION, port, token);
fRoster->CheckSanity();
FUNCTION_END();
}
bool
Registrar::QuitRequested()
{
FUNCTION_START();
return BApplication::QuitRequested();
}
EventQueue*
Registrar::GetEventQueue() const
{
return fEventQueue;
}
Registrar*
Registrar::App()
{
return dynamic_cast<Registrar*>(be_app);
}
void
Registrar::_MessageReceived(BMessage *message)
{
switch (message->what) {
case B_REG_GET_MIME_MESSENGER:
{
PRINT("B_REG_GET_MIME_MESSENGER\n");
BMessenger messenger(NULL, fMIMEManager);
BMessage reply(B_REG_SUCCESS);
reply.AddMessenger("messenger", messenger);
message->SendReply(&reply);
break;
}
case B_REG_GET_CLIPBOARD_MESSENGER:
{
PRINT("B_REG_GET_CLIPBOARD_MESSENGER\n");
BMessenger messenger(fClipboardHandler);
BMessage reply(B_REG_SUCCESS);
reply.AddMessenger("messenger", messenger);
message->SendReply(&reply);
break;
}
case B_REG_SHUT_DOWN:
{
PRINT("B_REG_SHUT_DOWN\n");
_HandleShutDown(message);
break;
}
case B_REG_IS_SHUT_DOWN_IN_PROGRESS:
{
PRINT("B_REG_IS_SHUT_DOWN_IN_PROGRESS\n");
_HandleIsShutDownInProgress(message);
break;
}
case B_REG_TEAM_DEBUGGER_ALERT:
{
if (fShutdownProcess != NULL)
fShutdownProcess->PostMessage(message);
break;
}
case B_REG_ADD_APP:
fRoster->HandleAddApplication(message);
break;
case B_REG_COMPLETE_REGISTRATION:
fRoster->HandleCompleteRegistration(message);
break;
case B_REG_IS_APP_REGISTERED:
fRoster->HandleIsAppRegistered(message);
break;
case B_REG_REMOVE_PRE_REGISTERED_APP:
fRoster->HandleRemovePreRegApp(message);
break;
case B_REG_REMOVE_APP:
fRoster->HandleRemoveApp(message);
break;
case B_REG_SET_THREAD_AND_TEAM:
fRoster->HandleSetThreadAndTeam(message);
break;
case B_REG_SET_SIGNATURE:
fRoster->HandleSetSignature(message);
break;
case B_REG_GET_APP_INFO:
fRoster->HandleGetAppInfo(message);
break;
case B_REG_GET_APP_LIST:
fRoster->HandleGetAppList(message);
break;
case B_REG_UPDATE_ACTIVE_APP:
fRoster->HandleUpdateActiveApp(message);
break;
case B_REG_BROADCAST:
fRoster->HandleBroadcast(message);
break;
case B_REG_START_WATCHING:
fRoster->HandleStartWatching(message);
break;
case B_REG_STOP_WATCHING:
fRoster->HandleStopWatching(message);
break;
case B_REG_GET_RECENT_DOCUMENTS:
fRoster->HandleGetRecentDocuments(message);
break;
case B_REG_GET_RECENT_FOLDERS:
fRoster->HandleGetRecentFolders(message);
break;
case B_REG_GET_RECENT_APPS:
fRoster->HandleGetRecentApps(message);
break;
case B_REG_ADD_TO_RECENT_DOCUMENTS:
fRoster->HandleAddToRecentDocuments(message);
break;
case B_REG_ADD_TO_RECENT_FOLDERS:
fRoster->HandleAddToRecentFolders(message);
break;
case B_REG_ADD_TO_RECENT_APPS:
fRoster->HandleAddToRecentApps(message);
break;
case B_REG_CLEAR_RECENT_DOCUMENTS:
fRoster->ClearRecentDocuments();
break;
case B_REG_CLEAR_RECENT_FOLDERS:
fRoster->ClearRecentFolders();
break;
case B_REG_CLEAR_RECENT_APPS:
fRoster->ClearRecentApps();
break;
case B_REG_LOAD_RECENT_LISTS:
fRoster->HandleLoadRecentLists(message);
break;
case B_REG_SAVE_RECENT_LISTS:
fRoster->HandleSaveRecentLists(message);
break;
case B_REG_REGISTER_MESSAGE_RUNNER:
fMessageRunnerManager->HandleRegisterRunner(message);
break;
case B_REG_UNREGISTER_MESSAGE_RUNNER:
fMessageRunnerManager->HandleUnregisterRunner(message);
break;
case B_REG_SET_MESSAGE_RUNNER_PARAMS:
fMessageRunnerManager->HandleSetRunnerParams(message);
break;
case B_REG_GET_MESSAGE_RUNNER_INFO:
fMessageRunnerManager->HandleGetRunnerInfo(message);
break;
case B_REG_PACKAGE_START_WATCHING:
case B_REG_PACKAGE_STOP_WATCHING:
fPackageWatchingManager->HandleStartStopWatching(message);
break;
case B_PACKAGE_UPDATE:
fPackageWatchingManager->NotifyWatchers(message);
break;
case B_SYSTEM_OBJECT_UPDATE:
{
team_id team = (team_id)message->GetInt32("team", -1);
if (team >= 0 && message->GetInt32("opcode", 0) == B_TEAM_DELETED)
fRoster->HandleRemoveApp(message);
break;
}
case B_REG_SHUTDOWN_FINISHED:
if (fShutdownProcess) {
fShutdownProcess->PostMessage(B_QUIT_REQUESTED,
fShutdownProcess);
fShutdownProcess = NULL;
}
break;
case kMsgAppServerStarted:
{
fRoster->HandleAppServerStarted(message);
break;
}
default:
BApplication::MessageReceived(message);
break;
}
}
void
Registrar::_HandleShutDown(BMessage *request)
{
status_t error = B_OK;
if (fShutdownProcess)
error = B_SHUTTING_DOWN;
bool needsReply = true;
if (error == B_OK) {
fShutdownProcess = new(nothrow) ShutdownProcess(fRoster, fEventQueue);
if (fShutdownProcess) {
error = fShutdownProcess->Init(request);
if (error == B_OK) {
DetachCurrentMessage();
fShutdownProcess->Run();
needsReply = false;
} else {
delete fShutdownProcess;
fShutdownProcess = NULL;
}
} else
error = B_NO_MEMORY;
}
if (needsReply)
ShutdownProcess::SendReply(request, error);
}
void
Registrar::_HandleIsShutDownInProgress(BMessage *request)
{
BMessage reply(B_REG_SUCCESS);
reply.AddBool("in-progress", fShutdownProcess != NULL);
request->SendReply(&reply);
}
int
main()
{
FUNCTION_START();
be_clipboard = new BClipboard(NULL);
status_t error;
Registrar *app = new Registrar(&error);
if (error != B_OK) {
fprintf(stderr, "REG: Failed to create the BApplication: %s\n",
strerror(error));
return 1;
}
rename_thread(find_thread(NULL), "roster");
PRINT("app->Run()...\n");
try {
app->Run();
} catch (std::exception& exception) {
char buffer[1024];
snprintf(buffer, sizeof(buffer),
"registrar main() caught exception: %s", exception.what());
debugger(buffer);
} catch (...) {
debugger("registrar main() caught unknown exception");
}
PRINT("delete app...\n");
delete app;
FUNCTION_END();
return 0;
}