xref: /haiku/src/servers/registrar/Registrar.cpp (revision 3cb015b1ee509d69c643506e8ff573808c86dcfc)
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