dlp: Pass file access callback to file stream reader
The callback is passed through the calls from the mojo interface to the file stream reader. Where it is used to gain a ScopedFileAccess token to read files. The callback is not yet created for the calls depending on the destination URL. That will happen with a CL for b/262203074. There are different cases for default behavior, where we do not need to query the daemon with a specific URL. Only files explicitly known/downloaded to the user can be protected. That excludes e.g. caches. The daemon would not deny those accesses, so we do not have to ask for permission. The other default are cases, where we want to allow access regardless of the rules. Here we have to query the daemon with a request for the system component (e.g. by the callback returned by ScopedFileAccessDelegate::GetCallbackForSystemIO). Design doc: go/access-to-dlp-restricted-files-upload BUG=b:262199707 Change-Id: Id71ac3463aae4c0d0b02bb3a264c2a8d05798f22 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4197601 Reviewed-by: Sergey Poromov <poromov@chromium.org> Reviewed-by: Austin Sullivan <asully@chromium.org> Commit-Queue: Daniel Brinkers <brinky@google.com> Reviewed-by: Marcello Salomao <msalomao@google.com> Reviewed-by: Marijn Kruisselbrink <mek@chromium.org> Cr-Commit-Position: refs/heads/main@{#1114995}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
9df0c47961
commit
9dacf9e173
chrome/browser
ash
chromeos
policy
media_galleries
sync_file_system
components/file_access
scoped_file_access_delegate.ccscoped_file_access_delegate.hscoped_file_access_delegate_unittest.cc
test
content/browser/blob_storage
storage
BUILD.gn
browser
BUILD.gn
blob
blob_data_builder.ccblob_data_builder.hblob_data_item.ccblob_data_item.hblob_reader.ccblob_reader.hblob_registry_impl.ccblob_registry_impl.hblob_storage_context.cc
file_system
file_stream_reader.hfile_system_backend.hfile_system_context.ccfile_system_context.hisolated_file_system_backend.ccisolated_file_system_backend.hlocal_file_stream_reader.cclocal_file_stream_reader.hlocal_file_stream_reader_unittest.ccsandbox_file_system_backend.ccsandbox_file_system_backend.h
test
@ -12,6 +12,7 @@
|
||||
#include "ash/webui/file_manager/url_constants.h"
|
||||
#include "base/check_op.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/notreached.h"
|
||||
#include "base/strings/escape.h"
|
||||
#include "base/task/task_traits.h"
|
||||
@ -24,6 +25,7 @@
|
||||
#include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
|
||||
#include "chrome/common/url_constants.h"
|
||||
#include "chromeos/ash/components/dbus/cros_disks/cros_disks_client.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "components/user_manager/user.h"
|
||||
#include "storage/browser/file_system/async_file_util.h"
|
||||
#include "storage/browser/file_system/external_mount_points.h"
|
||||
@ -421,7 +423,9 @@ FileSystemBackend::CreateFileStreamReader(
|
||||
int64_t offset,
|
||||
int64_t max_bytes_to_read,
|
||||
const base::Time& expected_modification_time,
|
||||
storage::FileSystemContext* context) const {
|
||||
storage::FileSystemContext* context,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) const {
|
||||
DCHECK(url.is_valid());
|
||||
|
||||
if (!IsAccessAllowed(url))
|
||||
@ -431,8 +435,15 @@ FileSystemBackend::CreateFileStreamReader(
|
||||
case storage::kFileSystemTypeProvided:
|
||||
return file_system_provider_delegate_->CreateFileStreamReader(
|
||||
url, offset, max_bytes_to_read, expected_modification_time, context);
|
||||
// The dlp file_access callback is needed for the local filesystem only.
|
||||
case storage::kFileSystemTypeLocal:
|
||||
case storage::kFileSystemTypeRestrictedLocal:
|
||||
return storage::FileStreamReader::CreateForLocalFile(
|
||||
base::ThreadPool::CreateTaskRunner(
|
||||
{base::MayBlock(), base::TaskPriority::USER_VISIBLE})
|
||||
.get(),
|
||||
url.path(), offset, expected_modification_time,
|
||||
std::move(file_access));
|
||||
case storage::kFileSystemTypeDriveFs:
|
||||
case storage::kFileSystemTypeSmbFs:
|
||||
case storage::kFileSystemTypeFuseBox:
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "components/account_id/account_id.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "storage/browser/file_system/file_system_backend.h"
|
||||
#include "storage/browser/file_system/task_runner_bound_observer_list.h"
|
||||
#include "storage/common/file_system/file_system_types.h"
|
||||
@ -125,7 +126,9 @@ class FileSystemBackend : public storage::ExternalFileSystemBackend {
|
||||
int64_t offset,
|
||||
int64_t max_bytes_to_read,
|
||||
const base::Time& expected_modification_time,
|
||||
storage::FileSystemContext* context) const override;
|
||||
storage::FileSystemContext* context,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) const override;
|
||||
std::unique_ptr<storage::FileStreamWriter> CreateFileStreamWriter(
|
||||
const storage::FileSystemURL& url,
|
||||
int64_t offset,
|
||||
|
@ -4,12 +4,16 @@
|
||||
|
||||
#include "chrome/browser/chromeos/policy/dlp/dlp_scoped_file_access_delegate.h"
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_forward.h"
|
||||
#include "base/process/process_handle.h"
|
||||
#include "base/task/bind_post_task.h"
|
||||
#include "chrome/browser/chromeos/policy/dlp/dlp_file_access_copy_or_move_delegate_factory.h"
|
||||
#include "chromeos/dbus/dlp/dlp_client.h"
|
||||
#include "components/file_access/scoped_file_access.h"
|
||||
#include "components/file_access/scoped_file_access_copy.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "content/public/browser/browser_task_traits.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
|
||||
@ -56,7 +60,7 @@ void DlpScopedFileAccessDelegate::Initialize(chromeos::DlpClient* client) {
|
||||
if (!request_files_access_for_system_io_callback_) {
|
||||
request_files_access_for_system_io_callback_ =
|
||||
new file_access::ScopedFileAccessDelegate::
|
||||
RequestFilesAccessForSystemIOCallback(base::BindPostTask(
|
||||
RequestFilesAccessIOCallback(base::BindPostTask(
|
||||
content::GetUIThreadTaskRunner({}),
|
||||
base::BindRepeating(&RequestFileAccessForSystem)));
|
||||
}
|
||||
@ -115,6 +119,29 @@ void DlpScopedFileAccessDelegate::RequestFilesAccessForSystem(
|
||||
PostRequestFileAccessToDaemon(request, std::move(callback));
|
||||
}
|
||||
|
||||
DlpScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
DlpScopedFileAccessDelegate::CreateFileAccessCallback(
|
||||
const GURL& destination) const {
|
||||
return base::BindPostTask(
|
||||
content::GetUIThreadTaskRunner({}),
|
||||
base::BindRepeating(
|
||||
[](const GURL& destination, const std::vector<base::FilePath>& files,
|
||||
base::OnceCallback<void(file_access::ScopedFileAccess)> callback) {
|
||||
if (file_access::ScopedFileAccessDelegate::HasInstance()) {
|
||||
file_access::ScopedFileAccessDelegate::Get()->RequestFilesAccess(
|
||||
files, destination,
|
||||
base::BindPostTask(content::GetIOThreadTaskRunner({}),
|
||||
std::move(callback)));
|
||||
} else {
|
||||
content::GetIOThreadTaskRunner({})->PostTask(
|
||||
FROM_HERE,
|
||||
base::BindOnce(std::move(callback),
|
||||
file_access::ScopedFileAccess::Allowed()));
|
||||
}
|
||||
},
|
||||
destination));
|
||||
}
|
||||
|
||||
void DlpScopedFileAccessDelegate::PostRequestFileAccessToDaemon(
|
||||
const ::dlp::RequestFileAccessRequest request,
|
||||
base::OnceCallback<void(file_access::ScopedFileAccess)> callback) {
|
||||
|
@ -44,6 +44,8 @@ class DlpScopedFileAccessDelegate
|
||||
const std::vector<base::FilePath>& files,
|
||||
base::OnceCallback<void(file_access::ScopedFileAccess)> callback)
|
||||
override;
|
||||
RequestFilesAccessIOCallback CreateFileAccessCallback(
|
||||
const GURL& destination) const override;
|
||||
|
||||
protected:
|
||||
explicit DlpScopedFileAccessDelegate(chromeos::DlpClient* client);
|
||||
|
@ -36,7 +36,8 @@ class DlpScopedFileAccessDelegateTest : public testing::Test {
|
||||
protected:
|
||||
content::BrowserTaskEnvironment task_environment_;
|
||||
chromeos::FakeDlpClient fake_dlp_client_;
|
||||
DlpScopedFileAccessDelegate delegate_{&fake_dlp_client_};
|
||||
std::unique_ptr<DlpScopedFileAccessDelegate> delegate_{
|
||||
new DlpScopedFileAccessDelegate(&fake_dlp_client_)};
|
||||
};
|
||||
|
||||
TEST_F(DlpScopedFileAccessDelegateTest, TestNoSingleton) {
|
||||
@ -44,14 +45,14 @@ TEST_F(DlpScopedFileAccessDelegateTest, TestNoSingleton) {
|
||||
base::CreateTemporaryFile(&file_path);
|
||||
|
||||
base::test::TestFuture<file_access::ScopedFileAccess> future1;
|
||||
delegate_.RequestFilesAccess({file_path}, GURL("example.com"),
|
||||
future1.GetCallback());
|
||||
delegate_->RequestFilesAccess({file_path}, GURL("example.com"),
|
||||
future1.GetCallback());
|
||||
EXPECT_TRUE(future1.Get<0>().is_allowed());
|
||||
|
||||
fake_dlp_client_.SetFileAccessAllowed(false);
|
||||
base::test::TestFuture<file_access::ScopedFileAccess> future2;
|
||||
delegate_.RequestFilesAccess({file_path}, GURL("example.com"),
|
||||
future2.GetCallback());
|
||||
delegate_->RequestFilesAccess({file_path}, GURL("example.com"),
|
||||
future2.GetCallback());
|
||||
EXPECT_FALSE(future2.Get<0>().is_allowed());
|
||||
}
|
||||
|
||||
@ -87,6 +88,84 @@ TEST_F(DlpScopedFileAccessDelegateTest,
|
||||
EXPECT_TRUE(future1.Get<0>().is_allowed());
|
||||
}
|
||||
|
||||
TEST_F(DlpScopedFileAccessDelegateTest, CreateFileAccessCallbackAllowTest) {
|
||||
base::FilePath file_path;
|
||||
base::CreateTemporaryFile(&file_path);
|
||||
|
||||
DlpScopedFileAccessDelegate::Initialize(&fake_dlp_client_);
|
||||
fake_dlp_client_.SetFileAccessAllowed(true);
|
||||
|
||||
base::test::TestFuture<file_access::ScopedFileAccess> future;
|
||||
auto* delegate = file_access::ScopedFileAccessDelegate::Get();
|
||||
auto cb = delegate->CreateFileAccessCallback(GURL("https://google.com"));
|
||||
cb.Run({file_path}, future.GetCallback());
|
||||
EXPECT_TRUE(future.Get<0>().is_allowed());
|
||||
}
|
||||
|
||||
TEST_F(DlpScopedFileAccessDelegateTest, CreateFileAccessCallbackDenyTest) {
|
||||
base::FilePath file_path;
|
||||
base::CreateTemporaryFile(&file_path);
|
||||
|
||||
DlpScopedFileAccessDelegate::Initialize(&fake_dlp_client_);
|
||||
fake_dlp_client_.SetFileAccessAllowed(false);
|
||||
|
||||
base::test::TestFuture<file_access::ScopedFileAccess> future;
|
||||
auto* delegate = file_access::ScopedFileAccessDelegate::Get();
|
||||
auto cb = delegate->CreateFileAccessCallback(GURL("https://google.com"));
|
||||
cb.Run({file_path}, future.GetCallback());
|
||||
EXPECT_FALSE(future.Get<0>().is_allowed());
|
||||
}
|
||||
|
||||
TEST_F(DlpScopedFileAccessDelegateTest,
|
||||
CreateFileAccessCallbackLostInstanceTest) {
|
||||
base::FilePath file_path;
|
||||
base::CreateTemporaryFile(&file_path);
|
||||
|
||||
DlpScopedFileAccessDelegate::Initialize(&fake_dlp_client_);
|
||||
fake_dlp_client_.SetFileAccessAllowed(false);
|
||||
|
||||
base::test::TestFuture<file_access::ScopedFileAccess> future;
|
||||
auto* delegate = file_access::ScopedFileAccessDelegate::Get();
|
||||
auto cb = delegate->CreateFileAccessCallback(GURL("https://google.com"));
|
||||
delegate_.reset();
|
||||
cb.Run({file_path}, future.GetCallback());
|
||||
EXPECT_TRUE(future.Get<0>().is_allowed());
|
||||
}
|
||||
|
||||
TEST_F(DlpScopedFileAccessDelegateTest, GetCallbackSystemTest) {
|
||||
base::FilePath file_path;
|
||||
base::CreateTemporaryFile(&file_path);
|
||||
|
||||
DlpScopedFileAccessDelegate::Initialize(&fake_dlp_client_);
|
||||
|
||||
// Post a task on IO thread to sync with to be sure the IO task setting
|
||||
// `request_files_access_for_system_io_callback_` has run.
|
||||
base::RunLoop init;
|
||||
auto io_thread = content::GetIOThreadTaskRunner({});
|
||||
io_thread->PostTask(
|
||||
FROM_HERE, base::BindOnce(&base::RunLoop::Quit, base::Unretained(&init)));
|
||||
init.Run();
|
||||
|
||||
base::test::TestFuture<file_access::ScopedFileAccess> future;
|
||||
auto* delegate = file_access::ScopedFileAccessDelegate::Get();
|
||||
auto cb = delegate->GetCallbackForSystem();
|
||||
EXPECT_TRUE(cb);
|
||||
cb.Run({file_path}, future.GetCallback());
|
||||
EXPECT_TRUE(future.Get<0>().is_allowed());
|
||||
}
|
||||
|
||||
TEST_F(DlpScopedFileAccessDelegateTest, GetCallbackSystemNoSingeltonTest) {
|
||||
base::FilePath file_path;
|
||||
base::CreateTemporaryFile(&file_path);
|
||||
|
||||
base::test::TestFuture<file_access::ScopedFileAccess> future;
|
||||
auto* delegate = file_access::ScopedFileAccessDelegate::Get();
|
||||
auto cb = delegate->GetCallbackForSystem();
|
||||
EXPECT_TRUE(cb);
|
||||
cb.Run({file_path}, future.GetCallback());
|
||||
EXPECT_TRUE(future.Get<0>().is_allowed());
|
||||
}
|
||||
|
||||
TEST_F(DlpScopedFileAccessDelegateTest, TestMultipleInstances) {
|
||||
DlpScopedFileAccessDelegate::Initialize(nullptr);
|
||||
EXPECT_NO_FATAL_FAILURE(DlpScopedFileAccessDelegate::Initialize(nullptr));
|
||||
@ -209,7 +288,6 @@ TEST_F(DlpScopedFileAccessDelegateTaskTest,
|
||||
std::move(callback));
|
||||
}),
|
||||
false /* = restore_original_callback*/);
|
||||
|
||||
// The request for file access should be granted as that is the default
|
||||
// behaviour for no running dlp (no rules).
|
||||
io_thread_->PostTask(
|
||||
|
@ -316,7 +316,9 @@ MediaFileSystemBackend::CreateFileStreamReader(
|
||||
int64_t offset,
|
||||
int64_t max_bytes_to_read,
|
||||
const base::Time& expected_modification_time,
|
||||
FileSystemContext* context) const {
|
||||
FileSystemContext* context,
|
||||
file_access::ScopedFileAccessDelegate::
|
||||
RequestFilesAccessIOCallback /*file_access*/) const {
|
||||
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
if (url.type() == storage::kFileSystemTypeDeviceMedia) {
|
||||
std::unique_ptr<storage::FileStreamReader> reader =
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "build/chromeos_buildflags.h"
|
||||
#include "chrome/browser/media_galleries/media_galleries_preferences.h"
|
||||
#include "components/download/public/common/quarantine_connection.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "storage/browser/file_system/file_system_backend.h"
|
||||
#include "storage/browser/file_system/file_system_request_info.h"
|
||||
#include "storage/browser/file_system/task_runner_bound_observer_list.h"
|
||||
@ -85,7 +86,9 @@ class MediaFileSystemBackend : public storage::FileSystemBackend {
|
||||
int64_t offset,
|
||||
int64_t max_bytes_to_read,
|
||||
const base::Time& expected_modification_time,
|
||||
storage::FileSystemContext* context) const override;
|
||||
storage::FileSystemContext* context,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) const override;
|
||||
std::unique_ptr<storage::FileStreamWriter> CreateFileStreamWriter(
|
||||
const storage::FileSystemURL& url,
|
||||
int64_t offset,
|
||||
|
@ -163,7 +163,9 @@ SyncFileSystemBackend::CreateFileStreamReader(
|
||||
int64_t offset,
|
||||
int64_t max_bytes_to_read,
|
||||
const base::Time& expected_modification_time,
|
||||
storage::FileSystemContext* context) const {
|
||||
storage::FileSystemContext* context,
|
||||
file_access::ScopedFileAccessDelegate::
|
||||
RequestFilesAccessIOCallback /*file_access*/) const {
|
||||
DCHECK(CanHandleType(url.type()));
|
||||
return GetDelegate()->CreateFileStreamReader(
|
||||
url, offset, expected_modification_time, context);
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "chrome/browser/sync_file_system/sync_callbacks.h"
|
||||
#include "chrome/browser/sync_file_system/sync_status_code.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "storage/browser/file_system/file_system_backend.h"
|
||||
#include "storage/browser/file_system/file_system_quota_util.h"
|
||||
#include "storage/browser/file_system/sandbox_file_system_backend_delegate.h"
|
||||
@ -60,7 +61,9 @@ class SyncFileSystemBackend : public storage::FileSystemBackend {
|
||||
int64_t offset,
|
||||
int64_t max_bytes_to_read,
|
||||
const base::Time& expected_modification_time,
|
||||
storage::FileSystemContext* context) const override;
|
||||
storage::FileSystemContext* context,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) const override;
|
||||
std::unique_ptr<storage::FileStreamWriter> CreateFileStreamWriter(
|
||||
const storage::FileSystemURL& url,
|
||||
int64_t offset,
|
||||
|
@ -3,6 +3,9 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "components/file_access/scoped_file_access.h"
|
||||
|
||||
namespace file_access {
|
||||
// static
|
||||
@ -35,6 +38,21 @@ void ScopedFileAccessDelegate::RequestFilesAccessForSystemIO(
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
ScopedFileAccessDelegate::GetCallbackForSystem() {
|
||||
return base::BindRepeating(
|
||||
[](const std::vector<base::FilePath>& file_paths,
|
||||
base::OnceCallback<void(ScopedFileAccess)> callback) {
|
||||
if (request_files_access_for_system_io_callback_) {
|
||||
request_files_access_for_system_io_callback_->Run(
|
||||
file_paths, std::move(callback));
|
||||
} else {
|
||||
std::move(callback).Run(ScopedFileAccess::Allowed());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ScopedFileAccessDelegate::ScopedFileAccessDelegate() {
|
||||
if (scoped_file_access_delegate_) {
|
||||
delete scoped_file_access_delegate_;
|
||||
@ -53,18 +71,18 @@ ScopedFileAccessDelegate*
|
||||
ScopedFileAccessDelegate::scoped_file_access_delegate_ = nullptr;
|
||||
|
||||
// static
|
||||
ScopedFileAccessDelegate::RequestFilesAccessForSystemIOCallback*
|
||||
ScopedFileAccessDelegate::RequestFilesAccessIOCallback*
|
||||
ScopedFileAccessDelegate::request_files_access_for_system_io_callback_ =
|
||||
nullptr;
|
||||
|
||||
ScopedFileAccessDelegate::ScopedRequestFilesAccessCallbackForTesting::
|
||||
ScopedRequestFilesAccessCallbackForTesting(
|
||||
RequestFilesAccessForSystemIOCallback callback,
|
||||
RequestFilesAccessIOCallback callback,
|
||||
bool restore_original_callback)
|
||||
: restore_original_callback_(restore_original_callback) {
|
||||
original_callback_ = request_files_access_for_system_io_callback_;
|
||||
request_files_access_for_system_io_callback_ =
|
||||
new RequestFilesAccessForSystemIOCallback(std::move(callback));
|
||||
new RequestFilesAccessIOCallback(std::move(callback));
|
||||
}
|
||||
|
||||
ScopedFileAccessDelegate::ScopedRequestFilesAccessCallbackForTesting::
|
||||
|
@ -29,7 +29,7 @@ namespace file_access {
|
||||
// to packages without direct access to the UI thread.
|
||||
class COMPONENT_EXPORT(FILE_ACCESS) ScopedFileAccessDelegate {
|
||||
public:
|
||||
using RequestFilesAccessForSystemIOCallback =
|
||||
using RequestFilesAccessIOCallback =
|
||||
base::RepeatingCallback<void(const std::vector<base::FilePath>&,
|
||||
base::OnceCallback<void(ScopedFileAccess)>)>;
|
||||
|
||||
@ -62,6 +62,12 @@ class COMPONENT_EXPORT(FILE_ACCESS) ScopedFileAccessDelegate {
|
||||
const std::vector<base::FilePath>& files,
|
||||
base::OnceCallback<void(file_access::ScopedFileAccess)> callback) = 0;
|
||||
|
||||
// Creates a callback to gain file access for the given `destination`. The
|
||||
// callback should be called on the IO thread. The method itself from the UI
|
||||
// thread.
|
||||
virtual RequestFilesAccessIOCallback CreateFileAccessCallback(
|
||||
const GURL& destination) const = 0;
|
||||
|
||||
// Called from the IO thread. Switches to the UI thread and calls
|
||||
// RequestFilesAccessForSystem there. The `callback` is run on the IO thread
|
||||
// again.
|
||||
@ -105,7 +111,7 @@ class COMPONENT_EXPORT(FILE_ACCESS) ScopedFileAccessDelegate {
|
||||
// Otherwise, it destroys the original callback when this class is
|
||||
// destroyed.
|
||||
explicit ScopedRequestFilesAccessCallbackForTesting(
|
||||
RequestFilesAccessForSystemIOCallback callback,
|
||||
RequestFilesAccessIOCallback callback,
|
||||
bool restore_original_callback = true);
|
||||
|
||||
virtual ~ScopedRequestFilesAccessCallbackForTesting();
|
||||
@ -121,8 +127,12 @@ class COMPONENT_EXPORT(FILE_ACCESS) ScopedFileAccessDelegate {
|
||||
|
||||
private:
|
||||
bool restore_original_callback_;
|
||||
RequestFilesAccessForSystemIOCallback* original_callback_ = nullptr;
|
||||
RequestFilesAccessIOCallback* original_callback_ = nullptr;
|
||||
};
|
||||
// Get a callback to get file access to files for system component
|
||||
// destination. Can be called from IO or UI thread. The callback should be
|
||||
// called on IO thread only.
|
||||
static RequestFilesAccessIOCallback GetCallbackForSystem();
|
||||
|
||||
protected:
|
||||
ScopedFileAccessDelegate();
|
||||
@ -136,7 +146,7 @@ class COMPONENT_EXPORT(FILE_ACCESS) ScopedFileAccessDelegate {
|
||||
// A single instance for a callback living on the IO thread which switches to
|
||||
// the UI thread to call RequestFilesAccessForSystem from there and switch
|
||||
// back to IO thread handing the ScopedFileAccess to another (given) callback.
|
||||
static RequestFilesAccessForSystemIOCallback*
|
||||
static RequestFilesAccessIOCallback*
|
||||
request_files_access_for_system_io_callback_;
|
||||
};
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_forward.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/location.h"
|
||||
#include "base/test/mock_callback.h"
|
||||
#include "base/test/task_environment.h"
|
||||
@ -30,6 +31,10 @@ class ScopedFileAccessDelegateTestInstance : public ScopedFileAccessDelegate {
|
||||
void RequestFilesAccessForSystem(
|
||||
const std::vector<base::FilePath>& files,
|
||||
base::OnceCallback<void(ScopedFileAccess)> callback) override {}
|
||||
RequestFilesAccessIOCallback CreateFileAccessCallback(
|
||||
const GURL& destination) const override {
|
||||
return base::DoNothing();
|
||||
}
|
||||
};
|
||||
int ScopedFileAccessDelegateTestInstance::instance_counter = 0;
|
||||
|
||||
|
@ -25,6 +25,10 @@ class MockScopedFileAccessDelegate : public ScopedFileAccessDelegate {
|
||||
(const std::vector<base::FilePath>&,
|
||||
base::OnceCallback<void(ScopedFileAccess)>),
|
||||
(override));
|
||||
MOCK_METHOD((RequestFilesAccessIOCallback),
|
||||
CreateFileAccessCallback,
|
||||
(const GURL& destination),
|
||||
(const override));
|
||||
};
|
||||
} // namespace file_access
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "base/feature_list.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
|
||||
#include "content/browser/child_process_security_policy_impl.h"
|
||||
#include "content/public/browser/browser_task_traits.h"
|
||||
@ -31,6 +32,11 @@ class BindingDelegate : public storage::BlobRegistryImpl::Delegate {
|
||||
bool CanAccessDataForOrigin(const url::Origin& origin) override {
|
||||
return security_policy_handle_.CanAccessDataForOrigin(origin);
|
||||
}
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
GetAccessCallback() override {
|
||||
// TODO (b/262203074) create actual callback
|
||||
return base::NullCallback();
|
||||
}
|
||||
|
||||
private:
|
||||
ChildProcessSecurityPolicyImpl::Handle security_policy_handle_;
|
||||
|
@ -12,11 +12,13 @@
|
||||
#include "base/files/file_enumerator.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/guid.h"
|
||||
#include "base/supports_user_data.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "base/task/task_runner.h"
|
||||
#include "base/task/thread_pool.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "content/browser/storage_partition_impl.h"
|
||||
#include "content/public/browser/blob_handle.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
@ -214,14 +216,16 @@ std::unique_ptr<BlobHandle> ChromeBlobStorageContext::CreateMemoryBackedBlob(
|
||||
return blob_handle;
|
||||
}
|
||||
|
||||
void ChromeBlobStorageContext::CreateFileSystemBlob(
|
||||
void ChromeBlobStorageContext::CreateFileSystemBlobWithFileAccess(
|
||||
scoped_refptr<storage::FileSystemContext> file_system_context,
|
||||
mojo::PendingReceiver<blink::mojom::Blob> blob_receiver,
|
||||
const storage::FileSystemURL& url,
|
||||
const std::string& blob_uuid,
|
||||
const std::string& content_type,
|
||||
const uint64_t file_size,
|
||||
const base::Time& file_modification_time) {
|
||||
const base::Time& file_modification_time,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
|
||||
auto blob_builder = std::make_unique<storage::BlobDataBuilder>(blob_uuid);
|
||||
@ -229,9 +233,9 @@ void ChromeBlobStorageContext::CreateFileSystemBlob(
|
||||
// Use AppendFileSystemFile here, since we're streaming the file directly
|
||||
// from the file system backend, and the file thus might not actually be
|
||||
// backed by a file on disk.
|
||||
blob_builder->AppendFileSystemFile(url, 0, file_size,
|
||||
file_modification_time,
|
||||
std::move(file_system_context));
|
||||
blob_builder->AppendFileSystemFile(
|
||||
url, 0, file_size, file_modification_time,
|
||||
std::move(file_system_context), std::move(file_access));
|
||||
}
|
||||
blob_builder->set_content_type(content_type);
|
||||
|
||||
@ -245,6 +249,19 @@ void ChromeBlobStorageContext::CreateFileSystemBlob(
|
||||
storage::BlobImpl::Create(std::move(blob_handle), std::move(blob_receiver));
|
||||
}
|
||||
|
||||
void ChromeBlobStorageContext::CreateFileSystemBlob(
|
||||
scoped_refptr<storage::FileSystemContext> file_system_context,
|
||||
mojo::PendingReceiver<blink::mojom::Blob> blob_receiver,
|
||||
const storage::FileSystemURL& url,
|
||||
const std::string& blob_uuid,
|
||||
const std::string& content_type,
|
||||
const uint64_t file_size,
|
||||
const base::Time& file_modification_time) {
|
||||
CreateFileSystemBlobWithFileAccess(
|
||||
file_system_context, std::move(blob_receiver), url, blob_uuid,
|
||||
content_type, file_size, file_modification_time, base::NullCallback());
|
||||
}
|
||||
|
||||
// static
|
||||
scoped_refptr<network::SharedURLLoaderFactory>
|
||||
ChromeBlobStorageContext::URLLoaderFactoryForToken(
|
||||
|
@ -12,10 +12,12 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/task/sequenced_task_runner_helpers.h"
|
||||
#include "base/time/time.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "content/common/content_export.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
@ -78,6 +80,23 @@ class CONTENT_EXPORT ChromeBlobStorageContext
|
||||
base::span<const uint8_t> data,
|
||||
const std::string& content_type);
|
||||
|
||||
// Creates a FileSystem File blob accessible by the renderer via the blob
|
||||
// remote corresponding to `blob_receiver`. The callback can grant or deny the
|
||||
// read access to the file. The callback `file_access` is used to grant or
|
||||
// deny access to files under dlp restrictions. Leaving it at NullCallback
|
||||
// will lead to default behaviour, which currently is granting it (until
|
||||
// b/265908846 is done).
|
||||
void CreateFileSystemBlobWithFileAccess(
|
||||
scoped_refptr<storage::FileSystemContext> file_system_context,
|
||||
mojo::PendingReceiver<blink::mojom::Blob> blob_receiver,
|
||||
const storage::FileSystemURL& url,
|
||||
const std::string& blob_uuid,
|
||||
const std::string& content_type,
|
||||
const uint64_t file_size,
|
||||
const base::Time& file_modification_time,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access);
|
||||
|
||||
// Creates a FileSystem File blob accessible by the renderer via the blob
|
||||
// remote corresponding to `blob_receiver`.
|
||||
void CreateFileSystemBlob(
|
||||
|
@ -5,6 +5,7 @@ import("//testing/test.gni")
|
||||
|
||||
test("storage_unittests") {
|
||||
deps = [
|
||||
"//components/file_access:test_support",
|
||||
"//storage/browser:unittests",
|
||||
"//storage/common:unittests",
|
||||
]
|
||||
|
@ -351,6 +351,7 @@ source_set("unittests") {
|
||||
"//base/test:test_support",
|
||||
"//build:chromeos_buildflags",
|
||||
"//components/file_access:file_access",
|
||||
"//components/file_access:test_support",
|
||||
"//components/services/filesystem/public/mojom",
|
||||
"//components/services/storage/public/cpp",
|
||||
"//mojo/public/cpp/system",
|
||||
@ -420,6 +421,7 @@ static_library("test_support") {
|
||||
":browser",
|
||||
"//base/test:test_support",
|
||||
"//build:chromeos_buildflags",
|
||||
"//components/file_access:file_access",
|
||||
"//components/services/storage/public/cpp",
|
||||
"//components/services/storage/public/mojom",
|
||||
"//net:test_support",
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/time/time.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "storage/browser/blob/blob_entry.h"
|
||||
#include "storage/browser/blob/blob_storage_registry.h"
|
||||
#include "storage/browser/blob/shareable_blob_data_item.h"
|
||||
@ -146,13 +147,16 @@ BlobDataBuilder::FutureFile BlobDataBuilder::AppendFutureFile(
|
||||
return FutureFile(std::move(item));
|
||||
}
|
||||
|
||||
void BlobDataBuilder::AppendFile(const FilePath& file_path,
|
||||
uint64_t offset,
|
||||
uint64_t length,
|
||||
const base::Time& expected_modification_time) {
|
||||
auto item = BlobDataItem::CreateFile(file_path, offset, length,
|
||||
expected_modification_time,
|
||||
ShareableFileReference::Get(file_path));
|
||||
void BlobDataBuilder::AppendFile(
|
||||
const FilePath& file_path,
|
||||
uint64_t offset,
|
||||
uint64_t length,
|
||||
const base::Time& expected_modification_time,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) {
|
||||
auto item = BlobDataItem::CreateFile(
|
||||
file_path, offset, length, expected_modification_time,
|
||||
ShareableFileReference::Get(file_path), std::move(file_access));
|
||||
DCHECK(!item->IsFutureFileItem()) << file_path.value();
|
||||
|
||||
auto shareable_item = base::MakeRefCounted<ShareableBlobDataItem>(
|
||||
@ -277,7 +281,8 @@ void BlobDataBuilder::SliceBlob(const BlobEntry* source,
|
||||
case BlobDataItem::Type::kFile: {
|
||||
data_item = BlobDataItem::CreateFile(
|
||||
source_item->path(), source_item->offset() + item_offset, read_size,
|
||||
source_item->expected_modification_time(), source_item->file_ref_);
|
||||
source_item->expected_modification_time(), source_item->file_ref_,
|
||||
source_item->file_access_);
|
||||
|
||||
if (source_item->IsFutureFileItem()) {
|
||||
// The source file isn't a real file yet (path is fake), so store the
|
||||
@ -290,7 +295,7 @@ void BlobDataBuilder::SliceBlob(const BlobEntry* source,
|
||||
data_item = BlobDataItem::CreateFileFilesystem(
|
||||
source_item->filesystem_url(), source_item->offset() + item_offset,
|
||||
read_size, source_item->expected_modification_time(),
|
||||
source_item->file_system_context());
|
||||
source_item->file_system_context(), source_item->file_access_);
|
||||
break;
|
||||
}
|
||||
case BlobDataItem::Type::kReadableDataHandle: {
|
||||
@ -320,11 +325,13 @@ void BlobDataBuilder::AppendFileSystemFile(
|
||||
uint64_t offset,
|
||||
uint64_t length,
|
||||
const base::Time& expected_modification_time,
|
||||
scoped_refptr<FileSystemContext> file_system_context) {
|
||||
scoped_refptr<FileSystemContext> file_system_context,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) {
|
||||
DCHECK_GT(length, 0ul);
|
||||
auto item = BlobDataItem::CreateFileFilesystem(
|
||||
url, offset, length, expected_modification_time,
|
||||
std::move(file_system_context));
|
||||
std::move(file_system_context), std::move(file_access));
|
||||
|
||||
auto shareable_item = base::MakeRefCounted<ShareableBlobDataItem>(
|
||||
std::move(item), ShareableBlobDataItem::POPULATED_WITHOUT_QUOTA);
|
||||
|
@ -13,8 +13,10 @@
|
||||
|
||||
#include "base/component_export.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/numerics/checked_math.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "components/services/storage/public/mojom/blob_storage_context.mojom.h"
|
||||
#include "storage/browser/blob/blob_data_item.h"
|
||||
#include "storage/browser/blob/blob_data_snapshot.h"
|
||||
@ -132,11 +134,17 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobDataBuilder {
|
||||
|
||||
// You must know the length of the file, you cannot use kuint64max to specify
|
||||
// the whole file. This method creates a ShareableFileReference to the given
|
||||
// file, which is stored in this builder.
|
||||
void AppendFile(const base::FilePath& file_path,
|
||||
uint64_t offset,
|
||||
uint64_t length,
|
||||
const base::Time& expected_modification_time);
|
||||
// file, which is stored in this builder. The callback `file_access` is used
|
||||
// to grant or deny access to files under dlp restrictions. Leaving it at
|
||||
// NullCallback will lead to default behaviour, which currently is granting it
|
||||
// (until b/265908846 is done).
|
||||
void AppendFile(
|
||||
const base::FilePath& file_path,
|
||||
uint64_t offset,
|
||||
uint64_t length,
|
||||
const base::Time& expected_modification_time,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access = base::NullCallback());
|
||||
|
||||
void AppendBlob(const std::string& uuid,
|
||||
uint64_t offset,
|
||||
@ -150,7 +158,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobDataBuilder {
|
||||
uint64_t offset,
|
||||
uint64_t length,
|
||||
const base::Time& expected_modification_time,
|
||||
scoped_refptr<FileSystemContext> file_system_context);
|
||||
scoped_refptr<FileSystemContext> file_system_context,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access = base::NullCallback());
|
||||
|
||||
void AppendReadableDataHandle(scoped_refptr<DataHandle> data_handle) {
|
||||
auto length = data_handle->GetSize();
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include "base/ranges/algorithm.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/time/time.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
#include "net/base/net_errors.h"
|
||||
#include "services/network/public/cpp/data_pipe_to_source_stream.h"
|
||||
@ -80,8 +82,12 @@ scoped_refptr<BlobDataItem> BlobDataItem::CreateBytesDescription(
|
||||
}
|
||||
|
||||
// static
|
||||
scoped_refptr<BlobDataItem> BlobDataItem::CreateFile(base::FilePath path) {
|
||||
return CreateFile(path, 0, blink::BlobUtils::kUnknownSize);
|
||||
scoped_refptr<BlobDataItem> BlobDataItem::CreateFile(
|
||||
base::FilePath path,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) {
|
||||
return CreateFile(path, 0, blink::BlobUtils::kUnknownSize, base::Time(),
|
||||
nullptr, std::move(file_access));
|
||||
}
|
||||
|
||||
// static
|
||||
@ -90,12 +96,15 @@ scoped_refptr<BlobDataItem> BlobDataItem::CreateFile(
|
||||
uint64_t offset,
|
||||
uint64_t length,
|
||||
base::Time expected_modification_time,
|
||||
scoped_refptr<ShareableFileReference> file_ref) {
|
||||
scoped_refptr<ShareableFileReference> file_ref,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) {
|
||||
auto item =
|
||||
base::WrapRefCounted(new BlobDataItem(Type::kFile, offset, length));
|
||||
item->path_ = std::move(path);
|
||||
item->expected_modification_time_ = std::move(expected_modification_time);
|
||||
item->file_ref_ = std::move(file_ref);
|
||||
item->file_access_ = std::move(file_access);
|
||||
// TODO(mek): DCHECK(!item->IsFutureFileItem()) when BlobDataBuilder has some
|
||||
// other way of slicing a future file.
|
||||
return item;
|
||||
@ -120,12 +129,15 @@ scoped_refptr<BlobDataItem> BlobDataItem::CreateFileFilesystem(
|
||||
uint64_t offset,
|
||||
uint64_t length,
|
||||
base::Time expected_modification_time,
|
||||
scoped_refptr<FileSystemContext> file_system_context) {
|
||||
scoped_refptr<FileSystemContext> file_system_context,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) {
|
||||
auto item = base::WrapRefCounted(
|
||||
new BlobDataItem(Type::kFileFilesystem, offset, length));
|
||||
item->filesystem_url_ = url;
|
||||
item->expected_modification_time_ = std::move(expected_modification_time);
|
||||
item->file_system_context_ = std::move(file_system_context);
|
||||
item->file_access_ = std::move(file_access);
|
||||
return item;
|
||||
}
|
||||
|
||||
|
@ -14,8 +14,11 @@
|
||||
#include "base/component_export.h"
|
||||
#include "base/containers/span.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/time/time.h"
|
||||
#include "components/file_access/scoped_file_access.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "components/services/storage/public/mojom/blob_storage_context.mojom.h"
|
||||
#include "net/base/io_buffer.h"
|
||||
#include "storage/browser/blob/shareable_file_reference.h"
|
||||
@ -83,13 +86,18 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobDataItem
|
||||
static scoped_refptr<BlobDataItem> CreateBytes(
|
||||
base::span<const uint8_t> bytes);
|
||||
static scoped_refptr<BlobDataItem> CreateBytesDescription(size_t length);
|
||||
static scoped_refptr<BlobDataItem> CreateFile(base::FilePath path);
|
||||
static scoped_refptr<BlobDataItem> CreateFile(
|
||||
base::FilePath path,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access = base::NullCallback());
|
||||
static scoped_refptr<BlobDataItem> CreateFile(
|
||||
base::FilePath path,
|
||||
uint64_t offset,
|
||||
uint64_t length,
|
||||
base::Time expected_modification_time = base::Time(),
|
||||
scoped_refptr<ShareableFileReference> file_ref = nullptr);
|
||||
scoped_refptr<ShareableFileReference> file_ref = nullptr,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access = base::NullCallback());
|
||||
static scoped_refptr<BlobDataItem> CreateFutureFile(uint64_t offset,
|
||||
uint64_t length,
|
||||
uint64_t file_id);
|
||||
@ -98,7 +106,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobDataItem
|
||||
uint64_t offset,
|
||||
uint64_t length,
|
||||
base::Time expected_modification_time,
|
||||
scoped_refptr<FileSystemContext> file_system_context);
|
||||
scoped_refptr<FileSystemContext> file_system_context,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access = base::NullCallback());
|
||||
static scoped_refptr<BlobDataItem> CreateReadableDataHandle(
|
||||
scoped_refptr<DataHandle> data_handle,
|
||||
uint64_t offset,
|
||||
@ -146,6 +156,12 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobDataItem
|
||||
// Returns |file_id| given to CreateFutureFile.
|
||||
uint64_t GetFutureFileID() const;
|
||||
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access() const {
|
||||
DCHECK(type_ == Type::kFile || type_ == Type::kFileFilesystem);
|
||||
return file_access_;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class BlobBuilderFromStream;
|
||||
friend class BlobDataBuilder;
|
||||
@ -195,6 +211,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobDataItem
|
||||
|
||||
scoped_refptr<FileSystemContext>
|
||||
file_system_context_; // For Type::kFileFilesystem.
|
||||
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access_; // For Type::kFile and kFileFilesystem.
|
||||
};
|
||||
|
||||
COMPONENT_EXPORT(STORAGE_BROWSER)
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/task/thread_pool.h"
|
||||
#include "base/trace_event/trace_event.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "net/base/io_buffer.h"
|
||||
#include "net/base/net_errors.h"
|
||||
#include "storage/browser/blob/blob_data_handle.h"
|
||||
@ -515,8 +516,7 @@ BlobReader::Status BlobReader::ReadItem() {
|
||||
GetOrCreateFileReaderAtIndex(current_item_index_);
|
||||
if (!reader)
|
||||
return ReportError(net::ERR_FILE_NOT_FOUND);
|
||||
|
||||
return ReadFileItem(reader, bytes_to_read);
|
||||
return ReadFileItem(reader, bytes_to_read, item.file_access());
|
||||
}
|
||||
|
||||
void BlobReader::AdvanceItem() {
|
||||
@ -560,8 +560,11 @@ void BlobReader::ReadBytesItem(const BlobDataItem& item, int bytes_to_read) {
|
||||
AdvanceBytesRead(bytes_to_read);
|
||||
}
|
||||
|
||||
BlobReader::Status BlobReader::ReadFileItem(FileStreamReader* reader,
|
||||
int bytes_to_read) {
|
||||
BlobReader::Status BlobReader::ReadFileItem(
|
||||
FileStreamReader* reader,
|
||||
int bytes_to_read,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
DCHECK(!io_pending_)
|
||||
<< "Can't begin IO while another IO operation is pending.";
|
||||
@ -725,7 +728,8 @@ std::unique_ptr<FileStreamReader> BlobReader::CreateFileStreamReader(
|
||||
}
|
||||
return FileStreamReader::CreateForLocalFile(
|
||||
file_task_runner_.get(), item.path(),
|
||||
item.offset() + additional_offset, item.expected_modification_time());
|
||||
item.offset() + additional_offset, item.expected_modification_time(),
|
||||
item.file_access());
|
||||
case BlobDataItem::Type::kFileFilesystem: {
|
||||
int64_t max_bytes_to_read =
|
||||
item.length() == std::numeric_limits<uint64_t>::max()
|
||||
@ -738,7 +742,8 @@ std::unique_ptr<FileStreamReader> BlobReader::CreateFileStreamReader(
|
||||
}
|
||||
return item.file_system_context()->CreateFileStreamReader(
|
||||
item.filesystem_url(), item.offset() + additional_offset,
|
||||
max_bytes_to_read, item.expected_modification_time());
|
||||
max_bytes_to_read, item.expected_modification_time(),
|
||||
item.file_access());
|
||||
}
|
||||
case BlobDataItem::Type::kBytes:
|
||||
case BlobDataItem::Type::kBytesDescription:
|
||||
|
@ -13,9 +13,13 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/component_export.h"
|
||||
#include "base/functional/callback_forward.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/gtest_prod_util.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/sequence_checker.h"
|
||||
#include "components/file_access/scoped_file_access.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "mojo/public/cpp/base/big_buffer.h"
|
||||
#include "mojo/public/cpp/system/data_pipe.h"
|
||||
#include "net/base/completion_once_callback.h"
|
||||
@ -168,7 +172,7 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobReader {
|
||||
FRIEND_TEST_ALL_PREFIXES(BlobReaderTest, HandleBeforeAsyncCancel);
|
||||
FRIEND_TEST_ALL_PREFIXES(BlobReaderTest, ReadFromIncompleteBlob);
|
||||
|
||||
BlobReader(const BlobDataHandle* blob_handle);
|
||||
explicit BlobReader(const BlobDataHandle* blob_handle);
|
||||
|
||||
bool total_size_calculated() const {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
@ -208,7 +212,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobReader {
|
||||
void AdvanceItem();
|
||||
void AdvanceBytesRead(int result);
|
||||
void ReadBytesItem(const BlobDataItem& item, int bytes_to_read);
|
||||
BlobReader::Status ReadFileItem(FileStreamReader* reader, int bytes_to_read);
|
||||
BlobReader::Status ReadFileItem(
|
||||
FileStreamReader* reader,
|
||||
int bytes_to_read,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access);
|
||||
void DidReadFile(int result);
|
||||
void DeleteItemReaders();
|
||||
Status ReadReadableDataHandle(const BlobDataItem& item, int bytes_to_read);
|
||||
|
@ -8,9 +8,12 @@
|
||||
|
||||
#include "base/barrier_closure.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/task/sequenced_task_runner.h"
|
||||
#include "components/file_access/scoped_file_access.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "net/base/features.h"
|
||||
#include "storage/browser/blob/blob_builder_from_stream.h"
|
||||
#include "storage/browser/blob/blob_data_builder.h"
|
||||
@ -57,17 +60,21 @@ class BlobRegistryImpl::BlobUnderConstruction {
|
||||
mojo::Remote<blink::mojom::Blob> blob;
|
||||
};
|
||||
|
||||
BlobUnderConstruction(BlobRegistryImpl* blob_registry,
|
||||
const std::string& uuid,
|
||||
const std::string& content_type,
|
||||
const std::string& content_disposition,
|
||||
std::vector<ElementEntry> elements,
|
||||
mojo::ReportBadMessageCallback bad_message_callback)
|
||||
BlobUnderConstruction(
|
||||
BlobRegistryImpl* blob_registry,
|
||||
const std::string& uuid,
|
||||
const std::string& content_type,
|
||||
const std::string& content_disposition,
|
||||
std::vector<ElementEntry> elements,
|
||||
mojo::ReportBadMessageCallback bad_message_callback,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access)
|
||||
: blob_registry_(blob_registry),
|
||||
uuid_(uuid),
|
||||
builder_(std::make_unique<BlobDataBuilder>(uuid)),
|
||||
elements_(std::move(elements)),
|
||||
bad_message_callback_(std::move(bad_message_callback)) {
|
||||
bad_message_callback_(std::move(bad_message_callback)),
|
||||
file_access_(std::move(file_access)) {
|
||||
builder_->set_content_type(content_type);
|
||||
builder_->set_content_disposition(content_disposition);
|
||||
}
|
||||
@ -213,6 +220,10 @@ class BlobRegistryImpl::BlobUnderConstruction {
|
||||
// Number of dependent blobs that have started constructing.
|
||||
size_t ready_dependent_blob_count_ = 0;
|
||||
|
||||
// Callback to gain dlp file access.
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access_;
|
||||
|
||||
base::WeakPtrFactory<BlobUnderConstruction> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
@ -383,9 +394,9 @@ void BlobRegistryImpl::BlobUnderConstruction::ResolvedAllBlobDependencies() {
|
||||
}
|
||||
} else if (element->is_file()) {
|
||||
const auto& f = element->get_file();
|
||||
builder_->AppendFile(
|
||||
f->path, f->offset, f->length,
|
||||
f->expected_modification_time.value_or(base::Time()));
|
||||
builder_->AppendFile(f->path, f->offset, f->length,
|
||||
f->expected_modification_time.value_or(base::Time()),
|
||||
file_access_);
|
||||
} else if (element->is_blob()) {
|
||||
DCHECK(blob_uuid_it != referenced_blob_uuids_.end());
|
||||
const std::string& blob_uuid = *blob_uuid_it++;
|
||||
@ -565,7 +576,7 @@ void BlobRegistryImpl::Register(
|
||||
|
||||
blobs_under_construction_[uuid] = std::make_unique<BlobUnderConstruction>(
|
||||
this, uuid, content_type, content_disposition, std::move(element_entries),
|
||||
receivers_.GetBadMessageCallback());
|
||||
receivers_.GetBadMessageCallback(), delegate->GetAccessCallback());
|
||||
|
||||
std::unique_ptr<BlobDataHandle> handle = context_->AddFutureBlob(
|
||||
uuid, content_type, content_disposition,
|
||||
|
@ -9,6 +9,9 @@
|
||||
#include "base/component_export.h"
|
||||
#include "base/containers/flat_set.h"
|
||||
#include "base/containers/unique_ptr_adapters.h"
|
||||
#include "base/functional/callback_forward.h"
|
||||
#include "components/file_access/scoped_file_access.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "mojo/public/cpp/bindings/receiver_set.h"
|
||||
#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
|
||||
#include "storage/browser/blob/blob_url_registry.h"
|
||||
@ -35,6 +38,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobRegistryImpl
|
||||
virtual ~Delegate() {}
|
||||
virtual bool CanReadFile(const base::FilePath& file) = 0;
|
||||
virtual bool CanAccessDataForOrigin(const url::Origin& origin) = 0;
|
||||
virtual file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
GetAccessCallback() = 0;
|
||||
};
|
||||
|
||||
BlobRegistryImpl(base::WeakPtr<BlobStorageContext> context,
|
||||
|
@ -530,8 +530,8 @@ void BlobStorageContext::FinishBuilding(BlobEntry* entry) {
|
||||
scoped_refptr<BlobDataItem> new_item = BlobDataItem::CreateFile(
|
||||
source_item->path(),
|
||||
source_item->offset() + copy.source_item_offset, dest_size,
|
||||
source_item->expected_modification_time(),
|
||||
source_item->file_ref_);
|
||||
source_item->expected_modification_time(), source_item->file_ref_,
|
||||
source_item->file_access_);
|
||||
copy.dest_item->set_item(std::move(new_item));
|
||||
break;
|
||||
}
|
||||
|
@ -12,7 +12,11 @@
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/component_export.h"
|
||||
#include "base/files/file.h"
|
||||
#include "base/functional/callback_forward.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "components/file_access/scoped_file_access.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "components/services/storage/public/cpp/filesystem/filesystem_proxy.h"
|
||||
#include "net/base/completion_once_callback.h"
|
||||
|
||||
@ -45,7 +49,9 @@ class FileStreamReader {
|
||||
scoped_refptr<base::TaskRunner> task_runner,
|
||||
const base::FilePath& file_path,
|
||||
int64_t initial_offset,
|
||||
const base::Time& expected_modification_time);
|
||||
const base::Time& expected_modification_time,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access = base::NullCallback());
|
||||
|
||||
// Creates a new FileReader for a local file |file_path|, which is a
|
||||
// relative path into |filesystem_proxy|. This function's behavior
|
||||
|
@ -16,7 +16,9 @@
|
||||
#include "base/files/file.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/functional/callback_forward.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "storage/browser/file_system/file_permission_policy.h"
|
||||
#include "storage/browser/file_system/file_stream_reader.h"
|
||||
#include "storage/browser/file_system/open_file_system_mode.h"
|
||||
#include "storage/browser/file_system/task_runner_bound_observer_list.h"
|
||||
#include "storage/common/file_system/file_system_types.h"
|
||||
@ -121,13 +123,17 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemBackend {
|
||||
// ERR_UPLOAD_FILE_CHANGED error.
|
||||
// This method itself does *not* check if the given path exists and is a
|
||||
// regular file. At most |max_bytes_to_read| can be fetched from the file
|
||||
// stream reader.
|
||||
// stream reader. The callback `file_access` grants access to dlp restricted
|
||||
// files. If it is a NullCallback currently the access will be granted. This
|
||||
// will change to being denied after b/265908846
|
||||
virtual std::unique_ptr<FileStreamReader> CreateFileStreamReader(
|
||||
const FileSystemURL& url,
|
||||
int64_t offset,
|
||||
int64_t max_bytes_to_read,
|
||||
const base::Time& expected_modification_time,
|
||||
FileSystemContext* context) const = 0;
|
||||
FileSystemContext* context,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) const = 0;
|
||||
|
||||
// Creates a new file stream writer for a given filesystem URL |url| with an
|
||||
// offset |offset|.
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "base/task/sequenced_task_runner.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "base/types/pass_key.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "components/services/storage/public/cpp/buckets/bucket_info.h"
|
||||
#include "components/services/storage/public/cpp/buckets/constants.h"
|
||||
#include "components/services/storage/public/cpp/quota_client_callback_wrapper.h"
|
||||
@ -595,14 +596,17 @@ std::unique_ptr<FileStreamReader> FileSystemContext::CreateFileStreamReader(
|
||||
const FileSystemURL& url,
|
||||
int64_t offset,
|
||||
int64_t max_bytes_to_read,
|
||||
const base::Time& expected_modification_time) {
|
||||
const base::Time& expected_modification_time,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) {
|
||||
if (!url.is_valid())
|
||||
return nullptr;
|
||||
FileSystemBackend* backend = GetFileSystemBackend(url.type());
|
||||
if (!backend)
|
||||
return nullptr;
|
||||
return backend->CreateFileStreamReader(url, offset, max_bytes_to_read,
|
||||
expected_modification_time, this);
|
||||
expected_modification_time, this,
|
||||
std::move(file_access));
|
||||
}
|
||||
|
||||
std::unique_ptr<FileStreamWriter> FileSystemContext::CreateFileStreamWriter(
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "base/component_export.h"
|
||||
#include "base/files/file.h"
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/memory/ref_counted_delete_on_sequence.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
@ -22,6 +23,7 @@
|
||||
#include "base/threading/sequence_bound.h"
|
||||
#include "base/types/pass_key.h"
|
||||
#include "build/build_config.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "components/services/storage/public/cpp/quota_error_or.h"
|
||||
#include "components/services/storage/public/mojom/quota_client.mojom.h"
|
||||
#include "mojo/public/cpp/bindings/receiver.h"
|
||||
@ -281,7 +283,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemContext
|
||||
const FileSystemURL& url,
|
||||
int64_t offset,
|
||||
int64_t max_bytes_to_read,
|
||||
const base::Time& expected_modification_time);
|
||||
const base::Time& expected_modification_time,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access = base::NullCallback());
|
||||
|
||||
// Creates new FileStreamWriter instance to write into a file pointed by
|
||||
// `url` from `offset`.
|
||||
|
@ -129,10 +129,12 @@ IsolatedFileSystemBackend::CreateFileStreamReader(
|
||||
int64_t offset,
|
||||
int64_t max_bytes_to_read,
|
||||
const base::Time& expected_modification_time,
|
||||
FileSystemContext* context) const {
|
||||
FileSystemContext* context,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) const {
|
||||
return FileStreamReader::CreateForLocalFile(
|
||||
context->default_file_task_runner(), url.path(), offset,
|
||||
expected_modification_time);
|
||||
expected_modification_time, std::move(file_access));
|
||||
}
|
||||
|
||||
std::unique_ptr<FileStreamWriter>
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "storage/browser/file_system/file_system_backend.h"
|
||||
#include "storage/browser/file_system/task_runner_bound_observer_list.h"
|
||||
|
||||
@ -44,7 +45,9 @@ class IsolatedFileSystemBackend : public FileSystemBackend {
|
||||
int64_t offset,
|
||||
int64_t max_bytes_to_read,
|
||||
const base::Time& expected_modification_time,
|
||||
FileSystemContext* context) const override;
|
||||
FileSystemContext* context,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) const override;
|
||||
std::unique_ptr<FileStreamWriter> CreateFileStreamWriter(
|
||||
const FileSystemURL& url,
|
||||
int64_t offset,
|
||||
|
@ -12,11 +12,14 @@
|
||||
#include "base/check_op.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/location.h"
|
||||
#include "base/task/bind_post_task.h"
|
||||
#include "base/task/sequenced_task_runner.h"
|
||||
#include "base/task/task_runner.h"
|
||||
#include "base/types/pass_key.h"
|
||||
#include "components/file_access/scoped_file_access.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "net/base/file_stream.h"
|
||||
#include "net/base/io_buffer.h"
|
||||
@ -46,10 +49,13 @@ std::unique_ptr<FileStreamReader> FileStreamReader::CreateForLocalFile(
|
||||
scoped_refptr<base::TaskRunner> task_runner,
|
||||
const base::FilePath& file_path,
|
||||
int64_t initial_offset,
|
||||
const base::Time& expected_modification_time) {
|
||||
const base::Time& expected_modification_time,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) {
|
||||
return std::make_unique<LocalFileStreamReader>(
|
||||
std::move(task_runner), file_path, initial_offset,
|
||||
expected_modification_time, base::PassKey<FileStreamReader>());
|
||||
expected_modification_time, base::PassKey<FileStreamReader>(),
|
||||
std::move(file_access));
|
||||
}
|
||||
|
||||
LocalFileStreamReader::~LocalFileStreamReader() = default;
|
||||
@ -84,11 +90,14 @@ LocalFileStreamReader::LocalFileStreamReader(
|
||||
const base::FilePath& file_path,
|
||||
int64_t initial_offset,
|
||||
const base::Time& expected_modification_time,
|
||||
base::PassKey<FileStreamReader> /*pass_key*/)
|
||||
base::PassKey<FileStreamReader> /*pass_key*/,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access)
|
||||
: task_runner_(std::move(task_runner)),
|
||||
file_path_(file_path),
|
||||
initial_offset_(initial_offset),
|
||||
expected_modification_time_(expected_modification_time) {}
|
||||
expected_modification_time_(expected_modification_time),
|
||||
file_access_(std::move(file_access)) {}
|
||||
|
||||
void LocalFileStreamReader::Open(net::CompletionOnceCallback callback) {
|
||||
DCHECK(!has_pending_open_);
|
||||
@ -98,8 +107,12 @@ void LocalFileStreamReader::Open(net::CompletionOnceCallback callback) {
|
||||
base::OnceCallback<void(file_access::ScopedFileAccess)> open_cb =
|
||||
base::BindOnce(&LocalFileStreamReader::OnScopedFileAccessRequested,
|
||||
weak_factory_.GetWeakPtr(), std::move(callback));
|
||||
if (file_access_) {
|
||||
file_access_.Run({file_path_}, std::move(open_cb));
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(b/262199707 b/265908846): Replace with getting access through a
|
||||
// TODO(b/265908846): Replace with getting access through a
|
||||
// callback.
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessForSystemIO(
|
||||
{file_path_}, std::move(open_cb));
|
||||
|
@ -12,10 +12,13 @@
|
||||
#include "base/component_export.h"
|
||||
#include "base/files/file.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/functional/callback_forward.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/time/time.h"
|
||||
#include "base/types/pass_key.h"
|
||||
#include "components/file_access/scoped_file_access.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "net/base/completion_once_callback.h"
|
||||
#include "storage/browser/file_system/file_stream_reader.h"
|
||||
|
||||
@ -34,11 +37,14 @@ namespace storage {
|
||||
class COMPONENT_EXPORT(STORAGE_BROWSER) LocalFileStreamReader
|
||||
: public FileStreamReader {
|
||||
public:
|
||||
LocalFileStreamReader(scoped_refptr<base::TaskRunner> task_runner,
|
||||
const base::FilePath& file_path,
|
||||
int64_t initial_offset,
|
||||
const base::Time& expected_modification_time,
|
||||
base::PassKey<FileStreamReader> pass_key);
|
||||
LocalFileStreamReader(
|
||||
scoped_refptr<base::TaskRunner> task_runner,
|
||||
const base::FilePath& file_path,
|
||||
int64_t initial_offset,
|
||||
const base::Time& expected_modification_time,
|
||||
base::PassKey<FileStreamReader> pass_key,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access);
|
||||
~LocalFileStreamReader() override;
|
||||
|
||||
// FileStreamReader overrides.
|
||||
@ -76,6 +82,8 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) LocalFileStreamReader
|
||||
const int64_t initial_offset_;
|
||||
const base::Time expected_modification_time_;
|
||||
bool has_pending_open_ = false;
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access_;
|
||||
base::WeakPtrFactory<LocalFileStreamReader> weak_factory_{this};
|
||||
};
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/files/scoped_temp_dir.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_forward.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/location.h"
|
||||
#include "base/run_loop.h"
|
||||
@ -70,14 +71,23 @@ class LocalFileStreamReaderTest : public FileStreamReaderTest {
|
||||
file_thread_.Stop();
|
||||
base::RunLoop().RunUntilIdle();
|
||||
}
|
||||
|
||||
std::unique_ptr<FileStreamReader> CreateFileReader(
|
||||
const std::string& file_name,
|
||||
int64_t initial_offset,
|
||||
const base::Time& expected_modification_time) override {
|
||||
return CreateFileReader(file_name, initial_offset,
|
||||
expected_modification_time, base::NullCallback());
|
||||
}
|
||||
|
||||
std::unique_ptr<FileStreamReader> CreateFileReader(
|
||||
const std::string& file_name,
|
||||
int64_t initial_offset,
|
||||
const base::Time& expected_modification_time,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) {
|
||||
return FileStreamReader::CreateForLocalFile(
|
||||
file_task_runner(), test_dir().AppendASCII(file_name), initial_offset,
|
||||
expected_modification_time);
|
||||
expected_modification_time, std::move(file_access));
|
||||
}
|
||||
|
||||
void WriteFile(const std::string& file_name,
|
||||
@ -124,7 +134,7 @@ INSTANTIATE_TYPED_TEST_SUITE_P(Local,
|
||||
FileStreamReaderTypedTest,
|
||||
LocalFileStreamReaderTest);
|
||||
|
||||
// TODO(b/262199707 b/265908846): Replace direct call to
|
||||
// TODO(b/265908846): Replace direct call to
|
||||
// file_access::ScopedFileAccessDelegate with getting access through a callback.
|
||||
TEST_F(LocalFileStreamReaderTest, ReadAllowedByDataLeakPrevention) {
|
||||
this->WriteTestFile();
|
||||
@ -151,7 +161,7 @@ TEST_F(LocalFileStreamReaderTest, ReadAllowedByDataLeakPrevention) {
|
||||
ASSERT_EQ(this->kTestData, data);
|
||||
}
|
||||
|
||||
// TODO(b/262199707 b/265908846): Replace direct call to
|
||||
// TODO(b/265908846): Replace direct call to
|
||||
// file_access::ScopedFileAccessDelegate with getting access through a callback.
|
||||
TEST_F(LocalFileStreamReaderTest, ReadBlockedByDataLeakPrevention) {
|
||||
this->WriteTestFile();
|
||||
@ -178,4 +188,50 @@ TEST_F(LocalFileStreamReaderTest, ReadBlockedByDataLeakPrevention) {
|
||||
ASSERT_EQ("", data);
|
||||
}
|
||||
|
||||
TEST_F(LocalFileStreamReaderTest, ReadAllowedByDataLeakPreventionCallback) {
|
||||
this->WriteTestFile();
|
||||
base::MockRepeatingCallback<void(
|
||||
const std::vector<base::FilePath>&,
|
||||
base::OnceCallback<void(file_access::ScopedFileAccess)>)>
|
||||
callback;
|
||||
EXPECT_CALL(
|
||||
callback,
|
||||
Run(testing::ElementsAre(test_dir().AppendASCII(kTestFileName)), _))
|
||||
.WillOnce(base::test::RunOnceCallback<1>(CreateScopedFileAccess(true)));
|
||||
|
||||
std::unique_ptr<FileStreamReader> reader(this->CreateFileReader(
|
||||
std::string(this->kTestFileName), 0, this->test_file_modification_time(),
|
||||
callback.Get()));
|
||||
|
||||
int result = 0;
|
||||
std::string data;
|
||||
ReadFromReader(reader.get(), &data, this->kTestData.size(), &result);
|
||||
ASSERT_EQ(net::OK, result);
|
||||
ASSERT_EQ(this->kTestData, data);
|
||||
}
|
||||
|
||||
TEST_F(LocalFileStreamReaderTest, ReadBlockedByDataLeakPreventionCallback) {
|
||||
this->WriteTestFile();
|
||||
base::MockRepeatingCallback<void(
|
||||
const std::vector<base::FilePath>&,
|
||||
base::OnceCallback<void(file_access::ScopedFileAccess)>)>
|
||||
callback;
|
||||
file_access::ScopedFileAccessDelegate::
|
||||
ScopedRequestFilesAccessCallbackForTesting file_access_callback(
|
||||
callback.Get());
|
||||
EXPECT_CALL(
|
||||
callback,
|
||||
Run(testing::ElementsAre(test_dir().AppendASCII(kTestFileName)), _))
|
||||
.WillOnce(base::test::RunOnceCallback<1>(CreateScopedFileAccess(false)));
|
||||
std::unique_ptr<FileStreamReader> reader(this->CreateFileReader(
|
||||
std::string(this->kTestFileName), 0, this->test_file_modification_time(),
|
||||
callback.Get()));
|
||||
|
||||
int result = 0;
|
||||
std::string data;
|
||||
ReadFromReader(reader.get(), &data, this->kTestData.size(), &result);
|
||||
ASSERT_EQ(net::ERR_ACCESS_DENIED, result);
|
||||
ASSERT_EQ("", data);
|
||||
}
|
||||
|
||||
} // namespace storage
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/metrics/histogram.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "storage/browser/file_system/async_file_util_adapter.h"
|
||||
#include "storage/browser/file_system/copy_or_move_file_validator.h"
|
||||
#include "storage/browser/file_system/file_stream_reader.h"
|
||||
@ -137,7 +138,9 @@ SandboxFileSystemBackend::CreateFileStreamReader(
|
||||
int64_t offset,
|
||||
int64_t max_bytes_to_read,
|
||||
const base::Time& expected_modification_time,
|
||||
FileSystemContext* context) const {
|
||||
FileSystemContext* context,
|
||||
file_access::ScopedFileAccessDelegate::
|
||||
RequestFilesAccessIOCallback /*file_access*/) const {
|
||||
DCHECK(CanHandleType(url.type()));
|
||||
DCHECK(delegate_);
|
||||
return delegate_->CreateFileStreamReader(url, offset,
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/component_export.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "storage/browser/file_system/file_system_backend.h"
|
||||
#include "storage/browser/file_system/file_system_quota_util.h"
|
||||
#include "storage/browser/file_system/sandbox_file_system_backend_delegate.h"
|
||||
@ -58,7 +59,9 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) SandboxFileSystemBackend
|
||||
int64_t offset,
|
||||
int64_t max_bytes_to_read,
|
||||
const base::Time& expected_modification_time,
|
||||
FileSystemContext* context) const override;
|
||||
FileSystemContext* context,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) const override;
|
||||
std::unique_ptr<FileStreamWriter> CreateFileStreamWriter(
|
||||
const FileSystemURL& url,
|
||||
int64_t offset,
|
||||
|
@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "storage/browser/test/mock_blob_registry_delegate.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
|
||||
namespace storage {
|
||||
|
||||
@ -15,4 +16,9 @@ bool MockBlobRegistryDelegate::CanAccessDataForOrigin(
|
||||
return can_access_data_for_origin;
|
||||
}
|
||||
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
MockBlobRegistryDelegate::GetAccessCallback() {
|
||||
return base::DoNothing();
|
||||
}
|
||||
|
||||
} // namespace storage
|
||||
|
@ -19,6 +19,8 @@ class MockBlobRegistryDelegate
|
||||
|
||||
bool CanReadFile(const base::FilePath& file) override;
|
||||
bool CanAccessDataForOrigin(const url::Origin& origin) override;
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
GetAccessCallback() override;
|
||||
|
||||
bool can_read_file_result = true;
|
||||
bool can_access_data_for_origin = true;
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "base/task/sequenced_task_runner.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "storage/browser/file_system/copy_or_move_file_validator.h"
|
||||
#include "storage/browser/file_system/file_observers.h"
|
||||
#include "storage/browser/file_system/file_system_operation.h"
|
||||
@ -216,7 +217,9 @@ std::unique_ptr<FileStreamReader> TestFileSystemBackend::CreateFileStreamReader(
|
||||
int64_t offset,
|
||||
int64_t max_bytes_to_read,
|
||||
const base::Time& expected_modification_time,
|
||||
FileSystemContext* context) const {
|
||||
FileSystemContext* context,
|
||||
file_access::ScopedFileAccessDelegate::
|
||||
RequestFilesAccessIOCallback /*file_access*/) const {
|
||||
return std::make_unique<SandboxFileStreamReader>(context, url, offset,
|
||||
expected_modification_time);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "components/file_access/scoped_file_access_delegate.h"
|
||||
#include "storage/browser/file_system/async_file_util_adapter.h"
|
||||
#include "storage/browser/file_system/file_system_backend.h"
|
||||
#include "storage/browser/file_system/task_runner_bound_observer_list.h"
|
||||
@ -61,7 +62,9 @@ class TestFileSystemBackend : public FileSystemBackend {
|
||||
int64_t offset,
|
||||
int64_t max_bytes_to_read,
|
||||
const base::Time& expected_modification_time,
|
||||
FileSystemContext* context) const override;
|
||||
FileSystemContext* context,
|
||||
file_access::ScopedFileAccessDelegate::RequestFilesAccessIOCallback
|
||||
file_access) const override;
|
||||
std::unique_ptr<FileStreamWriter> CreateFileStreamWriter(
|
||||
const FileSystemURL& url,
|
||||
int64_t offset,
|
||||
|
Reference in New Issue
Block a user