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 |