[FSA] Add basic dropdown lists to site settings page

Implements a basic Polymer dropdown list as outlined in the UX mockups,
to be displayed on the chrome://settings/content/filesystem page.

Additional functionality and remaining, required UI features will be
included in follow-up changes.

This change is hidden behind a feature flag that will not be enabled
until Persistent Permissions launches.
The UI implementation in this CL is NOT in its final state.

WIP Screenshot: https://screenshot.googleplex.com/4e53mPwVQyywFN2

Bug: 1354695
Change-Id: Ib04e3b681b32853c39014b1c749019ceec2ad3f3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4300321
Commit-Queue: Christine Smith <christinesm@chromium.org>
Reviewed-by: Demetrios Papadopoulos <dpapad@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1127799}
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn
index 38f2816..9122fb8 100644
--- a/chrome/browser/resources/settings/BUILD.gn
+++ b/chrome/browser/resources/settings/BUILD.gn
@@ -202,6 +202,8 @@
     "site_settings/chooser_exception_list.ts",
     "site_settings/site_details_permission_device_entry.ts",
     "site_settings/edit_exception_dialog.ts",
+    "site_settings/file_system_site_entry.ts",
+    "site_settings/file_system_site_entry_item.ts",
     "site_settings/file_system_site_list.ts",
     "site_settings/media_picker.ts",
     "site_settings/review_notification_permissions.ts",
diff --git a/chrome/browser/resources/settings/lazy_load.ts b/chrome/browser/resources/settings/lazy_load.ts
index 5f5f8f8..7795af4 100644
--- a/chrome/browser/resources/settings/lazy_load.ts
+++ b/chrome/browser/resources/settings/lazy_load.ts
@@ -34,6 +34,8 @@
 import './privacy_page/security_keys_phones_dialog.js';
 import './privacy_page/security_page.js';
 import './site_settings/all_sites.js';
+import './site_settings/file_system_site_entry.js';
+import './site_settings/file_system_site_entry_item.js';
 import './site_settings/file_system_site_list.js';
 import './site_settings_page/site_settings_page.js';
 import './site_settings/category_default_setting.js';
@@ -213,7 +215,9 @@
 export {ChooserExceptionListEntryElement} from './site_settings/chooser_exception_list_entry.js';
 export {ChooserType, ContentSetting, ContentSettingsTypes, CookieControlsMode, CookiesExceptionType, NotificationSetting, SITE_EXCEPTION_WILDCARD, SiteSettingSource, SortMethod} from './site_settings/constants.js';
 export {SettingsEditExceptionDialogElement} from './site_settings/edit_exception_dialog.js';
-export {FileSystemSiteListElement, OriginFileSystemGrants} from './site_settings/file_system_site_list.js';
+export {FileSystemSiteEntryElement} from './site_settings/file_system_site_entry.js';
+export {FileSystemSiteEntryItemElement} from './site_settings/file_system_site_entry_item.js';
+export {FileSystemGrant, FileSystemSiteListElement, OriginFileSystemGrants} from './site_settings/file_system_site_list.js';
 export {AppHandlerEntry, AppProtocolEntry, HandlerEntry, ProtocolEntry, ProtocolHandlersElement} from './site_settings/protocol_handlers.js';
 export {SettingsReviewNotificationPermissionsElement} from './site_settings/review_notification_permissions.js';
 export {SettingsCategoryDefaultRadioGroupElement} from './site_settings/settings_category_default_radio_group.js';
