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