Chromium Code Reviews| 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; |
| } |