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

Side by Side Diff: content/browser/frame_host/render_frame_host_impl_browsertest.cc

Issue 2738943002: Move beforeunload hang timer duties to its own timer. (Closed)
Patch Set: better test Created 3 years, 9 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "content/browser/frame_host/render_frame_host_impl.h" 5 #include "content/browser/frame_host/render_frame_host_impl.h"
6 6
7 #include "base/macros.h" 7 #include "base/macros.h"
8 #include "content/browser/web_contents/web_contents_impl.h" 8 #include "content/browser/web_contents/web_contents_impl.h"
9 #include "content/common/frame_messages.h"
10 #include "content/public/browser/javascript_dialog_manager.h"
9 #include "content/public/browser/render_frame_host.h" 11 #include "content/public/browser/render_frame_host.h"
10 #include "content/public/browser/web_contents.h" 12 #include "content/public/browser/web_contents.h"
11 #include "content/public/common/content_client.h" 13 #include "content/public/common/content_client.h"
14 #include "content/public/test/browser_test_utils.h"
12 #include "content/public/test/content_browser_test.h" 15 #include "content/public/test/content_browser_test.h"
13 #include "content/public/test/content_browser_test_utils.h" 16 #include "content/public/test/content_browser_test_utils.h"
14 #include "content/public/test/test_utils.h" 17 #include "content/public/test/test_utils.h"
15 #include "content/shell/browser/shell.h" 18 #include "content/shell/browser/shell.h"
16 #include "content/test/test_content_browser_client.h" 19 #include "content/test/test_content_browser_client.h"
17 20
18 namespace content { 21 namespace content {
19 22
20 namespace { 23 namespace {
21 24
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 EXPECT_EQ(blink::WebPageVisibilityStateVisible, 152 EXPECT_EQ(blink::WebPageVisibilityStateVisible,
150 web_contents->GetMainFrame()->GetVisibilityState()); 153 web_contents->GetMainFrame()->GetVisibilityState());
151 154
152 new_client.EnableVisibilityOverride(blink::WebPageVisibilityStatePrerender); 155 new_client.EnableVisibilityOverride(blink::WebPageVisibilityStatePrerender);
153 EXPECT_EQ(blink::WebPageVisibilityStatePrerender, 156 EXPECT_EQ(blink::WebPageVisibilityStatePrerender,
154 web_contents->GetMainFrame()->GetVisibilityState()); 157 web_contents->GetMainFrame()->GetVisibilityState());
155 158
156 SetBrowserClientForTesting(old_client); 159 SetBrowserClientForTesting(old_client);
157 } 160 }
158 161
162 namespace {
163
164 class TestJavaScriptDialogManager : public JavaScriptDialogManager,
165 public WebContentsDelegate {
166 public:
167 TestJavaScriptDialogManager() : message_loop_runner_(new MessageLoopRunner) {}
168 ~TestJavaScriptDialogManager() override {}
169
170 void Wait() {
171 message_loop_runner_->Run();
172 message_loop_runner_ = new MessageLoopRunner;
173 }
174
175 DialogClosedCallback& callback() { return callback_; }
176
177 // WebContentsDelegate
178
179 JavaScriptDialogManager* GetJavaScriptDialogManager(
180 WebContents* source) override {
181 return this;
182 }
183
184 // JavaScriptDialogManager
185
186 void RunJavaScriptDialog(WebContents* web_contents,
187 const GURL& origin_url,
188 JavaScriptDialogType dialog_type,
189 const base::string16& message_text,
190 const base::string16& default_prompt_text,
191 const DialogClosedCallback& callback,
192 bool* did_suppress_message) override {}
193
194 void RunBeforeUnloadDialog(WebContents* web_contents,
195 bool is_reload,
196 const DialogClosedCallback& callback) override {
197 callback_ = callback;
198 message_loop_runner_->Quit();
199 }
200
201 bool HandleJavaScriptDialog(WebContents* web_contents,
202 bool accept,
203 const base::string16* prompt_override) override {
204 return true;
205 }
206
207 void CancelDialogs(WebContents* web_contents, bool reset_state) override {}
208
209 private:
210 DialogClosedCallback callback_;
211
212 // The MessageLoopRunner used to spin the message loop.
213 scoped_refptr<MessageLoopRunner> message_loop_runner_;
214
215 DISALLOW_COPY_AND_ASSIGN(TestJavaScriptDialogManager);
216 };
217
218 class DropBeforeUnloadACKFilter : public BrowserMessageFilter {
219 public:
220 DropBeforeUnloadACKFilter() : BrowserMessageFilter(FrameMsgStart) {}
221
222 protected:
223 ~DropBeforeUnloadACKFilter() override {}
224
225 private:
226 // BrowserMessageFilter:
227 bool OnMessageReceived(const IPC::Message& message) override {
228 return message.type() == FrameHostMsg_BeforeUnload_ACK::ID;
229 }
230
231 DISALLOW_COPY_AND_ASSIGN(DropBeforeUnloadACKFilter);
232 };
233
234 } // namespace
235
236 // Tests that a beforeunload dialog in an iframe doesn't stop the beforeunload
237 // timer of a parent frame.
238 IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
239 IframeBeforeUnloadParentHang) {
240 WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
241 TestJavaScriptDialogManager dialog_manager;
242 wc->SetDelegate(&dialog_manager);
243
244 EXPECT_TRUE(NavigateToURL(shell(), GURL("about:blank")));
245 // Make an iframe with a beforeunload handler.
246 std::string script =
247 "var iframe = document.createElement('iframe');"
248 "document.body.appendChild(iframe);"
249 "iframe.contentWindow.onbeforeunload=function(e){return 'x'};";
250 EXPECT_TRUE(content::ExecuteScript(wc, script));
251 EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
252
253 // Force a process switch by going to a privileged page. The beforeunload
254 // timer will be started on the top-level frame but will be paused while the
255 // beforeunload dialog is shown by the subframe.
256 GURL web_ui_page(std::string(kChromeUIScheme) + "://" +
257 std::string(kChromeUIGpuHost));
258 shell()->LoadURL(web_ui_page);
259 dialog_manager.Wait();
260
261 RenderFrameHostImpl* main_frame =
262 static_cast<RenderFrameHostImpl*>(wc->GetMainFrame());
263 EXPECT_TRUE(main_frame->is_waiting_for_beforeunload_ack());
264
265 // Set up a filter to make sure that when the dialog is answered below and the
266 // renderer sends the beforeunload ACK, it gets... ahem... lost.
267 scoped_refptr<DropBeforeUnloadACKFilter> filter =
268 new DropBeforeUnloadACKFilter();
269 main_frame->GetProcess()->AddFilter(filter.get());
270
271 // Answer the dialog.
272 dialog_manager.callback().Run(true, base::string16());
273
274 // There will be no beforeunload ACK, so if the beforeunload ACK timer isn't
275 // functioning then the navigation will hang forever and this test will time
276 // out. If this waiting for the load stop works, this test won't time out.
277 EXPECT_TRUE(WaitForLoadStop(wc));
278 EXPECT_EQ(web_ui_page, wc->GetLastCommittedURL());
279
280 wc->SetDelegate(nullptr);
281 wc->SetJavaScriptDialogManagerForTesting(nullptr);
282 }
283
159 } // namespace content 284 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/frame_host/render_frame_host_impl.cc ('k') | content/browser/renderer_host/render_widget_host_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698