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