Skip to content

Commit cf9d044

Browse files
feat: add fileSystem to ses.setPermissionCheckHandler (#48327)
feat: add fileSystem to ses.setPermissionCheckHandler Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Shelley Vohr <[email protected]>
1 parent 99feff3 commit cf9d044

File tree

7 files changed

+325
-22
lines changed

7 files changed

+325
-22
lines changed

docs/api/session.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -939,14 +939,18 @@ session.fromPartition('some-partition').setPermissionRequestHandler((webContents
939939
* `top-level-storage-access` - Allow top-level sites to request third-party cookie access on behalf of embedded content originating from another site in the same related website set using the [Storage Access API](https://developer.mozilla.org/en-US/docs/Web/API/Storage_Access_API).
940940
* `usb` - Expose non-standard Universal Serial Bus (USB) compatible devices services to the web with the [WebUSB API](https://developer.mozilla.org/en-US/docs/Web/API/WebUSB_API).
941941
* `deprecated-sync-clipboard-read` _Deprecated_ - Request access to run `document.execCommand("paste")`
942+
* `fileSystem` - Access to read, write, and file management capabilities using the [File System API](https://developer.mozilla.org/en-US/docs/Web/API/File_System_API).
942943
* `requestingOrigin` string - The origin URL of the permission check
943944
* `details` Object - Some properties are only available on certain permission types.
944945
* `embeddingOrigin` string (optional) - The origin of the frame embedding the frame that made the permission check. Only set for cross-origin sub frames making permission checks.
945946
* `securityOrigin` string (optional) - The security origin of the `media` check.
946947
* `mediaType` string (optional) - The type of media access being requested, can be `video`,
947-
`audio` or `unknown`
948+
`audio` or `unknown`.
948949
* `requestingUrl` string (optional) - The last URL the requesting frame loaded. This is not provided for cross-origin sub frames making permission checks.
949-
* `isMainFrame` boolean - Whether the frame making the request is the main frame
950+
* `isMainFrame` boolean - Whether the frame making the request is the main frame.
951+
* `filePath` string (optional) - The path of a `fileSystem` request.
952+
* `isDirectory` boolean (optional) - Whether a `fileSystem` request is a directory.
953+
* `fileAccessType` string (optional) - The access type of a `fileSystem` request. Can be `writable` or `readable`.
950954
951955
Sets the handler which can be used to respond to permission checks for the `session`.
952956
Returning `true` will allow the permission and `false` will reject it. Please note that
@@ -968,6 +972,9 @@ session.fromPartition('some-partition').setPermissionCheckHandler((webContents,
968972
})
969973
```
970974
975+
> [!NOTE]
976+
> `isMainFrame` will always be `false` for a `fileSystem` request as a result of Chromium limitations.
977+
971978
#### `ses.setDisplayMediaRequestHandler(handler[, opts])`
972979
973980
* `handler` Function | null

shell/browser/electron_permission_manager.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,14 @@ void ElectronPermissionManager::SetBluetoothPairingHandler(
142142
bluetooth_pairing_handler_ = handler;
143143
}
144144

145+
bool ElectronPermissionManager::HasPermissionRequestHandler() const {
146+
return !request_handler_.is_null();
147+
}
148+
149+
bool ElectronPermissionManager::HasPermissionCheckHandler() const {
150+
return !check_handler_.is_null();
151+
}
152+
145153
void ElectronPermissionManager::RequestPermissionWithDetails(
146154
blink::mojom::PermissionDescriptorPtr permission,
147155
content::RenderFrameHost* render_frame_host,

shell/browser/electron_permission_manager.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ class ElectronPermissionManager : public content::PermissionControllerDelegate {
8282
void SetProtectedUSBHandler(const ProtectedUSBHandler& handler);
8383
void SetBluetoothPairingHandler(const BluetoothPairingHandler& handler);
8484

85+
bool HasPermissionRequestHandler() const;
86+
bool HasPermissionCheckHandler() const;
87+
8588
void CheckBluetoothDevicePair(gin_helper::Dictionary details,
8689
PairCallback pair_callback) const;
8790

shell/browser/file_system_access/file_system_access_permission_context.cc

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,28 @@ class FileSystemAccessPermissionContext::PermissionGrantImpl
257257
// FileSystemAccessPermissionGrant:
258258
PermissionStatus GetStatus() override {
259259
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
260+
261+
auto* permission_manager =
262+
static_cast<electron::ElectronPermissionManager*>(
263+
context_->browser_context()->GetPermissionControllerDelegate());
264+
if (permission_manager && permission_manager->HasPermissionCheckHandler()) {
265+
base::Value::Dict details;
266+
details.Set("filePath", base::FilePathToValue(path_info_.path));
267+
details.Set("isDirectory", handle_type_ == HandleType::kDirectory);
268+
details.Set("fileAccessType",
269+
type_ == GrantType::kWrite ? "writable" : "readable");
270+
271+
bool granted = permission_manager->CheckPermissionWithDetails(
272+
blink::PermissionType::FILE_SYSTEM, nullptr, origin_.GetURL(),
273+
std::move(details));
274+
return granted ? PermissionStatus::GRANTED : PermissionStatus::DENIED;
275+
}
276+
277+
return status_;
278+
}
279+
280+
PermissionStatus GetActivePermissionStatus() {
281+
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
260282
return status_;
261283
}
262284

@@ -279,8 +301,8 @@ class FileSystemAccessPermissionContext::PermissionGrantImpl
279301
// Check if a permission request has already been processed previously. This
280302
// check is done first because we don't want to reset the status of a
281303
// permission if it has already been granted.
282-
if (GetStatus() != PermissionStatus::ASK || !context_) {
283-
if (GetStatus() == PermissionStatus::GRANTED) {
304+
if (GetActivePermissionStatus() != PermissionStatus::ASK || !context_) {
305+
if (GetActivePermissionStatus() == PermissionStatus::GRANTED) {
284306
SetStatus(PermissionStatus::GRANTED);
285307
}
286308
std::move(callback).Run(PermissionRequestOutcome::kRequestAborted);
@@ -294,7 +316,7 @@ class FileSystemAccessPermissionContext::PermissionGrantImpl
294316
return;
295317
}
296318

297-
// Don't request permission for an inactive RenderFrameHost as the
319+
// Don't request permission for an inactive RenderFrameHost as the
298320
// page might not distinguish properly between user denying the permission
299321
// and automatic rejection.
300322
if (rfh->IsInactiveAndDisallowActivation(
@@ -347,7 +369,7 @@ class FileSystemAccessPermissionContext::PermissionGrantImpl
347369
permission_manager->RequestPermissionWithDetails(
348370
content::PermissionDescriptorUtil::
349371
CreatePermissionDescriptorForPermissionType(type),
350-
rfh, origin, false, std::move(details),
372+
rfh, origin, rfh->HasTransientUserActivation(), std::move(details),
351373
base::BindOnce(&PermissionGrantImpl::OnPermissionRequestResult, this,
352374
std::move(callback)));
353375
}
@@ -394,7 +416,8 @@ class FileSystemAccessPermissionContext::PermissionGrantImpl
394416
return;
395417
}
396418

397-
DCHECK_EQ(entry_it->second->GetStatus(), PermissionStatus::GRANTED);
419+
DCHECK_EQ(entry_it->second->GetActivePermissionStatus(),
420+
PermissionStatus::GRANTED);
398421

399422
auto* const grant_impl = entry_it->second;
400423
grant_impl->SetPath(new_path);
@@ -963,7 +986,8 @@ bool FileSystemAccessPermissionContext::OriginHasReadAccess(
963986
auto it = active_permissions_map_.find(origin);
964987
if (it != active_permissions_map_.end()) {
965988
return std::ranges::any_of(it->second.read_grants, [&](const auto& grant) {
966-
return grant.second->GetStatus() == PermissionStatus::GRANTED;
989+
return grant.second->GetActivePermissionStatus() ==
990+
PermissionStatus::GRANTED;
967991
});
968992
}
969993

@@ -977,7 +1001,8 @@ bool FileSystemAccessPermissionContext::OriginHasWriteAccess(
9771001
auto it = active_permissions_map_.find(origin);
9781002
if (it != active_permissions_map_.end()) {
9791003
return std::ranges::any_of(it->second.write_grants, [&](const auto& grant) {
980-
return grant.second->GetStatus() == PermissionStatus::GRANTED;
1004+
return grant.second->GetActivePermissionStatus() ==
1005+
PermissionStatus::GRANTED;
9811006
});
9821007
}
9831008

@@ -1031,7 +1056,7 @@ bool FileSystemAccessPermissionContext::AncestorHasActivePermission(
10311056
parent = parent.DirName()) {
10321057
auto i = relevant_grants.find(parent);
10331058
if (i != relevant_grants.end() && i->second &&
1034-
i->second->GetStatus() == PermissionStatus::GRANTED) {
1059+
i->second->GetActivePermissionStatus() == PermissionStatus::GRANTED) {
10351060
return true;
10361061
}
10371062
}
@@ -1054,7 +1079,7 @@ void FileSystemAccessPermissionContext::PermissionGrantDestroyed(
10541079
// be granted but won't be visible in any UI because the permission context
10551080
// isn't tracking them anymore.
10561081
if (grant_it == grants.end()) {
1057-
DCHECK_EQ(PermissionStatus::DENIED, grant->GetStatus());
1082+
DCHECK_EQ(PermissionStatus::DENIED, grant->GetActivePermissionStatus());
10581083
return;
10591084
}
10601085

0 commit comments

Comments
 (0)