diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/plugin_process_host.cc | 97 | ||||
-rw-r--r-- | chrome/browser/plugin_process_host.h | 3 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_win.cc | 98 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_win.h | 3 | ||||
-rw-r--r-- | chrome/common/plugin_messages_internal.h | 7 | ||||
-rw-r--r-- | chrome/plugin/webplugin_proxy.cc | 39 | ||||
-rw-r--r-- | chrome/plugin/webplugin_proxy.h | 4 | ||||
-rw-r--r-- | chrome/test/data/npapi/create_instance_in_paint.html | 44 | ||||
-rw-r--r-- | chrome/test/ui/npapi_test_helper.cc | 27 | ||||
-rw-r--r-- | chrome/test/ui/npapi_test_helper.h | 36 | ||||
-rw-r--r-- | chrome/test/ui/npapi_uitest.cc | 46 |
11 files changed, 188 insertions, 216 deletions
diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc index 6cea0c7..9ed3dbf 100644 --- a/chrome/browser/plugin_process_host.cc +++ b/chrome/browser/plugin_process_host.cc @@ -254,92 +254,16 @@ void PluginDownloadUrlHelper::DownloadCompletedHelper(bool success) { delete this; } - -// Sends the reply to the create window message on the IO thread. -class SendReplyTask : public Task { - public: - SendReplyTask(FilePath plugin_path, HWND window, IPC::Message* reply_msg) - : plugin_path_(plugin_path), - reply_msg_(reply_msg), - window_(window){ } - - virtual void Run() { - PluginProcessHost* plugin = - PluginService::GetInstance()->FindPluginProcess(plugin_path_); - if (!plugin) - return; - - plugin->AddWindow(window_); - plugin->Send(reply_msg_); - } - - private: - FilePath plugin_path_; - IPC::Message* reply_msg_; - HWND window_; -}; - -// Creates a child window of the given HWND on the UI thread. -class CreateWindowTask : public Task { - public: - CreateWindowTask( - FilePath plugin_path, HWND parent, IPC::Message* reply_msg) - : plugin_path_(plugin_path), parent_(parent), reply_msg_(reply_msg) { } - - virtual void Run() { - static ATOM window_class = 0; - if (!window_class) { - WNDCLASSEX wcex; - wcex.cbSize = sizeof(WNDCLASSEX); - wcex.style = CS_DBLCLKS; - wcex.lpfnWndProc = DefWindowProc; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = 0; - wcex.hInstance = GetModuleHandle(NULL); - wcex.hIcon = 0; - wcex.hCursor = 0; - wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1); - wcex.lpszMenuName = 0; - wcex.lpszClassName = kWrapperNativeWindowClassName; - wcex.hIconSm = 0; - window_class = RegisterClassEx(&wcex); - } - - HWND window = CreateWindowEx( - WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, - MAKEINTATOM(window_class), 0, - WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, - 0, 0, 0, 0, parent_, 0, GetModuleHandle(NULL), 0); - TRACK_HWND_CREATION(window); - - PluginProcessHostMsg_CreateWindow::WriteReplyParams( - reply_msg_, window); - - g_browser_process->io_thread()->message_loop()->PostTask( - FROM_HERE, new SendReplyTask(plugin_path_, window, reply_msg_)); - } - - private: - FilePath plugin_path_; - HWND parent_; - IPC::Message* reply_msg_; -}; - -void PluginProcessHost::OnCreateWindow(HWND parent, - IPC::Message* reply_msg) { - // Need to create this window on the UI thread. - PluginService::GetInstance()->main_message_loop()->PostTask( - FROM_HERE, new CreateWindowTask(info_.path, parent, reply_msg)); -} - -void PluginProcessHost::OnDestroyWindow(HWND window) { +void PluginProcessHost::OnPluginWindowDestroyed(HWND window, HWND parent) { + // The window is destroyed at this point, we just care about its parent, which + // is the intermediate window we created. std::set<HWND>::iterator window_index = - plugin_parent_windows_set_.find(window); - if (window_index != plugin_parent_windows_set_.end()) { - plugin_parent_windows_set_.erase(window_index); - } + plugin_parent_windows_set_.find(parent); + if (window_index == plugin_parent_windows_set_.end()) + return; - PostMessage(window, WM_CLOSE, 0, 0); + plugin_parent_windows_set_.erase(window_index); + PostMessage(parent, WM_CLOSE, 0, 0); } void PluginProcessHost::OnDownloadUrl(const std::string& url, @@ -499,9 +423,8 @@ void PluginProcessHost::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER_DELAY_REPLY(PluginProcessHostMsg_ResolveProxy, OnResolveProxy) #if defined(OS_WIN) - IPC_MESSAGE_HANDLER_DELAY_REPLY(PluginProcessHostMsg_CreateWindow, - OnCreateWindow) - IPC_MESSAGE_HANDLER(PluginProcessHostMsg_DestroyWindow, OnDestroyWindow) + IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginWindowDestroyed, + OnPluginWindowDestroyed) IPC_MESSAGE_HANDLER(PluginProcessHostMsg_DownloadUrl, OnDownloadUrl) #endif IPC_MESSAGE_UNHANDLED_ERROR() diff --git a/chrome/browser/plugin_process_host.h b/chrome/browser/plugin_process_host.h index c43fef2..a326bee 100644 --- a/chrome/browser/plugin_process_host.h +++ b/chrome/browser/plugin_process_host.h @@ -104,8 +104,7 @@ class PluginProcessHost : public ChildProcessHost, void OnPluginMessage(const std::vector<uint8>& data); #if defined(OS_WIN) - void OnCreateWindow(HWND parent, IPC::Message* reply_msg); - void OnDestroyWindow(HWND window); + void OnPluginWindowDestroyed(HWND window, HWND parent); void OnDownloadUrl(const std::string& url, int source_pid, gfx::NativeWindow caller_window); #endif diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc index fb243d3..1a29a99 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc @@ -11,7 +11,9 @@ #include "base/win_util.h" #include "chrome/browser/browser_accessibility.h" #include "chrome/browser/browser_accessibility_manager.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_trial.h" +#include "chrome/browser/plugin_process_host.h" #include "chrome/browser/renderer_host/backing_store.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/render_widget_host.h" @@ -116,6 +118,33 @@ static bool GetNewTextDirection(WebTextDirection* direction) { return true; } +class NotifyPluginProcessHostTask : public Task { + public: + NotifyPluginProcessHostTask(HWND window, HWND parent) + : window_(window), parent_(parent) { } + + private: + void Run() { + DWORD plugin_process_id; + GetWindowThreadProcessId(window_, &plugin_process_id); + for (ChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS); + !iter.Done(); ++iter) { + PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter); + if (plugin->GetProcessId() == plugin_process_id) { + plugin->AddWindow(parent_); + return; + } + } + + // The plugin process might have died in the time to execute the task, don't + // leak the HWND. + PostMessage(parent_, WM_CLOSE, 0, 0); + } + + HWND window_; // Plugin HWND, created and destroyed in the plugin process. + HWND parent_; // Parent HWND, created and destroyed on the browser UI thread. +}; + } // namespace // RenderWidgetHostView -------------------------------------------------------- @@ -219,6 +248,10 @@ void RenderWidgetHostViewWin::MovePluginWindows( if (plugin_window_moves.empty()) return; + bool oop_plugins = + !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) && + !CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessPlugins); + HDWP defer_window_pos_info = ::BeginDeferWindowPos(static_cast<int>(plugin_window_moves.size())); @@ -230,18 +263,36 @@ void RenderWidgetHostViewWin::MovePluginWindows( for (size_t i = 0; i < plugin_window_moves.size(); ++i) { unsigned long flags = 0; const WebPluginGeometry& move = plugin_window_moves[i]; + HWND window = move.window; // As the plugin parent window which lives on the browser UI thread is // destroyed asynchronously, it is possible that we have a stale window // sent in by the renderer for moving around. - if (!::IsWindow(move.window)) + // Note: get the parent before checking if the window is valid, to avoid a + // race condition where the window is destroyed after the check but before + // the GetParent call. + HWND parent = ::GetParent(window); + if (!::IsWindow(window)) continue; - // The renderer should only be trying to move windows that are children - // of its render widget window. - if (::IsChild(m_hWnd, move.window) == 0) { - NOTREACHED(); - continue; + if (oop_plugins) { + if (parent == m_hWnd) { + // The plugin window is a direct child of this window, add an + // intermediate window that lives on this thread to speed up scrolling. + // Note this only works with out of process plugins since we depend on + // PluginProcessHost to destroy the intermediate HWNDs. + parent = ReparentWindow(window); + ::ShowWindow(window, SW_SHOW); // Window was created hidden. + } else if (::GetParent(parent) != m_hWnd) { + // The renderer should only be trying to move windows that are children + // of its render widget window. + NOTREACHED(); + continue; + } + + // We move the intermediate parent window which doesn't result in cross- + // process synchronous Windows messages. + window = parent; } if (move.visible) @@ -257,10 +308,10 @@ void RenderWidgetHostViewWin::MovePluginWindows( // Note: System will own the hrgn after we call SetWindowRgn, // so we don't need to call DeleteObject(hrgn) - ::SetWindowRgn(move.window, hrgn, !move.clip_rect.IsEmpty()); + ::SetWindowRgn(window, hrgn, !move.clip_rect.IsEmpty()); defer_window_pos_info = ::DeferWindowPos(defer_window_pos_info, - move.window, NULL, + window, NULL, move.window_rect.x(), move.window_rect.y(), move.window_rect.width(), @@ -274,6 +325,37 @@ void RenderWidgetHostViewWin::MovePluginWindows( ::EndDeferWindowPos(defer_window_pos_info); } +HWND RenderWidgetHostViewWin::ReparentWindow(HWND window) { + static ATOM window_class = 0; + if (!window_class) { + WNDCLASSEX wcex; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.style = CS_DBLCLKS; + wcex.lpfnWndProc = ::DefWindowProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = GetModuleHandle(NULL); + wcex.hIcon = 0; + wcex.hCursor = 0; + wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1); + wcex.lpszMenuName = 0; + wcex.lpszClassName = kWrapperNativeWindowClassName; + wcex.hIconSm = 0; + window_class = RegisterClassEx(&wcex); + } + + HWND parent = CreateWindowEx( + WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, + MAKEINTATOM(window_class), 0, + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + 0, 0, 0, 0, ::GetParent(window), 0, GetModuleHandle(NULL), 0); + DCHECK(parent); + ::SetParent(window, parent); + g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, + new NotifyPluginProcessHostTask(window, parent)); + return parent; +} + void RenderWidgetHostViewWin::Focus() { if (IsWindow()) SetFocus(); diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.h b/chrome/browser/renderer_host/render_widget_host_view_win.h index 893e129..3501ca1 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.h +++ b/chrome/browser/renderer_host/render_widget_host_view_win.h @@ -210,6 +210,9 @@ class RenderWidgetHostViewWin : // given paint rect. void DrawResizeCorner(const gfx::Rect& paint_rect, HDC dc); + // Create an intermediate window between the given HWND and its parent. + HWND ReparentWindow(HWND window); + // The associated Model. RenderWidgetHost* render_widget_host_; diff --git a/chrome/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h index 11a0365..54839fb 100644 --- a/chrome/common/plugin_messages_internal.h +++ b/chrome/common/plugin_messages_internal.h @@ -78,9 +78,10 @@ IPC_BEGIN_MESSAGES(PluginProcessHost) HWND /* parent */, HWND /* child */) - // Destroys the given window on the UI thread. - IPC_MESSAGE_CONTROL1(PluginProcessHostMsg_DestroyWindow, - HWND /* window */) + // Destroys the given window's parent on the UI thread. + IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_PluginWindowDestroyed, + HWND /* window */, + HWND /* parent */) IPC_MESSAGE_ROUTED3(PluginProcessHostMsg_DownloadUrl, std::string /* URL */, diff --git a/chrome/plugin/webplugin_proxy.cc b/chrome/plugin/webplugin_proxy.cc index 7933082..6a827ce 100644 --- a/chrome/plugin/webplugin_proxy.cc +++ b/chrome/plugin/webplugin_proxy.cc @@ -38,49 +38,28 @@ WebPluginProxy::WebPluginProxy( delegate_(delegate), waiting_for_paint_(false), #pragma warning(suppress: 4355) // can use this - runnable_method_factory_(this), - parent_window_(NULL) { + runnable_method_factory_(this) { } WebPluginProxy::~WebPluginProxy() { if (cp_browsing_context_) GetContextMap().erase(cp_browsing_context_); - - if (parent_window_) { - PluginThread::current()->Send( - new PluginProcessHostMsg_DestroyWindow(parent_window_)); - } } bool WebPluginProxy::Send(IPC::Message* msg) { return channel_->Send(msg); } -bool WebPluginProxy::SetWindow(gfx::NativeView window) { - if (window) { - // To make scrolling windowed plugins fast, we create the page's direct - // child windows in the browser process. This way no cross process messages - // are sent. - HWND old_parent = GetParent(window); - IPC::SyncMessage* msg = new PluginProcessHostMsg_CreateWindow( - old_parent, &parent_window_); - - // Need to process window messages in the meantime to avoid a deadlock if - // the browser paints or sends any other (synchronous) WM_ message to the - // plugin window. - msg->EnableMessagePumping(); - PluginThread::current()->Send(msg); - - SetParent(window, parent_window_); - - // We want the browser process to move this window which has a message loop - // in its process. - window = parent_window_; - } - +void WebPluginProxy::SetWindow(gfx::NativeView window) { Send(new PluginHostMsg_SetWindow(route_id_, gfx::IdFromNativeView(window))); +} - return false; +void WebPluginProxy::WillDestroyWindow(gfx::NativeView window) { +#if defined(OS_WIN) + PluginThread::current()->Send( + new PluginProcessHostMsg_PluginWindowDestroyed( + window, ::GetParent(window))); +#endif } #if defined(OS_WIN) diff --git a/chrome/plugin/webplugin_proxy.h b/chrome/plugin/webplugin_proxy.h index 8c4629d..ea2c124 100644 --- a/chrome/plugin/webplugin_proxy.h +++ b/chrome/plugin/webplugin_proxy.h @@ -34,7 +34,8 @@ class WebPluginProxy : public WebPlugin { ~WebPluginProxy(); // WebPlugin overrides - bool SetWindow(gfx::NativeView window); + void SetWindow(gfx::NativeView window); + void WillDestroyWindow(gfx::NativeView window); #if defined(OS_WIN) void SetWindowlessPumpEvent(HANDLE pump_messages_event); void SetModalDialogEvent(HANDLE modal_dialog_event); @@ -136,7 +137,6 @@ class WebPluginProxy : public WebPlugin { bool waiting_for_paint_; uint32 cp_browsing_context_; scoped_ptr<base::WaitableEvent> modal_dialog_event_; - HWND parent_window_; // Variables used for desynchronized windowless plugin painting. See note in // webplugin_delegate_proxy.h for how this works. diff --git a/chrome/test/data/npapi/create_instance_in_paint.html b/chrome/test/data/npapi/create_instance_in_paint.html new file mode 100644 index 0000000..80e8935 --- /dev/null +++ b/chrome/test/data/npapi/create_instance_in_paint.html @@ -0,0 +1,44 @@ +<html> + +<head> +<script src="npapi.js"></script> +</head> + +<body> +<div id="statusPanel" style="border: 1px solid red; width: 100%"> +Test running.... +</div> + + +Plugin Instance In Paint Test<p> + +Tests that there's no deadlock when a plugin instance is created while handling a paint message. + +<DIV ID="PluginDiv"> +<embed type="application/vnd.npapi-test" + src="foo" + name="create_instance_in_paint" + id="1" + mode="np_embed" +> +</DIV> + +<DIV id="PluginDiv2"></DIV> + +<script> +var height = document.body.offsetHeight; + + +function CreateNewInstance() { + var obj = document.createElement('embed');
+ obj.setAttribute('type', 'application/vnd.npapi-test');
+ obj.setAttribute('src', 'bar');
+ obj.setAttribute('name', 'create_instance_in_paint');
+ obj.setAttribute('id', '2'); + obj.setAttribute('mode', 'np_embed'); + document.getElementById("PluginDiv2").appendChild(obj); +} +</script> + +</body> +</html> diff --git a/chrome/test/ui/npapi_test_helper.cc b/chrome/test/ui/npapi_test_helper.cc index 859d3df..ab891f6 100644 --- a/chrome/test/ui/npapi_test_helper.cc +++ b/chrome/test/ui/npapi_test_helper.cc @@ -4,30 +4,9 @@ // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// NPAPI test helper classes. +// Copyright (c) 2009 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/test/ui/npapi_test_helper.h" diff --git a/chrome/test/ui/npapi_test_helper.h b/chrome/test/ui/npapi_test_helper.h index 7b79e0e..6af2d73 100644 --- a/chrome/test/ui/npapi_test_helper.h +++ b/chrome/test/ui/npapi_test_helper.h @@ -1,31 +1,9 @@ -// Copyright 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Copyright (c) 2009 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 CHROME_TEST_HELPER_H_ +#define CHROME_TEST_HELPER_H_ #include "chrome/test/ui/ui_test.h" @@ -52,3 +30,5 @@ class NPAPIIncognitoTester : public NPAPITester { protected: virtual void SetUp(); }; + +#endif // CHROME_TEST_HELPER_H_ diff --git a/chrome/test/ui/npapi_uitest.cc b/chrome/test/ui/npapi_uitest.cc index 7826878..3a8905a 100644 --- a/chrome/test/ui/npapi_uitest.cc +++ b/chrome/test/ui/npapi_uitest.cc @@ -1,35 +1,6 @@ -// Copyright 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// -// NPAPI UnitTests. -// +// Copyright (c) 2009 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. // windows headers #include <windows.h> @@ -220,6 +191,17 @@ TEST_F(NPAPIVisiblePluginTester, VerifyPluginWindowRect) { kTestCompleteSuccess, kShortWaitTimeout); } +// Tests that creating a new instance of a plugin while another one is handling +// a paint message doesn't cause deadlock. +TEST_F(NPAPIVisiblePluginTester, CreateInstanceInPaint) { + show_window_ = true; + std::wstring test_case = L"create_instance_in_paint.html"; + GURL url = GetTestUrl(L"npapi", test_case); + NavigateToURL(url); + WaitForFinish("create_instance_in_paint", "2", url, kTestCompleteCookie, + kTestCompleteSuccess, kShortWaitTimeout); +} + TEST_F(NPAPIVisiblePluginTester, VerifyNPObjectLifetimeTest) { if (!UITest::in_process_renderer()) { show_window_ = true; |