9db0a52f60
In the plugin process, gtk_init needs to be called from the UI thread (PluginThread) not the main thread (PluginMain) which is an IO thread. Review URL: http://codereview.chromium.org/149424 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20340 0039d316-1c4b-4281-b951-d872f2087c98
228 linhas
6.9 KiB
C++
228 linhas
6.9 KiB
C++
// Copyright (c) 2006-2008 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/plugin/plugin_thread.h"
|
|
|
|
#include "build/build_config.h"
|
|
|
|
#if defined(OS_WIN)
|
|
#include <windows.h>
|
|
#include <objbase.h>
|
|
#endif
|
|
|
|
#include "base/command_line.h"
|
|
#include "base/lazy_instance.h"
|
|
#include "base/process_util.h"
|
|
#include "base/thread_local.h"
|
|
#include "chrome/common/child_process.h"
|
|
#include "chrome/common/chrome_plugin_lib.h"
|
|
#include "chrome/common/chrome_switches.h"
|
|
#include "chrome/common/notification_service.h"
|
|
#include "chrome/common/plugin_messages.h"
|
|
#include "chrome/common/render_messages.h"
|
|
#include "chrome/plugin/chrome_plugin_host.h"
|
|
#include "chrome/plugin/npobject_util.h"
|
|
#include "chrome/renderer/render_thread.h"
|
|
#include "net/base/net_errors.h"
|
|
#include "webkit/glue/plugins/plugin_lib.h"
|
|
#include "webkit/glue/webkit_glue.h"
|
|
|
|
static base::LazyInstance<base::ThreadLocalPointer<PluginThread> > lazy_tls(
|
|
base::LINKER_INITIALIZED);
|
|
|
|
PluginThread::PluginThread()
|
|
: ChildThread(base::Thread::Options(MessageLoop::TYPE_UI, 0)),
|
|
preloaded_plugin_module_(NULL) {
|
|
plugin_path_ = FilePath::FromWStringHack(
|
|
CommandLine::ForCurrentProcess()->GetSwitchValue(switches::kPluginPath));
|
|
}
|
|
|
|
PluginThread::~PluginThread() {
|
|
}
|
|
|
|
PluginThread* PluginThread::current() {
|
|
return lazy_tls.Pointer()->Get();
|
|
}
|
|
|
|
void PluginThread::OnControlMessageReceived(const IPC::Message& msg) {
|
|
IPC_BEGIN_MESSAGE_MAP(PluginThread, msg)
|
|
IPC_MESSAGE_HANDLER(PluginProcessMsg_CreateChannel, OnCreateChannel)
|
|
IPC_MESSAGE_HANDLER(PluginProcessMsg_PluginMessage, OnPluginMessage)
|
|
IPC_END_MESSAGE_MAP()
|
|
}
|
|
|
|
void PluginThread::Init() {
|
|
lazy_tls.Pointer()->Set(this);
|
|
#if defined(OS_LINUX)
|
|
{
|
|
// XEmbed plugins assume they are hosted in a Gtk application, so we need
|
|
// to initialize Gtk in the plugin process.
|
|
const std::vector<std::string>& args =
|
|
CommandLine::ForCurrentProcess()->argv();
|
|
int argc = args.size();
|
|
scoped_array<char *> argv(new char *[argc + 1]);
|
|
for (size_t i = 0; i < args.size(); ++i) {
|
|
// TODO(piman@google.com): can gtk_init modify argv? Just being safe
|
|
// here.
|
|
argv[i] = strdup(args[i].c_str());
|
|
}
|
|
argv[argc] = NULL;
|
|
char **argv_pointer = argv.get();
|
|
gtk_init(&argc, &argv_pointer);
|
|
for (size_t i = 0; i < args.size(); ++i) {
|
|
free(argv[i]);
|
|
}
|
|
}
|
|
#endif
|
|
ChildThread::Init();
|
|
|
|
PatchNPNFunctions();
|
|
#if defined(OS_WIN)
|
|
CoInitialize(NULL);
|
|
#endif
|
|
|
|
notification_service_.reset(new NotificationService);
|
|
|
|
// Preload the library to avoid loading, unloading then reloading
|
|
preloaded_plugin_module_ = base::LoadNativeLibrary(plugin_path_);
|
|
|
|
ChromePluginLib::Create(plugin_path_, GetCPBrowserFuncsForPlugin());
|
|
|
|
scoped_refptr<NPAPI::PluginLib> plugin =
|
|
NPAPI::PluginLib::CreatePluginLib(plugin_path_);
|
|
if (plugin.get()) {
|
|
plugin->NP_Initialize();
|
|
}
|
|
|
|
// Certain plugins, such as flash, steal the unhandled exception filter
|
|
// thus we never get crash reports when they fault. This call fixes it.
|
|
message_loop()->set_exception_restoration(true);
|
|
}
|
|
|
|
void PluginThread::CleanUp() {
|
|
if (preloaded_plugin_module_) {
|
|
base::UnloadNativeLibrary(preloaded_plugin_module_);
|
|
preloaded_plugin_module_ = NULL;
|
|
}
|
|
PluginChannelBase::CleanupChannels();
|
|
NPAPI::PluginLib::UnloadAllPlugins();
|
|
ChromePluginLib::UnloadAllPlugins();
|
|
notification_service_.reset();
|
|
#if defined(OS_WIN)
|
|
CoUninitialize();
|
|
#endif
|
|
|
|
if (webkit_glue::ShouldForcefullyTerminatePluginProcess())
|
|
base::KillProcess(base::GetCurrentProcessHandle(), 0, /* wait= */ false);
|
|
|
|
// Call this last because it deletes the ResourceDispatcher, which is used
|
|
// in some of the above cleanup.
|
|
// See http://code.google.com/p/chromium/issues/detail?id=8980
|
|
ChildThread::CleanUp();
|
|
lazy_tls.Pointer()->Set(NULL);
|
|
}
|
|
|
|
void PluginThread::OnCreateChannel(
|
|
int process_id,
|
|
bool off_the_record) {
|
|
scoped_refptr<PluginChannel> channel =
|
|
PluginChannel::GetPluginChannel(process_id, owner_loop());
|
|
IPC::ChannelHandle channel_handle;
|
|
if (channel.get()) {
|
|
channel_handle.name = channel->channel_name();
|
|
#if defined(OS_POSIX)
|
|
// On POSIX, pass the renderer-side FD. Also mark it as auto-close so that
|
|
// it gets closed after it has been sent.
|
|
int renderer_fd = channel->DisownRendererFd();
|
|
channel_handle.socket = base::FileDescriptor(renderer_fd, true);
|
|
#endif
|
|
channel->set_off_the_record(off_the_record);
|
|
}
|
|
|
|
Send(new PluginProcessHostMsg_ChannelCreated(channel_handle));
|
|
}
|
|
|
|
void PluginThread::OnPluginMessage(const std::vector<unsigned char> &data) {
|
|
// We Add/Release ref here to ensure that something will trigger the
|
|
// shutdown mechanism for processes started in the absence of renderer's
|
|
// opening a plugin channel.
|
|
ChildProcess::current()->AddRefProcess();
|
|
ChromePluginLib *chrome_plugin = ChromePluginLib::Find(plugin_path_);
|
|
if (chrome_plugin) {
|
|
void *data_ptr = const_cast<void*>(reinterpret_cast<const void*>(&data[0]));
|
|
uint32 data_len = static_cast<uint32>(data.size());
|
|
chrome_plugin->functions().on_message(data_ptr, data_len);
|
|
}
|
|
ChildProcess::current()->ReleaseProcess();
|
|
}
|
|
|
|
namespace webkit_glue {
|
|
|
|
#if defined(OS_WIN)
|
|
bool DownloadUrl(const std::string& url, HWND caller_window) {
|
|
PluginThread* plugin_thread = PluginThread::current();
|
|
if (!plugin_thread) {
|
|
return false;
|
|
}
|
|
|
|
IPC::Message* message =
|
|
new PluginProcessHostMsg_DownloadUrl(MSG_ROUTING_NONE, url,
|
|
::GetCurrentProcessId(),
|
|
caller_window);
|
|
return plugin_thread->Send(message);
|
|
}
|
|
#endif
|
|
|
|
bool GetPluginFinderURL(std::string* plugin_finder_url) {
|
|
if (!plugin_finder_url) {
|
|
NOTREACHED();
|
|
return false;
|
|
}
|
|
|
|
PluginThread* plugin_thread = PluginThread::current();
|
|
if (!plugin_thread)
|
|
return false;
|
|
|
|
plugin_thread->Send(
|
|
new PluginProcessHostMsg_GetPluginFinderUrl(plugin_finder_url));
|
|
DCHECK(!plugin_finder_url->empty());
|
|
return true;
|
|
}
|
|
|
|
bool IsDefaultPluginEnabled() {
|
|
#if defined(OS_WIN)
|
|
return true;
|
|
#elif defined(OS_LINUX)
|
|
// http://code.google.com/p/chromium/issues/detail?id=10952
|
|
return false;
|
|
#elif defined(OS_MACOSX)
|
|
NOTIMPLEMENTED();
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
// Dispatch the resolve proxy resquest to the right code, depending on which
|
|
// process the plugin is running in {renderer, browser, plugin}.
|
|
bool FindProxyForUrl(const GURL& url, std::string* proxy_list) {
|
|
int net_error;
|
|
std::string proxy_result;
|
|
|
|
bool result;
|
|
if (IsPluginProcess()) {
|
|
result = PluginThread::current()->Send(
|
|
new PluginProcessHostMsg_ResolveProxy(url, &net_error, &proxy_result));
|
|
} else {
|
|
result = RenderThread::current()->Send(
|
|
new ViewHostMsg_ResolveProxy(url, &net_error, &proxy_result));
|
|
}
|
|
|
|
if (!result || net_error != net::OK)
|
|
return false;
|
|
|
|
*proxy_list = proxy_result;
|
|
return true;
|
|
}
|
|
|
|
} // namespace webkit_glue
|