1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/plugins/ipc/interpose/plugin_child_interpose.mm Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,134 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +// Use "dyld interposing" to hook methods imported from other libraries in the 1.10 +// plugin child process. The basic technique is described at 1.11 +// http://books.google.com/books?id=K8vUkpOXhN4C&pg=PA73&lpg=PA73&dq=__interpose&source=bl&ots=OJnnXZYpZC&sig=o7I3lXvoduUi13SrPfOON7o3do4&hl=en&ei=AoehS9brCYGQNrvsmeUM&sa=X&oi=book_result&ct=result&resnum=6&ved=0CBsQ6AEwBQ#v=onepage&q=__interpose&f=false. 1.12 +// The idea of doing it for the plugin child process comes from Chromium code, 1.13 +// particularly from plugin_carbon_interpose_mac.cc 1.14 +// (http://codesearch.google.com/codesearch/p?hl=en#OAMlx_jo-ck/src/chrome/browser/plugin_carbon_interpose_mac.cc&q=nscursor&exact_package=chromium&d=1&l=168) 1.15 +// and from PluginProcessHost::Init() in plugin_process_host.cc 1.16 +// (http://codesearch.google.com/codesearch/p?hl=en#OAMlx_jo-ck/src/content/browser/plugin_process_host.cc&q=nscursor&exact_package=chromium&d=1&l=222). 1.17 + 1.18 +// These hooks are needed to make certain OS calls work from the child process 1.19 +// (a background process) that would normally only work when called in the 1.20 +// parent process (the foreground process). They allow us to serialize 1.21 +// information from the child process to the parent process, so that the same 1.22 +// (or equivalent) calls can be made from the parent process. 1.23 + 1.24 +// This file lives in a seperate module (libplugin_child_interpose.dylib), 1.25 +// which will get loaded by the OS before any other modules when the plugin 1.26 +// child process is launched (from GeckoChildProcessHost:: 1.27 +// PerformAsyncLaunchInternal()). For this reason it shouldn't link in other 1.28 +// browser modules when loaded. Instead it should use dlsym() to load 1.29 +// pointers to the methods it wants to call in other modules. 1.30 + 1.31 +#if !defined(__LP64__) 1.32 + 1.33 +#include <dlfcn.h> 1.34 +#import <Carbon/Carbon.h> 1.35 + 1.36 +// The header file QuickdrawAPI.h is missing on OS X 10.7 and up (though the 1.37 +// QuickDraw APIs defined in it are still present) -- so we need to supply the 1.38 +// relevant parts of its contents here. It's likely that Apple will eventually 1.39 +// remove the APIs themselves (probably in OS X 10.8), so we need to make them 1.40 +// weak imports, and test for their presence before using them. 1.41 +#if !defined(__QUICKDRAWAPI__) 1.42 + 1.43 +struct Cursor; 1.44 +extern "C" void SetCursor(const Cursor * crsr) __attribute__((weak_import)); 1.45 + 1.46 +#endif /* __QUICKDRAWAPI__ */ 1.47 + 1.48 +BOOL (*OnSetThemeCursorPtr) (ThemeCursor) = NULL; 1.49 +BOOL (*OnSetCursorPtr) (const Cursor*) = NULL; 1.50 +BOOL (*OnHideCursorPtr) () = NULL; 1.51 +BOOL (*OnShowCursorPtr) () = NULL; 1.52 + 1.53 +static BOOL loadXULPtrs() 1.54 +{ 1.55 + if (!OnSetThemeCursorPtr) { 1.56 + // mac_plugin_interposing_child_OnSetThemeCursor(ThemeCursor cursor) is in 1.57 + // PluginInterposeOSX.mm 1.58 + OnSetThemeCursorPtr = (BOOL(*)(ThemeCursor)) 1.59 + dlsym(RTLD_DEFAULT, "mac_plugin_interposing_child_OnSetThemeCursor"); 1.60 + } 1.61 + if (!OnSetCursorPtr) { 1.62 + // mac_plugin_interposing_child_OnSetCursor(const Cursor* cursor) is in 1.63 + // PluginInterposeOSX.mm 1.64 + OnSetCursorPtr = (BOOL(*)(const Cursor*)) 1.65 + dlsym(RTLD_DEFAULT, "mac_plugin_interposing_child_OnSetCursor"); 1.66 + } 1.67 + if (!OnHideCursorPtr) { 1.68 + // mac_plugin_interposing_child_OnHideCursor() is in PluginInterposeOSX.mm 1.69 + OnHideCursorPtr = (BOOL(*)()) 1.70 + dlsym(RTLD_DEFAULT, "mac_plugin_interposing_child_OnHideCursor"); 1.71 + } 1.72 + if (!OnShowCursorPtr) { 1.73 + // mac_plugin_interposing_child_OnShowCursor() is in PluginInterposeOSX.mm 1.74 + OnShowCursorPtr = (BOOL(*)()) 1.75 + dlsym(RTLD_DEFAULT, "mac_plugin_interposing_child_OnShowCursor"); 1.76 + } 1.77 + return (OnSetCursorPtr && OnSetThemeCursorPtr && OnHideCursorPtr && OnShowCursorPtr); 1.78 +} 1.79 + 1.80 +static OSStatus MacPluginChildSetThemeCursor(ThemeCursor cursor) 1.81 +{ 1.82 + if (loadXULPtrs()) { 1.83 + OnSetThemeCursorPtr(cursor); 1.84 + } 1.85 + return ::SetThemeCursor(cursor); 1.86 +} 1.87 + 1.88 +static void MacPluginChildSetCursor(const Cursor* cursor) 1.89 +{ 1.90 + if (::SetCursor) { 1.91 + if (loadXULPtrs()) { 1.92 + OnSetCursorPtr(cursor); 1.93 + } 1.94 + ::SetCursor(cursor); 1.95 + } 1.96 +} 1.97 + 1.98 +static CGError MacPluginChildCGDisplayHideCursor(CGDirectDisplayID display) 1.99 +{ 1.100 + if (loadXULPtrs()) { 1.101 + OnHideCursorPtr(); 1.102 + } 1.103 + return ::CGDisplayHideCursor(display); 1.104 +} 1.105 + 1.106 +static CGError MacPluginChildCGDisplayShowCursor(CGDirectDisplayID display) 1.107 +{ 1.108 + if (loadXULPtrs()) { 1.109 + OnShowCursorPtr(); 1.110 + } 1.111 + return ::CGDisplayShowCursor(display); 1.112 +} 1.113 + 1.114 +#pragma mark - 1.115 + 1.116 +struct interpose_substitution { 1.117 + const void* replacement; 1.118 + const void* original; 1.119 +}; 1.120 + 1.121 +#define INTERPOSE_FUNCTION(function) \ 1.122 + { reinterpret_cast<const void*>(MacPluginChild##function), \ 1.123 + reinterpret_cast<const void*>(function) } 1.124 + 1.125 +__attribute__((used)) static const interpose_substitution substitutions[] 1.126 + __attribute__((section("__DATA, __interpose"))) = { 1.127 + INTERPOSE_FUNCTION(SetThemeCursor), 1.128 + INTERPOSE_FUNCTION(CGDisplayHideCursor), 1.129 + INTERPOSE_FUNCTION(CGDisplayShowCursor), 1.130 + // SetCursor() and other QuickDraw APIs will probably be removed in OS X 1.131 + // 10.8. But this will make 'SetCursor' NULL, which will just stop the OS 1.132 + // from interposing it (tested using an INTERPOSE_FUNCTION_BROKEN macro 1.133 + // that just sets the second address of each tuple to NULL). 1.134 + INTERPOSE_FUNCTION(SetCursor), 1.135 +}; 1.136 + 1.137 +#endif // !__LP64__