#include "chrome/browser/file_system_access/chrome_file_system_access_permission_context.h"
#include <iterator>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include "base/base_paths.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/values_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/notreached.h"
#include "base/path_service.h"
#include "base/ranges/algorithm.h"
#include "base/strings/strcat.h"
#include "base/task/bind_post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.h"
#include "chrome/browser/file_system_access/file_system_access_permission_request_manager.h"
#include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/safe_browsing/download_protection/download_protection_util.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/file_system_access/file_system_access_dangerous_file_dialog.h"
#include "chrome/browser/ui/file_system_access/file_system_access_dialogs.h"
#include "chrome/browser/ui/file_system_access/file_system_access_restricted_directory_dialog.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/grit/generated_resources.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/pdf/common/pdf_util.h"
#include "components/permissions/features.h"
#include "components/permissions/object_permission_context_base.h"
#include "components/permissions/permission_decision_auto_blocker.h"
#include "components/permissions/permission_uma_util.h"
#include "components/permissions/permission_util.h"
#include "components/safe_browsing/buildflags.h"
#include "components/safe_browsing/content/common/file_type_policies.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/disallow_activation_reason.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/origin.h"
#if !BUILDFLAG(IS_ANDROID)
#include "chrome/browser/permissions/one_time_permissions_tracker_factory.h"
#include "chrome/browser/permissions/one_time_permissions_tracker_observer.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/web_applications/web_app_install_manager.h"
#include "chrome/browser/web_applications/web_app_install_manager_observer.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.h"
#endif
#if BUILDFLAG(FULL_SAFE_BROWSING)
#include "chrome/browser/safe_browsing/download_protection/download_protection_service.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#endif
namespace {
FileRequestData;
RequestAccess;
HandleType;
PersistedGrantStatus;
GrantType;
PermissionStatus;
PermissionAction;
constexpr base::TimeDelta kPermissionRevocationTimeout = …;
const char kPermissionIsDirectoryKey[] = …;
const char kPermissionWritableKey[] = …;
const char kPermissionReadableKey[] = …;
const char kDeprecatedPermissionLastUsedTimeKey[] = …;
const char kDefaultLastPickedDirectoryKey[] = …;
const char kCustomLastPickedDirectoryKey[] = …;
const char kPathKey[] = …;
const char kPathTypeKey[] = …;
const char kTimestampKey[] = …;
void ShowFileSystemAccessRestrictedDirectoryDialogOnUIThread(
content::GlobalRenderFrameHostId frame_id,
const url::Origin& origin,
HandleType handle_type,
base::OnceCallback<
void(ChromeFileSystemAccessPermissionContext::SensitiveEntryResult)>
callback) { … }
void ShowFileSystemAccessDangerousFileDialogOnUIThread(
content::GlobalRenderFrameHostId frame_id,
const url::Origin& origin,
const base::FilePath& path,
base::OnceCallback<
void(ChromeFileSystemAccessPermissionContext::SensitiveEntryResult)>
callback) { … }
#if BUILDFLAG(IS_WIN)
bool ContainsInvalidDNSCharacter(base::FilePath::StringType hostname) {
for (base::FilePath::CharType c : hostname) {
if (!((c >= L'A' && c <= L'Z') || (c >= L'a' && c <= L'z') ||
(c >= L'0' && c <= L'9') || (c == L'.') || (c == L'-'))) {
return true;
}
}
return false;
}
bool MaybeIsLocalUNCPath(const base::FilePath& path) {
if (!path.IsNetwork()) {
return false;
}
const std::vector<base::FilePath::StringType> components =
path.GetComponents();
if (components.size() >= 2 &&
(base::FilePath::CompareEqualIgnoreCase(components[1],
FILE_PATH_LITERAL("localhost")) ||
components[1] == FILE_PATH_LITERAL("127.0.0.1") ||
components[1] == FILE_PATH_LITERAL(".") ||
components[1] == FILE_PATH_LITERAL("?") ||
ContainsInvalidDNSCharacter(components[1]))) {
return true;
}
for (size_t i = 2; i < components.size(); ++i) {
if (components[i].back() == L'$') {
return true;
}
}
return false;
}
#endif
constexpr const int kNoBasePathKey = …;
enum BlockType { … };
const struct { … } kBlockedPaths[] = …;
struct BlockPathRule { … };
bool ShouldBlockAccessToPath(const base::FilePath& path,
HandleType handle_type,
std::vector<BlockPathRule> rules) { … }
void DoSafeBrowsingCheckOnUIThread(
content::GlobalRenderFrameHostId frame_id,
std::unique_ptr<content::FileSystemAccessWriteItem> item,
safe_browsing::CheckDownloadCallback callback) { … }
ChromeFileSystemAccessPermissionContext::AfterWriteCheckResult
InterpretSafeBrowsingResult(safe_browsing::DownloadCheckResult result) { … }
std::string GenerateLastPickedDirectoryKey(const std::string& id) { … }
std::string_view PathAsPermissionKey(const base::FilePath& path) { … }
std::string_view GetGrantKeyFromGrantType(GrantType type) { … }
bool FileHasDangerousExtension(const url::Origin& origin,
const base::FilePath& path,
Profile* profile) { … }
}
ChromeFileSystemAccessPermissionContext::Grants::Grants() = default;
ChromeFileSystemAccessPermissionContext::Grants::~Grants() = default;
ChromeFileSystemAccessPermissionContext::Grants::Grants(Grants&&) = default;
ChromeFileSystemAccessPermissionContext::Grants&
ChromeFileSystemAccessPermissionContext::Grants::operator=(Grants&&) = default;
class ChromeFileSystemAccessPermissionContext::PermissionGrantImpl
: public content::FileSystemAccessPermissionGrant { … };
struct ChromeFileSystemAccessPermissionContext::OriginState { … };
ChromeFileSystemAccessPermissionContext::
ChromeFileSystemAccessPermissionContext(content::BrowserContext* context,
const base::Clock* clock)
: … { … }
ChromeFileSystemAccessPermissionContext::
~ChromeFileSystemAccessPermissionContext() = default;
bool ChromeFileSystemAccessPermissionContext::RevokeActiveGrants(
const url::Origin& origin,
base::FilePath file_path) { … }
void ChromeFileSystemAccessPermissionContext::RevokeAllActiveGrants() { … }
scoped_refptr<content::FileSystemAccessPermissionGrant>
ChromeFileSystemAccessPermissionContext::GetReadPermissionGrant(
const url::Origin& origin,
const base::FilePath& path,
HandleType handle_type,
UserAction user_action) { … }
scoped_refptr<content::FileSystemAccessPermissionGrant>
ChromeFileSystemAccessPermissionContext::GetWritePermissionGrant(
const url::Origin& origin,
const base::FilePath& path,
HandleType handle_type,
UserAction user_action) { … }
std::vector<std::unique_ptr<permissions::ObjectPermissionContextBase::Object>>
ChromeFileSystemAccessPermissionContext::GetExtendedPersistedObjects(
const url::Origin& origin) { … }
std::vector<std::unique_ptr<permissions::ObjectPermissionContextBase::Object>>
ChromeFileSystemAccessPermissionContext::GetGrantedObjects(
const url::Origin& origin) { … }
std::vector<std::unique_ptr<permissions::ObjectPermissionContextBase::Object>>
ChromeFileSystemAccessPermissionContext::GetAllGrantedObjects() { … }
std::set<url::Origin>
ChromeFileSystemAccessPermissionContext::GetOriginsWithGrants() { … }
std::string ChromeFileSystemAccessPermissionContext::GetKeyForObject(
const base::Value::Dict& object) { … }
bool ChromeFileSystemAccessPermissionContext::IsValidObject(
const base::Value::Dict& dict) { … }
std::u16string ChromeFileSystemAccessPermissionContext::GetObjectDisplayName(
const base::Value::Dict& object) { … }
ContentSetting
ChromeFileSystemAccessPermissionContext::GetReadGuardContentSetting(
const url::Origin& origin) const { … }
ContentSetting
ChromeFileSystemAccessPermissionContext::GetWriteGuardContentSetting(
const url::Origin& origin) const { … }
std::vector<base::FilePath>
ChromeFileSystemAccessPermissionContext::GetGrantedPaths(
const url::Origin& origin) { … }
bool ChromeFileSystemAccessPermissionContext::CanObtainReadPermission(
const url::Origin& origin) { … }
bool ChromeFileSystemAccessPermissionContext::CanObtainWritePermission(
const url::Origin& origin) { … }
void ChromeFileSystemAccessPermissionContext::ConfirmSensitiveEntryAccess(
const url::Origin& origin,
PathType path_type,
const base::FilePath& path,
HandleType handle_type,
UserAction user_action,
content::GlobalRenderFrameHostId frame_id,
base::OnceCallback<void(SensitiveEntryResult)> callback) { … }
void ChromeFileSystemAccessPermissionContext::CheckPathsAgainstEnterprisePolicy(
std::vector<PathInfo> entries,
content::GlobalRenderFrameHostId frame_id,
EntriesAllowedByEnterprisePolicyCallback callback) { … }
#if BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)
void ChromeFileSystemAccessPermissionContext::OnContentAnalysisComplete(
std::vector<PathInfo> entries,
EntriesAllowedByEnterprisePolicyCallback callback,
std::vector<base::FilePath> paths,
std::vector<bool> allowed) { … }
#endif
void ChromeFileSystemAccessPermissionContext::CheckPathAgainstBlocklist(
PathType path_type,
const base::FilePath& path,
HandleType handle_type,
base::OnceCallback<void(bool)> callback) { … }
void ChromeFileSystemAccessPermissionContext::PerformAfterWriteChecks(
std::unique_ptr<content::FileSystemAccessWriteItem> item,
content::GlobalRenderFrameHostId frame_id,
base::OnceCallback<void(AfterWriteCheckResult)> callback) { … }
void ChromeFileSystemAccessPermissionContext::DidCheckPathAgainstBlocklist(
const url::Origin& origin,
const base::FilePath& path,
HandleType handle_type,
UserAction user_action,
content::GlobalRenderFrameHostId frame_id,
base::OnceCallback<void(SensitiveEntryResult)> callback,
bool should_block) { … }
void ChromeFileSystemAccessPermissionContext::MaybeEvictEntries(
base::Value::Dict& dict) { … }
void ChromeFileSystemAccessPermissionContext::SetLastPickedDirectory(
const url::Origin& origin,
const std::string& id,
const base::FilePath& path,
const PathType type) { … }
ChromeFileSystemAccessPermissionContext::PathInfo
ChromeFileSystemAccessPermissionContext::GetLastPickedDirectory(
const url::Origin& origin,
const std::string& id) { … }
base::FilePath
ChromeFileSystemAccessPermissionContext::GetWellKnownDirectoryPath(
blink::mojom::WellKnownDirectory directory,
const url::Origin& origin) { … }
std::u16string ChromeFileSystemAccessPermissionContext::GetPickerTitle(
const blink::mojom::FilePickerOptionsPtr& options) { … }
void ChromeFileSystemAccessPermissionContext::NotifyEntryMoved(
const url::Origin& origin,
const base::FilePath& old_path,
const base::FilePath& new_path) { … }
void ChromeFileSystemAccessPermissionContext::
OnFileCreatedFromShowSaveFilePicker(const GURL& file_picker_binding_context,
const storage::FileSystemURL& url) { … }
base::CallbackListSubscription ChromeFileSystemAccessPermissionContext::
AddFileCreatedFromShowSaveFilePickerCallback(
FileCreatedFromShowSaveFilePickerCallbackList::CallbackType callback) { … }
ChromeFileSystemAccessPermissionContext::Grants
ChromeFileSystemAccessPermissionContext::ConvertObjectsToGrants(
const std::vector<std::unique_ptr<Object>> objects) { … }
void ChromeFileSystemAccessPermissionContext::
CreatePersistedGrantsFromActiveGrants(const url::Origin& origin) { … }
void ChromeFileSystemAccessPermissionContext::RevokeGrant(
const url::Origin& origin,
const base::FilePath& file_path) { … }
void ChromeFileSystemAccessPermissionContext::RevokeGrants(
const url::Origin& origin) { … }
bool ChromeFileSystemAccessPermissionContext::OriginHasReadAccess(
const url::Origin& origin) { … }
bool ChromeFileSystemAccessPermissionContext::OriginHasWriteAccess(
const url::Origin& origin) { … }
#if !BUILDFLAG(IS_ANDROID)
void ChromeFileSystemAccessPermissionContext::OnAllTabsInBackgroundTimerExpired(
const url::Origin& origin,
const OneTimePermissionsTrackerObserver::BackgroundExpiryType&
expiry_type) { … }
void ChromeFileSystemAccessPermissionContext::OnLastPageFromOriginClosed(
const url::Origin& origin) { … }
void ChromeFileSystemAccessPermissionContext::OnShutdown() { … }
void ChromeFileSystemAccessPermissionContext::OnWebAppInstalled(
const webapps::AppId& app_id) { … }
void ChromeFileSystemAccessPermissionContext::OnWebAppInstalledWithOsHooks(
const webapps::AppId& app_id) { … }
void ChromeFileSystemAccessPermissionContext::OnWebAppWillBeUninstalled(
const webapps::AppId& app_id) { … }
void ChromeFileSystemAccessPermissionContext::
OnWebAppInstallManagerDestroyed() { … }
#endif
void ChromeFileSystemAccessPermissionContext::NavigatedAwayFromOrigin(
const url::Origin& origin) { … }
void ChromeFileSystemAccessPermissionContext::TriggerTimersForTesting() { … }
void ChromeFileSystemAccessPermissionContext::MaybeCleanupPermissions(
const url::Origin& origin) { … }
void ChromeFileSystemAccessPermissionContext::CleanupPermissions(
const url::Origin& origin) { … }
void ChromeFileSystemAccessPermissionContext::
OnRestorePermissionAllowedEveryTime(const url::Origin& origin) { … }
void ChromeFileSystemAccessPermissionContext::OnRestorePermissionAllowedOnce(
const url::Origin& origin) { … }
void ChromeFileSystemAccessPermissionContext::
UpdateGrantsOnRestorePermissionAllowed(const url::Origin& origin) { … }
void ChromeFileSystemAccessPermissionContext::
OnRestorePermissionDeniedOrDismissed(const url::Origin& origin) { … }
void ChromeFileSystemAccessPermissionContext::OnRestorePermissionIgnored(
const url::Origin& origin) { … }
void ChromeFileSystemAccessPermissionContext::
UpdateGrantsOnRestorePermissionNotAllowed(const url::Origin& origin) { … }
void ChromeFileSystemAccessPermissionContext::
UpdateGrantsOnPermissionRequestResult(const url::Origin& origin) { … }
bool ChromeFileSystemAccessPermissionContext::AncestorHasActivePermission(
const url::Origin& origin,
const base::FilePath& path,
GrantType grant_type) const { … }
bool ChromeFileSystemAccessPermissionContext::HasGrantedActivePermissionStatus(
PermissionGrantImpl* grant) const { … }
bool ChromeFileSystemAccessPermissionContext::
IsEligibleToUpgradePermissionRequestToRestorePrompt(
const url::Origin& origin,
const base::FilePath& file_path,
HandleType handle_type,
UserAction user_action,
GrantType grant_type) { … }
std::vector<FileRequestData> ChromeFileSystemAccessPermissionContext::
GetFileRequestDataForRestorePermissionPrompt(const url::Origin& origin) { … }
bool ChromeFileSystemAccessPermissionContext::HasPersistedGrantObject(
const url::Origin& origin,
const base::FilePath& file_path,
HandleType handle_type,
GrantType grant_type) { … }
bool ChromeFileSystemAccessPermissionContext::HasMatchingValue(
const base::Value::Dict& value,
const base::FilePath& file_path,
HandleType handle_type,
GrantType grant_type) { … }
void ChromeFileSystemAccessPermissionContext::
SetOriginHasExtendedPermissionForTesting(const url::Origin& origin) { … }
scoped_refptr<content::FileSystemAccessPermissionGrant>
ChromeFileSystemAccessPermissionContext::
GetExtendedReadPermissionGrantForTesting(
const url::Origin& origin,
const base::FilePath& path,
HandleType handle_type) { … }
scoped_refptr<content::FileSystemAccessPermissionGrant>
ChromeFileSystemAccessPermissionContext::
GetExtendedWritePermissionGrantForTesting(
const url::Origin& origin,
const base::FilePath& path,
HandleType handle_type) { … }
void ChromeFileSystemAccessPermissionContext::Shutdown() { … }
bool ChromeFileSystemAccessPermissionContext::
CanAutoGrantViaPersistentPermission(const url::Origin& origin,
const base::FilePath& path,
HandleType handle_type,
GrantType grant_type) { … }
bool ChromeFileSystemAccessPermissionContext::
CanAutoGrantViaAncestorPersistentPermission(const url::Origin& origin,
const base::FilePath& path,
GrantType grant_type) { … }
bool ChromeFileSystemAccessPermissionContext::OriginHasExtendedPermission(
const url::Origin& origin) { … }
void ChromeFileSystemAccessPermissionContext::SetOriginExtendedPermissionByUser(
const url::Origin& origin) { … }
void ChromeFileSystemAccessPermissionContext::
RemoveOriginExtendedPermissionByUser(const url::Origin& origin) { … }
void ChromeFileSystemAccessPermissionContext::RemoveExtendedPermission(
const url::Origin& origin) { … }
void ChromeFileSystemAccessPermissionContext::UpgradeToExtendedPermission(
const url::Origin& origin) { … }
ChromeFileSystemAccessPermissionContext::PersistedGrantType
ChromeFileSystemAccessPermissionContext::GetPersistedGrantType(
const url::Origin& origin) { … }
PersistedGrantStatus
ChromeFileSystemAccessPermissionContext::GetPersistedGrantStatus(
const url::Origin& origin) const { … }
void ChromeFileSystemAccessPermissionContext::SetPersistedGrantStatus(
const url::Origin& origin,
PersistedGrantStatus persisted_grant_status) { … }
void ChromeFileSystemAccessPermissionContext::PermissionGrantDestroyed(
PermissionGrantImpl* grant) { … }
void ChromeFileSystemAccessPermissionContext::ScheduleUsageIconUpdate() { … }
void ChromeFileSystemAccessPermissionContext::DoUsageIconUpdate() { … }
base::WeakPtr<ChromeFileSystemAccessPermissionContext>
ChromeFileSystemAccessPermissionContext::GetWeakPtr() { … }