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

Side by Side Diff: chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.cc

Issue 2505443003: Make sure all paths out of the dialog properly unregister observers. (Closed)
Patch Set: Created 4 years, 1 month 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
« no previous file with comments | « chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/javascript_dialogs/javascript_dialog_tab_helper.h" 5 #include "chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/feature_list.h" 9 #include "base/feature_list.h"
10 #include "base/metrics/histogram_macros.h" 10 #include "base/metrics/histogram_macros.h"
(...skipping 20 matching lines...) Expand all
31 } 31 }
32 32
33 bool IsWebContentsForemost(content::WebContents* web_contents) { 33 bool IsWebContentsForemost(content::WebContents* web_contents) {
34 Browser* browser = BrowserList::GetInstance()->GetLastActive(); 34 Browser* browser = BrowserList::GetInstance()->GetLastActive();
35 DCHECK(browser); 35 DCHECK(browser);
36 return browser->tab_strip_model()->GetActiveWebContents() == web_contents; 36 return browser->tab_strip_model()->GetActiveWebContents() == web_contents;
37 } 37 }
38 38
39 } // namespace 39 } // namespace
40 40
41 // A note on the interaction between the JavaScriptDialogTabHelper and the
42 // JavaScriptDialog classes.
43 //
44 // Either side can start the process of closing a dialog, and we need to ensure
45 // that everything is properly torn down no matter which side initiates.
46 //
47 // If closing is initiated by the JavaScriptDialogTabHelper, then it will call
48 // CloseDialog(), which calls JavaScriptDialog::CloseDialogWithoutCallback().
49 // That will clear the callback inside of JavaScriptDialog, and start the
50 // JavaScriptDialog on its own path of destruction. CloseDialog() then calls
51 // ClearDialogInfo() which removes observers.
52 //
53 // If closing is initiated by the JavaScriptDialog, which is a self-deleting
54 // object, then it will make its callback. The callback will have been wrapped
55 // within JavaScriptDialogTabHelper::RunJavaScriptDialog() to be a call to
56 // JavaScriptDialogTabHelper::OnDialogClosed(), which, after doing the callback,
57 // again calls ClearDialogInfo() to remove observers.
58
41 JavaScriptDialogTabHelper::JavaScriptDialogTabHelper( 59 JavaScriptDialogTabHelper::JavaScriptDialogTabHelper(
42 content::WebContents* web_contents) 60 content::WebContents* web_contents)
43 : content::WebContentsObserver(web_contents) { 61 : content::WebContentsObserver(web_contents) {
44 } 62 }
45 63
46 JavaScriptDialogTabHelper::~JavaScriptDialogTabHelper() { 64 JavaScriptDialogTabHelper::~JavaScriptDialogTabHelper() {
65 if (dialog_)
66 CloseDialog(true /*suppress_callback*/, false, base::string16());
47 } 67 }
48 68
49 void JavaScriptDialogTabHelper::SetDialogShownCallbackForTesting( 69 void JavaScriptDialogTabHelper::SetDialogShownCallbackForTesting(
50 base::Closure callback) { 70 base::Closure callback) {
51 dialog_shown_ = callback; 71 dialog_shown_ = callback;
52 } 72 }
53 73
54 void JavaScriptDialogTabHelper::RunJavaScriptDialog( 74 void JavaScriptDialogTabHelper::RunJavaScriptDialog(
55 content::WebContents* alerting_web_contents, 75 content::WebContents* alerting_web_contents,
56 const GURL& origin_url, 76 const GURL& origin_url,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 if (dialog_) { 132 if (dialog_) {
113 // There's already a dialog up; clear it out. 133 // There's already a dialog up; clear it out.
114 CloseDialog(false, false, base::string16()); 134 CloseDialog(false, false, base::string16());
115 } 135 }
116 136
117 base::string16 title = 137 base::string16 title =
118 AppModalDialogManager()->GetTitle(alerting_web_contents, origin_url); 138 AppModalDialogManager()->GetTitle(alerting_web_contents, origin_url);
119 dialog_callback_ = callback; 139 dialog_callback_ = callback;
120 dialog_ = JavaScriptDialog::Create( 140 dialog_ = JavaScriptDialog::Create(
121 parent_web_contents, alerting_web_contents, title, message_type, 141 parent_web_contents, alerting_web_contents, title, message_type,
122 message_text, default_prompt_text, callback); 142 message_text, default_prompt_text,
143 base::Bind(&JavaScriptDialogTabHelper::OnDialogClosed,
144 base::Unretained(this), callback));
123 145
124 BrowserList::AddObserver(this); 146 BrowserList::AddObserver(this);
125 147
126 // Message suppression is something that we don't give the user a checkbox 148 // Message suppression is something that we don't give the user a checkbox
127 // for any more. It was useful back in the day when dialogs were app-modal 149 // for any more. It was useful back in the day when dialogs were app-modal
128 // and clicking the checkbox was the only way to escape a loop that the page 150 // and clicking the checkbox was the only way to escape a loop that the page
129 // was doing, but now the user can just close the page. 151 // was doing, but now the user can just close the page.
130 *did_suppress_message = false; 152 *did_suppress_message = false;
131 153
132 if (!dialog_shown_.is_null()) { 154 if (!dialog_shown_.is_null()) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 void JavaScriptDialogTabHelper::WasHidden() { 237 void JavaScriptDialogTabHelper::WasHidden() {
216 if (dialog_) 238 if (dialog_)
217 CloseDialog(false, false, base::string16()); 239 CloseDialog(false, false, base::string16());
218 } 240 }
219 241
220 void JavaScriptDialogTabHelper::OnBrowserSetLastActive(Browser* browser) { 242 void JavaScriptDialogTabHelper::OnBrowserSetLastActive(Browser* browser) {
221 if (dialog_ && !IsWebContentsForemost(web_contents())) 243 if (dialog_ && !IsWebContentsForemost(web_contents()))
222 CloseDialog(false, false, base::string16()); 244 CloseDialog(false, false, base::string16());
223 } 245 }
224 246
247 void JavaScriptDialogTabHelper::OnDialogClosed(
248 DialogClosedCallback callback,
249 bool success,
250 const base::string16& user_input) {
251 callback.Run(success, user_input);
252
253 ClearDialogInfo();
254 }
255
225 void JavaScriptDialogTabHelper::CloseDialog(bool suppress_callback, 256 void JavaScriptDialogTabHelper::CloseDialog(bool suppress_callback,
226 bool success, 257 bool success,
227 const base::string16& user_input) { 258 const base::string16& user_input) {
228 DCHECK(dialog_); 259 DCHECK(dialog_);
229 260
230 dialog_->CloseDialogWithoutCallback(); 261 dialog_->CloseDialogWithoutCallback();
231 if (!suppress_callback) 262 if (!suppress_callback)
232 dialog_callback_.Run(success, user_input); 263 dialog_callback_.Run(success, user_input);
233 264
265 ClearDialogInfo();
266 }
267
268 void JavaScriptDialogTabHelper::ClearDialogInfo() {
234 dialog_.reset(); 269 dialog_.reset();
235 dialog_callback_.Reset(); 270 dialog_callback_.Reset();
236 BrowserList::RemoveObserver(this); 271 BrowserList::RemoveObserver(this);
237 } 272 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698