Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / renderer_host / render_process_host_browsertest.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
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 "base/command_line.h"
6 #include "content/browser/renderer_host/render_process_host_impl.h"
7 #include "content/common/child_process_messages.h"
8 #include "content/public/browser/render_process_host.h"
9 #include "content/public/browser/render_process_host_observer.h"
10 #include "content/public/browser/render_view_host.h"
11 #include "content/public/browser/web_contents.h"
12 #include "content/public/common/content_switches.h"
13 #include "content/public/common/url_constants.h"
14 #include "content/public/test/content_browser_test.h"
15 #include "content/public/test/content_browser_test_utils.h"
16 #include "content/shell/browser/shell.h"
17 #include "net/test/embedded_test_server/embedded_test_server.h"
18
19 #if defined(OS_WIN)
20 #include "base/win/windows_version.h"
21 #endif
22
23 namespace content {
24 namespace {
25
26 int RenderProcessHostCount() {
27   content::RenderProcessHost::iterator hosts =
28       content::RenderProcessHost::AllHostsIterator();
29   int count = 0;
30   while (!hosts.IsAtEnd()) {
31     if (hosts.GetCurrentValue()->HasConnection())
32       count++;
33     hosts.Advance();
34   }
35   return count;
36 }
37
38 class RenderProcessHostTest : public ContentBrowserTest,
39                               public RenderProcessHostObserver {
40  public:
41   RenderProcessHostTest() : process_exits_(0), host_destructions_(0) {}
42
43  protected:
44   // RenderProcessHostObserver:
45   void RenderProcessExited(RenderProcessHost* host,
46                            base::TerminationStatus status,
47                            int exit_code) override {
48     ++process_exits_;
49   }
50   void RenderProcessHostDestroyed(RenderProcessHost* host) override {
51     ++host_destructions_;
52   }
53
54   int process_exits_;
55   int host_destructions_;
56 };
57
58 // Sometimes the renderer process's ShutdownRequest (corresponding to the
59 // ViewMsg_WasSwappedOut from a previous navigation) doesn't arrive until after
60 // the browser process decides to re-use the renderer for a new purpose.  This
61 // test makes sure the browser doesn't let the renderer die in that case.  See
62 // http://crbug.com/87176.
63 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
64                        ShutdownRequestFromActiveTabIgnored) {
65   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
66
67   GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
68   NavigateToURL(shell(), test_url);
69   RenderProcessHost* rph =
70       shell()->web_contents()->GetRenderViewHost()->GetProcess();
71
72   host_destructions_ = 0;
73   process_exits_ = 0;
74   rph->AddObserver(this);
75   ChildProcessHostMsg_ShutdownRequest msg;
76   rph->OnMessageReceived(msg);
77
78   // If the RPH sends a mistaken ChildProcessMsg_Shutdown, the renderer process
79   // will take some time to die. Wait for a second tab to load in order to give
80   // that time to happen.
81   NavigateToURL(CreateBrowser(), test_url);
82
83   EXPECT_EQ(0, process_exits_);
84   if (!host_destructions_)
85     rph->RemoveObserver(this);
86 }
87
88 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
89                        GuestsAreNotSuitableHosts) {
90   // Set max renderers to 1 to force running out of processes.
91   content::RenderProcessHost::SetMaxRendererProcessCount(1);
92
93   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
94
95   GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
96   NavigateToURL(shell(), test_url);
97   RenderProcessHost* rph =
98       shell()->web_contents()->GetRenderViewHost()->GetProcess();
99   // Make it believe it's a guest.
100   reinterpret_cast<RenderProcessHostImpl*>(rph)->
101       set_is_isolated_guest_for_testing(true);
102   EXPECT_EQ(1, RenderProcessHostCount());
103
104   // Navigate to a different page.
105   GURL::Replacements replace_host;
106   std::string host_str("localhost");  // Must stay in scope with replace_host.
107   replace_host.SetHostStr(host_str);
108   GURL another_url = embedded_test_server()->GetURL("/simple_page.html");
109   another_url = another_url.ReplaceComponents(replace_host);
110   NavigateToURL(CreateBrowser(), another_url);
111
112   // Expect that we got another process (the guest renderer was not reused).
113   EXPECT_EQ(2, RenderProcessHostCount());
114 }
115
116 class ShellCloser : public RenderProcessHostObserver {
117  public:
118   ShellCloser(Shell* shell, std::string* logging_string)
119       : shell_(shell), logging_string_(logging_string) {}
120
121  protected:
122   // RenderProcessHostObserver:
123   void RenderProcessExited(RenderProcessHost* host,
124                            base::TerminationStatus status,
125                            int exit_code) override {
126     logging_string_->append("ShellCloser::RenderProcessExited ");
127     shell_->Close();
128   }
129
130   void RenderProcessHostDestroyed(RenderProcessHost* host) override {
131     logging_string_->append("ShellCloser::RenderProcessHostDestroyed ");
132   }
133
134   Shell* shell_;
135   std::string* logging_string_;
136 };
137
138 class ObserverLogger : public RenderProcessHostObserver {
139  public:
140   explicit ObserverLogger(std::string* logging_string)
141       : logging_string_(logging_string), host_destroyed_(false) {}
142
143   bool host_destroyed() { return host_destroyed_; }
144
145  protected:
146   // RenderProcessHostObserver:
147   void RenderProcessExited(RenderProcessHost* host,
148                            base::TerminationStatus status,
149                            int exit_code) override {
150     logging_string_->append("ObserverLogger::RenderProcessExited ");
151   }
152
153   void RenderProcessHostDestroyed(RenderProcessHost* host) override {
154     logging_string_->append("ObserverLogger::RenderProcessHostDestroyed ");
155     host_destroyed_ = true;
156   }
157
158   std::string* logging_string_;
159   bool host_destroyed_;
160 };
161
162 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
163                        AllProcessExitedCallsBeforeAnyHostDestroyedCalls) {
164   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
165
166   GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
167   NavigateToURL(shell(), test_url);
168
169   std::string logging_string;
170   ShellCloser shell_closer(shell(), &logging_string);
171   ObserverLogger observer_logger(&logging_string);
172   RenderProcessHost* rph =
173       shell()->web_contents()->GetRenderViewHost()->GetProcess();
174
175   // Ensure that the ShellCloser observer is first, so that it will have first
176   // dibs on the ProcessExited callback.
177   rph->AddObserver(&shell_closer);
178   rph->AddObserver(&observer_logger);
179
180   // This will crash the render process, and start all the callbacks.
181   NavigateToURL(shell(), GURL(kChromeUICrashURL));
182
183   // The key here is that all the RenderProcessExited callbacks precede all the
184   // RenderProcessHostDestroyed callbacks.
185   EXPECT_EQ("ShellCloser::RenderProcessExited "
186             "ObserverLogger::RenderProcessExited "
187             "ShellCloser::RenderProcessHostDestroyed "
188             "ObserverLogger::RenderProcessHostDestroyed ", logging_string);
189
190   // If the test fails, and somehow the RPH is still alive somehow, at least
191   // deregister the observers so that the test fails and doesn't also crash.
192   if (!observer_logger.host_destroyed()) {
193     rph->RemoveObserver(&shell_closer);
194     rph->RemoveObserver(&observer_logger);
195   }
196 }
197
198 #if defined(OS_WIN)
199 // Provides functionality to test renderer processes with the Win32K lockdown
200 // process mitigation.
201 class Win32KLockdownRendererProcessHostTest : public RenderProcessHostTest {
202  public:
203   Win32KLockdownRendererProcessHostTest() {}
204
205   virtual ~Win32KLockdownRendererProcessHostTest() {}
206
207  protected:
208   virtual void SetUp() override {
209     base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
210     command_line->AppendSwitch(switches::kEnableWin32kRendererLockDown);
211     RenderProcessHostTest::SetUp();
212   }
213
214  private:
215   DISALLOW_COPY_AND_ASSIGN(Win32KLockdownRendererProcessHostTest);
216 };
217
218 // Tests whether navigation requests with the Win32K lockdown mitigation set
219 // work correctly.
220 IN_PROC_BROWSER_TEST_F(Win32KLockdownRendererProcessHostTest,
221                        RendererWin32KLockdownNavigationTest) {
222   if (base::win::GetVersion() < base::win::VERSION_WIN8)
223     return;
224
225   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
226
227   GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
228   NavigateToURL(shell(), test_url);
229
230   EXPECT_EQ(1, RenderProcessHostCount());
231   EXPECT_EQ(0, process_exits_);
232 }
233 #endif
234
235 }  // namespace
236 }  // namespace content