diff options
-rw-r--r-- | chrome/common/resource_dispatcher.cc | 27 | ||||
-rw-r--r-- | chrome/common/resource_dispatcher.h | 4 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 26 | ||||
-rw-r--r-- | chrome/renderer/render_view.h | 11 | ||||
-rw-r--r-- | chrome/test/data/npapi/get_javascript_open_popup_with_plugin.html | 27 | ||||
-rw-r--r-- | chrome/test/data/npapi/popup_window_with_target_plugin.html | 27 | ||||
-rw-r--r-- | chrome/test/ui/npapi_uitest.cpp | 9 | ||||
-rw-r--r-- | webkit/glue/plugins/test/SConscript | 1 | ||||
-rw-r--r-- | webkit/glue/plugins/test/npapi_test_plugin.vcproj | 8 | ||||
-rw-r--r-- | webkit/glue/plugins/test/plugin_client.cc | 11 | ||||
-rw-r--r-- | webkit/glue/plugins/test/plugin_javascript_open_popup.cc | 52 | ||||
-rw-r--r-- | webkit/glue/plugins/test/plugin_javascript_open_popup.h | 42 |
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 |