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