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

Unified Diff: chrome/common/multi_process_notification_mac.mm

Issue 5970015: Add multi-process notification class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added missing file 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 side-by-side diff with in-line comments
Download patch
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..cad9f82a288dfc2fb613f2e1d62b68a1fc7d5ef4
--- /dev/null
+++ b/chrome/common/multi_process_notification_mac.mm
@@ -0,0 +1,154 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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"
+
+#import <Foundation/Foundation.h>
+#include <notify.h>
+#include <unistd.h>
+
+#include "base/basictypes.h"
+#include "base/eintr_wrapper.h"
+#include "base/file_path.h"
+#include "base/logging.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/path_service.h"
+#include "base/stringprintf.h"
+#include "base/sys_string_conversions.h"
+#include "base/task.h"
+#include "chrome/common/chrome_paths.h"
+
+namespace {
+
+std::string PrependDomain(const std::string& name,
Mark Mentovai 2011/01/06 17:59:09 The meaning of domain is overloaded in this functi
dmac 2011/01/06 18:22:37 Renamed.
+ multi_process_notification::Domain domain) {
+ base::mac::ScopedNSAutoreleasePool pool;
+ NSBundle *bundle = base::mac::MainAppBundle();
+ NSString *ns_bundle_id = [bundle bundleIdentifier];
+ std::string bundle_id = base::SysNSStringToUTF8(ns_bundle_id);
+ std::string domain_string;
+ switch (domain) {
+ case multi_process_notification::ProfileDomain: {
+ FilePath user_data_dir;
+ if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
+ NOTREACHED();
+ }
+ domain_string = StringPrintf("user.uid.%u.%s.",
+ getuid(), user_data_dir.value().c_str());
+ break;
+ }
+
+ case multi_process_notification::UserDomain:
+ domain_string = StringPrintf("user.uid.%u.", getuid());
+ break;
+
+ case multi_process_notification::SystemDomain:
+ break;
+ }
+ return domain_string + bundle_id + "." + name;
Mark Mentovai 2011/01/06 17:59:09 I think that these should always start with bundle
dmac 2011/01/06 18:22:37 See man 3 notify for why I did it a little ass-bac
+}
+
+
+} // namespace
+
+namespace multi_process_notification {
+
+bool Post(const std::string& name, Domain domain) {
+ std::string notification = PrependDomain(name, domain);
+ 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,
+ Domain domain,
+ Listener::Delegate* delegate);
+ virtual ~ListenerImpl();
+
+ bool Start();
+
+ virtual void OnFileCanReadWithoutBlocking(int fd);
+ virtual void OnFileCanWriteWithoutBlocking(int fd);
+
+ private:
+ std::string name_;
+ Domain domain_;
+ Listener::Delegate* delegate_;
+ int fd_;
+ int token_;
+ base::MessagePumpLibevent::FileDescriptorWatcher watcher_;
+
+ DISALLOW_COPY_AND_ASSIGN(ListenerImpl);
+};
+
+ListenerImpl::ListenerImpl(const std::string& name,
+ Domain domain,
+ Listener::Delegate* delegate)
+ : name_(name), domain_(domain), 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 = PrependDomain(name_, domain_);
+
+ uint32_t status = notify_register_file_descriptor(notification.c_str(), &fd_,
+ 0, &token_);
+ if (status != NOTIFY_STATUS_OK) {
+ LOG(ERROR) << "Unable to notify_register_file_descriptor for '"
+ << notification << "' Status:" << status;
Mark Mentovai 2011/01/06 17:59:09 Need a space after Status:?
dmac 2011/01/06 18:22:37 Done.
+ return false;
+ }
+
+ MessageLoopForIO *io_loop = MessageLoopForIO::current();
+ return io_loop->WatchFileDescriptor(fd_, true, MessageLoopForIO::WATCH_READ,
+ &watcher_, this);
+}
+
+void ListenerImpl::OnFileCanReadWithoutBlocking(int fd) {
+ DCHECK_EQ(fd, fd_);
+ int token = 0;
+ if (HANDLE_EINTR(read(fd_, &token, sizeof(token))) >= 0) {
+ // Have to swap to native endianness <http://openradar.appspot.com/8821081>.
+ 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,
+ Domain domain,
+ Listener::Delegate* delegate)
+ : impl_(new ListenerImpl(name, domain, delegate)) {
+}
+
+Listener::~Listener() {
+}
+
+bool Listener::Start() {
+ return impl_->Start();
+}
+
+} // namespace multi_process_notification

Powered by Google App Engine
This is Rietveld 408576698