Repository: electron/electron
Pull request: fix: `getAsFileSystemHandle` failure when drag-dropping two directories

#### Description of Change

Closes https://github.com/electron/electron/issues/45051.
Closes https://github.com/electron/electron/issues/45225.
Refs https://chromium-review.googlesource.com/c/chromium/src/+/5807287

Fixes an issue where drag-dropping two directories would cause `getAsFileSystemHandle` to never resolve. This happened because the existing logic only expected one directory and so the callback would be overwritten in this use case, triggered by a feature flag change upstream. We store this callback in order to emit an event on session, which is why this happened in Electron and not upstream as well. Fix this by keeping a map of callbacks corresponding to their file paths.

#### Checklist
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->

- [x] PR description included and stakeholders cc'd
- [x] `npm test` passes
- [x] [PR release notes](https://github.com/electron/clerk/blob/main/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/main/README.md#examples).

#### Release Notes

Notes: Fixed an issue where drag-dropping two directories would cause `getAsFileSystemHandle` to never resolve.


Changed files:
filename: shell/browser/file_system_access/file_system_access_permission_context.cc
patch: @@ -588,7 +588,7 @@ void FileSystemAccessPermissionContext::ConfirmSensitiveEntryAccess(
     content::GlobalRenderFrameHostId frame_id,
     base::OnceCallback<void(SensitiveEntryResult)> callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  callback_ = std::move(callback);
+  callback_map_[path_info.path] = std::move(callback);
 
   auto after_blocklist_check_callback = base::BindOnce(
       &FileSystemAccessPermissionContext::DidCheckPathAgainstBlocklist,
@@ -632,16 +632,18 @@ void FileSystemAccessPermissionContext::PerformAfterWriteChecks(
 }
 
 void FileSystemAccessPermissionContext::RunRestrictedPathCallback(
+    const base::FilePath& file_path,
     SensitiveEntryResult result) {
-  if (callback_)
-    std::move(callback_).Run(result);
+  if (base::Contains(callback_map_, file_path))
+    std::move(callback_map_[file_path]).Run(result);
 }
 
 void FileSystemAccessPermissionContext::OnRestrictedPathResult(
+    const base::FilePath& file_path,
     gin::Arguments* args) {
   SensitiveEntryResult result = SensitiveEntryResult::kAbort;
   args->GetNext(&result);
-  RunRestrictedPathCallback(result);
+  RunRestrictedPathCallback(file_path, result);
 }
 
 void FileSystemAccessPermissionContext::DidCheckPathAgainstBlocklist(
@@ -654,8 +656,9 @@ void FileSystemAccessPermissionContext::DidCheckPathAgainstBlocklist(
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (user_action == UserAction::kNone) {
-    RunRestrictedPathCallback(should_block ? SensitiveEntryResult::kAbort
-                                           : SensitiveEntryResult::kAllowed);
+    auto result = should_block ? SensitiveEntryResult::kAbort
+                               : SensitiveEntryResult::kAllowed;
+    RunRestrictedPathCallback(path_info.path, result);
     return;
   }
 
@@ -674,11 +677,11 @@ void FileSystemAccessPermissionContext::DidCheckPathAgainstBlocklist(
         "file-system-access-restricted", details,
         base::BindRepeating(
             &FileSystemAccessPermissionContext::OnRestrictedPathResult,
-            weak_factory_.GetWeakPtr()));
+            weak_factory_.GetWeakPtr(), path_info.path));
     return;
   }
 
-  RunRestrictedPathCallback(SensitiveEntryResult::kAllowed);
+  RunRestrictedPathCallback(path_info.path, SensitiveEntryResult::kAllowed);
 }
 
 void FileSystemAccessPermissionContext::MaybeEvictEntries(

filename: shell/browser/file_system_access/file_system_access_permission_context.h
patch: @@ -144,9 +144,11 @@ class FileSystemAccessPermissionContext
                                     content::GlobalRenderFrameHostId frame_id,
                                     bool should_block);
 
-  void RunRestrictedPathCallback(SensitiveEntryResult result);
+  void RunRestrictedPathCallback(const base::FilePath& file_path,
+                                 SensitiveEntryResult result);
 
-  void OnRestrictedPathResult(gin::Arguments* args);
+  void OnRestrictedPathResult(const base::FilePath& file_path,
+                              gin::Arguments* args);
 
   void MaybeEvictEntries(base::Value::Dict& dict);
 
@@ -170,7 +172,8 @@ class FileSystemAccessPermissionContext
 
   std::map<url::Origin, base::Value::Dict> id_pathinfo_map_;
 
-  base::OnceCallback<void(SensitiveEntryResult)> callback_;
+  std::map<base::FilePath, base::OnceCallback<void(SensitiveEntryResult)>>
+      callback_map_;
 
   base::WeakPtrFactory<FileSystemAccessPermissionContext> weak_factory_{this};
 };