fix: revoke Read access after removing file via FileSystemAccess API (#49620)

Refs https://chromium-review.googlesource.com/6677249
This commit is contained in:
Shelley Vohr
2026-02-10 15:48:05 +01:00
committed by GitHub
parent ef5b232e9f
commit 57a6e43025
2 changed files with 87 additions and 2 deletions

View File

@@ -36,6 +36,7 @@
#include "shell/browser/web_contents_permission_helper.h"
#include "shell/common/gin_converters/callback_converter.h"
#include "shell/common/gin_converters/file_path_converter.h"
#include "third_party/blink/public/common/features_generated.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"
@@ -443,6 +444,28 @@ class FileSystemAccessPermissionContext::PermissionGrantImpl
}
}
// Downgrades the in-memory read permission grant for the `path` if it exist
// in `grants`. This is different from
// ChromeFileSystemAccessPermissionContext::RevokeGrant in that this method
// does not reset the persisted permission state.
static void DowngradeReadGrantInMemory(
std::map<base::FilePath, PermissionGrantImpl*>& grants,
const content::PathInfo& path) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
auto entry_it = std::ranges::find_if(grants, [&path](const auto& entry) {
return entry.first == path.path;
});
if (entry_it == grants.end()) {
return;
}
DCHECK_EQ(entry_it->second->GetActivePermissionStatus(),
PermissionStatus::GRANTED);
auto* const grant_impl = entry_it->second;
grant_impl->SetStatus(PermissionStatus::DENIED);
}
protected:
~PermissionGrantImpl() override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -495,6 +518,10 @@ struct FileSystemAccessPermissionContext::OriginState {
// PermissionGrantDestroyed().
std::map<base::FilePath, PermissionGrantImpl*> read_grants;
std::map<base::FilePath, PermissionGrantImpl*> write_grants;
// Stores paths whose read grants have been downgraded to ASK after a
// remove() call and are eligible for restoration.
std::set<base::FilePath> downgraded_read_paths;
};
FileSystemAccessPermissionContext::FileSystemAccessPermissionContext(
@@ -958,15 +985,68 @@ void FileSystemAccessPermissionContext::NotifyEntryMoved(
PermissionGrantImpl::UpdateGrantPath(it->second.read_grants, old_path,
new_path, allow_overwrite);
}
if (base::FeatureList::IsEnabled(
blink::features::kFileSystemAccessRevokeReadOnRemove)) {
MaybeRestoreReadPermission(origin, new_path.path);
}
}
void FileSystemAccessPermissionContext::NotifyEntryModified(
const url::Origin& origin,
const content::PathInfo& path) {}
const content::PathInfo& path) {
CHECK(base::FeatureList::IsEnabled(
blink::features::kFileSystemAccessRevokeReadOnRemove));
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
MaybeRestoreReadPermission(origin, path.path);
}
void FileSystemAccessPermissionContext::MaybeRestoreReadPermission(
const url::Origin& origin,
const base::FilePath& path) {
auto it = active_permissions_map_.find(origin);
if (it == active_permissions_map_.end()) {
return;
}
OriginState& origin_state = it->second;
// Return early if the path was not previously downgraded.
if (origin_state.downgraded_read_paths.find(path) ==
origin_state.downgraded_read_paths.end()) {
return;
}
origin_state.downgraded_read_paths.erase(path);
// Set the grant's status back to GRANTED if it was previously downgraded.
auto grant_it = origin_state.read_grants.find(path);
// Exclude the case where the path does not exist in the read_grants map.
if (grant_it != origin_state.read_grants.end())
grant_it->second->SetStatus(PermissionStatus::GRANTED);
}
void FileSystemAccessPermissionContext::NotifyEntryRemoved(
const url::Origin& origin,
const content::PathInfo& path) {}
const content::PathInfo& path) {
CHECK(base::FeatureList::IsEnabled(
blink::features::kFileSystemAccessRevokeReadOnRemove));
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (AncestorHasActivePermission(origin, path.path, GrantType::kRead)) {
// If `path` has an active read grant inherited from its ancestor, don't
// downgrade its permission, as it will still get ancestor grant by default.
return;
}
auto it = active_permissions_map_.find(origin);
if (it != active_permissions_map_.end()) {
PermissionGrantImpl::DowngradeReadGrantInMemory(it->second.read_grants,
path);
// Marks the path as downgraded so that it can be restored later.
it->second.downgraded_read_paths.insert(path.path);
}
}
void FileSystemAccessPermissionContext::OnFileCreatedFromShowSaveFilePicker(
const GURL& file_picker_binding_context,

View File

@@ -140,6 +140,11 @@ class FileSystemAccessPermissionContext
void PermissionGrantDestroyed(PermissionGrantImpl* grant);
// Restores the read permission for `path` if it was previously downgraded,
// e.g. by a `remove()` call.
void MaybeRestoreReadPermission(const url::Origin& origin,
const base::FilePath& path);
void CheckShouldBlockAccessToPathAndReply(
base::FilePath path,
HandleType handle_type,