summaryrefslogtreecommitdiffstats
path: root/views
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-01 16:57:13 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-01 16:57:13 +0000
commit7c9d829192359328576965fe8a4a52a5ad6c7da3 (patch)
tree6f06ef0a1bd4f797ad2c9f2968950b625867136c /views
parent9d3fcf8bc99dfdfef66b983af69802ddbe76514d (diff)
downloadchromium_src-7c9d829192359328576965fe8a4a52a5ad6c7da3.zip
chromium_src-7c9d829192359328576965fe8a4a52a5ad6c7da3.tar.gz
chromium_src-7c9d829192359328576965fe8a4a52a5ad6c7da3.tar.bz2
Attempt at fixing leaks from SetProp. Apparently there is a finite
amount of memory reserved for properties and Windows doesn't always automatically free up the memory if the window is deleted without an explicit remove. For the time being I've made it easier to track SetProp leaks, but we may want to move to using something other than SetProp in the future that isn't as fragile. I didn't fix a couple of places that were trickier. I'm going to file separate bugs on them. BUG=44991 TEST=none Review URL: http://codereview.chromium.org/4195003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64619 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r--views/controls/menu/native_menu_win.cc12
-rw-r--r--views/controls/native_control.cc45
-rw-r--r--views/controls/native_control.h3
-rw-r--r--views/controls/native_control_win.cc6
-rw-r--r--views/controls/native_control_win.h9
-rw-r--r--views/focus/focus_util_win.cc7
-rw-r--r--views/focus/focus_util_win.h11
-rw-r--r--views/widget/widget_win.cc28
-rw-r--r--views/widget/widget_win.h15
9 files changed, 87 insertions, 49 deletions
diff --git a/views/controls/menu/native_menu_win.cc b/views/controls/menu/native_menu_win.cc
index 6236913..9993d4e 100644
--- a/views/controls/menu/native_menu_win.cc
+++ b/views/controls/menu/native_menu_win.cc
@@ -9,6 +9,7 @@
#include "app/l10n_util_win.h"
#include "base/logging.h"
#include "base/stl_util-inl.h"
+#include "base/win_util.h"
#include "gfx/canvas_skia.h"
#include "gfx/font.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -55,18 +56,16 @@ class NativeMenuWin::MenuHostWindow {
RegisterClass();
hwnd_ = CreateWindowEx(l10n_util::GetExtendedStyles(), kWindowClassName,
L"", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
- SetProp(hwnd_, kMenuHostWindowKey, this);
+ win_util::SetWindowUserData(hwnd_, this);
}
~MenuHostWindow() {
- RemoveProp(hwnd_, kMenuHostWindowKey);
DestroyWindow(hwnd_);
}
HWND hwnd() const { return hwnd_; }
private:
- static const wchar_t* kMenuHostWindowKey;
static const wchar_t* kWindowClassName;
void RegisterClass() {
@@ -276,7 +275,8 @@ class NativeMenuWin::MenuHostWindow {
WPARAM w_param,
LPARAM l_param) {
MenuHostWindow* host =
- reinterpret_cast<MenuHostWindow*>(GetProp(window, kMenuHostWindowKey));
+ reinterpret_cast<MenuHostWindow*>(win_util::GetWindowUserData(window));
+ // host is null during initial construction.
LRESULT l_result = 0;
if (!host || !host->ProcessWindowMessage(window, message, w_param, l_param,
&l_result)) {
@@ -294,10 +294,6 @@ class NativeMenuWin::MenuHostWindow {
const wchar_t* NativeMenuWin::MenuHostWindow::kWindowClassName =
L"ViewsMenuHostWindow";
-const wchar_t* NativeMenuWin::MenuHostWindow::kMenuHostWindowKey =
- L"__MENU_HOST_WINDOW__";
-
-
////////////////////////////////////////////////////////////////////////////////
// NativeMenuWin, public:
diff --git a/views/controls/native_control.cc b/views/controls/native_control.cc
index a0ff1b0..ef719c9 100644
--- a/views/controls/native_control.cc
+++ b/views/controls/native_control.cc
@@ -13,7 +13,9 @@
#include "app/keyboard_code_conversion_win.h"
#include "app/keyboard_codes.h"
#include "app/l10n_util_win.h"
+#include "app/win/scoped_prop.h"
#include "base/logging.h"
+#include "base/scoped_ptr.h"
#include "base/win_util.h"
#include "gfx/native_theme_win.h"
#include "views/background.h"
@@ -24,11 +26,6 @@
namespace views {
-// Maps to the original WNDPROC for the controller window before we subclassed
-// it.
-static const wchar_t* const kHandlerKey =
- L"__CONTROL_ORIGINAL_MESSAGE_HANDLER__";
-
// Maps to the NativeControl.
static const wchar_t* const kNativeControlKey = L"__NATIVE_CONTROL__";
@@ -37,10 +34,14 @@ class NativeControlContainer : public CWindowImpl<NativeControlContainer,
CWinTraits<WS_CHILD | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN>> {
public:
+ explicit NativeControlContainer(NativeControl* parent)
+ : parent_(parent),
+ control_(NULL),
+ original_handler_(NULL) {
+ }
- explicit NativeControlContainer(NativeControl* parent) : parent_(parent),
- control_(NULL) {
- Create(parent->GetWidget()->GetNativeView());
+ void Init() {
+ Create(parent_->GetWidget()->GetNativeView());
::ShowWindow(m_hWnd, SW_SHOW);
}
@@ -78,17 +79,18 @@ class NativeControlContainer : public CWindowImpl<NativeControlContainer,
parent_->NativeControlDestroyed();
delete this;
}
+
private:
+ friend class NativeControl;
LRESULT OnCreate(LPCREATESTRUCT create_struct) {
control_ = parent_->CreateNativeControl(m_hWnd);
// We subclass the control hwnd so we get the WM_KEYDOWN messages.
- WNDPROC original_handler =
- win_util::SetWindowProc(control_,
- &NativeControl::NativeControlWndProc);
- SetProp(control_, kHandlerKey, original_handler);
- SetProp(control_, kNativeControlKey , parent_);
+ original_handler_ = win_util::SetWindowProc(
+ control_, &NativeControl::NativeControlWndProc);
+ prop_.reset(
+ new app::win::ScopedProp(control_, kNativeControlKey , parent_));
::ShowWindow(control_, SW_SHOW);
return 1;
@@ -160,6 +162,12 @@ class NativeControlContainer : public CWindowImpl<NativeControlContainer,
NativeControl* parent_;
HWND control_;
+
+ // Message handler that was set before we reset it.
+ WNDPROC original_handler_;
+
+ scoped_ptr<app::win::ScopedProp> prop_;
+
DISALLOW_COPY_AND_ASSIGN(NativeControlContainer);
};
@@ -188,6 +196,7 @@ void NativeControl::ValidateNativeControl() {
if (!container_ && IsVisible()) {
container_ = new NativeControlContainer(this);
+ container_->Init();
hwnd_view_->Attach(*container_);
if (!enabled_)
EnableWindow(GetNativeControlHWND(), enabled_);
@@ -350,14 +359,15 @@ DWORD NativeControl::GetAdditionalRTLStyle() const {
}
// static
-LRESULT CALLBACK NativeControl::NativeControlWndProc(HWND window, UINT message,
+LRESULT CALLBACK NativeControl::NativeControlWndProc(HWND window,
+ UINT message,
WPARAM w_param,
LPARAM l_param) {
- HANDLE original_handler = GetProp(window, kHandlerKey);
- DCHECK(original_handler);
NativeControl* native_control =
static_cast<NativeControl*>(GetProp(window, kNativeControlKey));
DCHECK(native_control);
+ WNDPROC original_handler = native_control->container_->original_handler_;
+ DCHECK(original_handler);
if (message == WM_KEYDOWN &&
native_control->OnKeyDown(app::KeyboardCodeForWindowsKeyCode(w_param))) {
@@ -373,8 +383,7 @@ LRESULT CALLBACK NativeControl::NativeControlWndProc(HWND window, UINT message,
} else if (message == WM_DESTROY) {
win_util::SetWindowProc(window,
reinterpret_cast<WNDPROC>(original_handler));
- RemoveProp(window, kHandlerKey);
- RemoveProp(window, kNativeControlKey);
+ native_control->container_->prop_.reset();
}
return CallWindowProc(reinterpret_cast<WNDPROC>(original_handler), window,
diff --git a/views/controls/native_control.h b/views/controls/native_control.h
index 5a180d2..75a2a49 100644
--- a/views/controls/native_control.h
+++ b/views/controls/native_control.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -42,6 +42,7 @@ class NativeControl : public View {
// Overridden to do nothing.
virtual void Paint(gfx::Canvas* canvas);
+
protected:
friend class NativeControlContainer;
diff --git a/views/controls/native_control_win.cc b/views/controls/native_control_win.cc
index ba27f85..0c6d257 100644
--- a/views/controls/native_control_win.cc
+++ b/views/controls/native_control_win.cc
@@ -7,6 +7,7 @@
#include <windowsx.h>
#include "app/l10n_util_win.h"
+#include "app/win/scoped_prop.h"
#include "base/logging.h"
#include "base/win_util.h"
#include "views/focus/focus_manager.h"
@@ -129,8 +130,8 @@ void NativeControlWin::ShowContextMenu(const gfx::Point& location) {
void NativeControlWin::NativeControlCreated(HWND native_control) {
// Associate this object with the control's HWND so that WidgetWin can find
// this object when it receives messages from it.
- // Note that we never unset this property. We don't have to.
- SetProp(native_control, kNativeControlWinKey, this);
+ prop_.reset(
+ new app::win::ScopedProp(native_control, kNativeControlWinKey, this));
// Subclass so we get WM_KEYDOWN and WM_SETFOCUS messages.
original_wndproc_ =
@@ -210,6 +211,7 @@ LRESULT NativeControlWin::NativeControlWndProc(HWND window,
NOTREACHED();
}
} else if (message == WM_DESTROY) {
+ native_control->prop_.reset();
win_util::SetWindowProc(window, native_control->original_wndproc_);
}
diff --git a/views/controls/native_control_win.h b/views/controls/native_control_win.h
index 1b0273b..6d0fdf0 100644
--- a/views/controls/native_control_win.h
+++ b/views/controls/native_control_win.h
@@ -6,9 +6,16 @@
#define VIEWS_CONTROLS_NATIVE_CONTROL_WIN_H_
#pragma once
+#include "base/scoped_ptr.h"
#include "views/controls/combobox/combobox.h"
#include "views/controls/native/native_view_host.h"
+namespace app {
+namespace win {
+class ScopedProp;
+}
+}
+
namespace views {
// A View that hosts a native Windows control.
@@ -86,6 +93,8 @@ class NativeControlWin : public NativeViewHost {
// The window procedure before we subclassed.
WNDPROC original_wndproc_;
+ scoped_ptr<app::win::ScopedProp> prop_;
+
DISALLOW_COPY_AND_ASSIGN(NativeControlWin);
};
diff --git a/views/focus/focus_util_win.cc b/views/focus/focus_util_win.cc
index 381d02b..266a891 100644
--- a/views/focus/focus_util_win.cc
+++ b/views/focus/focus_util_win.cc
@@ -6,6 +6,7 @@
#include <windowsx.h>
+#include "app/win/scoped_prop.h"
#include "base/auto_reset.h"
#include "base/win_util.h"
@@ -52,9 +53,9 @@ static bool CanRedirectMouseWheelFrom(HWND window) {
return true;
}
-void SetWindowSupportsRerouteMouseWheel(HWND hwnd) {
- SetProp(hwnd, kHWNDSupportMouseWheelRerouting,
- reinterpret_cast<HANDLE>(true));
+app::win::ScopedProp* SetWindowSupportsRerouteMouseWheel(HWND hwnd) {
+ return new app::win::ScopedProp(hwnd, kHWNDSupportMouseWheelRerouting,
+ reinterpret_cast<HANDLE>(true));
}
bool RerouteMouseWheel(HWND window, WPARAM w_param, LPARAM l_param) {
diff --git a/views/focus/focus_util_win.h b/views/focus/focus_util_win.h
index 7a85720..2c53c68 100644
--- a/views/focus/focus_util_win.h
+++ b/views/focus/focus_util_win.h
@@ -8,12 +8,19 @@
#include <windows.h>
+namespace app {
+namespace win {
+class ScopedProp;
+}
+}
+
namespace views {
// Marks the passed |hwnd| as supporting mouse-wheel message rerouting.
// We reroute the mouse wheel messages to such HWND when they are under the
-// mouse pointer (but are not the active window)
-void SetWindowSupportsRerouteMouseWheel(HWND hwnd);
+// mouse pointer (but are not the active window). Callers must delete the
+// returned object before the window is destroyed (see ScopedProp for details).
+app::win::ScopedProp* SetWindowSupportsRerouteMouseWheel(HWND hwnd);
// Forwards mouse wheel messages to the window under it.
// Windows sends mouse wheel messages to the currently active window.
diff --git a/views/widget/widget_win.cc b/views/widget/widget_win.cc
index 102b48d..bb6ca8d 100644
--- a/views/widget/widget_win.cc
+++ b/views/widget/widget_win.cc
@@ -8,6 +8,7 @@
#include "app/l10n_util_win.h"
#include "app/system_monitor.h"
#include "app/win_util.h"
+#include "app/win/scoped_prop.h"
#include "base/string_util.h"
#include "base/win_util.h"
#include "gfx/canvas_skia.h"
@@ -36,10 +37,6 @@ bool WidgetWin::screen_reader_active_ = false;
// listening for MSAA events.
#define OBJID_CUSTOM 1
-bool SetRootViewForHWND(HWND hwnd, RootView* root_view) {
- return SetProp(hwnd, kRootViewWindowProperty, root_view) ? true : false;
-}
-
RootView* GetRootViewForHWND(HWND hwnd) {
return reinterpret_cast<RootView*>(::GetProp(hwnd, kRootViewWindowProperty));
}
@@ -168,7 +165,7 @@ void WidgetWin::Init(gfx::NativeView parent, const gfx::Rect& bounds) {
default_theme_provider_.reset(new DefaultThemeProvider());
- SetWindowSupportsRerouteMouseWheel(hwnd());
+ props_.push_back(SetWindowSupportsRerouteMouseWheel(hwnd()));
drop_target_ = new DropTargetWin(root_view_.get());
@@ -183,7 +180,7 @@ void WidgetWin::Init(gfx::NativeView parent, const gfx::Rect& bounds) {
}
// Sets the RootView as a property, so the automation can introspect windows.
- SetRootViewForHWND(hwnd(), root_view_.get());
+ SetNativeWindowProperty(kRootViewWindowProperty, root_view_.get());
MessageLoopForUI::current()->AddObserver(this);
@@ -421,12 +418,17 @@ const Window* WidgetWin::GetWindow() const {
return GetWindowImpl(hwnd());
}
-void WidgetWin::SetNativeWindowProperty(const std::wstring& name,
- void* value) {
+void WidgetWin::SetNativeWindowProperty(const std::wstring& name, void* value) {
+ // Remove the existing property (if any).
+ for (ScopedProps::iterator i = props_.begin(); i != props_.end(); ++i) {
+ if ((*i)->key() == name) {
+ props_.erase(i);
+ break;
+ }
+ }
+
if (value)
- SetProp(hwnd(), name.c_str(), value);
- else
- RemoveProp(hwnd(), name.c_str());
+ props_.push_back(new app::win::ScopedProp(hwnd(), name, value));
}
void* WidgetWin::GetNativeWindowProperty(const std::wstring& name) {
@@ -583,14 +585,12 @@ LRESULT WidgetWin::OnCreate(CREATESTRUCT* create_struct) {
}
void WidgetWin::OnDestroy() {
- SetNativeWindowProperty(kWidgetKey, NULL);
-
if (drop_target_.get()) {
RevokeDragDrop(hwnd());
drop_target_ = NULL;
}
- RemoveProp(hwnd(), kRootViewWindowProperty);
+ props_.reset();
}
void WidgetWin::OnDisplayChange(UINT bits_per_pixel, CSize screen_size) {
diff --git a/views/widget/widget_win.h b/views/widget/widget_win.h
index 029f34e..bfb9137 100644
--- a/views/widget/widget_win.h
+++ b/views/widget/widget_win.h
@@ -11,15 +11,23 @@
#include <atlcrack.h>
#include <atlmisc.h>
+#include <string>
#include <vector>
#include "base/message_loop.h"
#include "base/scoped_comptr_win.h"
+#include "base/scoped_vector.h"
#include "gfx/window_impl.h"
#include "views/focus/focus_manager.h"
#include "views/layout_manager.h"
#include "views/widget/widget.h"
+namespace app {
+namespace win {
+class ScopedProp;
+}
+}
+
namespace gfx {
class CanvasSkia;
class Rect;
@@ -34,7 +42,6 @@ class RootView;
class TooltipManagerWin;
class Window;
-bool SetRootViewForHWND(HWND hwnd, RootView* root_view);
RootView* GetRootViewForHWND(HWND hwnd);
// A Windows message reflected from other windows. This message is sent
@@ -480,6 +487,8 @@ class WidgetWin : public gfx::WindowImpl,
bool is_window_;
private:
+ typedef ScopedVector<app::win::ScopedProp> ScopedProps;
+
// Implementation of GetWindow. Ascends the parents of |hwnd| returning the
// first ancestor that is a Window.
static Window* GetWindowImpl(HWND hwnd);
@@ -585,6 +594,10 @@ class WidgetWin : public gfx::WindowImpl,
// The current position of the view events vector. When incrementing,
// we always mod this value with the max view events above .
int accessibility_view_events_index_;
+
+ ScopedProps props_;
+
+ DISALLOW_COPY_AND_ASSIGN(WidgetWin);
};
} // namespace views