feat: emit an event when accessing restricted path in File System Access API (#43162)
* fix: show a dialog when accessing restricted path in File System Access API Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * fix: allow overriding initial blocked paths Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * docs: fix doc Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * Update docs/api/session.md Co-authored-by: Erick Zhao <erick@hotmail.ca> Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * fix: change block to deny for consistency Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> --------- Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
This commit is contained in:
parent
e39c0f9dae
commit
ff3d3e6944
3 changed files with 149 additions and 18 deletions
|
@ -11,6 +11,7 @@
|
|||
#include "base/files/file_path.h"
|
||||
#include "base/json/values_util.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/task/bind_post_task.h"
|
||||
#include "base/task/thread_pool.h"
|
||||
#include "base/time/time.h"
|
||||
#include "base/timer/timer.h"
|
||||
|
@ -26,18 +27,52 @@
|
|||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "gin/data_object_builder.h"
|
||||
#include "shell/browser/api/electron_api_session.h"
|
||||
#include "shell/browser/electron_permission_manager.h"
|
||||
#include "shell/browser/web_contents_permission_helper.h"
|
||||
#include "shell/common/gin_converters/callback_converter.h"
|
||||
#include "shell/common/gin_converters/file_path_converter.h"
|
||||
#include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
namespace gin {
|
||||
|
||||
template <>
|
||||
struct Converter<
|
||||
ChromeFileSystemAccessPermissionContext::SensitiveEntryResult> {
|
||||
static bool FromV8(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
ChromeFileSystemAccessPermissionContext::SensitiveEntryResult* out) {
|
||||
std::string type;
|
||||
if (!ConvertFromV8(isolate, val, &type))
|
||||
return false;
|
||||
if (type == "allow")
|
||||
*out = ChromeFileSystemAccessPermissionContext::SensitiveEntryResult::
|
||||
kAllowed;
|
||||
else if (type == "tryAgain")
|
||||
*out = ChromeFileSystemAccessPermissionContext::SensitiveEntryResult::
|
||||
kTryAgain;
|
||||
else if (type == "deny")
|
||||
*out =
|
||||
ChromeFileSystemAccessPermissionContext::SensitiveEntryResult::kAbort;
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace gin
|
||||
|
||||
namespace {
|
||||
|
||||
using BlockType = ChromeFileSystemAccessPermissionContext::BlockType;
|
||||
using HandleType = content::FileSystemAccessPermissionContext::HandleType;
|
||||
using GrantType = electron::FileSystemAccessPermissionContext::GrantType;
|
||||
using SensitiveEntryResult =
|
||||
ChromeFileSystemAccessPermissionContext::SensitiveEntryResult;
|
||||
using blink::mojom::PermissionStatus;
|
||||
|
||||
// Dictionary keys for the FILE_SYSTEM_LAST_PICKED_DIRECTORY website setting.
|
||||
|
@ -527,11 +562,11 @@ void FileSystemAccessPermissionContext::ConfirmSensitiveEntryAccess(
|
|||
content::GlobalRenderFrameHostId frame_id,
|
||||
base::OnceCallback<void(SensitiveEntryResult)> callback) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
callback_ = std::move(callback);
|
||||
|
||||
auto after_blocklist_check_callback = base::BindOnce(
|
||||
&FileSystemAccessPermissionContext::DidCheckPathAgainstBlocklist,
|
||||
GetWeakPtr(), origin, path, handle_type, user_action, frame_id,
|
||||
std::move(callback));
|
||||
GetWeakPtr(), origin, path, handle_type, user_action, frame_id);
|
||||
CheckPathAgainstBlocklist(path_type, path, handle_type,
|
||||
std::move(after_blocklist_check_callback));
|
||||
}
|
||||
|
@ -570,31 +605,54 @@ void FileSystemAccessPermissionContext::PerformAfterWriteChecks(
|
|||
std::move(callback).Run(AfterWriteCheckResult::kAllow);
|
||||
}
|
||||
|
||||
void FileSystemAccessPermissionContext::RunRestrictedPathCallback(
|
||||
SensitiveEntryResult result) {
|
||||
if (callback_)
|
||||
std::move(callback_).Run(result);
|
||||
}
|
||||
|
||||
void FileSystemAccessPermissionContext::OnRestrictedPathResult(
|
||||
gin::Arguments* args) {
|
||||
SensitiveEntryResult result = SensitiveEntryResult::kAbort;
|
||||
args->GetNext(&result);
|
||||
RunRestrictedPathCallback(result);
|
||||
}
|
||||
|
||||
void FileSystemAccessPermissionContext::DidCheckPathAgainstBlocklist(
|
||||
const url::Origin& origin,
|
||||
const base::FilePath& path,
|
||||
HandleType handle_type,
|
||||
UserAction user_action,
|
||||
content::GlobalRenderFrameHostId frame_id,
|
||||
base::OnceCallback<void(SensitiveEntryResult)> callback,
|
||||
bool should_block) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
|
||||
if (user_action == UserAction::kNone) {
|
||||
std::move(callback).Run(should_block ? SensitiveEntryResult::kAbort
|
||||
: SensitiveEntryResult::kAllowed);
|
||||
RunRestrictedPathCallback(should_block ? SensitiveEntryResult::kAbort
|
||||
: SensitiveEntryResult::kAllowed);
|
||||
return;
|
||||
}
|
||||
|
||||
// Chromium opens a dialog here, but in Electron's case we log and abort.
|
||||
if (should_block) {
|
||||
LOG(INFO) << path.value()
|
||||
<< " is blocked by the blocklis and cannot be accessed";
|
||||
std::move(callback).Run(SensitiveEntryResult::kAbort);
|
||||
auto* session =
|
||||
electron::api::Session::FromBrowserContext(browser_context());
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
v8::Local<v8::Object> details =
|
||||
gin::DataObjectBuilder(isolate)
|
||||
.Set("origin", origin.GetURL().spec())
|
||||
.Set("isDirectory", handle_type == HandleType::kDirectory)
|
||||
.Set("path", path)
|
||||
.Build();
|
||||
session->Emit(
|
||||
"file-system-access-restricted", details,
|
||||
base::BindRepeating(
|
||||
&FileSystemAccessPermissionContext::OnRestrictedPathResult,
|
||||
weak_factory_.GetWeakPtr()));
|
||||
return;
|
||||
}
|
||||
|
||||
std::move(callback).Run(SensitiveEntryResult::kAllowed);
|
||||
RunRestrictedPathCallback(SensitiveEntryResult::kAllowed);
|
||||
}
|
||||
|
||||
void FileSystemAccessPermissionContext::MaybeEvictEntries(
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
|
||||
class GURL;
|
||||
|
||||
namespace gin {
|
||||
class Arguments;
|
||||
} // namespace gin
|
||||
|
||||
namespace base {
|
||||
class FilePath;
|
||||
} // namespace base
|
||||
|
@ -128,14 +132,16 @@ class FileSystemAccessPermissionContext
|
|||
const base::FilePath& path,
|
||||
HandleType handle_type,
|
||||
base::OnceCallback<void(bool)> callback);
|
||||
void DidCheckPathAgainstBlocklist(
|
||||
const url::Origin& origin,
|
||||
const base::FilePath& path,
|
||||
HandleType handle_type,
|
||||
UserAction user_action,
|
||||
content::GlobalRenderFrameHostId frame_id,
|
||||
base::OnceCallback<void(SensitiveEntryResult)> callback,
|
||||
bool should_block);
|
||||
void DidCheckPathAgainstBlocklist(const url::Origin& origin,
|
||||
const base::FilePath& path,
|
||||
HandleType handle_type,
|
||||
UserAction user_action,
|
||||
content::GlobalRenderFrameHostId frame_id,
|
||||
bool should_block);
|
||||
|
||||
void RunRestrictedPathCallback(SensitiveEntryResult result);
|
||||
|
||||
void OnRestrictedPathResult(gin::Arguments* args);
|
||||
|
||||
void MaybeEvictEntries(base::Value::Dict& dict);
|
||||
|
||||
|
@ -159,6 +165,8 @@ class FileSystemAccessPermissionContext
|
|||
|
||||
std::map<url::Origin, base::Value::Dict> id_pathinfo_map_;
|
||||
|
||||
base::OnceCallback<void(SensitiveEntryResult)> callback_;
|
||||
|
||||
base::WeakPtrFactory<FileSystemAccessPermissionContext> weak_factory_{this};
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue