1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 // Copyright (c) 2008 The Chromium Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
6 
7 #include "chrome/common/mach_message_source_mac.h"
8 
9 #include "base/logging.h"
10 
MachMessageSource(mach_port_t port,MachPortListener * msg_listener,bool * success)11 MachMessageSource::MachMessageSource(mach_port_t port,
12                                      MachPortListener* msg_listener,
13                                      bool* success) {
14   DCHECK(msg_listener);
15   DCHECK(success);
16   DCHECK(port != MACH_PORT_NULL);
17 
18   CFMachPortContext port_context = {0};
19   port_context.info = msg_listener;
20 
21   scoped_cftyperef<CFMachPortRef> cf_mach_port_ref(CFMachPortCreateWithPort(
22       kCFAllocatorDefault, port, MachMessageSource::OnReceiveMachMessage,
23       &port_context, NULL));
24 
25   if (cf_mach_port_ref.get() == NULL) {
26     CHROMIUM_LOG(WARNING) << "CFMachPortCreate failed";
27     *success = false;
28     return;
29   }
30 
31   // Create a RL source.
32   machport_runloop_ref_.reset(CFMachPortCreateRunLoopSource(
33       kCFAllocatorDefault, cf_mach_port_ref.get(), 0));
34 
35   if (machport_runloop_ref_.get() == NULL) {
36     CHROMIUM_LOG(WARNING) << "CFMachPortCreateRunLoopSource failed";
37     *success = false;
38     return;
39   }
40 
41   CFRunLoopAddSource(CFRunLoopGetCurrent(), machport_runloop_ref_.get(),
42                      kCFRunLoopCommonModes);
43   *success = true;
44 }
45 
~MachMessageSource()46 MachMessageSource::~MachMessageSource() {
47   CFRunLoopRemoveSource(CFRunLoopGetCurrent(), machport_runloop_ref_.get(),
48                         kCFRunLoopCommonModes);
49 }
50 
51 // static
OnReceiveMachMessage(CFMachPortRef port,void * msg,CFIndex size,void * closure)52 void MachMessageSource::OnReceiveMachMessage(CFMachPortRef port, void* msg,
53                                              CFIndex size, void* closure) {
54   MachPortListener* msg_listener = static_cast<MachPortListener*>(closure);
55   size_t msg_size = (size < 0) ? 0 : static_cast<size_t>(size);
56   DCHECK(msg && msg_size > 0);  // this should never happen!
57 
58   if (msg_listener && msg && msg_size > 0) {
59     msg_listener->OnMachMessageReceived(msg, msg_size);
60   }
61 }
62