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.
4
5 #include "content/browser/site_instance_impl.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10 #include <string>
11 #include <vector>
12
13 #include "base/command_line.h"
14 #include "base/compiler_specific.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/run_loop.h"
17 #include "base/strings/string16.h"
18 #include "base/test/mock_log.h"
19 #include "base/test/scoped_command_line.h"
20 #include "base/test/scoped_feature_list.h"
21 #include "content/browser/browsing_instance.h"
22 #include "content/browser/child_process_security_policy_impl.h"
23 #include "content/browser/isolated_origin_util.h"
24 #include "content/browser/renderer_host/navigation_entry_impl.h"
25 #include "content/browser/renderer_host/render_process_host_impl.h"
26 #include "content/browser/renderer_host/render_view_host_impl.h"
27 #include "content/browser/web_contents/web_contents_impl.h"
28 #include "content/browser/webui/content_web_ui_controller_factory.h"
29 #include "content/browser/webui/web_ui_controller_factory_registry.h"
30 #include "content/public/browser/browser_or_resource_context.h"
31 #include "content/public/browser/site_isolation_policy.h"
32 #include "content/public/common/bindings_policy.h"
33 #include "content/public/common/content_client.h"
34 #include "content/public/common/content_constants.h"
35 #include "content/public/common/content_features.h"
36 #include "content/public/common/content_switches.h"
37 #include "content/public/common/url_constants.h"
38 #include "content/public/common/url_utils.h"
39 #include "content/public/test/browser_task_environment.h"
40 #include "content/public/test/mock_render_process_host.h"
41 #include "content/public/test/test_browser_context.h"
42 #include "content/public/test/test_utils.h"
43 #include "content/test/test_content_browser_client.h"
44 #include "content/test/test_content_client.h"
45 #include "content/test/test_render_view_host.h"
46 #include "testing/gtest/include/gtest/gtest.h"
47 #include "url/origin.h"
48 #include "url/url_util.h"
49
50 namespace content {
51 namespace {
52
53 using IsolatedOriginSource = ChildProcessSecurityPolicy::IsolatedOriginSource;
54
DoesURLRequireDedicatedProcess(const IsolationContext & isolation_context,const GURL & url)55 bool DoesURLRequireDedicatedProcess(const IsolationContext& isolation_context,
56 const GURL& url) {
57 return SiteInstanceImpl::ComputeSiteInfoForTesting(isolation_context, url)
58 .RequiresDedicatedProcess(isolation_context);
59 }
60
CreateSimpleSiteInfo(const GURL & process_lock_url,bool is_origin_keyed)61 SiteInfo CreateSimpleSiteInfo(const GURL& process_lock_url,
62 bool is_origin_keyed) {
63 return SiteInfo(GURL("https://www.foo.com"), process_lock_url,
64 is_origin_keyed,
65 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
66 }
67
68 } // namespace
69
70 const char kPrivilegedScheme[] = "privileged";
71 const char kCustomStandardScheme[] = "custom-standard";
72
73 class SiteInstanceTestBrowserClient : public TestContentBrowserClient {
74 public:
SiteInstanceTestBrowserClient()75 SiteInstanceTestBrowserClient()
76 : privileged_process_id_(-1),
77 site_instance_delete_count_(0),
78 browsing_instance_delete_count_(0) {
79 WebUIControllerFactory::RegisterFactory(
80 ContentWebUIControllerFactory::GetInstance());
81 }
82
~SiteInstanceTestBrowserClient()83 ~SiteInstanceTestBrowserClient() override {
84 WebUIControllerFactory::UnregisterFactoryForTesting(
85 ContentWebUIControllerFactory::GetInstance());
86 }
87
IsSuitableHost(RenderProcessHost * process_host,const GURL & site_url)88 bool IsSuitableHost(RenderProcessHost* process_host,
89 const GURL& site_url) override {
90 return (privileged_process_id_ == process_host->GetID()) ==
91 site_url.SchemeIs(kPrivilegedScheme);
92 }
93
set_privileged_process_id(int process_id)94 void set_privileged_process_id(int process_id) {
95 privileged_process_id_ = process_id;
96 }
97
SiteInstanceDeleting(content::SiteInstance * site_instance)98 void SiteInstanceDeleting(content::SiteInstance* site_instance) override {
99 site_instance_delete_count_++;
100 // Infer deletion of the browsing instance.
101 if (static_cast<SiteInstanceImpl*>(site_instance)
102 ->browsing_instance_->HasOneRef()) {
103 browsing_instance_delete_count_++;
104 }
105 }
106
GetAndClearSiteInstanceDeleteCount()107 int GetAndClearSiteInstanceDeleteCount() {
108 int result = site_instance_delete_count_;
109 site_instance_delete_count_ = 0;
110 return result;
111 }
112
GetAndClearBrowsingInstanceDeleteCount()113 int GetAndClearBrowsingInstanceDeleteCount() {
114 int result = browsing_instance_delete_count_;
115 browsing_instance_delete_count_ = 0;
116 return result;
117 }
118
119 private:
120 int privileged_process_id_;
121
122 int site_instance_delete_count_;
123 int browsing_instance_delete_count_;
124 };
125
126 class SiteInstanceTest : public testing::Test {
127 public:
SiteInstanceTest()128 SiteInstanceTest() : old_browser_client_(nullptr) {
129 url::AddStandardScheme(kPrivilegedScheme, url::SCHEME_WITH_HOST);
130 url::AddStandardScheme(kCustomStandardScheme, url::SCHEME_WITH_HOST);
131 }
132
GetSiteForURL(const IsolationContext & isolation_context,const GURL & url)133 GURL GetSiteForURL(const IsolationContext& isolation_context,
134 const GURL& url) {
135 return SiteInstanceImpl::GetSiteForURL(
136 isolation_context, UrlInfo(url, false /* origin_requests_isolation */));
137 }
138
SetUp()139 void SetUp() override {
140 old_browser_client_ = SetBrowserClientForTesting(&browser_client_);
141 RenderProcessHostImpl::set_render_process_host_factory_for_testing(
142 &rph_factory_);
143 }
144
TearDown()145 void TearDown() override {
146 // Ensure that no RenderProcessHosts are left over after the tests.
147 EXPECT_TRUE(RenderProcessHost::AllHostsIterator().IsAtEnd());
148
149 SetBrowserClientForTesting(old_browser_client_);
150 RenderProcessHostImpl::set_render_process_host_factory_for_testing(nullptr);
151
152 // http://crbug.com/143565 found SiteInstanceTest leaking an
153 // AppCacheDatabase. This happens because some part of the test indirectly
154 // calls StoragePartitionImplMap::PostCreateInitialization(), which posts
155 // a task to the IO thread to create the AppCacheDatabase. Since the
156 // message loop is not running, the AppCacheDatabase ends up getting
157 // created when DrainMessageLoop() gets called at the end of a test case.
158 // Immediately after, the test case ends and the AppCacheDatabase gets
159 // scheduled for deletion. Here, call DrainMessageLoop() again so the
160 // AppCacheDatabase actually gets deleted.
161 DrainMessageLoop();
162 }
163
set_privileged_process_id(int process_id)164 void set_privileged_process_id(int process_id) {
165 browser_client_.set_privileged_process_id(process_id);
166 }
167
DrainMessageLoop()168 void DrainMessageLoop() {
169 // We don't just do this in TearDown() because we create TestBrowserContext
170 // objects in each test, which will be destructed before
171 // TearDown() is called.
172 base::RunLoop().RunUntilIdle();
173 }
174
browser_client()175 SiteInstanceTestBrowserClient* browser_client() { return &browser_client_; }
176
IsIsolatedOrigin(const GURL & url)177 bool IsIsolatedOrigin(const GURL& url) {
178 // It's fine to use an IsolationContext without an associated
179 // BrowsingInstance, since this helper is used by tests that deal with
180 // globally isolated origins.
181 IsolationContext isolation_context(&context_);
182 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
183 return policy->IsIsolatedOrigin(isolation_context, url::Origin::Create(url),
184 false /* origin_requests_isolation */);
185 }
186
context()187 BrowserContext* context() { return &context_; }
188
GetSiteInfoForURL(const std::string & url)189 SiteInfo GetSiteInfoForURL(const std::string& url) {
190 return SiteInstanceImpl::ComputeSiteInfoForTesting(
191 IsolationContext(&context_), GURL(url));
192 }
193
IsSameSite(BrowserContext * context,const GURL & url1,const GURL & url2)194 static bool IsSameSite(BrowserContext* context,
195 const GURL& url1,
196 const GURL& url2) {
197 return SiteInstanceImpl::IsSameSite(
198 IsolationContext(context),
199 UrlInfo(url1, false /* origin_requests_isolation */),
200 UrlInfo(url2, false /* origin_requests_isolation */),
201 /*should_compare_effective_urls=*/true);
202 }
203
204 private:
205 BrowserTaskEnvironment task_environment_;
206 TestBrowserContext context_;
207
208 SiteInstanceTestBrowserClient browser_client_;
209 ContentBrowserClient* old_browser_client_;
210 MockRenderProcessHostFactory rph_factory_;
211
212 url::ScopedSchemeRegistryForTests scoped_registry_;
213 };
214
215 // Tests that SiteInfo works correct as a key for std::map and std::set.
216 // Test SiteInfos with identical site URLs but various lock URLs, including
217 // variations of each that are origin keyed ("ok").
TEST_F(SiteInstanceTest,SiteInfoAsContainerKey)218 TEST_F(SiteInstanceTest, SiteInfoAsContainerKey) {
219 auto site_info_1 = CreateSimpleSiteInfo(GURL("https://foo.com"),
220 false /* is_origin_keyed */);
221 auto site_info_1ok =
222 CreateSimpleSiteInfo(GURL("https://foo.com"), true /* is_origin_keyed */);
223 auto site_info_2 = CreateSimpleSiteInfo(GURL("https://www.foo.com"),
224 false /* is_origin_keyed */);
225 auto site_info_2ok = CreateSimpleSiteInfo(GURL("https://www.foo.com"),
226 true /* is_origin_keyed */);
227 auto site_info_3 = CreateSimpleSiteInfo(GURL("https://sub.foo.com"),
228 false /* is_origin_keyed */);
229 auto site_info_3ok = CreateSimpleSiteInfo(GURL("https://sub.foo.com"),
230 true /* is_origin_keyed */);
231 auto site_info_4 = CreateSimpleSiteInfo(GURL(), false /* is_origin_keyed */);
232 auto site_info_4ok = CreateSimpleSiteInfo(GURL(), true /* is_origin_keyed */);
233
234 // Test SiteInfoOperators.
235 // Use EXPECT_TRUE and == below to avoid need to define SiteInfo::operator<<.
236 EXPECT_TRUE(site_info_1 == site_info_1);
237 EXPECT_FALSE(site_info_1 == site_info_2);
238 EXPECT_FALSE(site_info_1 == site_info_3);
239 EXPECT_FALSE(site_info_1 == site_info_4);
240 EXPECT_TRUE(site_info_2 == site_info_2);
241 EXPECT_FALSE(site_info_2 == site_info_3);
242 EXPECT_FALSE(site_info_2 == site_info_4);
243 EXPECT_TRUE(site_info_3 == site_info_3);
244 EXPECT_FALSE(site_info_3 == site_info_4);
245 EXPECT_TRUE(site_info_4 == site_info_4);
246
247 EXPECT_TRUE(site_info_1 < site_info_3); // 'f' before 's'/
248 EXPECT_TRUE(site_info_3 < site_info_2); // 's' before 'w'/
249 EXPECT_TRUE(site_info_4 < site_info_1); // Empty string first.
250
251 {
252 std::map<SiteInfo, int> test_map;
253 // Map tests: different lock URLs.
254 test_map[site_info_1] = 1;
255 test_map[site_info_2] = 2;
256 test_map[site_info_4] = 4;
257
258 // Make sure std::map treated the different SiteInfo's as distinct.
259 EXPECT_EQ(3u, test_map.size());
260
261 // Test that std::map::find() looks up the correct key.
262 auto it1 = test_map.find(site_info_1);
263 EXPECT_NE(it1, test_map.end());
264 EXPECT_EQ(1, it1->second);
265
266 auto it2 = test_map.find(site_info_2);
267 EXPECT_NE(it2, test_map.end());
268 EXPECT_EQ(2, it2->second);
269
270 EXPECT_EQ(test_map.end(), test_map.find(site_info_3));
271
272 auto it4 = test_map.find(site_info_4);
273 EXPECT_NE(it4, test_map.end());
274 EXPECT_EQ(4, it4->second);
275 }
276
277 {
278 std::map<SiteInfo, int> test_map;
279 // Map tests: different lock URLs and origin keys.
280
281 test_map[site_info_1] = 1;
282 test_map[site_info_2] = 2;
283 test_map[site_info_4] = 4;
284 test_map[site_info_1ok] = 11;
285 test_map[site_info_2ok] = 12;
286 test_map[site_info_4ok] = 14;
287
288 // Make sure std::map treated the different SiteInfo's as distinct.
289 EXPECT_EQ(6u, test_map.size());
290
291 // Test that std::map::find() looks up the correct key with is_origin_keyed
292 // == true.
293 auto it1 = test_map.find(site_info_1ok);
294 EXPECT_NE(it1, test_map.end());
295 EXPECT_EQ(11, it1->second);
296
297 auto it2 = test_map.find(site_info_2ok);
298 EXPECT_NE(it2, test_map.end());
299 EXPECT_EQ(12, it2->second);
300
301 EXPECT_EQ(test_map.end(), test_map.find(site_info_3));
302 EXPECT_EQ(test_map.end(), test_map.find(site_info_3ok));
303
304 auto it4 = test_map.find(site_info_4ok);
305 EXPECT_NE(it4, test_map.end());
306 EXPECT_EQ(14, it4->second);
307 }
308
309 {
310 std::set<SiteInfo> test_set;
311
312 // Set tests.
313 test_set.insert(site_info_1);
314 test_set.insert(site_info_2);
315 test_set.insert(site_info_4);
316
317 EXPECT_EQ(3u, test_set.size());
318
319 auto itS1 = test_set.find(site_info_1);
320 auto itS2 = test_set.find(site_info_2);
321 auto itS3 = test_set.find(site_info_3);
322 auto itS4 = test_set.find(site_info_4);
323
324 EXPECT_NE(test_set.end(), itS1);
325 EXPECT_NE(test_set.end(), itS2);
326 EXPECT_EQ(test_set.end(), itS3);
327 EXPECT_NE(test_set.end(), itS4);
328
329 // Use EXPECT_TRUE and == below to avoid need to define
330 // SiteInfo::operator<<.
331 EXPECT_TRUE(site_info_1 == *itS1);
332 EXPECT_TRUE(site_info_2 == *itS2);
333 EXPECT_TRUE(site_info_4 == *itS4);
334 }
335 {
336 std::set<SiteInfo> test_set;
337
338 // Set tests, testing is_origin_keyed.
339 test_set.insert(site_info_1);
340 test_set.insert(site_info_2);
341 test_set.insert(site_info_4);
342 test_set.insert(site_info_1ok);
343 test_set.insert(site_info_2ok);
344 test_set.insert(site_info_4ok);
345
346 EXPECT_EQ(6u, test_set.size());
347
348 auto itS1 = test_set.find(site_info_1ok);
349 auto itS2 = test_set.find(site_info_2ok);
350 auto itS3 = test_set.find(site_info_3ok);
351 auto itS4 = test_set.find(site_info_4ok);
352
353 EXPECT_NE(test_set.end(), itS1);
354 EXPECT_NE(test_set.end(), itS2);
355 EXPECT_EQ(test_set.end(), itS3);
356 EXPECT_NE(test_set.end(), itS4);
357
358 // Use EXPECT_TRUE and == below to avoid need to define
359 // SiteInfo::operator<<.
360 EXPECT_TRUE(site_info_1ok == *itS1);
361 EXPECT_TRUE(site_info_2ok == *itS2);
362 EXPECT_TRUE(site_info_4ok == *itS4);
363 }
364 }
365
366 // Test to ensure no memory leaks for SiteInstance objects.
TEST_F(SiteInstanceTest,SiteInstanceDestructor)367 TEST_F(SiteInstanceTest, SiteInstanceDestructor) {
368 TestBrowserContext context;
369
370 // The existence of this object will cause WebContentsImpl to create our
371 // test one instead of the real one.
372 RenderViewHostTestEnabler rvh_test_enabler;
373 const GURL url("test:foo");
374
375 // Ensure that instances are deleted when their NavigationEntries are gone.
376 scoped_refptr<SiteInstanceImpl> instance = SiteInstanceImpl::Create(&context);
377 EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
378
379 NavigationEntryImpl* e1 = new NavigationEntryImpl(
380 instance, url, Referrer(), base::nullopt, base::string16(),
381 ui::PAGE_TRANSITION_LINK, false, nullptr /* blob_url_loader_factory */);
382
383 // Redundantly setting e1's SiteInstance shouldn't affect the ref count.
384 e1->set_site_instance(instance);
385 EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
386 EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
387
388 // Add a second reference
389 NavigationEntryImpl* e2 = new NavigationEntryImpl(
390 instance, url, Referrer(), base::nullopt, base::string16(),
391 ui::PAGE_TRANSITION_LINK, false, nullptr /* blob_url_loader_factory */);
392
393 instance = nullptr;
394 EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
395 EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
396
397 // Now delete both entries and be sure the SiteInstance goes away.
398 delete e1;
399 EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
400 EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
401 delete e2;
402 // instance is now deleted
403 EXPECT_EQ(1, browser_client()->GetAndClearSiteInstanceDeleteCount());
404 EXPECT_EQ(1, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
405 // browsing_instance is now deleted
406
407 // Ensure that instances are deleted when their RenderViewHosts are gone.
408 std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
409 {
410 std::unique_ptr<WebContents> web_contents(
411 WebContents::Create(WebContents::CreateParams(
412 browser_context.get(),
413 SiteInstance::Create(browser_context.get()))));
414 EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
415 EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
416 }
417
418 // Make sure that we flush any messages related to the above WebContentsImpl
419 // destruction.
420 DrainMessageLoop();
421
422 EXPECT_EQ(1, browser_client()->GetAndClearSiteInstanceDeleteCount());
423 EXPECT_EQ(1, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
424 // contents is now deleted, along with instance and browsing_instance
425 }
426
427 // Ensure that default SiteInstances are deleted when all references to them
428 // are gone.
TEST_F(SiteInstanceTest,DefaultSiteInstanceDestruction)429 TEST_F(SiteInstanceTest, DefaultSiteInstanceDestruction) {
430 TestBrowserContext browser_context;
431 base::test::ScopedCommandLine scoped_command_line;
432
433 // Disable site isolation so we can get default SiteInstances on all
434 // platforms.
435 scoped_command_line.GetProcessCommandLine()->AppendSwitch(
436 switches::kDisableSiteIsolation);
437
438 // Ensure that default SiteInstances are deleted when all references to them
439 // are gone.
440 auto site_instance = SiteInstanceImpl::CreateForUrlInfo(
441 &browser_context, UrlInfo::CreateForTesting(GURL("http://foo.com")),
442 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
443
444 EXPECT_EQ(AreDefaultSiteInstancesEnabled(),
445 site_instance->IsDefaultSiteInstance());
446
447 site_instance.reset();
448
449 EXPECT_EQ(1, browser_client()->GetAndClearSiteInstanceDeleteCount());
450 EXPECT_EQ(1, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
451 }
452
453 // Test to ensure GetProcess returns and creates processes correctly.
TEST_F(SiteInstanceTest,GetProcess)454 TEST_F(SiteInstanceTest, GetProcess) {
455 // Ensure that GetProcess returns a process.
456 std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
457 scoped_refptr<SiteInstanceImpl> instance(
458 SiteInstanceImpl::Create(browser_context.get()));
459 RenderProcessHost* host1 = instance->GetProcess();
460 EXPECT_TRUE(host1 != nullptr);
461
462 // Ensure that GetProcess creates a new process.
463 scoped_refptr<SiteInstanceImpl> instance2(
464 SiteInstanceImpl::Create(browser_context.get()));
465 RenderProcessHost* host2 = instance2->GetProcess();
466 EXPECT_TRUE(host2 != nullptr);
467 EXPECT_NE(host1, host2);
468
469 DrainMessageLoop();
470 }
471
472 // Test to ensure SetSite and site() work properly.
TEST_F(SiteInstanceTest,SetSite)473 TEST_F(SiteInstanceTest, SetSite) {
474 TestBrowserContext context;
475
476 scoped_refptr<SiteInstanceImpl> instance(SiteInstanceImpl::Create(&context));
477 EXPECT_FALSE(instance->HasSite());
478 EXPECT_TRUE(instance->GetSiteURL().is_empty());
479
480 instance->SetSite(
481 UrlInfo::CreateForTesting(GURL("http://www.google.com/index.html")));
482 EXPECT_EQ(GURL("http://google.com"), instance->GetSiteURL());
483
484 EXPECT_TRUE(instance->HasSite());
485
486 DrainMessageLoop();
487 }
488
489 // Test to ensure GetSiteForURL properly returns sites for URLs.
TEST_F(SiteInstanceTest,GetSiteForURL)490 TEST_F(SiteInstanceTest, GetSiteForURL) {
491 TestBrowserContext context;
492
493 // Pages are irrelevant.
494 GURL test_url = GURL("http://www.google.com/index.html");
495 GURL site_url = SiteInstance::GetSiteForURL(&context, test_url);
496 EXPECT_EQ(GURL("http://google.com"), site_url);
497 EXPECT_EQ("http", site_url.scheme());
498 EXPECT_EQ("google.com", site_url.host());
499
500 // Ports are irrelevant.
501 test_url = GURL("https://www.google.com:8080");
502 site_url = SiteInstance::GetSiteForURL(&context, test_url);
503 EXPECT_EQ(GURL("https://google.com"), site_url);
504
505 // Punycode is canonicalized.
506 test_url = GURL("http://☃snowperson☃.net:333/");
507 site_url = SiteInstance::GetSiteForURL(&context, test_url);
508 EXPECT_EQ(GURL("http://xn--snowperson-di0gka.net"), site_url);
509
510 // Username and password are stripped out.
511 test_url = GURL("ftp://username:password@ftp.chromium.org/files/README");
512 site_url = SiteInstance::GetSiteForURL(&context, test_url);
513 EXPECT_EQ(GURL("ftp://chromium.org"), site_url);
514
515 // Literal IP addresses of any flavor are okay.
516 test_url = GURL("http://127.0.0.1/a.html");
517 site_url = SiteInstance::GetSiteForURL(&context, test_url);
518 EXPECT_EQ(GURL("http://127.0.0.1"), site_url);
519 EXPECT_EQ("127.0.0.1", site_url.host());
520
521 test_url = GURL("http://2130706433/a.html");
522 site_url = SiteInstance::GetSiteForURL(&context, test_url);
523 EXPECT_EQ(GURL("http://127.0.0.1"), site_url);
524 EXPECT_EQ("127.0.0.1", site_url.host());
525
526 test_url = GURL("http://[::1]:2/page.html");
527 site_url = SiteInstance::GetSiteForURL(&context, test_url);
528 EXPECT_EQ(GURL("http://[::1]"), site_url);
529 EXPECT_EQ("[::1]", site_url.host());
530
531 // Hostnames without TLDs are okay.
532 test_url = GURL("http://foo/a.html");
533 site_url = SiteInstance::GetSiteForURL(&context, test_url);
534 EXPECT_EQ(GURL("http://foo"), site_url);
535 EXPECT_EQ("foo", site_url.host());
536
537 // File URLs should include the scheme.
538 test_url = GURL("file:///C:/Downloads/");
539 site_url = SiteInstance::GetSiteForURL(&context, test_url);
540 EXPECT_EQ(GURL("file:"), site_url);
541 EXPECT_EQ("file", site_url.scheme());
542 EXPECT_FALSE(site_url.has_host());
543
544 // Some file URLs have hosts in the path. For consistency with Blink (which
545 // maps *all* file://... URLs into "file://" origin) such file URLs still need
546 // to map into "file:" site URL. See also https://crbug.com/776160.
547 test_url = GURL("file://server/path");
548 site_url = SiteInstance::GetSiteForURL(&context, test_url);
549 EXPECT_EQ(GURL("file:"), site_url);
550 EXPECT_EQ("file", site_url.scheme());
551 EXPECT_FALSE(site_url.has_host());
552
553 // Data URLs should include the whole URL, except for the hash.
554 test_url = GURL("data:text/html,foo");
555 site_url = SiteInstance::GetSiteForURL(&context, test_url);
556 EXPECT_EQ(test_url, site_url);
557 EXPECT_EQ("data", site_url.scheme());
558 EXPECT_FALSE(site_url.has_host());
559 test_url = GURL("data:text/html,foo#bar");
560 site_url = SiteInstance::GetSiteForURL(&context, test_url);
561 EXPECT_FALSE(site_url.has_ref());
562 EXPECT_NE(test_url, site_url);
563 EXPECT_TRUE(site_url.EqualsIgnoringRef(test_url));
564
565 // Javascript URLs should include the scheme.
566 test_url = GURL("javascript:foo();");
567 site_url = SiteInstance::GetSiteForURL(&context, test_url);
568 EXPECT_EQ(GURL("javascript:"), site_url);
569 EXPECT_EQ("javascript", site_url.scheme());
570 EXPECT_FALSE(site_url.has_host());
571
572 // Blob URLs extract the site from the origin.
573 test_url = GURL(
574 "blob:https://www.ftp.chromium.org/"
575 "4d4ff040-6d61-4446-86d3-13ca07ec9ab9");
576 site_url = SiteInstance::GetSiteForURL(&context, test_url);
577 EXPECT_EQ(GURL("https://chromium.org"), site_url);
578
579 // Blob URLs with file origin also extract the site from the origin.
580 test_url = GURL("blob:file:///1029e5a4-2983-4b90-a585-ed217563acfeb");
581 site_url = SiteInstance::GetSiteForURL(&context, test_url);
582 EXPECT_EQ(GURL("file:"), site_url);
583 EXPECT_EQ("file", site_url.scheme());
584 EXPECT_FALSE(site_url.has_host());
585
586 // Blob URLs created from a unique origin use the full URL as the site URL,
587 // except for the hash.
588 test_url = GURL("blob:null/1029e5a4-2983-4b90-a585-ed217563acfeb");
589 site_url = SiteInstance::GetSiteForURL(&context, test_url);
590 EXPECT_EQ(test_url, site_url);
591 test_url = GURL("blob:null/1029e5a4-2983-4b90-a585-ed217563acfeb#foo");
592 site_url = SiteInstance::GetSiteForURL(&context, test_url);
593 EXPECT_FALSE(site_url.has_ref());
594 EXPECT_NE(test_url, site_url);
595 EXPECT_TRUE(site_url.EqualsIgnoringRef(test_url));
596
597 // Private domains are preserved, appspot being such a site.
598 test_url = GURL(
599 "blob:http://www.example.appspot.com:44/"
600 "4d4ff040-6d61-4446-86d3-13ca07ec9ab9");
601 site_url = SiteInstance::GetSiteForURL(&context, test_url);
602 EXPECT_EQ(GURL("http://example.appspot.com"), site_url);
603
604 // The site of filesystem URLs is determined by the inner URL.
605 test_url = GURL("filesystem:http://www.google.com/foo/bar.html?foo#bar");
606 site_url = SiteInstance::GetSiteForURL(&context, test_url);
607 EXPECT_EQ(GURL("http://google.com"), site_url);
608
609 DrainMessageLoop();
610 }
611
612 // Test that process lock URLs are computed without using effective URLs.
TEST_F(SiteInstanceTest,ProcessLockDoesNotUseEffectiveURL)613 TEST_F(SiteInstanceTest, ProcessLockDoesNotUseEffectiveURL) {
614 GURL test_url("https://some.app.foo.com/");
615 GURL nonapp_site_url("https://foo.com/");
616 GURL app_url("https://app.com/");
617 EffectiveURLContentBrowserClient modified_client(
618 test_url, app_url, /* requires_dedicated_process */ true);
619 ContentBrowserClient* regular_client =
620 SetBrowserClientForTesting(&modified_client);
621 std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
622 IsolationContext isolation_context(browser_context.get());
623
624 // Sanity check that GetSiteForURL's |use_effective_urls| option works
625 // properly. When it's true, the site URL should correspond to the
626 // effective URL's site (app.com), rather than the original URL's site
627 // (foo.com).
628 {
629 GURL site_url = SiteInstanceImpl::GetSiteForURLInternal(
630 isolation_context, UrlInfo::CreateForTesting(test_url),
631 false /* use_effective_urls */);
632 EXPECT_EQ(nonapp_site_url, site_url);
633
634 site_url = SiteInstanceImpl::GetSiteForURLInternal(
635 isolation_context, UrlInfo::CreateForTesting(test_url),
636 true /* use_effective_urls */);
637 EXPECT_EQ(app_url, site_url);
638 }
639
640 SiteInfo expected_site_info(
641 app_url /* site_url */, nonapp_site_url /* process_lock_url */,
642 false /* is_origin_keyed */,
643 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
644
645 // New SiteInstance in a new BrowsingInstance with a predetermined URL.
646 {
647 scoped_refptr<SiteInstanceImpl> site_instance =
648 SiteInstanceImpl::CreateForUrlInfo(
649 browser_context.get(), UrlInfo::CreateForTesting(test_url),
650 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
651 EXPECT_EQ(expected_site_info, site_instance->GetSiteInfo());
652 }
653
654 // New related SiteInstance from an existing SiteInstance with a
655 // predetermined URL.
656 {
657 scoped_refptr<SiteInstanceImpl> bar_site_instance =
658 SiteInstanceImpl::CreateForUrlInfo(
659 browser_context.get(),
660 UrlInfo::CreateForTesting(GURL("https://bar.com/")),
661 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
662 scoped_refptr<SiteInstance> site_instance =
663 bar_site_instance->GetRelatedSiteInstance(test_url);
664 auto* site_instance_impl =
665 static_cast<SiteInstanceImpl*>(site_instance.get());
666 EXPECT_EQ(expected_site_info, site_instance_impl->GetSiteInfo());
667 }
668
669 // New SiteInstance with a lazily assigned site URL.
670 {
671 scoped_refptr<SiteInstanceImpl> site_instance =
672 SiteInstanceImpl::Create(browser_context.get());
673 EXPECT_FALSE(site_instance->HasSite());
674 site_instance->SetSite(UrlInfo::CreateForTesting(test_url));
675 EXPECT_EQ(expected_site_info, site_instance->GetSiteInfo());
676 }
677
678 SetBrowserClientForTesting(regular_client);
679 }
680
681 // Test of distinguishing URLs from different sites. Most of this logic is
682 // tested in RegistryControlledDomainTest. This test focuses on URLs with
683 // different schemes or ports.
TEST_F(SiteInstanceTest,IsSameSite)684 TEST_F(SiteInstanceTest, IsSameSite) {
685 TestBrowserContext context;
686 GURL url_foo = GURL("http://foo/a.html");
687 GURL url_foo2 = GURL("http://foo/b.html");
688 GURL url_foo_https = GURL("https://foo/a.html");
689 GURL url_foo_port = GURL("http://foo:8080/a.html");
690 GURL url_javascript = GURL("javascript:alert(1);");
691 GURL url_blank = GURL(url::kAboutBlankURL);
692
693 // Same scheme and port -> same site.
694 EXPECT_TRUE(IsSameSite(&context, url_foo, url_foo2));
695
696 // Different scheme -> different site.
697 EXPECT_FALSE(IsSameSite(&context, url_foo, url_foo_https));
698
699 // Different port -> same site.
700 // (Changes to document.domain make renderer ignore the port.)
701 EXPECT_TRUE(IsSameSite(&context, url_foo, url_foo_port));
702
703 // JavaScript links should be considered same site for anything.
704 EXPECT_TRUE(IsSameSite(&context, url_javascript, url_foo));
705 EXPECT_TRUE(IsSameSite(&context, url_javascript, url_foo_https));
706 EXPECT_TRUE(IsSameSite(&context, url_javascript, url_foo_port));
707
708 // Navigating to a blank page is considered the same site.
709 EXPECT_TRUE(IsSameSite(&context, url_foo, url_blank));
710 EXPECT_TRUE(IsSameSite(&context, url_foo_https, url_blank));
711 EXPECT_TRUE(IsSameSite(&context, url_foo_port, url_blank));
712
713 // Navigating from a blank site is not considered to be the same site.
714 EXPECT_FALSE(IsSameSite(&context, url_blank, url_foo));
715 EXPECT_FALSE(IsSameSite(&context, url_blank, url_foo_https));
716 EXPECT_FALSE(IsSameSite(&context, url_blank, url_foo_port));
717
718 DrainMessageLoop();
719 }
720
721 // Test that two file URLs are considered same-site if they have the same path,
722 // even if they have different fragments.
TEST_F(SiteInstanceTest,IsSameSiteForFileURLs)723 TEST_F(SiteInstanceTest, IsSameSiteForFileURLs) {
724 TestBrowserContext context;
725
726 // Two identical file URLs should be same-site.
727 EXPECT_TRUE(IsSameSite(&context, GURL("file:///foo/bar.html"),
728 GURL("file:///foo/bar.html")));
729
730 // File URLs with the same path but different fragment are considered
731 // same-site.
732 EXPECT_TRUE(IsSameSite(&context, GURL("file:///foo/bar.html"),
733 GURL("file:///foo/bar.html#baz")));
734 EXPECT_TRUE(IsSameSite(&context, GURL("file:///foo/bar.html#baz"),
735 GURL("file:///foo/bar.html")));
736 EXPECT_TRUE(IsSameSite(&context, GURL("file:///foo/bar.html#baz"),
737 GURL("file:///foo/bar.html#qux")));
738 EXPECT_TRUE(IsSameSite(&context, GURL("file:///#abc"), GURL("file:///#def")));
739
740 // Other cases are cross-site.
741 EXPECT_FALSE(IsSameSite(&context, GURL("file:///foo.html"),
742 GURL("file:///foo/bar.html")));
743 EXPECT_FALSE(
744 IsSameSite(&context, GURL("file:///#bar"), GURL("file:///foo/#bar")));
745 }
746
747 // Test to ensure that there is only one SiteInstance per site in a given
748 // BrowsingInstance, when process-per-site is not in use.
TEST_F(SiteInstanceTest,OneSiteInstancePerSite)749 TEST_F(SiteInstanceTest, OneSiteInstancePerSite) {
750 ASSERT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch(
751 switches::kProcessPerSite));
752 std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
753 BrowsingInstance* browsing_instance = new BrowsingInstance(
754 browser_context.get(),
755 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
756
757 const GURL url_a1("http://www.google.com/1.html");
758 scoped_refptr<SiteInstanceImpl> site_instance_a1(
759 browsing_instance->GetSiteInstanceForURL(
760 UrlInfo::CreateForTesting(url_a1), false));
761 EXPECT_TRUE(site_instance_a1.get() != nullptr);
762
763 // A separate site should create a separate SiteInstance.
764 const GURL url_b1("http://www.yahoo.com/");
765 scoped_refptr<SiteInstanceImpl> site_instance_b1(
766
767 browsing_instance->GetSiteInstanceForURL(
768 UrlInfo::CreateForTesting(url_b1), false));
769 EXPECT_NE(site_instance_a1.get(), site_instance_b1.get());
770 EXPECT_TRUE(site_instance_a1->IsRelatedSiteInstance(site_instance_b1.get()));
771
772 // Getting the new SiteInstance from the BrowsingInstance and from another
773 // SiteInstance in the BrowsingInstance should give the same result.
774 EXPECT_EQ(site_instance_b1.get(),
775 site_instance_a1->GetRelatedSiteInstance(url_b1));
776
777 // A second visit to the original site should return the same SiteInstance.
778 const GURL url_a2("http://www.google.com/2.html");
779 EXPECT_EQ(site_instance_a1.get(),
780 browsing_instance->GetSiteInstanceForURL(
781 UrlInfo::CreateForTesting(url_a2), false));
782 EXPECT_EQ(site_instance_a1.get(),
783 site_instance_a1->GetRelatedSiteInstance(url_a2));
784
785 // A visit to the original site in a new BrowsingInstance (same or different
786 // browser context) should return a different SiteInstance.
787 BrowsingInstance* browsing_instance2 = new BrowsingInstance(
788 browser_context.get(),
789 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
790 // Ensure the new SiteInstance is ref counted so that it gets deleted.
791 scoped_refptr<SiteInstanceImpl> site_instance_a2_2(
792 browsing_instance2->GetSiteInstanceForURL(
793 UrlInfo::CreateForTesting(url_a2), false));
794 EXPECT_NE(site_instance_a1.get(), site_instance_a2_2.get());
795 EXPECT_FALSE(
796 site_instance_a1->IsRelatedSiteInstance(site_instance_a2_2.get()));
797
798 // The two SiteInstances for http://google.com should not use the same process
799 // if process-per-site is not enabled.
800 RenderProcessHost* process_a1 = site_instance_a1->GetProcess();
801 RenderProcessHost* process_a2_2 = site_instance_a2_2->GetProcess();
802 EXPECT_NE(process_a1, process_a2_2);
803
804 // Should be able to see that we do have SiteInstances.
805 EXPECT_TRUE(browsing_instance->HasSiteInstance(
806 GetSiteInfoForURL("http://mail.google.com")));
807 EXPECT_TRUE(browsing_instance2->HasSiteInstance(
808 GetSiteInfoForURL("http://mail.google.com")));
809 EXPECT_TRUE(browsing_instance->HasSiteInstance(
810 GetSiteInfoForURL("http://mail.yahoo.com")));
811
812 // Should be able to see that we don't have SiteInstances.
813 EXPECT_FALSE(browsing_instance->HasSiteInstance(
814 GetSiteInfoForURL("https://www.google.com")));
815 EXPECT_FALSE(browsing_instance2->HasSiteInstance(
816 GetSiteInfoForURL("http://www.yahoo.com")));
817
818 // browsing_instances will be deleted when their SiteInstances are deleted.
819 // The processes will be unregistered when the RPH scoped_ptrs go away.
820
821 DrainMessageLoop();
822 }
823
824 // Test to ensure that there is only one RenderProcessHost per site for an
825 // entire BrowserContext, if process-per-site is in use.
TEST_F(SiteInstanceTest,OneSiteInstancePerSiteInBrowserContext)826 TEST_F(SiteInstanceTest, OneSiteInstancePerSiteInBrowserContext) {
827 base::CommandLine::ForCurrentProcess()->AppendSwitch(
828 switches::kProcessPerSite);
829 std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
830 scoped_refptr<BrowsingInstance> browsing_instance = new BrowsingInstance(
831 browser_context.get(),
832 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
833
834 const GURL url_a1("http://www.google.com/1.html");
835 scoped_refptr<SiteInstanceImpl> site_instance_a1(
836 browsing_instance->GetSiteInstanceForURL(
837 UrlInfo::CreateForTesting(url_a1), false));
838 EXPECT_TRUE(site_instance_a1.get() != nullptr);
839 RenderProcessHost* process_a1 = site_instance_a1->GetProcess();
840
841 // A separate site should create a separate SiteInstance.
842 const GURL url_b1("http://www.yahoo.com/");
843 scoped_refptr<SiteInstanceImpl> site_instance_b1(
844 browsing_instance->GetSiteInstanceForURL(
845 UrlInfo::CreateForTesting(url_b1), false));
846 EXPECT_NE(site_instance_a1.get(), site_instance_b1.get());
847 EXPECT_TRUE(site_instance_a1->IsRelatedSiteInstance(site_instance_b1.get()));
848
849 // Getting the new SiteInstance from the BrowsingInstance and from another
850 // SiteInstance in the BrowsingInstance should give the same result.
851 EXPECT_EQ(site_instance_b1.get(),
852 site_instance_a1->GetRelatedSiteInstance(url_b1));
853
854 // A second visit to the original site should return the same SiteInstance.
855 const GURL url_a2("http://www.google.com/2.html");
856 EXPECT_EQ(site_instance_a1.get(),
857 browsing_instance->GetSiteInstanceForURL(
858 UrlInfo::CreateForTesting(url_a2), false));
859 EXPECT_EQ(site_instance_a1.get(),
860 site_instance_a1->GetRelatedSiteInstance(url_a2));
861
862 // A visit to the original site in a new BrowsingInstance (same browser
863 // context) should return a different SiteInstance with the same process.
864 BrowsingInstance* browsing_instance2 = new BrowsingInstance(
865 browser_context.get(),
866 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
867 scoped_refptr<SiteInstanceImpl> site_instance_a1_2(
868 browsing_instance2->GetSiteInstanceForURL(
869 UrlInfo::CreateForTesting(url_a1), false));
870 EXPECT_TRUE(site_instance_a1.get() != nullptr);
871 EXPECT_NE(site_instance_a1.get(), site_instance_a1_2.get());
872 EXPECT_EQ(process_a1, site_instance_a1_2->GetProcess());
873
874 // A visit to the original site in a new BrowsingInstance (different browser
875 // context) should return a different SiteInstance with a different process.
876 std::unique_ptr<TestBrowserContext> browser_context2(
877 new TestBrowserContext());
878 BrowsingInstance* browsing_instance3 = new BrowsingInstance(
879 browser_context2.get(),
880 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
881 scoped_refptr<SiteInstanceImpl> site_instance_a2_3(
882 browsing_instance3->GetSiteInstanceForURL(
883 UrlInfo::CreateForTesting(url_a2), false));
884 EXPECT_TRUE(site_instance_a2_3.get() != nullptr);
885 RenderProcessHost* process_a2_3 = site_instance_a2_3->GetProcess();
886 EXPECT_NE(site_instance_a1.get(), site_instance_a2_3.get());
887 EXPECT_NE(process_a1, process_a2_3);
888
889 // Should be able to see that we do have SiteInstances.
890 EXPECT_TRUE(browsing_instance->HasSiteInstance(
891 GetSiteInfoForURL("http://mail.google.com"))); // visited before
892 EXPECT_TRUE(browsing_instance2->HasSiteInstance(
893 GetSiteInfoForURL("http://mail.google.com"))); // visited before
894 EXPECT_TRUE(browsing_instance->HasSiteInstance(
895 GetSiteInfoForURL("http://mail.yahoo.com"))); // visited before
896
897 // Should be able to see that we don't have SiteInstances.
898 EXPECT_FALSE(browsing_instance2->HasSiteInstance(GetSiteInfoForURL(
899 "http://www.yahoo.com"))); // different BI, same browser context
900 EXPECT_FALSE(browsing_instance->HasSiteInstance(
901 GetSiteInfoForURL("https://www.google.com"))); // not visited before
902 EXPECT_FALSE(browsing_instance3->HasSiteInstance(GetSiteInfoForURL(
903 "http://www.yahoo.com"))); // different BI, different context
904
905 // browsing_instances will be deleted when their SiteInstances are deleted.
906 // The processes will be unregistered when the RPH scoped_ptrs go away.
907
908 DrainMessageLoop();
909 }
910
911 // Test to ensure that IsSuitableForUrlInfo behaves properly for different types
912 // of URLs.
TEST_F(SiteInstanceTest,IsSuitableForUrlInfo)913 TEST_F(SiteInstanceTest, IsSuitableForUrlInfo) {
914 std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
915 RenderProcessHost* host;
916 scoped_refptr<SiteInstanceImpl> instance(
917 SiteInstanceImpl::Create(browser_context.get()));
918
919 EXPECT_FALSE(instance->HasSite());
920 EXPECT_TRUE(instance->GetSiteURL().is_empty());
921
922 // Check prior to assigning a site or process to the instance, which is
923 // expected to return false to allow the SiteInstance to be used for anything.
924 EXPECT_TRUE(instance->IsSuitableForUrlInfo(
925 UrlInfo::CreateForTesting(GURL("http://google.com"))));
926
927 instance->SetSite(UrlInfo::CreateForTesting(GURL("http://evernote.com/")));
928 EXPECT_TRUE(instance->HasSite());
929
930 // The call to GetProcess actually creates a new real process, which works
931 // fine, but might be a cause for problems in different contexts.
932 host = instance->GetProcess();
933 EXPECT_TRUE(host != nullptr);
934 EXPECT_TRUE(instance->HasProcess());
935
936 EXPECT_TRUE(instance->IsSuitableForUrlInfo(
937 UrlInfo::CreateForTesting(GURL("http://evernote.com"))));
938 EXPECT_TRUE(instance->IsSuitableForUrlInfo(UrlInfo::CreateForTesting(
939 GURL("javascript:alert(document.location.href);"))));
940
941 EXPECT_FALSE(instance->IsSuitableForUrlInfo(
942 UrlInfo::CreateForTesting(GetWebUIURL(kChromeUIGpuHost))));
943
944 // Test that WebUI SiteInstances reject normal web URLs.
945 const GURL webui_url(GetWebUIURL(kChromeUIGpuHost));
946 scoped_refptr<SiteInstanceImpl> webui_instance(
947 SiteInstanceImpl::Create(browser_context.get()));
948 webui_instance->SetSite(UrlInfo::CreateForTesting(webui_url));
949 RenderProcessHost* webui_host = webui_instance->GetProcess();
950
951 // Simulate granting WebUI bindings for the process.
952 ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
953 webui_host->GetID(), BINDINGS_POLICY_WEB_UI);
954
955 EXPECT_TRUE(webui_instance->HasProcess());
956 EXPECT_TRUE(webui_instance->IsSuitableForUrlInfo(
957 UrlInfo::CreateForTesting(webui_url)));
958 EXPECT_FALSE(webui_instance->IsSuitableForUrlInfo(
959 UrlInfo::CreateForTesting(GURL("http://google.com"))));
960 EXPECT_FALSE(webui_instance->IsSuitableForUrlInfo(
961 UrlInfo::CreateForTesting(GURL("http://gpu"))));
962
963 // WebUI uses process-per-site, so another instance will use the same process
964 // even if we haven't called GetProcess yet. Make sure IsSuitableForUrlInfo
965 // doesn't crash (http://crbug.com/137070).
966 scoped_refptr<SiteInstanceImpl> webui_instance2(
967 SiteInstanceImpl::Create(browser_context.get()));
968 webui_instance2->SetSite(UrlInfo::CreateForTesting(webui_url));
969 EXPECT_TRUE(webui_instance2->IsSuitableForUrlInfo(
970 UrlInfo::CreateForTesting(webui_url)));
971 EXPECT_FALSE(webui_instance2->IsSuitableForUrlInfo(
972 UrlInfo::CreateForTesting(GURL("http://google.com"))));
973
974 DrainMessageLoop();
975 }
976
977 // Test to ensure that IsSuitableForUrlInfo behaves properly even when
978 // --site-per-process is used (http://crbug.com/160671).
TEST_F(SiteInstanceTest,IsSuitableForUrlInfoInSitePerProcess)979 TEST_F(SiteInstanceTest, IsSuitableForUrlInfoInSitePerProcess) {
980 IsolateAllSitesForTesting(base::CommandLine::ForCurrentProcess());
981
982 std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
983 RenderProcessHost* host;
984 scoped_refptr<SiteInstanceImpl> instance(
985 SiteInstanceImpl::Create(browser_context.get()));
986
987 // Check prior to assigning a site or process to the instance, which is
988 // expected to return false to allow the SiteInstance to be used for anything.
989 EXPECT_TRUE(instance->IsSuitableForUrlInfo(
990 UrlInfo::CreateForTesting(GURL("http://google.com"))));
991
992 instance->SetSite(UrlInfo::CreateForTesting(GURL("http://evernote.com/")));
993 EXPECT_TRUE(instance->HasSite());
994
995 // The call to GetProcess actually creates a new real process, which works
996 // fine, but might be a cause for problems in different contexts.
997 host = instance->GetProcess();
998 EXPECT_TRUE(host != nullptr);
999 EXPECT_TRUE(instance->HasProcess());
1000
1001 EXPECT_TRUE(instance->IsSuitableForUrlInfo(
1002 UrlInfo::CreateForTesting(GURL("http://evernote.com"))));
1003 EXPECT_TRUE(instance->IsSuitableForUrlInfo(UrlInfo::CreateForTesting(
1004 GURL("javascript:alert(document.location.href);"))));
1005
1006 EXPECT_FALSE(instance->IsSuitableForUrlInfo(
1007 UrlInfo::CreateForTesting(GetWebUIURL(kChromeUIGpuHost))));
1008
1009 DrainMessageLoop();
1010 }
1011
1012 // Test that we do not reuse a process in process-per-site mode if it has the
1013 // wrong bindings for its URL. http://crbug.com/174059.
TEST_F(SiteInstanceTest,ProcessPerSiteWithWrongBindings)1014 TEST_F(SiteInstanceTest, ProcessPerSiteWithWrongBindings) {
1015 std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
1016 RenderProcessHost* host;
1017 RenderProcessHost* host2;
1018 scoped_refptr<SiteInstanceImpl> instance(
1019 SiteInstanceImpl::Create(browser_context.get()));
1020
1021 EXPECT_FALSE(instance->HasSite());
1022 EXPECT_TRUE(instance->GetSiteURL().is_empty());
1023
1024 // Simulate navigating to a WebUI URL in a process that does not have WebUI
1025 // bindings. This already requires bypassing security checks.
1026 const GURL webui_url(GetWebUIURL(kChromeUIGpuHost));
1027 instance->SetSite(UrlInfo::CreateForTesting(webui_url));
1028 EXPECT_TRUE(instance->HasSite());
1029
1030 // The call to GetProcess actually creates a new real process.
1031 host = instance->GetProcess();
1032 EXPECT_TRUE(host != nullptr);
1033 EXPECT_TRUE(instance->HasProcess());
1034
1035 // Without bindings, this should look like the wrong process.
1036 EXPECT_FALSE(
1037 instance->IsSuitableForUrlInfo(UrlInfo::CreateForTesting(webui_url)));
1038
1039 // WebUI uses process-per-site, so another instance would normally use the
1040 // same process. Make sure it doesn't use the same process if the bindings
1041 // are missing.
1042 scoped_refptr<SiteInstanceImpl> instance2(
1043 SiteInstanceImpl::Create(browser_context.get()));
1044 instance2->SetSite(UrlInfo::CreateForTesting(webui_url));
1045 host2 = instance2->GetProcess();
1046 EXPECT_TRUE(host2 != nullptr);
1047 EXPECT_TRUE(instance2->HasProcess());
1048 EXPECT_NE(host, host2);
1049
1050 DrainMessageLoop();
1051 }
1052
1053 // Test that we do not register processes with empty sites for process-per-site
1054 // mode.
TEST_F(SiteInstanceTest,NoProcessPerSiteForEmptySite)1055 TEST_F(SiteInstanceTest, NoProcessPerSiteForEmptySite) {
1056 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1057 switches::kProcessPerSite);
1058 std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
1059 RenderProcessHost* host;
1060 scoped_refptr<SiteInstanceImpl> instance(
1061 SiteInstanceImpl::Create(browser_context.get()));
1062
1063 instance->SetSite(UrlInfo());
1064 EXPECT_TRUE(instance->HasSite());
1065 EXPECT_TRUE(instance->GetSiteURL().is_empty());
1066 host = instance->GetProcess();
1067
1068 EXPECT_FALSE(RenderProcessHostImpl::GetSoleProcessHostForSite(
1069 instance->GetIsolationContext(), SiteInfo()));
1070
1071 DrainMessageLoop();
1072 }
1073
1074 // Check that an URL is considered same-site with blob: and filesystem: URLs
1075 // with a matching inner origin. See https://crbug.com/726370.
TEST_F(SiteInstanceTest,IsSameSiteForNestedURLs)1076 TEST_F(SiteInstanceTest, IsSameSiteForNestedURLs) {
1077 TestBrowserContext context;
1078 GURL foo_url("http://foo.com/");
1079 GURL bar_url("http://bar.com/");
1080 GURL blob_foo_url("blob:http://foo.com/uuid");
1081 GURL blob_bar_url("blob:http://bar.com/uuid");
1082 GURL fs_foo_url("filesystem:http://foo.com/path/");
1083 GURL fs_bar_url("filesystem:http://bar.com/path/");
1084
1085 EXPECT_TRUE(IsSameSite(&context, foo_url, blob_foo_url));
1086 EXPECT_TRUE(IsSameSite(&context, blob_foo_url, foo_url));
1087 EXPECT_FALSE(IsSameSite(&context, foo_url, blob_bar_url));
1088 EXPECT_FALSE(IsSameSite(&context, blob_foo_url, bar_url));
1089
1090 EXPECT_TRUE(IsSameSite(&context, foo_url, fs_foo_url));
1091 EXPECT_TRUE(IsSameSite(&context, fs_foo_url, foo_url));
1092 EXPECT_FALSE(IsSameSite(&context, foo_url, fs_bar_url));
1093 EXPECT_FALSE(IsSameSite(&context, fs_foo_url, bar_url));
1094
1095 EXPECT_TRUE(IsSameSite(&context, blob_foo_url, fs_foo_url));
1096 EXPECT_FALSE(IsSameSite(&context, blob_foo_url, fs_bar_url));
1097 EXPECT_FALSE(IsSameSite(&context, blob_foo_url, blob_bar_url));
1098 EXPECT_FALSE(IsSameSite(&context, fs_foo_url, fs_bar_url));
1099
1100 // Verify that the scheme and ETLD+1 are used for comparison.
1101 GURL www_bar_url("http://www.bar.com/");
1102 GURL bar_org_url("http://bar.org/");
1103 GURL https_bar_url("https://bar.com/");
1104 EXPECT_TRUE(IsSameSite(&context, www_bar_url, bar_url));
1105 EXPECT_TRUE(IsSameSite(&context, www_bar_url, blob_bar_url));
1106 EXPECT_TRUE(IsSameSite(&context, www_bar_url, fs_bar_url));
1107 EXPECT_FALSE(IsSameSite(&context, bar_org_url, bar_url));
1108 EXPECT_FALSE(IsSameSite(&context, bar_org_url, blob_bar_url));
1109 EXPECT_FALSE(IsSameSite(&context, bar_org_url, fs_bar_url));
1110 EXPECT_FALSE(IsSameSite(&context, https_bar_url, bar_url));
1111 EXPECT_FALSE(IsSameSite(&context, https_bar_url, blob_bar_url));
1112 EXPECT_FALSE(IsSameSite(&context, https_bar_url, fs_bar_url));
1113 }
1114
TEST_F(SiteInstanceTest,StrictOriginIsolation)1115 TEST_F(SiteInstanceTest, StrictOriginIsolation) {
1116 base::test::ScopedFeatureList feature_list;
1117 feature_list.InitAndEnableFeature(features::kStrictOriginIsolation);
1118 EXPECT_TRUE(base::FeatureList::IsEnabled(features::kStrictOriginIsolation));
1119
1120 GURL isolated1_foo_url("http://isolated1.foo.com");
1121 GURL isolated2_foo_url("http://isolated2.foo.com");
1122 TestBrowserContext browser_context;
1123 IsolationContext isolation_context(&browser_context);
1124
1125 EXPECT_FALSE(IsSameSite(context(), isolated1_foo_url, isolated2_foo_url));
1126 EXPECT_NE(GetSiteForURL(isolation_context, isolated1_foo_url),
1127 GetSiteForURL(isolation_context, isolated2_foo_url));
1128
1129 // A bunch of special cases of origins.
1130 GURL secure_foo("https://foo.com");
1131 EXPECT_EQ(GetSiteForURL(isolation_context, secure_foo), secure_foo);
1132 GURL foo_with_port("http://foo.com:1234");
1133 EXPECT_EQ(GetSiteForURL(isolation_context, foo_with_port), foo_with_port);
1134 GURL local_host("http://localhost");
1135 EXPECT_EQ(GetSiteForURL(isolation_context, local_host), local_host);
1136 GURL ip_local_host("http://127.0.0.1");
1137 EXPECT_EQ(GetSiteForURL(isolation_context, ip_local_host), ip_local_host);
1138
1139 // The following should not get origin-specific SiteInstances, as they don't
1140 // have valid hosts.
1141 GURL about_url("about:flags");
1142 EXPECT_NE(GetSiteForURL(isolation_context, about_url), about_url);
1143
1144 GURL file_url("file:///home/user/foo");
1145 EXPECT_NE(GetSiteForURL(isolation_context, file_url), file_url);
1146 }
1147
TEST_F(SiteInstanceTest,IsolatedOrigins)1148 TEST_F(SiteInstanceTest, IsolatedOrigins) {
1149 GURL foo_url("http://www.foo.com");
1150 GURL isolated_foo_url("http://isolated.foo.com");
1151 GURL isolated_bar_url("http://isolated.bar.com");
1152
1153 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
1154
1155 EXPECT_FALSE(IsIsolatedOrigin(isolated_foo_url));
1156 EXPECT_TRUE(IsSameSite(context(), foo_url, isolated_foo_url));
1157
1158 policy->AddIsolatedOrigins({url::Origin::Create(isolated_foo_url)},
1159 IsolatedOriginSource::TEST);
1160 EXPECT_TRUE(IsIsolatedOrigin(isolated_foo_url));
1161 EXPECT_FALSE(IsIsolatedOrigin(foo_url));
1162 EXPECT_FALSE(IsIsolatedOrigin(GURL("http://foo.com")));
1163 EXPECT_FALSE(IsIsolatedOrigin(GURL("http://www.bar.com")));
1164 EXPECT_TRUE(IsIsolatedOrigin(isolated_foo_url));
1165 EXPECT_FALSE(IsIsolatedOrigin(foo_url));
1166 EXPECT_FALSE(IsIsolatedOrigin(GURL("http://foo.com")));
1167 EXPECT_FALSE(IsIsolatedOrigin(GURL("http://www.bar.com")));
1168 // Different scheme.
1169 EXPECT_FALSE(IsIsolatedOrigin(GURL("https://isolated.foo.com")));
1170 // Different port.
1171 EXPECT_TRUE(IsIsolatedOrigin(GURL("http://isolated.foo.com:12345")));
1172
1173 policy->AddIsolatedOrigins({url::Origin::Create(isolated_bar_url)},
1174 IsolatedOriginSource::TEST);
1175 EXPECT_TRUE(IsIsolatedOrigin(isolated_bar_url));
1176
1177 // IsSameSite should compare origins rather than sites if either URL is an
1178 // isolated origin.
1179 EXPECT_FALSE(IsSameSite(context(), foo_url, isolated_foo_url));
1180 EXPECT_FALSE(IsSameSite(context(), isolated_foo_url, foo_url));
1181 EXPECT_FALSE(IsSameSite(context(), isolated_foo_url, isolated_bar_url));
1182 EXPECT_TRUE(IsSameSite(context(), isolated_foo_url, isolated_foo_url));
1183
1184 // Ensure blob and filesystem URLs with isolated origins are compared
1185 // correctly.
1186 GURL isolated_blob_foo_url("blob:http://isolated.foo.com/uuid");
1187 EXPECT_TRUE(IsSameSite(context(), isolated_foo_url, isolated_blob_foo_url));
1188 GURL isolated_filesystem_foo_url("filesystem:http://isolated.foo.com/bar/");
1189 EXPECT_TRUE(
1190 IsSameSite(context(), isolated_foo_url, isolated_filesystem_foo_url));
1191
1192 // The site URL for an isolated origin should be the full origin rather than
1193 // eTLD+1.
1194 IsolationContext isolation_context(context());
1195 EXPECT_EQ(isolated_foo_url,
1196 GetSiteForURL(isolation_context, isolated_foo_url));
1197 EXPECT_EQ(
1198 isolated_foo_url,
1199 GetSiteForURL(isolation_context, GURL("http://isolated.foo.com:12345")));
1200 EXPECT_EQ(isolated_bar_url,
1201 GetSiteForURL(isolation_context, isolated_bar_url));
1202 EXPECT_EQ(isolated_foo_url,
1203 GetSiteForURL(isolation_context, isolated_blob_foo_url));
1204 EXPECT_EQ(isolated_foo_url,
1205 GetSiteForURL(isolation_context, isolated_filesystem_foo_url));
1206
1207 // Isolated origins always require a dedicated process.
1208 EXPECT_TRUE(
1209 DoesURLRequireDedicatedProcess(isolation_context, isolated_foo_url));
1210 EXPECT_TRUE(
1211 DoesURLRequireDedicatedProcess(isolation_context, isolated_bar_url));
1212 EXPECT_TRUE(
1213 DoesURLRequireDedicatedProcess(isolation_context, isolated_blob_foo_url));
1214 EXPECT_TRUE(DoesURLRequireDedicatedProcess(isolation_context,
1215 isolated_filesystem_foo_url));
1216
1217 // Cleanup.
1218 policy->RemoveIsolatedOriginForTesting(url::Origin::Create(isolated_foo_url));
1219 policy->RemoveIsolatedOriginForTesting(url::Origin::Create(isolated_bar_url));
1220 }
1221
TEST_F(SiteInstanceTest,IsolatedOriginsWithPort)1222 TEST_F(SiteInstanceTest, IsolatedOriginsWithPort) {
1223 GURL isolated_foo_url("http://isolated.foo.com");
1224 GURL isolated_foo_with_port("http://isolated.foo.com:12345");
1225
1226 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
1227
1228 {
1229 base::test::MockLog mock_log;
1230 EXPECT_CALL(
1231 mock_log,
1232 Log(::logging::LOG_ERROR, testing::_, testing::_, testing::_,
1233 ::testing::HasSubstr("Ignoring port number in isolated origin: "
1234 "http://isolated.foo.com:12345")))
1235 .Times(1);
1236 mock_log.StartCapturingLogs();
1237
1238 policy->AddIsolatedOrigins({url::Origin::Create(isolated_foo_with_port)},
1239 IsolatedOriginSource::TEST);
1240 }
1241
1242 EXPECT_TRUE(IsIsolatedOrigin(isolated_foo_url));
1243 EXPECT_TRUE(IsIsolatedOrigin(isolated_foo_with_port));
1244
1245 IsolationContext isolation_context(context());
1246 EXPECT_EQ(isolated_foo_url,
1247 GetSiteForURL(isolation_context, isolated_foo_url));
1248 EXPECT_EQ(isolated_foo_url,
1249 GetSiteForURL(isolation_context, isolated_foo_with_port));
1250
1251 // Cleanup.
1252 policy->RemoveIsolatedOriginForTesting(url::Origin::Create(isolated_foo_url));
1253 policy->RemoveIsolatedOriginForTesting(
1254 url::Origin::Create(isolated_foo_with_port));
1255 }
1256
1257 // Check that only valid isolated origins are allowed to be registered.
TEST_F(SiteInstanceTest,IsValidIsolatedOrigin)1258 TEST_F(SiteInstanceTest, IsValidIsolatedOrigin) {
1259 // Unique origins are invalid, as are invalid URLs that resolve to
1260 // unique origins.
1261 EXPECT_FALSE(IsolatedOriginUtil::IsValidIsolatedOrigin(url::Origin()));
1262 EXPECT_FALSE(IsolatedOriginUtil::IsValidIsolatedOrigin(
1263 url::Origin::Create(GURL("invalid.url"))));
1264
1265 // IP addresses are ok.
1266 EXPECT_TRUE(IsolatedOriginUtil::IsValidIsolatedOrigin(
1267 url::Origin::Create(GURL("http://127.0.0.1"))));
1268
1269 // Hosts without a valid registry-controlled domain are disallowed. This
1270 // includes hosts that are themselves a registry-controlled domain.
1271 EXPECT_FALSE(IsolatedOriginUtil::IsValidIsolatedOrigin(
1272 url::Origin::Create(GURL("http://.com/"))));
1273 EXPECT_FALSE(IsolatedOriginUtil::IsValidIsolatedOrigin(
1274 url::Origin::Create(GURL("http://.com./"))));
1275 EXPECT_FALSE(IsolatedOriginUtil::IsValidIsolatedOrigin(
1276 url::Origin::Create(GURL("http://foo/"))));
1277 EXPECT_FALSE(IsolatedOriginUtil::IsValidIsolatedOrigin(
1278 url::Origin::Create(GURL("http://co.uk/"))));
1279 EXPECT_TRUE(IsolatedOriginUtil::IsValidIsolatedOrigin(
1280 url::Origin::Create(GURL("http://foo.bar.baz/"))));
1281
1282 // Scheme must be HTTP or HTTPS.
1283 EXPECT_FALSE(IsolatedOriginUtil::IsValidIsolatedOrigin(
1284 url::Origin::Create(GetWebUIURL(kChromeUIGpuHost))));
1285 EXPECT_TRUE(IsolatedOriginUtil::IsValidIsolatedOrigin(
1286 url::Origin::Create(GURL("http://a.com"))));
1287 EXPECT_TRUE(IsolatedOriginUtil::IsValidIsolatedOrigin(
1288 url::Origin::Create(GURL("https://b.co.uk"))));
1289
1290 // Trailing dot is disallowed.
1291 EXPECT_FALSE(IsolatedOriginUtil::IsValidIsolatedOrigin(
1292 url::Origin::Create(GURL("http://a.com."))));
1293 }
1294
TEST_F(SiteInstanceTest,SubdomainOnIsolatedSite)1295 TEST_F(SiteInstanceTest, SubdomainOnIsolatedSite) {
1296 GURL isolated_url("http://isolated.com");
1297 GURL foo_isolated_url("http://foo.isolated.com");
1298
1299 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
1300 policy->AddIsolatedOrigins({url::Origin::Create(isolated_url)},
1301 IsolatedOriginSource::TEST);
1302
1303 EXPECT_TRUE(IsIsolatedOrigin(isolated_url));
1304 EXPECT_TRUE(IsIsolatedOrigin(foo_isolated_url));
1305 EXPECT_FALSE(IsIsolatedOrigin(GURL("http://unisolated.com")));
1306 EXPECT_FALSE(IsIsolatedOrigin(GURL("http://isolated.foo.com")));
1307 // Wrong scheme.
1308 EXPECT_FALSE(IsIsolatedOrigin(GURL("https://foo.isolated.com")));
1309 // Subdomain with a different port.
1310 EXPECT_TRUE(IsIsolatedOrigin(GURL("http://foo.isolated.com:12345")));
1311
1312 // Appending a trailing dot to a URL should not bypass process isolation.
1313 EXPECT_TRUE(IsIsolatedOrigin(GURL("http://isolated.com.")));
1314 EXPECT_TRUE(IsIsolatedOrigin(GURL("http://foo.isolated.com.")));
1315
1316 // A new SiteInstance created for a subdomain on an isolated origin
1317 // should use the isolated origin's host and not its own host as the site
1318 // URL.
1319 IsolationContext isolation_context(context());
1320 EXPECT_EQ(isolated_url, GetSiteForURL(isolation_context, foo_isolated_url));
1321
1322 EXPECT_TRUE(
1323 DoesURLRequireDedicatedProcess(isolation_context, foo_isolated_url));
1324
1325 EXPECT_TRUE(IsSameSite(context(), isolated_url, foo_isolated_url));
1326 EXPECT_TRUE(IsSameSite(context(), foo_isolated_url, isolated_url));
1327
1328 // Don't try to match subdomains on IP addresses.
1329 GURL isolated_ip("http://127.0.0.1");
1330 policy->AddIsolatedOrigins({url::Origin::Create(isolated_ip)},
1331 IsolatedOriginSource::TEST);
1332 EXPECT_TRUE(IsIsolatedOrigin(isolated_ip));
1333 EXPECT_FALSE(IsIsolatedOrigin(GURL("http://42.127.0.0.1")));
1334
1335 // Cleanup.
1336 policy->RemoveIsolatedOriginForTesting(url::Origin::Create(isolated_url));
1337 policy->RemoveIsolatedOriginForTesting(url::Origin::Create(isolated_ip));
1338 }
1339
TEST_F(SiteInstanceTest,SubdomainOnIsolatedOrigin)1340 TEST_F(SiteInstanceTest, SubdomainOnIsolatedOrigin) {
1341 GURL foo_url("http://foo.com");
1342 GURL isolated_foo_url("http://isolated.foo.com");
1343 GURL bar_isolated_foo_url("http://bar.isolated.foo.com");
1344 GURL baz_isolated_foo_url("http://baz.isolated.foo.com");
1345
1346 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
1347 policy->AddIsolatedOrigins({url::Origin::Create(isolated_foo_url)},
1348 IsolatedOriginSource::TEST);
1349
1350 EXPECT_FALSE(IsIsolatedOrigin(foo_url));
1351 EXPECT_TRUE(IsIsolatedOrigin(isolated_foo_url));
1352 EXPECT_TRUE(IsIsolatedOrigin(bar_isolated_foo_url));
1353 EXPECT_TRUE(IsIsolatedOrigin(baz_isolated_foo_url));
1354
1355 IsolationContext isolation_context(context());
1356 EXPECT_EQ(foo_url, GetSiteForURL(isolation_context, foo_url));
1357 EXPECT_EQ(isolated_foo_url,
1358 GetSiteForURL(isolation_context, isolated_foo_url));
1359 EXPECT_EQ(isolated_foo_url,
1360 GetSiteForURL(isolation_context, bar_isolated_foo_url));
1361 EXPECT_EQ(isolated_foo_url,
1362 GetSiteForURL(isolation_context, baz_isolated_foo_url));
1363
1364 if (!AreAllSitesIsolatedForTesting()) {
1365 EXPECT_FALSE(DoesURLRequireDedicatedProcess(isolation_context, foo_url));
1366 }
1367 EXPECT_TRUE(
1368 DoesURLRequireDedicatedProcess(isolation_context, isolated_foo_url));
1369 EXPECT_TRUE(
1370 DoesURLRequireDedicatedProcess(isolation_context, bar_isolated_foo_url));
1371 EXPECT_TRUE(
1372 DoesURLRequireDedicatedProcess(isolation_context, baz_isolated_foo_url));
1373
1374 EXPECT_FALSE(IsSameSite(context(), foo_url, isolated_foo_url));
1375 EXPECT_FALSE(IsSameSite(context(), isolated_foo_url, foo_url));
1376 EXPECT_FALSE(IsSameSite(context(), foo_url, bar_isolated_foo_url));
1377 EXPECT_FALSE(IsSameSite(context(), bar_isolated_foo_url, foo_url));
1378 EXPECT_TRUE(IsSameSite(context(), bar_isolated_foo_url, isolated_foo_url));
1379 EXPECT_TRUE(IsSameSite(context(), isolated_foo_url, bar_isolated_foo_url));
1380 EXPECT_TRUE(
1381 IsSameSite(context(), bar_isolated_foo_url, baz_isolated_foo_url));
1382 EXPECT_TRUE(
1383 IsSameSite(context(), baz_isolated_foo_url, bar_isolated_foo_url));
1384
1385 // Cleanup.
1386 policy->RemoveIsolatedOriginForTesting(url::Origin::Create(isolated_foo_url));
1387 }
1388
TEST_F(SiteInstanceTest,MultipleIsolatedOriginsWithCommonSite)1389 TEST_F(SiteInstanceTest, MultipleIsolatedOriginsWithCommonSite) {
1390 GURL foo_url("http://foo.com");
1391 GURL bar_foo_url("http://bar.foo.com");
1392 GURL baz_bar_foo_url("http://baz.bar.foo.com");
1393 GURL qux_baz_bar_foo_url("http://qux.baz.bar.foo.com");
1394
1395 IsolationContext isolation_context(context());
1396 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
1397 policy->AddIsolatedOrigins(
1398 {url::Origin::Create(foo_url), url::Origin::Create(baz_bar_foo_url)},
1399 IsolatedOriginSource::TEST);
1400
1401 EXPECT_TRUE(IsIsolatedOrigin(foo_url));
1402 EXPECT_TRUE(IsIsolatedOrigin(bar_foo_url));
1403 EXPECT_TRUE(IsIsolatedOrigin(baz_bar_foo_url));
1404 EXPECT_TRUE(IsIsolatedOrigin(qux_baz_bar_foo_url));
1405
1406 EXPECT_EQ(foo_url, GetSiteForURL(isolation_context, foo_url));
1407 EXPECT_EQ(foo_url, GetSiteForURL(isolation_context, bar_foo_url));
1408 EXPECT_EQ(baz_bar_foo_url, GetSiteForURL(isolation_context, baz_bar_foo_url));
1409 EXPECT_EQ(baz_bar_foo_url,
1410 GetSiteForURL(isolation_context, qux_baz_bar_foo_url));
1411
1412 EXPECT_TRUE(DoesURLRequireDedicatedProcess(isolation_context, foo_url));
1413 EXPECT_TRUE(DoesURLRequireDedicatedProcess(isolation_context, bar_foo_url));
1414 EXPECT_TRUE(
1415 DoesURLRequireDedicatedProcess(isolation_context, baz_bar_foo_url));
1416 EXPECT_TRUE(
1417 DoesURLRequireDedicatedProcess(isolation_context, qux_baz_bar_foo_url));
1418
1419 EXPECT_TRUE(IsSameSite(context(), foo_url, bar_foo_url));
1420 EXPECT_FALSE(IsSameSite(context(), foo_url, baz_bar_foo_url));
1421 EXPECT_FALSE(IsSameSite(context(), foo_url, qux_baz_bar_foo_url));
1422
1423 EXPECT_FALSE(IsSameSite(context(), bar_foo_url, baz_bar_foo_url));
1424 EXPECT_FALSE(IsSameSite(context(), bar_foo_url, qux_baz_bar_foo_url));
1425
1426 EXPECT_TRUE(IsSameSite(context(), baz_bar_foo_url, qux_baz_bar_foo_url));
1427
1428 // Cleanup.
1429 policy->RemoveIsolatedOriginForTesting(url::Origin::Create(foo_url));
1430 policy->RemoveIsolatedOriginForTesting(url::Origin::Create(baz_bar_foo_url));
1431 }
1432
1433 // Check that new SiteInstances correctly preserve the full URL that was used
1434 // to initialize their site URL.
TEST_F(SiteInstanceTest,OriginalURL)1435 TEST_F(SiteInstanceTest, OriginalURL) {
1436 GURL original_url("https://foo.com/");
1437 GURL app_url("https://app.com/");
1438 EffectiveURLContentBrowserClient modified_client(
1439 original_url, app_url, /* requires_dedicated_process */ true);
1440 ContentBrowserClient* regular_client =
1441 SetBrowserClientForTesting(&modified_client);
1442 std::unique_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
1443
1444 SiteInfo expected_site_info(
1445 app_url /* site_url */, original_url /* process_lock_url */,
1446 false /* is_origin_keyed */,
1447 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
1448
1449 // New SiteInstance in a new BrowsingInstance with a predetermined URL. In
1450 // this and subsequent cases, the site URL should consist of the effective
1451 // URL's site, and the process lock URL and original URLs should be based on
1452 // |original_url|.
1453 {
1454 scoped_refptr<SiteInstanceImpl> site_instance =
1455 SiteInstanceImpl::CreateForUrlInfo(
1456 browser_context.get(), UrlInfo::CreateForTesting(original_url),
1457 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
1458 EXPECT_EQ(expected_site_info, site_instance->GetSiteInfo());
1459 EXPECT_EQ(original_url, site_instance->original_url());
1460 }
1461
1462 // New related SiteInstance from an existing SiteInstance with a
1463 // predetermined URL.
1464 {
1465 scoped_refptr<SiteInstanceImpl> bar_site_instance =
1466 SiteInstanceImpl::CreateForUrlInfo(
1467 browser_context.get(),
1468 UrlInfo::CreateForTesting(GURL("https://bar.com/")),
1469 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
1470 scoped_refptr<SiteInstance> site_instance =
1471 bar_site_instance->GetRelatedSiteInstance(original_url);
1472 auto* site_instance_impl =
1473 static_cast<SiteInstanceImpl*>(site_instance.get());
1474 EXPECT_EQ(expected_site_info, site_instance_impl->GetSiteInfo());
1475 EXPECT_EQ(original_url, site_instance_impl->original_url());
1476 }
1477
1478 // New SiteInstance with a lazily assigned site URL.
1479 {
1480 scoped_refptr<SiteInstanceImpl> site_instance =
1481 SiteInstanceImpl::Create(browser_context.get());
1482 EXPECT_FALSE(site_instance->HasSite());
1483 EXPECT_TRUE(site_instance->original_url().is_empty());
1484 site_instance->SetSite(UrlInfo::CreateForTesting(original_url));
1485 EXPECT_EQ(expected_site_info, site_instance->GetSiteInfo());
1486 EXPECT_EQ(original_url, site_instance->original_url());
1487 }
1488
1489 SetBrowserClientForTesting(regular_client);
1490 }
1491
1492 namespace {
1493
ProcessLockFromString(const std::string & url)1494 ProcessLock ProcessLockFromString(const std::string& url) {
1495 return ProcessLock(
1496 SiteInfo(GURL(url), GURL(url), false /* is_origin_keyed */,
1497 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated()));
1498 }
1499
1500 } // namespace
1501
TEST_F(SiteInstanceTest,IsProcessLockASite)1502 TEST_F(SiteInstanceTest, IsProcessLockASite) {
1503 EXPECT_FALSE(ProcessLockFromString("http://").IsASiteOrOrigin());
1504 EXPECT_FALSE(ProcessLockFromString("").IsASiteOrOrigin());
1505 EXPECT_FALSE(ProcessLockFromString("google.com").IsASiteOrOrigin());
1506 EXPECT_FALSE(ProcessLockFromString("http:").IsASiteOrOrigin());
1507 EXPECT_FALSE(ProcessLockFromString("chrome:").IsASiteOrOrigin());
1508
1509 EXPECT_TRUE(ProcessLockFromString("http://foo.com").IsASiteOrOrigin());
1510 EXPECT_TRUE(ProcessLockFromString("http://bar.foo.com").IsASiteOrOrigin());
1511 EXPECT_TRUE(
1512 ProcessLockFromString("http://user:pass@google.com:99/foo;bar?q=a#ref")
1513 .IsASiteOrOrigin());
1514 }
1515
TEST_F(SiteInstanceTest,StartIsolatingSite)1516 TEST_F(SiteInstanceTest, StartIsolatingSite) {
1517 // Skip this test case if dynamic isolated origins are not enabled.
1518 if (!SiteIsolationPolicy::AreDynamicIsolatedOriginsEnabled())
1519 return;
1520
1521 IsolationContext isolation_context(context());
1522 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
1523
1524 // StartIsolatingSite() should convert the URL to a site before isolating it.
1525 SiteInstance::StartIsolatingSite(context(),
1526 GURL("http://bar.foo.com/foo/bar.html"));
1527 EXPECT_TRUE(IsIsolatedOrigin(GURL("http://foo.com")));
1528 SiteInstance::StartIsolatingSite(context(), GURL("https://a.b.c.com:8000/"));
1529 EXPECT_TRUE(IsIsolatedOrigin(GURL("https://c.com")));
1530 SiteInstance::StartIsolatingSite(context(),
1531 GURL("http://bar.com/foo/bar.html"));
1532 EXPECT_TRUE(IsIsolatedOrigin(GURL("http://bar.com")));
1533
1534 // Attempts to isolate an unsupported isolated origin should be ignored.
1535 GURL data_url("data:,");
1536 GURL blank_url(url::kAboutBlankURL);
1537 SiteInstance::StartIsolatingSite(context(), data_url);
1538 SiteInstance::StartIsolatingSite(context(), blank_url);
1539 EXPECT_FALSE(IsIsolatedOrigin(data_url));
1540 EXPECT_FALSE(IsIsolatedOrigin(blank_url));
1541
1542 // Cleanup.
1543 policy->RemoveStateForBrowserContext(*context());
1544 }
1545
TEST_F(SiteInstanceTest,CreateForUrlInfo)1546 TEST_F(SiteInstanceTest, CreateForUrlInfo) {
1547 class CustomBrowserClient : public EffectiveURLContentBrowserClient {
1548 public:
1549 CustomBrowserClient(const GURL& url_to_modify, const GURL& url_to_return)
1550 : EffectiveURLContentBrowserClient(url_to_modify,
1551 url_to_return,
1552 false) {}
1553
1554 void set_should_not_assign_url(const GURL& url) {
1555 should_not_assign_url_ = url;
1556 }
1557
1558 bool ShouldAssignSiteForURL(const GURL& url) override {
1559 return url != should_not_assign_url_;
1560 }
1561
1562 private:
1563 GURL should_not_assign_url_;
1564 };
1565
1566 const GURL kNonIsolatedUrl("https://bar.com/");
1567 const GURL kIsolatedUrl("https://isolated.com/");
1568 const GURL kFileUrl("file:///C:/Downloads/");
1569 const GURL kCustomUrl("http://custom.foo.com");
1570 const GURL kCustomAppUrl(std::string(kCustomStandardScheme) + "://custom");
1571 CustomBrowserClient modified_client(kCustomUrl, kCustomAppUrl);
1572 ContentBrowserClient* regular_client =
1573 SetBrowserClientForTesting(&modified_client);
1574
1575 ChildProcessSecurityPolicyImpl::GetInstance()->AddIsolatedOrigins(
1576 {url::Origin::Create(kIsolatedUrl)}, IsolatedOriginSource::TEST);
1577
1578 auto instance1 = SiteInstanceImpl::CreateForUrlInfo(
1579 context(), UrlInfo::CreateForTesting(kNonIsolatedUrl),
1580 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
1581 auto instance2 = SiteInstanceImpl::CreateForUrlInfo(
1582 context(), UrlInfo::CreateForTesting(kIsolatedUrl),
1583 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
1584 auto instance3 = SiteInstanceImpl::CreateForUrlInfo(
1585 context(), UrlInfo::CreateForTesting(kFileUrl),
1586 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
1587 auto instance4 = SiteInstanceImpl::CreateForUrlInfo(
1588 context(), UrlInfo::CreateForTesting(GURL(url::kAboutBlankURL)),
1589 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
1590 auto instance5 = SiteInstanceImpl::CreateForUrlInfo(
1591 context(), UrlInfo::CreateForTesting(kCustomUrl),
1592 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
1593
1594 if (AreDefaultSiteInstancesEnabled()) {
1595 EXPECT_TRUE(instance1->IsDefaultSiteInstance());
1596 } else {
1597 EXPECT_FALSE(instance1->IsDefaultSiteInstance());
1598 EXPECT_EQ(kNonIsolatedUrl, instance1->GetSiteURL());
1599 }
1600 EXPECT_TRUE(instance1->DoesSiteInfoForURLMatch(
1601 UrlInfo::CreateForTesting(kNonIsolatedUrl)));
1602 EXPECT_TRUE(instance1->IsSameSiteWithURL(kNonIsolatedUrl));
1603
1604 EXPECT_FALSE(instance2->IsDefaultSiteInstance());
1605 EXPECT_EQ(kIsolatedUrl, instance2->GetSiteURL());
1606 EXPECT_TRUE(instance2->DoesSiteInfoForURLMatch(
1607 UrlInfo::CreateForTesting(kIsolatedUrl)));
1608 EXPECT_TRUE(instance2->IsSameSiteWithURL(kIsolatedUrl));
1609
1610 EXPECT_FALSE(instance3->IsDefaultSiteInstance());
1611 EXPECT_EQ(GURL("file:"), instance3->GetSiteURL());
1612 EXPECT_TRUE(
1613 instance3->DoesSiteInfoForURLMatch(UrlInfo::CreateForTesting(kFileUrl)));
1614 // Not same site because file URL's don't have a host.
1615 EXPECT_FALSE(instance3->IsSameSiteWithURL(kFileUrl));
1616
1617 // about:blank URLs generate a SiteInstance without the site URL set because
1618 // ShouldAssignSiteForURL() returns false and the expectation is that the
1619 // site URL will be set at a later time.
1620 EXPECT_FALSE(instance4->IsDefaultSiteInstance());
1621 EXPECT_FALSE(instance4->HasSite());
1622 EXPECT_FALSE(instance4->DoesSiteInfoForURLMatch(
1623 UrlInfo::CreateForTesting(GURL(url::kAboutBlankURL))));
1624 EXPECT_FALSE(instance4->IsSameSiteWithURL(GURL(url::kAboutBlankURL)));
1625
1626 // Test the standard effective URL case.
1627 EXPECT_TRUE(instance5->HasSite());
1628 if (AreDefaultSiteInstancesEnabled()) {
1629 EXPECT_TRUE(instance5->IsDefaultSiteInstance());
1630 } else {
1631 EXPECT_FALSE(instance5->IsDefaultSiteInstance());
1632 EXPECT_EQ("custom-standard://custom/", instance5->GetSiteURL());
1633 EXPECT_EQ("http://foo.com/", instance5->GetSiteInfo().process_lock_url());
1634 }
1635 EXPECT_TRUE(instance5->DoesSiteInfoForURLMatch(
1636 UrlInfo::CreateForTesting(kCustomUrl)));
1637 EXPECT_TRUE(instance5->IsSameSiteWithURL(kCustomUrl));
1638
1639 // Test the "do not assign site" case with an effective URL.
1640 modified_client.set_should_not_assign_url(kCustomUrl);
1641
1642 if (instance5->IsDefaultSiteInstance()) {
1643 // Verify that the default SiteInstance is no longer a site match
1644 // with |kCustomUrl| because this URL now requires a SiteInstance that
1645 // does not have its site set.
1646 EXPECT_FALSE(instance5->DoesSiteInfoForURLMatch(
1647 UrlInfo::CreateForTesting(kCustomUrl)));
1648 EXPECT_FALSE(instance5->IsSameSiteWithURL(kCustomUrl));
1649 }
1650
1651 // Verify that |kCustomUrl| will always construct a SiteInstance without
1652 // a site set now.
1653 auto instance6 = SiteInstanceImpl::CreateForUrlInfo(
1654 context(), UrlInfo::CreateForTesting(kCustomUrl),
1655 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
1656 EXPECT_FALSE(instance6->IsDefaultSiteInstance());
1657 EXPECT_FALSE(instance6->HasSite());
1658 EXPECT_FALSE(instance6->DoesSiteInfoForURLMatch(
1659 UrlInfo::CreateForTesting(kCustomUrl)));
1660 EXPECT_FALSE(instance6->IsSameSiteWithURL(kCustomUrl));
1661
1662 SetBrowserClientForTesting(regular_client);
1663 }
1664
TEST_F(SiteInstanceTest,CreateForGuest)1665 TEST_F(SiteInstanceTest, CreateForGuest) {
1666 const GURL kGuestUrl(std::string(kGuestScheme) + "://abc123/path");
1667
1668 // Verify that a SiteInstance created with CreateForUrlInfo() is not
1669 // considered a <webview> guest and has the path removed for the site URL like
1670 // any other standard URL.
1671 auto instance1 = SiteInstanceImpl::CreateForUrlInfo(
1672 context(), UrlInfo::CreateForTesting(kGuestUrl),
1673 CoopCoepCrossOriginIsolatedInfo::CreateNonIsolated());
1674 EXPECT_FALSE(instance1->IsGuest());
1675 if (AreAllSitesIsolatedForTesting()) {
1676 EXPECT_NE(kGuestUrl, instance1->GetSiteURL());
1677 EXPECT_EQ(GURL(std::string(kGuestScheme) + "://abc123/"),
1678 instance1->GetSiteURL());
1679 } else {
1680 EXPECT_TRUE(instance1->IsDefaultSiteInstance());
1681 }
1682
1683 // Verify that a SiteInstance created with CreateForGuest() is considered
1684 // a <webview> guest and has a site URL that is identical to what was passed
1685 // to CreateForGuest().
1686 auto instance2 = SiteInstanceImpl::CreateForGuest(context(), kGuestUrl);
1687 EXPECT_TRUE(instance2->IsGuest());
1688 EXPECT_EQ(kGuestUrl, instance2->GetSiteURL());
1689
1690 // Verify that a SiteInstance being considered a <webview> guest does not
1691 // depend on using a specific scheme.
1692 const GURL kGuestUrl2("my-special-scheme://abc123/path");
1693 auto instance3 = SiteInstanceImpl::CreateForGuest(context(), kGuestUrl2);
1694 EXPECT_TRUE(instance3->IsGuest());
1695 EXPECT_EQ(kGuestUrl2, instance3->GetSiteURL());
1696 }
1697
TEST_F(SiteInstanceTest,DoesSiteRequireDedicatedProcess)1698 TEST_F(SiteInstanceTest, DoesSiteRequireDedicatedProcess) {
1699 class CustomBrowserClient : public EffectiveURLContentBrowserClient {
1700 public:
1701 CustomBrowserClient(const GURL& url_to_modify,
1702 const GURL& url_to_return,
1703 bool requires_dedicated_process,
1704 const std::string& additional_webui_scheme)
1705 : EffectiveURLContentBrowserClient(url_to_modify,
1706 url_to_return,
1707 requires_dedicated_process),
1708 additional_webui_scheme_(additional_webui_scheme) {
1709 DCHECK(!additional_webui_scheme.empty());
1710 }
1711
1712 private:
1713 void GetAdditionalWebUISchemes(
1714 std::vector<std::string>* additional_schemes) override {
1715 additional_schemes->push_back(additional_webui_scheme_);
1716 }
1717
1718 const std::string additional_webui_scheme_;
1719 };
1720
1721 const std::vector<std::string> kUrlsThatDoNotRequireADedicatedProcess = {
1722 "about:blank",
1723 "http://foo.com",
1724 "data:text/html,Hello World!",
1725 "file:///tmp/test.txt",
1726 };
1727
1728 const char* kExplicitlyIsolatedURL = "http://isolated.com";
1729 const char* kCustomWebUIScheme = "my-webui";
1730 const char* kCustomWebUIUrl = "my-webui://show-stats";
1731 const char* kCustomUrl = "http://custom.foo.com";
1732 const char* kCustomAppUrl = "custom-scheme://custom";
1733 const std::vector<std::string> kUrlsThatAlwaysRequireADedicatedProcess = {
1734 kExplicitlyIsolatedURL,
1735 kUnreachableWebDataURL,
1736 GetWebUIURLString("network-error"),
1737 kCustomUrl,
1738 kCustomAppUrl,
1739 kCustomWebUIUrl,
1740 };
1741
1742 CustomBrowserClient modified_client(GURL(kCustomUrl), GURL(kCustomAppUrl),
1743 /* requires_dedicated_process */ true,
1744 kCustomWebUIScheme);
1745 ContentBrowserClient* regular_client =
1746 SetBrowserClientForTesting(&modified_client);
1747
1748 IsolationContext isolation_context(context());
1749 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
1750 policy->AddIsolatedOrigins(
1751 {url::Origin::Create(GURL(kExplicitlyIsolatedURL))},
1752 IsolatedOriginSource::TEST);
1753
1754 for (const auto& url : kUrlsThatAlwaysRequireADedicatedProcess) {
1755 EXPECT_TRUE(DoesURLRequireDedicatedProcess(isolation_context, GURL(url)));
1756 }
1757
1758 for (const auto& url : kUrlsThatDoNotRequireADedicatedProcess) {
1759 EXPECT_EQ(AreAllSitesIsolatedForTesting(),
1760 DoesURLRequireDedicatedProcess(isolation_context, GURL(url)));
1761 }
1762 SetBrowserClientForTesting(regular_client);
1763 }
1764
1765 } // namespace content
1766