diff --git a/chrome/browser/resources/settings/site_settings/file_system_site_entry.html b/chrome/browser/resources/settings/site_settings/file_system_site_entry.html
new file mode 100644
index 0000000..76de032
--- /dev/null
+++ b/chrome/browser/resources/settings/site_settings/file_system_site_entry.html
@@ -0,0 +1,42 @@
+<style include="cr-shared-style settings-shared">
+  .dropdown-row {
+    align-items: center;
+    display: flex;
+  }
+</style>
+
+<div class="list-frame">
+  <div class="dropdown-row">
+    <site-favicon url="[[grantsPerOrigin.origin]]"></site-favicon>
+    <cr-expand-button id="dropdownButton" class="cr-row"
+        expanded="{{expanded_}}">
+      [[grantsPerOrigin.origin]]
+    </cr-expand-button>
+  </div>
+  <iron-collapse id="collapseChild" expand-icon="cr:arrow-drop-down"
+      collapse-icon="cr:arrow-drop-up" opened="[[expanded_]]" no-animation
+      no-hover>
+    <!-- Edit Grants -->
+    <div>
+      <div hidden$="[[!grantsPerOrigin.editGrants.length]]">
+        $i18n{siteSettingsFileSystemSiteListEditHeader}
+      </div>
+      <template is="dom-repeat" items="[[grantsPerOrigin.editGrants]]"
+          as="editGrant">
+        <file-system-site-entry-item grant="[[editGrant]]">
+        </file-system-site-entry-item>
+      </template>
+    </div>
+    <!-- View Grants -->
+    <div>
+      <div hidden$="[[!grantsPerOrigin.viewGrants.length]]">
+        $i18n{siteSettingsFileSystemSiteListViewHeader}
+      </div>
+      <template is="dom-repeat" items="[[grantsPerOrigin.viewGrants]]"
+          as="viewGrant">
+        <file-system-site-entry-item grant="[[viewGrant]]">
+        </file-system-site-entry-item>
+      </template>
+    </div>
+  </iron-collapse>
+</div>
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/site_settings/file_system_site_entry.ts b/chrome/browser/resources/settings/site_settings/file_system_site_entry.ts
new file mode 100644
index 0000000..49fb7b7
--- /dev/null
+++ b/chrome/browser/resources/settings/site_settings/file_system_site_entry.ts
@@ -0,0 +1,57 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview
+ * 'file-system-site-entry' is an element representing a single origin's
+ * permission grant(s), granted via the File System Access API.
+ */
+import 'chrome://resources/cr_elements/cr_expand_button/cr_expand_button.js';
+import 'chrome://resources/cr_elements/cr_shared_style.css.js';
+import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
+import './file_system_site_entry_item.js';
+import '../settings_shared.css.js';
+import '../site_favicon.js';
+
+import {CrExpandButtonElement} from 'chrome://resources/cr_elements/cr_expand_button/cr_expand_button.js';
+import {IronCollapseElement} from 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
+import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {getTemplate} from './file_system_site_entry.html.js';
+import {OriginFileSystemGrants} from './file_system_site_list.js';
+
+export interface FileSystemSiteEntryElement {
+  $: {
+    collapseChild: IronCollapseElement,
+    dropdownButton: CrExpandButtonElement,
+  };
+}
+
+export class FileSystemSiteEntryElement extends PolymerElement {
+  static get is() {
+    return 'file-system-site-entry';
+  }
+
+  static get template() {
+    return getTemplate();
+  }
+
+  static get properties() {
+    return {
+      /**
+       * An Object representing an origin and its associated permission grants.
+       */
+      grantsPerOrigin: Object,
+    };
+  }
+  grantsPerOrigin: OriginFileSystemGrants;
+}
+declare global {
+  interface HTMLElementTagNameMap {
+    'file-system-site-entry': FileSystemSiteEntryElement;
+  }
+}
+
+customElements.define(
+    FileSystemSiteEntryElement.is, FileSystemSiteEntryElement);
diff --git a/chrome/browser/resources/settings/site_settings/file_system_site_entry_item.html b/chrome/browser/resources/settings/site_settings/file_system_site_entry_item.html
new file mode 100644
index 0000000..ae02fe20
--- /dev/null
+++ b/chrome/browser/resources/settings/site_settings/file_system_site_entry_item.html
@@ -0,0 +1,10 @@
+<style include="cr-shared-style settings-shared"></style>
+<div class="start row-aligned list-item">
+  <cr-icon-button class$="cr-icon [[getClassForListItem_(grant)]]">
+  </cr-icon-button>
+  <div class="site-representation middle text-elide">
+    <span class="display-name url-directionality text-elide">
+        [[grant.displayName]]
+    </span>
+  </div>
+</div>
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/site_settings/file_system_site_entry_item.ts b/chrome/browser/resources/settings/site_settings/file_system_site_entry_item.ts
new file mode 100644
index 0000000..1b4de93
--- /dev/null
+++ b/chrome/browser/resources/settings/site_settings/file_system_site_entry_item.ts
@@ -0,0 +1,51 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview
+ * 'file-system-site-entry-item' is an element representing a single
+ * permission grant for a given origin, granted via the File System Access API.
+ */
+import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js';
+import 'chrome://resources/cr_elements/cr_shared_style.css.js';
+import '../settings_shared.css.js';
+
+import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {getTemplate} from './file_system_site_entry_item.html.js';
+import {FileSystemGrant} from './file_system_site_list.js';
+
+export class FileSystemSiteEntryItemElement extends PolymerElement {
+  static get is() {
+    return 'file-system-site-entry-item';
+  }
+
+  static get template() {
+    return getTemplate();
+  }
+
+  static get properties() {
+    return {
+      /**
+       * An Object representing an origin and its associated permission grants.
+       */
+      grant: Object,
+    };
+  }
+
+  grant: FileSystemGrant;
+
+  private getClassForListItem_(): string {
+    return this.grant.isDirectory ? 'icon-folder-open' : 'icon-file';
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'file-system-site-entry-item': FileSystemSiteEntryItemElement;
+  }
+}
+
+customElements.define(
+    FileSystemSiteEntryItemElement.is, FileSystemSiteEntryItemElement);
diff --git a/chrome/browser/resources/settings/site_settings/file_system_site_list.html b/chrome/browser/resources/settings/site_settings/file_system_site_list.html
index da46546..52caa51 100644
--- a/chrome/browser/resources/settings/site_settings/file_system_site_list.html
+++ b/chrome/browser/resources/settings/site_settings/file_system_site_list.html
@@ -1,18 +1,4 @@
-<template is="dom-repeat" items="[[allowedGrants_]]"
-    as="allowedGrantsPerOrigin">
-  <h2>[[allowedGrantsPerOrigin.origin]]</h2>
-  <div>
-    <h3>$i18n{siteSettingsFileSystemSiteListEditHeader}</h3>
-    <template is="dom-repeat" items="[[allowedGrantsPerOrigin.editGrants]]"
-        as="editGrant">
-      <div class="display-name">[[editGrant.displayName]]</div>
-    </template>
-  </div>
-  <div>
-    <h3>$i18n{siteSettingsFileSystemSiteListViewHeader}</h3>
-    <template is="dom-repeat" items="[[allowedGrantsPerOrigin.viewGrants]]"
-        as="viewGrant">
-      <div class="display-name">[[viewGrant.displayName]]</div>
-    </template>
-  </div>
+<template is="dom-repeat" items="[[allowedGrants_]]" as="grantsPerOrigin">
+  <file-system-site-entry grants-per-origin="[[grantsPerOrigin]]">
+  </file-system-site-entry>
 </template>
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/site_settings/file_system_site_list.ts b/chrome/browser/resources/settings/site_settings/file_system_site_list.ts
index d6a91df..f2c68ed2 100644
--- a/chrome/browser/resources/settings/site_settings/file_system_site_list.ts
+++ b/chrome/browser/resources/settings/site_settings/file_system_site_list.ts
@@ -7,6 +7,7 @@
  * 'file-system-site-list' is an element representing a list of origin-specific
  * permission entries for the File System Access API.
  */
