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

Side by Side Diff: chrome/test/base/ui_test_utils.cc

Issue 2787393003: Fix races in tests waiting for beforeunload dialogs. (Closed)
Patch Set: rev Created 3 years, 8 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/test/base/ui_test_utils.h" 5 #include "chrome/test/base/ui_test_utils.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 10
(...skipping 23 matching lines...) Expand all
34 #include "chrome/browser/ui/browser_window.h" 34 #include "chrome/browser/ui/browser_window.h"
35 #include "chrome/browser/ui/find_bar/find_notification_details.h" 35 #include "chrome/browser/ui/find_bar/find_notification_details.h"
36 #include "chrome/browser/ui/find_bar/find_tab_helper.h" 36 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
37 #include "chrome/browser/ui/location_bar/location_bar.h" 37 #include "chrome/browser/ui/location_bar/location_bar.h"
38 #include "chrome/browser/ui/tabs/tab_strip_model.h" 38 #include "chrome/browser/ui/tabs/tab_strip_model.h"
39 #include "chrome/common/chrome_paths.h" 39 #include "chrome/common/chrome_paths.h"
40 #include "chrome/common/pref_names.h" 40 #include "chrome/common/pref_names.h"
41 #include "chrome/test/base/find_in_page_observer.h" 41 #include "chrome/test/base/find_in_page_observer.h"
42 #include "components/app_modal/app_modal_dialog.h" 42 #include "components/app_modal/app_modal_dialog.h"
43 #include "components/app_modal/app_modal_dialog_queue.h" 43 #include "components/app_modal/app_modal_dialog_queue.h"
44 #include "components/app_modal/javascript_app_modal_dialog.h"
44 #include "components/bookmarks/browser/bookmark_model.h" 45 #include "components/bookmarks/browser/bookmark_model.h"
45 #include "components/history/core/browser/history_service_observer.h" 46 #include "components/history/core/browser/history_service_observer.h"
46 #include "components/omnibox/browser/autocomplete_controller.h" 47 #include "components/omnibox/browser/autocomplete_controller.h"
47 #include "components/omnibox/browser/omnibox_edit_model.h" 48 #include "components/omnibox/browser/omnibox_edit_model.h"
48 #include "components/prefs/pref_service.h" 49 #include "components/prefs/pref_service.h"
49 #include "content/public/browser/download_item.h" 50 #include "content/public/browser/download_item.h"
50 #include "content/public/browser/download_manager.h" 51 #include "content/public/browser/download_manager.h"
51 #include "content/public/browser/navigation_controller.h" 52 #include "content/public/browser/navigation_controller.h"
52 #include "content/public/browser/navigation_entry.h" 53 #include "content/public/browser/navigation_entry.h"
53 #include "content/public/browser/notification_service.h" 54 #include "content/public/browser/notification_service.h"
55 #include "content/public/browser/render_frame_host.h"
54 #include "content/public/browser/render_process_host.h" 56 #include "content/public/browser/render_process_host.h"
55 #include "content/public/browser/storage_partition.h" 57 #include "content/public/browser/storage_partition.h"
56 #include "content/public/browser/web_contents.h" 58 #include "content/public/browser/web_contents.h"
57 #include "content/public/browser/web_contents_observer.h" 59 #include "content/public/browser/web_contents_observer.h"
58 #include "content/public/common/resource_request_body.h" 60 #include "content/public/common/resource_request_body.h"
59 #include "content/public/test/browser_test_utils.h" 61 #include "content/public/test/browser_test_utils.h"
60 #include "content/public/test/download_test_observer.h" 62 #include "content/public/test/download_test_observer.h"
61 #include "content/public/test/test_navigation_observer.h" 63 #include "content/public/test/test_navigation_observer.h"
62 #include "content/public/test/test_utils.h" 64 #include "content/public/test/test_utils.h"
63 #include "device/geolocation/geolocation_provider.h" 65 #include "device/geolocation/geolocation_provider.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 BrowserAddedObserver observer; 98 BrowserAddedObserver observer;
97 new_browser = observer.WaitForSingleNewBrowser(); 99 new_browser = observer.WaitForSingleNewBrowser();
98 // The new browser should never be in |excluded_browsers|. 100 // The new browser should never be in |excluded_browsers|.
99 DCHECK(!base::ContainsKey(excluded_browsers, new_browser)); 101 DCHECK(!base::ContainsKey(excluded_browsers, new_browser));
100 } 102 }
101 return new_browser; 103 return new_browser;
102 } 104 }
103 105
104 class AppModalDialogWaiter : public app_modal::AppModalDialogObserver { 106 class AppModalDialogWaiter : public app_modal::AppModalDialogObserver {
105 public: 107 public:
106 AppModalDialogWaiter() 108 AppModalDialogWaiter() : dialog_(nullptr) {}
107 : dialog_(NULL) { 109 ~AppModalDialogWaiter() override {}
108 }
109 ~AppModalDialogWaiter() override {
110 }
111 110
112 app_modal::AppModalDialog* Wait() { 111 app_modal::AppModalDialog* Wait() {
113 if (dialog_) 112 if (dialog_)
114 return dialog_; 113 return dialog_;
115 message_loop_runner_ = new content::MessageLoopRunner; 114 message_loop_runner_ = new content::MessageLoopRunner;
116 message_loop_runner_->Run(); 115 message_loop_runner_->Run();
117 EXPECT_TRUE(dialog_); 116 EXPECT_TRUE(dialog_);
118 return dialog_; 117 return dialog_;
119 } 118 }
120 119
121 // AppModalDialogWaiter: 120 // AppModalDialogObserver:
122 void Notify(app_modal::AppModalDialog* dialog) override { 121 void Notify(app_modal::AppModalDialog* dialog) override {
123 DCHECK(!dialog_); 122 DCHECK(!dialog_);
124 dialog_ = dialog; 123 dialog_ = dialog;
124 CheckForHangMonitorDisabling(dialog);
125 if (message_loop_runner_.get() && message_loop_runner_->loop_running()) 125 if (message_loop_runner_.get() && message_loop_runner_->loop_running())
126 message_loop_runner_->Quit(); 126 message_loop_runner_->Quit();
127 } 127 }
128 128
129 static void CheckForHangMonitorDisabling(app_modal::AppModalDialog* dialog) {
130 // If a test waits for a beforeunload dialog but hasn't disabled the
131 // beforeunload hang timer before triggering it, there will be a race
132 // between the dialog and the timer and the test will be flaky. We can't
133 // disable the timer here, as it's too late, but we can tell when we've won
134 // a race that we shouldn't have been in.
135 if (!dialog->IsJavaScriptModalDialog())
136 return;
137
138 auto* js_dialog = static_cast<app_modal::JavaScriptAppModalDialog*>(dialog);
139 if (!js_dialog->is_before_unload_dialog())
140 return;
141
142 // Unfortunately we don't know which frame spawned this dialog and should
143 // have the hang monitor disabled, so we cheat a bit and search for *a*
144 // frame with the hang monitor disabled. The failure case that's worrisome
145 // is someone who doesn't know the requirement to disable the hang monitor,
146 // and this will catch that case.
147 auto* contents = dialog->web_contents();
148 for (auto* frame : contents->GetAllFrames())
149 if (frame->IsBeforeUnloadHangMonitorDisabledForTesting())
150 return;
151
152 FAIL() << "If waiting for a beforeunload dialog, the beforeunload timer "
153 "must be disabled on the spawning frame to avoid flakiness.";
154 }
155
129 private: 156 private:
130 app_modal::AppModalDialog* dialog_; 157 app_modal::AppModalDialog* dialog_;
131 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; 158 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
132 159
133 DISALLOW_COPY_AND_ASSIGN(AppModalDialogWaiter); 160 DISALLOW_COPY_AND_ASSIGN(AppModalDialogWaiter);
134 }; 161 };
135 162
136 } // namespace 163 } // namespace
137 164
138 bool GetCurrentTabTitle(const Browser* browser, base::string16* title) { 165 bool GetCurrentTabTitle(const Browser* browser, base::string16* title) {
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 for (size_t tmp_itr = match; tmp_itr < src_size; ++tmp_itr) 329 for (size_t tmp_itr = match; tmp_itr < src_size; ++tmp_itr)
303 *build_dir = build_dir->Append(FILE_PATH_LITERAL("..")); 330 *build_dir = build_dir->Append(FILE_PATH_LITERAL(".."));
304 for (; match < exe_size; ++match) 331 for (; match < exe_size; ++match)
305 *build_dir = build_dir->Append(exe_parts[match]); 332 *build_dir = build_dir->Append(exe_parts[match]);
306 return true; 333 return true;
307 } 334 }
308 335
309 app_modal::AppModalDialog* WaitForAppModalDialog() { 336 app_modal::AppModalDialog* WaitForAppModalDialog() {
310 app_modal::AppModalDialogQueue* dialog_queue = 337 app_modal::AppModalDialogQueue* dialog_queue =
311 app_modal::AppModalDialogQueue::GetInstance(); 338 app_modal::AppModalDialogQueue::GetInstance();
312 if (dialog_queue->HasActiveDialog()) 339 if (dialog_queue->HasActiveDialog()) {
340 AppModalDialogWaiter::CheckForHangMonitorDisabling(
341 dialog_queue->active_dialog());
313 return dialog_queue->active_dialog(); 342 return dialog_queue->active_dialog();
343 }
314 AppModalDialogWaiter waiter; 344 AppModalDialogWaiter waiter;
315 return waiter.Wait(); 345 return waiter.Wait();
316 } 346 }
317 347
318 int FindInPage(WebContents* tab, 348 int FindInPage(WebContents* tab,
319 const base::string16& search_string, 349 const base::string16& search_string,
320 bool forward, 350 bool forward,
321 bool match_case, 351 bool match_case,
322 int* ordinal, 352 int* ordinal,
323 gfx::Rect* selection_rect) { 353 gfx::Rect* selection_rect) {
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 if (browser != browser_) 592 if (browser != browser_)
563 return; 593 return;
564 594
565 observed_ = true; 595 observed_ = true;
566 BrowserList::RemoveObserver(this); 596 BrowserList::RemoveObserver(this);
567 if (message_loop_runner_.get() && message_loop_runner_->loop_running()) 597 if (message_loop_runner_.get() && message_loop_runner_->loop_running())
568 message_loop_runner_->Quit(); 598 message_loop_runner_->Quit();
569 } 599 }
570 600
571 } // namespace ui_test_utils 601 } // namespace ui_test_utils
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698