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

Side by Side Diff: content/browser/renderer_host/render_process_host_impl_unittest.cc

Issue 16267002: Re-fix http://crbug.com/87176, and add a test. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Second round of creis comments Created 7 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « content/browser/renderer_host/render_process_host_impl.cc ('k') | content/content_tests.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 "content/browser/renderer_host/render_process_host_impl.h"
6
7 #include "base/command_line.h"
8 #include "base/process_util.h"
9 #include "base/run_loop.h"
10 #include "content/browser/child_process_launcher.h"
11 #include "content/browser/loader/resource_dispatcher_host_impl.h"
12 #include "content/browser/site_instance_impl.h"
13 #include "content/browser/storage_partition_impl.h"
14 #include "content/browser/webui/web_ui_controller_factory_registry.h"
15 #include "content/common/child_process_messages.h"
16 #include "content/common/view_messages.h"
17 #include "content/public/browser/render_process_host_factory.h"
18 #include "content/public/common/sandboxed_process_launcher_delegate.h"
19 #include "content/public/test/test_browser_context.h"
20 #include "content/public/test/test_browser_thread.h"
21 #include "content/test/test_content_browser_client.h"
22 #include "content/test/test_render_view_host_factory.h"
23 #include "content/test/test_web_contents.h"
24 #include "ipc/ipc_switches.h"
25 #include "ipc/ipc_test_sink.h"
26 #include "net/url_request/url_request_test_util.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28
29 namespace content {
30 namespace {
31
32 class FakeChildProcessLauncher;
33
34 struct LaunchedChildProcess {
35 // Becomes NULL after the FakeChildProcessLauncher is destroyed.
36 FakeChildProcessLauncher* launcher_;
37 // Collects messages sent to the child process.
38 IPC::TestSink messages_;
39 };
40
41 class FakeChildProcessLauncher : public ChildProcessLauncher {
42 public:
43 FakeChildProcessLauncher(LaunchedChildProcess* info,
44 const IPC::ChannelHandle& channel,
45 Client* client)
46 : info_(info),
47 client_(client),
48 starting_(true),
49 termination_status_(base::TERMINATION_STATUS_NORMAL_TERMINATION),
50 channel_(new IPC::ChannelProxy(
51 channel,
52 IPC::Channel::MODE_CLIENT,
53 &info->messages_,
54 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))),
55 weak_this_factory_(this) {
56 info_->launcher_ = this;
57
58 // Automatically start the child process so the RenderProcessHostImpl sends
59 // messages to it. To mimic real child processes, don't start instantly.
60 base::MessageLoopProxy::current()->PostTask(
61 FROM_HERE,
62 base::Bind(&FakeChildProcessLauncher::Start,
63 weak_this_factory_.GetWeakPtr()));
64 }
65
66 virtual ~FakeChildProcessLauncher() { info_->launcher_ = NULL; }
67
68 void Send(IPC::Message* msg) {
69 EXPECT_TRUE(channel_->Send(msg));
70 }
71
72 Client* client() const { return client_; }
73
74 // Implementation of ChildProcessLauncher.
75 virtual bool IsStarting() OVERRIDE { return starting_; }
76 virtual base::ProcessHandle GetHandle() OVERRIDE {
77 return base::Process::Current().handle();
78 }
79 virtual base::TerminationStatus GetChildTerminationStatus(bool known_dead,
80 int* exit_code)
81 OVERRIDE {
82 return termination_status_;
83 }
84 virtual void SetProcessBackgrounded(bool background) OVERRIDE {}
85 virtual void SetTerminateChildOnShutdown(bool terminate_on_shutdown)
86 OVERRIDE {}
87
88 private:
89 void Start() {
90 starting_ = false;
91 client_->OnProcessLaunched();
92 }
93
94 LaunchedChildProcess* info_;
95 Client* client_;
96 bool starting_;
97 base::TerminationStatus termination_status_;
98 scoped_ptr<IPC::ChannelProxy> channel_;
99 base::WeakPtrFactory<FakeChildProcessLauncher> weak_this_factory_;
100 };
101
102 scoped_ptr<ChildProcessLauncher> NewFakeChildProcessLauncher(
103 ScopedVector<LaunchedChildProcess>* child_processes,
104 #if defined(OS_WIN)
105 SandboxedProcessLauncherDelegate* delegate,
106 #elif defined(OS_POSIX)
107 bool use_zygote,
108 const base::EnvironmentVector& environ,
109 int ipcfd,
110 #endif
111 CommandLine* cmd_line,
112 int child_process_id,
113 ChildProcessLauncher::Client* client) {
114 #if defined(OS_WIN)
115 delete delegate;
116 #endif
117 scoped_ptr<CommandLine> cmd_line_deleter(cmd_line);
118 child_processes->push_back(new LaunchedChildProcess());
119 std::string channel_id =
120 cmd_line->GetSwitchValueASCII(switches::kProcessChannelID);
121 return scoped_ptr<ChildProcessLauncher>(new FakeChildProcessLauncher(
122 child_processes->back(),
123 IPC::ChannelHandle(channel_id
124 #if defined(OS_POSIX)
125 ,
126 base::FileDescriptor(ipcfd, false)
127 #endif
128 ),
129 client));
130 }
131
132 class RPHIBrowserContext : public TestBrowserContext {
133 private:
134 virtual net::URLRequestContextGetter* GetRequestContextForRenderProcess(
135 int renderer_child_id) OVERRIDE {
136 return GetRequestContext();
137 }
138 };
139
140 class RPHIBrowserClient : public TestContentBrowserClient {
141 public:
142 RPHIBrowserClient()
143 : request_context_getter_(new net::TestURLRequestContextGetter(
144 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))) {}
145
146 virtual net::URLRequestContextGetter* CreateRequestContext(
147 BrowserContext* browser_context,
148 ProtocolHandlerMap* protocol_handlers) OVERRIDE {
149 return request_context_getter_.get();
150 }
151
152 private:
153 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
154 };
155
156 class FakeChildProcessRPHFactory : public RenderProcessHostFactory {
157 public:
158 FakeChildProcessRPHFactory(
159 ScopedVector<LaunchedChildProcess>* child_processes,
160 StoragePartitionImpl* storage_partition)
161 : child_processes_(child_processes),
162 storage_partition_(storage_partition) {
163 SiteInstanceImpl::set_render_process_host_factory(this);
164 }
165 virtual ~FakeChildProcessRPHFactory() {
166 SiteInstanceImpl::set_render_process_host_factory(NULL);
167 }
168
169 virtual RenderProcessHost* CreateRenderProcessHost(
170 BrowserContext* browser_context) const OVERRIDE {
171 RenderProcessHostImpl* host = new RenderProcessHostImpl(
172 browser_context, storage_partition_, false, false);
173 host->SetChildProcessLauncherFactory(
174 base::Bind(&NewFakeChildProcessLauncher, child_processes_));
175 return host;
176 }
177
178 private:
179 ScopedVector<LaunchedChildProcess>* child_processes_;
180 StoragePartitionImpl* storage_partition_;
181 };
182
183 class RenderProcessHostImplTest : public testing::Test {
184 public:
185 RenderProcessHostImplTest()
186 : ui_thread_(BrowserThread::UI, &message_loop_),
187 webkit_thread_(BrowserThread::WEBKIT_DEPRECATED, &message_loop_),
188 file_user_blocking_thread_(BrowserThread::FILE_USER_BLOCKING,
189 &message_loop_),
190 io_thread_(BrowserThread::IO, &message_loop_),
191 old_browser_client_(SetBrowserClientForTesting(&test_browser_client_)) {
192 }
193
194 virtual ~RenderProcessHostImplTest() {
195 base::RunLoop().RunUntilIdle();
196 SetBrowserClientForTesting(old_browser_client_);
197 }
198
199 protected:
200 ScopedVector<LaunchedChildProcess> child_processes_;
201 base::MessageLoopForIO message_loop_;
Jeffrey Yasskin 2013/06/05 22:53:20 I'll be able to replace this list of threads with
202 TestBrowserThread ui_thread_;
203 TestBrowserThread webkit_thread_;
204 TestBrowserThread file_user_blocking_thread_;
205 TestBrowserThread io_thread_;
206
207 RPHIBrowserContext browser_context_;
208 RPHIBrowserClient test_browser_client_;
209 ContentBrowserClient* old_browser_client_;
210 ResourceDispatcherHostImpl resource_dispatcher_host_;
211
212 DISALLOW_COPY_AND_ASSIGN(RenderProcessHostImplTest);
213 };
214
215 // http://crbug.com/87176
216 TEST_F(RenderProcessHostImplTest,
217 RejectShutdownFromChildProcessWithOneActiveView) {
218 const GURL kUrl("http://example.com");
219
220 scoped_refptr<SiteInstance> site(
221 SiteInstance::CreateForURL(&browser_context_, kUrl));
222 FakeChildProcessRPHFactory rph_factory(
223 &child_processes_,
224 static_cast<StoragePartitionImpl*>(
225 TestBrowserContext::GetStoragePartition(&browser_context_,
226 site.get())));
227
228 WebContents::CreateParams params(&browser_context_, site.get());
229 scoped_ptr<WebContentsImpl> tab(
230 WebContentsImpl::CreateWithOpener(params, NULL));
231 tab->GetController().LoadURL(kUrl, Referrer(), PAGE_TRANSITION_TYPED, "");
232 base::RunLoop().RunUntilIdle();
233 ASSERT_EQ(1U, child_processes_.size());
234
235 child_processes_[0]->messages_.ClearMessages();
236
237 RenderProcessHostImpl* tab_process =
238 static_cast<RenderProcessHostImpl*>(tab->GetSiteInstance()->GetProcess());
239 EXPECT_EQ(1, tab_process->GetActiveViewCount());
240 EXPECT_EQ(child_processes_[0]->launcher_->client(), tab_process);
241
242 // Sometimes the renderer process's ShutdownRequest (corresponding to the
243 // ViewMsg_WasSwappedOut from a previous navigation) doesn't arrive until
244 // after the browser process decides to re-use the renderer for a new purpose.
245 // This test makes sure the browser doesn't let the renderer die in that case.
246 child_processes_[0]->launcher_->
247 Send(new ChildProcessHostMsg_ShutdownRequest());
248 base::RunLoop().RunUntilIdle();
249 EXPECT_FALSE(child_processes_[0]->messages_.GetFirstMessageMatching(
250 ChildProcessMsg_Shutdown::ID))
251 << "Host sent a message confirming that the renderer process should shut "
252 << "down even though it was still being used.";
253 }
254
255 } // namespace
256 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/renderer_host/render_process_host_impl.cc ('k') | content/content_tests.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698