+import './file_system_site_entry.js';
 
 import {EventTracker} from 'chrome://resources/js/event_tracker.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
@@ -18,7 +19,7 @@
 import {SiteSettingsMixin} from './site_settings_mixin.js';
 import {RawFileSystemGrant} from './site_settings_prefs_browser_proxy.js';
 
-interface FileSystemGrant {
+export interface FileSystemGrant {
   isDirectory: boolean;
   displayName: string;  // Might be a shortened file path
   origin: string;
diff --git a/chrome/test/data/webui/settings/BUILD.gn b/chrome/test/data/webui/settings/BUILD.gn
index dbda164..bc0a325 100644
--- a/chrome/test/data/webui/settings/BUILD.gn
+++ b/chrome/test/data/webui/settings/BUILD.gn
@@ -41,6 +41,8 @@
     "downloads_page_test.ts",
     "dropdown_menu_tests.ts",
     "extension_controlled_indicator_tests.ts",
+    "file_system_site_entry_tests.ts",
+    "file_system_site_entry_item_tests.ts",
     "file_system_site_list_tests.ts",
     "help_page_test.ts",
     "idle_load_tests.ts",
diff --git a/chrome/test/data/webui/settings/OWNERS b/chrome/test/data/webui/settings/OWNERS
index 4b6a8d5..ad7c7bbf 100644
--- a/chrome/test/data/webui/settings/OWNERS
+++ b/chrome/test/data/webui/settings/OWNERS
@@ -5,6 +5,7 @@
 per-file clear_browsing_data_test.ts=sauski@google.com
 per-file do_not_track_toggle_test.ts=sauski@google.com
 per-file do_not_track_toggle_test.ts=sauski@google.com
+per-file file_system_*=sauski@google.com
 per-file metrics_reporting_tests.ts=sauski@google.com
 per-file personalization_options_test.ts=sauski@google.com
 per-file privacy_page_test.ts=sauski@google.com,rainhard@chromium.org,sideyilmaz@chromium.org
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js
index 62dba05d..72dbb25 100644
--- a/chrome/test/data/webui/settings/cr_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -925,7 +925,9 @@
  ['DownloadsPage', 'downloads_page_test.js'],
  ['DropdownMenu', 'dropdown_menu_tests.js'],
  ['ExtensionControlledIndicator', 'extension_controlled_indicator_tests.js'],
- ['FileSystemSettings', 'file_system_site_list_tests.js'],
+ ['FileSystemSettingsList', 'file_system_site_list_tests.js'],
+ ['FileSystemSettingsListEntries', 'file_system_site_entry_tests.js'],
+ ['FileSystemSettingsListEntryItems', 'file_system_site_entry_item_tests.js'],
  ['HelpPage', 'help_page_test.js'],
  ['PasswordView', 'password_view_test.js'],
  ['PasswordsExportDialog', 'passwords_export_dialog_test.js'],
diff --git a/chrome/test/data/webui/settings/file_system_site_entry_item_tests.ts b/chrome/test/data/webui/settings/file_system_site_entry_item_tests.ts
new file mode 100644
index 0000000..bcc2070
--- /dev/null
+++ b/chrome/test/data/webui/settings/file_system_site_entry_item_tests.ts
@@ -0,0 +1,73 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// clang-format off
+import 'chrome://settings/lazy_load.js';
+
+import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {FileSystemGrant, FileSystemSiteEntryItemElement} from 'chrome://settings/lazy_load.js';
+import {CrSettingsPrefs} from 'chrome://settings/settings.js';
+import {assertTrue} from 'chrome://webui-test/chai_assert.js';
+
+// clang-format on
+
+suite(
+    'FileSystemSettings_EnablePersistentPermissions_SiteEntryItem_DirGrant',
+    function() {
+      let testElement: FileSystemSiteEntryItemElement;
+      const origin: string = 'https://a.com/';
+      const directoryFilePath: string = 'a/';
+      const TEST_FILE_SYSTEM_DIRECTORY_GRANT: FileSystemGrant = {
+        origin: origin,
+        filePath: directoryFilePath,
+        displayName: directoryFilePath,
+        isDirectory: true,
+      };
+      const filePath: string = 'a/b';
+      const TEST_FILE_SYSTEM_FILE_GRANT: FileSystemGrant = {
+        origin: origin,
+        filePath: filePath,
+        displayName: filePath,
+        isDirectory: false,
+      };
+
+      suiteSetup(function() {
+        CrSettingsPrefs.setInitialized();
+
+        loadTimeData.overrideValues({
+          showPersistentPermissions: true,
+        });
+      });
+
+      // Initialize the file-system-site-entry-item element for a directory
+      // grant.
+      setup(function() {
+        document.body.innerHTML = window.trustedTypes!.emptyHTML;
+        testElement = document.createElement('file-system-site-entry-item');
+        document.body.appendChild(testElement);
+      });
+
+      test('FileSystemSiteListEntryItemsPopulated', function() {
+        testElement.grant = TEST_FILE_SYSTEM_DIRECTORY_GRANT;
+        flush();
+        const directoryGrantDisplayName =
+            testElement.shadowRoot!.querySelector('.display-name');
+        assertTrue(!!directoryGrantDisplayName);
+        const icon = testElement.shadowRoot!.querySelector('cr-icon-button');
+        assertTrue(!!icon);
+        assertTrue(icon.classList.contains('icon-folder-open'));
+      });
+
+      test('FileSystemSiteListEntryItemsPopulated', function() {
+        testElement.grant = TEST_FILE_SYSTEM_FILE_GRANT;
+        flush();
+        const fileGrantDisplayName =
+            testElement.shadowRoot!.querySelector('.display-name');
+        assertTrue(!!fileGrantDisplayName);
+        const icon = testElement.shadowRoot!.querySelector('cr-icon-button');
+        assertTrue(!!icon);
+        assertTrue(icon.classList.contains('icon-file'));
+      });
+    });
diff --git a/chrome/test/data/webui/settings/file_system_site_entry_tests.ts b/chrome/test/data/webui/settings/file_system_site_entry_tests.ts
new file mode 100644
index 0000000..12fc9ac
--- /dev/null
+++ b/chrome/test/data/webui/settings/file_system_site_entry_tests.ts
@@ -0,0 +1,102 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// clang-format off
+import 'chrome://settings/lazy_load.js';
+
+import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {FileSystemGrant, FileSystemSiteEntryElement, OriginFileSystemGrants} from 'chrome://settings/lazy_load.js';
+import {CrSettingsPrefs} from 'chrome://settings/settings.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
+
+// clang-format on
+suite('FileSystemSettings_EnablePersistentPermissions', function() {
+  let testElement: FileSystemSiteEntryElement;
+
+  suiteSetup(function() {
+    CrSettingsPrefs.setInitialized();
+
+    loadTimeData.overrideValues({
+      showPersistentPermissions: true,
+    });
+  });
+
+  // Initialize the file-system-site-list element.
+  setup(function() {
+    document.body.innerHTML = window.trustedTypes!.emptyHTML;
+    testElement = new FileSystemSiteEntryElement();
+    document.body.appendChild(testElement);
+  });
+
+  test('FileSystemSiteListEntriesPopulated', function() {
+    const origin: string = 'https://a.com/';
+    const filePath1: string = 'a/b';
+    const filePath2: string = 'a/b/c';
+    const filePath3: string = 'e/f';
+    const directoryFilePath1: string = 'g/h/';
+    const directoryFilePath2: string = 'i/';
+
+    const TEST_FILE_SYSTEM_FILE_WRITE_GRANT1: FileSystemGrant = {
+      origin: origin,
+      filePath: filePath1,
+      displayName: filePath1,
+      isDirectory: false,
+    };
+    const TEST_FILE_SYSTEM_FILE_WRITE_GRANT2: FileSystemGrant = {
+      origin: origin,
+      filePath: filePath2,
+      displayName: filePath2,
+      isDirectory: false,
+    };
+    const TEST_FILE_SYSTEM_FILE_READ_GRANT: FileSystemGrant = {
+      origin: origin,
+      filePath: filePath3,
+      displayName: filePath3,
+      isDirectory: false,
+    };
+    const TEST_FILE_SYSTEM_DIRECTORY_READ_GRANT: FileSystemGrant = {
+      origin: origin,
+      filePath: directoryFilePath1,
+      displayName: directoryFilePath1,
+      isDirectory: true,
+    };
+    const TEST_FILE_SYSTEM_DIRECTORY_WRITE_GRANT: FileSystemGrant = {
+      origin: origin,
+      filePath: directoryFilePath2,
+      displayName: directoryFilePath2,
+      isDirectory: true,
+    };
+    const TEST_FILE_SYSTEM_GRANTS_PER_ORIGIN: OriginFileSystemGrants = {
+      origin: origin,
+      viewGrants: [
+        TEST_FILE_SYSTEM_DIRECTORY_READ_GRANT,
+        TEST_FILE_SYSTEM_FILE_READ_GRANT,
+      ],
+      editGrants: [
+        TEST_FILE_SYSTEM_DIRECTORY_WRITE_GRANT,
+        TEST_FILE_SYSTEM_FILE_WRITE_GRANT1,
+        TEST_FILE_SYSTEM_FILE_WRITE_GRANT2,
+      ],
+    };
+    testElement.grantsPerOrigin = TEST_FILE_SYSTEM_GRANTS_PER_ORIGIN;
+    flush();
+
+    // The dropdown button opens the dropdown list.
+    testElement.$.dropdownButton.click();
+    const collapseChild = testElement.$.collapseChild;
+
+    assertTrue(collapseChild!.opened);
+    flush();
+
+    // Ensure that the `collapseChild` element is populated as expected.
+    assertEquals(
+        5,
+        collapseChild!.querySelectorAll('file-system-site-entry-item').length);
+
+    // The dropdown button closes the dropdown list if tapped when opened.
+    testElement.$.dropdownButton.click();
+    assertFalse(collapseChild!.opened);
+  });
+});
diff --git a/chrome/test/data/webui/settings/file_system_site_list_tests.ts b/chrome/test/data/webui/settings/file_system_site_list_tests.ts
index 6c09ff6..af8322188 100644
--- a/chrome/test/data/webui/settings/file_system_site_list_tests.ts
+++ b/chrome/test/data/webui/settings/file_system_site_list_tests.ts
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 // clang-format off
-import 'chrome://settings/settings.js';
+import 'chrome://settings/lazy_load.js';
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
@@ -26,10 +26,6 @@
     });
   });
 
