blob: 9b90d52cac2b6a0d15e1ec1f562f0e376ce6be7c [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_PUBLIC_BROWSER_SITE_INSTANCE_H_
#define CONTENT_PUBLIC_BROWSER_SITE_INSTANCE_H_
#include <stddef.h>
#include <stdint.h>
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "content/public/browser/site_instance_process_assignment.h"
#include "url/gurl.h"
namespace content {
class BrowserContext;
class RenderProcessHost;
///////////////////////////////////////////////////////////////////////////////
// SiteInstance interface.
//
// In an ideal sense, a SiteInstance represents a group of documents and workers
// that can share memory with each other, and thus must live in the same
// renderer process. In the spec, this roughly corresponds to an agent cluster.
// Documents that are able to synchronously script each other will always be
// placed in the same SiteInstance.
//
// A document's SiteInstance is determined by a combination of where the
// document comes from (i.e., a principal based on its "site") and which frames
// have references to it (i.e., the browsing context group, or "instance"). The
// site part groups together documents that can script each other, while the
// instance part allows independent copies of such documents to safely live in
// different processes.
//
// The principal is usually based on the site of the document's URL: the scheme
// and "registrable domain" (i.e., eTLD+1), not the full origin. For example,
// https://dev.chromium.org would have a site of https://chromium.org. This
// preserves compatibility with document.domain modifications, which allow
// similar origin pages to script each other. (Note that there are many
// exceptions, and the policy for determining site URLs is complex.) Meanwhile,
// an "instance" is represented by the BrowsingInstance class, which includes
// all frames that can find each other based on how they were created (e.g.,
// window.open or targeted links).
//
// In practice, a SiteInstance may contain documents from more than a single
// site, usually for compatibility or performance reasons. For example, on
// platforms that do not support out-of-process iframes, cross-site iframes must
// necessarily be loaded in the same process as their parent document. Chrome's
// process model uses SiteInstance as the basic primitive for assigning
// documents to processes, and the process model's behavior is tuned primarily
// by changing how SiteInstance principals (e.g., site URLs) are defined.
//
// Various process models are currently supported:
//
// FULL SITE ISOLATION (the current default for desktop platforms): Every
// document from the web uses a SiteInstance whose process is strictly locked to
// a single site (scheme + eTLD+1), such that the renderer process can be
// prevented from loading documents outside that site. Cross-site navigations
// always change SiteInstances (usually within the same BrowsingInstance,
// although sometimes the BrowsingInstance changes as well). Subframes from
// other sites will use different SiteInstances (always within the same
// BrowsingInstance), and thus out-of-process iframes.
//
// PARTIAL SITE ISOLATION (the current Google Chrome default on most Android
// devices): Documents from sites that are most likely to involve login use
// SiteInstances that are strictly locked to such sites, while one shared
// SiteInstance within each BrowsingInstance is used for the remaining documents
// from other less sensitive sites. This avoids out-of-process iframes in the
// common case for performance reasons, while protecting the sites that are most
// likely to be targeted in attacks.
//
// NO SITE ISOLATION (the current Google Chrome default on low-end Android
// devices and Android WebView): No documents from the web use locked processes,
// and no out-of-process iframes are created. The shared SiteInstance for each
// BrowsingInstance is always used for documents from the web.
//
// In each model, there are many exceptions, such as always requiring locked
// processes for chrome:// URLs, or allowing some special cases to share
// processes with each other (e.g., file:// URLs).
//
// In terms of lifetime, each RenderFrameHost tracks the SiteInstance it is
// associated with, to identify its principal and determine its process. Each
// FrameNavigationEntry also tracks the SiteInstance that rendered it, to
// prevent loading attacker-controlled data into the wrong process on a session
// history navigation. A SiteInstance is jointly owned by these references and
// is only alive as long as it is accessible, either from current documents or
// from session history.
//
///////////////////////////////////////////////////////////////////////////////
class CONTENT_EXPORT SiteInstance : public base::RefCounted<SiteInstance> {
public:
// Returns a unique ID for this SiteInstance.
virtual int32_t GetId() = 0;
// Returns a unique ID for the BrowsingInstance (i.e., group of related
// browsing contexts) to which this SiteInstance belongs. This allows callers
// to identify which SiteInstances can asynchronously script each other.
virtual int32_t GetBrowsingInstanceId() = 0;
// Whether this SiteInstance has a running process associated with it.
// This may return true before the first call to GetProcess(), in cases where
// we use process-per-site and there is an existing process available.
virtual bool HasProcess() = 0;
// Returns the current RenderProcessHost being used to render pages for this
// SiteInstance. If there is no RenderProcessHost (because either none has
// yet been created or there was one but it was cleanly destroyed (e.g. when
// it is not actively being used), then this method will create a new
// RenderProcessHost (and a new ID). Note that renderer process crashes leave
// the current RenderProcessHost (and ID) in place.
//
// For sites that require process-per-site mode (e.g., NTP), this will
// ensure only one RenderProcessHost for the site exists within the
// BrowserContext.
virtual content::RenderProcessHost* GetProcess() = 0;
// Browser context to which this SiteInstance (and all related
// SiteInstances) belongs.
virtual content::BrowserContext* GetBrowserContext() = 0;
// Get the web site that this SiteInstance is rendering pages for. This
// includes the scheme and registered domain, but not the port.
//
// NOTE: In most cases, code should be performing checks against the origin
// returned by |RenderFrameHost::GetLastCommittedOrigin()|. In contrast, the
// GURL returned by |GetSiteURL()| should not be considered authoritative
// because:
// - a SiteInstance can host pages from multiple sites if "site per process"
// is not enabled and the SiteInstance isn't hosting pages that require
// process isolation (e.g. WebUI or extensions)
// - even with site per process, the site URL is not an origin: while often
// derived from the origin, it only contains the scheme and the eTLD + 1,
// i.e. an origin with the host "deeply.nested.subdomain.example.com"
// corresponds to a site URL with the host "example.com".
virtual const GURL& GetSiteURL() = 0;
// Gets a SiteInstance for the given URL that shares the current
// BrowsingInstance, creating a new SiteInstance if necessary. This ensures
// that a BrowsingInstance only has one SiteInstance per site, so that pages
// in a BrowsingInstance have the ability to script each other.
virtual scoped_refptr<SiteInstance> GetRelatedSiteInstance(
const GURL& url) = 0;
// Returns whether the given SiteInstance is in the same BrowsingInstance as
// this one. If so, JavaScript interactions that are permitted across
// origins (e.g., postMessage) should be supported.
virtual bool IsRelatedSiteInstance(const SiteInstance* instance) = 0;
// Returns the total active WebContents count for this SiteInstance and all
// related SiteInstances in the same BrowsingInstance.
virtual size_t GetRelatedActiveContentsCount() = 0;
// Returns true if this SiteInstance is for a site that requires a dedicated
// process. This only returns true under the "site per process" process model.
virtual bool RequiresDedicatedProcess() = 0;
// Return whether this SiteInstance and the provided |url| are part of the
// same web site, for the purpose of assigning them to processes accordingly.
// The decision is currently based on the registered domain of the URLs
// (google.com, bbc.co.uk), as well as the scheme (https, http). This ensures
// that two pages will be in the same process if they can communicate with
// other via JavaScript. (e.g., docs.google.com and mail.google.com have DOM
// access to each other if they both set their document.domain properties to
// google.com.) Note that if the destination is a blank page, we consider
// that to be part of the same web site for the purposes for process
// assignment.
virtual bool IsSameSiteWithURL(const GURL& url) = 0;
// Returns true if this object is used for a <webview> guest.
virtual bool IsGuest() = 0;
// Returns how this SiteInstance was assigned to a renderer process the most
// recent time that such an assignment was done. This allows the content
// embedder to collect metrics on how renderer process starting or reuse
// affects performance.
virtual SiteInstanceProcessAssignment GetLastProcessAssignmentOutcome() = 0;
// Write a representation of this object into a trace.
virtual void WriteIntoTracedValue(perfetto::TracedValue context) = 0;
// Factory method to create a new SiteInstance. This will create a new
// BrowsingInstance, so it should only be used when creating a new tab from
// scratch (or similar circumstances).
//
// The render process host factory may be nullptr. See SiteInstance
// constructor.
static scoped_refptr<SiteInstance> Create(
content::BrowserContext* browser_context);
// Factory method to get the appropriate SiteInstance for the given URL, in
// a new BrowsingInstance. Use this instead of Create when you know the URL,
// since it allows special site grouping rules to be applied (for example, to
// obey process-per-site for sites that require it, such as NTP, or to use a
// default SiteInstance for sites that don't require a dedicated process on
// Android).
static scoped_refptr<SiteInstance> CreateForURL(
content::BrowserContext* browser_context,
const GURL& url);
// Factory method to create a SiteInstance for a <webview> guest in a new
// BrowsingInstance.
// TODO(734722): Replace this method once SecurityPrincipal is available.
static scoped_refptr<SiteInstance> CreateForGuest(
content::BrowserContext* browser_context,
const GURL& guest_site_url);
// Determine if a URL should "use up" a site. URLs such as about:blank or
// chrome-native:// leave the site unassigned.
static bool ShouldAssignSiteForURL(const GURL& url);
// Starts requiring a dedicated process for |url|'s site. On platforms where
// strict site isolation is disabled, this may be used as a runtime signal
// that a certain site should become process-isolated, because its security
// is important to the user (e.g., if the user has typed a password on that
// site). The site will be determined from |url|'s scheme and eTLD+1. If
// |context| is non-null, the site will be isolated only within that
// BrowserContext; if |context| is null, the site will be isolated globally
// for all BrowserContexts.
//
// Note that this has no effect if site isolation is turned off, such as via
// the kDisableSiteIsolation cmdline flag or enterprise policy -- see also
// SiteIsolationPolicy::AreDynamicIsolatedOriginsEnabled().
//
// Currently this function assumes that the site is added *persistently*: it
// will ask the embedder to save the site as part of profile data for
// |context|, so that it survives restarts. The site will be cleared from
// profile data if the user clears browsing data. Future uses of this
// function may want to avoid persistence by passing in a new flag.
static void StartIsolatingSite(BrowserContext* context, const GURL& url);
protected:
friend class base::RefCounted<SiteInstance>;
SiteInstance() {}
virtual ~SiteInstance() {}
};
} // namespace content.
#endif // CONTENT_PUBLIC_BROWSER_SITE_INSTANCE_H_