blob: 0d01c96bb113113425e14feca09b4cd8da9f3abe [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_NATIVE_FILE_SYSTEM_CHROME_NATIVE_FILE_SYSTEM_PERMISSION_CONTEXT_H_
#define CHROME_BROWSER_NATIVE_FILE_SYSTEM_CHROME_NATIVE_FILE_SYSTEM_PERMISSION_CONTEXT_H_
#include <map>
#include <vector>
#include "base/sequence_checker.h"
#include "chrome/browser/permissions/permission_util.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/keyed_service/core/keyed_service.h"
#include "content/public/browser/native_file_system_permission_context.h"
#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
class HostContentSettingsMap;
namespace content {
class BrowserContext;
} // namespace content
// Chrome implementation of NativeFileSystemPermissionContext. Currently
// implements a single per-origin write permission state.
//
// All methods must be called on the UI thread.
//
// This class does not inherit from ChooserContextBase because the model this
// API uses doesn't really match what ChooserContextBase has to provide. The
// limited lifetime of native file system permission grants (scoped to the
// lifetime of the handles that reference the grants), and the possible
// interactions between grants for directories and grants for children of those
// directories as well as possible interactions between read and write grants
// make it harder to squeeze this into a shape that fits with
// ChooserContextBase.
class ChromeNativeFileSystemPermissionContext
: public content::NativeFileSystemPermissionContext,
public KeyedService {
public:
explicit ChromeNativeFileSystemPermissionContext(
content::BrowserContext* context);
~ChromeNativeFileSystemPermissionContext() override;
class WritePermissionGrantImpl
: public content::NativeFileSystemPermissionGrant {
public:
// In the current implementation permission grants are scoped to the frame
// they are requested in. Within a frame we only want to have one grant per
// path. The Key struct contains these fields. Keys are comparable so they
// can be used with sorted containers like std::map and std::set.
// TODO(https://crbug.com/984769): Eliminate process_id and frame_id and
// replace usage of this struct with just a file path when grants stop being
// scoped to a frame.
struct Key {
base::FilePath path;
int process_id = 0;
int frame_id = 0;
bool operator==(const Key& rhs) const;
bool operator<(const Key& rhs) const;
};
WritePermissionGrantImpl(
base::WeakPtr<ChromeNativeFileSystemPermissionContext> context,
const url::Origin& origin,
const Key& key,
bool is_directory);
// content::NativeFileSystemPermissionGrant implementation:
PermissionStatus GetStatus() override;
void RequestPermission(
int process_id,
int frame_id,
base::OnceCallback<void(PermissionRequestOutcome)> callback) override;
const url::Origin& origin() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return origin_;
}
bool is_directory() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return is_directory_;
}
const base::FilePath& path() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return key_.path;
}
const Key& key() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return key_;
}
// Returns true if the |content_setting_guard_type_| has not been blocked.
bool CanRequestPermission();
void SetStatus(PermissionStatus status);
protected:
~WritePermissionGrantImpl() override;
private:
void OnPermissionRequestComplete(
base::OnceCallback<void(PermissionRequestOutcome)> callback,
PermissionRequestOutcome outcome,
PermissionAction result);
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtr<ChromeNativeFileSystemPermissionContext> const context_;
const url::Origin origin_;
const Key key_;
const bool is_directory_;
// This member should only be updated via SetStatus(), to make sure
// observers are properly notified about any change in status.
PermissionStatus status_ = PermissionStatus::ASK;
DISALLOW_COPY_AND_ASSIGN(WritePermissionGrantImpl);
};
// content::NativeFileSystemPermissionContext:
scoped_refptr<content::NativeFileSystemPermissionGrant>
GetReadPermissionGrant(const url::Origin& origin,
const base::FilePath& path,
bool is_directory,
int process_id,
int frame_id) override;
bool CanRequestWritePermission(const url::Origin& origin) override;
scoped_refptr<content::NativeFileSystemPermissionGrant>
GetWritePermissionGrant(const url::Origin& origin,
const base::FilePath& path,
bool is_directory,
int process_id,
int frame_id,
UserAction user_action) override;
void ConfirmSensitiveDirectoryAccess(
const url::Origin& origin,
const std::vector<base::FilePath>& paths,
bool is_directory,
int process_id,
int frame_id,
base::OnceCallback<void(SensitiveDirectoryResult)> callback) override;
void ConfirmDirectoryReadAccess(
const url::Origin& origin,
const base::FilePath& path,
int process_id,
int frame_id,
base::OnceCallback<void(PermissionStatus)> callback) override;
void PerformAfterWriteChecks(
std::unique_ptr<content::NativeFileSystemWriteItem> item,
int process_id,
int frame_id,
base::OnceCallback<void(AfterWriteCheckResult)> callback) override;
// Returns a snapshot of the currently granted permissions.
// TODO(https://crbug.com/984769): Eliminate process_id and frame_id from this
// method when grants stop being scoped to a frame.
struct Grants {
Grants();
~Grants();
Grants(Grants&&);
Grants& operator=(Grants&&);
std::vector<base::FilePath> file_write_grants;
std::vector<base::FilePath> directory_write_grants;
};
Grants GetPermissionGrants(const url::Origin& origin,
int process_id,
int frame_id);
// Revokes directory read access for the given origin in the given tab.
void RevokeDirectoryReadGrants(const url::Origin& origin,
int process_id,
int frame_id);
// Revokes write access for the given origin in the given tab.
void RevokeWriteGrants(const url::Origin& origin,
int process_id,
int frame_id);
// Revokes write access and directory read access for the given origin in the
// given tab.
void RevokeGrantsForOriginAndTab(const url::Origin& origin,
int process_id,
int frame_id);
HostContentSettingsMap* content_settings() { return content_settings_.get(); }
private:
void PermissionGrantDestroyed(WritePermissionGrantImpl* grant);
void DidConfirmSensitiveDirectoryAccess(
const url::Origin& origin,
const std::vector<base::FilePath>& paths,
bool is_directory,
int process_id,
int frame_id,
base::OnceCallback<void(SensitiveDirectoryResult)> callback,
bool should_block);
SEQUENCE_CHECKER(sequence_checker_);
// Permission state per origin.
struct OriginState;
std::map<url::Origin, OriginState> origins_;
scoped_refptr<HostContentSettingsMap> content_settings_;
base::WeakPtrFactory<ChromeNativeFileSystemPermissionContext> weak_factory_{
this};
DISALLOW_COPY_AND_ASSIGN(ChromeNativeFileSystemPermissionContext);
};
#endif // CHROME_BROWSER_NATIVE_FILE_SYSTEM_CHROME_NATIVE_FILE_SYSTEM_PERMISSION_CONTEXT_H_