| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CONTENT_BROWSER_CHILD_PROCESS_SECURITY_POLICY_IMPL_H_ |
| #define CONTENT_BROWSER_CHILD_PROCESS_SECURITY_POLICY_IMPL_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <string_view> |
| #include <vector> |
| |
| #include "base/containers/flat_map.h" |
| #include "base/containers/flat_set.h" |
| #include "base/gtest_prod_util.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/singleton.h" |
| #include "base/synchronization/lock.h" |
| #include "base/thread_annotations.h" |
| #include "base/time/time.h" |
| #include "content/browser/can_commit_status.h" |
| #include "content/browser/isolated_origin_util.h" |
| #include "content/browser/isolation_context.h" |
| #include "content/browser/origin_agent_cluster_isolation_state.h" |
| #include "content/common/content_export.h" |
| #include "content/public/browser/child_process_security_policy.h" |
| #include "content/public/common/bindings_policy.h" |
| #include "storage/common/file_system/file_system_types.h" |
| #include "url/origin.h" |
| |
| class GURL; |
| |
| namespace base { |
| class FilePath; |
| } // namespace base |
| |
| namespace network { |
| class ResourceRequestBody; |
| } // namespace network |
| |
| namespace storage { |
| class FileSystemContext; |
| class FileSystemURL; |
| } // namespace storage |
| |
| namespace content { |
| |
| class BrowserContext; |
| class IsolationContext; |
| class ProcessLock; |
| class ResourceContext; |
| struct UrlInfo; |
| |
| class CONTENT_EXPORT ChildProcessSecurityPolicyImpl |
| : public ChildProcessSecurityPolicy { |
| public: |
| // Handle used to access the security state for a specific process. |
| // |
| // Objects that require the security state to be preserved beyond the |
| // lifetime of the RenderProcessHostImpl should hold an instance of this |
| // object and use it to answer security policy questions. (e.g. Mojo services |
| // created by RPHI that can receive calls after RPHI destruction). This |
| // object should only be called on the UI and IO threads. |
| // |
| // Note: Some security methods, like CanAccessDataForOrigin(), require |
| // information from the BrowserContext to make its decisions. These methods |
| // will fall back to failsafe values if called after BrowserContext |
| // destruction. Callers should be prepared to gracefully handle this or |
| // ensure that they don't make any calls after BrowserContext destruction. |
| class CONTENT_EXPORT Handle { |
| public: |
| Handle(); |
| Handle(Handle&&); |
| Handle(const Handle&) = delete; |
| ~Handle(); |
| |
| Handle& operator=(const Handle&) = delete; |
| Handle& operator=(Handle&&); |
| |
| // Create a new instance of Handle, holding another reference to the same |
| // process ID as the current one. |
| Handle Duplicate(); |
| |
| // Returns true if this object has a valid process ID. |
| // Returns false if this object was created with the default constructor, |
| // the contents of this object was transferred to another Handle via |
| // std::move(), or ChildProcessSecurityPolicyImpl::CreateHandle() |
| // created this object after the process has already been destructed. |
| bool is_valid() const; |
| |
| // Before servicing a child process's request to upload a file to the web, |
| // the browser should call this method to determine whether the process has |
| // the capability to upload the requested file. |
| bool CanReadFile(const base::FilePath& file); |
| |
| // Explicit read permissions check for FileSystemURL specified files. |
| bool CanReadFileSystemFile(const storage::FileSystemURL& url); |
| |
| // Returns true if the process is permitted to read and modify the data for |
| // the given `origin`. For more details, see |
| // ChildProcessSecurityPolicy::CanAccessDataForOrigin(). |
| bool CanAccessDataForOrigin(const url::Origin& origin); |
| |
| // Returns the original `child_id` used to create the handle. |
| int child_id() { return child_id_; } |
| |
| private: |
| friend class ChildProcessSecurityPolicyImpl; |
| // |child_id| - The ID of the process that this Handle is being created |
| // for, or ChildProcessHost::kInvalidUniqueID if an invalid handle is being |
| // created. |
| // |duplicating_handle| - True if the handle is being created by a |
| // Duplicate() call. Otherwise false. This is used to trigger special |
| // behavior for handle duplication that is not allowed for Handles created |
| // by other means. |
| Handle(int child_id, bool duplicating_handle); |
| |
| // The ID of the child process that this handle is associated with or |
| // ChildProcessHost::kInvalidUniqueID if the handle is no longer valid. |
| int child_id_; |
| }; |
| |
| ChildProcessSecurityPolicyImpl(const ChildProcessSecurityPolicyImpl&) = |
| delete; |
| ChildProcessSecurityPolicyImpl& operator=( |
| const ChildProcessSecurityPolicyImpl&) = delete; |
| |
| // Object can only be created through GetInstance() so the constructor is |
| // private. |
| ~ChildProcessSecurityPolicyImpl() override; |
| |
| static ChildProcessSecurityPolicyImpl* GetInstance(); |
| |
| // ChildProcessSecurityPolicy implementation. |
| void RegisterWebSafeScheme(const std::string& scheme) override; |
| void RegisterWebSafeIsolatedScheme( |
| const std::string& scheme, |
| bool always_allow_in_origin_headers) override; |
| bool IsWebSafeScheme(const std::string& scheme) override; |
| void GrantReadFile(int child_id, const base::FilePath& file) override; |
| void GrantCreateReadWriteFile(int child_id, |
| const base::FilePath& file) override; |
| void GrantCopyInto(int child_id, const base::FilePath& dir) override; |
| void GrantDeleteFrom(int child_id, const base::FilePath& dir) override; |
| void GrantReadFileSystem(int child_id, |
| const std::string& filesystem_id) override; |
| void GrantWriteFileSystem(int child_id, |
| const std::string& filesystem_id) override; |
| void GrantCreateFileForFileSystem(int child_id, |
| const std::string& filesystem_id) override; |
| void GrantCreateReadWriteFileSystem( |
| int child_id, |
| const std::string& filesystem_id) override; |
| void GrantCopyIntoFileSystem(int child_id, |
| const std::string& filesystem_id) override; |
| void GrantDeleteFromFileSystem(int child_id, |
| const std::string& filesystem_id) override; |
| void GrantCommitOrigin(int child_id, const url::Origin& origin) override; |
| void GrantRequestOrigin(int child_id, const url::Origin& origin) override; |
| void GrantRequestScheme(int child_id, const std::string& scheme) override; |
| bool CanRequestURL(int child_id, const GURL& url) override; |
| bool CanReadFile(int child_id, const base::FilePath& file) override; |
| bool CanCreateReadWriteFile(int child_id, |
| const base::FilePath& file) override; |
| bool CanReadFileSystem(int child_id, |
| const std::string& filesystem_id) override; |
| bool CanReadWriteFileSystem(int child_id, |
| const std::string& filesystem_id) override; |
| bool CanCopyIntoFileSystem(int child_id, |
| const std::string& filesystem_id) override; |
| bool CanDeleteFromFileSystem(int child_id, |
| const std::string& filesystem_id) override; |
| bool HasWebUIBindings(int child_id) override; |
| void GrantSendMidiMessage(int child_id) override; |
| void GrantSendMidiSysExMessage(int child_id) override; |
| bool CanAccessDataForOrigin(int child_id, const url::Origin& origin) override; |
| bool HostsOrigin(int child_id, const url::Origin& origin) override; |
| void AddFutureIsolatedOrigins( |
| std::string_view origins_list, |
| IsolatedOriginSource source, |
| BrowserContext* browser_context = nullptr) override; |
| void AddFutureIsolatedOrigins( |
| const std::vector<url::Origin>& origins, |
| IsolatedOriginSource source, |
| BrowserContext* browser_context = nullptr) override; |
| bool IsGloballyIsolatedOriginForTesting(const url::Origin& origin) override; |
| std::vector<url::Origin> GetIsolatedOrigins( |
| std::optional<IsolatedOriginSource> source = std::nullopt, |
| BrowserContext* browser_context = nullptr) override; |
| bool IsIsolatedSiteFromSource(const url::Origin& origin, |
| IsolatedOriginSource source) override; |
| void ClearIsolatedOriginsForTesting() override; |
| |
| // Centralized internal implementation of site isolation enforcements, |
| // including CanAccessDataForOrigin and HostsOrigin. It supports the following |
| // types of access checks, in order of increasing strictness: |
| enum class AccessType { |
| // Whether the process can commit a navigation to an origin, allowing a |
| // document with that origin to be hosted in this process. This is |
| // specifically about whether a particular new origin may be introduced |
| // into a given process. |
| kCanCommitNewOrigin, |
| // Whether the process has previously committed a document or instantiated a |
| // worker with the particular origin. This can be used to verify whether a |
| // particular origin can be used as an initiator or source origin, e.g. in |
| // postMessage or other IPCs sent from this process. Unlike |
| // kCanCommitNewOrigin, this check assumes that the origin must already |
| // exist in the process. Because a document/worker destruction may race with |
| // processing legitimate IPCs on behalf of `origin`, this check also allows |
| // the case where an origin has been hosted by the process in the past, but |
| // not necessarily now. |
| kHostsOrigin, |
| // Whether the process can access data belonging to an origin already |
| // committed in the process, such as passwords, localStorage, or cookies. |
| // Similarly to kHostsOrigin, this check assumes that the origin must |
| // already |
| // exist in the process, but it is more strict for certain kinds of |
| // processes that aren't supposed to access any data. For example, sandboxed |
| // frame processes (which contain only opaque origins) or PDF processes |
| // cannot access data for any origin. |
| kCanAccessDataForCommittedOrigin, |
| }; |
| bool CanAccessOrigin(int child_id, |
| const url::Origin& origin, |
| AccessType access_type); |
| |
| // Determines if the combination of origin, url and web_exposed_isolation_info |
| // bundled in `url_info` are safe to commit to the process associated with |
| // `child_id`. |
| // |
| // Returns CAN_COMMIT_ORIGIN_AND_URL if it is safe to commit `url_info` origin |
| // and `url_info`'s url combination to the process associated with `child_id`. |
| // Returns CANNOT_COMMIT_URL if `url_info` url is not safe to commit. |
| // Returns CANNOT_COMMIT_ORIGIN if `url_info` origin is not safe to commit. |
| CanCommitStatus CanCommitOriginAndUrl( |
| int child_id, |
| const IsolationContext& isolation_context, |
| const UrlInfo& url_info); |
| |
| // Whether the process is allowed to commit a document from the given URL. |
| // This is more restrictive than CanRequestURL, since CanRequestURL allows |
| // requests that might lead to cross-process navigations or external protocol |
| // handlers. Used primarily as a helper for CanCommitOriginAndUrl and thus not |
| // exposed publicly. |
| bool CanCommitURL(int child_id, const GURL& url); |
| |
| // This function will check whether |origin| requires process isolation |
| // within |isolation_context|, and if so, it will return true and put the |
| // most specific matching isolated origin into |result|. |
| // |
| // Such origins may be registered with the --isolate-origins command-line |
| // flag, via features::IsolateOrigins, via an IsolateOrigins enterprise |
| // policy, or by a content/ embedder using |
| // ContentBrowserClient::GetOriginsRequiringDedicatedProcess(). |
| // |
| // If |origin| does not require process isolation, this function will return |
| // false, and |result| will be a unique origin. This means that neither |
| // |origin|, nor any origins for which |origin| is a subdomain, have been |
| // registered as isolated origins. |
| // |
| // For example, if both https://isolated.com/ and |
| // https://bar.foo.isolated.com/ are registered as isolated origins, then the |
| // values returned in |result| are: |
| // https://isolated.com/ --> https://isolated.com/ |
| // https://foo.isolated.com/ --> https://isolated.com/ |
| // https://bar.foo.isolated.com/ --> https://bar.foo.isolated.com/ |
| // https://baz.bar.foo.isolated.com/ --> https://bar.foo.isolated.com/ |
| // https://unisolated.com/ --> (unique origin) |
| // |
| // |isolation_context| is used to determine which origins are isolated in |
| // this context. For example, isolated origins that are dynamically added |
| // will only affect future BrowsingInstances. |
| bool GetMatchingProcessIsolatedOrigin( |
| const IsolationContext& isolation_context, |
| const url::Origin& origin, |
| bool requests_origin_keyed_process, |
| url::Origin* result); |
| |
| // Removes any origin isolation opt-in entries associated with the |
| // |browsing_instance_id| of the BrowsingInstance. |
| void RemoveOptInIsolatedOriginsForBrowsingInstance( |
| const BrowsingInstanceId& browsing_instance_id); |
| |
| // Registers |origin| isolation state in the BrowsingInstance associated |
| // with |isolation_context|. |
| // |
| // |is_origin_agent_cluster| is used to indicate |origin| will receive (at |
| // least) logical isolation via OriginAgentCluster in the renderer. If it is |
| // false, then |requires_origin_keyed_process| must also be false. |
| // |
| // If |requires_origin_keyed_process| is true, then |origin| will be |
| // registered as an origin-keyed process; that is, subdomains of |origin| |
| // won't be automatically grouped with |origin|. In particular, this can be |
| // used for cases using the Origin-Agent-Cluster header. |
| // |
| // If |requires_origin_keyed_process| is false, then subdomains of |origin| |
| // will be grouped together with |origin| in the same process. |origin| is |
| // required to be a site (scheme and eTLD+1) in this case. |
| // |
| // If this function is called with differing values of |
| // |requires_origin_keyed_process| for |
| // the same IsolationContext and origin, then origin-keyed process isolation |
| // takes precedence for |origin|, though site-keyed process isolation will |
| // still be used for subdomains of |origin|. |
| // |
| // If |origin| has already been registered as isolated for the same |
| // BrowsingInstance amd the same value of |requires_origin_keyed_process|, |
| // then nothing will be changed by this call. |
| void AddOriginIsolationStateForBrowsingInstance( |
| const IsolationContext& isolation_context, |
| const url::Origin& origin, |
| bool is_origin_agent_cluster, |
| bool requires_origin_keyed_process); |
| |
| // Adds `origin` to the IsolatedOrigins list for only the BrowsingInstance of |
| // `isolation_context`, without isolating all subdomains. For use when the |
| // isolation is triggered by COOP headers. |
| void AddCoopIsolatedOriginForBrowsingInstance( |
| const IsolationContext& isolation_context, |
| const url::Origin& origin, |
| IsolatedOriginSource source); |
| |
| // This function will check whether |origin| has opted-in to logical or |
| // process isolation (via the Origin-Agent-Cluster header), with respect to |
| // the current state of the |isolation_context|. It is different from |
| // IsIsolatedOrigin() in that it only deals with Origin-Agent-Cluster |
| // isolation status, whereas IsIsolatedOrigin() considers all possible |
| // mechanisms for requesting isolation. It will check for two things: |
| // 1) whether |origin| already is assigned to a SiteInstance in the |
| // |isolation_context| by being tracked in |
| // |origin_isolation_by_browsing_instance_|, in which case we follow the |
| // same policy, or |
| // 2) if it's not currently tracked as described above, whether |origin| is |
| // currently requesting isolation via |requested_isolation_state|. |
| OriginAgentClusterIsolationState DetermineOriginAgentClusterIsolation( |
| const IsolationContext& isolation_context, |
| const url::Origin& origin, |
| const OriginAgentClusterIsolationState& requested_isolation_state); |
| |
| // This function adds |origin| to the master list of origins that have |
| // ever requested opt-in isolation in the given |browser_context|, either via |
| // an OriginPolicy or opt-in header. Returns true if |origin| is not already |
| // in the list. |
| bool UpdateOriginIsolationOptInListIfNecessary( |
| BrowserContext* browser_context, |
| const url::Origin& origin); |
| |
| // A version of GetMatchingProcessIsolatedOrigin that takes in both the |
| // |origin| and the |site_url| that |origin| corresponds to. |site_url| is |
| // the key by which |origin| will be looked up in |isolated_origins_| within |
| // |isolation_context|; this function allows it to be passed in when it is |
| // already known to avoid recomputing it internally. |
| bool GetMatchingProcessIsolatedOrigin( |
| const IsolationContext& isolation_context, |
| const url::Origin& origin, |
| bool requests_origin_keyed_process, |
| const GURL& site_url, |
| url::Origin* result); |
| |
| // Returns if |child_id| can read all of the |files|. |
| bool CanReadAllFiles(int child_id, const std::vector<base::FilePath>& files); |
| |
| // Validate that |child_id| in |file_system_context| is allowed to access |
| // data in the POST body specified by |body|. Can be called on any thread. |
| bool CanReadRequestBody( |
| int child_id, |
| const storage::FileSystemContext* file_system_context, |
| const scoped_refptr<network::ResourceRequestBody>& body); |
| |
| // Validate that `process` is allowed to access data in the POST body |
| // specified by |body|. Has to be called on the UI thread. |
| bool CanReadRequestBody( |
| RenderProcessHost* process, |
| const scoped_refptr<network::ResourceRequestBody>& body); |
| |
| // Pseudo schemes are treated differently than other schemes because they |
| // cannot be requested like normal URLs. There is no mechanism for revoking |
| // pseudo schemes. |
| void RegisterPseudoScheme(const std::string& scheme); |
| |
| // Returns true iff |scheme| has been registered as pseudo scheme. |
| bool IsPseudoScheme(const std::string& scheme); |
| |
| // Upon creation, child processes should register themselves by calling this |
| // this method exactly once. This call must be made on the UI thread. |
| void Add(int child_id, BrowserContext* browser_context); |
| |
| // Helper method for unit tests that calls Add() and |
| // LockProcess() with an "allow_any_site" lock. This ensures that the process |
| // policy is always in a state where it is valid to call |
| // CanAccessDataForOrigin(). |
| void AddForTesting(int child_id, BrowserContext* browser_context); |
| |
| // Upon destruction, child processes should unregister themselves by calling |
| // this method exactly once. This call must be made on the UI thread. |
| // |
| // Note: Pre-Remove() permissions remain in effect on the IO thread until |
| // the task posted to the IO thread by this call runs and removes the entry |
| // from |pending_remove_state_|. |
| // This UI -> IO task sequence ensures that any pending tasks, on the IO |
| // thread, for this |child_id| are allowed to run before access is completely |
| // revoked. |
| void Remove(int child_id); |
| |
| // Whenever the browser processes commands the child process to commit a URL, |
| // it should call this method to grant the child process the capability to |
| // commit anything from the URL's origin, along with permission to request all |
| // URLs of the same scheme. |
| void GrantCommitURL(int child_id, const GURL& url); |
| |
| // Whenever the browser process drops a file icon on a tab, it should call |
| // this method to grant the child process the capability to request this one |
| // file:// URL (or content:// URL in android), but not all urls of the file:// |
| // scheme. |
| void GrantRequestOfSpecificFile(int child_id, const base::FilePath& file); |
| |
| // Revokes all permissions granted to the given file. |
| void RevokeAllPermissionsForFile(int child_id, const base::FilePath& file); |
| |
| // Grant the child process the ability to use Web UI Bindings. |
| void GrantWebUIBindings(int child_id, BindingsPolicySet bindings); |
| |
| // Grant the child process the ability to read raw cookies. |
| void GrantReadRawCookies(int child_id); |
| |
| // Revoke read raw cookies permission. |
| void RevokeReadRawCookies(int child_id); |
| |
| // Some APIs for Android WebView and <webview> tags allow bypassing some |
| // security checks, such as which URLs are allowed to commit. This method |
| // grants that ability to any document with an origin used with these APIs, |
| // because the exemption is needed for about:blank frames that inherit the |
| // same origin. |
| // |
| // For safety, this is limited to opaque origins used with LoadDataWithBaseURL |
| // in unlocked processes, as well as file origins used with |
| // allow_universal_access_from_file_urls. |
| // |
| // Note that LoadDataWithBaseURL can be used with non-opaque origins as well, |
| // but in that case the bypass is only allowed for the document and not the |
| // entire origin, to prevent other code in the origin from bypassing checks. |
| void GrantOriginCheckExemptionForWebView(int child_id, |
| const url::Origin& origin); |
| |
| // Returns whether the given opaque or file origin was granted an exemption |
| // due to Android WebView and <webview> APIs, allowing its documents to bypass |
| // certain URL and origin checks. |
| bool HasOriginCheckExemptionForWebView(int child_id, |
| const url::Origin& origin); |
| |
| // Explicit permissions checks for FileSystemURL specified files. |
| bool CanReadFileSystemFile(int child_id, |
| const storage::FileSystemURL& filesystem_url); |
| bool CanWriteFileSystemFile(int child_id, |
| const storage::FileSystemURL& filesystem_url); |
| bool CanCreateFileSystemFile(int child_id, |
| const storage::FileSystemURL& filesystem_url); |
| bool CanCreateReadWriteFileSystemFile( |
| int child_id, |
| const storage::FileSystemURL& filesystem_url); |
| bool CanCopyIntoFileSystemFile(int child_id, |
| const storage::FileSystemURL& filesystem_url); |
| bool CanDeleteFileSystemFile(int child_id, |
| const storage::FileSystemURL& filesystem_url); |
| bool CanMoveFileSystemFile(int child_id, |
| const storage::FileSystemURL& src_url, |
| const storage::FileSystemURL& dest_url); |
| bool CanCopyFileSystemFile(int child_id, |
| const storage::FileSystemURL& src_url, |
| const storage::FileSystemURL& dest_url); |
| |
| // Returns true if the specified child_id has been granted ReadRawCookies. |
| bool CanReadRawCookies(int child_id); |
| |
| // Notifies security state of |child_id| about the IsolationContext it will |
| // host. The main side effect is proper setting of the lowest |
| // BrowsingInstanceId associated with the security state. |
| void IncludeIsolationContext(int child_id, |
| const IsolationContext& isolation_context); |
| |
| // Sets the process identified by |child_id| as only permitted to access data |
| // for the origin specified by |site_info|'s process_lock_url(). Most callers |
| // should use RenderProcessHostImpl::SetProcessLock instead of calling this |
| // directly. |isolation_context| provides the context, such as |
| // BrowsingInstance, from which this process locked was created. This |
| // information is used when making isolation decisions for this process, such |
| // as determining which isolated origins pertain to it. |is_process_used| |
| // indicates whether any content has been loaded in the process already. |
| void LockProcess(const IsolationContext& isolation_context, |
| int child_id, |
| bool is_process_used, |
| const ProcessLock& process_lock); |
| |
| // Testing helper method that generates a lock_url from |url| and then |
| // calls LockProcess() with that lock URL. |
| void LockProcessForTesting(const IsolationContext& isolation_context, |
| int child_id, |
| const GURL& url); |
| |
| // Retrieves the current ProcessLock of process |child_id|. Returns an empty |
| // lock if the process does not exist or if it is not locked. |
| ProcessLock GetProcessLock(int child_id); |
| |
| // Register FileSystem type and permission policy which should be used |
| // for the type. The |policy| must be a bitwise-or'd value of |
| // storage::FilePermissionPolicy. |
| void RegisterFileSystemPermissionPolicy(storage::FileSystemType type, |
| int policy); |
| |
| // Returns true if sending MIDI messages is allowed. |
| bool CanSendMidiMessage(int child_id); |
| |
| // Returns true if sending system exclusive (SysEx) MIDI messages is allowed. |
| bool CanSendMidiSysExMessage(int child_id); |
| |
| // Remove all isolated origins associated with |browser_context| and clear any |
| // pointers that may reference |browser_context|. This is |
| // typically used when |browser_context| is being destroyed and assumes that |
| // no processes are running or will run for that profile; this makes the |
| // isolated origin removal safe. Note that |browser_context| cannot be null; |
| // i.e., isolated origins that apply globally to all profiles cannot |
| // currently be removed, since that is not safe to do at runtime. |
| void RemoveStateForBrowserContext(const BrowserContext& browser_context); |
| |
| // Check whether |origin| requires origin-wide process isolation within |
| // |isolation_context|. |
| // |
| // Subdomains of an isolated origin are considered part of that isolated |
| // origin. Thus, if https://isolated.foo.com/ had been added as an isolated |
| // origin, this will return true for https://isolated.foo.com/, |
| // https://bar.isolated.foo.com/, or https://baz.bar.isolated.foo.com/; and |
| // it will return false for https://foo.com/ or https://unisolated.foo.com/. |
| // |
| // |isolation_context| is used to determine which origins are isolated in |
| // this context. For example, isolated origins that are dynamically added |
| // will only affect future BrowsingInstances. |origin_requests_isolation| may |
| // be true during navigation requests, and allows us to correctly determine |
| // isolation status for an origin that may not have had its isolation status |
| // recorded in the BrowsingInstance yet. |
| bool IsIsolatedOrigin(const IsolationContext& isolation_context, |
| const url::Origin& origin, |
| bool origin_requests_isolation); |
| |
| // Removes a previously added isolated origin, currently only used in tests. |
| // |
| // TODO(alexmos): Exposing this more generally will require extra care, such |
| // as ensuring that there are no active SiteInstances in that origin. |
| void RemoveIsolatedOriginForTesting(const url::Origin& origin); |
| |
| // Returns false for redirects that must be blocked no matter which renderer |
| // process initiated the request (if any). |
| // Note: Checking CanRedirectToURL is not enough. CanRequestURL(child_id, url) |
| // represents a stricter subset. It must also be used for |
| // renderer-initiated navigations. |
| bool CanRedirectToURL(const GURL& url); |
| |
| // Sets "killed_process_origin_lock" crash key with lock info for the |
| // process associated with |child_id|. |
| void LogKilledProcessOriginLock(int child_id); |
| |
| // Creates a Handle object for a specific child process ID. |
| // |
| // This handle can be used to extend the lifetime of policy state beyond |
| // the Remove() call for |child_id|. This should be used by objects that can |
| // outlive the RenderProcessHostImpl object associated with |child_id| and |
| // need to be able to make policy decisions after RPHI destruction. (e.g. |
| // Mojo services created by RPHI) |
| // |
| // Returns a valid Handle for any |child_id| that is present in |
| // |security_state_|. Otherwise it returns a Handle that returns false for |
| // all policy checks. |
| Handle CreateHandle(int child_id); |
| |
| // Returns true if we have seen an explicit Origin-Agent-Cluster header |
| // (either opt-in or opt-out) for this |origin| in the given |browser_context| |
| // before in any BrowsingInstance. |
| bool HasOriginEverRequestedOriginAgentClusterValue( |
| BrowserContext* browser_context, |
| const url::Origin& origin); |
| |
| // Adds |origin| to the opt-in-out list as having the default isolation state |
| // for the BrowsingInstance specified by |isolation_context|, if we need to |
| // track it and it's not already in the list. |
| // |is_global_walk_or_frame_removal| should be set to true during the global |
| // walk that is triggered when |origin| first requests opt-in isolation, so |
| // that the function can skip safety checks that will be unnecessary during |
| // the global walk. It is also set to true if this function is called when |
| // removing a FrameNavigationEntry, since that entry won't be available to any |
| // subsequent global walks. |
| void AddDefaultIsolatedOriginIfNeeded( |
| const IsolationContext& isolation_context, |
| const url::Origin& origin, |
| bool is_global_walk_or_frame_removal); |
| |
| // Add `origin` to the list of committed origins for the process identified by |
| // `child_id`. An attempt to add the same origin more than once is safely |
| // ignored. Note that there is currently no way to revoke an origin once it |
| // has been committed, even if all associated documents and workers go away. |
| // This might need to be revisited in the future if the list of committed |
| // origins grows too large. |
| void AddCommittedOrigin(int child_id, const url::Origin& origin); |
| |
| // Allows tests to modify the delay in cleaning up BrowsingInstanceIds. If the |
| // delay is set to zero, cleanup happens immediately. |
| void SetBrowsingInstanceCleanupDelayForTesting(int64_t delay_in_seconds) { |
| browsing_instance_cleanup_delay_ = base::Seconds(delay_in_seconds); |
| } |
| |
| // Allows tests to query the number of BrowsingInstanceIds associated with a |
| // child process. |
| size_t BrowsingInstanceIdCountForTesting(int child_id); |
| |
| void ClearRegisteredSchemeForTesting(const std::string& scheme); |
| |
| // Checks if the provided `url` matches any committed origin in the process |
| // `child_id`. Currently only exposed for testing, since normally this check |
| // happens within CanAccessMaybeOpaqueOrigin(). |
| bool MatchesCommittedOriginForTesting(int child_id, |
| const GURL& url, |
| bool url_is_for_precursor_origin); |
| |
| // Exposes LookupOriginIsolationState() for tests. |
| OriginAgentClusterIsolationState* LookupOriginIsolationStateForTesting( |
| const BrowsingInstanceId& browsing_instance_id, |
| const url::Origin& origin); |
| |
| private: |
| friend class ChildProcessSecurityPolicyInProcessBrowserTest; |
| friend class ChildProcessSecurityPolicyTest; |
| friend class ChildProcessSecurityPolicyImpl::Handle; |
| FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyInProcessBrowserTest, |
| NoLeak); |
| FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, FilePermissions); |
| FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, |
| AddFutureIsolatedOrigins); |
| FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, |
| DynamicIsolatedOrigins); |
| FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, |
| IsolatedOriginsForSpecificBrowserContexts); |
| FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, |
| IsolatedOriginsForSpecificBrowsingInstances); |
| FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, |
| IsolatedOriginsForCurrentAndFutureBrowsingInstances); |
| FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, |
| IsolatedOriginsRemovedWhenBrowserContextDestroyed); |
| FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, |
| IsolateAllSuborigins); |
| FRIEND_TEST_ALL_PREFIXES( |
| ChildProcessSecurityPolicyTest_NoOriginKeyedProcessesByDefault, |
| WildcardAndNonWildcardOrigins); |
| FRIEND_TEST_ALL_PREFIXES( |
| ChildProcessSecurityPolicyTest_NoOriginKeyedProcessesByDefault, |
| WildcardAndNonWildcardEmbedded); |
| FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, |
| ParseIsolatedOrigins); |
| FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, WildcardDefaultPort); |
| FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, |
| MatchesCommittedOrigin); |
| |
| class SecurityState; |
| |
| typedef std::set<std::string> SchemeSet; |
| typedef std::map<int, std::unique_ptr<SecurityState>> SecurityStateMap; |
| typedef std::map<storage::FileSystemType, int> FileSystemPermissionPolicyMap; |
| |
| // This class holds an isolated origin along with information such as which |
| // BrowsingInstances and profile it applies to. See |isolated_origins_| |
| // below for more details. |
| class CONTENT_EXPORT IsolatedOriginEntry { |
| public: |
| IsolatedOriginEntry(const url::Origin& origin, |
| bool applies_to_future_browsing_instances, |
| BrowsingInstanceId browsing_instance_id, |
| BrowserContext* browser_context, |
| ResourceContext* resource_context, |
| bool isolate_all_subdomains, |
| IsolatedOriginSource source); |
| // Copyable and movable. |
| IsolatedOriginEntry(const IsolatedOriginEntry& other); |
| IsolatedOriginEntry& operator=(const IsolatedOriginEntry& other); |
| IsolatedOriginEntry(IsolatedOriginEntry&& other); |
| IsolatedOriginEntry& operator=(IsolatedOriginEntry&& other); |
| ~IsolatedOriginEntry(); |
| |
| // Allow this class to be used as a key in STL. |
| bool operator<(const IsolatedOriginEntry& other) const { |
| return std::tie(origin_, applies_to_future_browsing_instances_, |
| browsing_instance_id_, browser_context_, |
| resource_context_, isolate_all_subdomains_, source_) < |
| std::tie(other.origin_, |
| other.applies_to_future_browsing_instances_, |
| other.browsing_instance_id_, other.browser_context_, |
| other.resource_context_, other.isolate_all_subdomains_, |
| source_); |
| } |
| |
| bool operator==(const IsolatedOriginEntry& other) const { |
| return origin_ == other.origin_ && |
| applies_to_future_browsing_instances_ == |
| other.applies_to_future_browsing_instances_ && |
| browsing_instance_id_ == other.browsing_instance_id_ && |
| browser_context_ == other.browser_context_ && |
| resource_context_ == other.resource_context_ && |
| isolate_all_subdomains_ == other.isolate_all_subdomains_ && |
| source_ == other.source_; |
| } |
| |
| // True if this isolated origin applies globally to all profiles. |
| bool AppliesToAllBrowserContexts() const; |
| |
| // True if (1) this entry is associated with the same profile as |
| // |browser_or_resource_context|, or (2) this entry applies to all |
| // profiles. May be used on UI or IO threads. |
| bool MatchesProfile( |
| const BrowserOrResourceContext& browser_or_resource_context) const; |
| |
| // True if this entry applies to the BrowsingInstance specified by |
| // `browsing_instance_id`. See `applies_to_future_browsing_instances_` and |
| // `browsing_instance_id_` for more details. |
| bool MatchesBrowsingInstance(BrowsingInstanceId browsing_instance_id) const; |
| |
| const url::Origin& origin() const { return origin_; } |
| |
| // See the declaration of `applies_to_future_browsing_instances_` for |
| // details. |
| bool applies_to_future_browsing_instances() const { |
| return applies_to_future_browsing_instances_; |
| } |
| |
| // See the declaration of `browsing_instance_id_` for details. |
| BrowsingInstanceId browsing_instance_id() const { |
| return browsing_instance_id_; |
| } |
| |
| const BrowserContext* browser_context() const { return browser_context_; } |
| |
| bool isolate_all_subdomains() const { return isolate_all_subdomains_; } |
| |
| IsolatedOriginSource source() const { return source_; } |
| |
| private: |
| url::Origin origin_; |
| |
| // If this is false, the origin is isolated only in the BrowsingInstance |
| // specified by `browsing_instance_id_`. If this is true, the origin is |
| // isolated in all BrowsingInstances that have an ID equal to or |
| // greater than `browsing_instance_id_`. |
| bool applies_to_future_browsing_instances_; |
| |
| // Specifies which BrowsingInstance(s) this IsolatedOriginEntry applies to. |
| // When `applies_to_future_browsing_instances_` is false, this refers to a |
| // specific BrowsingInstance. Otherwise, it specifies the minimum |
| // BrowsingInstance ID, and the origin is isolated in all |
| // BrowsingInstances with IDs greater than or equal to this value. |
| BrowsingInstanceId browsing_instance_id_; |
| |
| // Optional information about the profile where the isolated origin |
| // applies. |browser_context_| may be used on the UI thread, and |
| // |resource_context_| may be used on the IO thread. If these are null, |
| // then the isolated origin applies globally to all profiles. |
| raw_ptr<BrowserContext> browser_context_; |
| raw_ptr<ResourceContext> resource_context_; |
| |
| // True if origins at this or lower level should be treated as distinct |
| // isolated origins, effectively isolating all domains below a given domain, |
| // e.g. if the origin is https://foo.com and isolate_all_subdomains_ is |
| // true, then https://bar.foo.com, https://qux.bar.foo.com and all |
| // subdomains of the form https://<<any pattern here>>.foo.com are |
| // considered isolated origins. |
| bool isolate_all_subdomains_; |
| |
| // This tracks the source of each isolated origin entry, e.g., to |
| // distinguish those that should be displayed to the user from those that |
| // should not. See https://crbug.com/920911. |
| IsolatedOriginSource source_; |
| }; |
| |
| // A struct to hold the OAC opted-in origins and their isolation state. It |
| // associates a specific |origin| with its OriginAgentClusterIsolationState, |
| // and is tracked in |origin_isolation_by_browsing_instance_|. |
| struct OriginAgentClusterOptInEntry { |
| OriginAgentClusterOptInEntry( |
| const OriginAgentClusterIsolationState& oac_isolation_state_in, |
| const url::Origin& origin_in); |
| OriginAgentClusterOptInEntry(const OriginAgentClusterOptInEntry&); |
| ~OriginAgentClusterOptInEntry(); |
| |
| OriginAgentClusterIsolationState oac_isolation_state; |
| url::Origin origin; |
| }; |
| |
| // Obtain an instance of ChildProcessSecurityPolicyImpl via GetInstance(). |
| ChildProcessSecurityPolicyImpl(); |
| friend struct base::DefaultSingletonTraits<ChildProcessSecurityPolicyImpl>; |
| |
| // Determines if certain permissions were granted for a file to given child |
| // process. |permissions| is an internally defined bit-set. |
| bool ChildProcessHasPermissionsForFile(int child_id, |
| const base::FilePath& file, |
| int permissions) |
| EXCLUSIVE_LOCKS_REQUIRED(lock_); |
| |
| // Grant a particular permission set for a file. |permissions| is an |
| // internally defined bit-set. |
| void GrantPermissionsForFile(int child_id, |
| const base::FilePath& file, |
| int permissions); |
| |
| // Grants access permission to the given isolated file system |
| // identified by |filesystem_id|. See comments for |
| // ChildProcessSecurityPolicy::GrantReadFileSystem() for more details. |
| void GrantPermissionsForFileSystem(int child_id, |
| const std::string& filesystem_id, |
| int permission); |
| |
| // Determines if certain permissions were granted for a file. |permissions| |
| // is an internally defined bit-set. |
| bool HasPermissionsForFile(int child_id, |
| const base::FilePath& file, |
| int permissions); |
| |
| // Determines if certain permissions were granted for a file in FileSystem |
| // API. |permissions| is an internally defined bit-set. |
| bool HasPermissionsForFileSystemFile( |
| int child_id, |
| const storage::FileSystemURL& filesystem_url, |
| int permissions); |
| |
| // Determines if certain permissions were granted for a file system. |
| // |permissions| is an internally defined bit-set. |
| bool HasPermissionsForFileSystem(int child_id, |
| const std::string& filesystem_id, |
| int permission); |
| |
| // Gets the SecurityState object associated with |child_id|. |
| // Note: Returned object is only valid for the duration the caller holds |
| // |lock_|. |
| SecurityState* GetSecurityState(int child_id) EXCLUSIVE_LOCKS_REQUIRED(lock_); |
| |
| // Convert a list of comma separated isolated origins in |pattern_list|, |
| // specified either as wildcard origins, non-wildcard origins or a mix of the |
| // two into IsolatedOriginPatterns, suitable for addition via |
| // AddFutureIsolatedOrigins(). |
| static std::vector<IsolatedOriginPattern> ParseIsolatedOrigins( |
| std::string_view pattern_list); |
| |
| void AddFutureIsolatedOrigins( |
| const std::vector<IsolatedOriginPattern>& patterns, |
| IsolatedOriginSource source, |
| BrowserContext* browser_context = nullptr); |
| |
| // Internal helper used for adding a particular isolated origin. See |
| // IsolatedOriginEntry for descriptions of various parameters. |
| void AddIsolatedOriginInternal(BrowserContext* browser_context, |
| const url::Origin& origin, |
| bool applies_to_future_browsing_instances, |
| BrowsingInstanceId browsing_instance_id, |
| bool isolate_all_subdomains, |
| IsolatedOriginSource source) |
| EXCLUSIVE_LOCKS_REQUIRED(isolated_origins_lock_); |
| |
| bool AddProcessReference(int child_id, bool duplicating_handle); |
| bool AddProcessReferenceLocked(int child_id, bool duplicating_handle) |
| EXCLUSIVE_LOCKS_REQUIRED(lock_); |
| void RemoveProcessReference(int child_id); |
| void RemoveProcessReferenceLocked(int child_id) |
| EXCLUSIVE_LOCKS_REQUIRED(lock_); |
| |
| // Internal helper for RemoveOptInIsolatedOriginsForBrowsingInstance(). |
| void RemoveOptInIsolatedOriginsForBrowsingInstanceInternal( |
| const BrowsingInstanceId browsing_instance_id); |
| |
| // Creates the value to place in the "killed_process_origin_lock" crash key |
| // based on the contents of |security_state|. |
| static std::string GetKilledProcessOriginLock( |
| const SecurityState* security_state); |
| |
| // Helper for CanAccessMaybeOpaqueOrigin, to perform two security checks: |
| // - Jail check: a process locked to a particular site shouldn't access data |
| // belonging to other sites. |
| // - Citadel check: a process not locked to any site shouldn't access data |
| // belonging to sites that require a dedicated process. |
| // |
| // These checks are performed by comparing the actual ProcessLock of the |
| // process represented by `child_id` and `security_state` to an expected |
| // ProcessLock computed from `url`, which takes into account factors such as |
| // whether `url` should be site-isolated or origin-isolated (or not isolated, |
| // e.g. on Android). Determining site-vs-origin isolation is non-trivial: the |
| // answer may differ depending on BrowsingInstance (e.g., OriginAgentCluster |
| // might require origin isolation only for certain BrowsingInstances), so all |
| // BrowsingInstances hosting in the process must be consulted. |
| // |
| // This function returns true only if both Jail and Citadel checks pass. On |
| // failure, it also populates `out_failure_reason` with debugging information |
| // about the cause of the failure, as well as `out_expected_process_lock` with |
| // what the process lock was expected to be (e.g., to be used in crash keys). |
| // |
| // This function must be called while already holding `lock_`. |
| bool PerformJailAndCitadelChecks(int child_id, |
| SecurityState* security_state, |
| const GURL& url, |
| bool url_is_precursor_of_opaque_origin, |
| AccessType access_type, |
| ProcessLock& out_expected_process_lock, |
| std::string& out_failure_reason) |
| EXCLUSIVE_LOCKS_REQUIRED(lock_); |
| |
| // Helper for public CanAccessOrigin overloads. |
| bool CanAccessMaybeOpaqueOrigin(int child_id, |
| const GURL& url, |
| bool url_is_precursor_of_opaque_origin, |
| AccessType access_type); |
| |
| // Helper used by CanAccessOrigin to impose additional restrictions on a |
| // sandboxed process locked to `process_lock`. |
| bool IsAccessAllowedForSandboxedProcess(const ProcessLock& process_lock, |
| const GURL& url, |
| bool url_is_for_opaque_origin, |
| AccessType access_type); |
| |
| // Helper used by CanAccessOrigin to impose additional restrictions on a |
| // process that only hosts PDF documents. |
| bool IsAccessAllowedForPdfProcess(AccessType access_type); |
| |
| // Utility function to simplify lookups for OriginAgentClusterOptInEntry |
| // values by origin. |
| OriginAgentClusterIsolationState* LookupOriginIsolationState( |
| const BrowsingInstanceId& browsing_instance_id, |
| const url::Origin& origin) |
| EXCLUSIVE_LOCKS_REQUIRED(origins_isolation_opt_in_lock_); |
| |
| // You must acquire this lock before reading or writing any members of this |
| // class, except for isolated_origins_, schemes_okay_to_*, and |
| // pseudo_schemes_, which use their own locks. You must not block while |
| // holding this lock. |
| base::Lock lock_; |
| |
| // These schemes are allow-listed for all child processes in various contexts. |
| // These sets are protected by |schemes_lock_| rather than |lock_|. |
| base::Lock schemes_lock_; |
| SchemeSet schemes_okay_to_commit_in_any_process_ GUARDED_BY(schemes_lock_); |
| SchemeSet schemes_okay_to_request_in_any_process_ GUARDED_BY(schemes_lock_); |
| SchemeSet schemes_okay_to_appear_as_origin_headers_ GUARDED_BY(schemes_lock_); |
| |
| // These schemes do not actually represent retrievable URLs. For example, |
| // the the URLs in the "about" scheme are aliases to other URLs. This set is |
| // protected by |schemes_lock_|. |
| SchemeSet pseudo_schemes_ GUARDED_BY(schemes_lock_); |
| |
| // This map holds a SecurityState for each child process. The key for the |
| // map is the ID of the ChildProcessHost. The SecurityState objects are |
| // owned by this object and are protected by |lock_|. References to them must |
| // not escape this class. |
| SecurityStateMap security_state_ GUARDED_BY(lock_); |
| |
| // This map holds the SecurityState for a child process after Remove() |
| // is called on the UI thread. An entry stays in this map until a task has |
| // run on the IO thread. This is necessary to provide consistent security |
| // decisions and avoid races between the UI & IO threads during child process |
| // shutdown. This separate map is used to preserve SecurityState info AND |
| // preventing mutation of that state after Remove() is called. |
| SecurityStateMap pending_remove_state_ GUARDED_BY(lock_); |
| |
| FileSystemPermissionPolicyMap file_system_policy_map_ GUARDED_BY(lock_); |
| |
| // Contains a mapping between child process ID and the number of outstanding |
| // references that want to keep the SecurityState for each process alive. |
| // This object and Handles created by this object increment/decrement |
| // the counts in this map and only destroy a SecurityState object for a |
| // process when its count goes to zero. |
| std::map<int, int> process_reference_counts_ GUARDED_BY(lock_); |
| |
| // You must acquire this lock before reading or writing isolated_origins_. |
| // You must not block while holding this lock. |
| // |
| // It is allowed to hold both |lock_| and |isolated_origins_lock_|, but in |
| // this case, |lock_| should always be acquired first to prevent deadlock. |
| base::Lock isolated_origins_lock_ ACQUIRED_AFTER(lock_); |
| |
| // Tracks origins for which the entire origin should be treated as a site |
| // when making process model decisions, rather than the origin's scheme and |
| // eTLD+1. Each of these origins requires a dedicated process. This set is |
| // protected by |isolated_origins_lock_|. |
| // |
| // The origins are stored in a map indexed by a site URL computed for each |
| // origin. For example, adding https://foo.com, https://bar.foo.com, and |
| // https://www.bar.com would result in the following structure: |
| // https://foo.com -> { https://foo.com, https://bar.foo.com } |
| // https://bar.com -> { https://www.bar.com } |
| // This organization speeds up lookups of isolated origins. The site can be |
| // found in O(log n) time, and the corresponding list of origins to search |
| // using the expensive DoesOriginMatchIsolatedOrigin() comparison is |
| // typically small. |
| // |
| // Each origin entry stores information about: |
| // 1. Which BrowsingInstances it applies to. This is a combination of a |
| // BrowsingInstance ID |browsing_instance_id_| and a bool flag |
| // |applies_to_future_browsing_instances_| stored in in each origin's |
| // IsolatedOriginEntry. When |applies_to_future_browsing_instances_| is |
| // true, the origin will be isolated in all BrowsingInstances with |
| // IDs equal to or greater than |browsing_instance_id_|. When |
| // |applies_to_future_browsing_instances_| is false, the origin will be |
| // isolated only in a single BrowsingInstance with ID |
| // |browsing_instance_id_|. |
| // 2. Optionally, which BrowserContext (profile) it applies to. When the |
| // |browser_context| field in the IsolatedOriginEntry is non-null, a |
| // particular isolated origin entry only applies to that BrowserContext. |
| // A ResourceContext, BrowserContext's representation on the IO thread, |
| // is also stored in the entry to facilitate checks on the IO thread. |
| // Note that the same origin may be isolated in different profiles, |
| // possibly with different BrowsingInstance ID cut-offs. For example: |
| // https://foo.com -> { [https://test.foo.com profile1 4], |
| // [https://test.foo.com profile2 7] } |
| // represents https://test.foo.com being isolated in profile1 |
| // with BrowsingInstance ID 4, and also in profile2 with |
| // BrowsingInstance ID 7. |
| base::flat_map<GURL, std::vector<IsolatedOriginEntry>> isolated_origins_ |
| GUARDED_BY(isolated_origins_lock_); |
| |
| // TODO(wjmaclean): Move these lists into a per-BrowserContext container, to |
| // prevent any record of sites visible in one profile from being visible to |
| // another profile. |
| base::Lock origins_isolation_opt_in_lock_; |
| // The set of all origins that have ever requested opt-in isolation or |
| // requested to opt-out, organized by BrowserContext. This is tracked so we |
| // know which origins need to be tracked when using default isolation in any |
| // given BrowsingInstance. Origins requesting isolation opt-in or out, if |
| // successful, are marked as isolated or not via |
| // DetermineOriginAgentClusterIsolation's checking |
| // |requested_isolation_state|. Each BrowserContext's state is tracked |
| // separately so that timing attacks do not reveal whether an origin has been |
| // visited in another (e.g., incognito) BrowserContext. In general, the state |
| // of other BrowsingInstances is not observable outside such timing side |
| // channels. |
| base::flat_map<BrowserContext*, base::flat_set<url::Origin>> |
| origin_isolation_opt_ins_and_outs_ |
| GUARDED_BY(origins_isolation_opt_in_lock_); |
| |
| // A map to track origins that have been isolated within a given |
| // BrowsingInstance, or that have been loaded in a BrowsingInstance |
| // without isolation, but that have requested isolation in at least one other |
| // BrowsingInstance. Origins loaded without isolation are tracked to make sure |
| // we don't try to isolate the origin in the associated BrowsingInstance at a |
| // later time, in order to keep the isolation consistent over the lifetime of |
| // the BrowsingInstance. |
| base::flat_map<BrowsingInstanceId, std::vector<OriginAgentClusterOptInEntry>> |
| origin_isolation_by_browsing_instance_ |
| GUARDED_BY(origins_isolation_opt_in_lock_); |
| |
| // When we are notified a BrowsingInstance has destructed, delay cleanup by |
| // this amount to allow outstanding IO thread requests to complete. May be set |
| // to different values in tests. Note: the value is chosen to be slightly |
| // longer than the KeepAliveHandleFactory delay of 30 seconds, with the aim of |
| // covering the maximum time needed by any IncrementKeepAliveRefCount callers. |
| // TODO(wjmaclean): we know the IncrementKeepAliveRefCount API needs |
| // improvement, and with it the BrowsingInstance cleanup here can also be |
| // improved. |
| base::TimeDelta browsing_instance_cleanup_delay_; |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_BROWSER_CHILD_PROCESS_SECURITY_POLICY_IMPL_H_ |