1 // LaunchTesterHelper.cpp 2 3 #include <stdio.h> 4 #include <string.h> 5 6 #include <Autolock.h> 7 #include <Entry.h> 8 #include <List.h> 9 #include <Message.h> 10 #include <Messenger.h> 11 #include <Path.h> 12 13 #include "LaunchTesterHelper.h" 14 #include "RosterTestAppDefs.h" 15 16 ///////////////// 17 // LaunchContext 18 19 const char *LaunchContext::kStandardArgv[] = { 20 "Some", "nice", "arguments" 21 }; 22 const int32 LaunchContext::kStandardArgc 23 = sizeof(kStandardArgv) / sizeof(const char*); 24 25 // Message 26 class LaunchContext::Message { 27 public: 28 BMessage message; 29 bigtime_t when; 30 }; 31 32 // Sleeper 33 class LaunchContext::Sleeper { 34 public: 35 Sleeper() : fMessageCode(0), fSemaphore(-1) {} 36 37 ~Sleeper() 38 { 39 delete_sem(fSemaphore); 40 } 41 42 status_t Init(uint32 messageCode) 43 { 44 fMessageCode = messageCode; 45 fSemaphore = create_sem(0, "sleeper sem"); 46 return (fSemaphore >= 0 ? B_OK : fSemaphore); 47 } 48 49 uint32 MessageCode() const { return fMessageCode; } 50 51 status_t Sleep(bigtime_t timeout = B_INFINITE_TIMEOUT) 52 { 53 return acquire_sem_etc(fSemaphore, 1, B_RELATIVE_TIMEOUT, timeout); 54 } 55 56 status_t WakeUp() 57 { 58 return release_sem(fSemaphore); 59 } 60 61 private: 62 uint32 fMessageCode; 63 sem_id fSemaphore; 64 }; 65 66 // AppInfo 67 class LaunchContext::AppInfo { 68 public: 69 AppInfo(team_id team) 70 : fTeam(team), 71 fMessenger(), 72 fMessages(), 73 fTerminating(false) 74 { 75 } 76 77 ~AppInfo() 78 { 79 for (int32 i = 0; LaunchContext::Message *message = MessageAt(i); i++) 80 delete message; 81 } 82 83 team_id Team() const 84 { 85 return fTeam; 86 } 87 88 void SetMessenger(BMessenger messenger) 89 { 90 fMessenger = messenger; 91 } 92 93 BMessenger Messenger() const 94 { 95 return fMessenger; 96 } 97 98 void Terminate() 99 { 100 if (!fTerminating && fMessenger.IsValid()) 101 { 102 fTerminating = true; 103 fMessenger.SendMessage(B_QUIT_REQUESTED); 104 } 105 } 106 107 void AddMessage(const BMessage &_message) 108 { 109 LaunchContext::Message *message = new LaunchContext::Message; 110 message->message = _message; 111 message->when = system_time(); 112 fMessages.AddItem(message); 113 NotifySleepers(_message.what); 114 } 115 116 LaunchContext::Message *RemoveMessage(int32 index) 117 { 118 return (LaunchContext::Message*)fMessages.RemoveItem(index); 119 } 120 121 LaunchContext::Message *MessageAt(int32 index) const 122 { 123 return (LaunchContext::Message*)fMessages.ItemAt(index); 124 } 125 126 LaunchContext::Message *FindMessage(uint32 messageCode, 127 int32 startIndex = 0) const 128 { 129 LaunchContext::Message *message = NULL; 130 for (int32 i = startIndex; (message = MessageAt(i)) != NULL; i++) { 131 if (message->message.what == messageCode) 132 break; 133 } 134 return message; 135 } 136 137 void AddSleeper(Sleeper *sleeper) 138 { 139 fSleepers.AddItem(sleeper); 140 } 141 142 void RemoveSleeper(Sleeper *sleeper) 143 { 144 fSleepers.RemoveItem(sleeper); 145 } 146 147 void NotifySleepers(uint32 messageCode) 148 { 149 for (int32 i = 0; 150 Sleeper *sleeper = (Sleeper*)fSleepers.ItemAt(i); 151 i++) { 152 if (sleeper->MessageCode() == messageCode) 153 sleeper->WakeUp(); 154 } 155 } 156 157 private: 158 team_id fTeam; 159 BMessenger fMessenger; 160 BList fMessages; 161 bool fTerminating; 162 BList fSleepers; 163 }; 164 165 // constructor 166 LaunchContext::LaunchContext() 167 : fAppInfos(), 168 fSleepers(), 169 fLock(), 170 fAppThread(B_ERROR), 171 fTerminator(B_ERROR), 172 fTerminating(false) 173 { 174 RosterLaunchApp *app = dynamic_cast<RosterLaunchApp*>(be_app); 175 app->SetLaunchContext(this); 176 app->Unlock(); 177 fAppThread = spawn_thread(AppThreadEntry, "app thread", B_NORMAL_PRIORITY, 178 this); 179 if (fAppThread >= 0) { 180 status_t error = resume_thread(fAppThread); 181 if (error != B_OK) 182 printf("ERROR: Couldn't resume app thread: %s\n", strerror(error)); 183 } else 184 printf("ERROR: Couldn't spawn app thread: %s\n", strerror(fAppThread)); 185 } 186 187 // destructor 188 LaunchContext::~LaunchContext() 189 { 190 Terminate(); 191 // cleanup 192 for (int32 i = 0; AppInfo *info = AppInfoAt(i); i++) 193 delete info; 194 for (int32 i = 0; 195 BMessage *message = (BMessage*)fStandardMessages.ItemAt(i); 196 i++) { 197 delete message; 198 } 199 } 200 201 // () 202 status_t 203 LaunchContext::operator()(LaunchCaller &caller, const char *type, 204 team_id *team) 205 { 206 BMessage message1(MSG_1); 207 BMessage message2(MSG_2); 208 BMessage message3(MSG_3); 209 BList messages; 210 messages.AddItem(&message1); 211 messages.AddItem(&message2); 212 messages.AddItem(&message3); 213 return (*this)(caller, type, &messages, kStandardArgc, kStandardArgv, 214 team); 215 } 216 217 // () 218 status_t 219 LaunchContext::operator()(LaunchCaller &caller, const char *type, 220 BList *messages, int32 argc, const char **argv, 221 team_id *team) 222 { 223 BAutolock _lock(fLock); 224 status_t result = caller(type, messages, argc, argv, team); 225 if (result == B_OK && team) 226 CreateAppInfo(*team); 227 return result; 228 } 229 230 // HandleMessage 231 void 232 LaunchContext::HandleMessage(BMessage *message) 233 { 234 //printf("LaunchContext::HandleMessage(%6ld: %.4s)\n", 235 //message->ReturnAddress().Team(), (char*)&message->what); 236 //if (message->what == MSG_MESSAGE_RECEIVED) { 237 // BMessage sentMessage; 238 // message->FindMessage("message", &sentMessage); 239 // team_id sender = -1; 240 // message->FindInt32("sender", &sender); 241 // printf(" <- %6ld: %.4s\n", sender, (char*)&sentMessage.what); 242 //} 243 244 BAutolock _lock(fLock); 245 switch (message->what) { 246 case MSG_STARTED: 247 case MSG_TERMINATED: 248 case MSG_MAIN_ARGS: 249 case MSG_ARGV_RECEIVED: 250 case MSG_REFS_RECEIVED: 251 case MSG_MESSAGE_RECEIVED: 252 case MSG_QUIT_REQUESTED: 253 case MSG_READY_TO_RUN: 254 case MSG_1: 255 case MSG_2: 256 case MSG_3: 257 case MSG_REPLY: 258 { 259 BMessenger messenger = message->ReturnAddress(); 260 // add the message to the respective team's message list 261 // Note: catch messages that have not been sent by us or the 262 // remote team. The R5 registrar seems to send a B_REPLY message 263 // sometimes. 264 team_id sender = -1; 265 bool dontIgnore = false; 266 if (message->FindInt32("sender", &sender) != B_OK 267 || sender == be_app->Team() 268 || sender == messenger.Team() 269 || (message->FindBool("don't ignore", &dontIgnore) == B_OK) 270 && dontIgnore) { 271 AppInfo *info = CreateAppInfo(messenger); 272 info->AddMessage(*message); 273 if (fTerminating) 274 TerminateApp(info); 275 } 276 NotifySleepers(message->what); 277 break; 278 } 279 default: 280 break; 281 } 282 } 283 284 // Terminate 285 void 286 LaunchContext::Terminate() 287 { 288 fLock.Lock(); 289 if (!fTerminating) { 290 fTerminating = true; 291 // tell all test apps to quit 292 for (int32 i = 0; AppInfo *info = AppInfoAt(i); i++) 293 TerminateApp(info); 294 // start terminator 295 fTerminator = spawn_thread(TerminatorEntry, "terminator", 296 B_NORMAL_PRIORITY, this); 297 if (fTerminator >= 0) { 298 status_t error = resume_thread(fTerminator); 299 if (error != B_OK) { 300 printf("ERROR: Couldn't resume terminator thread: %s\n", 301 strerror(error)); 302 } 303 } else { 304 printf("ERROR: Couldn't spawn terminator thread: %s\n", 305 strerror(fTerminator)); 306 } 307 } 308 fLock.Unlock(); 309 // wait for the app to terminate 310 int32 dummy; 311 wait_for_thread(fAppThread, &dummy); 312 wait_for_thread(fTerminator, &dummy); 313 } 314 315 // TerminateApp 316 void 317 LaunchContext::TerminateApp(team_id team, bool wait) 318 { 319 fLock.Lock(); 320 if (AppInfo *info = AppInfoFor(team)) 321 TerminateApp(info); 322 fLock.Unlock(); 323 if (wait) 324 WaitForMessage(team, MSG_TERMINATED); 325 } 326 327 // TeamAt 328 team_id 329 LaunchContext::TeamAt(int32 index) const 330 { 331 BAutolock _lock(fLock); 332 team_id team = B_ERROR; 333 if (AppInfo *info = AppInfoAt(index)) 334 team = info->Team(); 335 return team; 336 } 337 338 // AppMessengerFor 339 BMessenger 340 LaunchContext::AppMessengerFor(team_id team) const 341 { 342 BAutolock _lock(fLock); 343 BMessenger result; 344 if (AppInfo *info = AppInfoFor(team)) { 345 // We need to do some hacking. 346 BMessenger messenger; 347 struct fake_messenger { 348 port_id fPort; 349 int32 fHandlerToken; 350 team_id fTeam; 351 int32 extra0; 352 int32 extra1; 353 bool fPreferredTarget; 354 bool extra2; 355 bool extra3; 356 bool extra4; 357 } &fake = *(fake_messenger*)&messenger; 358 status_t error = B_OK; 359 fake.fTeam = team; 360 // find app looper port 361 bool found = false; 362 int32 cookie = 0; 363 port_info info; 364 while (error == B_OK && !found) { 365 error = get_next_port_info(fake.fTeam, &cookie, &info); 366 found = (error == B_OK 367 && (!strcmp("AppLooperPort", info.name) 368 || !strcmp("rAppLooperPort", info.name))); 369 } 370 // init messenger 371 if (error == B_OK) { 372 fake.fPort = info.port; 373 fake.fHandlerToken = 0; 374 fake.fPreferredTarget = true; 375 } 376 if (error == B_OK) 377 result = messenger; 378 } 379 return result; 380 } 381 382 // NextMessageFrom 383 BMessage* 384 LaunchContext::NextMessageFrom(team_id team, int32 &cookie, bigtime_t *time) 385 { 386 BAutolock _lock(fLock); 387 BMessage *message = NULL; 388 if (AppInfo *info = AppInfoFor(team)) { 389 if (Message *contextMessage = info->MessageAt(cookie++)) 390 message = &contextMessage->message; 391 } 392 return message; 393 } 394 395 // CheckNextMessage 396 bool 397 LaunchContext::CheckNextMessage(LaunchCaller &caller, team_id team, 398 int32 &cookie, uint32 what) 399 { 400 BMessage *message = NextMessageFrom(team, cookie); 401 return (message && message->what == what); 402 } 403 404 // CheckMainArgsMessage 405 bool 406 LaunchContext::CheckMainArgsMessage(LaunchCaller &caller, team_id team, 407 int32 &cookie, const entry_ref *appRef, 408 bool useRef) 409 { 410 int32 argc = 0; 411 const char **argv = NULL; 412 if (caller.SupportsArgv()) { 413 argc = kStandardArgc; 414 argv = kStandardArgv; 415 } 416 return CheckMainArgsMessage(caller, team, cookie, appRef, argc, argv, 417 useRef); 418 } 419 420 // CheckMainArgsMessage 421 bool 422 LaunchContext::CheckMainArgsMessage(LaunchCaller &caller, team_id team, 423 int32 &cookie, const entry_ref *appRef, 424 int32 argc, const char **argv, bool useRef) 425 { 426 useRef &= caller.SupportsArgv() && argv && argc > 0; 427 const entry_ref *ref = (useRef ? caller.Ref() : NULL); 428 return CheckArgsMessage(caller, team, cookie, appRef, ref, argc, argv, 429 MSG_MAIN_ARGS); 430 } 431 432 // CheckArgvMessage 433 bool 434 LaunchContext::CheckArgvMessage(LaunchCaller &caller, team_id team, 435 int32 &cookie, const entry_ref *appRef, 436 bool useRef) 437 { 438 bool result = true; 439 if (caller.SupportsArgv()) { 440 result = CheckArgvMessage(caller, team, cookie, appRef, kStandardArgc, 441 kStandardArgv, useRef); 442 } 443 return result; 444 } 445 446 // CheckArgvMessage 447 bool 448 LaunchContext::CheckArgvMessage(LaunchCaller &caller, team_id team, 449 int32 &cookie, const entry_ref *appRef, 450 int32 argc, const char **argv, bool useRef) 451 { 452 const entry_ref *ref = (useRef ? caller.Ref() : NULL); 453 return CheckArgvMessage(caller, team, cookie, appRef, ref , argc, argv); 454 } 455 456 // CheckArgvMessage 457 bool 458 LaunchContext::CheckArgvMessage(LaunchCaller &caller, team_id team, 459 int32 &cookie, const entry_ref *appRef, 460 const entry_ref *ref , int32 argc, 461 const char **argv) 462 { 463 return CheckArgsMessage(caller, team, cookie, appRef, ref, argc, argv, 464 MSG_ARGV_RECEIVED); 465 } 466 467 // CheckArgsMessage 468 bool 469 LaunchContext::CheckArgsMessage(LaunchCaller &caller, team_id team, 470 int32 &cookie, const entry_ref *appRef, 471 const entry_ref *ref , int32 argc, 472 const char **argv, uint32 messageCode) 473 { 474 BMessage *message = NextMessageFrom(team, cookie); 475 bool result = (message && message->what == messageCode); 476 int32 additionalRef = (ref ? 1 : 0); 477 // check argc 478 int32 foundArgc = -1; 479 if (result) { 480 result = (message->FindInt32("argc", &foundArgc) == B_OK 481 && foundArgc == argc + 1 + additionalRef); 482 if (!result) 483 printf("argc differ: %ld vs %ld + 1 + %ld\n", foundArgc, argc, additionalRef); 484 } 485 // check argv[0] (the app file name) 486 if (result) { 487 BPath path; 488 const char *arg = NULL; 489 result = (path.SetTo(appRef) == B_OK 490 && message->FindString("argv", 0, &arg) == B_OK 491 && path == arg); 492 if (!result) 493 printf("app paths differ: `%s' vs `%s'\n", arg, path.Path()); 494 } 495 // check remaining argv 496 for (int32 i = 1; result && i < argc; i++) { 497 const char *arg = NULL; 498 result = (message->FindString("argv", i, &arg) == B_OK 499 && !strcmp(arg, argv[i - 1])); 500 if (!result) 501 printf("arg[%ld] differ: `%s' vs `%s'\n", i, arg, argv[i - 1]); 502 } 503 // check additional ref 504 if (result && additionalRef) { 505 BPath path; 506 const char *arg = NULL; 507 result = (path.SetTo(ref) == B_OK 508 && message->FindString("argv", argc + 1, &arg) == B_OK 509 && path == arg); 510 if (!result) 511 printf("document paths differ: `%s' vs `%s'\n", arg, path.Path()); 512 } 513 return result; 514 } 515 516 // CheckMessageMessages 517 bool 518 LaunchContext::CheckMessageMessages(LaunchCaller &caller, team_id team, 519 int32 &cookie) 520 { 521 BAutolock _lock(fLock); 522 bool result = true; 523 for (int32 i = 0; i < 3; i++) 524 result &= CheckMessageMessage(caller, team, cookie, i); 525 return result; 526 } 527 528 // CheckMessageMessage 529 bool 530 LaunchContext::CheckMessageMessage(LaunchCaller &caller, team_id team, 531 int32 &cookie, int32 index) 532 { 533 bool result = true; 534 if (caller.SupportsMessages() > index && index < 3) { 535 uint32 commands[] = { MSG_1, MSG_2, MSG_3 }; 536 BMessage message(commands[index]); 537 result = CheckMessageMessage(caller, team, cookie, &message); 538 } 539 return result; 540 } 541 542 // CheckMessageMessage 543 bool 544 LaunchContext::CheckMessageMessage(LaunchCaller &caller, team_id team, 545 int32 &cookie, 546 const BMessage *expectedMessage) 547 { 548 BMessage *message = NextMessageFrom(team, cookie); 549 bool result = (message && message->what == MSG_MESSAGE_RECEIVED); 550 if (result) { 551 BMessage sentMessage; 552 result = (message->FindMessage("message", &sentMessage) == B_OK 553 && sentMessage.what == expectedMessage->what); 554 } 555 return result; 556 } 557 558 // CheckRefsMessage 559 bool 560 LaunchContext::CheckRefsMessage(LaunchCaller &caller, team_id team, 561 int32 &cookie) 562 { 563 bool result = true; 564 if (caller.SupportsRefs()) 565 result = CheckRefsMessage(caller, team, cookie, caller.Ref()); 566 return result; 567 } 568 569 // CheckRefsMessage 570 bool 571 LaunchContext::CheckRefsMessage(LaunchCaller &caller, team_id team, 572 int32 &cookie, const entry_ref *refs, 573 int32 count) 574 { 575 BMessage *message = NextMessageFrom(team, cookie); 576 bool result = (message && message->what == MSG_REFS_RECEIVED); 577 if (result) { 578 entry_ref ref; 579 for (int32 i = 0; result && i < count; i++) { 580 result = (message->FindRef("refs", i, &ref) == B_OK 581 && ref == refs[i]); 582 } 583 } 584 return result; 585 } 586 587 // WaitForMessage 588 bool 589 LaunchContext::WaitForMessage(uint32 messageCode, bool fromNow, 590 bigtime_t timeout) 591 { 592 status_t error = B_ERROR; 593 fLock.Lock(); 594 error = B_OK; 595 if (fromNow || !FindMessage(messageCode)) { 596 // add sleeper 597 Sleeper *sleeper = new Sleeper; 598 error = sleeper->Init(messageCode); 599 if (error == B_OK) { 600 AddSleeper(sleeper); 601 fLock.Unlock(); 602 // sleep 603 error = sleeper->Sleep(timeout); 604 fLock.Lock(); 605 // remove sleeper 606 RemoveSleeper(sleeper); 607 delete sleeper; 608 } 609 } 610 fLock.Unlock(); 611 return (error == B_OK); 612 } 613 614 // WaitForMessage 615 bool 616 LaunchContext::WaitForMessage(team_id team, uint32 messageCode, bool fromNow, 617 bigtime_t timeout, int32 startIndex) 618 { 619 status_t error = B_ERROR; 620 fLock.Lock(); 621 if (AppInfo *info = AppInfoFor(team)) { 622 error = B_OK; 623 if (fromNow || !info->FindMessage(messageCode, startIndex)) { 624 // add sleeper 625 Sleeper *sleeper = new Sleeper; 626 error = sleeper->Init(messageCode); 627 if (error == B_OK) { 628 info->AddSleeper(sleeper); 629 fLock.Unlock(); 630 // sleep 631 error = sleeper->Sleep(timeout); 632 fLock.Lock(); 633 // remove sleeper 634 info->RemoveSleeper(sleeper); 635 delete sleeper; 636 } 637 } 638 } 639 fLock.Unlock(); 640 return (error == B_OK); 641 } 642 643 // StandardMessages 644 BList* 645 LaunchContext::StandardMessages() 646 { 647 if (fStandardMessages.IsEmpty()) { 648 fStandardMessages.AddItem(new BMessage(MSG_1)); 649 fStandardMessages.AddItem(new BMessage(MSG_2)); 650 fStandardMessages.AddItem(new BMessage(MSG_3)); 651 } 652 return &fStandardMessages; 653 } 654 655 // AppInfoAt 656 LaunchContext::AppInfo* 657 LaunchContext::AppInfoAt(int32 index) const 658 { 659 return (AppInfo*)fAppInfos.ItemAt(index); 660 } 661 662 // AppInfoFor 663 LaunchContext::AppInfo* 664 LaunchContext::AppInfoFor(team_id team) const 665 { 666 for (int32 i = 0; AppInfo *info = AppInfoAt(i); i++) { 667 if (info->Team() == team) 668 return info; 669 } 670 return NULL; 671 } 672 673 // CreateAppInfo 674 LaunchContext::AppInfo* 675 LaunchContext::CreateAppInfo(BMessenger messenger) 676 { 677 return CreateAppInfo(messenger.Team(), &messenger); 678 } 679 680 // CreateAppInfo 681 LaunchContext::AppInfo* 682 LaunchContext::CreateAppInfo(team_id team, const BMessenger *messenger) 683 { 684 AppInfo *info = AppInfoFor(team); 685 if (!info) { 686 info = new AppInfo(team); 687 fAppInfos.AddItem(info); 688 } 689 if (messenger && !info->Messenger().IsValid()) 690 info->SetMessenger(*messenger); 691 return info; 692 } 693 694 // TerminateApp 695 void 696 LaunchContext::TerminateApp(AppInfo *info) 697 { 698 if (info) 699 info->Terminate(); 700 } 701 702 // Terminator 703 int32 704 LaunchContext::Terminator() 705 { 706 bool allGone = false; 707 while (!allGone) { 708 allGone = true; 709 fLock.Lock(); 710 for (int32 i = 0; AppInfo *info = AppInfoAt(i); i++) { 711 team_info teamInfo; 712 allGone &= (get_team_info(info->Team(), &teamInfo) != B_OK); 713 } 714 fLock.Unlock(); 715 if (!allGone) 716 snooze(10000); 717 } 718 be_app->PostMessage(B_QUIT_REQUESTED, be_app); 719 return 0; 720 } 721 722 // AppThreadEntry 723 int32 724 LaunchContext::AppThreadEntry(void *) 725 { 726 be_app->Lock(); 727 be_app->Run(); 728 return 0; 729 } 730 731 // TerminatorEntry 732 int32 733 LaunchContext::TerminatorEntry(void *data) 734 { 735 return ((LaunchContext*)data)->Terminator(); 736 } 737 738 // FindMessage 739 LaunchContext::Message* 740 LaunchContext::FindMessage(uint32 messageCode) 741 { 742 BAutolock _lock(fLock); 743 Message *message = NULL; 744 AppInfo *info = NULL; 745 for (int32 i = 0; !message && (info = AppInfoAt(i)) != NULL; i++) 746 message = info->FindMessage(messageCode); 747 return message; 748 } 749 750 // AddSleeper 751 void 752 LaunchContext::AddSleeper(Sleeper *sleeper) 753 { 754 fSleepers.AddItem(sleeper); 755 } 756 757 // RemoveSleeper 758 void 759 LaunchContext::RemoveSleeper(Sleeper *sleeper) 760 { 761 fSleepers.RemoveItem(sleeper); 762 } 763 764 // NotifySleepers 765 void 766 LaunchContext::NotifySleepers(uint32 messageCode) 767 { 768 for (int32 i = 0; Sleeper *sleeper = (Sleeper*)fSleepers.ItemAt(i); i++) { 769 if (sleeper->MessageCode() == messageCode) 770 sleeper->WakeUp(); 771 } 772 } 773 774 775 /////////////////// 776 // RosterLaunchApp 777 778 // constructor 779 RosterLaunchApp::RosterLaunchApp(const char *signature) 780 : BApplication(signature), 781 fLaunchContext(NULL), 782 fHandler(NULL) 783 { 784 } 785 786 // destructor 787 RosterLaunchApp::~RosterLaunchApp() 788 { 789 SetHandler(NULL); 790 } 791 792 // MessageReceived 793 void 794 RosterLaunchApp::MessageReceived(BMessage *message) 795 { 796 if (fLaunchContext) 797 fLaunchContext->HandleMessage(message); 798 } 799 800 // SetLaunchContext 801 void 802 RosterLaunchApp::SetLaunchContext(LaunchContext *context) 803 { 804 fLaunchContext = context; 805 } 806 807 // GetLaunchContext 808 LaunchContext * 809 RosterLaunchApp::GetLaunchContext() const 810 { 811 return fLaunchContext; 812 } 813 814 // SetHandler 815 void 816 RosterLaunchApp::SetHandler(BHandler *handler) 817 { 818 Lock(); 819 if (fHandler) { 820 RemoveHandler(fHandler); 821 delete fHandler; 822 fHandler = NULL; 823 } 824 if (handler) { 825 fHandler = handler; 826 AddHandler(handler); 827 } 828 Unlock(); 829 } 830 831 832 ////////////////////////// 833 // RosterBroadcastHandler 834 835 // constructor 836 RosterBroadcastHandler::RosterBroadcastHandler() 837 { 838 } 839 840 // MessageReceived 841 void 842 RosterBroadcastHandler::MessageReceived(BMessage *message) 843 { 844 RosterLaunchApp *app = dynamic_cast<RosterLaunchApp*>(be_app); 845 if (LaunchContext *launchContext = app->GetLaunchContext()) { 846 message->AddInt32("original what", (int32)message->what); 847 message->what = MSG_REPLY; 848 launchContext->HandleMessage(message); 849 } 850 } 851 852