xref: /haiku/src/kits/app/Handler.cpp (revision 0c66734e4da3cdd60a0552014b0f46275a358796)
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 };
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 == NULL)
188 		return B_OK;
189 
190 	return data->AddString(kArchiveNameField, fName);
191 }
192 
193 
194 void
195 BHandler::MessageReceived(BMessage* message)
196 {
197 	BMessage reply(B_REPLY);
198 
199 	switch (message->what) {
200 		case kMsgStartObserving:
201 		case kMsgStopObserving:
202 		{
203 			BMessenger target;
204 			uint32 what;
205 			if (message->FindMessenger(kObserveTarget, &target) != B_OK
206 				|| message->FindInt32(B_OBSERVE_WHAT_CHANGE, (int32*)&what)
207 					!= B_OK) {
208 				break;
209 			}
210 
211 			ObserverList* list = _ObserverList();
212 			if (list != NULL) {
213 				if (message->what == kMsgStartObserving)
214 					list->Add(target, what);
215 				else
216 					list->Remove(target, what);
217 			}
218 			break;
219 		}
220 
221 		case B_GET_PROPERTY:
222 		{
223 			int32 cur;
224 			BMessage specifier;
225 			int32 form;
226 			const char* prop;
227 
228 			status_t err = message->GetCurrentSpecifier(&cur, &specifier,
229 				&form, &prop);
230 			if (err != B_OK && err != B_BAD_SCRIPT_SYNTAX)
231 				break;
232 			bool known = false;
233 			// B_BAD_SCRIPT_SYNTAX defaults to the Messenger property
234 			if (err == B_BAD_SCRIPT_SYNTAX || cur < 0
235 				|| (strcmp(prop, "Messenger") == 0)) {
236 				err = reply.AddMessenger("result", this);
237 				known = true;
238 			} else if (strcmp(prop, "Suites") == 0) {
239 				err = GetSupportedSuites(&reply);
240 				known = true;
241 			} else if (strcmp(prop, "InternalName") == 0) {
242 				err = reply.AddString("result", Name());
243 				known = true;
244 			}
245 
246 			if (known) {
247 				reply.AddInt32("error", B_OK);
248 				message->SendReply(&reply);
249 				return;
250 			}
251 			// let's try next handler
252 			break;
253 		}
254 
255 		case B_GET_SUPPORTED_SUITES:
256 		{
257 			reply.AddInt32("error", GetSupportedSuites(&reply));
258 			message->SendReply(&reply);
259 			return;
260 		}
261 	}
262 
263 	// ToDo: there is some more work needed here
264 	// (someone in the know should fill in)!
265 
266 	if (fNextHandler) {
267 		// we need to apply the next handler's filters here, too
268 		BHandler* target = Looper()->_HandlerFilter(message, fNextHandler);
269 		if (target != NULL && target != this) {
270 			// TODO: we also need to make sure that "target" is not before
271 			//	us in the handler chain - at least in case it wasn't before
272 			//	the handler actually targeted with this message - this could
273 			//	get ugly, though.
274 			target->MessageReceived(message);
275 		}
276 	} else if (message->what != B_MESSAGE_NOT_UNDERSTOOD
277 		&& (message->WasDropped() || message->HasSpecifiers())) {
278 		printf("BHandler %s: MessageReceived() couldn't understand the message:\n", Name());
279 		message->PrintToStream();
280 		message->SendReply(B_MESSAGE_NOT_UNDERSTOOD);
281 	}
282 }
283 
284 
285 BLooper*
286 BHandler::Looper() const
287 {
288 	return fLooper;
289 }
290 
291 
292 void
293 BHandler::SetName(const char* name)
294 {
295 	if (fName != NULL) {
296 		free(fName);
297 		fName = NULL;
298 	}
299 
300 	if (name != NULL)
301 		fName = strdup(name);
302 }
303 
304 
305 const char*
306 BHandler::Name() const
307 {
308 	return fName;
309 }
310 
311 
312 void
313 BHandler::SetNextHandler(BHandler* handler)
314 {
315 	if (fLooper == NULL) {
316 		debugger("handler must belong to looper before setting NextHandler");
317 		return;
318 	}
319 
320 	if (!fLooper->IsLocked()) {
321 		debugger("The handler's looper must be locked before setting NextHandler");
322 		return;
323 	}
324 
325 	if (handler != NULL && fLooper != handler->Looper()) {
326 		debugger("The handler and its NextHandler must have the same looper");
327 		return;
328 	}
329 
330 	fNextHandler = handler;
331 }
332 
333 
334 BHandler*
335 BHandler::NextHandler() const
336 {
337 	return fNextHandler;
338 }
339 
340 
341 void
342 BHandler::AddFilter(BMessageFilter* filter)
343 {
344 	BLooper* looper = fLooper;
345 	if (looper != NULL && !looper->IsLocked()) {
346 		debugger("Owning Looper must be locked before calling SetFilterList");
347 		return;
348 	}
349 
350 	if (looper != NULL)
351 		filter->SetLooper(looper);
352 
353 	if (fFilters == NULL)
354 		fFilters = new BList;
355 
356 	fFilters->AddItem(filter);
357 }
358 
359 
360 bool
361 BHandler::RemoveFilter(BMessageFilter* filter)
362 {
363 	BLooper* looper = fLooper;
364 	if (looper != NULL && !looper->IsLocked()) {
365 		debugger("Owning Looper must be locked before calling SetFilterList");
366 		return false;
367 	}
368 
369 	if (fFilters != NULL && fFilters->RemoveItem((void*)filter)) {
370 		filter->SetLooper(NULL);
371 		return true;
372 	}
373 
374 	return false;
375 }
376 
377 
378 void
379 BHandler::SetFilterList(BList* filters)
380 {
381 	BLooper* looper = fLooper;
382 	if (looper != NULL && !looper->IsLocked()) {
383 		debugger("Owning Looper must be locked before calling SetFilterList");
384 		return;
385 	}
386 
387 	/**
388 		@note	I would like to use BObjectList internally, but this function is
389 				spec'd such that fFilters would get deleted and then assigned
390 				'filters', which would obviously mess this up.  Wondering if
391 				anyone ever assigns a list of filters and then checks against
392 				FilterList() to see if they are the same.
393 	 */
394 
395 	// TODO: Explore issues with using BObjectList
396 	if (fFilters != NULL) {
397 		fFilters->DoForEach(FilterDeleter);
398 		delete fFilters;
399 	}
400 
401 	fFilters = filters;
402 	if (fFilters) {
403 		for (int32 i = 0; i < fFilters->CountItems(); ++i) {
404 			BMessageFilter* filter =
405 				static_cast<BMessageFilter*>(fFilters->ItemAt(i));
406 			if (filter != NULL)
407 				filter->SetLooper(looper);
408 		}
409 	}
410 }
411 
412 
413 BList*
414 BHandler::FilterList()
415 {
416 	return fFilters;
417 }
418 
419 
420 bool
421 BHandler::LockLooper()
422 {
423 	BLooper* looper = fLooper;
424 	// Locking the looper also makes sure that the looper is valid
425 	if (looper != NULL && looper->Lock()) {
426 		// Have we locked the right looper? That's as far as the
427 		// "pseudo-atomic" operation mentioned in the BeBook.
428 		if (fLooper == looper)
429 			return true;
430 
431 		// we locked the wrong looper, bail out
432 		looper->Unlock();
433 	}
434 
435 	return false;
436 }
437 
438 
439 status_t
440 BHandler::LockLooperWithTimeout(bigtime_t timeout)
441 {
442 	BLooper* looper = fLooper;
443 	if (looper == NULL)
444 		return B_BAD_VALUE;
445 
446 	status_t status = looper->LockWithTimeout(timeout);
447 	if (status != B_OK)
448 		return status;
449 
450 	if (fLooper != looper) {
451 		// we locked the wrong looper, bail out
452 		looper->Unlock();
453 		return B_MISMATCHED_VALUES;
454 	}
455 
456 	return B_OK;
457 }
458 
459 
460 void
461 BHandler::UnlockLooper()
462 {
463 	fLooper->Unlock();
464 }
465 
466 
467 BHandler*
468 BHandler::ResolveSpecifier(BMessage* message, int32 index,
469 	BMessage* specifier, int32 what, const char* property)
470 {
471 	// Straight from the BeBook
472 	BPropertyInfo propertyInfo(sHandlerPropInfo);
473 	if (propertyInfo.FindMatch(message, index, specifier, what, property) >= 0)
474 		return this;
475 
476 	BMessage reply(B_MESSAGE_NOT_UNDERSTOOD);
477 	reply.AddInt32("error", B_BAD_SCRIPT_SYNTAX);
478 	reply.AddString("message", "Didn't understand the specifier(s)");
479 	message->SendReply(&reply);
480 
481 	return NULL;
482 }
483 
484 
485 status_t
486 BHandler::GetSupportedSuites(BMessage* data)
487 {
488 /**
489 	@note	This is the output from the original implementation (calling
490 			PrintToStream() on both data and the contained BPropertyInfo):
491 
492 BMessage: what =  (0x0, or 0)
493 	entry         suites, type='CSTR', c=1, size=21, data[0]: "suite/vnd.Be-handler"
494 	entry       messages, type='SCTD', c=1, size= 0,
495 	  property   commands                       types                specifiers
496 --------------------------------------------------------------------------------
497 		Suites   PGET                                               1
498 				 (RTSC,suites)
499 				 (DTCS,messages)
500 
501 	 Messenger   PGET                          GNSM                 1
502   InternalName   PGET                          RTSC                 1
503 
504 			With a good deal of trial and error, I determined that the
505 			parenthetical clauses are entries in the 'ctypes' field of
506 			property_info.  'ctypes' is an array of 'compound_type', which
507 			contains an array of 'field_pair's.  I haven't the foggiest what
508 			either 'compound_type' or 'field_pair' is for, being as the
509 			scripting docs are so bloody horrible.  The corresponding
510 			property_info array is declared in the globals section.
511  */
512 
513 	if (data == NULL)
514 		return B_BAD_VALUE;
515 
516 	status_t result = data->AddString("suites", "suite/vnd.Be-handler");
517 	if (result == B_OK) {
518 		BPropertyInfo propertyInfo(sHandlerPropInfo);
519 		result = data->AddFlat("messages", &propertyInfo);
520 	}
521 
522 	return result;
523 }
524 
525 
526 status_t
527 BHandler::StartWatching(BMessenger target, uint32 what)
528 {
529 	BMessage message(kMsgStartObserving);
530 	message.AddMessenger(kObserveTarget, this);
531 	message.AddInt32(B_OBSERVE_WHAT_CHANGE, what);
532 
533 	return target.SendMessage(&message);
534 }
535 
536 
537 status_t
538 BHandler::StartWatchingAll(BMessenger target)
539 {
540 	return StartWatching(target, B_OBSERVER_OBSERVE_ALL);
541 }
542 
543 
544 status_t
545 BHandler::StopWatching(BMessenger target, uint32 what)
546 {
547 	BMessage message(kMsgStopObserving);
548 	message.AddMessenger(kObserveTarget, this);
549 	message.AddInt32(B_OBSERVE_WHAT_CHANGE, what);
550 
551 	return target.SendMessage(&message);
552 }
553 
554 
555 status_t
556 BHandler::StopWatchingAll(BMessenger target)
557 {
558 	return StopWatching(target, B_OBSERVER_OBSERVE_ALL);
559 }
560 
561 
562 status_t
563 BHandler::StartWatching(BHandler* handler, uint32 what)
564 {
565 	ObserverList* list = _ObserverList();
566 	if (list == NULL)
567 		return B_NO_MEMORY;
568 
569 	return list->Add(handler, what);
570 }
571 
572 
573 status_t
574 BHandler::StartWatchingAll(BHandler* handler)
575 {
576 	return StartWatching(handler, B_OBSERVER_OBSERVE_ALL);
577 }
578 
579 
580 status_t
581 BHandler::StopWatching(BHandler* handler, uint32 what)
582 {
583 	ObserverList* list = _ObserverList();
584 	if (list == NULL)
585 		return B_NO_MEMORY;
586 
587 	return list->Remove(handler, what);
588 }
589 
590 
591 status_t
592 BHandler::StopWatchingAll(BHandler* handler)
593 {
594 	return StopWatching(handler, B_OBSERVER_OBSERVE_ALL);
595 }
596 
597 
598 status_t
599 BHandler::Perform(perform_code d, void* arg)
600 {
601 	return BArchivable::Perform(d, arg);
602 }
603 
604 
605 void
606 BHandler::SendNotices(uint32 what, const BMessage* notice)
607 {
608 	if (fObserverList != NULL)
609 		fObserverList->SendNotices(what, notice);
610 }
611 
612 
613 bool
614 BHandler::IsWatched() const
615 {
616 	return fObserverList && !fObserverList->IsEmpty();
617 }
618 
619 
620 void
621 BHandler::_InitData(const char* name)
622 {
623 	SetName(name);
624 
625 	fLooper = NULL;
626 	fNextHandler = NULL;
627 	fFilters = NULL;
628 	fObserverList = NULL;
629 
630 	fToken = gDefaultTokens.NewToken(B_HANDLER_TOKEN, this);
631 }
632 
633 
634 ObserverList*
635 BHandler::_ObserverList()
636 {
637 	if (fObserverList == NULL)
638 		fObserverList = new (std::nothrow) BPrivate::ObserverList();
639 
640 	return fObserverList;
641 }
642 
643 
644 BHandler::BHandler(const BHandler &)
645 {
646 	// No copy construction allowed.
647 }
648 
649 
650 BHandler &
651 BHandler::operator=(const BHandler &)
652 {
653 	// No assignments allowed.
654 	return *this;
655 }
656 
657 
658 void
659 BHandler::SetLooper(BLooper* looper)
660 {
661 	fLooper = looper;
662 	gDefaultTokens.SetHandlerTarget(fToken,
663 		looper ? looper->fDirectTarget : NULL);
664 
665 	if (fFilters != NULL) {
666 		for (int32 i = 0; i < fFilters->CountItems(); i++) {
667 			static_cast<BMessageFilter*>(
668 				fFilters->ItemAtFast(i))->SetLooper(looper);
669 		}
670 	}
671 }
672 
673 
674 #if __GNUC__ < 3
675 // binary compatibility with R4.5
676 
677 extern "C" void
678 _ReservedHandler1__8BHandler(BHandler* handler, uint32 what,
679 	const BMessage* notice)
680 {
681 	handler->BHandler::SendNotices(what, notice);
682 }
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