1 /* 2 * Copyright 2001-2015, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ingo Weinhold, ingo_weinhold@gmx.de 7 */ 8 9 #include "Registrar.h" 10 11 #include <stdio.h> 12 #include <string.h> 13 14 #include <exception> 15 16 #include <Application.h> 17 #include <Clipboard.h> 18 #include <Message.h> 19 #include <MessengerPrivate.h> 20 #include <OS.h> 21 #include <RegistrarDefs.h> 22 #include <RosterPrivate.h> 23 #include <system_info.h> 24 25 #include "AuthenticationManager.h" 26 #include "ClipboardHandler.h" 27 #include "Debug.h" 28 #include "EventQueue.h" 29 #include "MessageDeliverer.h" 30 #include "MessageEvent.h" 31 #include "MessageRunnerManager.h" 32 #include "MessagingService.h" 33 #include "MIMEManager.h" 34 #include "PackageWatchingManager.h" 35 #include "ShutdownProcess.h" 36 #include "TRoster.h" 37 38 39 /*! 40 \class Registrar 41 \brief The application class of the registrar. 42 43 Glues the registrar services together and dispatches the roster messages. 44 */ 45 46 using std::nothrow; 47 using namespace BPrivate; 48 49 //! Name of the event queue. 50 static const char *kEventQueueName = "timer_thread"; 51 52 53 /*! \brief Creates the registrar application class. 54 \param error Passed to the BApplication constructor for returning an 55 error code. 56 */ 57 Registrar::Registrar(status_t* _error) 58 : 59 BServer(B_REGISTRAR_SIGNATURE, B_REGISTRAR_PORT_NAME, -1, false, _error), 60 fRoster(NULL), 61 fClipboardHandler(NULL), 62 fMIMEManager(NULL), 63 fEventQueue(NULL), 64 fMessageRunnerManager(NULL), 65 fShutdownProcess(NULL), 66 fAuthenticationManager(NULL), 67 fPackageWatchingManager(NULL) 68 { 69 FUNCTION_START(); 70 71 set_thread_priority(find_thread(NULL), B_NORMAL_PRIORITY + 1); 72 } 73 74 75 /*! \brief Frees all resources associated with the registrar. 76 77 All registrar services, that haven't been shut down earlier, are 78 terminated. 79 */ 80 Registrar::~Registrar() 81 { 82 FUNCTION_START(); 83 Lock(); 84 fEventQueue->Die(); 85 delete fAuthenticationManager; 86 delete fPackageWatchingManager; 87 delete fMessageRunnerManager; 88 delete fEventQueue; 89 fMIMEManager->Lock(); 90 fMIMEManager->Quit(); 91 RemoveHandler(fClipboardHandler); 92 delete fClipboardHandler; 93 delete fRoster; 94 // Invalidate the global be_roster, so that the BApplication destructor 95 // won't dead-lock when sending a message to itself. 96 BRoster::Private().SetTo(BMessenger(), BMessenger()); 97 FUNCTION_END(); 98 } 99 100 101 /*! \brief Overrides the super class version to dispatch roster specific 102 messages. 103 \param message The message to be handled 104 */ 105 void 106 Registrar::MessageReceived(BMessage *message) 107 { 108 try { 109 _MessageReceived(message); 110 } catch (std::exception& exception) { 111 char buffer[1024]; 112 snprintf(buffer, sizeof(buffer), 113 "Registrar::MessageReceived() caught exception: %s", 114 exception.what()); 115 debugger(buffer); 116 } catch (...) { 117 debugger("Registrar::MessageReceived() caught unknown exception"); 118 } 119 } 120 121 122 /*! \brief Overrides the super class version to initialize the registrar 123 services. 124 */ 125 void 126 Registrar::ReadyToRun() 127 { 128 FUNCTION_START(); 129 130 // create message deliverer 131 status_t error = MessageDeliverer::CreateDefault(); 132 if (error != B_OK) { 133 FATAL("Registrar::ReadyToRun(): Failed to create the message " 134 "deliverer: %s\n", strerror(error)); 135 } 136 137 // create event queue 138 fEventQueue = new EventQueue(kEventQueueName); 139 140 // create authentication manager 141 fAuthenticationManager = new AuthenticationManager; 142 fAuthenticationManager->Init(); 143 144 // create roster 145 fRoster = new TRoster; 146 fRoster->Init(); 147 148 // create clipboard handler 149 fClipboardHandler = new ClipboardHandler; 150 AddHandler(fClipboardHandler); 151 152 // create MIME manager 153 fMIMEManager = new MIMEManager; 154 fMIMEManager->Run(); 155 156 // create message runner manager 157 fMessageRunnerManager = new MessageRunnerManager(fEventQueue); 158 159 // init the global be_roster 160 BRoster::Private().SetTo(be_app_messenger, BMessenger(NULL, fMIMEManager)); 161 162 // create the messaging service 163 error = MessagingService::CreateDefault(); 164 if (error != B_OK) { 165 ERROR("Registrar::ReadyToRun(): Failed to init messaging service " 166 "(that's by design when running under R5): %s\n", strerror(error)); 167 } 168 169 // create the package watching manager 170 fPackageWatchingManager = new PackageWatchingManager; 171 172 // Sanity check roster after team deletion 173 BMessenger target(this); 174 BMessenger::Private messengerPrivate(target); 175 176 port_id port = messengerPrivate.Port(); 177 int32 token = messengerPrivate.Token(); 178 __start_watching_system(-1, B_WATCH_SYSTEM_TEAM_DELETION, port, token); 179 fRoster->CheckSanity(); 180 // Clean up any teams that exited before we started watching 181 182 FUNCTION_END(); 183 } 184 185 186 /*! \brief Overrides the super class version to avoid termination of the 187 registrar until the system shutdown. 188 */ 189 bool 190 Registrar::QuitRequested() 191 { 192 FUNCTION_START(); 193 // The final registrar must not quit. At least not that easily. ;-) 194 return BApplication::QuitRequested(); 195 } 196 197 198 /*! \brief Returns the registrar's event queue. 199 \return The registrar's event queue. 200 */ 201 EventQueue* 202 Registrar::GetEventQueue() const 203 { 204 return fEventQueue; 205 } 206 207 208 /*! \brief Returns the Registrar application object. 209 \return The Registrar application object. 210 */ 211 Registrar* 212 Registrar::App() 213 { 214 return dynamic_cast<Registrar*>(be_app); 215 } 216 217 218 void 219 Registrar::_MessageReceived(BMessage *message) 220 { 221 switch (message->what) { 222 // general requests 223 case B_REG_GET_MIME_MESSENGER: 224 { 225 PRINT("B_REG_GET_MIME_MESSENGER\n"); 226 BMessenger messenger(NULL, fMIMEManager); 227 BMessage reply(B_REG_SUCCESS); 228 reply.AddMessenger("messenger", messenger); 229 message->SendReply(&reply); 230 break; 231 } 232 233 case B_REG_GET_CLIPBOARD_MESSENGER: 234 { 235 PRINT("B_REG_GET_CLIPBOARD_MESSENGER\n"); 236 BMessenger messenger(fClipboardHandler); 237 BMessage reply(B_REG_SUCCESS); 238 reply.AddMessenger("messenger", messenger); 239 message->SendReply(&reply); 240 break; 241 } 242 243 // shutdown process 244 case B_REG_SHUT_DOWN: 245 { 246 PRINT("B_REG_SHUT_DOWN\n"); 247 248 _HandleShutDown(message); 249 break; 250 } 251 case B_REG_IS_SHUT_DOWN_IN_PROGRESS: 252 { 253 PRINT("B_REG_IS_SHUT_DOWN_IN_PROGRESS\n"); 254 255 _HandleIsShutDownInProgress(message); 256 break; 257 } 258 case B_REG_TEAM_DEBUGGER_ALERT: 259 { 260 if (fShutdownProcess != NULL) 261 fShutdownProcess->PostMessage(message); 262 break; 263 } 264 265 // roster requests 266 case B_REG_ADD_APP: 267 fRoster->HandleAddApplication(message); 268 break; 269 case B_REG_COMPLETE_REGISTRATION: 270 fRoster->HandleCompleteRegistration(message); 271 break; 272 case B_REG_IS_APP_REGISTERED: 273 fRoster->HandleIsAppRegistered(message); 274 break; 275 case B_REG_REMOVE_PRE_REGISTERED_APP: 276 fRoster->HandleRemovePreRegApp(message); 277 break; 278 case B_REG_REMOVE_APP: 279 fRoster->HandleRemoveApp(message); 280 break; 281 case B_REG_SET_THREAD_AND_TEAM: 282 fRoster->HandleSetThreadAndTeam(message); 283 break; 284 case B_REG_SET_SIGNATURE: 285 fRoster->HandleSetSignature(message); 286 break; 287 case B_REG_GET_APP_INFO: 288 fRoster->HandleGetAppInfo(message); 289 break; 290 case B_REG_GET_APP_LIST: 291 fRoster->HandleGetAppList(message); 292 break; 293 case B_REG_UPDATE_ACTIVE_APP: 294 fRoster->HandleUpdateActiveApp(message); 295 break; 296 case B_REG_BROADCAST: 297 fRoster->HandleBroadcast(message); 298 break; 299 case B_REG_START_WATCHING: 300 fRoster->HandleStartWatching(message); 301 break; 302 case B_REG_STOP_WATCHING: 303 fRoster->HandleStopWatching(message); 304 break; 305 case B_REG_GET_RECENT_DOCUMENTS: 306 fRoster->HandleGetRecentDocuments(message); 307 break; 308 case B_REG_GET_RECENT_FOLDERS: 309 fRoster->HandleGetRecentFolders(message); 310 break; 311 case B_REG_GET_RECENT_APPS: 312 fRoster->HandleGetRecentApps(message); 313 break; 314 case B_REG_ADD_TO_RECENT_DOCUMENTS: 315 fRoster->HandleAddToRecentDocuments(message); 316 break; 317 case B_REG_ADD_TO_RECENT_FOLDERS: 318 fRoster->HandleAddToRecentFolders(message); 319 break; 320 case B_REG_ADD_TO_RECENT_APPS: 321 fRoster->HandleAddToRecentApps(message); 322 break; 323 case B_REG_CLEAR_RECENT_DOCUMENTS: 324 fRoster->ClearRecentDocuments(); 325 break; 326 case B_REG_CLEAR_RECENT_FOLDERS: 327 fRoster->ClearRecentFolders(); 328 break; 329 case B_REG_CLEAR_RECENT_APPS: 330 fRoster->ClearRecentApps(); 331 break; 332 case B_REG_LOAD_RECENT_LISTS: 333 fRoster->HandleLoadRecentLists(message); 334 break; 335 case B_REG_SAVE_RECENT_LISTS: 336 fRoster->HandleSaveRecentLists(message); 337 break; 338 339 // message runner requests 340 case B_REG_REGISTER_MESSAGE_RUNNER: 341 fMessageRunnerManager->HandleRegisterRunner(message); 342 break; 343 case B_REG_UNREGISTER_MESSAGE_RUNNER: 344 fMessageRunnerManager->HandleUnregisterRunner(message); 345 break; 346 case B_REG_SET_MESSAGE_RUNNER_PARAMS: 347 fMessageRunnerManager->HandleSetRunnerParams(message); 348 break; 349 case B_REG_GET_MESSAGE_RUNNER_INFO: 350 fMessageRunnerManager->HandleGetRunnerInfo(message); 351 break; 352 353 // package watching requests 354 case B_REG_PACKAGE_START_WATCHING: 355 case B_REG_PACKAGE_STOP_WATCHING: 356 fPackageWatchingManager->HandleStartStopWatching(message); 357 break; 358 case B_PACKAGE_UPDATE: 359 fPackageWatchingManager->NotifyWatchers(message); 360 break; 361 362 // internal messages 363 case B_SYSTEM_OBJECT_UPDATE: 364 { 365 team_id team = (team_id)message->GetInt32("team", -1); 366 if (team >= 0 && message->GetInt32("opcode", 0) == B_TEAM_DELETED) 367 fRoster->HandleRemoveApp(message); 368 break; 369 } 370 case B_REG_SHUTDOWN_FINISHED: 371 if (fShutdownProcess) { 372 fShutdownProcess->PostMessage(B_QUIT_REQUESTED, 373 fShutdownProcess); 374 fShutdownProcess = NULL; 375 } 376 break; 377 378 case kMsgRestartAppServer: 379 { 380 fRoster->HandleRestartAppServer(message); 381 break; 382 } 383 384 default: 385 BApplication::MessageReceived(message); 386 break; 387 } 388 } 389 390 391 /*! \brief Handle a shut down request message. 392 \param request The request to be handled. 393 */ 394 void 395 Registrar::_HandleShutDown(BMessage *request) 396 { 397 status_t error = B_OK; 398 399 // check, whether we're already shutting down 400 if (fShutdownProcess) 401 error = B_SHUTTING_DOWN; 402 403 bool needsReply = true; 404 if (error == B_OK) { 405 // create a ShutdownProcess 406 fShutdownProcess = new(nothrow) ShutdownProcess(fRoster, fEventQueue); 407 if (fShutdownProcess) { 408 error = fShutdownProcess->Init(request); 409 if (error == B_OK) { 410 DetachCurrentMessage(); 411 fShutdownProcess->Run(); 412 needsReply = false; 413 } else { 414 delete fShutdownProcess; 415 fShutdownProcess = NULL; 416 } 417 } else 418 error = B_NO_MEMORY; 419 } 420 421 if (needsReply) 422 ShutdownProcess::SendReply(request, error); 423 } 424 425 426 /*! \brief Handle a is shut down in progress request message. 427 \param request The request to be handled. 428 */ 429 void 430 Registrar::_HandleIsShutDownInProgress(BMessage *request) 431 { 432 BMessage reply(B_REG_SUCCESS); 433 reply.AddBool("in-progress", fShutdownProcess != NULL); 434 request->SendReply(&reply); 435 } 436 437 438 // #pragma mark - 439 440 441 /*! \brief Creates and runs the registrar application. 442 443 The main thread is renamed. 444 445 \return 0. 446 */ 447 int 448 main() 449 { 450 FUNCTION_START(); 451 452 // Create the global be_clipboard manually -- it will not work, since it 453 // wants to talk to the registrar in its constructor, but it doesn't have 454 // to and we would otherwise deadlock when initializing our GUI in the 455 // app thread. 456 be_clipboard = new BClipboard(NULL); 457 458 // create and run the registrar application 459 status_t error; 460 Registrar *app = new Registrar(&error); 461 if (error != B_OK) { 462 fprintf(stderr, "REG: Failed to create the BApplication: %s\n", 463 strerror(error)); 464 return 1; 465 } 466 467 // rename the main thread 468 rename_thread(find_thread(NULL), "roster"); 469 470 PRINT("app->Run()...\n"); 471 472 try { 473 app->Run(); 474 } catch (std::exception& exception) { 475 char buffer[1024]; 476 snprintf(buffer, sizeof(buffer), 477 "registrar main() caught exception: %s", exception.what()); 478 debugger(buffer); 479 } catch (...) { 480 debugger("registrar main() caught unknown exception"); 481 } 482 483 PRINT("delete app...\n"); 484 delete app; 485 486 FUNCTION_END(); 487 return 0; 488 } 489 490