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

Side by Side Diff: chrome/browser/ui/views/global_error_bubble_view.cc

Issue 2650923002: Fixes ungraceful handling of destroyed GlobalError GlobalErrorBubbleView. (Closed)
Patch Set: Created 3 years, 11 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/ui/views/global_error_bubble_view.h" 5 #include "chrome/browser/ui/views/global_error_bubble_view.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <vector> 9 #include <vector>
10 10
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 : BubbleDialogDelegateView(anchor_view, arrow), 67 : BubbleDialogDelegateView(anchor_view, arrow),
68 browser_(browser), 68 browser_(browser),
69 error_(error) { 69 error_(error) {
70 if (!anchor_view) 70 if (!anchor_view)
71 SetAnchorRect(gfx::Rect(anchor_point, gfx::Size())); 71 SetAnchorRect(gfx::Rect(anchor_point, gfx::Size()));
72 } 72 }
73 73
74 GlobalErrorBubbleView::~GlobalErrorBubbleView() {} 74 GlobalErrorBubbleView::~GlobalErrorBubbleView() {}
75 75
76 base::string16 GlobalErrorBubbleView::GetWindowTitle() const { 76 base::string16 GlobalErrorBubbleView::GetWindowTitle() const {
77 return error_->GetBubbleViewTitle(); 77 if (error_) {
Wez 2017/01/24 01:45:55 nit: I'd recommend using an early-exit pattern for
CJ 2017/01/25 01:11:21 Done. you meant !error right?
Wez 2017/01/26 18:34:09 D'oh! Yes :D
78 return error_->GetBubbleViewTitle();
79 }
80 return base::string16();
78 } 81 }
79 82
80 gfx::ImageSkia GlobalErrorBubbleView::GetWindowIcon() { 83 gfx::ImageSkia GlobalErrorBubbleView::GetWindowIcon() {
81 gfx::Image image = error_->GetBubbleViewIcon(); 84 gfx::Image image;
85 if (error_) {
86 image = error_->GetBubbleViewIcon();
87 }
82 DCHECK(!image.IsEmpty()); 88 DCHECK(!image.IsEmpty());
Wez 2017/01/24 01:45:55 This DCHECK will trivially fail if |error_| is nul
CJ 2017/01/25 01:11:21 Done.
83 return *image.ToImageSkia(); 89 return *image.ToImageSkia();
84 } 90 }
85 91
86 bool GlobalErrorBubbleView::ShouldShowWindowIcon() const { 92 bool GlobalErrorBubbleView::ShouldShowWindowIcon() const {
87 return true; 93 return true;
88 } 94 }
89 95
90 void GlobalErrorBubbleView::WindowClosing() { 96 void GlobalErrorBubbleView::WindowClosing() {
91 if (error_) 97 if (error_)
92 error_->BubbleViewDidClose(browser_); 98 error_->BubbleViewDidClose(browser_);
93 } 99 }
94 100
95 void GlobalErrorBubbleView::Init() { 101 void GlobalErrorBubbleView::Init() {
96 // Compensate for built-in vertical padding in the anchor view's image. 102 // Compensate for built-in vertical padding in the anchor view's image.
97 set_anchor_view_insets(gfx::Insets( 103 set_anchor_view_insets(gfx::Insets(
98 GetLayoutConstant(LOCATION_BAR_BUBBLE_ANCHOR_VERTICAL_INSET), 0)); 104 GetLayoutConstant(LOCATION_BAR_BUBBLE_ANCHOR_VERTICAL_INSET), 0));
99 105
106 DCHECK(error_);
Wez 2017/01/24 01:45:55 Ooooh, this is a fun one :) It's good to document
CJ 2017/01/25 01:11:20 Done.
100 std::vector<base::string16> message_strings(error_->GetBubbleViewMessages()); 107 std::vector<base::string16> message_strings(error_->GetBubbleViewMessages());
101 std::vector<views::Label*> message_labels; 108 std::vector<views::Label*> message_labels;
102 for (size_t i = 0; i < message_strings.size(); ++i) { 109 for (size_t i = 0; i < message_strings.size(); ++i) {
103 views::Label* message_label = new views::Label(message_strings[i]); 110 views::Label* message_label = new views::Label(message_strings[i]);
104 message_label->SetMultiLine(true); 111 message_label->SetMultiLine(true);
105 message_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 112 message_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
106 message_labels.push_back(message_label); 113 message_labels.push_back(message_label);
107 } 114 }
108 115
109 views::GridLayout* layout = new views::GridLayout(this); 116 views::GridLayout* layout = new views::GridLayout(this);
110 SetLayoutManager(layout); 117 SetLayoutManager(layout);
111 118
112 // First row, message labels. 119 // First row, message labels.
113 views::ColumnSet* cs = layout->AddColumnSet(0); 120 views::ColumnSet* cs = layout->AddColumnSet(0);
114 cs->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, 121 cs->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
115 views::GridLayout::FIXED, kMaxBubbleViewWidth, 0); 122 views::GridLayout::FIXED, kMaxBubbleViewWidth, 0);
116 123
117 for (size_t i = 0; i < message_labels.size(); ++i) { 124 for (size_t i = 0; i < message_labels.size(); ++i) {
118 layout->StartRow(1, 0); 125 layout->StartRow(1, 0);
119 layout->AddView(message_labels[i]); 126 layout->AddView(message_labels[i]);
120 if (i < message_labels.size() - 1) 127 if (i < message_labels.size() - 1)
121 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 128 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
122 } 129 }
123 130
124 // These bubbles show at times where activation is sporadic (like at startup, 131 // These bubbles show at times where activation is sporadic (like at startup,
125 // or a new window opening). Make sure the bubble doesn't disappear before the 132 // or a new window opening). Make sure the bubble doesn't disappear before the
126 // user sees it, if the bubble needs to be acknowledged. 133 // user sees it, if the bubble needs to be acknowledged.
134 DCHECK(error_);
Wez 2017/01/24 01:45:55 See above :)
CJ 2017/01/25 01:11:21 Done.
127 set_close_on_deactivate(error_->ShouldCloseOnDeactivate()); 135 set_close_on_deactivate(error_->ShouldCloseOnDeactivate());
128 } 136 }
129 137
130 void GlobalErrorBubbleView::UpdateButton(views::LabelButton* button, 138 void GlobalErrorBubbleView::UpdateButton(views::LabelButton* button,
131 ui::DialogButton type) { 139 ui::DialogButton type) {
132 BubbleDialogDelegateView::UpdateButton(button, type); 140 if (error_) {
133 if (type == ui::DIALOG_BUTTON_OK && 141 BubbleDialogDelegateView::UpdateButton(button, type);
Wez 2017/01/24 01:45:55 nit: Does UpdateButton reference |error_| in some
CJ 2017/01/25 01:11:21 Seems to. Found that through my tests as the Stric
Wez 2017/01/26 18:34:09 Ahhh! That makes sense - UpdateButton() is causing
CJ 2017/01/27 00:44:05 Done.
134 error_->ShouldAddElevationIconToAcceptButton()) { 142 if (type == ui::DIALOG_BUTTON_OK &&
135 elevation_icon_setter_.reset(new ElevationIconSetter( 143 error_->ShouldAddElevationIconToAcceptButton()) {
136 button, base::Bind(&GlobalErrorBubbleView::SizeToContents, 144 elevation_icon_setter_.reset(new ElevationIconSetter(
137 base::Unretained(this)))); 145 button, base::Bind(&GlobalErrorBubbleView::SizeToContents,
146 base::Unretained(this))));
147 }
138 } 148 }
139 } 149 }
140 150
141 bool GlobalErrorBubbleView::ShouldShowCloseButton() const { 151 bool GlobalErrorBubbleView::ShouldShowCloseButton() const {
142 return error_ && error_->ShouldShowCloseButton(); 152 return error_ && error_->ShouldShowCloseButton();
143 } 153 }
144 154
145 bool GlobalErrorBubbleView::ShouldDefaultButtonBeBlue() const { 155 bool GlobalErrorBubbleView::ShouldDefaultButtonBeBlue() const {
146 return true; 156 return true;
147 } 157 }
148 158
149 base::string16 GlobalErrorBubbleView::GetDialogButtonLabel( 159 base::string16 GlobalErrorBubbleView::GetDialogButtonLabel(
150 ui::DialogButton button) const { 160 ui::DialogButton button) const {
161 DCHECK(error_);
Wez 2017/01/24 01:45:55 As noted above, the de-references below will alrea
CJ 2017/01/25 01:11:21 Done.
151 return button == ui::DIALOG_BUTTON_OK 162 return button == ui::DIALOG_BUTTON_OK
152 ? error_->GetBubbleViewAcceptButtonLabel() 163 ? error_->GetBubbleViewAcceptButtonLabel()
153 : error_->GetBubbleViewCancelButtonLabel(); 164 : error_->GetBubbleViewCancelButtonLabel();
154 } 165 }
155 166
156 int GlobalErrorBubbleView::GetDialogButtons() const { 167 int GlobalErrorBubbleView::GetDialogButtons() const {
168 DCHECK(error_);
Wez 2017/01/24 01:45:55 See GetDialogButtonLabel comment above.
CJ 2017/01/25 01:11:21 Done.
157 return ui::DIALOG_BUTTON_OK | 169 return ui::DIALOG_BUTTON_OK |
158 (error_->GetBubbleViewCancelButtonLabel().empty() 170 (error_->GetBubbleViewCancelButtonLabel().empty()
159 ? 0 171 ? 0
160 : ui::DIALOG_BUTTON_CANCEL); 172 : ui::DIALOG_BUTTON_CANCEL);
161 } 173 }
162 174
163 bool GlobalErrorBubbleView::Cancel() { 175 bool GlobalErrorBubbleView::Cancel() {
164 error_->BubbleViewCancelButtonPressed(browser_); 176 if (error_)
177 error_->BubbleViewCancelButtonPressed(browser_);
165 return true; 178 return true;
166 } 179 }
167 180
168 bool GlobalErrorBubbleView::Accept() { 181 bool GlobalErrorBubbleView::Accept() {
169 error_->BubbleViewAcceptButtonPressed(browser_); 182 if (error_)
183 error_->BubbleViewAcceptButtonPressed(browser_);
170 return true; 184 return true;
171 } 185 }
172 186
173 bool GlobalErrorBubbleView::Close() { 187 bool GlobalErrorBubbleView::Close() {
174 // Don't fall through to either Cancel() or Accept(). 188 // Don't fall through to either Cancel() or Accept().
175 return true; 189 return true;
176 } 190 }
177 191
178 void GlobalErrorBubbleView::CloseBubbleView() { 192 void GlobalErrorBubbleView::CloseBubbleView() {
179 GetWidget()->Close(); 193 GetWidget()->Close();
180 } 194 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698