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 #ifndef CONTENT_PUBLIC_BROWSER_SITE_INSTANCE_H_ 6 #define CONTENT_PUBLIC_BROWSER_SITE_INSTANCE_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include "base/memory/ref_counted.h" 12 #include "content/common/content_export.h" 13 #include "url/gurl.h" 14 15 namespace content { 16 class BrowserContext; 17 class RenderProcessHost; 18 19 /////////////////////////////////////////////////////////////////////////////// 20 // SiteInstance interface. 21 // 22 // A SiteInstance represents a group of web pages that must live in the same 23 // renderer process. Pages able to synchronously script each other will always 24 // be placed in the same SiteInstance. Pages unable to synchronously script 25 // each other may also be placed in the same SiteInstance, as determined by the 26 // process model. 27 // 28 // A page's SiteInstance is determined by a combination of where the page comes 29 // from (the site) and which frames have references to each other (the 30 // instance). Here, a "site" is similar to the page's origin but includes only 31 // the registered domain name and scheme, not the port or subdomains. This 32 // accounts for the fact that changes to document.domain allow similar origin 33 // pages with different ports or subdomains to script each other. An "instance" 34 // includes all frames that might be able to script each other because of how 35 // they were created (e.g., window.open or targeted links). We represent 36 // instances using the BrowsingInstance class. 37 // 38 // Four process models are currently supported: 39 // 40 // PROCESS PER SITE INSTANCE (the current default): SiteInstances are created 41 // (1) when the user manually creates a new tab (which also creates a new 42 // BrowsingInstance), and (2) when the user navigates across site boundaries 43 // (which uses the same BrowsingInstance). If the user navigates within a site, 44 // the same SiteInstance is used. Caveat: we currently allow renderer-initiated 45 // cross-site navigations to stay in the same SiteInstance, to preserve 46 // compatibility in cases like cross-site iframes that open popups. This means 47 // that most SiteInstances will contain pages from multiple sites. 48 // 49 // SITE PER PROCESS (currently experimental): is the most granular process 50 // model and is made possible by our support for out-of-process iframes. A 51 // subframe will be given a different SiteInstance if its site differs from the 52 // containing document. Cross-site navigation of top-level frames or subframes 53 // will trigger a change of SiteInstances, even if the navigation is renderer 54 // initiated. In this model, each process can be dedicated to documents from 55 // just one site, allowing the same origin policy to be enforced by the sandbox. 56 // 57 // PROCESS PER TAB: SiteInstances are created when the user manually creates a 58 // new tab, but not when navigating across site boundaries (unless a process 59 // swap is required for security reasons, such as navigating from a privileged 60 // WebUI page to a normal web page). This corresponds to one process per 61 // BrowsingInstance. 62 // 63 // PROCESS PER SITE: We consolidate all SiteInstances for a given site into the 64 // same process, throughout the entire browser context. This ensures that only 65 // one process will be used for each site. Note that there is no strict process 66 // isolation of sites in this mode, so a given SiteInstance can still contain 67 // pages from multiple sites. 68 // 69 // Each NavigationEntry for a WebContents points to the SiteInstance that 70 // rendered it. Each RenderFrameHost also points to the SiteInstance that it is 71 // associated with. A SiteInstance keeps track of the number of these 72 // references and deletes itself when the count goes to zero. This means that 73 // a SiteInstance is only live as long as it is accessible, either from new 74 // tabs with no NavigationEntries or in NavigationEntries in the history. 75 // 76 /////////////////////////////////////////////////////////////////////////////// 77 class CONTENT_EXPORT SiteInstance : public base::RefCounted<SiteInstance> { 78 public: 79 // Returns a unique ID for this SiteInstance. 80 virtual int32_t GetId() = 0; 81 82 // Returns a unique ID for the BrowsingInstance (i.e., group of related 83 // browsing contexts) to which this SiteInstance belongs. This allows callers 84 // to identify which SiteInstances can asynchronously script each other. 85 virtual int32_t GetBrowsingInstanceId() = 0; 86 87 // Whether this SiteInstance has a running process associated with it. 88 // This may return true before the first call to GetProcess(), in cases where 89 // we use process-per-site and there is an existing process available. 90 virtual bool HasProcess() = 0; 91 92 // Returns the current RenderProcessHost being used to render pages for this 93 // SiteInstance. If there is no RenderProcessHost (because either none has 94 // yet been created or there was one but it was cleanly destroyed (e.g. when 95 // it is not actively being used), then this method will create a new 96 // RenderProcessHost (and a new ID). Note that renderer process crashes leave 97 // the current RenderProcessHost (and ID) in place. 98 // 99 // For sites that require process-per-site mode (e.g., WebUI), this will 100 // ensure only one RenderProcessHost for the site exists within the 101 // BrowserContext. 102 virtual content::RenderProcessHost* GetProcess() = 0; 103 104 // Browser context to which this SiteInstance (and all related 105 // SiteInstances) belongs. 106 virtual content::BrowserContext* GetBrowserContext() = 0; 107 108 // Get the web site that this SiteInstance is rendering pages for. This 109 // includes the scheme and registered domain, but not the port. 110 // 111 // NOTE: In most cases, code should be performing checks against the origin 112 // returned by |RenderFrameHost::GetLastCommittedOrigin()|. In contrast, the 113 // GURL returned by |GetSiteURL()| should not be considered authoritative 114 // because: 115 // - a SiteInstance can host pages from multiple sites if "site per process" 116 // is not enabled and the SiteInstance isn't hosting pages that require 117 // process isolation (e.g. WebUI or extensions) 118 // - even with site per process, the site URL is not an origin: while often 119 // derived from the origin, it only contains the scheme and the eTLD + 1, 120 // i.e. an origin with the host "deeply.nested.subdomain.example.com" 121 // corresponds to a site URL with the host "example.com". 122 virtual const GURL& GetSiteURL() = 0; 123 124 // Gets a SiteInstance for the given URL that shares the current 125 // BrowsingInstance, creating a new SiteInstance if necessary. This ensures 126 // that a BrowsingInstance only has one SiteInstance per site, so that pages 127 // in a BrowsingInstance have the ability to script each other. 128 virtual scoped_refptr<SiteInstance> GetRelatedSiteInstance( 129 const GURL& url) = 0; 130 131 // Returns whether the given SiteInstance is in the same BrowsingInstance as 132 // this one. If so, JavaScript interactions that are permitted across 133 // origins (e.g., postMessage) should be supported. 134 virtual bool IsRelatedSiteInstance(const SiteInstance* instance) = 0; 135 136 // Returns the total active WebContents count for this SiteInstance and all 137 // related SiteInstances in the same BrowsingInstance. 138 virtual size_t GetRelatedActiveContentsCount() = 0; 139 140 // Returns true if this SiteInstance is for a site that requires a dedicated 141 // process. This only returns true under the "site per process" process model. 142 virtual bool RequiresDedicatedProcess() = 0; 143 144 // Return whether this SiteInstance and the provided |url| are part of the 145 // same web site, for the purpose of assigning them to processes accordingly. 146 // The decision is currently based on the registered domain of the URLs 147 // (google.com, bbc.co.uk), as well as the scheme (https, http). This ensures 148 // that two pages will be in the same process if they can communicate with 149 // other via JavaScript. (e.g., docs.google.com and mail.google.com have DOM 150 // access to each other if they both set their document.domain properties to 151 // google.com.) Note that if the destination is a blank page, we consider 152 // that to be part of the same web site for the purposes for process 153 // assignment. 154 virtual bool IsSameSiteWithURL(const GURL& url) = 0; 155 156 // Returns true if this object is used for a <webview> guest. 157 virtual bool IsGuest() = 0; 158 159 // Factory method to create a new SiteInstance. This will create a new 160 // new BrowsingInstance, so it should only be used when creating a new tab 161 // from scratch (or similar circumstances). 162 // 163 // The render process host factory may be nullptr. See SiteInstance 164 // constructor. 165 static scoped_refptr<SiteInstance> Create( 166 content::BrowserContext* browser_context); 167 168 // Factory method to get the appropriate SiteInstance for the given URL, in 169 // a new BrowsingInstance. Use this instead of Create when you know the URL, 170 // since it allows special site grouping rules to be applied (for example, 171 // to group chrome-ui pages into the same instance). 172 static scoped_refptr<SiteInstance> CreateForURL( 173 content::BrowserContext* browser_context, 174 const GURL& url); 175 176 // Factory method to create a SiteInstance for a <webview> guest in a new 177 // BrowsingInstance. 178 // TODO(734722): Replace this method once SecurityPrincipal is available. 179 static scoped_refptr<SiteInstance> CreateForGuest( 180 content::BrowserContext* browser_context, 181 const GURL& guest_site_url); 182 183 // Determine if a URL should "use up" a site. URLs such as about:blank or 184 // chrome-native:// leave the site unassigned. 185 static bool ShouldAssignSiteForURL(const GURL& url); 186 187 // Returns the site for the given URL, which includes only the scheme and 188 // registered domain. Returns an empty GURL if the URL has no host. Prior to 189 // determining the site, |url| is resolved to an effective URL via 190 // ContentBrowserClient::GetEffectiveURL(). 191 static GURL GetSiteForURL(BrowserContext* context, const GURL& url); 192 193 // Starts requiring a dedicated process for |url|'s site. On platforms where 194 // strict site isolation is disabled, this may be used as a runtime signal 195 // that a certain site should become process-isolated, because its security 196 // is important to the user (e.g., if the user has typed a password on that 197 // site). The site will be determined from |url|'s scheme and eTLD+1. If 198 // |context| is non-null, the site will be isolated only within that 199 // BrowserContext; if |context| is null, the site will be isolated globally 200 // for all BrowserContexts. 201 // 202 // Note that this has no effect if site isolation is turned off, such as via 203 // the kDisableSiteIsolation cmdline flag or enterprise policy -- see also 204 // SiteIsolationPolicy::AreDynamicIsolatedOriginsEnabled(). 205 // 206 // Currently this function assumes that the site is added *persistently*: it 207 // will ask the embedder to save the site as part of profile data for 208 // |context|, so that it survives restarts. The site will be cleared from 209 // profile data if the user clears browsing data. Future uses of this 210 // function may want to avoid persistence by passing in a new flag. 211 static void StartIsolatingSite(BrowserContext* context, const GURL& url); 212 213 protected: 214 friend class base::RefCounted<SiteInstance>; 215 SiteInstance()216 SiteInstance() {} ~SiteInstance()217 virtual ~SiteInstance() {} 218 }; 219 220 } // namespace content. 221 222 #endif // CONTENT_PUBLIC_BROWSER_SITE_INSTANCE_H_ 223