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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/autocomplete/autocomplete_edit.h" 5 #include "chrome/browser/autocomplete/autocomplete_edit.h"
6 6
7 #include <locale> 7 #include <locale>
8 8
9 #include "base/base_drag_source.h" 9 #include "base/base_drag_source.h"
10 #include "base/clipboard.h" 10 #include "base/clipboard.h"
11 #include "base/iat_patch.h" 11 #include "base/iat_patch.h"
12 #include "base/lazy_instance.h"
12 #include "base/ref_counted.h" 13 #include "base/ref_counted.h"
13 #include "base/scoped_clipboard_writer.h" 14 #include "base/scoped_clipboard_writer.h"
14 #include "base/string_util.h" 15 #include "base/string_util.h"
15 #include "chrome/app/chrome_dll_resource.h" 16 #include "chrome/app/chrome_dll_resource.h"
16 #include "chrome/browser/autocomplete/autocomplete_accessibility.h" 17 #include "chrome/browser/autocomplete/autocomplete_accessibility.h"
17 #include "chrome/browser/autocomplete/autocomplete_popup.h" 18 #include "chrome/browser/autocomplete/autocomplete_popup.h"
18 #include "chrome/browser/autocomplete/edit_drop_target.h" 19 #include "chrome/browser/autocomplete/edit_drop_target.h"
19 #include "chrome/browser/autocomplete/keyword_provider.h" 20 #include "chrome/browser/autocomplete/keyword_provider.h"
20 #include "chrome/browser/browser_process.h" 21 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/command_updater.h" 22 #include "chrome/browser/command_updater.h"
(...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 if (text_object_model_) 627 if (text_object_model_)
627 text_object_model_->Undo(tomResume, NULL); 628 text_object_model_->Undo(tomResume, NULL);
628 } 629 }
629 630
630 /////////////////////////////////////////////////////////////////////////////// 631 ///////////////////////////////////////////////////////////////////////////////
631 // AutocompleteEditView 632 // AutocompleteEditView
632 633
633 // TODO (jcampan): these colors should be derived from the system colors to 634 // TODO (jcampan): these colors should be derived from the system colors to
634 // ensure they show properly. Bug #948807. 635 // ensure they show properly. Bug #948807.
635 // Colors used to emphasize the scheme in the URL. 636 // Colors used to emphasize the scheme in the URL.
636 static const COLORREF kSecureSchemeColor = RGB(0, 150, 20); 637
637 static const COLORREF kInsecureSchemeColor = RGB(200, 0, 0); 638 namespace {
639
640 const COLORREF kSecureSchemeColor = RGB(0, 150, 20);
641 const COLORREF kInsecureSchemeColor = RGB(200, 0, 0);
638 642
639 // Colors used to strike-out the scheme when it is insecure. 643 // Colors used to strike-out the scheme when it is insecure.
640 static const SkColor kSchemeStrikeoutColor = SkColorSetRGB(210, 0, 0); 644 const SkColor kSchemeStrikeoutColor = SkColorSetRGB(210, 0, 0);
641 static const SkColor kSchemeSelectedStrikeoutColor = 645 const SkColor kSchemeSelectedStrikeoutColor =
642 SkColorSetRGB(255, 255, 255); 646 SkColorSetRGB(255, 255, 255);
643 647
644 // These are used to hook the CRichEditCtrl's calls to BeginPaint() and 648 // These are used to hook the CRichEditCtrl's calls to BeginPaint() and
645 // EndPaint() and provide a memory DC instead. See OnPaint(). 649 // EndPaint() and provide a memory DC instead. See OnPaint().
646 static HWND edit_hwnd = NULL; 650 HWND edit_hwnd = NULL;
647 static PAINTSTRUCT paint_struct; 651 PAINTSTRUCT paint_struct;
652
653 HDC BeginPaintIntercept(HWND hWnd, LPPAINTSTRUCT lpPaint) {
654 if (!edit_hwnd || (hWnd != edit_hwnd))
655 return ::BeginPaint(hWnd, lpPaint);
656
657 *lpPaint = paint_struct;
658 return paint_struct.hdc;
659 }
660
661 BOOL EndPaintIntercept(HWND hWnd, const PAINTSTRUCT* lpPaint) {
662 return (edit_hwnd && (hWnd == edit_hwnd)) ?
663 true : ::EndPaint(hWnd, lpPaint);
664 }
648 665
649 // Returns a lazily initialized property bag accessor for saving our state in a 666 // Returns a lazily initialized property bag accessor for saving our state in a
650 // TabContents. 667 // TabContents.
651 static PropertyAccessor<AutocompleteEditState>* GetStateAccessor() { 668 PropertyAccessor<AutocompleteEditState>* GetStateAccessor() {
652 static PropertyAccessor<AutocompleteEditState> state; 669 static PropertyAccessor<AutocompleteEditState> state;
653 return &state; 670 return &state;
654 } 671 }
655 672
673 class PaintPatcher {
amit 2009/02/26 15:00:32 maybe derive privately from RefCounted and just ca
674 public:
675 PaintPatcher() : refcount_(0) { }
676 ~PaintPatcher() { DCHECK(refcount_ == 0); }
677
678 void RefPatch() {
679 if (refcount_ == 0) {
680 DCHECK(!begin_paint_.is_patched());
681 DCHECK(!end_paint_.is_patched());
682 begin_paint_.Patch(L"riched20.dll", "user32.dll", "BeginPaint",
683 &BeginPaintIntercept);
684 end_paint_.Patch(L"riched20.dll", "user32.dll", "EndPaint",
685 &EndPaintIntercept);
686 }
687 ++refcount_;
688 }
689
690 void DerefPatch() {
691 DCHECK(begin_paint_.is_patched());
692 DCHECK(end_paint_.is_patched());
693 --refcount_;
694 if (refcount_ == 0) {
695 begin_paint_.Unpatch();
696 end_paint_.Unpatch();
697 }
698 }
699
700 private:
amit 2009/02/26 15:00:32 DISABLE_COPY_AND_ASSIGN
701 size_t refcount_;
702 iat_patch::IATPatchFunction begin_paint_;
703 iat_patch::IATPatchFunction end_paint_;
704 };
705
706 base::LazyInstance<PaintPatcher> g_paint_patcher(base::LINKER_INITIALIZED);
707
708 } // namespace
709
656 AutocompleteEditView::AutocompleteEditView( 710 AutocompleteEditView::AutocompleteEditView(
657 const ChromeFont& font, 711 const ChromeFont& font,
658 AutocompleteEditController* controller, 712 AutocompleteEditController* controller,
659 ToolbarModel* toolbar_model, 713 ToolbarModel* toolbar_model,
660 views::View* parent_view, 714 views::View* parent_view,
661 HWND hwnd, 715 HWND hwnd,
662 Profile* profile, 716 Profile* profile,
663 CommandUpdater* command_updater, 717 CommandUpdater* command_updater,
664 bool popup_window_mode) 718 bool popup_window_mode)
665 : model_(new AutocompleteEditModel(this, controller, profile)), 719 : model_(new AutocompleteEditModel(this, controller, profile)),
(...skipping 12 matching lines...) Expand all
678 possible_drag_(false), 732 possible_drag_(false),
679 in_drag_(false), 733 in_drag_(false),
680 initiated_drag_(false), 734 initiated_drag_(false),
681 drop_highlight_position_(-1), 735 drop_highlight_position_(-1),
682 background_color_(0), 736 background_color_(0),
683 scheme_security_level_(ToolbarModel::NORMAL) { 737 scheme_security_level_(ToolbarModel::NORMAL) {
684 model_->set_popup_model(popup_model_.get()); 738 model_->set_popup_model(popup_model_.get());
685 739
686 saved_selection_for_focus_change_.cpMin = -1; 740 saved_selection_for_focus_change_.cpMin = -1;
687 741
688 // Statics used for global patching of riched20.dll. 742 g_paint_patcher.Pointer()->RefPatch();
689 static HMODULE richedit_module = NULL;
690 static iat_patch::IATPatchFunction patch_begin_paint;
691 static iat_patch::IATPatchFunction patch_end_paint;
692
693 if (!richedit_module) {
694 richedit_module = LoadLibrary(L"riched20.dll");
695 if (richedit_module) {
696 DCHECK(!patch_begin_paint.is_patched());
697 patch_begin_paint.Patch(richedit_module, "user32.dll", "BeginPaint",
698 &BeginPaintIntercept);
699 DCHECK(!patch_end_paint.is_patched());
700 patch_end_paint.Patch(richedit_module, "user32.dll", "EndPaint",
701 &EndPaintIntercept);
702 }
703 }
704 743
705 Create(hwnd, 0, 0, 0, l10n_util::GetExtendedStyles()); 744 Create(hwnd, 0, 0, 0, l10n_util::GetExtendedStyles());
706 SetReadOnly(popup_window_mode_); 745 SetReadOnly(popup_window_mode_);
707 SetFont(font_.hfont()); 746 SetFont(font_.hfont());
708 747
709 // NOTE: Do not use SetWordBreakProcEx() here, that is no longer supported as 748 // NOTE: Do not use SetWordBreakProcEx() here, that is no longer supported as
710 // of Rich Edit 2.0 onward. 749 // of Rich Edit 2.0 onward.
711 SendMessage(m_hWnd, EM_SETWORDBREAKPROC, 0, 750 SendMessage(m_hWnd, EM_SETWORDBREAKPROC, 0,
712 reinterpret_cast<LPARAM>(&WordBreakProc)); 751 reinterpret_cast<LPARAM>(&WordBreakProc));
713 752
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 scoped_refptr<EditDropTarget> drop_target = new EditDropTarget(this); 819 scoped_refptr<EditDropTarget> drop_target = new EditDropTarget(this);
781 RegisterDragDrop(m_hWnd, drop_target.get()); 820 RegisterDragDrop(m_hWnd, drop_target.get());
782 } 821 }
783 } 822 }
784 823
785 AutocompleteEditView::~AutocompleteEditView() { 824 AutocompleteEditView::~AutocompleteEditView() {
786 NotificationService::current()->Notify( 825 NotificationService::current()->Notify(
787 NotificationType::AUTOCOMPLETE_EDIT_DESTROYED, 826 NotificationType::AUTOCOMPLETE_EDIT_DESTROYED,
788 Source<AutocompleteEditView>(this), 827 Source<AutocompleteEditView>(this),
789 NotificationService::NoDetails()); 828 NotificationService::NoDetails());
829
830 // We balance our reference count and unpatch when the last instance has
831 // been destroyed. This prevents us from relying on the AtExit or static
832 // destructor sequence to do our unpatching, which is generally fragile.
833 g_paint_patcher.Pointer()->DerefPatch();
790 } 834 }
791 835
792 void AutocompleteEditView::SaveStateToTab(TabContents* tab) { 836 void AutocompleteEditView::SaveStateToTab(TabContents* tab) {
793 DCHECK(tab); 837 DCHECK(tab);
794 838
795 const AutocompleteEditModel::State model_state( 839 const AutocompleteEditModel::State model_state(
796 model_->GetStateForTabSwitch()); 840 model_->GetStateForTabSwitch());
797 841
798 CHARRANGE selection; 842 CHARRANGE selection;
799 GetSelection(selection); 843 GetSelection(selection);
(...skipping 567 matching lines...) Expand 10 before | Expand all | Expand 10 after
1367 bool AutocompleteEditView::SchemeEnd(LPTSTR edit_text, 1411 bool AutocompleteEditView::SchemeEnd(LPTSTR edit_text,
1368 int current_pos, 1412 int current_pos,
1369 int length) { 1413 int length) {
1370 return (current_pos >= 0) && 1414 return (current_pos >= 0) &&
1371 ((length - current_pos) > 2) && 1415 ((length - current_pos) > 2) &&
1372 (edit_text[current_pos] == ':') && 1416 (edit_text[current_pos] == ':') &&
1373 (edit_text[current_pos + 1] == '/') && 1417 (edit_text[current_pos + 1] == '/') &&
1374 (edit_text[current_pos + 2] == '/'); 1418 (edit_text[current_pos + 2] == '/');
1375 } 1419 }
1376 1420
1377 // static
1378 HDC AutocompleteEditView::BeginPaintIntercept(HWND hWnd,
1379 LPPAINTSTRUCT lpPaint) {
1380 if (!edit_hwnd || (hWnd != edit_hwnd))
1381 return ::BeginPaint(hWnd, lpPaint);
1382
1383 *lpPaint = paint_struct;
1384 return paint_struct.hdc;
1385 }
1386
1387 // static
1388 BOOL AutocompleteEditView::EndPaintIntercept(HWND hWnd,
1389 const PAINTSTRUCT* lpPaint) {
1390 return (edit_hwnd && (hWnd == edit_hwnd)) ?
1391 true : ::EndPaint(hWnd, lpPaint);
1392 }
1393
1394 void AutocompleteEditView::OnChar(TCHAR ch, UINT repeat_count, UINT flags) { 1421 void AutocompleteEditView::OnChar(TCHAR ch, UINT repeat_count, UINT flags) {
1395 // Don't let alt-enter beep. Not sure this is necessary, as the standard 1422 // Don't let alt-enter beep. Not sure this is necessary, as the standard
1396 // alt-enter will hit DiscardWMSysChar() and get thrown away, and 1423 // alt-enter will hit DiscardWMSysChar() and get thrown away, and
1397 // ctrl-alt-enter doesn't seem to reach here for some reason? At least not on 1424 // ctrl-alt-enter doesn't seem to reach here for some reason? At least not on
1398 // my system... still, this is harmless and maybe necessary in other locales. 1425 // my system... still, this is harmless and maybe necessary in other locales.
1399 if (ch == VK_RETURN && (flags & KF_ALTDOWN)) 1426 if (ch == VK_RETURN && (flags & KF_ALTDOWN))
1400 return; 1427 return;
1401 1428
1402 // Escape is processed in OnKeyDown. Don't let any WM_CHAR messages propagate 1429 // Escape is processed in OnKeyDown. Don't let any WM_CHAR messages propagate
1403 // as we don't want the RichEdit to do anything funky. 1430 // as we don't want the RichEdit to do anything funky.
(...skipping 1054 matching lines...) Expand 10 before | Expand all | Expand 10 after
2458 } 2485 }
2459 2486
2460 void AutocompleteEditView::RepaintDropHighlight(int position) { 2487 void AutocompleteEditView::RepaintDropHighlight(int position) {
2461 if ((position != -1) && (position <= GetTextLength())) { 2488 if ((position != -1) && (position <= GetTextLength())) {
2462 const POINT min_loc(PosFromChar(position)); 2489 const POINT min_loc(PosFromChar(position));
2463 const RECT highlight_bounds = {min_loc.x - 1, font_y_adjustment_, 2490 const RECT highlight_bounds = {min_loc.x - 1, font_y_adjustment_,
2464 min_loc.x + 2, font_ascent_ + font_descent_ + font_y_adjustment_}; 2491 min_loc.x + 2, font_ascent_ + font_descent_ + font_y_adjustment_};
2465 InvalidateRect(&highlight_bounds, false); 2492 InvalidateRect(&highlight_bounds, false);
2466 } 2493 }
2467 } 2494 }
OLDNEW
« 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