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