| Index: trunk/src/content/renderer/renderer_main_platform_delegate_mac.mm
|
| ===================================================================
|
| --- trunk/src/content/renderer/renderer_main_platform_delegate_mac.mm (revision 254033)
|
| +++ trunk/src/content/renderer/renderer_main_platform_delegate_mac.mm (working copy)
|
| @@ -10,6 +10,8 @@
|
|
|
| #include "base/command_line.h"
|
| #include "base/logging.h"
|
| +#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"
|
| @@ -17,11 +19,56 @@
|
| #include "content/public/common/content_switches.h"
|
| #import "content/public/common/injection_test_mac.h"
|
| #include "content/common/sandbox_init_mac.h"
|
| +#include "third_party/mach_override/mach_override.h"
|
|
|
| +extern "C" {
|
| +// SPI logging functions for CF that are exported externally.
|
| +void CFLog(int32_t level, CFStringRef format, ...);
|
| +void _CFLogvEx(void* log_func, void* copy_desc_func,
|
| + CFDictionaryRef format_options, int32_t level,
|
| + CFStringRef format, va_list args);
|
| +} // extern "C"
|
| +
|
| namespace content {
|
|
|
| namespace {
|
|
|
| +// This leaked array stores the text input services input and layout sources,
|
| +// which is returned in CrTISCreateInputSourceList(). This list is computed
|
| +// right after the sandbox is initialized.
|
| +CFArrayRef g_text_input_services_source_list_ = NULL;
|
| +
|
| +CFArrayRef CrTISCreateInputSourceList(
|
| + CFDictionaryRef properties,
|
| + Boolean includeAllInstalled) {
|
| + DCHECK(g_text_input_services_source_list_);
|
| + // Callers assume ownership of the result, so increase the retain count.
|
| + CFRetain(g_text_input_services_source_list_);
|
| + return g_text_input_services_source_list_;
|
| +}
|
| +
|
| +// Text Input Services expects to be able to XPC to HIServices, but the
|
| +// renderer sandbox blocks that. TIS then becomes very vocal about this on
|
| +// every new renderer startup, so filter out those log messages.
|
| +void CrRendererCFLog(int32_t level, CFStringRef format, ...) {
|
| + const CFStringRef kAnnoyingLogMessages[] = {
|
| + CFSTR("Error received in message reply handler: %s\n"),
|
| + CFSTR("Connection Invalid error for service %s.\n"),
|
| + };
|
| +
|
| + for (size_t i = 0; i < arraysize(kAnnoyingLogMessages); ++i) {
|
| + if (CFStringCompare(format, kAnnoyingLogMessages[i], 0) ==
|
| + kCFCompareEqualTo) {
|
| + return;
|
| + }
|
| + }
|
| +
|
| + va_list args;
|
| + va_start(args, format);
|
| + _CFLogvEx(NULL, NULL, NULL, level, format, args);
|
| + va_end(args);
|
| +}
|
| +
|
| // You are about to read a pretty disgusting hack. In a static initializer,
|
| // 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
|
| @@ -117,6 +164,10 @@
|
| // running a renderer needs to also be reflected in chrome_main.cc for
|
| // --single-process support.
|
| void RendererMainPlatformDelegate::PlatformInitialize() {
|
| + // Initialize NSApplication up front. Without this call, drawing of
|
| + // native UI elements (e.g. buttons) in WebKit will explode.
|
| + [NSApplication sharedApplication];
|
| +
|
| if (![NSThread isMultiThreaded]) {
|
| NSString* string = @"";
|
| [NSThread detachNewThreadSelector:@selector(length)
|
| @@ -158,13 +209,52 @@
|
| }
|
|
|
| bool RendererMainPlatformDelegate::EnableSandbox() {
|
| + // rdar://9251340 http://openradar.me/9251340
|
| + // See http://crbug.com/31225 and http://crbug.com/152566
|
| + // To check if this is broken:
|
| + // 1. Enable Multi language input (simplified chinese)
|
| + // 2. Ensure "Show/Hide Trackpad Handwriting" shortcut works.
|
| + // (ctrl+shift+space).
|
| + // 3. Now open a new tab in Google Chrome or start Google Chrome
|
| + // 4. Try ctrl+shift+space shortcut again. Shortcut will not work, IME will
|
| + // either not appear or (worse) not disappear on ctrl-shift-space.
|
| + // (Run `ps aux | grep Chinese` (10.6/10.7) or `ps aux | grep Trackpad`
|
| + // and then kill that pid to make it go away.)
|
| + //
|
| + // Chinese Handwriting was introduced in 10.6 and is confirmed broken on
|
| + // 10.6, 10.7, and 10.8. It's fixed on 10.9.
|
| + bool needs_ime_hack = base::mac::IsOSMountainLionOrEarlier();
|
| +
|
| + if (needs_ime_hack) {
|
| + mach_error_t err = mach_override_ptr(
|
| + (void*)&TISCreateInputSourceList,
|
| + (void*)&CrTISCreateInputSourceList,
|
| + NULL);
|
| + CHECK_EQ(err_none, err);
|
| +
|
| + // Override the private CFLog function so that the console is not spammed
|
| + // by TIS failing to connect to HIServices over XPC.
|
| + err = mach_override_ptr((void*)&CFLog, (void*)&CrRendererCFLog, NULL);
|
| + CHECK_EQ(err_none, err);
|
| + }
|
| +
|
| // Enable the sandbox.
|
| bool sandbox_initialized = InitializeSandbox();
|
|
|
| - // The sandbox is now engaged. Make sure that the renderer has not connected
|
| - // itself to Cocoa.
|
| - CHECK(NSApp == nil);
|
| + if (needs_ime_hack) {
|
| + // After the sandbox is initialized, call into TIS. Doing this before
|
| + // the sandbox is in place will open up renderer access to the
|
| + // pasteboard and an XPC connection to "com.apple.hiservices-xpcservice".
|
| + base::ScopedCFTypeRef<TISInputSourceRef> layout_source(
|
| + TISCopyCurrentKeyboardLayoutInputSource());
|
| + base::ScopedCFTypeRef<TISInputSourceRef> input_source(
|
| + TISCopyCurrentKeyboardInputSource());
|
|
|
| + CFTypeRef source_list[] = { layout_source.get(), input_source.get() };
|
| + g_text_input_services_source_list_ = CFArrayCreate(kCFAllocatorDefault,
|
| + source_list, arraysize(source_list), &kCFTypeArrayCallBacks);
|
| + }
|
| +
|
| DisconnectCFNotificationCenter();
|
|
|
| return sandbox_initialized;
|
|
|