diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-21 21:48:36 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-21 21:48:36 +0000 |
commit | 875d489e8aadd251c638c1bad6bb7ca967605f98 (patch) | |
tree | e1be54c561d33b240f6c88b042c9b2df732ac5c6 /chrome | |
parent | e3db4fabfc7aabca3cd1998e05d2a769fbd0c5b6 (diff) | |
download | chromium_src-875d489e8aadd251c638c1bad6bb7ca967605f98.zip chromium_src-875d489e8aadd251c638c1bad6bb7ca967605f98.tar.gz chromium_src-875d489e8aadd251c638c1bad6bb7ca967605f98.tar.bz2 |
Fix hang seen in plugin process because plugin creation ended up having to wait on UI thread. Instead of using sync messages, the plugin hwnd is initially parented to the RenderWidgetHost's HWND. It's then lazily reparented to an intermediate HWND on the UI thread when it comes time to move it.
BUG=10711
TEST=added regression tests, but testers please confirm plugins on top video sites are placed correctly.
Review URL: http://codereview.chromium.org/67285
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14137 0039d316-1c4b-4281-b951-d872f2087c98
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; |