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