summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordeanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-24 21:16:42 +0000
committerdeanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-24 21:16:42 +0000
commit1692ea885338dd799ae9f47151d2a7fd4d1b10c4 (patch)
treea262a1e095318a2ea796f55507275b1bd2dffb13
parent616dab5a62842c3d98b65620ad986fd485e54eec (diff)
downloadchromium_src-1692ea885338dd799ae9f47151d2a7fd4d1b10c4.zip
chromium_src-1692ea885338dd799ae9f47151d2a7fd4d1b10c4.tar.gz
chromium_src-1692ea885338dd799ae9f47151d2a7fd4d1b10c4.tar.bz2
Attempt to fix a IAT unpatch crash.
The IAT destructor (which will unpatch) now should run at AtExitManager shutdown, which is before we return from main(). It was a static constructor (bad), which registers an atexit() destructor which happens sometime during ExitProcess / LdrShutdown. Also this removes some static constructors (the iat patchers, the throttle_queue, etc). I removed a StatsCounter completely, removing its static initializer. BUG=6886 Review URL: http://codereview.chromium.org/18712 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8613 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.cc104
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.h12
2 files changed, 58 insertions, 58 deletions
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.cc b/webkit/glue/plugins/webplugin_delegate_impl.cc
index 3abcbd6..12333ae 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl.cc
+++ b/webkit/glue/plugins/webplugin_delegate_impl.cc
@@ -8,6 +8,8 @@
#include <vector>
#include "base/file_util.h"
+#include "base/iat_patch.h"
+#include "base/lazy_instance.h"
#include "base/message_loop.h"
#include "base/stats_counters.h"
#include "base/string_util.h"
@@ -21,14 +23,13 @@
#include "webkit/glue/plugins/plugin_stream_url.h"
#include "webkit/glue/webkit_glue.h"
-static StatsCounter windowless_queue("Plugin.ThrottleQueue");
+namespace {
-static const wchar_t kWebPluginDelegateProperty[] =
- L"WebPluginDelegateProperty";
-static const wchar_t kPluginNameAtomProperty[] = L"PluginNameAtom";
-static const wchar_t kDummyActivationWindowName[] = L"DummyWindowForActivation";
-static const wchar_t kPluginOrigProc[] = L"OriginalPtr";
-static const wchar_t kPluginFlashThrottle[] = L"FlashThrottle";
+const wchar_t kWebPluginDelegateProperty[] = L"WebPluginDelegateProperty";
+const wchar_t kPluginNameAtomProperty[] = L"PluginNameAtom";
+const wchar_t kDummyActivationWindowName[] = L"DummyWindowForActivation";
+const wchar_t kPluginOrigProc[] = L"OriginalPtr";
+const wchar_t kPluginFlashThrottle[] = L"FlashThrottle";
// The fastest we are willing to process WM_USER+1 events for Flash.
// Flash can easily exceed the limits of our CPU if we don't throttle it.
@@ -39,14 +40,22 @@ static const wchar_t kPluginFlashThrottle[] = L"FlashThrottle";
// time currently required to paint Flash plugins. There isn't a good
// way to count the time spent in aggregate plugin painting, however, so
// this seems to work well enough.
-static const int kFlashWMUSERMessageThrottleDelayMs = 5;
+const int kFlashWMUSERMessageThrottleDelayMs = 5;
-std::list<MSG> WebPluginDelegateImpl::throttle_queue_;
+// The current instance of the plugin which entered the modal loop.
+WebPluginDelegateImpl* g_current_plugin_instance = NULL;
-WebPluginDelegateImpl* WebPluginDelegateImpl::current_plugin_instance_ = NULL;
+base::LazyInstance<std::list<MSG> > g_throttle_queue(base::LINKER_INITIALIZED);
-iat_patch::IATPatchFunction WebPluginDelegateImpl::iat_patch_track_popup_menu_;
-iat_patch::IATPatchFunction WebPluginDelegateImpl::iat_patch_set_cursor_;
+// Helper object for patching the TrackPopupMenu API.
+base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_track_popup_menu(
+ base::LINKER_INITIALIZED);
+
+// Helper object for patching the SetCursor API.
+base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_set_cursor(
+ base::LINKER_INITIALIZED);
+
+} // namespace
WebPluginDelegateImpl* WebPluginDelegateImpl::Create(
const FilePath& filename,
@@ -112,8 +121,8 @@ bool WebPluginDelegateImpl::IsDummyActivationWindow(HWND window) {
LRESULT CALLBACK WebPluginDelegateImpl::HandleEventMessageFilterHook(
int code, WPARAM wParam, LPARAM lParam) {
- DCHECK(current_plugin_instance_);
- current_plugin_instance_->OnModalLoopEntered();
+ DCHECK(g_current_plugin_instance);
+ g_current_plugin_instance->OnModalLoopEntered();
return CallNextHookEx(NULL, code, wParam, lParam);
}
@@ -261,9 +270,9 @@ bool WebPluginDelegateImpl::Initialize(const GURL& url,
// lives on the browser thread. Our workaround is to intercept the
// TrackPopupMenu API for Silverlight and replace the window handle
// with the dummy activation window.
- if (windowless_ && !iat_patch_track_popup_menu_.is_patched() &&
+ if (windowless_ && !g_iat_patch_track_popup_menu.Pointer()->is_patched() &&
(quirks_ & PLUGIN_QUIRK_PATCH_TRACKPOPUP_MENU)) {
- iat_patch_track_popup_menu_.Patch(
+ g_iat_patch_track_popup_menu.Pointer()->Patch(
plugin_module_handle_, "user32.dll", "TrackPopupMenu",
WebPluginDelegateImpl::TrackPopupMenuPatch);
}
@@ -274,11 +283,11 @@ bool WebPluginDelegateImpl::Initialize(const GURL& url,
// and remember the cursor being set. This is shipped over to the browser
// in the HandleEvent call, which ensures that the cursor does not change
// when a windowless plugin instance changes the cursor in a background tab.
- if (windowless_ && !iat_patch_set_cursor_.is_patched() &&
+ if (windowless_ && !g_iat_patch_set_cursor.Pointer()->is_patched() &&
(quirks_ & PLUGIN_QUIRK_PATCH_SETCURSOR)) {
- iat_patch_set_cursor_.Patch(plugin_module_handle_, "user32.dll",
- "SetCursor",
- WebPluginDelegateImpl::SetCursorPatch);
+ g_iat_patch_set_cursor.Pointer()->Patch(
+ plugin_module_handle_, "user32.dll", "SetCursor",
+ WebPluginDelegateImpl::SetCursorPatch);
}
return true;
}
@@ -303,12 +312,12 @@ void WebPluginDelegateImpl::DestroyInstance() {
if (instance_->plugin_lib()) {
// Unpatch if this is the last plugin instance.
if (instance_->plugin_lib()->instance_count() == 1) {
- if (iat_patch_set_cursor_.is_patched()) {
- iat_patch_set_cursor_.Unpatch();
+ if (g_iat_patch_set_cursor.Pointer()->is_patched()) {
+ g_iat_patch_set_cursor.Pointer()->Unpatch();
}
- if (iat_patch_track_popup_menu_.is_patched()) {
- iat_patch_track_popup_menu_.Unpatch();
+ if (g_iat_patch_track_popup_menu.Pointer()->is_patched()) {
+ g_iat_patch_track_popup_menu.Pointer()->Unpatch();
}
}
}
@@ -504,11 +513,12 @@ void WebPluginDelegateImpl::WindowedDestroyWindow() {
// the queue.
// static
void WebPluginDelegateImpl::ClearThrottleQueueForWindow(HWND window) {
+ std::list<MSG>* throttle_queue = g_throttle_queue.Pointer();
+
std::list<MSG>::iterator it;
- for (it = throttle_queue_.begin(); it != throttle_queue_.end(); ) {
+ for (it = throttle_queue->begin(); it != throttle_queue->end(); ) {
if (it->hwnd == window) {
- it = throttle_queue_.erase(it);
- windowless_queue.Decrement();
+ it = throttle_queue->erase(it);
} else {
it++;
}
@@ -523,10 +533,11 @@ void WebPluginDelegateImpl::OnThrottleMessage() {
// message it finds for each plugin. It is important to service
// all active plugins with each pass through the throttle, otherwise
// we see video jankiness.
+ std::list<MSG>* throttle_queue = g_throttle_queue.Pointer();
std::map<HWND, int> processed;
- std::list<MSG>::iterator it = throttle_queue_.begin();
- while (it != throttle_queue_.end()) {
+ std::list<MSG>::iterator it = throttle_queue->begin();
+ while (it != throttle_queue->end()) {
const MSG& msg = *it;
if (processed.find(msg.hwnd) == processed.end()) {
WNDPROC proc = reinterpret_cast<WNDPROC>(msg.time);
@@ -536,14 +547,13 @@ void WebPluginDelegateImpl::OnThrottleMessage() {
if (IsWindow(msg.hwnd))
CallWindowProc(proc, msg.hwnd, msg.message, msg.wParam, msg.lParam);
processed[msg.hwnd] = 1;
- it = throttle_queue_.erase(it);
- windowless_queue.Decrement();
+ it = throttle_queue->erase(it);
} else {
it++;
}
}
- if (throttle_queue_.size() > 0)
+ if (throttle_queue->size() > 0)
MessageLoop::current()->PostDelayedTask(FROM_HERE,
NewRunnableFunction(&WebPluginDelegateImpl::OnThrottleMessage),
kFlashWMUSERMessageThrottleDelayMs);
@@ -560,10 +570,12 @@ void WebPluginDelegateImpl::ThrottleMessage(WNDPROC proc, HWND hwnd,
msg.message = message;
msg.wParam = wParam;
msg.lParam = lParam;
- throttle_queue_.push_back(msg);
- windowless_queue.Increment();
- if (throttle_queue_.size() == 1) {
+ std::list<MSG>* throttle_queue = g_throttle_queue.Pointer();
+
+ throttle_queue->push_back(msg);
+
+ if (throttle_queue->size() == 1) {
MessageLoop::current()->PostDelayedTask(FROM_HERE,
NewRunnableFunction(&WebPluginDelegateImpl::OnThrottleMessage),
kFlashWMUSERMessageThrottleDelayMs);
@@ -815,7 +827,7 @@ LRESULT CALLBACK WebPluginDelegateImpl::NativeWndProc(
return FALSE;
}
- current_plugin_instance_ = delegate;
+ g_current_plugin_instance = delegate;
switch (message) {
case WM_NCDESTROY: {
@@ -834,7 +846,7 @@ LRESULT CALLBACK WebPluginDelegateImpl::NativeWndProc(
if (delegate->quirks() & PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE) {
WebPluginDelegateImpl::ThrottleMessage(delegate->plugin_wnd_proc_, hwnd,
message, wparam, lparam);
- current_plugin_instance_ = NULL;
+ g_current_plugin_instance = NULL;
return FALSE;
}
break;
@@ -861,7 +873,7 @@ LRESULT CALLBACK WebPluginDelegateImpl::NativeWndProc(
LRESULT result = CallWindowProc(delegate->plugin_wnd_proc_, hwnd, message,
wparam, lparam);
delegate->is_calling_wndproc = false;
- current_plugin_instance_ = NULL;
+ g_current_plugin_instance = NULL;
return result;
}
@@ -1003,7 +1015,7 @@ bool WebPluginDelegateImpl::HandleEvent(NPEvent* event,
bool old_task_reentrancy_state =
MessageLoop::current()->NestableTasksAllowed();
- current_plugin_instance_ = this;
+ g_current_plugin_instance = this;
handle_event_depth_++;
@@ -1029,7 +1041,7 @@ bool WebPluginDelegateImpl::HandleEvent(NPEvent* event,
handle_event_depth_--;
- current_plugin_instance_ = NULL;
+ g_current_plugin_instance = NULL;
MessageLoop::current()->SetNestableTasksAllowed(old_task_reentrancy_state);
@@ -1125,14 +1137,14 @@ void WebPluginDelegateImpl::OnUserGestureEnd() {
BOOL WINAPI WebPluginDelegateImpl::TrackPopupMenuPatch(
HMENU menu, unsigned int flags, int x, int y, int reserved,
HWND window, const RECT* rect) {
- if (current_plugin_instance_) {
+ if (g_current_plugin_instance) {
unsigned long window_process_id = 0;
unsigned long window_thread_id =
GetWindowThreadProcessId(window, &window_process_id);
// TrackPopupMenu fails if the window passed in belongs to a different
// thread.
if (::GetCurrentThreadId() != window_thread_id) {
- window = current_plugin_instance_->dummy_window_for_activation_;
+ window = g_current_plugin_instance->dummy_window_for_activation_;
}
}
return TrackPopupMenu(menu, flags, x, y, reserved, window, rect);
@@ -1143,19 +1155,19 @@ HCURSOR WINAPI WebPluginDelegateImpl::SetCursorPatch(HCURSOR cursor) {
// instantiated on the plugin thread. This causes annoying cursor flicker
// when the mouse is moved on a foreground tab, with a windowless plugin
// instance in a background tab. We just ignore the call here.
- if (!current_plugin_instance_)
+ if (!g_current_plugin_instance)
return GetCursor();
- if (!current_plugin_instance_->windowless()) {
+ if (!g_current_plugin_instance->windowless()) {
return SetCursor(cursor);
}
// It is ok to pass NULL here to GetCursor as we are not looking for cursor
// types defined by Webkit.
HCURSOR previous_cursor =
- current_plugin_instance_->current_windowless_cursor_.GetCursor(NULL);
+ g_current_plugin_instance->current_windowless_cursor_.GetCursor(NULL);
- current_plugin_instance_->current_windowless_cursor_.InitFromExternalCursor(
+ g_current_plugin_instance->current_windowless_cursor_.InitFromExternalCursor(
cursor);
return previous_cursor;
}
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h
index d01046c..fcb849d 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl.h
+++ b/webkit/glue/plugins/webplugin_delegate_impl.h
@@ -10,7 +10,6 @@
#include "base/file_path.h"
#include "base/gfx/native_widget_types.h"
-#include "base/iat_patch.h"
#include "base/ref_counted.h"
#include "base/task.h"
#include "third_party/npapi/bindings/npapi.h"
@@ -203,8 +202,6 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
HWND dummy_window_for_activation_;
bool CreateDummyWindowForActivation();
- static std::list<MSG> throttle_queue_;
-
// Returns true if the event passed in needs to be tracked for a potential
// modal loop.
static bool ShouldTrackEventForModalLoops(NPEvent* event);
@@ -226,9 +223,6 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// Handle to the message filter hook
HHOOK handle_event_message_filter_hook_;
- // The current instance of the plugin which entered the modal loop.
- static WebPluginDelegateImpl* current_plugin_instance_;
-
// Event which is set when the plugin enters a modal loop in the course
// of a NPP_HandleEvent call.
HANDLE handle_event_pump_messages_event_;
@@ -249,9 +243,6 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// The plugin module handle.
HMODULE plugin_module_handle_;
- // Helper object for patching the TrackPopupMenu API
- static iat_patch::IATPatchFunction iat_patch_track_popup_menu_;
-
// TrackPopupMenu interceptor. Parameters are the same as the Win32 function
// TrackPopupMenu.
static BOOL WINAPI TrackPopupMenuPatch(HMENU menu, unsigned int flags, int x,
@@ -261,9 +252,6 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// SetCursor interceptor for windowless plugins.
static HCURSOR WINAPI SetCursorPatch(HCURSOR cursor);
- // Helper object for patching the SetCursor API
- static iat_patch::IATPatchFunction iat_patch_set_cursor_;
-
// Holds the current cursor set by the windowless plugin.
WebCursor current_windowless_cursor_;