Index: content/renderer/renderer_main_platform_delegate_mac.mm |
diff --git a/content/renderer/renderer_main_platform_delegate_mac.mm b/content/renderer/renderer_main_platform_delegate_mac.mm |
index 9f6172e71e1ff7800de39c96c4a5e36cbc57287c..df47f3d0e1072629559b5cea71258d4e54c18af5 100644 |
--- a/content/renderer/renderer_main_platform_delegate_mac.mm |
+++ b/content/renderer/renderer_main_platform_delegate_mac.mm |
@@ -13,6 +13,7 @@ |
#import "base/mac/foundation_util.h" |
#import "base/mac/mac_util.h" |
#include "base/mac/scoped_cftyperef.h" |
+#include "base/strings/string_number_conversions.h" |
#include "base/strings/sys_string_conversions.h" |
#include "content/common/sandbox_mac.h" |
#include "content/public/common/content_switches.h" |
@@ -68,6 +69,87 @@ void CrRendererCFLog(int32_t level, CFStringRef format, ...) { |
va_end(args); |
} |
+// You are about to read a pretty disgusting hack. In a static initializer, |
Avi (use Gerrit)
2014/02/25 19:54:47
Yes, this is disgusting.
|
+// CoreFoundation decides to connect with cfprefsd(8) using Mach IPC. There is |
+// no public way to close this Mach port after-the-fact, nor a way to stop it |
+// from happening since it is done pre-main in dyld. But the address of the |
+// CFMachPort can be found in the run loop's string description. Below, that |
+// address is parsed, cast, and then used to invalidate the Mach port to |
+// disable communication with cfprefsd. |
+void DisconnectCFNotificationCenter() { |
+ base::ScopedCFTypeRef<CFStringRef> run_loop_description( |
+ CFCopyDescription(CFRunLoopGetCurrent())); |
+ const CFIndex length = CFStringGetLength(run_loop_description); |
+ for (CFIndex i = 0; i < length; ) { |
+ // Find the start of a CFMachPort run loop source, which looks like this, |
+ // without new lines: |
+ // 1 : <CFRunLoopSource 0x7d16ea90 [0xa160af80]>{signalled = No, |
+ // valid = Yes, order = 0, context = |
+ // <CFMachPort 0x7d16fe00 [0xa160af80]>{valid = Yes, port = 3a0f, |
+ // source = 0x7d16ea90, callout = |
+ // _ZL14MessageHandlerP12__CFMachPortPvlS1_ (0x96df59c2), context = |
+ // <CFMachPort context 0x1475b>}} |
+ CFRange run_loop_source_context_range; |
+ if (!CFStringFindWithOptions(run_loop_description, |
+ CFSTR(", context = <CFMachPort "), CFRangeMake(i, length - i), |
+ 0, &run_loop_source_context_range)) { |
+ break; |
+ } |
+ i = run_loop_source_context_range.location + |
+ run_loop_source_context_range.length; |
+ |
+ // The address of the CFMachPort is the first hexadecimal address after the |
+ // CF type name. |
+ CFRange port_address_range = CFRangeMake(i, 0); |
+ for (CFIndex j = port_address_range.location; j < length; ++j) { |
+ UniChar c = CFStringGetCharacterAtIndex(run_loop_description, j); |
+ if (c == ' ') |
+ break; |
+ ++port_address_range.length; |
+ } |
+ |
+ base::ScopedCFTypeRef<CFStringRef> port_address_string( |
+ CFStringCreateWithSubstring(NULL, run_loop_description, |
+ port_address_range)); |
+ if (!port_address_string) |
+ continue; |
+ |
+ // Convert the string to an address. |
+ std::string port_address_std_string = |
+ base::SysCFStringRefToUTF8(port_address_string); |
+#if __LP64__ |
+ uint64 port_address = 0; |
+ if (!base::HexStringToUInt64(port_address_std_string, &port_address)) |
+ continue; |
+#else |
+ uint32 port_address = 0; |
+ if (!base::HexStringToUInt(port_address_std_string, &port_address)) |
+ continue; |
+#endif |
+ |
+ // Cast the address to an object. |
+ CFMachPortRef mach_port = reinterpret_cast<CFMachPortRef>(port_address); |
+ if (CFGetTypeID(mach_port) != CFMachPortGetTypeID()) |
+ continue; |
+ |
+ // Verify that this is the Mach port that needs to be disconnected by the |
+ // name of its callout function. Example description (no new lines): |
+ // <CFMachPort 0x7d16fe00 [0xa160af80]>{valid = Yes, port = 3a0f, source = |
+ // 0x7d16ea90, callout = __CFXNotificationReceiveFromServer (0x96df59c2), |
+ // context = <CFMachPort context 0x1475b>} |
+ base::ScopedCFTypeRef<CFStringRef> port_description( |
+ CFCopyDescription(mach_port)); |
+ if (CFStringFindWithOptions(port_description, |
+ CFSTR(", callout = __CFXNotificationReceiveFromServer ("), |
+ CFRangeMake(0, CFStringGetLength(port_description)), |
+ 0, |
+ NULL)) { |
+ CFMachPortInvalidate(mach_port); |
+ return; |
+ } |
+ } |
+} |
+ |
} // namespace |
RendererMainPlatformDelegate::RendererMainPlatformDelegate( |
@@ -173,6 +255,8 @@ bool RendererMainPlatformDelegate::EnableSandbox() { |
source_list, arraysize(source_list), &kCFTypeArrayCallBacks); |
} |
+ DisconnectCFNotificationCenter(); |
+ |
return sandbox_initialized; |
} |