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

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: 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);
179 void OnListen(); 178 void OnListen();
180 179
181 // Watcher overrides 180 // Watcher overrides
182 virtual void OnFileCanReadWithoutBlocking(int fd); 181 virtual void OnFileCanReadWithoutBlocking(int fd);
183 virtual void OnFileCanWriteWithoutBlocking(int fd); 182 virtual void OnFileCanWriteWithoutBlocking(int fd);
184 183
185 private: 184 private:
186 std::string name_; 185 std::string name_;
187 Domain domain_; 186 Domain domain_;
188 Listener::Delegate* delegate_; 187 Listener::Delegate* delegate_;
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 } 422 }
424 } else { 423 } else {
425 base::AutoLock autolock(switchboard_lock_); 424 base::AutoLock autolock(switchboard_lock_);
426 if (g_switchboard_thread_) { 425 if (g_switchboard_thread_) {
427 std::string notification = AddPrefixToNotification(name_, domain_); 426 std::string notification = AddPrefixToNotification(name_, domain_);
428 CHECK(g_switchboard_thread_->RemoveListener(this, notification)); 427 CHECK(g_switchboard_thread_->RemoveListener(this, notification));
429 } 428 }
430 } 429 }
431 } 430 }
432 431
433 bool ListenerImpl::Start() { 432 bool ListenerImpl::Start(MessageLoop* io_loop_to_listen_on) {
434 DCHECK_EQ(fd_, -1); 433 DCHECK_EQ(fd_, -1);
435 DCHECK_EQ(token_, -1); 434 DCHECK_EQ(token_, -1);
435 if (io_loop_to_listen_on->type() != MessageLoop::TYPE_IO) {
436 return false;
garykac 2011/01/19 22:49:40 Log an error here?
dmac 2011/01/19 23:14:41 Done.
437 }
436 message_loop_proxy_ = base::MessageLoopProxy::CreateForCurrentThread(); 438 message_loop_proxy_ = base::MessageLoopProxy::CreateForCurrentThread();
437 Task* task; 439 Task* task;
438 if(UseLeopardSwitchboardThread()) { 440 if(UseLeopardSwitchboardThread()) {
439 task = NewRunnableMethod(this, &ListenerImpl::StartLeopard); 441 task = NewRunnableMethod(this, &ListenerImpl::StartLeopard);
440 } else { 442 } else {
441 task = NewRunnableMethod(this, &ListenerImpl::StartSnowLeopard); 443 task = NewRunnableMethod(this, &ListenerImpl::StartSnowLeopard);
442 } 444 }
443 return BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, task); 445 io_loop_to_listen_on->PostTask(FROM_HERE, task);
446 return true;
444 } 447 }
445 448
446 void ListenerImpl::StartLeopard() { 449 void ListenerImpl::StartLeopard() {
447 DCHECK(UseLeopardSwitchboardThread()); 450 DCHECK(UseLeopardSwitchboardThread());
448 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 451 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
449 bool success = true; 452 bool success = true;
450 { 453 {
451 base::AutoLock autolock(switchboard_lock_); 454 base::AutoLock autolock(switchboard_lock_);
452 if (g_switchboard_thread_ && g_switchboard_thread_->HasBeenJoined()) { 455 if (g_switchboard_thread_ && g_switchboard_thread_->HasBeenJoined()) {
453 // The only time this should ever occur is in unit tests. 456 // The only time this should ever occur is in unit tests.
454 delete g_switchboard_thread_; 457 delete g_switchboard_thread_;
455 g_switchboard_thread_ = NULL; 458 g_switchboard_thread_ = NULL;
456 } 459 }
457 DCHECK(!(g_switchboard_thread_ && g_switchboard_thread_->finished())); 460 DCHECK(!(g_switchboard_thread_ && g_switchboard_thread_->finished()));
458 if (!g_switchboard_thread_) { 461 if (!g_switchboard_thread_) {
459 g_switchboard_thread_ = new LeopardSwitchboardThread(); 462 g_switchboard_thread_ = new LeopardSwitchboardThread();
460 success = g_switchboard_thread_->Init(); 463 success = g_switchboard_thread_->Init();
461 if (success) { 464 if (success) {
462 g_switchboard_thread_->Start(); 465 g_switchboard_thread_->Start();
463 } 466 }
464 } 467 }
465 if (success) { 468 if (success) {
466 std::string notification = AddPrefixToNotification(name_, domain_); 469 std::string notification = AddPrefixToNotification(name_, domain_);
467 success = g_switchboard_thread_->AddListener(this, notification); 470 success = g_switchboard_thread_->AddListener(this, notification);
468 } 471 }
469 } 472 }
470 Task* task = 473 Task* task =
471 new Listener::ListenerStartedTask(name_, domain_, delegate_, success); 474 new Listener::ListenerStartedTask(name_, domain_, delegate_, success);
472 CHECK(message_loop_proxy_->PostTask(FROM_HERE, task)); 475 CHECK(message_loop_proxy_->PostTask(FROM_HERE, task));
473 } 476 }
474 477
475 void ListenerImpl::StartSnowLeopard() { 478 void ListenerImpl::StartSnowLeopard() {
476 DCHECK(!UseLeopardSwitchboardThread()); 479 DCHECK(!UseLeopardSwitchboardThread());
477 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 480 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
478 bool success = true; 481 bool success = true;
479 std::string notification = AddPrefixToNotification(name_, domain_); 482 std::string notification = AddPrefixToNotification(name_, domain_);
480 uint32_t status = notify_register_file_descriptor( 483 uint32_t status = notify_register_file_descriptor(
481 notification.c_str(), &fd_, 0, &token_); 484 notification.c_str(), &fd_, 0, &token_);
482 if (status != NOTIFY_STATUS_OK) { 485 if (status != NOTIFY_STATUS_OK) {
483 LOG(ERROR) << "unable to notify_register_file_descriptor for '" 486 LOG(ERROR) << "unable to notify_register_file_descriptor for '"
484 << notification << "' Status: " << status; 487 << notification << "' Status: " << status;
485 success = false; 488 success = false;
486 } 489 }
487 if (success) { 490 if (success) {
488 MessageLoopForIO* io_loop = MessageLoopForIO::current(); 491 MessageLoopForIO* io_loop = MessageLoopForIO::current();
489 success = io_loop->WatchFileDescriptor( 492 success = io_loop->WatchFileDescriptor(
490 fd_, true, MessageLoopForIO::WATCH_READ, &watcher_, this); 493 fd_, true, MessageLoopForIO::WATCH_READ, &watcher_, this);
491 } 494 }
492 Task* task = 495 Task* task =
493 new Listener::ListenerStartedTask(name_, domain_, delegate_, success); 496 new Listener::ListenerStartedTask(name_, domain_, delegate_, success);
494 CHECK(message_loop_proxy_->PostTask(FROM_HERE, task)); 497 CHECK(message_loop_proxy_->PostTask(FROM_HERE, task));
495 } 498 }
496 499
497 void ListenerImpl::OnFileCanReadWithoutBlocking(int fd) { 500 void ListenerImpl::OnFileCanReadWithoutBlocking(int fd) {
498 DCHECK(!UseLeopardSwitchboardThread()); 501 DCHECK(!UseLeopardSwitchboardThread());
499 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 502 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
500 DCHECK_EQ(fd, fd_); 503 DCHECK_EQ(fd, fd_);
501 int token; 504 int token;
502 int status = HANDLE_EINTR(read(fd, &token, sizeof(token))); 505 int status = HANDLE_EINTR(read(fd, &token, sizeof(token)));
503 if (status < 0) { 506 if (status < 0) {
504 PLOG(ERROR) << "read"; 507 PLOG(ERROR) << "read";
505 } else if (status == 0) { 508 } else if (status == 0) {
506 LOG(ERROR) << "external_fd_ closed"; 509 LOG(ERROR) << "external_fd_ closed";
507 } else if (status != sizeof(token)) { 510 } else if (status != sizeof(token)) {
508 LOG(ERROR) << "unexpected read size " << status; 511 LOG(ERROR) << "unexpected read size " << status;
509 } else { 512 } else {
510 // Have to swap to native endianness <http://openradar.appspot.com/8821081>. 513 // Have to swap to native endianness <http://openradar.appspot.com/8821081>.
511 token = static_cast<int>(ntohl(token)); 514 token = static_cast<int>(ntohl(token));
512 if (token == token_) { 515 if (token == token_) {
513 OnListen(); 516 OnListen();
514 } else { 517 } else {
515 LOG(ERROR) << "unexpected value " << token; 518 LOG(ERROR) << "unexpected value " << token;
516 } 519 }
517 } 520 }
518 } 521 }
519 522
520 void ListenerImpl::OnListen() { 523 void ListenerImpl::OnListen() {
521 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 524 DCHECK_EQ(MessageLoop::TYPE_IO, MessageLoop::current()->type());
522 Task* task = 525 Task* task =
523 new Listener::NotificationReceivedTask(name_, domain_, delegate_); 526 new Listener::NotificationReceivedTask(name_, domain_, delegate_);
524 CHECK(message_loop_proxy_->PostTask(FROM_HERE, task)); 527 CHECK(message_loop_proxy_->PostTask(FROM_HERE, task));
525 } 528 }
526 529
527 void ListenerImpl::OnFileCanWriteWithoutBlocking(int fd) { 530 void ListenerImpl::OnFileCanWriteWithoutBlocking(int fd) {
528 NOTREACHED(); 531 NOTREACHED();
529 } 532 }
530 533
531 Listener::Listener( 534 Listener::Listener(
532 const std::string& name, Domain domain, Listener::Delegate* delegate) 535 const std::string& name, Domain domain, Listener::Delegate* delegate)
533 : impl_(new ListenerImpl(name, domain, delegate)) { 536 : impl_(new ListenerImpl(name, domain, delegate)) {
534 } 537 }
535 538
536 Listener::~Listener() { 539 Listener::~Listener() {
537 } 540 }
538 541
539 bool Listener::Start() { 542 bool Listener::Start(MessageLoop* io_loop_to_listen_on) {
540 return impl_->Start(); 543 return impl_->Start(io_loop_to_listen_on);
541 } 544 }
542 545
543 } // namespace multi_process_notification 546 } // namespace multi_process_notification
544 547
545 DISABLE_RUNNABLE_METHOD_REFCOUNT(multi_process_notification::ListenerImpl); 548 DISABLE_RUNNABLE_METHOD_REFCOUNT(multi_process_notification::ListenerImpl);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698