Index: chrome/common/multi_process_notification_mac.mm |
diff --git a/chrome/common/multi_process_notification_mac.mm b/chrome/common/multi_process_notification_mac.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4509589e76124f320e6ac680484d9c040ef6db87 |
--- /dev/null |
+++ b/chrome/common/multi_process_notification_mac.mm |
@@ -0,0 +1,115 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
Mark Mentovai
2011/01/04 18:19:33
What will you use this for?
How is it supposed to
dmac
2011/01/06 06:06:03
Sending notifications to the service process.
|
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/common/multi_process_notification.h" |
+ |
+#include <notify.h> |
Mark Mentovai
2011/01/04 18:19:33
<notify.h> and <Foundation/Foundation.h> can be in
dmac
2011/01/06 06:06:03
Done.
|
+ |
+#import <Foundation/Foundation.h> |
+ |
+#include "base/mac/mac_util.h" |
+#include "base/mac/scoped_nsautorelease_pool.h" |
+#include "base/message_loop.h" |
+#include "base/message_pump_libevent.h" |
+#include "base/sys_string_conversions.h" |
+#include "base/task.h" |
+ |
+namespace { |
+ |
+std::string PrependBundleID(const std::string& name) { |
+ base::mac::ScopedNSAutoreleasePool pool; |
+ NSBundle *bundle = base::mac::MainAppBundle(); |
+ NSString *ns_bundle_id = [bundle bundleIdentifier]; |
+ std::string bundle_id = base::SysNSStringToUTF8(ns_bundle_id); |
+ return bundle_id + "." + name; |
+} |
+ |
+} // namespace |
+ |
+namespace multi_process_notification { |
+ |
+bool Post(const std::string& name) { |
+ std::string notification = PrependBundleID(name); |
+ uint32_t status = notify_post(notification.c_str()); |
+ DCHECK_EQ(status, static_cast<uint32_t>(NOTIFY_STATUS_OK)); |
+ return status == NOTIFY_STATUS_OK; |
+} |
+ |
+class ListenerImpl : public base::MessagePumpLibevent::Watcher { |
+ public: |
+ ListenerImpl(const std::string& name, |
+ Listener::Delegate* delegate); |
+ virtual ~ListenerImpl(); |
+ |
+ virtual bool Start(); |
+ |
+ virtual void OnFileCanReadWithoutBlocking(int fd); |
+ virtual void OnFileCanWriteWithoutBlocking(int fd); |
+ |
+ private: |
+ std::string name_; |
+ base::MessagePumpLibevent::FileDescriptorWatcher watcher_; |
+ Listener::Delegate* delegate_; |
+ int fd_; |
+ int token_; |
+}; |
+ |
+ListenerImpl::ListenerImpl(const std::string& name, |
+ Listener::Delegate* delegate) |
+ : name_(name), delegate_(delegate), fd_(-1), token_(-1) { |
+} |
+ |
+ListenerImpl::~ListenerImpl() { |
+ if (token_ != -1) { |
+ uint32_t status = notify_cancel(token_); |
+ DCHECK_EQ(status, static_cast<uint32_t>(NOTIFY_STATUS_OK)); |
+ token_ = -1; |
+ } |
+} |
+ |
+bool ListenerImpl::Start() { |
+ DCHECK_EQ(fd_, -1); |
+ DCHECK_EQ(token_, -1); |
+ std::string notification = PrependBundleID(name_); |
+ |
+ uint32_t status = notify_register_file_descriptor(notification.c_str(), &fd_, |
+ 0, &token_); |
+ if (status != NOTIFY_STATUS_OK) { |
+ return false; |
+ } |
+ |
+ MessageLoopForIO *io_loop = MessageLoopForIO::current(); |
+ return io_loop->WatchFileDescriptor(fd_, true, MessageLoopForIO::WATCH_READ, |
Mark Mentovai
2011/01/04 18:19:33
Do you ever need to undo this? watcher_ will disap
dmac
2011/01/06 06:06:03
when watcher_ is destroyed it handles taking care
|
+ &watcher_, this); |
+} |
+ |
+void ListenerImpl::OnFileCanReadWithoutBlocking(int fd) { |
+ DCHECK_EQ(fd, fd_); |
+ int token = 0; |
+ if (read(fd_, &token, sizeof(token)) >= 0) { |
Mark Mentovai
2011/01/04 18:19:33
HANDLE_EINTR from base/eintr_wrapper.h.
dmac
2011/01/06 06:06:03
Done.
|
+ // Have to swap to native endianness <rdar://problem/5352778>. |
Mark Mentovai
2011/01/04 18:19:33
Link to the problem: good.
Link to the problem th
dmac
2011/01/06 06:06:03
I copied the rdar link from some Apple source code
|
+ token = static_cast<int>(ntohl(token)); |
+ if (token == token_) { |
+ delegate_->OnNotificationReceived(name_); |
+ } else { |
+ LOG(WARNING) << "Unexpected value " << token; |
+ } |
+ } |
+} |
+ |
+void ListenerImpl::OnFileCanWriteWithoutBlocking(int fd) { |
+ NOTREACHED(); |
+} |
+ |
+Listener::Listener(const std::string& name, Listener::Delegate* delegate) : |
+ impl_(new ListenerImpl(name, delegate)) { |
+} |
+ |
+Listener::~Listener() { } |
Mark Mentovai
2011/01/04 18:19:33
{} on separate lines, along with whatever other qu
dmac
2011/01/06 06:06:03
Done.
|
+ |
+bool Listener::Start() { |
+ return impl_->Start(); |
+} |
+ |
+} // namespace multi_process_notification |