1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
content / browser / child_process_security_policy_impl.h [blame]
// 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);
// 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);
// 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);
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_