summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/plugin_carbon_interpose_mac.cc105
-rw-r--r--chrome/browser/plugin_process_host.cc21
-rw-r--r--chrome/chrome.gyp52
-rw-r--r--chrome/common/plugin_carbon_interpose_constants_mac.cc13
-rw-r--r--chrome/common/plugin_carbon_interpose_constants_mac.h16
-rw-r--r--chrome/plugin/plugin_main.cc41
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)