1 // Copyright (c) 2012 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.
5 #include "base/command_line.h"
6 #include "base/compiler_specific.h"
7 #include "base/memory/scoped_vector.h"
8 #include "base/strings/string16.h"
9 #include "content/browser/browser_thread_impl.h"
10 #include "content/browser/browsing_instance.h"
11 #include "content/browser/child_process_security_policy_impl.h"
12 #include "content/browser/frame_host/navigation_entry_impl.h"
13 #include "content/browser/renderer_host/render_process_host_impl.h"
14 #include "content/browser/renderer_host/render_view_host_impl.h"
15 #include "content/browser/site_instance_impl.h"
16 #include "content/browser/web_contents/web_contents_impl.h"
17 #include "content/browser/webui/web_ui_controller_factory_registry.h"
18 #include "content/public/common/content_client.h"
19 #include "content/public/common/content_constants.h"
20 #include "content/public/common/content_switches.h"
21 #include "content/public/common/url_constants.h"
22 #include "content/public/common/url_utils.h"
23 #include "content/public/test/mock_render_process_host.h"
24 #include "content/public/test/test_browser_context.h"
25 #include "content/public/test/test_browser_thread.h"
26 #include "content/test/test_content_browser_client.h"
27 #include "content/test/test_content_client.h"
28 #include "content/test/test_render_view_host.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "url/url_util.h"
35 const char kPrivilegedScheme
[] = "privileged";
37 class SiteInstanceTestWebUIControllerFactory
: public WebUIControllerFactory
{
39 WebUIController
* CreateWebUIControllerForURL(WebUI
* web_ui
,
40 const GURL
& url
) const override
{
43 WebUI::TypeID
GetWebUIType(BrowserContext
* browser_context
,
44 const GURL
& url
) const override
{
45 return WebUI::kNoWebUI
;
47 bool UseWebUIForURL(BrowserContext
* browser_context
,
48 const GURL
& url
) const override
{
49 return HasWebUIScheme(url
);
51 bool UseWebUIBindingsForURL(BrowserContext
* browser_context
,
52 const GURL
& url
) const override
{
53 return HasWebUIScheme(url
);
57 class SiteInstanceTestBrowserClient
: public TestContentBrowserClient
{
59 SiteInstanceTestBrowserClient()
60 : privileged_process_id_(-1) {
61 WebUIControllerFactory::RegisterFactory(&factory_
);
64 ~SiteInstanceTestBrowserClient() override
{
65 WebUIControllerFactory::UnregisterFactoryForTesting(&factory_
);
68 bool IsSuitableHost(RenderProcessHost
* process_host
,
69 const GURL
& site_url
) override
{
70 return (privileged_process_id_
== process_host
->GetID()) ==
71 site_url
.SchemeIs(kPrivilegedScheme
);
74 void set_privileged_process_id(int process_id
) {
75 privileged_process_id_
= process_id
;
79 SiteInstanceTestWebUIControllerFactory factory_
;
80 int privileged_process_id_
;
83 class SiteInstanceTest
: public testing::Test
{
86 : ui_thread_(BrowserThread::UI
, &message_loop_
),
87 file_user_blocking_thread_(BrowserThread::FILE_USER_BLOCKING
,
89 io_thread_(BrowserThread::IO
, &message_loop_
),
90 old_browser_client_(NULL
) {
93 void SetUp() override
{
94 old_browser_client_
= SetBrowserClientForTesting(&browser_client_
);
95 url::AddStandardScheme(kPrivilegedScheme
);
96 url::AddStandardScheme(kChromeUIScheme
);
98 SiteInstanceImpl::set_render_process_host_factory(&rph_factory_
);
101 void TearDown() override
{
102 // Ensure that no RenderProcessHosts are left over after the tests.
103 EXPECT_TRUE(RenderProcessHost::AllHostsIterator().IsAtEnd());
105 SetBrowserClientForTesting(old_browser_client_
);
106 SiteInstanceImpl::set_render_process_host_factory(NULL
);
108 // http://crbug.com/143565 found SiteInstanceTest leaking an
109 // AppCacheDatabase. This happens because some part of the test indirectly
110 // calls StoragePartitionImplMap::PostCreateInitialization(), which posts
111 // a task to the IO thread to create the AppCacheDatabase. Since the
112 // message loop is not running, the AppCacheDatabase ends up getting
113 // created when DrainMessageLoops() gets called at the end of a test case.
114 // Immediately after, the test case ends and the AppCacheDatabase gets
115 // scheduled for deletion. Here, call DrainMessageLoops() again so the
116 // AppCacheDatabase actually gets deleted.
120 void set_privileged_process_id(int process_id
) {
121 browser_client_
.set_privileged_process_id(process_id
);
124 void DrainMessageLoops() {
125 // We don't just do this in TearDown() because we create TestBrowserContext
126 // objects in each test, which will be destructed before
127 // TearDown() is called.
128 base::MessageLoop::current()->RunUntilIdle();
129 message_loop_
.RunUntilIdle();
133 base::MessageLoopForUI message_loop_
;
134 TestBrowserThread ui_thread_
;
135 TestBrowserThread file_user_blocking_thread_
;
136 TestBrowserThread io_thread_
;
138 SiteInstanceTestBrowserClient browser_client_
;
139 ContentBrowserClient
* old_browser_client_
;
140 MockRenderProcessHostFactory rph_factory_
;
143 // Subclass of BrowsingInstance that updates a counter when deleted and
144 // returns TestSiteInstances from GetSiteInstanceForURL.
145 class TestBrowsingInstance
: public BrowsingInstance
{
147 TestBrowsingInstance(BrowserContext
* browser_context
, int* delete_counter
)
148 : BrowsingInstance(browser_context
),
149 delete_counter_(delete_counter
) {
152 // Make a few methods public for tests.
153 using BrowsingInstance::browser_context
;
154 using BrowsingInstance::HasSiteInstance
;
155 using BrowsingInstance::GetSiteInstanceForURL
;
156 using BrowsingInstance::RegisterSiteInstance
;
157 using BrowsingInstance::UnregisterSiteInstance
;
160 ~TestBrowsingInstance() override
{ (*delete_counter_
)++; }
162 int* delete_counter_
;
165 // Subclass of SiteInstanceImpl that updates a counter when deleted.
166 class TestSiteInstance
: public SiteInstanceImpl
{
168 static TestSiteInstance
* CreateTestSiteInstance(
169 BrowserContext
* browser_context
,
170 int* site_delete_counter
,
171 int* browsing_delete_counter
) {
172 TestBrowsingInstance
* browsing_instance
=
173 new TestBrowsingInstance(browser_context
, browsing_delete_counter
);
174 return new TestSiteInstance(browsing_instance
, site_delete_counter
);
178 TestSiteInstance(BrowsingInstance
* browsing_instance
, int* delete_counter
)
179 : SiteInstanceImpl(browsing_instance
), delete_counter_(delete_counter
) {}
180 ~TestSiteInstance() override
{ (*delete_counter_
)++; }
182 int* delete_counter_
;
187 // Test to ensure no memory leaks for SiteInstance objects.
188 TEST_F(SiteInstanceTest
, SiteInstanceDestructor
) {
189 // The existence of this object will cause WebContentsImpl to create our
190 // test one instead of the real one.
191 RenderViewHostTestEnabler rvh_test_enabler
;
192 int site_delete_counter
= 0;
193 int browsing_delete_counter
= 0;
194 const GURL
url("test:foo");
196 // Ensure that instances are deleted when their NavigationEntries are gone.
197 TestSiteInstance
* instance
=
198 TestSiteInstance::CreateTestSiteInstance(NULL
, &site_delete_counter
,
199 &browsing_delete_counter
);
200 EXPECT_EQ(0, site_delete_counter
);
202 NavigationEntryImpl
* e1
= new NavigationEntryImpl(
203 instance
, 0, url
, Referrer(), base::string16(), ui::PAGE_TRANSITION_LINK
,
206 // Redundantly setting e1's SiteInstance shouldn't affect the ref count.
207 e1
->set_site_instance(instance
);
208 EXPECT_EQ(0, site_delete_counter
);
210 // Add a second reference
211 NavigationEntryImpl
* e2
= new NavigationEntryImpl(
212 instance
, 0, url
, Referrer(), base::string16(), ui::PAGE_TRANSITION_LINK
,
215 // Now delete both entries and be sure the SiteInstance goes away.
217 EXPECT_EQ(0, site_delete_counter
);
218 EXPECT_EQ(0, browsing_delete_counter
);
220 EXPECT_EQ(1, site_delete_counter
);
221 // instance is now deleted
222 EXPECT_EQ(1, browsing_delete_counter
);
223 // browsing_instance is now deleted
225 // Ensure that instances are deleted when their RenderViewHosts are gone.
226 scoped_ptr
<TestBrowserContext
> browser_context(new TestBrowserContext());
228 TestSiteInstance::CreateTestSiteInstance(browser_context
.get(),
229 &site_delete_counter
,
230 &browsing_delete_counter
);
232 scoped_ptr
<WebContentsImpl
> web_contents(static_cast<WebContentsImpl
*>(
233 WebContents::Create(WebContents::CreateParams(
234 browser_context
.get(), instance
))));
235 EXPECT_EQ(1, site_delete_counter
);
236 EXPECT_EQ(1, browsing_delete_counter
);
239 // Make sure that we flush any messages related to the above WebContentsImpl
243 EXPECT_EQ(2, site_delete_counter
);
244 EXPECT_EQ(2, browsing_delete_counter
);
245 // contents is now deleted, along with instance and browsing_instance
248 // Test that NavigationEntries with SiteInstances can be cloned, but that their
249 // SiteInstances can be changed afterwards. Also tests that the ref counts are
250 // updated properly after the change.
251 TEST_F(SiteInstanceTest
, CloneNavigationEntry
) {
252 int site_delete_counter1
= 0;
253 int site_delete_counter2
= 0;
254 int browsing_delete_counter
= 0;
255 const GURL
url("test:foo");
257 SiteInstanceImpl
* instance1
=
258 TestSiteInstance::CreateTestSiteInstance(NULL
, &site_delete_counter1
,
259 &browsing_delete_counter
);
260 SiteInstanceImpl
* instance2
=
261 TestSiteInstance::CreateTestSiteInstance(NULL
, &site_delete_counter2
,
262 &browsing_delete_counter
);
264 NavigationEntryImpl
* e1
= new NavigationEntryImpl(
265 instance1
, 0, url
, Referrer(), base::string16(), ui::PAGE_TRANSITION_LINK
,
268 NavigationEntryImpl
* e2
= e1
->Clone();
270 // Should be able to change the SiteInstance of the cloned entry.
271 e2
->set_site_instance(instance2
);
273 // The first SiteInstance should go away after deleting e1, since e2 should
274 // no longer be referencing it.
276 EXPECT_EQ(1, site_delete_counter1
);
277 EXPECT_EQ(0, site_delete_counter2
);
279 // The second SiteInstance should go away after deleting e2.
281 EXPECT_EQ(1, site_delete_counter1
);
282 EXPECT_EQ(1, site_delete_counter2
);
284 // Both BrowsingInstances are also now deleted
285 EXPECT_EQ(2, browsing_delete_counter
);
290 // Test to ensure GetProcess returns and creates processes correctly.
291 TEST_F(SiteInstanceTest
, GetProcess
) {
292 // Ensure that GetProcess returns a process.
293 scoped_ptr
<TestBrowserContext
> browser_context(new TestBrowserContext());
294 scoped_ptr
<RenderProcessHost
> host1
;
295 scoped_refptr
<SiteInstanceImpl
> instance(static_cast<SiteInstanceImpl
*>(
296 SiteInstance::Create(browser_context
.get())));
297 host1
.reset(instance
->GetProcess());
298 EXPECT_TRUE(host1
.get() != NULL
);
300 // Ensure that GetProcess creates a new process.
301 scoped_refptr
<SiteInstanceImpl
> instance2(static_cast<SiteInstanceImpl
*>(
302 SiteInstance::Create(browser_context
.get())));
303 scoped_ptr
<RenderProcessHost
> host2(instance2
->GetProcess());
304 EXPECT_TRUE(host2
.get() != NULL
);
305 EXPECT_NE(host1
.get(), host2
.get());
310 // Test to ensure SetSite and site() work properly.
311 TEST_F(SiteInstanceTest
, SetSite
) {
312 scoped_refptr
<SiteInstanceImpl
> instance(static_cast<SiteInstanceImpl
*>(
313 SiteInstance::Create(NULL
)));
314 EXPECT_FALSE(instance
->HasSite());
315 EXPECT_TRUE(instance
->GetSiteURL().is_empty());
317 instance
->SetSite(GURL("http://www.google.com/index.html"));
318 EXPECT_EQ(GURL("http://google.com"), instance
->GetSiteURL());
320 EXPECT_TRUE(instance
->HasSite());
325 // Test to ensure GetSiteForURL properly returns sites for URLs.
326 TEST_F(SiteInstanceTest
, GetSiteForURL
) {
327 // Pages are irrelevant.
328 GURL test_url
= GURL("http://www.google.com/index.html");
329 GURL site_url
= SiteInstanceImpl::GetSiteForURL(NULL
, test_url
);
330 EXPECT_EQ(GURL("http://google.com"), site_url
);
331 EXPECT_EQ("http", site_url
.scheme());
332 EXPECT_EQ("google.com", site_url
.host());
334 // Ports are irrlevant.
335 test_url
= GURL("https://www.google.com:8080");
336 site_url
= SiteInstanceImpl::GetSiteForURL(NULL
, test_url
);
337 EXPECT_EQ(GURL("https://google.com"), site_url
);
339 // Hostnames without TLDs are ok.
340 test_url
= GURL("http://foo/a.html");
341 site_url
= SiteInstanceImpl::GetSiteForURL(NULL
, test_url
);
342 EXPECT_EQ(GURL("http://foo"), site_url
);
343 EXPECT_EQ("foo", site_url
.host());
345 // File URLs should include the scheme.
346 test_url
= GURL("file:///C:/Downloads/");
347 site_url
= SiteInstanceImpl::GetSiteForURL(NULL
, test_url
);
348 EXPECT_EQ(GURL("file:"), site_url
);
349 EXPECT_EQ("file", site_url
.scheme());
350 EXPECT_FALSE(site_url
.has_host());
352 // Some file URLs have hosts in the path.
353 test_url
= GURL("file://server/path");
354 site_url
= SiteInstanceImpl::GetSiteForURL(NULL
, test_url
);
355 EXPECT_EQ(GURL("file://server"), site_url
);
356 EXPECT_EQ("server", site_url
.host());
358 // Data URLs should include the scheme.
359 test_url
= GURL("data:text/html,foo");
360 site_url
= SiteInstanceImpl::GetSiteForURL(NULL
, test_url
);
361 EXPECT_EQ(GURL("data:"), site_url
);
362 EXPECT_EQ("data", site_url
.scheme());
363 EXPECT_FALSE(site_url
.has_host());
365 // Javascript URLs should include the scheme.
366 test_url
= GURL("javascript:foo();");
367 site_url
= SiteInstanceImpl::GetSiteForURL(NULL
, test_url
);
368 EXPECT_EQ(GURL("javascript:"), site_url
);
369 EXPECT_EQ("javascript", site_url
.scheme());
370 EXPECT_FALSE(site_url
.has_host());
372 // Guest URLs are special and need to have the path in the site as well,
373 // since it affects the StoragePartition configuration.
374 std::string
guest_url(kGuestScheme
);
375 guest_url
.append("://abc123/path");
376 test_url
= GURL(guest_url
);
377 site_url
= SiteInstanceImpl::GetSiteForURL(NULL
, test_url
);
378 EXPECT_EQ(test_url
, site_url
);
383 // Test of distinguishing URLs from different sites. Most of this logic is
384 // tested in RegistryControlledDomainTest. This test focuses on URLs with
385 // different schemes or ports.
386 TEST_F(SiteInstanceTest
, IsSameWebSite
) {
387 GURL url_foo
= GURL("http://foo/a.html");
388 GURL url_foo2
= GURL("http://foo/b.html");
389 GURL url_foo_https
= GURL("https://foo/a.html");
390 GURL url_foo_port
= GURL("http://foo:8080/a.html");
391 GURL url_javascript
= GURL("javascript:alert(1);");
392 GURL url_blank
= GURL(url::kAboutBlankURL
);
394 // Same scheme and port -> same site.
395 EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL
, url_foo
, url_foo2
));
397 // Different scheme -> different site.
398 EXPECT_FALSE(SiteInstance::IsSameWebSite(NULL
, url_foo
, url_foo_https
));
400 // Different port -> same site.
401 // (Changes to document.domain make renderer ignore the port.)
402 EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL
, url_foo
, url_foo_port
));
404 // JavaScript links should be considered same site for anything.
405 EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL
, url_javascript
, url_foo
));
406 EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL
, url_javascript
, url_foo_https
));
407 EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL
, url_javascript
, url_foo_port
));
409 // Navigating to a blank page is considered the same site.
410 EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL
, url_foo
, url_blank
));
411 EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL
, url_foo_https
, url_blank
));
412 EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL
, url_foo_port
, url_blank
));
414 // Navigating from a blank site is not considered to be the same site.
415 EXPECT_FALSE(SiteInstance::IsSameWebSite(NULL
, url_blank
, url_foo
));
416 EXPECT_FALSE(SiteInstance::IsSameWebSite(NULL
, url_blank
, url_foo_https
));
417 EXPECT_FALSE(SiteInstance::IsSameWebSite(NULL
, url_blank
, url_foo_port
));
422 // Test to ensure that there is only one SiteInstance per site in a given
423 // BrowsingInstance, when process-per-site is not in use.
424 TEST_F(SiteInstanceTest
, OneSiteInstancePerSite
) {
425 ASSERT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch(
426 switches::kProcessPerSite
));
427 int delete_counter
= 0;
428 scoped_ptr
<TestBrowserContext
> browser_context(new TestBrowserContext());
429 TestBrowsingInstance
* browsing_instance
=
430 new TestBrowsingInstance(browser_context
.get(), &delete_counter
);
432 const GURL
url_a1("http://www.google.com/1.html");
433 scoped_refptr
<SiteInstanceImpl
> site_instance_a1(
434 static_cast<SiteInstanceImpl
*>(
435 browsing_instance
->GetSiteInstanceForURL(url_a1
)));
436 EXPECT_TRUE(site_instance_a1
.get() != NULL
);
438 // A separate site should create a separate SiteInstance.
439 const GURL
url_b1("http://www.yahoo.com/");
440 scoped_refptr
<SiteInstanceImpl
> site_instance_b1(
441 static_cast<SiteInstanceImpl
*>(
442 browsing_instance
->GetSiteInstanceForURL(url_b1
)));
443 EXPECT_NE(site_instance_a1
.get(), site_instance_b1
.get());
444 EXPECT_TRUE(site_instance_a1
->IsRelatedSiteInstance(site_instance_b1
.get()));
446 // Getting the new SiteInstance from the BrowsingInstance and from another
447 // SiteInstance in the BrowsingInstance should give the same result.
448 EXPECT_EQ(site_instance_b1
.get(),
449 site_instance_a1
->GetRelatedSiteInstance(url_b1
));
451 // A second visit to the original site should return the same SiteInstance.
452 const GURL
url_a2("http://www.google.com/2.html");
453 EXPECT_EQ(site_instance_a1
.get(),
454 browsing_instance
->GetSiteInstanceForURL(url_a2
));
455 EXPECT_EQ(site_instance_a1
.get(),
456 site_instance_a1
->GetRelatedSiteInstance(url_a2
));
458 // A visit to the original site in a new BrowsingInstance (same or different
459 // browser context) should return a different SiteInstance.
460 TestBrowsingInstance
* browsing_instance2
=
461 new TestBrowsingInstance(browser_context
.get(), &delete_counter
);
462 // Ensure the new SiteInstance is ref counted so that it gets deleted.
463 scoped_refptr
<SiteInstanceImpl
> site_instance_a2_2(
464 static_cast<SiteInstanceImpl
*>(
465 browsing_instance2
->GetSiteInstanceForURL(url_a2
)));
466 EXPECT_NE(site_instance_a1
.get(), site_instance_a2_2
.get());
468 site_instance_a1
->IsRelatedSiteInstance(site_instance_a2_2
.get()));
470 // The two SiteInstances for http://google.com should not use the same process
471 // if process-per-site is not enabled.
472 scoped_ptr
<RenderProcessHost
> process_a1(site_instance_a1
->GetProcess());
473 scoped_ptr
<RenderProcessHost
> process_a2_2(site_instance_a2_2
->GetProcess());
474 EXPECT_NE(process_a1
.get(), process_a2_2
.get());
476 // Should be able to see that we do have SiteInstances.
477 EXPECT_TRUE(browsing_instance
->HasSiteInstance(
478 GURL("http://mail.google.com")));
479 EXPECT_TRUE(browsing_instance2
->HasSiteInstance(
480 GURL("http://mail.google.com")));
481 EXPECT_TRUE(browsing_instance
->HasSiteInstance(
482 GURL("http://mail.yahoo.com")));
484 // Should be able to see that we don't have SiteInstances.
485 EXPECT_FALSE(browsing_instance
->HasSiteInstance(
486 GURL("https://www.google.com")));
487 EXPECT_FALSE(browsing_instance2
->HasSiteInstance(
488 GURL("http://www.yahoo.com")));
490 // browsing_instances will be deleted when their SiteInstances are deleted.
491 // The processes will be unregistered when the RPH scoped_ptrs go away.
496 // Test to ensure that there is only one RenderProcessHost per site for an
497 // entire BrowserContext, if process-per-site is in use.
498 TEST_F(SiteInstanceTest
, OneSiteInstancePerSiteInBrowserContext
) {
499 base::CommandLine::ForCurrentProcess()->AppendSwitch(
500 switches::kProcessPerSite
);
501 int delete_counter
= 0;
502 scoped_ptr
<TestBrowserContext
> browser_context(new TestBrowserContext());
503 TestBrowsingInstance
* browsing_instance
=
504 new TestBrowsingInstance(browser_context
.get(), &delete_counter
);
506 const GURL
url_a1("http://www.google.com/1.html");
507 scoped_refptr
<SiteInstanceImpl
> site_instance_a1(
508 static_cast<SiteInstanceImpl
*>(
509 browsing_instance
->GetSiteInstanceForURL(url_a1
)));
510 EXPECT_TRUE(site_instance_a1
.get() != NULL
);
511 scoped_ptr
<RenderProcessHost
> process_a1(site_instance_a1
->GetProcess());
513 // A separate site should create a separate SiteInstance.
514 const GURL
url_b1("http://www.yahoo.com/");
515 scoped_refptr
<SiteInstanceImpl
> site_instance_b1(
516 static_cast<SiteInstanceImpl
*>(
517 browsing_instance
->GetSiteInstanceForURL(url_b1
)));
518 EXPECT_NE(site_instance_a1
.get(), site_instance_b1
.get());
519 EXPECT_TRUE(site_instance_a1
->IsRelatedSiteInstance(site_instance_b1
.get()));
521 // Getting the new SiteInstance from the BrowsingInstance and from another
522 // SiteInstance in the BrowsingInstance should give the same result.
523 EXPECT_EQ(site_instance_b1
.get(),
524 site_instance_a1
->GetRelatedSiteInstance(url_b1
));
526 // A second visit to the original site should return the same SiteInstance.
527 const GURL
url_a2("http://www.google.com/2.html");
528 EXPECT_EQ(site_instance_a1
.get(),
529 browsing_instance
->GetSiteInstanceForURL(url_a2
));
530 EXPECT_EQ(site_instance_a1
.get(),
531 site_instance_a1
->GetRelatedSiteInstance(url_a2
));
533 // A visit to the original site in a new BrowsingInstance (same browser
534 // context) should return a different SiteInstance with the same process.
535 TestBrowsingInstance
* browsing_instance2
=
536 new TestBrowsingInstance(browser_context
.get(), &delete_counter
);
537 scoped_refptr
<SiteInstanceImpl
> site_instance_a1_2(
538 static_cast<SiteInstanceImpl
*>(
539 browsing_instance2
->GetSiteInstanceForURL(url_a1
)));
540 EXPECT_TRUE(site_instance_a1
.get() != NULL
);
541 EXPECT_NE(site_instance_a1
.get(), site_instance_a1_2
.get());
542 EXPECT_EQ(process_a1
.get(), site_instance_a1_2
->GetProcess());
544 // A visit to the original site in a new BrowsingInstance (different browser
545 // context) should return a different SiteInstance with a different process.
546 scoped_ptr
<TestBrowserContext
> browser_context2(new TestBrowserContext());
547 TestBrowsingInstance
* browsing_instance3
=
548 new TestBrowsingInstance(browser_context2
.get(), &delete_counter
);
549 scoped_refptr
<SiteInstanceImpl
> site_instance_a2_3(
550 static_cast<SiteInstanceImpl
*>(
551 browsing_instance3
->GetSiteInstanceForURL(url_a2
)));
552 EXPECT_TRUE(site_instance_a2_3
.get() != NULL
);
553 scoped_ptr
<RenderProcessHost
> process_a2_3(site_instance_a2_3
->GetProcess());
554 EXPECT_NE(site_instance_a1
.get(), site_instance_a2_3
.get());
555 EXPECT_NE(process_a1
.get(), process_a2_3
.get());
557 // Should be able to see that we do have SiteInstances.
558 EXPECT_TRUE(browsing_instance
->HasSiteInstance(
559 GURL("http://mail.google.com"))); // visited before
560 EXPECT_TRUE(browsing_instance2
->HasSiteInstance(
561 GURL("http://mail.google.com"))); // visited before
562 EXPECT_TRUE(browsing_instance
->HasSiteInstance(
563 GURL("http://mail.yahoo.com"))); // visited before
565 // Should be able to see that we don't have SiteInstances.
566 EXPECT_FALSE(browsing_instance2
->HasSiteInstance(
567 GURL("http://www.yahoo.com"))); // different BI, same browser context
568 EXPECT_FALSE(browsing_instance
->HasSiteInstance(
569 GURL("https://www.google.com"))); // not visited before
570 EXPECT_FALSE(browsing_instance3
->HasSiteInstance(
571 GURL("http://www.yahoo.com"))); // different BI, different context
573 // browsing_instances will be deleted when their SiteInstances are deleted.
574 // The processes will be unregistered when the RPH scoped_ptrs go away.
579 static SiteInstanceImpl
* CreateSiteInstance(BrowserContext
* browser_context
,
581 return static_cast<SiteInstanceImpl
*>(
582 SiteInstance::CreateForURL(browser_context
, url
));
585 // Test to ensure that pages that require certain privileges are grouped
586 // in processes with similar pages.
587 TEST_F(SiteInstanceTest
, ProcessSharingByType
) {
588 // This test shouldn't run with --site-per-process or
589 // --enable-strict-site-isolation modes, since they don't allow render
590 // process reuse, which this test explicitly exercises.
591 const base::CommandLine
& command_line
=
592 *base::CommandLine::ForCurrentProcess();
593 if (command_line
.HasSwitch(switches::kSitePerProcess
) ||
594 command_line
.HasSwitch(switches::kEnableStrictSiteIsolation
))
597 // On Android by default the number of renderer hosts is unlimited and process
598 // sharing doesn't happen. We set the override so that the test can run
600 RenderProcessHost::SetMaxRendererProcessCount(kMaxRendererProcessCount
);
602 ChildProcessSecurityPolicyImpl
* policy
=
603 ChildProcessSecurityPolicyImpl::GetInstance();
605 // Make a bunch of mock renderers so that we hit the limit.
606 scoped_ptr
<TestBrowserContext
> browser_context(new TestBrowserContext());
607 ScopedVector
<MockRenderProcessHost
> hosts
;
608 for (size_t i
= 0; i
< kMaxRendererProcessCount
; ++i
)
609 hosts
.push_back(new MockRenderProcessHost(browser_context
.get()));
611 // Create some extension instances and make sure they share a process.
612 scoped_refptr
<SiteInstanceImpl
> extension1_instance(
613 CreateSiteInstance(browser_context
.get(),
614 GURL(kPrivilegedScheme
+ std::string("://foo/bar"))));
615 set_privileged_process_id(extension1_instance
->GetProcess()->GetID());
617 scoped_refptr
<SiteInstanceImpl
> extension2_instance(
618 CreateSiteInstance(browser_context
.get(),
619 GURL(kPrivilegedScheme
+ std::string("://baz/bar"))));
621 scoped_ptr
<RenderProcessHost
> extension_host(
622 extension1_instance
->GetProcess());
623 EXPECT_EQ(extension1_instance
->GetProcess(),
624 extension2_instance
->GetProcess());
626 // Create some WebUI instances and make sure they share a process.
627 scoped_refptr
<SiteInstanceImpl
> webui1_instance(CreateSiteInstance(
628 browser_context
.get(), GURL(kChromeUIScheme
+ std::string("://newtab"))));
629 policy
->GrantWebUIBindings(webui1_instance
->GetProcess()->GetID());
631 scoped_refptr
<SiteInstanceImpl
> webui2_instance(
632 CreateSiteInstance(browser_context
.get(),
633 GURL(kChromeUIScheme
+ std::string("://history"))));
635 scoped_ptr
<RenderProcessHost
> dom_host(webui1_instance
->GetProcess());
636 EXPECT_EQ(webui1_instance
->GetProcess(), webui2_instance
->GetProcess());
638 // Make sure none of differing privilege processes are mixed.
639 EXPECT_NE(extension1_instance
->GetProcess(), webui1_instance
->GetProcess());
641 for (size_t i
= 0; i
< kMaxRendererProcessCount
; ++i
) {
642 EXPECT_NE(extension1_instance
->GetProcess(), hosts
[i
]);
643 EXPECT_NE(webui1_instance
->GetProcess(), hosts
[i
]);
648 // Disable the process limit override.
649 RenderProcessHost::SetMaxRendererProcessCount(0u);
652 // Test to ensure that HasWrongProcessForURL behaves properly for different
654 TEST_F(SiteInstanceTest
, HasWrongProcessForURL
) {
655 scoped_ptr
<TestBrowserContext
> browser_context(new TestBrowserContext());
656 scoped_ptr
<RenderProcessHost
> host
;
657 scoped_refptr
<SiteInstanceImpl
> instance(static_cast<SiteInstanceImpl
*>(
658 SiteInstance::Create(browser_context
.get())));
660 EXPECT_FALSE(instance
->HasSite());
661 EXPECT_TRUE(instance
->GetSiteURL().is_empty());
663 instance
->SetSite(GURL("http://evernote.com/"));
664 EXPECT_TRUE(instance
->HasSite());
666 // Check prior to "assigning" a process to the instance, which is expected
667 // to return false due to not being attached to any process yet.
668 EXPECT_FALSE(instance
->HasWrongProcessForURL(GURL("http://google.com")));
670 // The call to GetProcess actually creates a new real process, which works
671 // fine, but might be a cause for problems in different contexts.
672 host
.reset(instance
->GetProcess());
673 EXPECT_TRUE(host
.get() != NULL
);
674 EXPECT_TRUE(instance
->HasProcess());
676 EXPECT_FALSE(instance
->HasWrongProcessForURL(GURL("http://evernote.com")));
677 EXPECT_FALSE(instance
->HasWrongProcessForURL(
678 GURL("javascript:alert(document.location.href);")));
680 EXPECT_TRUE(instance
->HasWrongProcessForURL(GURL("chrome://settings")));
682 // Test that WebUI SiteInstances reject normal web URLs.
683 const GURL
webui_url("chrome://settings");
684 scoped_refptr
<SiteInstanceImpl
> webui_instance(static_cast<SiteInstanceImpl
*>(
685 SiteInstance::Create(browser_context
.get())));
686 webui_instance
->SetSite(webui_url
);
687 scoped_ptr
<RenderProcessHost
> webui_host(webui_instance
->GetProcess());
689 // Simulate granting WebUI bindings for the process.
690 ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
691 webui_host
->GetID());
693 EXPECT_TRUE(webui_instance
->HasProcess());
694 EXPECT_FALSE(webui_instance
->HasWrongProcessForURL(webui_url
));
695 EXPECT_TRUE(webui_instance
->HasWrongProcessForURL(GURL("http://google.com")));
697 // WebUI uses process-per-site, so another instance will use the same process
698 // even if we haven't called GetProcess yet. Make sure HasWrongProcessForURL
699 // doesn't crash (http://crbug.com/137070).
700 scoped_refptr
<SiteInstanceImpl
> webui_instance2(
701 static_cast<SiteInstanceImpl
*>(
702 SiteInstance::Create(browser_context
.get())));
703 webui_instance2
->SetSite(webui_url
);
704 EXPECT_FALSE(webui_instance2
->HasWrongProcessForURL(webui_url
));
706 webui_instance2
->HasWrongProcessForURL(GURL("http://google.com")));
711 // Test to ensure that HasWrongProcessForURL behaves properly even when
712 // --site-per-process is used (http://crbug.com/160671).
713 TEST_F(SiteInstanceTest
, HasWrongProcessForURLInSitePerProcess
) {
714 base::CommandLine::ForCurrentProcess()->AppendSwitch(
715 switches::kSitePerProcess
);
717 scoped_ptr
<TestBrowserContext
> browser_context(new TestBrowserContext());
718 scoped_ptr
<RenderProcessHost
> host
;
719 scoped_refptr
<SiteInstanceImpl
> instance(static_cast<SiteInstanceImpl
*>(
720 SiteInstance::Create(browser_context
.get())));
722 instance
->SetSite(GURL("http://evernote.com/"));
723 EXPECT_TRUE(instance
->HasSite());
725 // Check prior to "assigning" a process to the instance, which is expected
726 // to return false due to not being attached to any process yet.
727 EXPECT_FALSE(instance
->HasWrongProcessForURL(GURL("http://google.com")));
729 // The call to GetProcess actually creates a new real process, which works
730 // fine, but might be a cause for problems in different contexts.
731 host
.reset(instance
->GetProcess());
732 EXPECT_TRUE(host
.get() != NULL
);
733 EXPECT_TRUE(instance
->HasProcess());
735 EXPECT_FALSE(instance
->HasWrongProcessForURL(GURL("http://evernote.com")));
736 EXPECT_FALSE(instance
->HasWrongProcessForURL(
737 GURL("javascript:alert(document.location.href);")));
739 EXPECT_TRUE(instance
->HasWrongProcessForURL(GURL("chrome://settings")));
744 // Test that we do not reuse a process in process-per-site mode if it has the
745 // wrong bindings for its URL. http://crbug.com/174059.
746 TEST_F(SiteInstanceTest
, ProcessPerSiteWithWrongBindings
) {
747 scoped_ptr
<TestBrowserContext
> browser_context(new TestBrowserContext());
748 scoped_ptr
<RenderProcessHost
> host
;
749 scoped_ptr
<RenderProcessHost
> host2
;
750 scoped_refptr
<SiteInstanceImpl
> instance(static_cast<SiteInstanceImpl
*>(
751 SiteInstance::Create(browser_context
.get())));
753 EXPECT_FALSE(instance
->HasSite());
754 EXPECT_TRUE(instance
->GetSiteURL().is_empty());
756 // Simulate navigating to a WebUI URL in a process that does not have WebUI
757 // bindings. This already requires bypassing security checks.
758 const GURL
webui_url("chrome://settings");
759 instance
->SetSite(webui_url
);
760 EXPECT_TRUE(instance
->HasSite());
762 // The call to GetProcess actually creates a new real process.
763 host
.reset(instance
->GetProcess());
764 EXPECT_TRUE(host
.get() != NULL
);
765 EXPECT_TRUE(instance
->HasProcess());
767 // Without bindings, this should look like the wrong process.
768 EXPECT_TRUE(instance
->HasWrongProcessForURL(webui_url
));
770 // WebUI uses process-per-site, so another instance would normally use the
771 // same process. Make sure it doesn't use the same process if the bindings
773 scoped_refptr
<SiteInstanceImpl
> instance2(
774 static_cast<SiteInstanceImpl
*>(
775 SiteInstance::Create(browser_context
.get())));
776 instance2
->SetSite(webui_url
);
777 host2
.reset(instance2
->GetProcess());
778 EXPECT_TRUE(host2
.get() != NULL
);
779 EXPECT_TRUE(instance2
->HasProcess());
780 EXPECT_NE(host
.get(), host2
.get());
785 // Test that we do not register processes with empty sites for process-per-site
787 TEST_F(SiteInstanceTest
, NoProcessPerSiteForEmptySite
) {
788 base::CommandLine::ForCurrentProcess()->AppendSwitch(
789 switches::kProcessPerSite
);
790 scoped_ptr
<TestBrowserContext
> browser_context(new TestBrowserContext());
791 scoped_ptr
<RenderProcessHost
> host
;
792 scoped_refptr
<SiteInstanceImpl
> instance(static_cast<SiteInstanceImpl
*>(
793 SiteInstance::Create(browser_context
.get())));
795 instance
->SetSite(GURL());
796 EXPECT_TRUE(instance
->HasSite());
797 EXPECT_TRUE(instance
->GetSiteURL().is_empty());
798 host
.reset(instance
->GetProcess());
800 EXPECT_FALSE(RenderProcessHostImpl::GetProcessHostForSite(
801 browser_context
.get(), GURL()));
806 } // namespace content