Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3677)

Unified Diff: chrome/browser/autocomplete/autocomplete_edit.cc

Issue 21453: Try a new approach to fixing IAT unpatch crashes when the DLL is gone. (Closed)
Patch Set: DCHECK Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/autocomplete/autocomplete_edit.h ('k') | webkit/glue/plugins/webplugin_delegate_impl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/autocomplete/autocomplete_edit.cc
diff --git a/chrome/browser/autocomplete/autocomplete_edit.cc b/chrome/browser/autocomplete/autocomplete_edit.cc
index b332832f8e9395f737795c803dc7c1df5b9ea913..395deec816e9a9a0aaf99516910723726d96feb3 100644
--- a/chrome/browser/autocomplete/autocomplete_edit.cc
+++ b/chrome/browser/autocomplete/autocomplete_edit.cc
@@ -9,6 +9,7 @@
#include "base/base_drag_source.h"
#include "base/clipboard.h"
#include "base/iat_patch.h"
+#include "base/lazy_instance.h"
#include "base/ref_counted.h"
#include "base/scoped_clipboard_writer.h"
#include "base/string_util.h"
@@ -633,26 +634,79 @@ AutocompleteEditView::ScopedSuspendUndo::~ScopedSuspendUndo() {
// TODO (jcampan): these colors should be derived from the system colors to
// ensure they show properly. Bug #948807.
// Colors used to emphasize the scheme in the URL.
-static const COLORREF kSecureSchemeColor = RGB(0, 150, 20);
-static const COLORREF kInsecureSchemeColor = RGB(200, 0, 0);
+
+namespace {
+
+const COLORREF kSecureSchemeColor = RGB(0, 150, 20);
+const COLORREF kInsecureSchemeColor = RGB(200, 0, 0);
// Colors used to strike-out the scheme when it is insecure.
-static const SkColor kSchemeStrikeoutColor = SkColorSetRGB(210, 0, 0);
-static const SkColor kSchemeSelectedStrikeoutColor =
+const SkColor kSchemeStrikeoutColor = SkColorSetRGB(210, 0, 0);
+const SkColor kSchemeSelectedStrikeoutColor =
SkColorSetRGB(255, 255, 255);
// These are used to hook the CRichEditCtrl's calls to BeginPaint() and
// EndPaint() and provide a memory DC instead. See OnPaint().
-static HWND edit_hwnd = NULL;
-static PAINTSTRUCT paint_struct;
+HWND edit_hwnd = NULL;
+PAINTSTRUCT paint_struct;
+
+HDC BeginPaintIntercept(HWND hWnd, LPPAINTSTRUCT lpPaint) {
+ if (!edit_hwnd || (hWnd != edit_hwnd))
+ return ::BeginPaint(hWnd, lpPaint);
+
+ *lpPaint = paint_struct;
+ return paint_struct.hdc;
+}
+
+BOOL EndPaintIntercept(HWND hWnd, const PAINTSTRUCT* lpPaint) {
+ return (edit_hwnd && (hWnd == edit_hwnd)) ?
+ true : ::EndPaint(hWnd, lpPaint);
+}
// Returns a lazily initialized property bag accessor for saving our state in a
// TabContents.
-static PropertyAccessor<AutocompleteEditState>* GetStateAccessor() {
+PropertyAccessor<AutocompleteEditState>* GetStateAccessor() {
static PropertyAccessor<AutocompleteEditState> state;
return &state;
}
+class PaintPatcher {
amit 2009/02/26 15:00:32 maybe derive privately from RefCounted and just ca
+ public:
+ PaintPatcher() : refcount_(0) { }
+ ~PaintPatcher() { DCHECK(refcount_ == 0); }
+
+ void RefPatch() {
+ if (refcount_ == 0) {
+ DCHECK(!begin_paint_.is_patched());
+ DCHECK(!end_paint_.is_patched());
+ begin_paint_.Patch(L"riched20.dll", "user32.dll", "BeginPaint",
+ &BeginPaintIntercept);
+ end_paint_.Patch(L"riched20.dll", "user32.dll", "EndPaint",
+ &EndPaintIntercept);
+ }
+ ++refcount_;
+ }
+
+ void DerefPatch() {
+ DCHECK(begin_paint_.is_patched());
+ DCHECK(end_paint_.is_patched());
+ --refcount_;
+ if (refcount_ == 0) {
+ begin_paint_.Unpatch();
+ end_paint_.Unpatch();
+ }
+ }
+
+ private:
amit 2009/02/26 15:00:32 DISABLE_COPY_AND_ASSIGN
+ size_t refcount_;
+ iat_patch::IATPatchFunction begin_paint_;
+ iat_patch::IATPatchFunction end_paint_;
+};
+
+base::LazyInstance<PaintPatcher> g_paint_patcher(base::LINKER_INITIALIZED);
+
+} // namespace
+
AutocompleteEditView::AutocompleteEditView(
const ChromeFont& font,
AutocompleteEditController* controller,
@@ -685,22 +739,7 @@ AutocompleteEditView::AutocompleteEditView(
saved_selection_for_focus_change_.cpMin = -1;
- // Statics used for global patching of riched20.dll.
- static HMODULE richedit_module = NULL;
- static iat_patch::IATPatchFunction patch_begin_paint;
- static iat_patch::IATPatchFunction patch_end_paint;
-
- if (!richedit_module) {
- richedit_module = LoadLibrary(L"riched20.dll");
- if (richedit_module) {
- DCHECK(!patch_begin_paint.is_patched());
- patch_begin_paint.Patch(richedit_module, "user32.dll", "BeginPaint",
- &BeginPaintIntercept);
- DCHECK(!patch_end_paint.is_patched());
- patch_end_paint.Patch(richedit_module, "user32.dll", "EndPaint",
- &EndPaintIntercept);
- }
- }
+ g_paint_patcher.Pointer()->RefPatch();
Create(hwnd, 0, 0, 0, l10n_util::GetExtendedStyles());
SetReadOnly(popup_window_mode_);
@@ -787,6 +826,11 @@ AutocompleteEditView::~AutocompleteEditView() {
NotificationType::AUTOCOMPLETE_EDIT_DESTROYED,
Source<AutocompleteEditView>(this),
NotificationService::NoDetails());
+
+ // We balance our reference count and unpatch when the last instance has
+ // been destroyed. This prevents us from relying on the AtExit or static
+ // destructor sequence to do our unpatching, which is generally fragile.
+ g_paint_patcher.Pointer()->DerefPatch();
}
void AutocompleteEditView::SaveStateToTab(TabContents* tab) {
@@ -1374,23 +1418,6 @@ bool AutocompleteEditView::SchemeEnd(LPTSTR edit_text,
(edit_text[current_pos + 2] == '/');
}
-// static
-HDC AutocompleteEditView::BeginPaintIntercept(HWND hWnd,
- LPPAINTSTRUCT lpPaint) {
- if (!edit_hwnd || (hWnd != edit_hwnd))
- return ::BeginPaint(hWnd, lpPaint);
-
- *lpPaint = paint_struct;
- return paint_struct.hdc;
-}
-
-// static
-BOOL AutocompleteEditView::EndPaintIntercept(HWND hWnd,
- const PAINTSTRUCT* lpPaint) {
- return (edit_hwnd && (hWnd == edit_hwnd)) ?
- true : ::EndPaint(hWnd, lpPaint);
-}
-
void AutocompleteEditView::OnChar(TCHAR ch, UINT repeat_count, UINT flags) {
// Don't let alt-enter beep. Not sure this is necessary, as the standard
// alt-enter will hit DiscardWMSysChar() and get thrown away, and
« no previous file with comments | « chrome/browser/autocomplete/autocomplete_edit.h ('k') | webkit/glue/plugins/webplugin_delegate_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698