chromium/chrome/browser/resources/settings/site_settings/file_system_site_list.ts

// 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-list' is an element representing a list of origin-specific
 * permission entries for the File System Access API.
 */
import 'chrome://resources/cr_elements/cr_shared_style.css.js';
import 'chrome://resources/cr_elements/cr_shared_vars.css.js';
import '../settings_shared.css.js';
import './file_system_site_entry.js';

import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js';
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';

import {routes} from '../route.js';
import type {Route} from '../router.js';
import {RouteObserverMixin} from '../router.js';

import {ContentSettingsTypes} from './constants.js';
import {getTemplate} from './file_system_site_list.html.js';
import {SiteSettingsMixin} from './site_settings_mixin.js';

export interface FileSystemGrant {
  isDirectory: boolean;
  displayName: string;  // Might be a shortened file path.
  filePath: string;
}

export interface OriginFileSystemGrants {
  origin: string;
  viewGrants: FileSystemGrant[];
  editGrants: FileSystemGrant[];
}

declare global {
  interface HTMLElementEventMap {
    'revoke-grants': CustomEvent<OriginFileSystemGrants>;
  }
}

const FileSystemSiteListElementBase =
    WebUiListenerMixin(RouteObserverMixin(SiteSettingsMixin(PolymerElement)));

export class FileSystemSiteListElement extends FileSystemSiteListElementBase {
  static get is() {
    return 'file-system-site-list';
  }

  static get template() {
    return getTemplate();
  }

  static get properties() {
    return {
      /**
       * Array of the File System permission grants that are actively displayed,
       * grouped by origin.
       */
      allowedGrants_: {
        type: Array,
        value: () => [],
      },
    };
  }

  private allowedGrants_: OriginFileSystemGrants[];

  override connectedCallback() {
    super.connectedCallback();

    this.addWebUiListener(
        'contentSettingChooserPermissionChanged',
        (category: ContentSettingsTypes) => {
          if (category === ContentSettingsTypes.FILE_SYSTEM_WRITE) {
            this.populateList_();
          }
        });
  }

  override disconnectedCallback() {
    super.disconnectedCallback();
  }

  /**
   * Reload the site list when the chrome://settings/content/filesystem
   * page is visited.
   *
   * RouteObserverMixin
   */
  override currentRouteChanged(currentRoute: Route, oldRoute?: Route) {
    if (currentRoute === routes.SITE_SETTINGS_FILE_SYSTEM_WRITE &&
        currentRoute !== oldRoute) {
      this.populateList_();
    }
  }

  /**
   * Retrieves a list of all known origins with allowed permissions,
   * granted via the File System Access API.
   */
  private async populateList_() {
    const response = await this.browserProxy.getFileSystemGrants();
    this.set('allowedGrants_', response);
  }

  /**
   * Determines whether there are any allowed File System Access permission
   * grants.
   */
  private hasAllowedGrants_(): boolean {
    return this.allowedGrants_.length > 0;
  }

  /**
   * Revoke all permission grants for a given origin, then update the list
   * displayed on the UI.
   */
  private onRevokeGrants_(e: CustomEvent<OriginFileSystemGrants>) {
    this.browserProxy.revokeFileSystemGrants(e.detail.origin);
  }
}

declare global {
  interface HTMLElementTagNameMap {
    'file-system-site-list': FileSystemSiteListElement;
  }
}

customElements.define(FileSystemSiteListElement.is, FileSystemSiteListElement);