xref: /haiku/src/kits/app/Handler.cpp (revision fc1ca2da5cfcb00ffdf791606d5ae97fdd58a638)
1 /*
2  * Copyright 2001-2007, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Erik Jaesler (erik@cgsoftware.com)
7  *		Axel Dörfler, axeld@pinc-software.de
8  */
9 
10 
11 #include <TokenSpace.h>
12 
13 #include <AppDefs.h>
14 #include <Handler.h>
15 #include <Looper.h>
16 #include <Message.h>
17 #include <MessageFilter.h>
18 #include <Messenger.h>
19 #include <PropertyInfo.h>
20 
21 #include <algorithm>
22 #include <new>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <vector>
27 
28 using std::map;
29 using std::vector;
30 using BPrivate::gDefaultTokens;
31 
32 
33 static const char* kArchiveNameField = "_name";
34 
35 static const uint32 kMsgStartObserving = '_OBS';
36 static const uint32 kMsgStopObserving = '_OBP';
37 static const char* kObserveTarget = "be:observe_target";
38 
39 
40 static property_info sHandlerPropInfo[] = {
41 	{
42 		"Suites",					// name
43 		{ B_GET_PROPERTY },			// commands
44 		{ B_DIRECT_SPECIFIER },		// specifiers
45 		NULL,						// usage
46 		0,							// extra data
47 		{ 0 },						// types
48 		{							// ctypes (compound_type)
49 			{						// ctypes[0]
50 				{					// pairs[0]
51 					{
52 						"suites",		// name
53 						B_STRING_TYPE	// type
54 					}
55 				}
56 			},
57 			{						// ctypes[1]
58 				{					// pairs[0]
59 					{
60 						"messages",
61 						B_PROPERTY_INFO_TYPE
62 					}
63 				}
64 			}
65 		},
66 		{}		// reserved
67 	},
68 	{
69 		"Messenger",
70 			{ B_GET_PROPERTY },
71 			{ B_DIRECT_SPECIFIER },
72 			NULL, 0,
73 			{ B_MESSENGER_TYPE },
74 			{},
75 			{}
76 	},
77 	{
78 		"InternalName",
79 			{ B_GET_PROPERTY },
80 			{ B_DIRECT_SPECIFIER },
81 			NULL, 0,
82 			{ B_STRING_TYPE },
83 			{},
84 			{}
85 	},
86 	{}
87 };
88 
89 bool FilterDeleter(void *filter);
90 
91 namespace BPrivate {
92 
93 class ObserverList {
94 	public:
95 		ObserverList();
96 		~ObserverList();
97 
98 		status_t SendNotices(uint32 what, const BMessage* notice);
99 		status_t Add(const BHandler* handler, uint32 what);
100 		status_t Add(const BMessenger& messenger, uint32 what);
101 		status_t Remove(const BHandler* handler, uint32 what);
102 		status_t Remove(const BMessenger& messenger, uint32 what);
103 		bool IsEmpty();
104 
105 	private:
106 		typedef map<uint32, vector<const BHandler *> > HandlerObserverMap;
107 		typedef map<uint32, vector<BMessenger> > MessengerObserverMap;
108 
109 		void _ValidateHandlers(uint32 what);
110 		void _SendNotices(uint32 what, BMessage* notice);
111 
112 		HandlerObserverMap		fHandlerMap;
113 		MessengerObserverMap	fMessengerMap;
114 };
115 
116 }	// namespace BPrivate
117 
118 using namespace BPrivate;
119 
120 
121 //	#pragma mark -
122 
123 
124 BHandler::BHandler(const char *name)
125 	: BArchivable(),
126 	fName(NULL)
127 {
128 	_InitData(name);
129 }
130 
131 
132 BHandler::~BHandler()
133 {
134 	// remove all filters
135 	if (fFilters) {
136 		int32 count = fFilters->CountItems();
137 		for (int32 i = 0; i < count; i++)
138 			delete (BMessageFilter*)fFilters->ItemAtFast(i);
139 		delete fFilters;
140 	}
141 
142 	// remove all observers (the observer list manages itself)
143 	delete fObserverList;
144 
145 	// free rest
146 	free(fName);
147 	gDefaultTokens.RemoveToken(fToken);
148 }
149 
150 
151 BHandler::BHandler(BMessage *data)
152 	: BArchivable(data),
153 	fName(NULL)
154 {
155 	const char *name = NULL;
156 
157 	if (data)
158 		data->FindString(kArchiveNameField, &name);
159 
160 	_InitData(name);
161 }
162 
163 
164 BArchivable *
165 BHandler::Instantiate(BMessage *data)
166 {
167 	if (!validate_instantiation(data, "BHandler"))
168 		return NULL;
169 
170 	return new BHandler(data);
171 }
172 
173 
174 status_t
175 BHandler::Archive(BMessage *data, bool deep) const
176 {
177 	status_t status = BArchivable::Archive(data, deep);
178 	if (status < B_OK)
179 		return status;
180 
181 	if (!fName)
182 		return B_OK;
183 	return data->AddString(kArchiveNameField, fName);
184 }
185 
186 
187 void
188 BHandler::MessageReceived(BMessage *message)
189 {
190 	BMessage reply(B_REPLY);
191 
192 	switch (message->what) {
193 		case kMsgStartObserving:
194 		case kMsgStopObserving:
195 		{
196 			BMessenger target;
197 			uint32 what;
198 			if (message->FindMessenger(kObserveTarget, &target) != B_OK
199 				|| message->FindInt32(B_OBSERVE_WHAT_CHANGE, (int32*)&what) != B_OK)
200 				break;
201 
202 			ObserverList* list = _ObserverList();
203 			if (list != NULL) {
204 				if (message->what == kMsgStartObserving)
205 					list->Add(target, what);
206 				else
207 					list->Remove(target, what);
208 			}
209 			break;
210 		}
211 
212 		case B_GET_PROPERTY:
213 		{
214 			int32 cur;
215 			BMessage specifier;
216 			int32 form;
217 			const char *prop;
218 
219 			status_t err = message->GetCurrentSpecifier(&cur, &specifier, &form, &prop);
220 			bool known = false;
221 			if (cur < 0 || (strcmp(prop, "Messenger") == 0)) {
222 				err = reply.AddMessenger("result", this);
223 				known = true;
224 			} else if (strcmp(prop, "Suites") == 0) {
225 				err = GetSupportedSuites(&reply);
226 				known = true;
227 			} else if (strcmp(prop, "InternalName") == 0) {
228 				err = reply.AddString("result", Name());
229 				known = true;
230 			}
231 
232 			if (known) {
233 				reply.AddInt32("error", B_OK);
234 				message->SendReply(&reply);
235 				return;
236 			}
237 			// let's try next handler
238 			break;
239 		}
240 
241 		case B_GET_SUPPORTED_SUITES:
242 		{
243 			reply.AddInt32("error", GetSupportedSuites(&reply));
244 			message->SendReply(&reply);
245 			return;
246 		}
247 	}
248 
249 	// ToDo: there is some more work needed here (someone in the know should fill in)!
250 
251 	if (fNextHandler) {
252 		// we need to apply the next handler's filters here, too
253 		BHandler* target = Looper()->_HandlerFilter(message, fNextHandler);
254 		if (target != NULL && target != this) {
255 			// TODO: we also need to make sure that "target" is not before
256 			//	us in the handler chain - at least in case it wasn't before
257 			//	the handler actually targeted with this message - this could
258 			//	get ugly, though.
259 			target->MessageReceived(message);
260 		}
261 	} else if (message->what != B_MESSAGE_NOT_UNDERSTOOD
262 		&& (message->WasDropped() || message->HasSpecifiers())) {
263 		printf("BHandler %s: MessageReceived() couldn't understand the message:\n", Name());
264 		message->PrintToStream();
265 		message->SendReply(B_MESSAGE_NOT_UNDERSTOOD);
266 	}
267 }
268 
269 
270 BLooper *
271 BHandler::Looper() const
272 {
273 	return fLooper;
274 }
275 
276 
277 void
278 BHandler::SetName(const char *name)
279 {
280 	if (fName != NULL) {
281 		free(fName);
282 		fName = NULL;
283 	}
284 
285 	if (name != NULL)
286 		fName = strdup(name);
287 }
288 
289 
290 const char *
291 BHandler::Name() const
292 {
293 	return fName;
294 }
295 
296 
297 void
298 BHandler::SetNextHandler(BHandler *handler)
299 {
300 	if (!fLooper) {
301 		debugger("handler must belong to looper before setting NextHandler");
302 		return;
303 	}
304 
305 	if (!fLooper->IsLocked()) {
306 		debugger("The handler's looper must be locked before setting NextHandler");
307 		return;
308 	}
309 
310 	if (handler && fLooper != handler->Looper()) {
311 		debugger("The handler and its NextHandler must have the same looper");
312 		return;
313 	}
314 
315 	fNextHandler = handler;
316 }
317 
318 
319 BHandler *
320 BHandler::NextHandler() const
321 {
322 	return fNextHandler;
323 }
324 
325 
326 void
327 BHandler::AddFilter(BMessageFilter *filter)
328 {
329 	if (fLooper && !fLooper->IsLocked()) {
330 		debugger("Owning Looper must be locked before calling SetFilterList");
331 		return;
332 	}
333 
334 	if (fLooper != NULL)
335 		filter->SetLooper(fLooper);
336 
337 	if (!fFilters)
338 		fFilters = new BList;
339 
340 	fFilters->AddItem(filter);
341 }
342 
343 
344 bool
345 BHandler::RemoveFilter(BMessageFilter *filter)
346 {
347 	if (fLooper && !fLooper->IsLocked()) {
348 		debugger("Owning Looper must be locked before calling SetFilterList");
349 		return false;
350 	}
351 
352 	if (fFilters != NULL && fFilters->RemoveItem((void *)filter)) {
353 		filter->SetLooper(NULL);
354 		return true;
355 	}
356 
357 	return false;
358 }
359 
360 
361 void
362 BHandler::SetFilterList(BList* filters)
363 {
364 	if (fLooper && !fLooper->IsLocked()) {
365 		debugger("Owning Looper must be locked before calling SetFilterList");
366 		return;
367 	}
368 
369 	/**
370 		@note	I would like to use BObjectList internally, but this function is
371 				spec'd such that fFilters would get deleted and then assigned
372 				'filters', which would obviously mess this up.  Wondering if
373 				anyone ever assigns a list of filters and then checks against
374 				FilterList() to see if they are the same.
375 	 */
376 
377 	// TODO: Explore issues with using BObjectList
378 	if (fFilters) {
379 		fFilters->DoForEach(FilterDeleter);
380 		delete fFilters;
381 	}
382 
383 	fFilters = filters;
384 	if (fFilters) {
385 		for (int32 i = 0; i < fFilters->CountItems(); ++i) {
386 			BMessageFilter *filter =
387 				static_cast<BMessageFilter *>(fFilters->ItemAt(i));
388 			if (filter != NULL)
389 				filter->SetLooper(fLooper);
390 		}
391 	}
392 }
393 
394 
395 BList *
396 BHandler::FilterList()
397 {
398 	return fFilters;
399 }
400 
401 
402 bool
403 BHandler::LockLooper()
404 {
405 	BLooper *looper = fLooper;
406 	// Locking the looper also makes sure that the looper is valid
407 	if (looper != NULL && looper->Lock()) {
408 		// Have we locked the right looper? That's as far as the
409 		// "pseudo-atomic" operation mentioned in the BeBook.
410 		if (fLooper == looper)
411 			return true;
412 
413 		// we locked the wrong looper, bail out
414 		looper->Unlock();
415 	}
416 
417 	return false;
418 }
419 
420 
421 status_t
422 BHandler::LockLooperWithTimeout(bigtime_t timeout)
423 {
424 	BLooper *looper = fLooper;
425 	if (looper == NULL)
426 		return B_BAD_VALUE;
427 
428 	status_t status = looper->LockWithTimeout(timeout);
429 	if (status != B_OK)
430 		return status;
431 
432 	if (fLooper != looper) {
433 		// we locked the wrong looper, bail out
434 		looper->Unlock();
435 		return B_MISMATCHED_VALUES;
436 	}
437 
438 	return B_OK;
439 }
440 
441 
442 void
443 BHandler::UnlockLooper()
444 {
445 	// The looper is locked at this point, and cannot change
446 	if (fLooper != NULL)
447 		fLooper->Unlock();
448 }
449 
450 
451 BHandler *
452 BHandler::ResolveSpecifier(BMessage *msg, int32 index,
453 	BMessage *specifier, int32 form, const char *property)
454 {
455 	// Straight from the BeBook
456 	BPropertyInfo propertyInfo(sHandlerPropInfo);
457 	if (propertyInfo.FindMatch(msg, index, specifier, form, property) >= 0)
458 		return this;
459 
460 	BMessage reply(B_MESSAGE_NOT_UNDERSTOOD);
461 	reply.AddInt32("error", B_BAD_SCRIPT_SYNTAX);
462 	reply.AddString("message", "Didn't understand the specifier(s)");
463 	msg->SendReply(&reply);
464 
465 	return NULL;
466 }
467 
468 
469 status_t
470 BHandler::GetSupportedSuites(BMessage *data)
471 {
472 /**
473 	@note	This is the output from the original implementation (calling
474 			PrintToStream() on both data and the contained BPropertyInfo):
475 
476 BMessage: what =  (0x0, or 0)
477     entry         suites, type='CSTR', c=1, size=21, data[0]: "suite/vnd.Be-handler"
478     entry       messages, type='SCTD', c=1, size= 0,
479       property   commands                       types                specifiers
480 --------------------------------------------------------------------------------
481         Suites   PGET                                               1
482                  (RTSC,suites)
483                  (DTCS,messages)
484 
485      Messenger   PGET                          GNSM                 1
486   InternalName   PGET                          RTSC                 1
487 
488 			With a good deal of trial and error, I determined that the
489 			parenthetical clauses are entries in the 'ctypes' field of
490 			property_info.  'ctypes' is an array of 'compound_type', which
491 			contains an array of 'field_pair's.  I haven't the foggiest what
492 			either 'compound_type' or 'field_pair' is for, being as the
493 			scripting docs are so bloody horrible.  The corresponding
494 			property_info array is declared in the globals section.
495  */
496 
497 	status_t err = B_OK;
498 	if (!data)
499 		err = B_BAD_VALUE;
500 
501 	if (!err) {
502 		err = data->AddString("suites", "suite/vnd.Be-handler");
503 		if (!err) {
504 			BPropertyInfo propertyInfo(sHandlerPropInfo);
505 			err = data->AddFlat("messages", &propertyInfo);
506 		}
507 	}
508 
509 	return err;
510 }
511 
512 
513 status_t
514 BHandler::StartWatching(BMessenger target, uint32 what)
515 {
516 	BMessage message(kMsgStartObserving);
517 	message.AddMessenger(kObserveTarget, this);
518 	message.AddInt32(B_OBSERVE_WHAT_CHANGE, what);
519 
520 	return target.SendMessage(&message);
521 }
522 
523 
524 status_t
525 BHandler::StartWatchingAll(BMessenger target)
526 {
527 	return StartWatching(target, B_OBSERVER_OBSERVE_ALL);
528 }
529 
530 
531 status_t
532 BHandler::StopWatching(BMessenger target, uint32 what)
533 {
534 	BMessage message(kMsgStopObserving);
535 	message.AddMessenger(kObserveTarget, this);
536 	message.AddInt32(B_OBSERVE_WHAT_CHANGE, what);
537 
538 	return target.SendMessage(&message);
539 }
540 
541 
542 status_t
543 BHandler::StopWatchingAll(BMessenger target)
544 {
545 	return StopWatching(target, B_OBSERVER_OBSERVE_ALL);
546 }
547 
548 
549 status_t
550 BHandler::StartWatching(BHandler* handler, uint32 what)
551 {
552 	ObserverList* list = _ObserverList();
553 	if (list == NULL)
554 		return B_NO_MEMORY;
555 
556 	return list->Add(handler, what);
557 }
558 
559 
560 status_t
561 BHandler::StartWatchingAll(BHandler* handler)
562 {
563 	return StartWatching(handler, B_OBSERVER_OBSERVE_ALL);
564 }
565 
566 
567 status_t
568 BHandler::StopWatching(BHandler* handler, uint32 what)
569 {
570 	ObserverList* list = _ObserverList();
571 	if (list == NULL)
572 		return B_NO_MEMORY;
573 
574 	return list->Remove(handler, what);
575 }
576 
577 
578 status_t
579 BHandler::StopWatchingAll(BHandler *handler)
580 {
581 	return StopWatching(handler, B_OBSERVER_OBSERVE_ALL);
582 }
583 
584 
585 status_t
586 BHandler::Perform(perform_code d, void *arg)
587 {
588 	return BArchivable::Perform(d, arg);
589 }
590 
591 
592 void
593 BHandler::SendNotices(uint32 what, const BMessage *msg)
594 {
595 	if (fObserverList != NULL)
596 		fObserverList->SendNotices(what, msg);
597 }
598 
599 
600 bool
601 BHandler::IsWatched() const
602 {
603 	return fObserverList && !fObserverList->IsEmpty();
604 }
605 
606 
607 void
608 BHandler::_InitData(const char *name)
609 {
610 	SetName(name);
611 
612 	fLooper = NULL;
613 	fNextHandler = NULL;
614 	fFilters = NULL;
615 	fObserverList = NULL;
616 
617 	fToken = gDefaultTokens.NewToken(B_HANDLER_TOKEN, this);
618 }
619 
620 
621 ObserverList*
622 BHandler::_ObserverList()
623 {
624 	if (fObserverList == NULL)
625 		fObserverList = new (std::nothrow) BPrivate::ObserverList();
626 
627 	return fObserverList;
628 }
629 
630 
631 BHandler::BHandler(const BHandler &)
632 {
633 	// No copy construction allowed.
634 }
635 
636 
637 BHandler &
638 BHandler::operator=(const BHandler &)
639 {
640 	// No assignments allowed.
641 	return *this;
642 }
643 
644 
645 void
646 BHandler::SetLooper(BLooper *looper)
647 {
648 	fLooper = looper;
649 	gDefaultTokens.SetHandlerTarget(fToken, looper ? looper->fDirectTarget : NULL);
650 
651 	if (fFilters) {
652 		for (int32 i = 0; i < fFilters->CountItems(); i++)
653 			static_cast<BMessageFilter *>(fFilters->ItemAtFast(i))->SetLooper(looper);
654 	}
655 }
656 
657 
658 #ifdef __INTEL__
659 // binary compatibility with R4.5
660 extern "C" void _ReservedHandler1__8BHandler(void) {}
661 #endif
662 
663 void BHandler::_ReservedHandler2() {}
664 void BHandler::_ReservedHandler3() {}
665 void BHandler::_ReservedHandler4() {}
666 
667 
668 //	#pragma mark -
669 
670 
671 ObserverList::ObserverList()
672 {
673 }
674 
675 
676 ObserverList::~ObserverList()
677 {
678 }
679 
680 
681 void
682 ObserverList::_ValidateHandlers(uint32 what)
683 {
684 	vector<const BHandler *>& handlers = fHandlerMap[what];
685 	vector<const BHandler *>::iterator iterator = handlers.begin();
686 
687 	while (iterator != handlers.end()) {
688 		BMessenger target(*iterator);
689 		if (!target.IsValid()) {
690 			iterator++;
691 			continue;
692 		}
693 
694 		Add(target, what);
695 		iterator = handlers.erase(iterator);
696 	}
697 }
698 
699 
700 void
701 ObserverList::_SendNotices(uint32 what, BMessage* message)
702 {
703 	// first iterate over the list of handlers and try to make valid messengers out of them
704 	_ValidateHandlers(what);
705 
706 	// now send it to all messengers we know
707 	vector<BMessenger>& messengers = fMessengerMap[what];
708 	vector<BMessenger>::iterator iterator = messengers.begin();
709 
710 	while (iterator != messengers.end()) {
711 		if (!(*iterator).IsValid()) {
712 			iterator = messengers.erase(iterator);
713 			continue;
714 		}
715 
716 		(*iterator).SendMessage(message);
717 		iterator++;
718 	}
719 }
720 
721 
722 status_t
723 ObserverList::SendNotices(uint32 what, const BMessage* message)
724 {
725 	BMessage *copy = NULL;
726 	if (message) {
727 		copy = new BMessage(*message);
728 		copy->what = B_OBSERVER_NOTICE_CHANGE;
729 		copy->AddInt32(B_OBSERVE_ORIGINAL_WHAT, message->what);
730 	} else
731 		copy = new BMessage(B_OBSERVER_NOTICE_CHANGE);
732 
733 	copy->AddInt32(B_OBSERVE_WHAT_CHANGE, what);
734 
735 	_SendNotices(what, copy);
736 	_SendNotices(B_OBSERVER_OBSERVE_ALL, copy);
737 
738 	delete copy;
739 	return B_OK;
740 }
741 
742 
743 status_t
744 ObserverList::Add(const BHandler *handler, uint32 what)
745 {
746 	if (handler == NULL)
747 		return B_BAD_HANDLER;
748 
749 	// if this handler already represents a valid target, add its messenger
750 	BMessenger target(handler);
751 	if (target.IsValid())
752 		return Add(target, what);
753 
754 	vector<const BHandler*> &handlers = fHandlerMap[what];
755 
756 	vector<const BHandler*>::iterator iter;
757 	iter = find(handlers.begin(), handlers.end(), handler);
758 	if (iter != handlers.end()) {
759 		// TODO: do we want to have a reference count for this?
760 		return B_OK;
761 	}
762 
763 	handlers.push_back(handler);
764 	return B_OK;
765 }
766 
767 
768 status_t
769 ObserverList::Add(const BMessenger &messenger, uint32 what)
770 {
771 	vector<BMessenger> &messengers = fMessengerMap[what];
772 
773 	vector<BMessenger>::iterator iter;
774 	iter = find(messengers.begin(), messengers.end(), messenger);
775 	if (iter != messengers.end()) {
776 		// TODO: do we want to have a reference count for this?
777 		return B_OK;
778 	}
779 
780 	messengers.push_back(messenger);
781 	return B_OK;
782 }
783 
784 
785 status_t
786 ObserverList::Remove(const BHandler *handler, uint32 what)
787 {
788 	if (handler == NULL)
789 		return B_BAD_HANDLER;
790 
791 	// look into the list of messengers
792 	BMessenger target(handler);
793 	if (target.IsValid() && Remove(target, what) == B_OK)
794 		return B_OK;
795 
796 	vector<const BHandler*> &handlers = fHandlerMap[what];
797 
798 	vector<const BHandler*>::iterator iterator = find(handlers.begin(),
799 		handlers.end(), handler);
800 	if (iterator != handlers.end()) {
801 		handlers.erase(iterator);
802 		if (handlers.empty())
803 			fHandlerMap.erase(what);
804 
805 		return B_OK;
806 	}
807 
808 	return B_BAD_HANDLER;
809 }
810 
811 
812 status_t
813 ObserverList::Remove(const BMessenger &messenger, uint32 what)
814 {
815 	vector<BMessenger> &messengers = fMessengerMap[what];
816 
817 	vector<BMessenger>::iterator iterator = find(messengers.begin(),
818 		messengers.end(), messenger);
819 	if (iterator != messengers.end()) {
820 		messengers.erase(iterator);
821 		if (messengers.empty())
822 			fMessengerMap.erase(what);
823 
824 		return B_OK;
825 	}
826 
827 	return B_BAD_HANDLER;
828 }
829 
830 
831 bool
832 ObserverList::IsEmpty()
833 {
834 	return fHandlerMap.empty() && fMessengerMap.empty();
835 }
836 
837 
838 //	#pragma mark -
839 
840 
841 bool
842 FilterDeleter(void *_filter)
843 {
844 	delete static_cast<BMessageFilter *>(_filter);
845 	return false;
846 }
847 
848