1 // Registrar.cpp 2 3 #include "Debug.h" 4 5 #include <stdio.h> 6 #include <string.h> 7 8 #include <Application.h> 9 #include <Message.h> 10 #include <OS.h> 11 #include <RegistrarDefs.h> 12 #include <RosterPrivate.h> 13 14 #include "ClipboardHandler.h" 15 #include "EventQueue.h" 16 #include "MessageDeliverer.h" 17 #include "MessageEvent.h" 18 #include "MessageRunnerManager.h" 19 #include "MessagingService.h" 20 #include "MIMEManager.h" 21 #include "Registrar.h" 22 #include "ShutdownProcess.h" 23 #include "TRoster.h" 24 25 /*! 26 \class Registrar 27 \brief The application class of the registrar. 28 29 Glues the registrar services together and dispatches the roster messages. 30 */ 31 32 using std::nothrow; 33 using namespace BPrivate; 34 35 //! Name of the event queue. 36 static const char *kEventQueueName = "timer_thread"; 37 38 //! Time interval between two roster sanity checks (1 s). 39 static const bigtime_t kRosterSanityEventInterval = 1000000LL; 40 41 // constructor 42 /*! \brief Creates the registrar application class. 43 \param error Passed to the BApplication constructor for returning an 44 error code. 45 */ 46 Registrar::Registrar(status_t *error) 47 : BServer(kRegistrarSignature, false, error), 48 fRoster(NULL), 49 fClipboardHandler(NULL), 50 fMIMEManager(NULL), 51 fEventQueue(NULL), 52 fMessageRunnerManager(NULL), 53 fSanityEvent(NULL), 54 fShutdownProcess(NULL) 55 { 56 FUNCTION_START(); 57 } 58 59 // destructor 60 /*! \brief Frees all resources associated with the registrar. 61 62 All registrar services, that haven't been shut down earlier, are 63 terminated. 64 */ 65 Registrar::~Registrar() 66 { 67 FUNCTION_START(); 68 Lock(); 69 fEventQueue->Die(); 70 delete fMessageRunnerManager; 71 delete fEventQueue; 72 delete fSanityEvent; 73 fMIMEManager->Lock(); 74 fMIMEManager->Quit(); 75 RemoveHandler(fClipboardHandler); 76 delete fClipboardHandler; 77 delete fRoster; 78 // Invalidate the global be_roster, so that the BApplication destructor 79 // won't dead-lock when sending a message to itself. 80 BRoster::Private().SetTo(BMessenger(), BMessenger()); 81 FUNCTION_END(); 82 } 83 84 // MessageReceived 85 /*! \brief Overrides the super class version to dispatch roster specific 86 messages. 87 \param message The message to be handled 88 */ 89 void 90 Registrar::MessageReceived(BMessage *message) 91 { 92 switch (message->what) { 93 // general requests 94 case B_REG_GET_MIME_MESSENGER: 95 { 96 PRINT(("B_REG_GET_MIME_MESSENGER\n")); 97 BMessenger messenger(NULL, fMIMEManager); 98 BMessage reply(B_REG_SUCCESS); 99 reply.AddMessenger("messenger", messenger); 100 message->SendReply(&reply); 101 break; 102 } 103 104 case B_REG_GET_CLIPBOARD_MESSENGER: 105 { 106 PRINT(("B_REG_GET_CLIPBOARD_MESSENGER\n")); 107 BMessenger messenger(fClipboardHandler); 108 BMessage reply(B_REG_SUCCESS); 109 reply.AddMessenger("messenger", messenger); 110 message->SendReply(&reply); 111 break; 112 } 113 114 case B_REG_SHUT_DOWN: 115 { 116 PRINT(("B_REG_SHUT_DOWN\n")); 117 118 _HandleShutDown(message); 119 break; 120 } 121 122 // roster requests 123 case B_REG_ADD_APP: 124 fRoster->HandleAddApplication(message); 125 break; 126 case B_REG_COMPLETE_REGISTRATION: 127 fRoster->HandleCompleteRegistration(message); 128 break; 129 case B_REG_IS_APP_REGISTERED: 130 fRoster->HandleIsAppRegistered(message); 131 break; 132 case B_REG_REMOVE_PRE_REGISTERED_APP: 133 fRoster->HandleRemovePreRegApp(message); 134 break; 135 case B_REG_REMOVE_APP: 136 fRoster->HandleRemoveApp(message); 137 break; 138 case B_REG_SET_THREAD_AND_TEAM: 139 fRoster->HandleSetThreadAndTeam(message); 140 break; 141 case B_REG_SET_SIGNATURE: 142 fRoster->HandleSetSignature(message); 143 break; 144 case B_REG_GET_APP_INFO: 145 fRoster->HandleGetAppInfo(message); 146 break; 147 case B_REG_GET_APP_LIST: 148 fRoster->HandleGetAppList(message); 149 break; 150 case B_REG_ACTIVATE_APP: 151 fRoster->HandleActivateApp(message); 152 break; 153 case B_REG_BROADCAST: 154 fRoster->HandleBroadcast(message); 155 break; 156 case B_REG_START_WATCHING: 157 fRoster->HandleStartWatching(message); 158 break; 159 case B_REG_STOP_WATCHING: 160 fRoster->HandleStopWatching(message); 161 break; 162 case B_REG_GET_RECENT_DOCUMENTS: 163 fRoster->HandleGetRecentDocuments(message); 164 break; 165 case B_REG_GET_RECENT_FOLDERS: 166 fRoster->HandleGetRecentFolders(message); 167 break; 168 case B_REG_GET_RECENT_APPS: 169 fRoster->HandleGetRecentApps(message); 170 break; 171 case B_REG_ADD_TO_RECENT_DOCUMENTS: 172 fRoster->HandleAddToRecentDocuments(message); 173 break; 174 case B_REG_ADD_TO_RECENT_FOLDERS: 175 fRoster->HandleAddToRecentFolders(message); 176 break; 177 case B_REG_ADD_TO_RECENT_APPS: 178 fRoster->HandleAddToRecentApps(message); 179 break; 180 case B_REG_CLEAR_RECENT_DOCUMENTS: 181 fRoster->ClearRecentDocuments(); 182 break; 183 case B_REG_CLEAR_RECENT_FOLDERS: 184 fRoster->ClearRecentFolders(); 185 break; 186 case B_REG_CLEAR_RECENT_APPS: 187 fRoster->ClearRecentApps(); 188 break; 189 case B_REG_LOAD_RECENT_LISTS: 190 fRoster->HandleLoadRecentLists(message); 191 break; 192 case B_REG_SAVE_RECENT_LISTS: 193 fRoster->HandleSaveRecentLists(message); 194 break; 195 196 // message runner requests 197 case B_REG_REGISTER_MESSAGE_RUNNER: 198 fMessageRunnerManager->HandleRegisterRunner(message); 199 break; 200 case B_REG_UNREGISTER_MESSAGE_RUNNER: 201 fMessageRunnerManager->HandleUnregisterRunner(message); 202 break; 203 case B_REG_SET_MESSAGE_RUNNER_PARAMS: 204 fMessageRunnerManager->HandleSetRunnerParams(message); 205 break; 206 case B_REG_GET_MESSAGE_RUNNER_INFO: 207 fMessageRunnerManager->HandleGetRunnerInfo(message); 208 break; 209 210 // internal messages 211 case B_REG_ROSTER_SANITY_EVENT: 212 fRoster->CheckSanity(); 213 fSanityEvent->SetTime(system_time() + kRosterSanityEventInterval); 214 fEventQueue->AddEvent(fSanityEvent); 215 break; 216 case B_REG_SHUTDOWN_FINISHED: 217 if (fShutdownProcess) { 218 fShutdownProcess->PostMessage(B_QUIT_REQUESTED, 219 fShutdownProcess); 220 fShutdownProcess = NULL; 221 } 222 break; 223 224 default: 225 BApplication::MessageReceived(message); 226 break; 227 } 228 } 229 230 // ReadyToRun 231 /*! \brief Overrides the super class version to initialize the registrar 232 services. 233 */ 234 void 235 Registrar::ReadyToRun() 236 { 237 FUNCTION_START(); 238 239 // create message deliverer 240 status_t error = MessageDeliverer::CreateDefault(); 241 if (error != B_OK) { 242 FATAL(("Registrar::ReadyToRun(): Failed to create the message " 243 "deliverer: %s\n", strerror(error))); 244 } 245 246 // create event queue 247 fEventQueue = new EventQueue(kEventQueueName); 248 249 // create roster 250 fRoster = new TRoster; 251 fRoster->Init(); 252 253 // create clipboard handler 254 fClipboardHandler = new ClipboardHandler; 255 AddHandler(fClipboardHandler); 256 257 // create MIME manager 258 fMIMEManager = new MIMEManager; 259 fMIMEManager->Run(); 260 261 // create message runner manager 262 fMessageRunnerManager = new MessageRunnerManager(fEventQueue); 263 264 // init the global be_roster 265 BRoster::Private().SetTo(be_app_messenger, BMessenger(NULL, fMIMEManager)); 266 267 // create the messaging service 268 error = MessagingService::CreateDefault(); 269 if (error != B_OK) { 270 ERROR(("Registrar::ReadyToRun(): Failed to init messaging service " 271 "(that's by design when running under R5): %s\n", strerror(error))); 272 } 273 274 // create and schedule the sanity message event 275 fSanityEvent = new MessageEvent(system_time() + kRosterSanityEventInterval, 276 this, B_REG_ROSTER_SANITY_EVENT); 277 fSanityEvent->SetAutoDelete(false); 278 fEventQueue->AddEvent(fSanityEvent); 279 280 FUNCTION_END(); 281 } 282 283 // QuitRequested 284 /*! \brief Overrides the super class version to avoid termination of the 285 registrar until the system shutdown. 286 */ 287 bool 288 Registrar::QuitRequested() 289 { 290 FUNCTION_START(); 291 // The final registrar must not quit. At least not that easily. ;-) 292 return BApplication::QuitRequested(); 293 } 294 295 // GetEventQueue 296 /*! \brief Returns the registrar's event queue. 297 \return The registrar's event queue. 298 */ 299 EventQueue* 300 Registrar::GetEventQueue() const 301 { 302 return fEventQueue; 303 } 304 305 // App 306 /*! \brief Returns the Registrar application object. 307 \return The Registrar application object. 308 */ 309 Registrar* 310 Registrar::App() 311 { 312 return dynamic_cast<Registrar*>(be_app); 313 } 314 315 // _HandleShutDown 316 /*! \brief Handle a shut down request message. 317 \param request The request to be handled. 318 */ 319 void 320 Registrar::_HandleShutDown(BMessage *request) 321 { 322 status_t error = B_OK; 323 324 // check, whether we're already shutting down 325 if (fShutdownProcess) 326 error = B_SHUTTING_DOWN; 327 328 bool needsReply = true; 329 if (error == B_OK) { 330 // create a ShutdownProcess 331 fShutdownProcess = new(nothrow) ShutdownProcess(fRoster, fEventQueue); 332 if (fShutdownProcess) { 333 error = fShutdownProcess->Init(request); 334 if (error == B_OK) { 335 DetachCurrentMessage(); 336 fShutdownProcess->Run(); 337 needsReply = false; 338 } else { 339 delete fShutdownProcess; 340 fShutdownProcess = NULL; 341 } 342 } else 343 error = B_NO_MEMORY; 344 } 345 346 if (needsReply) 347 ShutdownProcess::SendReply(request, error); 348 } 349 350 // main 351 /*! \brief Creates and runs the registrar application. 352 353 The main thread is renamed. 354 355 \return 0. 356 */ 357 int 358 main() 359 { 360 FUNCTION_START(); 361 362 // create and run the registrar application 363 status_t error; 364 Registrar *app = new Registrar(&error); 365 if (error != B_OK) { 366 fprintf(stderr, "REG: Failed to create the BApplication: %s\n", 367 strerror(error)); 368 return 1; 369 } 370 371 // rename the main thread 372 rename_thread(find_thread(NULL), kRosterThreadName); 373 374 PRINT(("app->Run()...\n")); 375 app->Run(); 376 377 PRINT(("delete app...\n")); 378 delete app; 379 380 FUNCTION_END(); 381 return 0; 382 } 383 384