Commit 1900d71b authored by Marijn Kruisselbrink's avatar Marijn Kruisselbrink Committed by Commit Bot

[FS] Pass PathType to ConfirmSensitiveDirectoryAccess.

External paths aren't absolute paths, and thus need to be treated
differently. Actually blocking paths (like the root of the Downloads
directory) seems to have been broken already, so for now this just
allows all external paths. We should add special chrome-os logic to
block what we do want to block in a follow-up.

Bug: 1009970, 1134029
Change-Id: I8e5e437698b619d9df643706119c8b3492f58476
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2442901Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarVictor Costan <pwnall@chromium.org>
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#820277}
parent d01b9662
...@@ -350,25 +350,29 @@ bool ChromeNativeFileSystemPermissionContext::CanObtainWritePermission( ...@@ -350,25 +350,29 @@ bool ChromeNativeFileSystemPermissionContext::CanObtainWritePermission(
void ChromeNativeFileSystemPermissionContext::ConfirmSensitiveDirectoryAccess( void ChromeNativeFileSystemPermissionContext::ConfirmSensitiveDirectoryAccess(
const url::Origin& origin, const url::Origin& origin,
const std::vector<base::FilePath>& paths, PathType path_type,
const base::FilePath& path,
HandleType handle_type, HandleType handle_type,
content::GlobalFrameRoutingId frame_id, content::GlobalFrameRoutingId frame_id,
base::OnceCallback<void(SensitiveDirectoryResult)> callback) { base::OnceCallback<void(SensitiveDirectoryResult)> callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (paths.empty()) {
// TODO(https://crbug.com/1009970): Figure out what external paths should be
// blocked. We could resolve the external path to a local path, and check for
// blocked directories based on that, but that doesn't work well. Instead we
// should have a separate Chrome OS only code path to block for example the
// root of certain external file systems.
if (path_type == PathType::kExternal) {
std::move(callback).Run(SensitiveDirectoryResult::kAllowed); std::move(callback).Run(SensitiveDirectoryResult::kAllowed);
return; return;
} }
// It is enough to only verify access to the first path, as multiple
// file selection is only supported if all files are in the same
// directory.
base::ThreadPool::PostTaskAndReplyWithResult( base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&ShouldBlockAccessToPath, paths[0], handle_type), base::BindOnce(&ShouldBlockAccessToPath, path, handle_type),
base::BindOnce(&ChromeNativeFileSystemPermissionContext:: base::BindOnce(&ChromeNativeFileSystemPermissionContext::
DidConfirmSensitiveDirectoryAccess, DidConfirmSensitiveDirectoryAccess,
GetWeakPtr(), origin, paths, handle_type, frame_id, GetWeakPtr(), origin, path, handle_type, frame_id,
std::move(callback))); std::move(callback)));
} }
...@@ -398,7 +402,7 @@ void ChromeNativeFileSystemPermissionContext::PerformAfterWriteChecks( ...@@ -398,7 +402,7 @@ void ChromeNativeFileSystemPermissionContext::PerformAfterWriteChecks(
void ChromeNativeFileSystemPermissionContext:: void ChromeNativeFileSystemPermissionContext::
DidConfirmSensitiveDirectoryAccess( DidConfirmSensitiveDirectoryAccess(
const url::Origin& origin, const url::Origin& origin,
const std::vector<base::FilePath>& paths, const base::FilePath& path,
HandleType handle_type, HandleType handle_type,
content::GlobalFrameRoutingId frame_id, content::GlobalFrameRoutingId frame_id,
base::OnceCallback<void(SensitiveDirectoryResult)> callback, base::OnceCallback<void(SensitiveDirectoryResult)> callback,
...@@ -415,7 +419,7 @@ void ChromeNativeFileSystemPermissionContext:: ...@@ -415,7 +419,7 @@ void ChromeNativeFileSystemPermissionContext::
content::GetUIThreadTaskRunner({})->PostTask( content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&ShowNativeFileSystemRestrictedDirectoryDialogOnUIThread, base::BindOnce(&ShowNativeFileSystemRestrictedDirectoryDialogOnUIThread,
frame_id, origin, paths[0], handle_type, frame_id, origin, path, handle_type,
std::move(result_callback))); std::move(result_callback)));
} }
......
...@@ -48,7 +48,8 @@ class ChromeNativeFileSystemPermissionContext ...@@ -48,7 +48,8 @@ class ChromeNativeFileSystemPermissionContext
// content::NativeFileSystemPermissionContext: // content::NativeFileSystemPermissionContext:
void ConfirmSensitiveDirectoryAccess( void ConfirmSensitiveDirectoryAccess(
const url::Origin& origin, const url::Origin& origin,
const std::vector<base::FilePath>& paths, PathType path_type,
const base::FilePath& path,
HandleType handle_type, HandleType handle_type,
content::GlobalFrameRoutingId frame_id, content::GlobalFrameRoutingId frame_id,
base::OnceCallback<void(SensitiveDirectoryResult)> callback) override; base::OnceCallback<void(SensitiveDirectoryResult)> callback) override;
...@@ -96,7 +97,7 @@ class ChromeNativeFileSystemPermissionContext ...@@ -96,7 +97,7 @@ class ChromeNativeFileSystemPermissionContext
private: private:
void DidConfirmSensitiveDirectoryAccess( void DidConfirmSensitiveDirectoryAccess(
const url::Origin& origin, const url::Origin& origin,
const std::vector<base::FilePath>& paths, const base::FilePath& path,
HandleType handle_type, HandleType handle_type,
content::GlobalFrameRoutingId frame_id, content::GlobalFrameRoutingId frame_id,
base::OnceCallback<void(SensitiveDirectoryResult)> callback, base::OnceCallback<void(SensitiveDirectoryResult)> callback,
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
using content::BrowserContext; using content::BrowserContext;
using HandleType = ChromeNativeFileSystemPermissionContext::HandleType; using HandleType = ChromeNativeFileSystemPermissionContext::HandleType;
using PathType = ChromeNativeFileSystemPermissionContext::PathType;
using UserAction = ChromeNativeFileSystemPermissionContext::UserAction; using UserAction = ChromeNativeFileSystemPermissionContext::UserAction;
using PermissionStatus = using PermissionStatus =
content::NativeFileSystemPermissionGrant::PermissionStatus; content::NativeFileSystemPermissionGrant::PermissionStatus;
...@@ -96,12 +97,14 @@ class ChromeNativeFileSystemPermissionContextTest : public testing::Test { ...@@ -96,12 +97,14 @@ class ChromeNativeFileSystemPermissionContextTest : public testing::Test {
SensitiveDirectoryResult ConfirmSensitiveDirectoryAccessSync( SensitiveDirectoryResult ConfirmSensitiveDirectoryAccessSync(
ChromeNativeFileSystemPermissionContext* context, ChromeNativeFileSystemPermissionContext* context,
const std::vector<base::FilePath>& paths, PathType path_type,
const base::FilePath& path,
HandleType handle_type) { HandleType handle_type) {
base::RunLoop loop; base::RunLoop loop;
SensitiveDirectoryResult out_result; SensitiveDirectoryResult out_result;
permission_context_->ConfirmSensitiveDirectoryAccess( permission_context_->ConfirmSensitiveDirectoryAccess(
kTestOrigin, paths, handle_type, content::GlobalFrameRoutingId(), kTestOrigin, path_type, path, handle_type,
content::GlobalFrameRoutingId(),
base::BindLambdaForTesting([&](SensitiveDirectoryResult result) { base::BindLambdaForTesting([&](SensitiveDirectoryResult result) {
out_result = result; out_result = result;
loop.Quit(); loop.Quit();
...@@ -161,16 +164,20 @@ TEST_F(ChromeNativeFileSystemPermissionContextTest, ...@@ -161,16 +164,20 @@ TEST_F(ChromeNativeFileSystemPermissionContextTest,
// Path outside any special directories should be allowed. // Path outside any special directories should be allowed.
EXPECT_EQ(SensitiveDirectoryResult::kAllowed, EXPECT_EQ(SensitiveDirectoryResult::kAllowed,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(permission_context(),
permission_context(), {kTestPath}, HandleType::kFile)); PathType::kLocal, kTestPath,
HandleType::kFile));
EXPECT_EQ(SensitiveDirectoryResult::kAllowed, EXPECT_EQ(SensitiveDirectoryResult::kAllowed,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(permission_context(),
permission_context(), {kTestPath}, HandleType::kDirectory)); PathType::kLocal, kTestPath,
HandleType::kDirectory));
// Empty set of paths should also be allowed. // External (relative) paths should also be allowed.
EXPECT_EQ(SensitiveDirectoryResult::kAllowed, EXPECT_EQ(
ConfirmSensitiveDirectoryAccessSync(permission_context(), {}, SensitiveDirectoryResult::kAllowed,
HandleType::kFile)); ConfirmSensitiveDirectoryAccessSync(
permission_context(), PathType::kExternal,
base::FilePath(FILE_PATH_LITERAL("foo/bar")), HandleType::kFile));
} }
TEST_F(ChromeNativeFileSystemPermissionContextTest, TEST_F(ChromeNativeFileSystemPermissionContextTest,
...@@ -180,22 +187,23 @@ TEST_F(ChromeNativeFileSystemPermissionContextTest, ...@@ -180,22 +187,23 @@ TEST_F(ChromeNativeFileSystemPermissionContextTest,
// Home directory itself should not be allowed. // Home directory itself should not be allowed.
EXPECT_EQ(SensitiveDirectoryResult::kAbort, EXPECT_EQ(SensitiveDirectoryResult::kAbort,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(permission_context(),
permission_context(), {home_dir}, HandleType::kDirectory)); PathType::kLocal, home_dir,
HandleType::kDirectory));
// Parent of home directory should also not be allowed. // Parent of home directory should also not be allowed.
EXPECT_EQ( EXPECT_EQ(SensitiveDirectoryResult::kAbort,
SensitiveDirectoryResult::kAbort,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(
permission_context(), {temp_dir_.GetPath()}, HandleType::kDirectory)); permission_context(), PathType::kLocal, temp_dir_.GetPath(),
HandleType::kDirectory));
// Paths inside home directory should be allowed. // Paths inside home directory should be allowed.
EXPECT_EQ(SensitiveDirectoryResult::kAllowed, EXPECT_EQ(SensitiveDirectoryResult::kAllowed,
ConfirmSensitiveDirectoryAccessSync(permission_context(), ConfirmSensitiveDirectoryAccessSync(
{home_dir.AppendASCII("foo")}, permission_context(), PathType::kLocal,
HandleType::kFile)); home_dir.AppendASCII("foo"), HandleType::kFile));
EXPECT_EQ(SensitiveDirectoryResult::kAllowed, EXPECT_EQ(SensitiveDirectoryResult::kAllowed,
ConfirmSensitiveDirectoryAccessSync(permission_context(), ConfirmSensitiveDirectoryAccessSync(
{home_dir.AppendASCII("foo")}, permission_context(), PathType::kLocal,
HandleType::kDirectory)); home_dir.AppendASCII("foo"), HandleType::kDirectory));
} }
TEST_F(ChromeNativeFileSystemPermissionContextTest, TEST_F(ChromeNativeFileSystemPermissionContextTest,
...@@ -205,22 +213,23 @@ TEST_F(ChromeNativeFileSystemPermissionContextTest, ...@@ -205,22 +213,23 @@ TEST_F(ChromeNativeFileSystemPermissionContextTest,
// App directory itself should not be allowed. // App directory itself should not be allowed.
EXPECT_EQ(SensitiveDirectoryResult::kAbort, EXPECT_EQ(SensitiveDirectoryResult::kAbort,
ConfirmSensitiveDirectoryAccessSync(permission_context(), {app_dir}, ConfirmSensitiveDirectoryAccessSync(permission_context(),
PathType::kLocal, app_dir,
HandleType::kDirectory)); HandleType::kDirectory));
// Parent of App directory should also not be allowed. // Parent of App directory should also not be allowed.
EXPECT_EQ( EXPECT_EQ(SensitiveDirectoryResult::kAbort,
SensitiveDirectoryResult::kAbort,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(
permission_context(), {temp_dir_.GetPath()}, HandleType::kDirectory)); permission_context(), PathType::kLocal, temp_dir_.GetPath(),
HandleType::kDirectory));
// Paths inside App directory should also not be allowed. // Paths inside App directory should also not be allowed.
EXPECT_EQ(SensitiveDirectoryResult::kAbort, EXPECT_EQ(SensitiveDirectoryResult::kAbort,
ConfirmSensitiveDirectoryAccessSync(permission_context(), ConfirmSensitiveDirectoryAccessSync(
{app_dir.AppendASCII("foo")}, permission_context(), PathType::kLocal,
HandleType::kFile)); app_dir.AppendASCII("foo"), HandleType::kFile));
EXPECT_EQ(SensitiveDirectoryResult::kAbort, EXPECT_EQ(SensitiveDirectoryResult::kAbort,
ConfirmSensitiveDirectoryAccessSync(permission_context(), ConfirmSensitiveDirectoryAccessSync(
{app_dir.AppendASCII("foo")}, permission_context(), PathType::kLocal,
HandleType::kDirectory)); app_dir.AppendASCII("foo"), HandleType::kDirectory));
} }
TEST_F(ChromeNativeFileSystemPermissionContextTest, TEST_F(ChromeNativeFileSystemPermissionContextTest,
...@@ -234,26 +243,28 @@ TEST_F(ChromeNativeFileSystemPermissionContextTest, ...@@ -234,26 +243,28 @@ TEST_F(ChromeNativeFileSystemPermissionContextTest,
// User Data directory itself should not be allowed. // User Data directory itself should not be allowed.
EXPECT_EQ(SensitiveDirectoryResult::kAbort, EXPECT_EQ(SensitiveDirectoryResult::kAbort,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(permission_context(),
permission_context(), {user_data_dir}, HandleType::kDirectory)); PathType::kLocal, user_data_dir,
HandleType::kDirectory));
// Parent of User Data directory should also not be allowed. // Parent of User Data directory should also not be allowed.
EXPECT_EQ( EXPECT_EQ(SensitiveDirectoryResult::kAbort,
SensitiveDirectoryResult::kAbort,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(
permission_context(), {temp_dir_.GetPath()}, HandleType::kDirectory)); permission_context(), PathType::kLocal, temp_dir_.GetPath(),
HandleType::kDirectory));
// The nested Download directory itself should not be allowed. // The nested Download directory itself should not be allowed.
EXPECT_EQ(SensitiveDirectoryResult::kAbort, EXPECT_EQ(SensitiveDirectoryResult::kAbort,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(permission_context(),
permission_context(), {download_dir}, HandleType::kDirectory)); PathType::kLocal, download_dir,
HandleType::kDirectory));
// Paths inside the nested Download directory should be allowed. // Paths inside the nested Download directory should be allowed.
EXPECT_EQ(SensitiveDirectoryResult::kAllowed, EXPECT_EQ(SensitiveDirectoryResult::kAllowed,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(
permission_context(), {download_dir.AppendASCII("foo")}, permission_context(), PathType::kLocal,
HandleType::kFile)); download_dir.AppendASCII("foo"), HandleType::kFile));
EXPECT_EQ(SensitiveDirectoryResult::kAllowed, EXPECT_EQ(SensitiveDirectoryResult::kAllowed,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(
permission_context(), {download_dir.AppendASCII("foo")}, permission_context(), PathType::kLocal,
HandleType::kDirectory)); download_dir.AppendASCII("foo"), HandleType::kDirectory));
#if defined(OS_WIN) #if defined(OS_WIN)
// DIR_IE_INTERNET_CACHE is an example of a directory where nested directories // DIR_IE_INTERNET_CACHE is an example of a directory where nested directories
...@@ -263,20 +274,20 @@ TEST_F(ChromeNativeFileSystemPermissionContextTest, ...@@ -263,20 +274,20 @@ TEST_F(ChromeNativeFileSystemPermissionContextTest,
internet_cache, true, true); internet_cache, true, true);
// The nested INetCache directory itself should not be allowed. // The nested INetCache directory itself should not be allowed.
EXPECT_EQ( EXPECT_EQ(SensitiveDirectoryResult::kAbort,
SensitiveDirectoryResult::kAbort,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(
permission_context(), {internet_cache}, HandleType::kDirectory)); permission_context(), PathType::kLocal, internet_cache,
HandleType::kDirectory));
// Files inside the nested INetCache directory should be allowed. // Files inside the nested INetCache directory should be allowed.
EXPECT_EQ(SensitiveDirectoryResult::kAllowed, EXPECT_EQ(SensitiveDirectoryResult::kAllowed,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(
permission_context(), {internet_cache.AppendASCII("foo")}, permission_context(), PathType::kLocal,
HandleType::kFile)); internet_cache.AppendASCII("foo"), HandleType::kFile));
// But directories should be blocked. // But directories should be blocked.
EXPECT_EQ(SensitiveDirectoryResult::kAbort, EXPECT_EQ(SensitiveDirectoryResult::kAbort,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(
permission_context(), {internet_cache.AppendASCII("foo")}, permission_context(), PathType::kLocal,
HandleType::kDirectory)); internet_cache.AppendASCII("foo"), HandleType::kDirectory));
#endif #endif
} }
...@@ -287,14 +298,14 @@ TEST_F(ChromeNativeFileSystemPermissionContextTest, ...@@ -287,14 +298,14 @@ TEST_F(ChromeNativeFileSystemPermissionContextTest,
// ~/.ssh should be blocked // ~/.ssh should be blocked
EXPECT_EQ(SensitiveDirectoryResult::kAbort, EXPECT_EQ(SensitiveDirectoryResult::kAbort,
ConfirmSensitiveDirectoryAccessSync(permission_context(), ConfirmSensitiveDirectoryAccessSync(
{home_dir.AppendASCII(".ssh")}, permission_context(), PathType::kLocal,
HandleType::kDirectory)); home_dir.AppendASCII(".ssh"), HandleType::kDirectory));
// And anything inside ~/.ssh should also be blocked // And anything inside ~/.ssh should also be blocked
EXPECT_EQ(SensitiveDirectoryResult::kAbort, EXPECT_EQ(SensitiveDirectoryResult::kAbort,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(
permission_context(), {home_dir.AppendASCII(".ssh/id_rsa")}, permission_context(), PathType::kLocal,
HandleType::kFile)); home_dir.AppendASCII(".ssh/id_rsa"), HandleType::kFile));
} }
TEST_F(ChromeNativeFileSystemPermissionContextTest, TEST_F(ChromeNativeFileSystemPermissionContextTest,
...@@ -306,19 +317,19 @@ TEST_F(ChromeNativeFileSystemPermissionContextTest, ...@@ -306,19 +317,19 @@ TEST_F(ChromeNativeFileSystemPermissionContextTest,
EXPECT_EQ( EXPECT_EQ(
SensitiveDirectoryResult::kAbort, SensitiveDirectoryResult::kAbort,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(
permission_context(), {base::FilePath(FILE_PATH_LITERAL("/dev"))}, permission_context(), PathType::kLocal,
HandleType::kDirectory)); base::FilePath(FILE_PATH_LITERAL("/dev")), HandleType::kDirectory));
// As well as children of /dev. // As well as children of /dev.
EXPECT_EQ( EXPECT_EQ(SensitiveDirectoryResult::kAbort,
SensitiveDirectoryResult::kAbort,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(
permission_context(), {base::FilePath(FILE_PATH_LITERAL("/dev/foo"))}, permission_context(), PathType::kLocal,
base::FilePath(FILE_PATH_LITERAL("/dev/foo")),
HandleType::kDirectory)); HandleType::kDirectory));
EXPECT_EQ( EXPECT_EQ(
SensitiveDirectoryResult::kAbort, SensitiveDirectoryResult::kAbort,
ConfirmSensitiveDirectoryAccessSync( ConfirmSensitiveDirectoryAccessSync(
permission_context(), {base::FilePath(FILE_PATH_LITERAL("/dev/foo"))}, permission_context(), PathType::kLocal,
HandleType::kFile)); base::FilePath(FILE_PATH_LITERAL("/dev/foo")), HandleType::kFile));
#endif #endif
} }
......
...@@ -474,18 +474,23 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenDirectory_DenyAccess) { ...@@ -474,18 +474,23 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenDirectory_DenyAccess) {
auto write_grant = base::MakeRefCounted<FixedNativeFileSystemPermissionGrant>( auto write_grant = base::MakeRefCounted<FixedNativeFileSystemPermissionGrant>(
PermissionStatus::ASK, base::FilePath()); PermissionStatus::ASK, base::FilePath());
EXPECT_CALL(permission_context, auto origin =
CanObtainReadPermission(url::Origin::Create( url::Origin::Create(embedded_test_server()->GetURL("/title1.html"));
embedded_test_server()->GetURL("/title1.html")))) auto frame_id = GlobalFrameRoutingId(
shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(),
shell()->web_contents()->GetMainFrame()->GetRoutingID());
EXPECT_CALL(permission_context, CanObtainReadPermission(origin))
.WillOnce(testing::Return(true)); .WillOnce(testing::Return(true));
EXPECT_CALL(permission_context, EXPECT_CALL(
permission_context,
ConfirmSensitiveDirectoryAccess_( ConfirmSensitiveDirectoryAccess_(
testing::_, testing::_, testing::_, testing::_, testing::_)) origin, NativeFileSystemPermissionContext::PathType::kLocal, test_dir,
.WillOnce(RunOnceCallback<4>(SensitiveDirectoryResult::kAllowed)); NativeFileSystemPermissionContext::HandleType::kDirectory, frame_id,
testing::_))
.WillOnce(RunOnceCallback<5>(SensitiveDirectoryResult::kAllowed));
auto origin =
url::Origin::Create(embedded_test_server()->GetURL("/title1.html"));
EXPECT_CALL(permission_context, EXPECT_CALL(permission_context,
GetReadPermissionGrant( GetReadPermissionGrant(
origin, test_dir, origin, test_dir,
...@@ -502,9 +507,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenDirectory_DenyAccess) { ...@@ -502,9 +507,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenDirectory_DenyAccess) {
EXPECT_CALL( EXPECT_CALL(
*read_grant, *read_grant,
RequestPermission_( RequestPermission_(
GlobalFrameRoutingId( frame_id,
shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(),
shell()->web_contents()->GetMainFrame()->GetRoutingID()),
NativeFileSystemPermissionGrant::UserActivationState::kNotRequired, NativeFileSystemPermissionGrant::UserActivationState::kNotRequired,
testing::_)) testing::_))
.WillOnce(RunOnceCallback<2>(NativeFileSystemPermissionGrant:: .WillOnce(RunOnceCallback<2>(NativeFileSystemPermissionGrant::
...@@ -536,10 +539,19 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, ...@@ -536,10 +539,19 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,
->GetNativeFileSystemEntryFactory()) ->GetNativeFileSystemEntryFactory())
->SetPermissionContextForTesting(&permission_context); ->SetPermissionContextForTesting(&permission_context);
EXPECT_CALL(permission_context, auto origin =
url::Origin::Create(embedded_test_server()->GetURL("/title1.html"));
auto frame_id = GlobalFrameRoutingId(
shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(),
shell()->web_contents()->GetMainFrame()->GetRoutingID());
EXPECT_CALL(
permission_context,
ConfirmSensitiveDirectoryAccess_( ConfirmSensitiveDirectoryAccess_(
testing::_, testing::_, testing::_, testing::_, testing::_)) origin, NativeFileSystemPermissionContext::PathType::kLocal,
.WillOnce(RunOnceCallback<4>(SensitiveDirectoryResult::kAbort)); test_file, NativeFileSystemPermissionContext::HandleType::kFile,
frame_id, testing::_))
.WillOnce(RunOnceCallback<5>(SensitiveDirectoryResult::kAbort));
EXPECT_CALL(permission_context, EXPECT_CALL(permission_context,
CanObtainReadPermission(url::Origin::Create( CanObtainReadPermission(url::Origin::Create(
...@@ -587,18 +599,23 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, ...@@ -587,18 +599,23 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,
->GetNativeFileSystemEntryFactory()) ->GetNativeFileSystemEntryFactory())
->SetPermissionContextForTesting(&permission_context); ->SetPermissionContextForTesting(&permission_context);
EXPECT_CALL(permission_context, auto origin =
url::Origin::Create(embedded_test_server()->GetURL("/title1.html"));
auto frame_id = GlobalFrameRoutingId(
shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(),
shell()->web_contents()->GetMainFrame()->GetRoutingID());
EXPECT_CALL(
permission_context,
ConfirmSensitiveDirectoryAccess_( ConfirmSensitiveDirectoryAccess_(
testing::_, testing::_, testing::_, testing::_, testing::_)) origin, NativeFileSystemPermissionContext::PathType::kLocal,
.WillOnce(RunOnceCallback<4>(SensitiveDirectoryResult::kAbort)); test_file, NativeFileSystemPermissionContext::HandleType::kFile,
frame_id, testing::_))
.WillOnce(RunOnceCallback<5>(SensitiveDirectoryResult::kAbort));
EXPECT_CALL(permission_context, EXPECT_CALL(permission_context, CanObtainReadPermission(origin))
CanObtainReadPermission(url::Origin::Create(
embedded_test_server()->GetURL("/title1.html"))))
.WillOnce(testing::Return(true)); .WillOnce(testing::Return(true));
EXPECT_CALL(permission_context, EXPECT_CALL(permission_context, CanObtainWritePermission(origin))
CanObtainWritePermission(url::Origin::Create(
embedded_test_server()->GetURL("/title1.html"))))
.WillOnce(testing::Return(true)); .WillOnce(testing::Return(true));
ASSERT_TRUE( ASSERT_TRUE(
......
...@@ -13,12 +13,13 @@ MockNativeFileSystemPermissionContext:: ...@@ -13,12 +13,13 @@ MockNativeFileSystemPermissionContext::
void MockNativeFileSystemPermissionContext::ConfirmSensitiveDirectoryAccess( void MockNativeFileSystemPermissionContext::ConfirmSensitiveDirectoryAccess(
const url::Origin& origin, const url::Origin& origin,
const std::vector<base::FilePath>& paths, PathType path_type,
const base::FilePath& path,
HandleType handle_type, HandleType handle_type,
GlobalFrameRoutingId frame_id, GlobalFrameRoutingId frame_id,
base::OnceCallback<void(SensitiveDirectoryResult)> callback) { base::OnceCallback<void(SensitiveDirectoryResult)> callback) {
ConfirmSensitiveDirectoryAccess_(origin, paths, handle_type, frame_id, ConfirmSensitiveDirectoryAccess_(origin, path_type, path, handle_type,
callback); frame_id, callback);
} }
void MockNativeFileSystemPermissionContext::PerformAfterWriteChecks( void MockNativeFileSystemPermissionContext::PerformAfterWriteChecks(
......
...@@ -32,14 +32,16 @@ class MockNativeFileSystemPermissionContext ...@@ -32,14 +32,16 @@ class MockNativeFileSystemPermissionContext
void ConfirmSensitiveDirectoryAccess( void ConfirmSensitiveDirectoryAccess(
const url::Origin& origin, const url::Origin& origin,
const std::vector<base::FilePath>& paths, PathType path_type,
const base::FilePath& path,
HandleType handle_type, HandleType handle_type,
GlobalFrameRoutingId frame_id, GlobalFrameRoutingId frame_id,
base::OnceCallback<void(SensitiveDirectoryResult)> callback) override; base::OnceCallback<void(SensitiveDirectoryResult)> callback) override;
MOCK_METHOD5( MOCK_METHOD6(
ConfirmSensitiveDirectoryAccess_, ConfirmSensitiveDirectoryAccess_,
void(const url::Origin& origin, void(const url::Origin& origin,
const std::vector<base::FilePath>& paths, PathType path_type,
const base::FilePath& path,
HandleType handle_type, HandleType handle_type,
GlobalFrameRoutingId frame_id, GlobalFrameRoutingId frame_id,
base::OnceCallback<void(SensitiveDirectoryResult)>& callback)); base::OnceCallback<void(SensitiveDirectoryResult)>& callback));
......
...@@ -832,7 +832,7 @@ void NativeFileSystemManagerImpl::DidChooseEntries( ...@@ -832,7 +832,7 @@ void NativeFileSystemManagerImpl::DidChooseEntries(
std::vector<FileSystemChooser::ResultEntry> entries) { std::vector<FileSystemChooser::ResultEntry> entries) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (result->status != NativeFileSystemStatus::kOk) { if (result->status != NativeFileSystemStatus::kOk || entries.empty()) {
std::move(callback).Run( std::move(callback).Run(
std::move(result), std::move(result),
std::vector<blink::mojom::NativeFileSystemEntryPtr>()); std::vector<blink::mojom::NativeFileSystemEntryPtr>());
...@@ -846,15 +846,14 @@ void NativeFileSystemManagerImpl::DidChooseEntries( ...@@ -846,15 +846,14 @@ void NativeFileSystemManagerImpl::DidChooseEntries(
return; return;
} }
std::vector<base::FilePath> paths; // It is enough to only verify access to the first path, as multiple
paths.reserve(entries.size()); // file selection is only supported if all files are in the same
for (const auto& entry : entries) // directory.
paths.push_back(entry.path); FileSystemChooser::ResultEntry first_entry = entries.front();
const bool is_directory = const bool is_directory =
options.type() == blink::mojom::ChooseFileSystemEntryType::kOpenDirectory; options.type() == blink::mojom::ChooseFileSystemEntryType::kOpenDirectory;
permission_context_->ConfirmSensitiveDirectoryAccess( permission_context_->ConfirmSensitiveDirectoryAccess(
binding_context.origin, std::move(paths), binding_context.origin, first_entry.type, first_entry.path,
is_directory ? HandleType::kDirectory : HandleType::kFile, is_directory ? HandleType::kDirectory : HandleType::kFile,
binding_context.frame_id, binding_context.frame_id,
base::BindOnce( base::BindOnce(
......
...@@ -25,6 +25,7 @@ class CONTENT_EXPORT NativeFileSystemEntryFactory ...@@ -25,6 +25,7 @@ class CONTENT_EXPORT NativeFileSystemEntryFactory
BrowserThread::DeleteOnUIThread> { BrowserThread::DeleteOnUIThread> {
public: public:
using UserAction = NativeFileSystemPermissionContext::UserAction; using UserAction = NativeFileSystemPermissionContext::UserAction;
using PathType = NativeFileSystemPermissionContext::PathType;
// Context from which a created handle is going to be used. This is used for // Context from which a created handle is going to be used. This is used for
// security and permission checks. Pass in the URL most relevant as the url // security and permission checks. Pass in the URL most relevant as the url
...@@ -48,19 +49,6 @@ class CONTENT_EXPORT NativeFileSystemEntryFactory ...@@ -48,19 +49,6 @@ class CONTENT_EXPORT NativeFileSystemEntryFactory
int process_id() const { return frame_id.child_id; } int process_id() const { return frame_id.child_id; }
}; };
enum class PathType {
// A path on the local file system. Files with these paths can be operated
// on by base::File.
kLocal,
// A path on an "external" file system. These paths can only be accessed via
// the filesystem abstraction in //storage/browser/file_system, and a
// storage::kFileSystemTypeExternal storage::FileSystemURL.
// This path type should be used for paths retrieved via the `virtual_path`
// member of a ui::SelectedFileInfo struct.
kExternal
};
// Creates a new NativeFileSystemEntryPtr from the path to a file. Assumes the // Creates a new NativeFileSystemEntryPtr from the path to a file. Assumes the
// passed in path is valid and represents a file. // passed in path is valid and represents a file.
virtual blink::mojom::NativeFileSystemEntryPtr CreateFileEntryFromPath( virtual blink::mojom::NativeFileSystemEntryPtr CreateFileEntryFromPath(
......
...@@ -46,6 +46,19 @@ class NativeFileSystemPermissionContext { ...@@ -46,6 +46,19 @@ class NativeFileSystemPermissionContext {
// handles. // handles.
enum class HandleType { kFile, kDirectory }; enum class HandleType { kFile, kDirectory };
enum class PathType {
// A path on the local file system. Files with these paths can be operated
// on by base::File.
kLocal,
// A path on an "external" file system. These paths can only be accessed via
// the filesystem abstraction in //storage/browser/file_system, and a
// storage::FileSystemURL of type storage::kFileSystemTypeExternal.
// This path type should be used for paths retrieved via the `virtual_path`
// member of a ui::SelectedFileInfo struct.
kExternal
};
// Returns the read permission grant to use for a particular path. // Returns the read permission grant to use for a particular path.
virtual scoped_refptr<NativeFileSystemPermissionGrant> GetReadPermissionGrant( virtual scoped_refptr<NativeFileSystemPermissionGrant> GetReadPermissionGrant(
const url::Origin& origin, const url::Origin& origin,
...@@ -72,14 +85,15 @@ class NativeFileSystemPermissionContext { ...@@ -72,14 +85,15 @@ class NativeFileSystemPermissionContext {
kAbort = 2, // Abandon entirely, as if picking was cancelled. kAbort = 2, // Abandon entirely, as if picking was cancelled.
kMaxValue = kAbort kMaxValue = kAbort
}; };
// Checks if access to the given |paths| should be allowed or blocked. This is // Checks if access to the given |path| should be allowed or blocked. This is
// used to implement blocks for certain sensitive directories such as the // used to implement blocks for certain sensitive directories such as the
// "Windows" system directory, as well as the root of the "home" directory. // "Windows" system directory, as well as the root of the "home" directory.
// Calls |callback| with the result of the check, after potentially showing // Calls |callback| with the result of the check, after potentially showing
// some UI to the user if the path should not be accessed. // some UI to the user if the path should not be accessed.
virtual void ConfirmSensitiveDirectoryAccess( virtual void ConfirmSensitiveDirectoryAccess(
const url::Origin& origin, const url::Origin& origin,
const std::vector<base::FilePath>& paths, PathType path_type,
const base::FilePath& path,
HandleType handle_type, HandleType handle_type,
GlobalFrameRoutingId frame_id, GlobalFrameRoutingId frame_id,
base::OnceCallback<void(SensitiveDirectoryResult)> callback) = 0; base::OnceCallback<void(SensitiveDirectoryResult)> callback) = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment