summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/common/resource_dispatcher.cc27
-rw-r--r--chrome/common/resource_dispatcher.h4
-rw-r--r--chrome/renderer/render_view.cc26
-rw-r--r--chrome/renderer/render_view.h11
-rw-r--r--chrome/test/data/npapi/get_javascript_open_popup_with_plugin.html27
-rw-r--r--chrome/test/data/npapi/popup_window_with_target_plugin.html27
-rw-r--r--chrome/test/ui/npapi_uitest.cpp9
-rw-r--r--webkit/glue/plugins/test/SConscript1
-rw-r--r--webkit/glue/plugins/test/npapi_test_plugin.vcproj8
-rw-r--r--webkit/glue/plugins/test/plugin_client.cc11
-rw-r--r--webkit/glue/plugins/test/plugin_javascript_open_popup.cc52
-rw-r--r--webkit/glue/plugins/test/plugin_javascript_open_popup.h42
12 files changed, 234 insertions, 11 deletions
diff --git a/chrome/common/resource_dispatcher.cc b/chrome/common/resource_dispatcher.cc
index e3099af..81ed5a2 100644
--- a/chrome/common/resource_dispatcher.cc
+++ b/chrome/common/resource_dispatcher.cc
@@ -244,15 +244,8 @@ ResourceDispatcher::~ResourceDispatcher() {
// ResourceDispatcher implementation ------------------------------------------
bool ResourceDispatcher::OnMessageReceived(const IPC::Message& message) {
- switch (message.type()) {
- case ViewMsg_Resource_UploadProgress::ID:
- case ViewMsg_Resource_ReceivedResponse::ID:
- case ViewMsg_Resource_ReceivedRedirect::ID:
- case ViewMsg_Resource_DataReceived::ID:
- case ViewMsg_Resource_RequestComplete::ID:
- break;
- default:
- return false;
+ if (!IsResourceMessage(message)) {
+ return false;
}
int request_id;
@@ -508,3 +501,19 @@ webkit_glue::ResourceLoaderBridge* ResourceDispatcher::CreateBridge(
request_context);
}
+
+bool ResourceDispatcher::IsResourceMessage(const IPC::Message& message) const {
+ switch (message.type()) {
+ case ViewMsg_Resource_UploadProgress::ID:
+ case ViewMsg_Resource_ReceivedResponse::ID:
+ case ViewMsg_Resource_ReceivedRedirect::ID:
+ case ViewMsg_Resource_DataReceived::ID:
+ case ViewMsg_Resource_RequestComplete::ID:
+ return true;
+
+ default:
+ break;
+ }
+
+ return false;
+} \ No newline at end of file
diff --git a/chrome/common/resource_dispatcher.h b/chrome/common/resource_dispatcher.h
index 984aed2..b4c4037 100644
--- a/chrome/common/resource_dispatcher.h
+++ b/chrome/common/resource_dispatcher.h
@@ -68,6 +68,10 @@ class ResourceDispatcher : public base::RefCounted<ResourceDispatcher> {
message_sender_ = NULL;
}
+ // Returns true if the message passed in is a resource related
+ // message.
+ bool IsResourceMessage(const IPC::Message& message) const;
+
private:
friend class ResourceDispatcherTest;
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 253a869..f6c19d7 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -156,7 +156,8 @@ RenderView::RenderView()
disable_popup_blocking_(false),
has_unload_listener_(false),
decrement_shared_popup_at_destruction_(false),
- greasemonkey_enabled_(false) {
+ greasemonkey_enabled_(false),
+ waiting_for_create_window_ack_(false) {
resource_dispatcher_ = new ResourceDispatcher(this);
#ifdef CHROME_PERSONALIZATION
personalization_ = Personalization::CreateRendererPersonalization();
@@ -291,9 +292,22 @@ void RenderView::Init(HWND parent_hwnd,
}
void RenderView::OnMessageReceived(const IPC::Message& message) {
+ // If the current RenderView instance represents a popup, then we
+ // need to wait for ViewMsg_CreatingNew_ACK to be sent by the browser.
+ // As part of this ack we also receive the browser window handle, which
+ // parents any plugins instantiated in this RenderView instance.
+ // Plugins can be instantiated only when we receive the parent window
+ // handle as they are child windows.
+ if (waiting_for_create_window_ack_ &&
+ resource_dispatcher_->IsResourceMessage(message)) {
+ queued_resource_messages_.push(new IPC::Message(message));
+ return;
+ }
+
// Let the resource dispatcher intercept resource messages first.
if (resource_dispatcher_->OnMessageReceived(message))
return;
+
IPC_BEGIN_MESSAGE_MAP(RenderView, message)
IPC_MESSAGE_HANDLER(ViewMsg_CreatingNew_ACK, OnCreatingNewAck)
IPC_MESSAGE_HANDLER(ViewMsg_CaptureThumbnail, SendThumbnail)
@@ -375,6 +389,15 @@ void RenderView::OnMessageReceived(const IPC::Message& message) {
// view.
void RenderView::OnCreatingNewAck(HWND parent) {
CompleteInit(parent);
+
+ waiting_for_create_window_ack_ = false;
+
+ while (!queued_resource_messages_.empty()) {
+ IPC::Message* queued_msg = queued_resource_messages_.front();
+ queued_resource_messages_.pop();
+ resource_dispatcher_->OnMessageReceived(*queued_msg);
+ delete queued_msg;
+ }
}
void RenderView::SendThumbnail() {
@@ -1715,6 +1738,7 @@ WebView* RenderView::CreateWebView(WebView* webview, bool user_gesture) {
prefs, shared_popup_counter_,
routing_id);
view->set_opened_by_user_gesture(user_gesture);
+ view->set_waiting_for_create_window_ack(true);
// Copy over the alternate error page URL so we can have alt error pages in
// the new render view (we don't need the browser to send the URL back down).
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index cba9df9..9c50dfe 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -512,6 +512,10 @@ class RenderView : public RenderWidget, public WebViewDelegate,
// A helper method used by WasOpenedByUserGesture.
bool WasOpenedByUserGestureHelper() const;
+ void set_waiting_for_create_window_ack(bool wait) {
+ waiting_for_create_window_ack_ = wait;
+ }
+
// Handles resource loads for this view.
scoped_refptr<ResourceDispatcher> resource_dispatcher_;
@@ -658,6 +662,13 @@ class RenderView : public RenderWidget, public WebViewDelegate,
// True if Greasemonkey is enabled in this process.
bool greasemonkey_enabled_;
+ // Resource message queue. Used to queue up resource IPCs if we need
+ // to wait for an ACK from the browser before proceeding.
+ std::queue<IPC::Message*> queued_resource_messages_;
+
+ // Set if we are waiting for an ack for ViewHostMsg_CreateWindow
+ bool waiting_for_create_window_ack_;
+
DISALLOW_COPY_AND_ASSIGN(RenderView);
};
diff --git a/chrome/test/data/npapi/get_javascript_open_popup_with_plugin.html b/chrome/test/data/npapi/get_javascript_open_popup_with_plugin.html
new file mode 100644
index 0000000..8f2f01a
--- /dev/null
+++ b/chrome/test/data/npapi/get_javascript_open_popup_with_plugin.html
@@ -0,0 +1,27 @@
+<html>
+
+<head>
+<script src="npapi.js"></script>
+</head>
+
+
+<body>
+<div id="statusPanel" style="border: 1px solid red; width: 100%">
+Test running....
+</div>
+
+
+Open Popup window with plugin Test<p>
+This test instantiates a plugin which executes the window.open call to open a popup <br />
+window with a windowed plugin instance. The test verifies that the plugin instance in <br />
+the popup window always has a valid parent window. <br />
+
+<embed type="application/vnd.npapi-test"
+ src="foo"
+ name="plugin_javascript_open_popup_with_plugin"
+ id="1"
+ mode="np_embed"
+>
+
+</body>
+</html>
diff --git a/chrome/test/data/npapi/popup_window_with_target_plugin.html b/chrome/test/data/npapi/popup_window_with_target_plugin.html
new file mode 100644
index 0000000..5f203bd
--- /dev/null
+++ b/chrome/test/data/npapi/popup_window_with_target_plugin.html
@@ -0,0 +1,27 @@
+<html>
+
+<head>
+<script src="npapi.js"></script>
+</head>
+
+
+<body>
+<div id="statusPanel" style="border: 1px solid red; width: 100%">
+Test running....
+</div>
+
+
+Open Popup window with plugin Test<p>
+This test instantiates a plugin which executes the window.open call to open a popup <br />
+window with a windowed plugin instance. The test verifies that the plugin instance in <br />
+the popup window always has a valid parent window.<br />
+
+<embed type="application/vnd.npapi-test"
+ src="foo"
+ name="plugin_popup_with_plugin_target"
+ id="1"
+ mode="np_embed"
+>
+
+</body>
+</html>
diff --git a/chrome/test/ui/npapi_uitest.cpp b/chrome/test/ui/npapi_uitest.cpp
index 525e48e..bce1497 100644
--- a/chrome/test/ui/npapi_uitest.cpp
+++ b/chrome/test/ui/npapi_uitest.cpp
@@ -270,4 +270,13 @@ TEST_F(NPAPIVisiblePluginTester, SelfDeletePluginInNPNEvaluate) {
kTestCompleteCookie, kTestCompleteSuccess,
kShortWaitTimeout);
}
+}
+
+TEST_F(NPAPIVisiblePluginTester, OpenPopupWindowWithPlugin) {
+ GURL url = GetTestUrl(L"npapi",
+ L"get_javascript_open_popup_with_plugin.html");
+ NavigateToURL(url);
+ WaitForFinish("plugin_popup_with_plugin_target", "1", url,
+ kTestCompleteCookie, kTestCompleteSuccess,
+ kShortWaitTimeout);
} \ No newline at end of file
diff --git a/webkit/glue/plugins/test/SConscript b/webkit/glue/plugins/test/SConscript
index bfdc821..9068be2 100644
--- a/webkit/glue/plugins/test/SConscript
+++ b/webkit/glue/plugins/test/SConscript
@@ -16,6 +16,7 @@ input_files = [
'plugin_geturl_test.cc',
'plugin_new_fails_test.cc',
'plugin_npobject_proxy_test.cc',
+ 'plugin_javascript_open_popup.cc',
'plugin_test.cc'
]
diff --git a/webkit/glue/plugins/test/npapi_test_plugin.vcproj b/webkit/glue/plugins/test/npapi_test_plugin.vcproj
index ffcd76c..d52bba8 100644
--- a/webkit/glue/plugins/test/npapi_test_plugin.vcproj
+++ b/webkit/glue/plugins/test/npapi_test_plugin.vcproj
@@ -207,6 +207,14 @@
>
</File>
<File
+ RelativePath=".\plugin_javascript_open_popup.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\plugin_javascript_open_popup.h"
+ >
+ </File>
+ <File
RelativePath=".\plugin_new_fails_test.cc"
>
</File>
diff --git a/webkit/glue/plugins/test/plugin_client.cc b/webkit/glue/plugins/test/plugin_client.cc
index a2f5dc6..868810e 100644
--- a/webkit/glue/plugins/test/plugin_client.cc
+++ b/webkit/glue/plugins/test/plugin_client.cc
@@ -13,6 +13,7 @@
#include "webkit/glue/plugins/test/plugin_npobject_lifetime_test.h"
#include "webkit/glue/plugins/test/plugin_npobject_proxy_test.h"
#include "webkit/glue/plugins/test/plugin_window_size_test.h"
+#include "webkit/glue/plugins/test/plugin_javascript_open_popup.h"
#include "third_party/npapi/bindings/npapi.h"
#include "third_party/npapi/bindings/npruntime.h"
@@ -125,9 +126,17 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode,
new_test = new NPAPIClient::NewFailsTest(instance,
NPAPIClient::PluginClient::HostFunctions());
} else if (base::strcasecmp(argv[name_index],
- "npobject_delete_plugin_in_evaluate") == 0) {
+ "npobject_delete_plugin_in_evaluate") == 0) {
new_test = new NPAPIClient::NPObjectDeletePluginInNPN_Evaluate(instance,
NPAPIClient::PluginClient::HostFunctions());
+ } else if (base::strcasecmp(argv[name_index],
+ "plugin_javascript_open_popup_with_plugin") == 0) {
+ new_test = new NPAPIClient::ExecuteJavascriptOpenPopupWithPluginTest(
+ instance, NPAPIClient::PluginClient::HostFunctions());
+ } else if (base::strcasecmp(argv[name_index],
+ "plugin_popup_with_plugin_target") == 0) {
+ new_test = new NPAPIClient::ExecuteJavascriptPopupWindowTargetPluginTest(
+ instance, NPAPIClient::PluginClient::HostFunctions());
} else {
// If we don't have a test case for this, create a
// generic one which basically never fails.
diff --git a/webkit/glue/plugins/test/plugin_javascript_open_popup.cc b/webkit/glue/plugins/test/plugin_javascript_open_popup.cc
new file mode 100644
index 0000000..cd9c121
--- /dev/null
+++ b/webkit/glue/plugins/test/plugin_javascript_open_popup.cc
@@ -0,0 +1,52 @@
+// 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 "webkit/glue/plugins/test/plugin_javascript_open_popup.h"
+
+#include "webkit/glue/plugins/test/plugin_client.h"
+
+namespace NPAPIClient {
+
+ExecuteJavascriptOpenPopupWithPluginTest::
+ ExecuteJavascriptOpenPopupWithPluginTest(NPP id,
+ NPNetscapeFuncs *host_functions)
+ : PluginTest(id, host_functions),
+ popup_window_test_started_(false) {
+}
+
+int16 ExecuteJavascriptOpenPopupWithPluginTest::SetWindow(
+ NPWindow* window) {
+ if (!popup_window_test_started_) {
+ popup_window_test_started_ = true;
+ HostFunctions()->geturl(
+ id(), "popup_window_with_target_plugin.html", "_blank");
+ }
+ return PluginTest::SetWindow(window);
+}
+
+// ExecuteJavascriptPopupWindowTargetPluginTest member defines.
+ExecuteJavascriptPopupWindowTargetPluginTest::
+ ExecuteJavascriptPopupWindowTargetPluginTest(
+ NPP id, NPNetscapeFuncs* host_functions)
+ : PluginTest(id, host_functions),
+ test_completed_(false) {
+}
+
+int16 ExecuteJavascriptPopupWindowTargetPluginTest::SetWindow(
+ NPWindow* window) {
+ if (!test_completed_) {
+ HWND window_handle = reinterpret_cast<HWND>(window->window);
+
+ if (IsWindow(window_handle)) {
+ HWND parent_window = GetParent(window_handle);
+ if (!IsWindow(parent_window) || parent_window == GetDesktopWindow()) {
+ SetError("Windowed plugin instantiated with NULL parent");
+ }
+ SignalTestCompleted();
+ test_completed_ = true;
+ }
+ }
+ return PluginTest::SetWindow(window);
+}
+
+} // namespace NPAPIClient
diff --git a/webkit/glue/plugins/test/plugin_javascript_open_popup.h b/webkit/glue/plugins/test/plugin_javascript_open_popup.h
new file mode 100644
index 0000000..e2a29a8
--- /dev/null
+++ b/webkit/glue/plugins/test/plugin_javascript_open_popup.h
@@ -0,0 +1,42 @@
+// 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.
+
+#ifndef WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_JAVASCRIPT_OPEN_POPUP_H
+#define WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_JAVASCRIPT_OPEN_POPUP_H
+
+#include "webkit/glue/plugins/test/plugin_test.h"
+
+namespace NPAPIClient {
+
+// This class tests the case where a windowed plugin instance is
+// instantiated in a popup window. The plugin instance needs to
+// have a valid parent window.
+class ExecuteJavascriptOpenPopupWithPluginTest : public PluginTest {
+ public:
+ // Constructor.
+ ExecuteJavascriptOpenPopupWithPluginTest(
+ NPP id, NPNetscapeFuncs *host_functions);
+ // NPAPI SetWindow handler.
+ virtual NPError SetWindow(NPWindow* window);
+
+ private:
+ bool popup_window_test_started_;
+};
+
+// This class represents a windowed plugin instance instantiated within a
+// popup window. It verifies that the plugin instance has a valid parent.
+class ExecuteJavascriptPopupWindowTargetPluginTest : public PluginTest {
+ public:
+ ExecuteJavascriptPopupWindowTargetPluginTest(
+ NPP id, NPNetscapeFuncs *host_functions);
+ // NPAPI SetWindow handler.
+ virtual NPError SetWindow(NPWindow* window);
+
+ private:
+ bool test_completed_;
+};
+
+} // namespace NPAPIClient
+
+#endif // WEBKIT_GLUE_PLUGINS_TEST_PLUGIN_JAVASCRIPT_OPEN_POPUP_H \ No newline at end of file