-  suiteTeardown(function() {
-    CrSettingsPrefs.resetForTesting();
-  });
-
   // Initialize the file-system-site-list element.
   setup(function() {
     document.body.innerHTML = window.trustedTypes!.emptyHTML;
@@ -39,40 +35,23 @@
     document.body.appendChild(testElement);
   });
 
-  teardown(function() {
-    testElement.remove();
-    Router.getInstance().resetRouteForTesting();
-  });
-
   function navigateToFileSystemSettingsPage() {
     Router.getInstance().navigateTo(routes.SITE_SETTINGS_FILE_SYSTEM_WRITE);
   }
 
   test('FileSystemSiteListPopulated', async function() {
     const origin: string = 'https://a.com/';
+    const origin2: string = 'https://b.com/';
     const filePath1: string = 'a/b';
     const filePath2: string = 'a/b/c';
-    const filePath3: string = 'e/f';
     const directoryFilePath1: string = 'g/h/';
     const directoryFilePath2: string = 'i/';
 
-    const TEST_FILE_SYSTEM_FILE_WRITE_GRANT1: RawFileSystemGrant = {
+    const TEST_FILE_SYSTEM_DIRECTORY_WRITE_GRANT: RawFileSystemGrant = {
       origin: origin,
-      filePath: filePath1,
+      filePath: directoryFilePath2,
       isWritable: true,
-      isDirectory: false,
-    };
-    const TEST_FILE_SYSTEM_FILE_WRITE_GRANT2: RawFileSystemGrant = {
-      origin: origin,
-      filePath: filePath2,
-      isWritable: true,
-      isDirectory: false,
-    };
-    const TEST_FILE_SYSTEM_FILE_READ_GRANT: RawFileSystemGrant = {
-      origin: origin,
-      filePath: filePath3,
-      isWritable: false,
-      isDirectory: false,
+      isDirectory: true,
     };
     const TEST_FILE_SYSTEM_DIRECTORY_READ_GRANT: RawFileSystemGrant = {
       origin: origin,
@@ -80,61 +59,43 @@
       isWritable: false,
       isDirectory: true,
     };
-    const TEST_FILE_SYSTEM_DIRECTORY_WRITE_GRANT: RawFileSystemGrant = {
-      origin: origin,
-      filePath: directoryFilePath2,
+    const TEST_FILE_SYSTEM_FILE_READ_GRANT: RawFileSystemGrant = {
+      origin: origin2,
+      filePath: filePath2,
+      isWritable: false,
+      isDirectory: false,
+    };
+    const TEST_FILE_SYSTEM_FILE_WRITE_GRANT: RawFileSystemGrant = {
+      origin: origin2,
+      filePath: filePath1,
       isWritable: true,
-      isDirectory: true,
+      isDirectory: false,
     };
 
-    browserProxy.setFileSystemGrants([{
-      origin: origin,
-      directoryReadGrants: [TEST_FILE_SYSTEM_DIRECTORY_READ_GRANT],
-      directoryWriteGrants: [TEST_FILE_SYSTEM_DIRECTORY_WRITE_GRANT],
-      fileReadGrants: [TEST_FILE_SYSTEM_FILE_READ_GRANT],
-      fileWriteGrants: [
-        TEST_FILE_SYSTEM_FILE_WRITE_GRANT1,
-        TEST_FILE_SYSTEM_FILE_WRITE_GRANT2,
-      ],
-    }]);
-
-    // File paths listed in the order that they are displayed on the UI:
-    // (For all grants listed in the ordering below, are in the order they
-    // are listed in `setFileSystemGrants` above).
-    // File write grants -> directory write grants -> file read grants ->
-    // directory read grants.
-    const allFilePathsInDisplayOrder: string[] = [
-      filePath1,
-      filePath2,
-      directoryFilePath2,
-      filePath3,
-      directoryFilePath1,
-    ];
+    browserProxy.setFileSystemGrants([
+      {
+        origin: origin,
+        directoryReadGrants: [TEST_FILE_SYSTEM_DIRECTORY_READ_GRANT],
+        directoryWriteGrants: [TEST_FILE_SYSTEM_DIRECTORY_WRITE_GRANT],
+        fileReadGrants: [],
+        fileWriteGrants: [],
+      },
+      {
+        origin: origin2,
+        directoryReadGrants: [],
+        directoryWriteGrants: [],
+        fileReadGrants: [TEST_FILE_SYSTEM_FILE_READ_GRANT],
+        fileWriteGrants: [TEST_FILE_SYSTEM_FILE_WRITE_GRANT],
+      },
+    ]);
 
     navigateToFileSystemSettingsPage();
     await browserProxy.whenCalled('getFileSystemGrants');
     flush();
 
     // Ensure that the list container element is populated.
-    // The number of h2 elements displayed on the page equals the number of
-    // origins with allowed permission grants.
-    const fileSystemOriginsWithAllowedGrants =
-        testElement.shadowRoot!.querySelectorAll('h2');
-    assertEquals(1, fileSystemOriginsWithAllowedGrants.length);
-
-    // The number of elements with the `display-name` class attribute
-    // equals the number of file paths associated with an
-    // allowed permission grant for a given origin.
-    const fileSystemAllowedGrants =
-        testElement.shadowRoot!.querySelectorAll('div.display-name');
-    assertEquals(
-        allFilePathsInDisplayOrder.length, fileSystemAllowedGrants.length);
-
-    // The values of the data displayed on the page are as expected.
-    for (let i = 0; i < fileSystemAllowedGrants.length; i++) {
-      assertEquals(
-          allFilePathsInDisplayOrder[i],
-          fileSystemAllowedGrants[i]!.textContent);
-    }
+    const fileSystemSiteEntries =
+        testElement.shadowRoot!.querySelectorAll('file-system-site-entry');
+    assertEquals(2, fileSystemSiteEntries.length);
   });
 });
