diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/plugin_carbon_interpose_mac.cc | 105 | ||||
-rw-r--r-- | chrome/browser/plugin_process_host.cc | 21 | ||||
-rw-r--r-- | chrome/chrome.gyp | 52 | ||||
-rw-r--r-- | chrome/common/plugin_carbon_interpose_constants_mac.cc | 13 | ||||
-rw-r--r-- | chrome/common/plugin_carbon_interpose_constants_mac.h | 16 | ||||
-rw-r--r-- | chrome/plugin/plugin_main.cc | 41 |
6 files changed, 245 insertions, 3 deletions
diff --git a/chrome/browser/plugin_carbon_interpose_mac.cc b/chrome/browser/plugin_carbon_interpose_mac.cc new file mode 100644 index 0000000..315cdfa --- /dev/null +++ b/chrome/browser/plugin_carbon_interpose_mac.cc @@ -0,0 +1,105 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <Carbon/Carbon.h> + +#include "webkit/glue/plugins/fake_plugin_window_tracker_mac.h" + +// The process that was frontmost when a plugin created a new window; generally +// we expect this to be the browser UI process. +static ProcessSerialNumber g_saved_front_process = { 0, 0 }; + +// Bring the plugin process to the front so that the user can see it. +// TODO: Make this an IPC to order the plugin process above the browser +// process but not necessarily the frontmost. +static void SwitchToPluginProcess() { + ProcessSerialNumber this_process, front_process; + if (GetCurrentProcess(&this_process) != noErr) + return; + if (GetFrontProcess(&front_process) != noErr) + return; + Boolean matched = false; + if (SameProcess(&this_process, &front_process, &matched) != noErr) + return; + if (!matched) { + // TODO: We may need to keep a stack, or at least check the total window + // count, since this won't work if a plugin opens more than one window at + // a time. + g_saved_front_process = front_process; + SetFrontProcess(&this_process); + } +} + +// If the plugin process is still the front process, bring the prior +// front process (normally this will be the browser process) back to +// the front. +// TODO: Make this an IPC message so that the browser can properly +// reactivate the window. +static void SwitchToSavedProcess() { + ProcessSerialNumber this_process, front_process; + if (GetCurrentProcess(&this_process) != noErr) + return; + if (GetFrontProcess(&front_process) != noErr) + return; + Boolean matched = false; + if (SameProcess(&this_process, &front_process, &matched) != noErr) + return; + if (matched) { + SetFrontProcess(&g_saved_front_process); + } +} + +#pragma mark - + +static Boolean ChromePluginIsWindowHilited(WindowRef window) { + // TODO(stuartmorgan): Always returning true (instead of the real answer, + // which would be false) means that clicking works, but it's not correct + // either. Ideally we need a way to find out if the delegate corresponds + // to a browser window that is active. + const WebPluginDelegateImpl* delegate = + FakePluginWindowTracker::SharedInstance()->GetDelegateForFakeWindow( + window); + Boolean isHilited = delegate ? true : IsWindowHilited(window); + return isHilited; +} + +static void ChromePluginSelectWindow(WindowRef window) { + SwitchToPluginProcess(); + SelectWindow(window); +} + +static void ChromePluginShowWindow(WindowRef window) { + SwitchToPluginProcess(); + ShowWindow(window); +} + +static void ChromePluginDisposeWindow(WindowRef window) { + SwitchToSavedProcess(); + DisposeWindow(window); +} + +static void ChromePluginHideWindow(WindowRef window) { + SwitchToSavedProcess(); + HideWindow(window); +} + +#pragma mark - + +struct interpose_substitution { + const void* replacement; + const void* original; +}; + +#define INTERPOSE_FUNCTION(function) \ + { reinterpret_cast<const void*>(ChromePlugin##function), \ + reinterpret_cast<const void*>(function) } + +__attribute__((used)) static const interpose_substitution substitutions[] + __attribute__((section("__DATA, __interpose"))) = { + INTERPOSE_FUNCTION(IsWindowHilited), + INTERPOSE_FUNCTION(SelectWindow), + INTERPOSE_FUNCTION(ShowWindow), + INTERPOSE_FUNCTION(DisposeWindow), + INTERPOSE_FUNCTION(HideWindow), +}; diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc index d57daae..3c5f169 100644 --- a/chrome/browser/plugin_process_host.cc +++ b/chrome/browser/plugin_process_host.cc @@ -64,6 +64,10 @@ #include "base/gfx/gtk_native_view_id_manager.h" #endif +#if defined(OS_MACOSX) +#include "chrome/common/plugin_carbon_interpose_constants_mac.h" +#endif + static const char kDefaultPluginFinderURL[] = "http://dl.google.com/chrome/plugins/plugins2.xml"; @@ -410,7 +414,22 @@ bool PluginProcessHost::Init(const WebPluginInfo& info, if (ipcfd > -1) fds_to_map.push_back(std::pair<int, int>( ipcfd, kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor)); - base::LaunchApp(cmd_line.argv(), fds_to_map, false, &process); + base::environment_vector env; +#if defined(OS_MACOSX) + // Add our interposing library for Carbon. This is stripped back out in + // plugin_main.cc, so changes here should be reflected there. + std::string interpose_list(plugin_interpose_strings::kInterposeLibraryPath); + const char* existing_list = + getenv(plugin_interpose_strings::kDYLDInsertLibrariesKey); + if (existing_list) { + interpose_list.insert(0, ":"); + interpose_list.insert(0, existing_list); + } + env.push_back(std::pair<const char*, const char*>( + plugin_interpose_strings::kDYLDInsertLibrariesKey, + interpose_list.c_str())); +#endif + base::LaunchApp(cmd_line.argv(), env, fds_to_map, false, &process); #endif if (!process) diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index c4e12bf..6b59d03 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -453,6 +453,8 @@ 'common/platform_util_linux.cc', 'common/platform_util_mac.mm', 'common/platform_util_win.cc', + 'common/plugin_carbon_interpose_constants_mac.h', + 'common/plugin_carbon_interpose_constants_mac.cc', 'common/plugin_messages.h', 'common/plugin_messages_internal.h', 'common/pref_member.cc', @@ -3015,7 +3017,8 @@ 'destination': '<(PRODUCT_DIR)/<(mac_product_name).app/Contents/MacOS/', 'files': ['../third_party/ffmpeg/binaries/chrome/libavcodec.52.dylib', '../third_party/ffmpeg/binaries/chrome/libavformat.52.dylib', - '../third_party/ffmpeg/binaries/chrome/libavutil.50.dylib'], + '../third_party/ffmpeg/binaries/chrome/libavutil.50.dylib', + '<(PRODUCT_DIR)/plugin_carbon_interpose.dylib'], }, ], }, { # else: 'branding!="Chrome" @@ -3028,7 +3031,8 @@ 'destination': '<(PRODUCT_DIR)/<(mac_product_name).app/Contents/MacOS/', 'files': ['../third_party/ffmpeg/binaries/chromium/libavcodec.52.dylib', '../third_party/ffmpeg/binaries/chromium/libavformat.52.dylib', - '../third_party/ffmpeg/binaries/chromium/libavutil.50.dylib'], + '../third_party/ffmpeg/binaries/chromium/libavutil.50.dylib', + '<(PRODUCT_DIR)/plugin_carbon_interpose.dylib'], }, ], }], @@ -3077,6 +3081,7 @@ # Bring in pdfsqueeze and run it on all pdfs 'dependencies': [ '../build/temp_gyp/pdfsqueeze.gyp:pdfsqueeze', + 'interpose_dependency_shim', ], 'rules': [ { @@ -4496,6 +4501,49 @@ }, ], # 'actions' }, + { + # Dummy target to allow chrome to require plugin_carbon_interpose to + # build without actually linking to the resulting library. + 'target_name': 'interpose_dependency_shim', + 'type': 'executable', + 'dependencies': [ + 'plugin_carbon_interpose', + ], + # In release, we end up with a strip step that is unhappy if there is + # no binary. Rather than check in a new file for this temporary hack, + # just generate a source file on the fly. + 'actions': [ + { + 'action_name': 'generate_stub_main', + 'process_outputs_as_sources': 1, + 'inputs': [], + 'outputs': [ '<(INTERMEDIATE_DIR)/dummy_main.c' ], + 'action': [ + 'bash', '-c', + 'echo "int main() { return 0; }" > <(INTERMEDIATE_DIR)/dummy_main.c' + ], + }, + ], + }, + { + # dylib for interposing Carbon calls in the plugin process. + 'target_name': 'plugin_carbon_interpose', + 'type': 'shared_library', + 'dependencies': [ + 'chrome_dll', + ], + 'sources': [ + 'browser/plugin_carbon_interpose_mac.cc', + ], + 'include_dirs': [ + '..', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Carbon.framework', + ], + }, + }, ] }, { # else: OS != "mac" 'targets': [ diff --git a/chrome/common/plugin_carbon_interpose_constants_mac.cc b/chrome/common/plugin_carbon_interpose_constants_mac.cc new file mode 100644 index 0000000..26f0edc --- /dev/null +++ b/chrome/common/plugin_carbon_interpose_constants_mac.cc @@ -0,0 +1,13 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/plugin_carbon_interpose_constants_mac.h" + +namespace plugin_interpose_strings { + +const char kDYLDInsertLibrariesKey[] = "DYLD_INSERT_LIBRARIES"; +const char kInterposeLibraryPath[] = + "@executable_path/plugin_carbon_interpose.dylib"; + +} // namespace plugin_interpose_strings diff --git a/chrome/common/plugin_carbon_interpose_constants_mac.h b/chrome/common/plugin_carbon_interpose_constants_mac.h new file mode 100644 index 0000000..f90085f --- /dev/null +++ b/chrome/common/plugin_carbon_interpose_constants_mac.h @@ -0,0 +1,16 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_COMMON_PLUGIN_CARBON_INTERPOSE_CONSTANTS_MAC_H_ +#define CHROME_COMMON_PLUGIN_CARBON_INTERPOSE_CONSTANTS_MAC_H_ + +// Strings used in setting up Carbon interposing for the plugin process. +namespace plugin_interpose_strings { + +extern const char kDYLDInsertLibrariesKey[]; +extern const char kInterposeLibraryPath[]; + +} // namespace plugin_interpose_strings + +#endif // CHROME_BROWSER_PLUGIN_CARBON_INTERPOSE_CONSTANTS_MAC_H_ diff --git a/chrome/plugin/plugin_main.cc b/chrome/plugin/plugin_main.cc index 63d295d..afc83a5 100644 --- a/chrome/plugin/plugin_main.cc +++ b/chrome/plugin/plugin_main.cc @@ -25,8 +25,45 @@ #elif defined(OS_LINUX) #include "base/global_descriptors_posix.h" #include "ipc/ipc_descriptors.h" +#elif defined(OS_MACOSX) +#include "chrome/common/plugin_carbon_interpose_constants_mac.h" #endif +#if defined(OS_MACOSX) +// Removes our Carbon library interposing from the environment so that it +// doesn't carry into any processes that plugins might start. +static void TrimInterposeEnvironment() { + const char* interpose_list = + getenv(plugin_interpose_strings::kDYLDInsertLibrariesKey); + if (!interpose_list) { + NOTREACHED() << "No interposing libraries set"; + return; + } + + // The list is a :-separated list of paths. Because we append our interpose + // library just before forking in plugin_process_host.cc, the only cases we + // need to handle are: + // 1) The whole string is "<kInterposeLibraryPath>", so just clear it, or + // 2) ":<kInterposeLibraryPath>" is the end of the string, so trim and re-set. + int suffix_offset = strlen(interpose_list) - + strlen(plugin_interpose_strings::kInterposeLibraryPath); + if (suffix_offset == 0 && + strcmp(interpose_list, + plugin_interpose_strings::kInterposeLibraryPath) == 0) { + unsetenv(plugin_interpose_strings::kDYLDInsertLibrariesKey); + } else if (suffix_offset > 0 && interpose_list[suffix_offset - 1] == ':' && + strcmp(interpose_list + suffix_offset, + plugin_interpose_strings::kInterposeLibraryPath) == 0) { + std::string trimmed_list = + std::string(interpose_list).substr(0, suffix_offset - 1); + setenv(plugin_interpose_strings::kDYLDInsertLibrariesKey, + trimmed_list.c_str(), 1); + } else { + NOTREACHED() << "Missing Carbon interposing library"; + } +} +#endif // OS_MACOSX + // main() routine for running as the plugin process. int PluginMain(const MainFunctionParams& parameters) { // The main thread of the plugin services UI. @@ -37,6 +74,10 @@ int PluginMain(const MainFunctionParams& parameters) { // Initialize the SystemMonitor base::SystemMonitor::Start(); +#if defined(OS_MACOSX) + TrimInterposeEnvironment(); +#endif + const CommandLine& parsed_command_line = parameters.command_line_; #if defined(OS_WIN) |