summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/browser_uitest.cc2
-rw-r--r--chrome/common/plugin_messages.h13
-rw-r--r--chrome/common/plugin_messages_internal.h6
-rw-r--r--chrome/plugin/npobject_proxy.cc72
-rw-r--r--chrome/plugin/npobject_proxy.h12
-rw-r--r--chrome/plugin/npobject_stub.cc18
-rw-r--r--chrome/plugin/npobject_stub.h9
-rw-r--r--chrome/plugin/npobject_util.cc8
-rw-r--r--chrome/plugin/npobject_util.h8
-rw-r--r--chrome/plugin/plugin_channel.cc121
-rw-r--r--chrome/plugin/plugin_channel.h12
-rw-r--r--chrome/plugin/plugin_channel_base.cc9
-rw-r--r--chrome/plugin/plugin_channel_base.h5
-rw-r--r--chrome/plugin/webplugin_delegate_stub.cc10
-rw-r--r--chrome/plugin/webplugin_delegate_stub.h1
-rw-r--r--chrome/plugin/webplugin_proxy.cc45
-rw-r--r--chrome/plugin/webplugin_proxy.h17
-rw-r--r--chrome/renderer/plugin_channel_host.h4
-rw-r--r--chrome/renderer/render_view.cc13
-rw-r--r--chrome/renderer/render_view.h13
-rw-r--r--chrome/renderer/webplugin_delegate_proxy.cc12
21 files changed, 245 insertions, 165 deletions
diff --git a/chrome/browser/browser_uitest.cc b/chrome/browser/browser_uitest.cc
index 1ef62a1..0a3fee9 100644
--- a/chrome/browser/browser_uitest.cc
+++ b/chrome/browser/browser_uitest.cc
@@ -191,7 +191,6 @@ TEST_F(VisibleBrowserTest, WindowOpenClose) {
}
#endif
-#if defined(OS_WIN) // only works on Windows for now: http:://crbug.com/15891
class ShowModalDialogTest : public UITest {
public:
ShowModalDialogTest() {
@@ -221,7 +220,6 @@ TEST_F(ShowModalDialogTest, BasicTest) {
ASSERT_TRUE(tab->GetTabTitle(&title));
ASSERT_EQ(L"SUCCESS", title);
}
-#endif
class SecurityTest : public UITest {
protected:
diff --git a/chrome/common/plugin_messages.h b/chrome/common/plugin_messages.h
index 142450c..d507882 100644
--- a/chrome/common/plugin_messages.h
+++ b/chrome/common/plugin_messages.h
@@ -37,9 +37,6 @@ struct PluginMsg_Init_Params {
GURL page_url;
std::vector<std::string> arg_names;
std::vector<std::string> arg_values;
-#if defined(OS_WIN)
- HANDLE modal_dialog_event;
-#endif
bool load_manually;
};
@@ -123,9 +120,6 @@ struct ParamTraits<PluginMsg_Init_Params> {
DCHECK(p.arg_names.size() == p.arg_values.size());
WriteParam(m, p.arg_names);
WriteParam(m, p.arg_values);
-#if defined(OS_WIN)
- WriteParam(m, p.modal_dialog_event);
-#endif
WriteParam(m, p.load_manually);
}
static bool Read(const Message* m, void** iter, param_type* p) {
@@ -134,9 +128,6 @@ struct ParamTraits<PluginMsg_Init_Params> {
ReadParam(m, iter, &p->page_url) &&
ReadParam(m, iter, &p->arg_names) &&
ReadParam(m, iter, &p->arg_values) &&
-#if defined(OS_WIN)
- ReadParam(m, iter, &p->modal_dialog_event) &&
-#endif
ReadParam(m, iter, &p->load_manually);
}
static void Log(const param_type& p, std::wstring* l) {
@@ -151,10 +142,6 @@ struct ParamTraits<PluginMsg_Init_Params> {
l->append(L", ");
LogParam(p.arg_values, l);
l->append(L", ");
-#if defined(OS_WIN)
- LogParam(p.modal_dialog_event, l);
- l->append(L", ");
-#endif
LogParam(p.load_manually, l);
l->append(L")");
}
diff --git a/chrome/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h
index 9049fa7..f03cf97 100644
--- a/chrome/common/plugin_messages_internal.h
+++ b/chrome/common/plugin_messages_internal.h
@@ -227,6 +227,12 @@ IPC_BEGIN_MESSAGES(Plugin)
IPC_SYNC_MESSAGE_ROUTED1_0(PluginMsg_HandleURLRequestReply,
PluginMsg_URLRequestReply_Params)
+
+ IPC_MESSAGE_CONTROL1(PluginMsg_SignalModalDialogEvent,
+ gfx::NativeViewId /* containing_window */)
+
+ IPC_MESSAGE_CONTROL1(PluginMsg_ResetModalDialogEvent,
+ gfx::NativeViewId /* containing_window */)
IPC_END_MESSAGES(Plugin)
diff --git a/chrome/plugin/npobject_proxy.cc b/chrome/plugin/npobject_proxy.cc
index f224cdb..492c6c8 100644
--- a/chrome/plugin/npobject_proxy.cc
+++ b/chrome/plugin/npobject_proxy.cc
@@ -4,10 +4,9 @@
#include "chrome/plugin/npobject_proxy.h"
-#include "base/waitable_event.h"
#include "chrome/common/plugin_messages.h"
#include "chrome/plugin/npobject_util.h"
-#include "chrome/plugin/plugin_channel_base.h"
+#include "chrome/plugin/plugin_channel.h"
#include "webkit/api/public/WebBindings.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/glue/plugins/plugin_instance.h"
@@ -51,12 +50,12 @@ NPObjectProxy::NPObjectProxy(
PluginChannelBase* channel,
int route_id,
intptr_t npobject_ptr,
- base::WaitableEvent* modal_dialog_event,
+ gfx::NativeViewId containing_window,
const GURL& page_url)
: channel_(channel),
route_id_(route_id),
npobject_ptr_(npobject_ptr),
- modal_dialog_event_(modal_dialog_event),
+ containing_window_(containing_window),
page_url_(page_url) {
channel_->AddRoute(route_id, this, true);
}
@@ -72,12 +71,12 @@ NPObjectProxy::~NPObjectProxy() {
NPObject* NPObjectProxy::Create(PluginChannelBase* channel,
int route_id,
intptr_t npobject_ptr,
- base::WaitableEvent* modal_dialog_event,
+ gfx::NativeViewId containing_window,
const GURL& page_url) {
NPObjectWrapper* obj = reinterpret_cast<NPObjectWrapper*>(
WebBindings::createObject(0, &npclass_proxy_));
obj->proxy = new NPObjectProxy(
- channel, route_id, npobject_ptr, modal_dialog_event, page_url);
+ channel, route_id, npobject_ptr, containing_window, page_url);
return reinterpret_cast<NPObject*>(obj);
}
@@ -161,6 +160,7 @@ bool NPObjectProxy::NPInvokePrivate(NPP npp,
}
bool result = false;
+ gfx::NativeViewId containing_window = proxy->containing_window_;
NPIdentifier_Param name_param;
if (is_default) {
// The data won't actually get used, but set it so we don't send random
@@ -177,7 +177,7 @@ bool NPObjectProxy::NPInvokePrivate(NPP npp,
for (unsigned int i = 0; i < arg_count; ++i) {
NPVariant_Param param;
CreateNPVariantParam(
- args[i], channel_copy, &param, false, proxy->modal_dialog_event_,
+ args[i], channel_copy, &param, false, containing_window,
proxy->page_url_);
args_param.push_back(param);
}
@@ -192,9 +192,13 @@ bool NPObjectProxy::NPInvokePrivate(NPP npp,
// queue while waiting for a reply. We need to do this to simulate what
// happens when everything runs in-process (while calling MessageBox window
// messages are pumped).
- msg->set_pump_messages_event(proxy->modal_dialog_event_);
-
- base::WaitableEvent* modal_dialog_event_handle = proxy->modal_dialog_event_;
+ if (IsPluginProcess()) {
+ PluginChannel* channel = static_cast<PluginChannel*>(proxy->channel_.get());
+ if (channel) {
+ msg->set_pump_messages_event(
+ channel->GetModalDialogEvent(containing_window));
+ }
+ }
GURL page_url = proxy->page_url_;
proxy->Send(msg);
@@ -206,8 +210,7 @@ bool NPObjectProxy::NPInvokePrivate(NPP npp,
return false;
CreateNPVariant(
- param_result, channel_copy, np_result, modal_dialog_event_handle,
- page_url);
+ param_result, channel_copy, np_result, containing_window, page_url);
return true;
}
@@ -248,17 +251,17 @@ bool NPObjectProxy::NPGetProperty(NPObject *obj,
if (obj == NULL)
return false;
- bool result = false;
NPObjectProxy* proxy = GetProxy(obj);
if (!proxy) {
return obj->_class->getProperty(obj, name, np_result);
}
+ bool result = false;
+ gfx::NativeViewId containing_window = proxy->containing_window_;
NPIdentifier_Param name_param;
CreateNPIdentifierParam(name, &name_param);
NPVariant_Param param;
- base::WaitableEvent* modal_dialog_event_handle = proxy->modal_dialog_event_;
scoped_refptr<PluginChannelBase> channel(proxy->channel_);
GURL page_url = proxy->page_url_;
@@ -270,7 +273,7 @@ bool NPObjectProxy::NPGetProperty(NPObject *obj,
return false;
CreateNPVariant(
- param, channel.get(), np_result, modal_dialog_event_handle, page_url);
+ param, channel.get(), np_result, containing_window, page_url);
return true;
}
@@ -281,19 +284,20 @@ bool NPObjectProxy::NPSetProperty(NPObject *obj,
if (obj == NULL)
return false;
- bool result = false;
NPObjectProxy* proxy = GetProxy(obj);
if (!proxy) {
return obj->_class->setProperty(obj, name, value);
}
+ bool result = false;
+ gfx::NativeViewId containing_window = proxy->containing_window_;
NPIdentifier_Param name_param;
CreateNPIdentifierParam(name, &name_param);
NPVariant_Param value_param;
CreateNPVariantParam(
*value, proxy->channel(), &value_param, false,
- proxy->modal_dialog_event_, proxy->page_url_);
+ containing_window, proxy->page_url_);
proxy->Send(new NPObjectMsg_SetProperty(
proxy->route_id(), name_param, value_param, &result));
@@ -384,6 +388,7 @@ bool NPObjectProxy::NPNConstruct(NPObject *obj,
}
bool result = false;
+ gfx::NativeViewId containing_window = proxy->containing_window_;
// Note: This instance can get destroyed in the context of
// Send so addref the channel in this scope.
@@ -392,7 +397,7 @@ bool NPObjectProxy::NPNConstruct(NPObject *obj,
for (unsigned int i = 0; i < arg_count; ++i) {
NPVariant_Param param;
CreateNPVariantParam(
- args[i], channel_copy, &param, false, proxy->modal_dialog_event_,
+ args[i], channel_copy, &param, false, containing_window,
proxy->page_url_);
args_param.push_back(param);
}
@@ -402,9 +407,13 @@ bool NPObjectProxy::NPNConstruct(NPObject *obj,
proxy->route_id_, args_param, &param_result, &result);
// See comment in NPObjectProxy::NPInvokePrivate.
- msg->set_pump_messages_event(proxy->modal_dialog_event_);
-
- base::WaitableEvent* modal_dialog_event_handle = proxy->modal_dialog_event_;
+ if (IsPluginProcess()) {
+ PluginChannel* channel = static_cast<PluginChannel*>(proxy->channel_.get());
+ if (channel) {
+ msg->set_pump_messages_event(
+ channel->GetModalDialogEvent(proxy->containing_window_));
+ }
+ }
GURL page_url = proxy->page_url_;
proxy->Send(msg);
@@ -416,8 +425,7 @@ bool NPObjectProxy::NPNConstruct(NPObject *obj,
return false;
CreateNPVariant(
- param_result, channel_copy, np_result, modal_dialog_event_handle,
- page_url);
+ param_result, channel_copy, np_result, containing_window, page_url);
return true;
}
@@ -425,12 +433,13 @@ bool NPObjectProxy::NPNEvaluate(NPP npp,
NPObject *obj,
NPString *script,
NPVariant *result_var) {
- bool result = false;
NPObjectProxy* proxy = GetProxy(obj);
if (!proxy) {
return false;
}
+ bool result = false;
+ gfx::NativeViewId containing_window = proxy->containing_window_;
bool popups_allowed = false;
if (npp) {
@@ -450,11 +459,15 @@ bool NPObjectProxy::NPNEvaluate(NPP npp,
&result_param,
&result);
- // Please refer to the comments in NPObjectProxy::NPInvokePrivate for
- // the reasoning behind setting the pump messages event in the sync message.
- msg->set_pump_messages_event(proxy->modal_dialog_event_);
+ // See comment in NPObjectProxy::NPInvokePrivate.
+ if (IsPluginProcess()) {
+ PluginChannel* channel = static_cast<PluginChannel*>(proxy->channel_.get());
+ if (channel) {
+ msg->set_pump_messages_event(
+ channel->GetModalDialogEvent(proxy->containing_window_));
+ }
+ }
scoped_refptr<PluginChannelBase> channel(proxy->channel_);
- base::WaitableEvent* modal_dialog_event_handle = proxy->modal_dialog_event_;
GURL page_url = proxy->page_url_;
proxy->Send(msg);
@@ -464,8 +477,7 @@ bool NPObjectProxy::NPNEvaluate(NPP npp,
return false;
CreateNPVariant(
- result_param, channel.get(), result_var, modal_dialog_event_handle,
- page_url);
+ result_param, channel.get(), result_var, containing_window, page_url);
return true;
}
diff --git a/chrome/plugin/npobject_proxy.h b/chrome/plugin/npobject_proxy.h
index 8858a1b..08b408d 100644
--- a/chrome/plugin/npobject_proxy.h
+++ b/chrome/plugin/npobject_proxy.h
@@ -8,6 +8,7 @@
#ifndef CHROME_PLUGIN_NPOBJECT_PROXY_H_
#define CHROME_PLUGIN_NPOBJECT_PROXY_H_
+#include "base/gfx/native_widget_types.h"
#include "base/ref_counted.h"
#include "googleurl/src/gurl.h"
#include "ipc/ipc_channel.h"
@@ -16,10 +17,6 @@
class PluginChannelBase;
struct NPObject;
-namespace base {
-class WaitableEvent;
-}
-
// When running a plugin in a different process from the renderer, we need to
// proxy calls to NPObjects across process boundaries. This happens both ways,
// as a plugin can get an NPObject for the window, and a page can get an
@@ -33,11 +30,10 @@ class NPObjectProxy : public IPC::Channel::Listener,
public:
~NPObjectProxy();
- // modal_dialog_event_ is must be valid for the lifetime of the NPObjectProxy.
static NPObject* Create(PluginChannelBase* channel,
int route_id,
intptr_t npobject_ptr,
- base::WaitableEvent* modal_dialog_event,
+ gfx::NativeViewId containing_window,
const GURL& page_url);
// IPC::Message::Sender implementation:
@@ -103,7 +99,7 @@ class NPObjectProxy : public IPC::Channel::Listener,
NPObjectProxy(PluginChannelBase* channel,
int route_id,
intptr_t npobject_ptr,
- base::WaitableEvent* modal_dialog_event,
+ gfx::NativeViewId containing_window,
const GURL& page_url);
// IPC::Channel::Listener implementation:
@@ -120,7 +116,7 @@ class NPObjectProxy : public IPC::Channel::Listener,
scoped_refptr<PluginChannelBase> channel_;
int route_id_;
intptr_t npobject_ptr_;
- base::WaitableEvent* modal_dialog_event_;
+ gfx::NativeViewId containing_window_;
// The url of the main frame hosting the plugin.
GURL page_url_;
diff --git a/chrome/plugin/npobject_stub.cc b/chrome/plugin/npobject_stub.cc
index a48049d..cc59bec 100644
--- a/chrome/plugin/npobject_stub.cc
+++ b/chrome/plugin/npobject_stub.cc
@@ -21,14 +21,14 @@ NPObjectStub::NPObjectStub(
NPObject* npobject,
PluginChannelBase* channel,
int route_id,
- base::WaitableEvent* modal_dialog_event,
+ gfx::NativeViewId containing_window,
const GURL& page_url)
: npobject_(npobject),
channel_(channel),
route_id_(route_id),
valid_(true),
web_plugin_delegate_proxy_(NULL),
- modal_dialog_event_(modal_dialog_event),
+ containing_window_(containing_window),
page_url_(page_url) {
channel_->AddRoute(route_id, this, true);
@@ -127,7 +127,7 @@ void NPObjectStub::OnInvoke(bool is_default,
NPVariant* args_var = new NPVariant[arg_count];
for (int i = 0; i < arg_count; ++i) {
CreateNPVariant(
- args[i], local_channel, &(args_var[i]), modal_dialog_event_,
+ args[i], local_channel, &(args_var[i]), containing_window_,
page_url_);
}
@@ -164,7 +164,7 @@ void NPObjectStub::OnInvoke(bool is_default,
delete[] args_var;
CreateNPVariantParam(
- result_var, local_channel, &result_param, true, modal_dialog_event_,
+ result_var, local_channel, &result_param, true, containing_window_,
page_url_);
NPObjectMsg_Invoke::WriteReplyParams(reply_msg, result_param, return_value);
local_channel->Send(reply_msg);
@@ -202,7 +202,7 @@ void NPObjectStub::OnGetProperty(const NPIdentifier_Param& name,
}
CreateNPVariantParam(
- result_var, channel_, property, true, modal_dialog_event_, page_url_);
+ result_var, channel_, property, true, containing_window_, page_url_);
}
void NPObjectStub::OnSetProperty(const NPIdentifier_Param& name,
@@ -214,7 +214,7 @@ void NPObjectStub::OnSetProperty(const NPIdentifier_Param& name,
NPIdentifier id = CreateNPIdentifier(name);
NPVariant property_var;
CreateNPVariant(
- property, channel_, &property_var, modal_dialog_event_, page_url_);
+ property, channel_, &property_var, containing_window_, page_url_);
if (IsPluginProcess()) {
if (npobject_->_class->setProperty) {
@@ -313,7 +313,7 @@ void NPObjectStub::OnConstruct(const std::vector<NPVariant_Param>& args,
NPVariant* args_var = new NPVariant[arg_count];
for (int i = 0; i < arg_count; ++i) {
CreateNPVariant(
- args[i], local_channel, &(args_var[i]), modal_dialog_event_, page_url_);
+ args[i], local_channel, &(args_var[i]), containing_window_, page_url_);
}
if (IsPluginProcess()) {
@@ -334,7 +334,7 @@ void NPObjectStub::OnConstruct(const std::vector<NPVariant_Param>& args,
delete[] args_var;
CreateNPVariantParam(
- result_var, local_channel, &result_param, true, modal_dialog_event_,
+ result_var, local_channel, &result_param, true, containing_window_,
page_url_);
NPObjectMsg_Invoke::WriteReplyParams(reply_msg, result_param, return_value);
local_channel->Send(reply_msg);
@@ -364,7 +364,7 @@ void NPObjectStub::OnEvaluate(const std::string& script,
NPVariant_Param result_param;
CreateNPVariantParam(
- result_var, local_channel, &result_param, true, modal_dialog_event_,
+ result_var, local_channel, &result_param, true, containing_window_,
page_url_);
NPObjectMsg_Evaluate::WriteReplyParams(reply_msg, result_param, return_value);
local_channel->Send(reply_msg);
diff --git a/chrome/plugin/npobject_stub.h b/chrome/plugin/npobject_stub.h
index 0f59290..6017f73 100644
--- a/chrome/plugin/npobject_stub.h
+++ b/chrome/plugin/npobject_stub.h
@@ -10,14 +10,11 @@
#include <vector>
+#include "base/gfx/native_widget_types.h"
#include "base/ref_counted.h"
#include "googleurl/src/gurl.h"
#include "ipc/ipc_channel.h"
-namespace base {
-class WaitableEvent;
-}
-
class PluginChannelBase;
class WebPluginDelegateProxy;
struct NPIdentifier_Param;
@@ -33,7 +30,7 @@ class NPObjectStub : public IPC::Channel::Listener,
NPObjectStub(NPObject* npobject,
PluginChannelBase* channel,
int route_id,
- base::WaitableEvent* modal_dialog_event,
+ gfx::NativeViewId containing_window,
const GURL& page_url);
~NPObjectStub();
@@ -91,7 +88,7 @@ class NPObjectStub : public IPC::Channel::Listener,
bool valid_;
WebPluginDelegateProxy* web_plugin_delegate_proxy_;
- base::WaitableEvent* modal_dialog_event_;
+ gfx::NativeViewId containing_window_;
// The url of the main frame hosting the plugin.
GURL page_url_;
diff --git a/chrome/plugin/npobject_util.cc b/chrome/plugin/npobject_util.cc
index 3625992..71d866e 100644
--- a/chrome/plugin/npobject_util.cc
+++ b/chrome/plugin/npobject_util.cc
@@ -141,7 +141,7 @@ void CreateNPVariantParam(const NPVariant& variant,
PluginChannelBase* channel,
NPVariant_Param* param,
bool release,
- base::WaitableEvent* modal_dialog_event,
+ gfx::NativeViewId containing_window,
const GURL& page_url) {
switch (variant.type) {
case NPVariantType_Void:
@@ -187,7 +187,7 @@ void CreateNPVariantParam(const NPVariant& variant,
param->type = NPVARIANT_PARAM_OBJECT_ROUTING_ID;
int route_id = channel->GenerateRouteID();
new NPObjectStub(
- variant.value.objectValue, channel, route_id, modal_dialog_event,
+ variant.value.objectValue, channel, route_id, containing_window,
page_url);
param->npobject_routing_id = route_id;
param->npobject_pointer =
@@ -209,7 +209,7 @@ void CreateNPVariantParam(const NPVariant& variant,
void CreateNPVariant(const NPVariant_Param& param,
PluginChannelBase* channel,
NPVariant* result,
- base::WaitableEvent* modal_dialog_event,
+ gfx::NativeViewId containing_window,
const GURL& page_url) {
switch (param.type) {
case NPVARIANT_PARAM_VOID:
@@ -243,7 +243,7 @@ void CreateNPVariant(const NPVariant_Param& param,
NPObjectProxy::Create(channel,
param.npobject_routing_id,
param.npobject_pointer,
- modal_dialog_event,
+ containing_window,
page_url);
break;
case NPVARIANT_PARAM_OBJECT_POINTER:
diff --git a/chrome/plugin/npobject_util.h b/chrome/plugin/npobject_util.h
index 861d591..3fcc701 100644
--- a/chrome/plugin/npobject_util.h
+++ b/chrome/plugin/npobject_util.h
@@ -26,10 +26,6 @@ struct NPVariant_Param;
typedef _NPVariant NPVariant;
typedef void *NPIdentifier;
-namespace base {
-class WaitableEvent;
-}
-
// Needs to be called early in the plugin process lifetime, before any
// plugin instances are initialized.
void PatchNPNFunctions();
@@ -53,14 +49,14 @@ void CreateNPVariantParam(const NPVariant& variant,
PluginChannelBase* channel,
NPVariant_Param* param,
bool release,
- base::WaitableEvent* modal_dialog_event,
+ gfx::NativeViewId containing_window,
const GURL& page_url);
// Creates an NPVariant from the marshalled object.
void CreateNPVariant(const NPVariant_Param& param,
PluginChannelBase* channel,
NPVariant* result,
- base::WaitableEvent* modal_dialog_event,
+ gfx::NativeViewId containing_window,
const GURL& page_url);
#if defined(OS_WIN)
diff --git a/chrome/plugin/plugin_channel.cc b/chrome/plugin/plugin_channel.cc
index f852a21..54ed6f3 100644
--- a/chrome/plugin/plugin_channel.cc
+++ b/chrome/plugin/plugin_channel.cc
@@ -5,13 +5,17 @@
#include "chrome/plugin/plugin_channel.h"
#include "base/command_line.h"
+#include "base/lock.h"
#include "base/process_util.h"
#include "base/string_util.h"
+#include "base/waitable_event.h"
#include "build/build_config.h"
#include "chrome/common/child_process.h"
#include "chrome/common/plugin_messages.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/plugin/plugin_thread.h"
+#include "chrome/plugin/webplugin_delegate_stub.h"
+#include "chrome/plugin/webplugin_proxy.h"
#if defined(OS_POSIX)
#include "ipc/ipc_channel_posix.h"
@@ -27,6 +31,107 @@ class PluginReleaseTask : public Task {
// How long we wait before releasing the plugin process.
static const int kPluginReleaseTimeMS = 10000;
+
+// If a sync call to the renderer results in a modal dialog, we need to have a
+// way to know so that we can run a nested message loop to simulate what would
+// happen in a single process browser and avoid deadlock.
+class PluginChannel::MessageFilter : public IPC::ChannelProxy::MessageFilter {
+ public:
+ MessageFilter() : channel_(NULL) { }
+ ~MessageFilter() {
+ // Clean up in case of renderer crash.
+ for (ModalDialogEventMap::iterator i = modal_dialog_event_map_.begin();
+ i != modal_dialog_event_map_.end(); ++i) {
+ delete i->second.event;
+ }
+ }
+
+ base::WaitableEvent* GetModalDialogEvent(
+ gfx::NativeViewId containing_window) {
+ AutoLock auto_lock(modal_dialog_event_map_lock_);
+ if (!modal_dialog_event_map_.count(containing_window)) {
+ NOTREACHED();
+ return NULL;
+ }
+
+ return modal_dialog_event_map_[containing_window].event;
+ }
+
+ // Decrement the ref count associated with the modal dialog event for the
+ // given tab.
+ void ReleaseModalDialogEvent(gfx::NativeViewId containing_window) {
+ AutoLock auto_lock(modal_dialog_event_map_lock_);
+ if (!modal_dialog_event_map_.count(containing_window)) {
+ NOTREACHED();
+ return;
+ }
+
+ if (--(modal_dialog_event_map_[containing_window].refcount))
+ return;
+
+ // Delete the event when the stack unwinds as it could be in use now.
+ MessageLoop::current()->DeleteSoon(
+ FROM_HERE, modal_dialog_event_map_[containing_window].event);
+ modal_dialog_event_map_.erase(containing_window);
+ }
+
+ bool Send(IPC::Message* message) {
+ // Need this function for the IPC_MESSAGE_HANDLER_DELAY_REPLY macro.
+ return channel_->Send(message);
+ }
+
+ private:
+ void OnFilterAdded(IPC::Channel* channel) { channel_ = channel; }
+
+ bool OnMessageReceived(const IPC::Message& message) {
+ IPC_BEGIN_MESSAGE_MAP(PluginChannel::MessageFilter, message)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(PluginMsg_Init, OnInit)
+ IPC_MESSAGE_HANDLER(PluginMsg_SignalModalDialogEvent,
+ OnSignalModalDialogEvent)
+ IPC_MESSAGE_HANDLER(PluginMsg_ResetModalDialogEvent,
+ OnResetModalDialogEvent)
+ IPC_END_MESSAGE_MAP()
+ return message.type() == PluginMsg_SignalModalDialogEvent::ID ||
+ message.type() == PluginMsg_ResetModalDialogEvent::ID;
+ }
+
+ void OnInit(const PluginMsg_Init_Params& params, IPC::Message* reply_msg) {
+ AutoLock auto_lock(modal_dialog_event_map_lock_);
+ if (modal_dialog_event_map_.count(params.containing_window)) {
+ modal_dialog_event_map_[params.containing_window].refcount++;
+ return;
+ }
+
+ WaitableEventWrapper wrapper;
+ wrapper.event = new base::WaitableEvent(true, false);
+ wrapper.refcount = 1;
+ modal_dialog_event_map_[params.containing_window] = wrapper;
+ }
+
+ void OnSignalModalDialogEvent(gfx::NativeViewId containing_window) {
+ AutoLock auto_lock(modal_dialog_event_map_lock_);
+ if (modal_dialog_event_map_.count(containing_window))
+ modal_dialog_event_map_[containing_window].event->Signal();
+ }
+
+ void OnResetModalDialogEvent(gfx::NativeViewId containing_window) {
+ AutoLock auto_lock(modal_dialog_event_map_lock_);
+ if (modal_dialog_event_map_.count(containing_window))
+ modal_dialog_event_map_[containing_window].event->Reset();
+ }
+
+ struct WaitableEventWrapper {
+ base::WaitableEvent* event;
+ int refcount; // There could be multiple plugin instances per tab.
+ };
+ typedef std::map<gfx::NativeViewId, WaitableEventWrapper> ModalDialogEventMap;
+ ModalDialogEventMap modal_dialog_event_map_;
+ Lock modal_dialog_event_map_lock_;
+
+ IPC::Channel* channel_;
+};
+
+
PluginChannel* PluginChannel::GetPluginChannel(int renderer_id,
MessageLoop* ipc_message_loop) {
// Map renderer ID to a (single) channel to that process.
@@ -54,7 +159,8 @@ PluginChannel::PluginChannel()
renderer_fd_(-1),
#endif
in_send_(0),
- off_the_record_(false) {
+ off_the_record_(false),
+ filter_(new MessageFilter()) {
SendUnblockingOnlyDuringDispatch();
ChildProcess::current()->AddRefProcess();
const CommandLine* command_line = CommandLine::ForCurrentProcess();
@@ -116,6 +222,8 @@ void PluginChannel::OnDestroyInstance(int instance_id,
IPC::Message* reply_msg) {
for (size_t i = 0; i < plugin_stubs_.size(); ++i) {
if (plugin_stubs_[i]->instance_id() == instance_id) {
+ filter_->ReleaseModalDialogEvent(
+ plugin_stubs_[i]->webplugin()->containing_window());
plugin_stubs_.erase(plugin_stubs_.begin() + i);
RemoveRoute(instance_id);
Send(reply_msg);
@@ -135,6 +243,11 @@ int PluginChannel::GenerateRouteID() {
return ++last_id;
}
+base::WaitableEvent* PluginChannel::GetModalDialogEvent(
+ gfx::NativeViewId containing_window) {
+ return filter_->GetModalDialogEvent(containing_window);
+}
+
void PluginChannel::OnChannelConnected(int32 peer_pid) {
base::ProcessHandle handle;
if (!base::OpenProcessHandle(peer_pid, &handle)) {
@@ -177,5 +290,9 @@ bool PluginChannel::Init(MessageLoop* ipc_message_loop, bool create_pipe_now) {
IPC::SocketPair(&plugin_fd, &renderer_fd_);
IPC::AddChannelSocket(channel_name(), plugin_fd);
#endif
- return PluginChannelBase::Init(ipc_message_loop, create_pipe_now);
+ if (!PluginChannelBase::Init(ipc_message_loop, create_pipe_now))
+ return false;
+
+ channel_->AddFilter(filter_.get());
+ return true;
}
diff --git a/chrome/plugin/plugin_channel.h b/chrome/plugin/plugin_channel.h
index 5e512f3..35c0799 100644
--- a/chrome/plugin/plugin_channel.h
+++ b/chrome/plugin/plugin_channel.h
@@ -6,11 +6,16 @@
#define CHROME_PLUGIN_PLUGIN_CHANNEL_H_
#include <vector>
+#include "base/ref_counted.h"
#include "base/scoped_handle.h"
#include "build/build_config.h"
#include "chrome/plugin/plugin_channel_base.h"
#include "chrome/plugin/webplugin_delegate_stub.h"
+namespace base {
+class WaitableEvent;
+}
+
// Encapsulates an IPC channel between the plugin process and one renderer
// process. On the renderer side there's a corresponding PluginChannelHost.
class PluginChannel : public PluginChannelBase {
@@ -34,6 +39,10 @@ class PluginChannel : public PluginChannelBase {
int GenerateRouteID();
+ // Returns the event that's set when a call to the renderer causes a modal
+ // dialog to come up.
+ base::WaitableEvent* GetModalDialogEvent(gfx::NativeViewId containing_window);
+
#if defined(OS_POSIX)
// When first created, the PluginChannel gets assigned the file descriptor
// for the renderer.
@@ -62,6 +71,8 @@ class PluginChannel : public PluginChannelBase {
virtual bool Init(MessageLoop* ipc_message_loop, bool create_pipe_now);
private:
+ class MessageFilter;
+
// Called on the plugin thread
PluginChannel();
@@ -90,6 +101,7 @@ class PluginChannel : public PluginChannelBase {
int in_send_; // Tracks if we're in a Send call.
bool log_messages_; // True if we should log sent and received messages.
bool off_the_record_; // True if the renderer is in off the record mode.
+ scoped_refptr<MessageFilter> filter_; // Handles the modal dialog events.
DISALLOW_EVIL_CONSTRUCTORS(PluginChannel);
};
diff --git a/chrome/plugin/plugin_channel_base.cc b/chrome/plugin/plugin_channel_base.cc
index 73a32e6..9c7d3ca 100644
--- a/chrome/plugin/plugin_channel_base.cc
+++ b/chrome/plugin/plugin_channel_base.cc
@@ -46,6 +46,15 @@ PluginChannelBase* PluginChannelBase::GetChannel(
return channel;
}
+void PluginChannelBase::Broadcast(IPC::Message* message) {
+ for (PluginChannelMap::iterator iter = g_plugin_channels_.begin();
+ iter != g_plugin_channels_.end();
+ ++iter) {
+ iter->second->Send(new IPC::Message(*message));
+ }
+ delete message;
+}
+
PluginChannelBase::PluginChannelBase()
: plugin_count_(0),
peer_pid_(0),
diff --git a/chrome/plugin/plugin_channel_base.h b/chrome/plugin/plugin_channel_base.h
index 9c72294..f8c3396 100644
--- a/chrome/plugin/plugin_channel_base.h
+++ b/chrome/plugin/plugin_channel_base.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/basictypes.h"
+#include "base/gfx/native_widget_types.h"
#include "base/hash_tables.h"
#include "base/message_loop.h"
#include "base/ref_counted.h"
@@ -64,6 +65,9 @@ class PluginChannelBase : public IPC::Channel::Listener,
PluginChannelFactory factory, MessageLoop* ipc_message_loop,
bool create_pipe_now);
+ // Sends a message to all instances.
+ static void Broadcast(IPC::Message* message);
+
// Called on the worker thread
PluginChannelBase();
@@ -86,7 +90,6 @@ class PluginChannelBase : public IPC::Channel::Listener,
scoped_ptr<IPC::SyncChannel> channel_;
private:
-
IPC::Channel::Mode mode_;
std::string channel_name_;
int plugin_count_;
diff --git a/chrome/plugin/webplugin_delegate_stub.cc b/chrome/plugin/webplugin_delegate_stub.cc
index cf2c689..ca247f7 100644
--- a/chrome/plugin/webplugin_delegate_stub.cc
+++ b/chrome/plugin/webplugin_delegate_stub.cc
@@ -148,12 +148,8 @@ void WebPluginDelegateStub::OnInit(const PluginMsg_Init_Params& params,
// params.containing_window, &parent));
#endif
- webplugin_ = new WebPluginProxy(channel_, instance_id_, page_url_);
-#if defined(OS_WIN)
- if (!webplugin_->SetModalDialogEvent(params.modal_dialog_event))
- return;
-#endif
-
+ webplugin_ = new WebPluginProxy(
+ channel_, instance_id_, page_url_, params.containing_window);
delegate_ = WebPluginDelegateImpl::Create(path, mime_type_, parent);
if (delegate_) {
webplugin_->set_delegate(delegate_);
@@ -289,7 +285,7 @@ void WebPluginDelegateStub::OnGetPluginScriptableObject(int* route_id,
// The stub will delete itself when the proxy tells it that it's released, or
// otherwise when the channel is closed.
new NPObjectStub(
- object, channel_.get(), *route_id, webplugin_->modal_dialog_event(),
+ object, channel_.get(), *route_id, webplugin_->containing_window(),
page_url_);
// Release ref added by GetPluginScriptableObject (our stub holds its own).
diff --git a/chrome/plugin/webplugin_delegate_stub.h b/chrome/plugin/webplugin_delegate_stub.h
index 9ad63d20..849066f 100644
--- a/chrome/plugin/webplugin_delegate_stub.h
+++ b/chrome/plugin/webplugin_delegate_stub.h
@@ -47,6 +47,7 @@ class WebPluginDelegateStub : public IPC::Channel::Listener,
virtual bool Send(IPC::Message* msg);
int instance_id() { return instance_id_; }
+ WebPluginProxy* webplugin() { return webplugin_; }
private:
// Message handlers for the WebPluginDelegate calls that are proxied from the
diff --git a/chrome/plugin/webplugin_proxy.cc b/chrome/plugin/webplugin_proxy.cc
index 0eb570a..ad0b1cb 100644
--- a/chrome/plugin/webplugin_proxy.cc
+++ b/chrome/plugin/webplugin_proxy.cc
@@ -17,7 +17,6 @@
#include "base/scoped_handle.h"
#include "base/shared_memory.h"
#include "base/singleton.h"
-#include "base/waitable_event.h"
#include "build/build_config.h"
#include "chrome/common/child_process_logging.h"
#include "chrome/common/plugin_messages.h"
@@ -46,7 +45,8 @@ static ContextMap& GetContextMap() {
WebPluginProxy::WebPluginProxy(
PluginChannel* channel,
int route_id,
- const GURL& page_url)
+ const GURL& page_url,
+ gfx::NativeViewId containing_window)
: channel_(channel),
route_id_(route_id),
cp_browsing_context_(0),
@@ -54,9 +54,9 @@ WebPluginProxy::WebPluginProxy(
plugin_element_(NULL),
delegate_(NULL),
waiting_for_paint_(false),
+ containing_window_(containing_window),
page_url_(page_url),
- ALLOW_THIS_IN_INITIALIZER_LIST(runnable_method_factory_(this))
-{
+ ALLOW_THIS_IN_INITIALIZER_LIST(runnable_method_factory_(this)) {
}
WebPluginProxy::~WebPluginProxy() {
@@ -95,27 +95,6 @@ void WebPluginProxy::SetWindowlessPumpEvent(HANDLE pump_messages_event) {
Send(new PluginHostMsg_SetWindowlessPumpEvent(
route_id_, pump_messages_event_for_renderer));
}
-
-bool WebPluginProxy::SetModalDialogEvent(HANDLE modal_dialog_event) {
- // TODO(port): figure out how this will be set in the browser process, or
- // come up with a different mechanism.
- HANDLE event = NULL;
- BOOL result = DuplicateHandle(channel_->renderer_handle(),
- modal_dialog_event,
- GetCurrentProcess(),
- &event,
- SYNCHRONIZE,
- FALSE,
- 0);
- DCHECK(result) <<
- "Couldn't duplicate the modal dialog handle for the plugin." \
- "handle: " << channel_->renderer_handle() << ". err: " << GetLastError();
- if (!event)
- return false;
-
- modal_dialog_event_.reset(new base::WaitableEvent(event));
- return true;
-}
#endif
void WebPluginProxy::CancelResource(int id) {
@@ -180,8 +159,7 @@ NPObject* WebPluginProxy::GetWindowScriptNPObject() {
return NULL;
window_npobject_ = NPObjectProxy::Create(
- channel_, npobject_route_id, npobject_ptr, modal_dialog_event_.get(),
- page_url_);
+ channel_, npobject_route_id, npobject_ptr, containing_window_, page_url_);
return window_npobject_;
}
@@ -199,8 +177,7 @@ NPObject* WebPluginProxy::GetPluginElement() {
return NULL;
plugin_element_ = NPObjectProxy::Create(
- channel_, npobject_route_id, npobject_ptr, modal_dialog_event_.get(),
- page_url_);
+ channel_, npobject_route_id, npobject_ptr, containing_window_, page_url_);
return plugin_element_;
}
@@ -226,13 +203,9 @@ void WebPluginProxy::ShowModalHTMLDialog(const GURL& url, int width, int height,
new PluginHostMsg_ShowModalHTMLDialog(
route_id_, url, width, height, json_arguments, json_retval);
- // Create a new event and set it. This forces us to pump messages while
- // waiting for a response (which won't come until the dialog is closed). This
- // avoids a deadlock.
- scoped_ptr<base::WaitableEvent> event(
- new base::WaitableEvent(false, true));
- msg->set_pump_messages_event(event.get());
-
+ // Pump messages while waiting for a response (which won't come until the
+ // dialog is closed). This avoids a deadlock.
+ msg->EnableMessagePumping();
Send(msg);
}
diff --git a/chrome/plugin/webplugin_proxy.h b/chrome/plugin/webplugin_proxy.h
index 0ff1890..8f74109 100644
--- a/chrome/plugin/webplugin_proxy.h
+++ b/chrome/plugin/webplugin_proxy.h
@@ -23,11 +23,6 @@
#include "webkit/glue/webplugin.h"
class PluginChannel;
-
-namespace base {
-class WaitableEvent;
-}
-
class WebPluginDelegateImpl;
// This is an implementation of WebPlugin that proxies all calls to the
@@ -38,7 +33,8 @@ class WebPluginProxy : public webkit_glue::WebPlugin {
// marshalled WebPlugin calls.
WebPluginProxy(PluginChannel* channel,
int route_id,
- const GURL& page_url);
+ const GURL& page_url,
+ gfx::NativeViewId containing_window);
~WebPluginProxy();
void set_delegate(WebPluginDelegateImpl* d) { delegate_ = d; }
@@ -48,9 +44,8 @@ class WebPluginProxy : public webkit_glue::WebPlugin {
void WillDestroyWindow(gfx::PluginWindowHandle window);
#if defined(OS_WIN)
void SetWindowlessPumpEvent(HANDLE pump_messages_event);
- // Returns true on success.
- bool SetModalDialogEvent(HANDLE modal_dialog_event);
#endif
+
void CancelResource(int id);
void Invalidate();
void InvalidateRect(const gfx::Rect& rect);
@@ -127,9 +122,7 @@ class WebPluginProxy : public webkit_glue::WebPlugin {
void ResourceClientDeleted(
webkit_glue::WebPluginResourceClient* resource_client);
- base::WaitableEvent* modal_dialog_event() {
- return modal_dialog_event_.get();
- }
+ gfx::NativeViewId containing_window() { return containing_window_; }
private:
bool Send(IPC::Message* msg);
@@ -166,7 +159,7 @@ class WebPluginProxy : public webkit_glue::WebPlugin {
WebPluginDelegateImpl* delegate_;
gfx::Rect damaged_rect_;
bool waiting_for_paint_;
- scoped_ptr<base::WaitableEvent> modal_dialog_event_;
+ gfx::NativeViewId containing_window_;
// The url of the main frame hosting the plugin.
GURL page_url_;
diff --git a/chrome/renderer/plugin_channel_host.h b/chrome/renderer/plugin_channel_host.h
index 8d27f9a..f3d066b 100644
--- a/chrome/renderer/plugin_channel_host.h
+++ b/chrome/renderer/plugin_channel_host.h
@@ -33,6 +33,10 @@ class PluginChannelHost : public PluginChannelBase {
static bool IsListening();
+ static void Broadcast(IPC::Message* message) {
+ PluginChannelBase::Broadcast(message);
+ }
+
private:
// Called on the render thread
PluginChannelHost();
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 231cfa7..66ac3bf 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -29,6 +29,7 @@
#include "chrome/common/chrome_constants.h"
#include "chrome/common/jstemplate_builder.h"
#include "chrome/common/page_zoom.h"
+#include "chrome/common/plugin_messages.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/renderer_preferences.h"
#include "chrome/common/thumbnail_score.h"
@@ -44,6 +45,7 @@
#include "chrome/renderer/localized_error.h"
#include "chrome/renderer/media/audio_renderer_impl.h"
#include "chrome/renderer/navigation_state.h"
+#include "chrome/renderer/plugin_channel_host.h"
#include "chrome/renderer/print_web_view_helper.h"
#include "chrome/renderer/render_process.h"
#include "chrome/renderer/user_script_slave.h"
@@ -208,7 +210,6 @@ RenderView::RenderView(RenderThreadBase* render_thread,
last_indexed_page_id_(-1),
opened_by_user_gesture_(true),
ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)),
- modal_dialog_count_(0),
devtools_agent_(NULL),
devtools_client_(NULL),
history_back_list_count_(0),
@@ -230,8 +231,6 @@ RenderView::RenderView(RenderThreadBase* render_thread,
document_tag_(0),
webkit_preferences_(webkit_preferences) {
Singleton<RenderViewSet>()->render_view_set_.insert(this);
-
- modal_dialog_event_.reset(new base::WaitableEvent(true, false));
}
RenderView::~RenderView() {
@@ -3573,14 +3572,14 @@ void RenderView::EnsureDocumentTag() {
}
bool RenderView::SendAndRunNestedMessageLoop(IPC::SyncMessage* message) {
- if (modal_dialog_count_++ == 0)
- modal_dialog_event_->Signal();
+ PluginChannelHost::Broadcast(
+ new PluginMsg_SignalModalDialogEvent(host_window_));
message->EnableMessagePumping(); // Runs a nested message loop.
bool rv = Send(message);
- if (--modal_dialog_count_ == 0)
- modal_dialog_event_->Reset();
+ PluginChannelHost::Broadcast(
+ new PluginMsg_ResetModalDialogEvent(host_window_));
return rv;
}
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index fd8c981..decad59 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -140,10 +140,6 @@ class RenderView : public RenderWidget,
return host_window_;
}
- base::WaitableEvent* modal_dialog_event() {
- return modal_dialog_event_.get();
- }
-
int browser_window_id() {
return browser_window_id_;
}
@@ -819,15 +815,6 @@ class RenderView : public RenderWidget,
// recent message if new ones come in).
scoped_ptr<IPC::Message> queued_find_reply_message_;
- // Handle to an event that's set when the page is showing a modal dialog (or
- // equivalent constrained window). The renderer and any plugin processes
- // check this to know if they should pump messages/tasks then.
- scoped_ptr<base::WaitableEvent> modal_dialog_event_;
-
- // Multiple dialog boxes can be shown before the first one is finished,
- // so we keep a counter to know when we can reset the modal dialog event.
- int modal_dialog_count_;
-
// Provides access to this renderer from the remote Inspector UI.
scoped_ptr<DevToolsAgent> devtools_agent_;
diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc
index 4c5e54e..cdf5720 100644
--- a/chrome/renderer/webplugin_delegate_proxy.cc
+++ b/chrome/renderer/webplugin_delegate_proxy.cc
@@ -271,9 +271,6 @@ bool WebPluginDelegateProxy::Initialize(const GURL& url,
}
}
params.load_manually = load_manually;
-#if defined(OS_WIN)
- params.modal_dialog_event = render_view_->modal_dialog_event()->handle();
-#endif
plugin_ = plugin;
@@ -746,8 +743,7 @@ NPObject* WebPluginDelegateProxy::GetPluginScriptableObject() {
return NULL;
npobject_ = NPObjectProxy::Create(
- channel_host_.get(), route_id, npobject_ptr,
- render_view_->modal_dialog_event(), page_url_);
+ channel_host_.get(), route_id, npobject_ptr, 0, page_url_);
return WebBindings::retainObject(npobject_);
}
@@ -833,8 +829,7 @@ void WebPluginDelegateProxy::OnGetWindowScriptNPObject(
// The stub will delete itself when the proxy tells it that it's released, or
// otherwise when the channel is closed.
NPObjectStub* stub = new NPObjectStub(
- npobject, channel_host_.get(), route_id,
- render_view_->modal_dialog_event(), page_url_);
+ npobject, channel_host_.get(), route_id, 0, page_url_);
window_script_object_ = stub;
window_script_object_->set_proxy(this);
*success = true;
@@ -853,8 +848,7 @@ void WebPluginDelegateProxy::OnGetPluginElement(
// The stub will delete itself when the proxy tells it that it's released, or
// otherwise when the channel is closed.
new NPObjectStub(
- npobject, channel_host_.get(), route_id,
- render_view_->modal_dialog_event(), page_url_);
+ npobject, channel_host_.get(), route_id, 0, page_url_);
*success = true;
*npobject_ptr = reinterpret_cast<intptr_t>(npobject);
}