\ No newline at end of file
diff --git a/ui/webui/resources/cr_elements/cr_icons.css b/ui/webui/resources/cr_elements/cr_icons.css
index 2e0890e..e24bbd8 100644
--- a/ui/webui/resources/cr_elements/cr_icons.css
+++ b/ui/webui/resources/cr_elements/cr_icons.css
@@ -35,6 +35,10 @@
   --cr-icon-image: url(chrome://resources/images/icon_edit.svg);
 }
 
+.icon-file {
+  --cr-icon-image: url(chrome://resources/images/icon_filetype_generic.svg);
+}
+
 .icon-folder-open {
   --cr-icon-image: url(chrome://resources/images/icon_folder_open.svg);
 }
diff --git a/ui/webui/resources/images/BUILD.gn b/ui/webui/resources/images/BUILD.gn
index 853ddb5..e6f6d39 100644
--- a/ui/webui/resources/images/BUILD.gn
+++ b/ui/webui/resources/images/BUILD.gn
@@ -59,6 +59,7 @@
       "icon_edit.svg",
       "icon_expand_less.svg",
       "icon_expand_more.svg",
+      "icon_filetype_generic.svg",
       "icon_folder_open.svg",
       "icon_journeys.svg",
       "icon_more_vert.svg",
diff --git a/ui/webui/resources/images/icon_filetype_generic.svg b/ui/webui/resources/images/icon_filetype_generic.svg
new file mode 100644
index 0000000..ba78ddce
--- /dev/null
+++ b/ui/webui/resources/images/icon_filetype_generic.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+  <path fill="#5f6368" d="M11 2l5 5v10a1 1 0 01-1 1H5a1 1 0 01-1-1V3a1 1 0 011-1h6zm-1 2H6v12h8V8h-4V4z"/>
+</svg>
\ No newline at end of file