[M120 Migration]Fix for crash during chrome exit
[platform/framework/web/chromium-efl.git] / chrome / browser / crash_recovery_browsertest.cc
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <utility>
6
7 #include "base/base_switches.h"
8 #include "base/command_line.h"
9 #include "base/files/file_path.h"
10 #include "base/functional/bind.h"
11 #include "base/strings/stringprintf.h"
12 #include "build/build_config.h"
13 #include "build/chromeos_buildflags.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_commands.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model.h"
17 #include "chrome/common/url_constants.h"
18 #include "chrome/test/base/in_process_browser_test.h"
19 #include "chrome/test/base/ui_test_utils.h"
20 #include "content/public/browser/navigation_controller.h"
21 #include "content/public/browser/navigation_entry.h"
22 #include "content/public/browser/render_frame_host.h"
23 #include "content/public/browser/render_process_host.h"
24 #include "content/public/browser/render_widget_host_view.h"
25 #include "content/public/browser/web_contents.h"
26 #include "content/public/test/browser_test.h"
27 #include "content/public/test/browser_test_utils.h"
28 #include "content/public/test/no_renderer_crashes_assertion.h"
29 #include "net/test/embedded_test_server/embedded_test_server.h"
30 #include "net/test/embedded_test_server/http_request.h"
31 #include "net/test/embedded_test_server/http_response.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33 #include "third_party/blink/public/common/chrome_debug_urls.h"
34 #include "ui/base/page_transition_types.h"
35
36 using content::OpenURLParams;
37 using content::Referrer;
38 using content::WebContents;
39
40 // TODO(jam): http://crbug.com/350550
41 #if !(BUILDFLAG(IS_CHROMEOS_ASH) && defined(ADDRESS_SANITIZER))
42
43 namespace {
44
45 void SimulateRendererCrash(Browser* browser) {
46   content::RenderProcessHostWatcher crash_observer(
47       browser->tab_strip_model()->GetActiveWebContents(),
48       content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
49   browser->OpenURL(OpenURLParams(GURL(blink::kChromeUICrashURL), Referrer(),
50                                  WindowOpenDisposition::CURRENT_TAB,
51                                  ui::PAGE_TRANSITION_TYPED, false));
52   crash_observer.Wait();
53 }
54
55 // A request handler which returns a different result each time but stays fresh
56 // into the far future.
57 class CacheMaxAgeHandler {
58  public:
59   explicit CacheMaxAgeHandler(const std::string& path)
60       : path_(path), request_count_(0) { }
61
62   CacheMaxAgeHandler(const CacheMaxAgeHandler&) = delete;
63   CacheMaxAgeHandler& operator=(const CacheMaxAgeHandler&) = delete;
64
65   std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
66       const net::test_server::HttpRequest& request) {
67     if (request.relative_url != path_)
68       return nullptr;
69
70     request_count_++;
71     std::unique_ptr<net::test_server::BasicHttpResponse> response(
72         new net::test_server::BasicHttpResponse);
73     response->set_content(base::StringPrintf("<title>%d</title>",
74                                              request_count_));
75     response->set_content_type("text/html");
76     response->AddCustomHeader("Cache-Control", "max-age=99999");
77     return std::move(response);
78   }
79  private:
80   std::string path_;
81   int request_count_;
82 };
83
84 class CrashRecoveryBrowserTest : public InProcessBrowserTest {
85  protected:
86   WebContents* GetActiveWebContents() {
87     return browser()->tab_strip_model()->GetActiveWebContents();
88   }
89
90  private:
91   void SetUpCommandLine(base::CommandLine* command_line) override {
92     command_line->AppendSwitch(switches::kDisableBreakpad);
93   }
94
95   content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes_;
96 };
97
98 // Test that reload works after a crash.
99 IN_PROC_BROWSER_TEST_F(CrashRecoveryBrowserTest, Reload) {
100   // The title of the active tab should change each time this URL is loaded.
101   GURL url(
102       "data:text/html,<script>document.title=new Date().valueOf()</script>");
103   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
104
105   std::u16string title_before_crash;
106   std::u16string title_after_crash;
107
108   ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
109                                                 &title_before_crash));
110   SimulateRendererCrash(browser());
111   chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
112   EXPECT_TRUE(content::WaitForLoadStop(GetActiveWebContents()));
113   ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
114                                                 &title_after_crash));
115   EXPECT_NE(title_before_crash, title_after_crash);
116   ASSERT_TRUE(
117       GetActiveWebContents()->GetPrimaryMainFrame()->GetView()->IsShowing());
118   ASSERT_FALSE(GetActiveWebContents()
119                    ->GetPrimaryMainFrame()
120                    ->GetProcess()
121                    ->IsProcessBackgrounded());
122 }
123
124 // Test that reload after a crash forces a cache revalidation.
125 IN_PROC_BROWSER_TEST_F(CrashRecoveryBrowserTest, ReloadCacheRevalidate) {
126   const char kTestPath[] = "/test";
127
128   // Use the test server so as not to bypass cache behavior. The title of the
129   // active tab should change only when this URL is reloaded.
130   embedded_test_server()->RegisterRequestHandler(
131       base::BindRepeating(&CacheMaxAgeHandler::HandleRequest,
132                           base::Owned(new CacheMaxAgeHandler(kTestPath))));
133   ASSERT_TRUE(embedded_test_server()->Start());
134   ASSERT_TRUE(ui_test_utils::NavigateToURL(
135       browser(), embedded_test_server()->GetURL(kTestPath)));
136
137   std::u16string title_before_crash;
138   std::u16string title_after_crash;
139
140   ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
141                                                 &title_before_crash));
142   SimulateRendererCrash(browser());
143   chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
144   EXPECT_TRUE(content::WaitForLoadStop(GetActiveWebContents()));
145   ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
146                                                 &title_after_crash));
147   EXPECT_NE(title_before_crash, title_after_crash);
148 }
149
150 // Tests that loading a crashed page in a new tab correctly updates the title.
151 // There was an earlier bug (1270510) in process-per-site in which the max page
152 // ID of the RenderProcessHost was stale, so the NavigationEntry in the new tab
153 // was not committed.  This prevents regression of that bug.
154 IN_PROC_BROWSER_TEST_F(CrashRecoveryBrowserTest, LoadInNewTab) {
155   const base::FilePath::CharType kTitle2File[] =
156       FILE_PATH_LITERAL("title2.html");
157
158   GURL url(ui_test_utils::GetTestUrl(
159       base::FilePath(base::FilePath::kCurrentDirectory),
160       base::FilePath(kTitle2File)));
161   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
162
163   std::u16string title_before_crash;
164   std::u16string title_after_crash;
165
166   ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
167                                                 &title_before_crash));
168   SimulateRendererCrash(browser());
169   ASSERT_EQ(GURL(blink::kChromeUICrashURL), GetActiveWebContents()
170                                                 ->GetController()
171                                                 .GetVisibleEntry()
172                                                 ->GetVirtualURL());
173   chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
174   EXPECT_TRUE(content::WaitForLoadStop(GetActiveWebContents()));
175   ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(),
176                                                 &title_after_crash));
177   EXPECT_EQ(title_before_crash, title_after_crash);
178 }
179
180 // Tests that reloads of navigation errors behave correctly after a crash.
181 // Regression test for http://crbug.com/348918
182 IN_PROC_BROWSER_TEST_F(CrashRecoveryBrowserTest, DoubleReloadWithError) {
183   GURL url(content::GetWebUIURL("bogus"));
184   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
185   ASSERT_EQ(url, GetActiveWebContents()->GetVisibleURL());
186
187   SimulateRendererCrash(browser());
188
189   chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
190   EXPECT_FALSE(content::WaitForLoadStop(GetActiveWebContents()));
191   ASSERT_EQ(url, GetActiveWebContents()->GetVisibleURL());
192
193   chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB);
194   EXPECT_FALSE(content::WaitForLoadStop(GetActiveWebContents()));
195   ASSERT_EQ(url, GetActiveWebContents()->GetVisibleURL());
196 }
197
198 // Tests that a beforeunload handler doesn't run if user navigates to
199 // chrome::crash.
200 IN_PROC_BROWSER_TEST_F(CrashRecoveryBrowserTest, BeforeUnloadNotRun) {
201   const char* kBeforeUnloadHTML =
202     "<html><body>"
203     "<script>window.onbeforeunload=function(e){return 'foo'}</script>"
204     "</body></html>";
205   GURL url(std::string("data:text/html,") + kBeforeUnloadHTML);
206   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
207   SimulateRendererCrash(browser());
208 }
209
210 }  // namespace
211
212 #endif