[FSA] Update `queryPermission()` to include persistent permission state.

Previously, even if a handle has persistent permission,
`queryPermission()` could return `PermissionStatus::ASK`; only when
`requestPermission()` is called, the persistent permission status would
be retrieved for auto-granting. However, this could be a confusing
behavior to API users, as the persistence of permission is
implementation detail.

`FileSystemAccessPermissionGrant.GetStatus()` is now updated to read
from persisted grant objects and to return the combined state between
active and persisted grants. This method is used not only for
`queryPermission()` API, but also in various places internally such as
returning child handles from a parent directory handle.

Instead of introducing a new `GetPersistedStatus()`, the existing
`GetStatus()` is updated to account for persistent permission.
Additionally, a new private method `GetActivePermissionStatus()` is
introduced to replace the former usage of `GetStatus()` within
`ChromeFileSystemAccessPermissionContext`.

Bug: 1011533
Change-Id: Ica5ca4f74395c6ccf66235f022b8ce345440b9d2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4989830
Commit-Queue: Daseul Lee <dslee@chromium.org>
Reviewed-by: Christine Smith <christinesm@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1217870}
diff --git a/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc b/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
index 3849975..adbc96e4 100644
--- a/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
+++ b/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
@@ -546,8 +546,21 @@
   // FileSystemAccessPermissionGrant:
   PermissionStatus GetStatus() override {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    // TODO(crbug.com/1011533): Determine if this should return denied for
+    // guard block, and how ancestor permission should be handled.
+    if (status_ == PermissionStatus::ASK &&
+        context_->CanAutoGrantViaPersistentPermission(origin_, path_,
+                                                      handle_type_, type_)) {
+      return PermissionStatus::GRANTED;
+    }
     return status_;
   }
