| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/plugin/plugin_thread.h" | |
| 6 | |
| 7 #include "build/build_config.h" | |
| 8 | |
| 9 #if defined(USE_X11) | |
| 10 #include <gtk/gtk.h> | |
| 11 #elif defined(OS_MACOSX) | |
| 12 #include <CoreFoundation/CoreFoundation.h> | |
| 13 #endif | |
| 14 | |
| 15 #include <string> | |
| 16 #include <vector> | |
| 17 | |
| 18 #include "base/command_line.h" | |
| 19 #include "base/lazy_instance.h" | |
| 20 #include "base/process_util.h" | |
| 21 #include "base/threading/thread_local.h" | |
| 22 #include "chrome/plugin/npobject_util.h" | |
| 23 #include "chrome/renderer/render_thread.h" | |
| 24 #include "content/common/child_process.h" | |
| 25 #include "content/common/content_client.h" | |
| 26 #include "content/common/content_switches.h" | |
| 27 #include "content/common/child_process_messages.h" | |
| 28 #include "content/common/plugin_messages.h" | |
| 29 #include "ipc/ipc_channel_handle.h" | |
| 30 #include "net/base/net_errors.h" | |
| 31 #include "webkit/glue/webkit_glue.h" | |
| 32 #include "webkit/plugins/npapi/plugin_lib.h" | |
| 33 #include "webkit/plugins/npapi/webplugin_delegate_impl.h" | |
| 34 | |
| 35 #if defined(TOOLKIT_USES_GTK) | |
| 36 #include "ui/gfx/gtk_util.h" | |
| 37 #endif | |
| 38 | |
| 39 #if defined(USE_X11) | |
| 40 #include "ui/base/x/x11_util.h" | |
| 41 #endif | |
| 42 | |
| 43 static base::LazyInstance<base::ThreadLocalPointer<PluginThread> > lazy_tls( | |
| 44 base::LINKER_INITIALIZED); | |
| 45 | |
| 46 PluginThread::PluginThread() | |
| 47 : preloaded_plugin_module_(NULL) { | |
| 48 plugin_path_ = | |
| 49 CommandLine::ForCurrentProcess()->GetSwitchValuePath( | |
| 50 switches::kPluginPath); | |
| 51 | |
| 52 lazy_tls.Pointer()->Set(this); | |
| 53 #if defined(OS_LINUX) | |
| 54 { | |
| 55 // XEmbed plugins assume they are hosted in a Gtk application, so we need | |
| 56 // to initialize Gtk in the plugin process. | |
| 57 g_thread_init(NULL); | |
| 58 | |
| 59 // Flash has problems receiving clicks with newer GTKs due to the | |
| 60 // client-side windows change. To be safe, we just always set the | |
| 61 // backwards-compat environment variable. | |
| 62 setenv("GDK_NATIVE_WINDOWS", "1", 1); | |
| 63 | |
| 64 gfx::GtkInitFromCommandLine(*CommandLine::ForCurrentProcess()); | |
| 65 | |
| 66 // GTK after 2.18 resets the environment variable. But if we're using | |
| 67 // nspluginwrapper, that means it'll spawn its subprocess without the | |
| 68 // environment variable! So set it again. | |
| 69 setenv("GDK_NATIVE_WINDOWS", "1", 1); | |
| 70 } | |
| 71 | |
| 72 ui::SetDefaultX11ErrorHandlers(); | |
| 73 #endif | |
| 74 | |
| 75 PatchNPNFunctions(); | |
| 76 | |
| 77 // Preload the library to avoid loading, unloading then reloading | |
| 78 preloaded_plugin_module_ = base::LoadNativeLibrary(plugin_path_); | |
| 79 | |
| 80 scoped_refptr<webkit::npapi::PluginLib> plugin( | |
| 81 webkit::npapi::PluginLib::CreatePluginLib(plugin_path_)); | |
| 82 if (plugin.get()) | |
| 83 plugin->NP_Initialize(); | |
| 84 | |
| 85 content::GetContentClient()->PluginProcessStarted( | |
| 86 plugin.get() ? plugin->plugin_info().name : string16()); | |
| 87 | |
| 88 // Certain plugins, such as flash, steal the unhandled exception filter | |
| 89 // thus we never get crash reports when they fault. This call fixes it. | |
| 90 message_loop()->set_exception_restoration(true); | |
| 91 } | |
| 92 | |
| 93 PluginThread::~PluginThread() { | |
| 94 if (preloaded_plugin_module_) { | |
| 95 base::UnloadNativeLibrary(preloaded_plugin_module_); | |
| 96 preloaded_plugin_module_ = NULL; | |
| 97 } | |
| 98 PluginChannelBase::CleanupChannels(); | |
| 99 webkit::npapi::PluginLib::UnloadAllPlugins(); | |
| 100 | |
| 101 if (webkit_glue::ShouldForcefullyTerminatePluginProcess()) | |
| 102 base::KillProcess(base::GetCurrentProcessHandle(), 0, /* wait= */ false); | |
| 103 | |
| 104 lazy_tls.Pointer()->Set(NULL); | |
| 105 } | |
| 106 | |
| 107 PluginThread* PluginThread::current() { | |
| 108 return lazy_tls.Pointer()->Get(); | |
| 109 } | |
| 110 | |
| 111 bool PluginThread::OnControlMessageReceived(const IPC::Message& msg) { | |
| 112 bool handled = true; | |
| 113 IPC_BEGIN_MESSAGE_MAP(PluginThread, msg) | |
| 114 IPC_MESSAGE_HANDLER(PluginProcessMsg_CreateChannel, OnCreateChannel) | |
| 115 IPC_MESSAGE_HANDLER(PluginProcessMsg_NotifyRenderersOfPendingShutdown, | |
| 116 OnNotifyRenderersOfPendingShutdown) | |
| 117 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 118 IPC_END_MESSAGE_MAP() | |
| 119 return handled; | |
| 120 } | |
| 121 | |
| 122 void PluginThread::OnCreateChannel(int renderer_id, | |
| 123 bool incognito) { | |
| 124 scoped_refptr<PluginChannel> channel(PluginChannel::GetPluginChannel( | |
| 125 renderer_id, ChildProcess::current()->io_message_loop())); | |
| 126 IPC::ChannelHandle channel_handle; | |
| 127 if (channel.get()) { | |
| 128 channel_handle.name = channel->channel_handle().name; | |
| 129 #if defined(OS_POSIX) | |
| 130 // On POSIX, pass the renderer-side FD. | |
| 131 channel_handle.socket = base::FileDescriptor(channel->renderer_fd(), false); | |
| 132 #endif | |
| 133 channel->set_incognito(incognito); | |
| 134 } | |
| 135 | |
| 136 Send(new PluginProcessHostMsg_ChannelCreated(channel_handle)); | |
| 137 } | |
| 138 | |
| 139 void PluginThread::OnNotifyRenderersOfPendingShutdown() { | |
| 140 PluginChannel::NotifyRenderersOfPendingShutdown(); | |
| 141 } | |
| 142 | |
| 143 namespace webkit_glue { | |
| 144 | |
| 145 #if defined(OS_WIN) | |
| 146 bool DownloadUrl(const std::string& url, HWND caller_window) { | |
| 147 PluginThread* plugin_thread = PluginThread::current(); | |
| 148 if (!plugin_thread) { | |
| 149 return false; | |
| 150 } | |
| 151 | |
| 152 IPC::Message* message = | |
| 153 new PluginProcessHostMsg_DownloadUrl(MSG_ROUTING_NONE, url, | |
| 154 ::GetCurrentProcessId(), | |
| 155 caller_window); | |
| 156 return plugin_thread->Send(message); | |
| 157 } | |
| 158 #endif | |
| 159 | |
| 160 bool GetPluginFinderURL(std::string* plugin_finder_url) { | |
| 161 if (!plugin_finder_url) { | |
| 162 NOTREACHED(); | |
| 163 return false; | |
| 164 } | |
| 165 | |
| 166 PluginThread* plugin_thread = PluginThread::current(); | |
| 167 if (!plugin_thread) | |
| 168 return false; | |
| 169 | |
| 170 plugin_thread->Send( | |
| 171 new PluginProcessHostMsg_GetPluginFinderUrl(plugin_finder_url)); | |
| 172 // If we get an empty string back this means the plugin finder has been | |
| 173 // disabled. | |
| 174 return true; | |
| 175 } | |
| 176 | |
| 177 bool IsDefaultPluginEnabled() { | |
| 178 return true; | |
| 179 } | |
| 180 | |
| 181 bool FindProxyForUrl(const GURL& url, std::string* proxy_list) { | |
| 182 int net_error; | |
| 183 std::string proxy_result; | |
| 184 | |
| 185 bool result = ChildThread::current()->Send( | |
| 186 new ChildProcessHostMsg_ResolveProxy(url, &net_error, &proxy_result)); | |
| 187 if (!result || net_error != net::OK) | |
| 188 return false; | |
| 189 | |
| 190 *proxy_list = proxy_result; | |
| 191 return true; | |
| 192 } | |
| 193 | |
| 194 } // namespace webkit_glue | |
| OLD | NEW |