fix: File System API permissions should reset on WebContents destruction (#43009)
fix: active File System API permissions should reset on WebContents destruction
This commit is contained in:
parent
aa23198ad8
commit
976f5d1b75
5 changed files with 124 additions and 4 deletions
|
@ -390,6 +390,8 @@ filenames = {
|
||||||
"shell/browser/file_system_access/file_system_access_permission_context.h",
|
"shell/browser/file_system_access/file_system_access_permission_context.h",
|
||||||
"shell/browser/file_system_access/file_system_access_permission_context_factory.cc",
|
"shell/browser/file_system_access/file_system_access_permission_context_factory.cc",
|
||||||
"shell/browser/file_system_access/file_system_access_permission_context_factory.h",
|
"shell/browser/file_system_access/file_system_access_permission_context_factory.h",
|
||||||
|
"shell/browser/file_system_access/file_system_access_web_contents_helper.cc",
|
||||||
|
"shell/browser/file_system_access/file_system_access_web_contents_helper.h",
|
||||||
"shell/browser/font_defaults.cc",
|
"shell/browser/font_defaults.cc",
|
||||||
"shell/browser/font_defaults.h",
|
"shell/browser/font_defaults.h",
|
||||||
"shell/browser/hid/electron_hid_delegate.cc",
|
"shell/browser/hid/electron_hid_delegate.cc",
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "base/task/bind_post_task.h"
|
#include "base/task/bind_post_task.h"
|
||||||
#include "base/task/thread_pool.h"
|
#include "base/task/thread_pool.h"
|
||||||
#include "base/time/time.h"
|
#include "base/time/time.h"
|
||||||
|
#include "base/timer/timer.h"
|
||||||
#include "base/values.h"
|
#include "base/values.h"
|
||||||
#include "chrome/browser/browser_process.h"
|
#include "chrome/browser/browser_process.h"
|
||||||
#include "chrome/browser/file_system_access/chrome_file_system_access_permission_context.h" // nogncheck
|
#include "chrome/browser/file_system_access/chrome_file_system_access_permission_context.h" // nogncheck
|
||||||
|
@ -92,6 +93,8 @@ const char kPathKey[] = "path";
|
||||||
const char kPathTypeKey[] = "path-type";
|
const char kPathTypeKey[] = "path-type";
|
||||||
const char kTimestampKey[] = "timestamp";
|
const char kTimestampKey[] = "timestamp";
|
||||||
|
|
||||||
|
constexpr base::TimeDelta kPermissionRevocationTimeout = base::Seconds(5);
|
||||||
|
|
||||||
#if BUILDFLAG(IS_WIN)
|
#if BUILDFLAG(IS_WIN)
|
||||||
[[nodiscard]] constexpr bool ContainsInvalidDNSCharacter(
|
[[nodiscard]] constexpr bool ContainsInvalidDNSCharacter(
|
||||||
base::FilePath::StringType hostname) {
|
base::FilePath::StringType hostname) {
|
||||||
|
@ -418,6 +421,7 @@ class FileSystemAccessPermissionContext::PermissionGrantImpl
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FileSystemAccessPermissionContext::OriginState {
|
struct FileSystemAccessPermissionContext::OriginState {
|
||||||
|
std::unique_ptr<base::RetainingOneShotTimer> cleanup_timer;
|
||||||
// Raw pointers, owned collectively by all the handles that reference this
|
// Raw pointers, owned collectively by all the handles that reference this
|
||||||
// grant. When last reference goes away this state is cleared as well by
|
// grant. When last reference goes away this state is cleared as well by
|
||||||
// PermissionGrantDestroyed().
|
// PermissionGrantDestroyed().
|
||||||
|
@ -831,7 +835,7 @@ void FileSystemAccessPermissionContext::CheckPathsAgainstEnterprisePolicy(
|
||||||
std::move(callback).Run(std::move(entries));
|
std::move(callback).Run(std::move(entries));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSystemAccessPermissionContext::RevokeGrant(
|
void FileSystemAccessPermissionContext::RevokeActiveGrants(
|
||||||
const url::Origin& origin,
|
const url::Origin& origin,
|
||||||
const base::FilePath& file_path) {
|
const base::FilePath& file_path) {
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
@ -881,10 +885,30 @@ bool FileSystemAccessPermissionContext::OriginHasWriteAccess(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileSystemAccessPermissionContext::NavigatedAwayFromOrigin(
|
||||||
|
const url::Origin& origin) {
|
||||||
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
|
auto it = active_permissions_map_.find(origin);
|
||||||
|
// If we have no permissions for the origin, there is nothing to do.
|
||||||
|
if (it == active_permissions_map_.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start a timer to possibly clean up permissions for this origin.
|
||||||
|
if (!it->second.cleanup_timer) {
|
||||||
|
it->second.cleanup_timer = std::make_unique<base::RetainingOneShotTimer>(
|
||||||
|
FROM_HERE, kPermissionRevocationTimeout,
|
||||||
|
base::BindRepeating(
|
||||||
|
&FileSystemAccessPermissionContext::CleanupPermissions,
|
||||||
|
base::Unretained(this), origin));
|
||||||
|
}
|
||||||
|
it->second.cleanup_timer->Reset();
|
||||||
|
}
|
||||||
|
|
||||||
void FileSystemAccessPermissionContext::CleanupPermissions(
|
void FileSystemAccessPermissionContext::CleanupPermissions(
|
||||||
const url::Origin& origin) {
|
const url::Origin& origin) {
|
||||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||||
RevokeGrant(origin);
|
RevokeActiveGrants(origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileSystemAccessPermissionContext::AncestorHasActivePermission(
|
bool FileSystemAccessPermissionContext::AncestorHasActivePermission(
|
||||||
|
|
|
@ -112,12 +112,16 @@ class FileSystemAccessPermissionContext
|
||||||
|
|
||||||
enum class RequestType { kNewPermission, kRestorePermissions };
|
enum class RequestType { kNewPermission, kRestorePermissions };
|
||||||
|
|
||||||
void RevokeGrant(const url::Origin& origin,
|
void RevokeActiveGrants(const url::Origin& origin,
|
||||||
const base::FilePath& file_path = base::FilePath());
|
const base::FilePath& file_path = base::FilePath());
|
||||||
|
|
||||||
bool OriginHasReadAccess(const url::Origin& origin);
|
bool OriginHasReadAccess(const url::Origin& origin);
|
||||||
bool OriginHasWriteAccess(const url::Origin& origin);
|
bool OriginHasWriteAccess(const url::Origin& origin);
|
||||||
|
|
||||||
|
// Called by FileSystemAccessWebContentsHelper when a top-level frame was
|
||||||
|
// navigated away from `origin` to some other origin.
|
||||||
|
void NavigatedAwayFromOrigin(const url::Origin& origin);
|
||||||
|
|
||||||
content::BrowserContext* browser_context() const { return browser_context_; }
|
content::BrowserContext* browser_context() const { return browser_context_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
// Copyright (c) 2024 Microsoft, GmbH
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "shell/browser/file_system_access/file_system_access_web_contents_helper.h"
|
||||||
|
|
||||||
|
#include "content/public/browser/browser_context.h"
|
||||||
|
#include "content/public/browser/navigation_handle.h"
|
||||||
|
#include "shell/browser/file_system_access/file_system_access_permission_context.h"
|
||||||
|
#include "shell/browser/file_system_access/file_system_access_permission_context_factory.h"
|
||||||
|
|
||||||
|
FileSystemAccessWebContentsHelper::~FileSystemAccessWebContentsHelper() =
|
||||||
|
default;
|
||||||
|
|
||||||
|
void FileSystemAccessWebContentsHelper::DidFinishNavigation(
|
||||||
|
content::NavigationHandle* navigation) {
|
||||||
|
// We only care about top-level navigations that actually committed.
|
||||||
|
if (!navigation->IsInPrimaryMainFrame() || !navigation->HasCommitted())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto src_origin =
|
||||||
|
url::Origin::Create(navigation->GetPreviousPrimaryMainFrameURL());
|
||||||
|
auto dest_origin = url::Origin::Create(navigation->GetURL());
|
||||||
|
|
||||||
|
if (src_origin == dest_origin)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Navigated away from |src_origin|, tell permission context to check if
|
||||||
|
// permissions need to be revoked.
|
||||||
|
auto* context =
|
||||||
|
electron::FileSystemAccessPermissionContextFactory::GetForBrowserContext(
|
||||||
|
web_contents()->GetBrowserContext());
|
||||||
|
if (context)
|
||||||
|
context->NavigatedAwayFromOrigin(src_origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSystemAccessWebContentsHelper::WebContentsDestroyed() {
|
||||||
|
auto src_origin =
|
||||||
|
web_contents()->GetPrimaryMainFrame()->GetLastCommittedOrigin();
|
||||||
|
|
||||||
|
// Navigated away from |src_origin|, tell permission context to check if
|
||||||
|
// permissions need to be revoked.
|
||||||
|
auto* context =
|
||||||
|
electron::FileSystemAccessPermissionContextFactory::GetForBrowserContext(
|
||||||
|
web_contents()->GetBrowserContext());
|
||||||
|
if (context)
|
||||||
|
context->NavigatedAwayFromOrigin(src_origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileSystemAccessWebContentsHelper::FileSystemAccessWebContentsHelper(
|
||||||
|
content::WebContents* web_contents)
|
||||||
|
: content::WebContentsObserver(web_contents),
|
||||||
|
content::WebContentsUserData<FileSystemAccessWebContentsHelper>(
|
||||||
|
*web_contents) {}
|
||||||
|
|
||||||
|
WEB_CONTENTS_USER_DATA_KEY_IMPL(FileSystemAccessWebContentsHelper);
|
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright (c) 2024 Microsoft, GmbH
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef ELECTRON_SHELL_BROWSER_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_WEB_CONTENTS_HELPER_H_
|
||||||
|
#define ELECTRON_SHELL_BROWSER_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_WEB_CONTENTS_HELPER_H_
|
||||||
|
|
||||||
|
#include "content/public/browser/web_contents_observer.h"
|
||||||
|
#include "content/public/browser/web_contents_user_data.h"
|
||||||
|
|
||||||
|
class FileSystemAccessWebContentsHelper
|
||||||
|
: public content::WebContentsObserver,
|
||||||
|
public content::WebContentsUserData<FileSystemAccessWebContentsHelper> {
|
||||||
|
public:
|
||||||
|
FileSystemAccessWebContentsHelper(const FileSystemAccessWebContentsHelper&) =
|
||||||
|
delete;
|
||||||
|
FileSystemAccessWebContentsHelper& operator=(
|
||||||
|
const FileSystemAccessWebContentsHelper&) = delete;
|
||||||
|
~FileSystemAccessWebContentsHelper() override;
|
||||||
|
|
||||||
|
// content::WebContentsObserver
|
||||||
|
void DidFinishNavigation(
|
||||||
|
content::NavigationHandle* navigation_handle) override;
|
||||||
|
void WebContentsDestroyed() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit FileSystemAccessWebContentsHelper(
|
||||||
|
content::WebContents* web_contents);
|
||||||
|
friend class content::WebContentsUserData<FileSystemAccessWebContentsHelper>;
|
||||||
|
|
||||||
|
WEB_CONTENTS_USER_DATA_KEY_DECL();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ELECTRON_SHELL_BROWSER_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_WEB_CONTENTS_HELPER_H_
|
Loading…
Add table
Add a link
Reference in a new issue