+
+  PermissionStatus GetActivePermissionStatus() {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    return status_;
+  }
+
   base::FilePath GetPath() override {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     return path_;
@@ -562,8 +575,8 @@
     // Check if a permission request has already been processed previously. This
     // check is done first because we don't want to reset the status of a
     // permission if it has already been granted.
-    if (GetStatus() != PermissionStatus::ASK || !context_) {
-      if (GetStatus() == PermissionStatus::GRANTED) {
+    if (GetActivePermissionStatus() != PermissionStatus::ASK || !context_) {
+      if (GetActivePermissionStatus() == PermissionStatus::GRANTED) {
         SetStatus(PermissionStatus::GRANTED,
                   PersistedPermissionOptions::kUpdatePersistedPermission);
       }
@@ -829,7 +842,8 @@
       return;
     }
 
-    DCHECK_EQ(entry_it->second->GetStatus(), PermissionStatus::GRANTED);
+    DCHECK_EQ(entry_it->second->GetActivePermissionStatus(),
+              PermissionStatus::GRANTED);
 
     auto* const grant_impl = entry_it->second;
     grant_impl->SetPath(new_path);
@@ -1205,7 +1219,8 @@
       break;
   }
 
-  if (existing_grant->GetStatus() == PermissionStatus::GRANTED) {
+  if (existing_grant->GetActivePermissionStatus() ==
+      PermissionStatus::GRANTED) {
     ScheduleUsageIconUpdate();
   }
 
@@ -1291,7 +1306,8 @@
       break;
   }
 
-  if (existing_grant->GetStatus() == PermissionStatus::GRANTED) {
+  if (existing_grant->GetActivePermissionStatus() ==
+      PermissionStatus::GRANTED) {
     ScheduleUsageIconUpdate();
   }
 
@@ -1334,7 +1350,8 @@
   auto it = active_permissions_map_.find(origin);
   if (it != active_permissions_map_.end()) {
     for (const auto& grant : it->second.read_grants) {
-      if (grant.second->GetStatus() == PermissionStatus::GRANTED) {
+      if (grant.second->GetActivePermissionStatus() ==
+          PermissionStatus::GRANTED) {
         auto value = grant.second->AsValue();
 
         // Persisted permissions include both read and write information in
@@ -1343,7 +1360,8 @@
         auto file_path = grant.first;
         auto write_grant_it = it->second.write_grants.find(file_path);
         if (write_grant_it != it->second.write_grants.end() &&
-            write_grant_it->second->GetStatus() == PermissionStatus::GRANTED) {
+            write_grant_it->second->GetActivePermissionStatus() ==
+                PermissionStatus::GRANTED) {
           value.Set(kPermissionWritableKey, true);
         }
 
@@ -1838,14 +1856,16 @@
     if (origin_it != active_permissions_map_.end()) {
       OriginState& origin_state = origin_it->second;
       for (auto& read_grant : origin_state.read_grants) {
-        if (read_grant.second->GetStatus() == PermissionStatus::GRANTED) {
+        if (read_grant.second->GetActivePermissionStatus() ==
+            PermissionStatus::GRANTED) {
           read_grant.second->SetStatus(
               PermissionStatus::GRANTED,
               PersistedPermissionOptions::kUpdatePersistedPermission);
         }
       }
       for (auto& write_grant : origin_state.write_grants) {
-        if (write_grant.second->GetStatus() == PermissionStatus::GRANTED) {
+        if (write_grant.second->GetActivePermissionStatus() ==
+            PermissionStatus::GRANTED) {
           write_grant.second->SetStatus(
               PermissionStatus::GRANTED,
               PersistedPermissionOptions::kUpdatePersistedPermission);
@@ -1914,7 +1934,8 @@
   auto it = active_permissions_map_.find(origin);
   if (it != active_permissions_map_.end()) {
     return base::ranges::any_of(it->second.read_grants, [&](const auto& grant) {
-      return grant.second->GetStatus() == PermissionStatus::GRANTED;
+      return grant.second->GetActivePermissionStatus() ==
+             PermissionStatus::GRANTED;
     });
   }
 
@@ -1943,7 +1964,8 @@
   if (it != active_permissions_map_.end()) {
     return base::ranges::any_of(
         it->second.write_grants, [&](const auto& grant) {
-          return grant.second->GetStatus() == PermissionStatus::GRANTED;
+          return grant.second->GetActivePermissionStatus() ==
+                 PermissionStatus::GRANTED;
         });
   }
 
@@ -2304,7 +2326,7 @@
        parent = parent.DirName()) {
     auto i = relevant_grants.find(parent);
     if (i != relevant_grants.end() && i->second &&
-        i->second->GetStatus() == PermissionStatus::GRANTED) {
+        i->second->GetActivePermissionStatus() == PermissionStatus::GRANTED) {
       return true;
     }
   }
@@ -2612,7 +2634,7 @@
   // be granted but won't be visible in any UI because the permission context
   // isn't tracking them anymore.
   if (grant_it == grants.end()) {
-    DCHECK_EQ(PermissionStatus::DENIED, grant->GetStatus());
+    DCHECK_EQ(PermissionStatus::DENIED, grant->GetActivePermissionStatus());
     return;
   }
 
diff --git a/chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc b/chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc
index 7e656b1..4f4c175a 100644
--- a/chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc
+++ b/chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc
@@ -1059,11 +1059,7 @@
   EXPECT_TRUE(permission_context()->HasExtendedPermissionForTesting(
       kTestOrigin, kTestPath, HandleType::kFile, GrantType::kWrite));
 
-  grant.reset();
-  // Permission should not be granted for `kOpen`.
-  grant = permission_context()->GetWritePermissionGrant(
-      kTestOrigin, kTestPath, HandleType::kFile, UserAction::kOpen);
-  EXPECT_EQ(grant->GetStatus(), PermissionStatus::ASK);
+  permission_context()->RevokeActiveGrantsForTesting(kTestOrigin, kTestPath);
 
   // Permission should be auto-granted here via the persisted permission.
   base::test::TestFuture<PermissionRequestOutcome> future;
@@ -1141,7 +1137,6 @@
   // Revoke the active grant, but not the persisted permission. The granted
   // object for the given origin is not revoked.
   permission_context()->RevokeActiveGrantsForTesting(kTestOrigin);
-  EXPECT_EQ(grant->GetStatus(), PermissionStatus::ASK);
   ASSERT_THAT(
       permission_context()->GetExtendedPersistedObjectsForTesting(kTestOrigin),
       testing::SizeIs(1));
@@ -2041,25 +2036,6 @@
 }
 
 TEST_F(ChromeFileSystemAccessPermissionContextTest,
-       PersistedPermission_RevokeOnlyActiveGrants) {
-  permission_context()->SetOriginHasExtendedPermissionForTesting(kTestOrigin);
-  auto grant = permission_context()->GetWritePermissionGrant(
-      kTestOrigin, kTestPath, HandleType::kFile, UserAction::kSave);
-  EXPECT_EQ(grant->GetStatus(), PermissionStatus::GRANTED);
-  // Revoke active grant, but not the persisted permission.
-  permission_context()->RevokeActiveGrantsForTesting(kTestOrigin);
-  EXPECT_EQ(grant->GetStatus(), PermissionStatus::ASK);
-  EXPECT_TRUE(permission_context()->HasExtendedPermissionForTesting(
-      kTestOrigin, kTestPath, HandleType::kFile, GrantType::kWrite));
-
-  ChromeFileSystemAccessPermissionContext::Grants grants =
-      permission_context()->ConvertObjectsToGrants(
-          permission_context()->GetGrantedObjects(kTestOrigin));
-  std::vector<base::FilePath> expected_res = {kTestPath};
-  EXPECT_EQ(grants.file_write_grants, expected_res);
-}
-
-TEST_F(ChromeFileSystemAccessPermissionContextTest,
        PersistedPermission_RevokeGrantByFilePath) {
   auto grant = permission_context()->GetWritePermissionGrant(
       kTestOrigin, kTestPath, HandleType::kFile, UserAction::kSave);
@@ -2080,15 +2056,7 @@
   auto grant = permission_context()->GetWritePermissionGrant(
       kTestOrigin, kTestPath, HandleType::kFile, UserAction::kSave);
   EXPECT_EQ(grant->GetStatus(), PermissionStatus::GRANTED);
-  grant.reset();
-  EXPECT_TRUE(permission_context()->HasExtendedPermissionForTesting(
-      kTestOrigin, kTestPath, HandleType::kFile, GrantType::kWrite));
-
-  // After reset, the grant should be cleared, and the new grant request should
-  // be in the `ASK` state.
-  grant = permission_context()->GetWritePermissionGrant(
-      kTestOrigin, kTestPath, HandleType::kFile, UserAction::kOpen);
-  EXPECT_EQ(grant->GetStatus(), PermissionStatus::ASK);
+  permission_context()->RevokeActiveGrantsForTesting(kTestOrigin, kTestPath);
 
   SetDefaultContentSettingValue(ContentSettingsType::FILE_SYSTEM_WRITE_GUARD,
                                 CONTENT_SETTING_BLOCK);