Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(767)

Side by Side Diff: chrome/browser/multi_process_notification_mac.mm

Issue 6312007: Fix up notifications so that they aren't only on Browser IOThread. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added name and domain accessors to Listener interface Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/multi_process_notification.h" 5 #include "chrome/browser/multi_process_notification.h"
6 6
7 #import <Foundation/Foundation.h> 7 #import <Foundation/Foundation.h>
8 #include <notify.h> 8 #include <notify.h>
9 #include <sys/select.h> 9 #include <sys/select.h>
10 #include <sys/socket.h> 10 #include <sys/socket.h>
(...skipping 10 matching lines...) Expand all
21 #include "base/mac/scoped_nsautorelease_pool.h" 21 #include "base/mac/scoped_nsautorelease_pool.h"
22 #include "base/message_loop_proxy.h" 22 #include "base/message_loop_proxy.h"
23 #include "base/message_pump_libevent.h" 23 #include "base/message_pump_libevent.h"
24 #include "base/path_service.h" 24 #include "base/path_service.h"
25 #include "base/ref_counted.h" 25 #include "base/ref_counted.h"
26 #include "base/stringprintf.h" 26 #include "base/stringprintf.h"
27 #include "base/synchronization/lock.h" 27 #include "base/synchronization/lock.h"
28 #include "base/sys_string_conversions.h" 28 #include "base/sys_string_conversions.h"
29 #include "base/sys_info.h" 29 #include "base/sys_info.h"
30 #include "base/threading/simple_thread.h" 30 #include "base/threading/simple_thread.h"
31 #include "chrome/browser/browser_thread.h"
32 #include "chrome/common/chrome_paths.h" 31 #include "chrome/common/chrome_paths.h"
33 32
34 // Enable this to build with leopard_switchboard_thread 33 // Enable this to build with leopard_switchboard_thread
35 // #define USE_LEOPARD_SWITCHBOARD_THREAD 1 34 // #define USE_LEOPARD_SWITCHBOARD_THREAD 1
36 35
37 namespace { 36 namespace {
38 37
39 std::string AddPrefixToNotification(const std::string& name, 38 std::string AddPrefixToNotification(const std::string& name,
40 multi_process_notification::Domain domain) { 39 multi_process_notification::Domain domain) {
41 // The ordering of the components in the string returned by this function 40 // The ordering of the components in the string returned by this function
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 base::MessagePumpLibevent::FileDescriptorWatcher watcher_; 167 base::MessagePumpLibevent::FileDescriptorWatcher watcher_;
169 }; 168 };
170 169
171 class ListenerImpl : public base::MessagePumpLibevent::Watcher { 170 class ListenerImpl : public base::MessagePumpLibevent::Watcher {
172 public: 171 public:
173 ListenerImpl(const std::string& name, 172 ListenerImpl(const std::string& name,
174 Domain domain, 173 Domain domain,
175 Listener::Delegate* delegate); 174 Listener::Delegate* delegate);
176 virtual ~ListenerImpl(); 175 virtual ~ListenerImpl();
177 176
178 bool Start(); 177 bool Start(MessageLoop* io_loop_to_listen_on);
178
179 std::string name() const { return name_; }
180 Domain domain() const { return domain_; }
181
179 void OnListen(); 182 void OnListen();
180 183
181 // Watcher overrides 184 // Watcher overrides
182 virtual void OnFileCanReadWithoutBlocking(int fd); 185 virtual void OnFileCanReadWithoutBlocking(int fd);
183 virtual void OnFileCanWriteWithoutBlocking(int fd); 186 virtual void OnFileCanWriteWithoutBlocking(int fd);
184 187
185 private: 188 private:
186 std::string name_; 189 std::string name_;
187 Domain domain_; 190 Domain domain_;
188 Listener::Delegate* delegate_; 191 Listener::Delegate* delegate_;
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 } 426 }
424 } else { 427 } else {
425 base::AutoLock autolock(switchboard_lock_); 428 base::AutoLock autolock(switchboard_lock_);
426 if (g_switchboard_thread_) { 429 if (g_switchboard_thread_) {
427 std::string notification = AddPrefixToNotification(name_, domain_); 430 std::string notification = AddPrefixToNotification(name_, domain_);
428 CHECK(g_switchboard_thread_->RemoveListener(this, notification)); 431 CHECK(g_switchboard_thread_->RemoveListener(this, notification));
429 } 432 }
430 } 433 }
431 } 434 }
432 435
433 bool ListenerImpl::Start() { 436 bool ListenerImpl::Start(MessageLoop* io_loop_to_listen_on) {
434 DCHECK_EQ(fd_, -1); 437 DCHECK_EQ(fd_, -1);
435 DCHECK_EQ(token_, -1); 438 DCHECK_EQ(token_, -1);
439 if (io_loop_to_listen_on->type() != MessageLoop::TYPE_IO) {
440 DLOG(ERROR) << "io_loop_to_listen_on must be TYPE_IO";
441 return false;
442 }
436 message_loop_proxy_ = base::MessageLoopProxy::CreateForCurrentThread(); 443 message_loop_proxy_ = base::MessageLoopProxy::CreateForCurrentThread();
437 Task* task; 444 Task* task;
438 if(UseLeopardSwitchboardThread()) { 445 if(UseLeopardSwitchboardThread()) {
439 task = NewRunnableMethod(this, &ListenerImpl::StartLeopard); 446 task = NewRunnableMethod(this, &ListenerImpl::StartLeopard);
440 } else { 447 } else {
441 task = NewRunnableMethod(this, &ListenerImpl::StartSnowLeopard); 448 task = NewRunnableMethod(this, &ListenerImpl::StartSnowLeopard);
442 } 449 }
443 return BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, task); 450 io_loop_to_listen_on->PostTask(FROM_HERE, task);
451 return true;
444 } 452 }
445 453
446 void ListenerImpl::StartLeopard() { 454 void ListenerImpl::StartLeopard() {
447 DCHECK(UseLeopardSwitchboardThread()); 455 DCHECK(UseLeopardSwitchboardThread());
448 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 456 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
449 bool success = true; 457 bool success = true;
450 { 458 {
451 base::AutoLock autolock(switchboard_lock_); 459 base::AutoLock autolock(switchboard_lock_);
452 if (g_switchboard_thread_ && g_switchboard_thread_->HasBeenJoined()) { 460 if (g_switchboard_thread_ && g_switchboard_thread_->HasBeenJoined()) {
453 // The only time this should ever occur is in unit tests. 461 // The only time this should ever occur is in unit tests.
454 delete g_switchboard_thread_; 462 delete g_switchboard_thread_;
455 g_switchboard_thread_ = NULL; 463 g_switchboard_thread_ = NULL;
456 } 464 }
457 DCHECK(!(g_switchboard_thread_ && g_switchboard_thread_->finished())); 465 DCHECK(!(g_switchboard_thread_ && g_switchboard_thread_->finished()));
458 if (!g_switchboard_thread_) { 466 if (!g_switchboard_thread_) {
459 g_switchboard_thread_ = new LeopardSwitchboardThread(); 467 g_switchboard_thread_ = new LeopardSwitchboardThread();
460 success = g_switchboard_thread_->Init(); 468 success = g_switchboard_thread_->Init();
461 if (success) { 469 if (success) {
462 g_switchboard_thread_->Start(); 470 g_switchboard_thread_->Start();
463 } 471 }
464 } 472 }
465 if (success) { 473 if (success) {
466 std::string notification = AddPrefixToNotification(name_, domain_); 474 std::string notification = AddPrefixToNotification(name_, domain_);
467 success = g_switchboard_thread_->AddListener(this, notification); 475 success = g_switchboard_thread_->AddListener(this, notification);
468 } 476 }
469 } 477 }
470 Task* task = 478 Task* task =
471 new Listener::ListenerStartedTask(name_, domain_, delegate_, success); 479 new Listener::ListenerStartedTask(name_, domain_, delegate_, success);
472 CHECK(message_loop_proxy_->PostTask(FROM_HERE, task)); 480 CHECK(message_loop_proxy_->PostTask(FROM_HERE, task));
473 } 481 }
474 482
475 void ListenerImpl::StartSnowLeopard() { 483 void ListenerImpl::StartSnowLeopard() {
476 DCHECK(!UseLeopardSwitchboardThread()); 484 DCHECK(!UseLeopardSwitchboardThread());
477 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 485 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
478 bool success = true; 486 bool success = true;
479 std::string notification = AddPrefixToNotification(name_, domain_); 487 std::string notification = AddPrefixToNotification(name_, domain_);
480 uint32_t status = notify_register_file_descriptor( 488 uint32_t status = notify_register_file_descriptor(
481 notification.c_str(), &fd_, 0, &token_); 489 notification.c_str(), &fd_, 0, &token_);
482 if (status != NOTIFY_STATUS_OK) { 490 if (status != NOTIFY_STATUS_OK) {
483 LOG(ERROR) << "unable to notify_register_file_descriptor for '" 491 LOG(ERROR) << "unable to notify_register_file_descriptor for '"
484 << notification << "' Status: " << status; 492 << notification << "' Status: " << status;
485 success = false; 493 success = false;
486 } 494 }
487 if (success) { 495 if (success) {
488 MessageLoopForIO* io_loop = MessageLoopForIO::current(); 496 MessageLoopForIO* io_loop = MessageLoopForIO::current();
489 success = io_loop->WatchFileDescriptor( 497 success = io_loop->WatchFileDescriptor(
490 fd_, true, MessageLoopForIO::WATCH_READ, &watcher_, this); 498 fd_, true, MessageLoopForIO::WATCH_READ, &watcher_, this);
491 } 499 }
492 Task* task = 500 Task* task =
493 new Listener::ListenerStartedTask(name_, domain_, delegate_, success); 501 new Listener::ListenerStartedTask(name_, domain_, delegate_, success);
494 CHECK(message_loop_proxy_->PostTask(FROM_HERE, task)); 502 CHECK(message_loop_proxy_->PostTask(FROM_HERE, task));
495 } 503 }
496 504
497 void ListenerImpl::OnFileCanReadWithoutBlocking(int fd) { 505 void ListenerImpl::OnFileCanReadWithoutBlocking(int fd) {
498 DCHECK(!UseLeopardSwitchboardThread()); 506 DCHECK(!UseLeopardSwitchboardThread());
499 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 507 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
500 DCHECK_EQ(fd, fd_); 508 DCHECK_EQ(fd, fd_);
501 int token; 509 int token;
502 int status = HANDLE_EINTR(read(fd, &token, sizeof(token))); 510 int status = HANDLE_EINTR(read(fd, &token, sizeof(token)));
503 if (status < 0) { 511 if (status < 0) {
504 PLOG(ERROR) << "read"; 512 PLOG(ERROR) << "read";
505 } else if (status == 0) { 513 } else if (status == 0) {
506 LOG(ERROR) << "external_fd_ closed"; 514 LOG(ERROR) << "external_fd_ closed";
507 } else if (status != sizeof(token)) { 515 } else if (status != sizeof(token)) {
508 LOG(ERROR) << "unexpected read size " << status; 516 LOG(ERROR) << "unexpected read size " << status;
509 } else { 517 } else {
510 // Have to swap to native endianness <http://openradar.appspot.com/8821081>. 518 // Have to swap to native endianness <http://openradar.appspot.com/8821081>.
511 token = static_cast<int>(ntohl(token)); 519 token = static_cast<int>(ntohl(token));
512 if (token == token_) { 520 if (token == token_) {
513 OnListen(); 521 OnListen();
514 } else { 522 } else {
515 LOG(ERROR) << "unexpected value " << token; 523 LOG(ERROR) << "unexpected value " << token;
516 } 524 }
517 } 525 }
518 } 526 }
519 527
520 void ListenerImpl::OnListen() { 528 void ListenerImpl::OnListen() {
521 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 529 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
522 Task* task = 530 Task* task =
523 new Listener::NotificationReceivedTask(name_, domain_, delegate_); 531 new Listener::NotificationReceivedTask(name_, domain_, delegate_);
524 CHECK(message_loop_proxy_->PostTask(FROM_HERE, task)); 532 CHECK(message_loop_proxy_->PostTask(FROM_HERE, task));
525 } 533 }
526 534
527 void ListenerImpl::OnFileCanWriteWithoutBlocking(int fd) { 535 void ListenerImpl::OnFileCanWriteWithoutBlocking(int fd) {
528 NOTREACHED(); 536 NOTREACHED();
529 } 537 }
530 538
531 Listener::Listener( 539 Listener::Listener(
532 const std::string& name, Domain domain, Listener::Delegate* delegate) 540 const std::string& name, Domain domain, Listener::Delegate* delegate)
533 : impl_(new ListenerImpl(name, domain, delegate)) { 541 : impl_(new ListenerImpl(name, domain, delegate)) {
534 } 542 }
535 543
536 Listener::~Listener() { 544 Listener::~Listener() {
537 } 545 }
538 546
539 bool Listener::Start() { 547 bool Listener::Start(MessageLoop* io_loop_to_listen_on) {
540 return impl_->Start(); 548 return impl_->Start(io_loop_to_listen_on);
549 }
550
551 std::string Listener::name() const {
552 return impl_->name();
553 }
554
555 Domain Listener::domain() const {
556 return impl_->domain();
541 } 557 }
542 558
543 } // namespace multi_process_notification 559 } // namespace multi_process_notification
544 560
545 DISABLE_RUNNABLE_METHOD_REFCOUNT(multi_process_notification::ListenerImpl); 561 DISABLE_RUNNABLE_METHOD_REFCOUNT(multi_process_notification::ListenerImpl);
OLDNEW
« no previous file with comments | « chrome/browser/multi_process_notification_linux.cc ('k') | chrome/browser/multi_process_notification_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698