diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/content/browser/native_file_system | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/content/browser/native_file_system')
22 files changed, 523 insertions, 531 deletions
diff --git a/chromium/content/browser/native_file_system/file_system_chooser_browsertest.cc b/chromium/content/browser/native_file_system/file_system_chooser_browsertest.cc index 8a36eaa3d0d..44a887c37f9 100644 --- a/chromium/content/browser/native_file_system/file_system_chooser_browsertest.cc +++ b/chromium/content/browser/native_file_system/file_system_chooser_browsertest.cc @@ -36,8 +36,8 @@ using blink::mojom::PermissionStatus; using SensitiveDirectoryResult = NativeFileSystemPermissionContext::SensitiveDirectoryResult; -// This browser test implements end-to-end tests for the chooseFileSystemEntry -// API. +// This browser test implements end-to-end tests for the file picker +// APIs. class FileSystemChooserBrowserTest : public ContentBrowserTest { public: void SetUp() override { @@ -67,11 +67,11 @@ class FileSystemChooserBrowserTest : public ContentBrowserTest { return web_contents->IsFullscreenForCurrentTab(); } - void EnterFullscreen(GURL url) { + void EnterFullscreen() { WebContentsImpl* web_contents_impl = static_cast<WebContentsImpl*>(shell()->web_contents()); - web_contents_impl->EnterFullscreenMode(url, - blink::mojom::FullscreenOptions()); + web_contents_impl->EnterFullscreenMode(web_contents_impl->GetMainFrame(), + {}); } base::FilePath CreateTestFile(const std::string& contents) { @@ -99,7 +99,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, CancelDialog) { ui::SelectFileDialog::SetFactory(new CancellingSelectFileDialogFactory); ASSERT_TRUE( NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); - auto result = EvalJs(shell(), "self.chooseFileSystemEntries()"); + auto result = EvalJs(shell(), "self.showOpenFilePicker()"); EXPECT_TRUE(result.error.find("aborted") != std::string::npos) << result.error; } @@ -115,7 +115,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenFile) { EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(), EvalJs(shell(), "(async () => {" - " let e = await self.chooseFileSystemEntries();" + " let [e] = await self.showOpenFilePicker();" " self.selected_entry = e;" " return e.name; })()")); EXPECT_EQ(ui::SelectFileDialog::SELECT_OPEN_FILE, dialog_params.type); @@ -145,7 +145,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenFileNonASCII) { EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(), EvalJs(shell(), "(async () => {" - " let e = await self.chooseFileSystemEntries();" + " let [e] = await self.showOpenFilePicker();" " self.selected_entry = e;" " return e.name; })()")); EXPECT_EQ(ui::SelectFileDialog::SELECT_OPEN_FILE, dialog_params.type); @@ -166,12 +166,12 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, FullscreenOpenFile) { new FakeSelectFileDialogFactory({test_file}, &dialog_params)); ASSERT_TRUE( NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); - EnterFullscreen(embedded_test_server()->GetURL("/title1.html")); + EnterFullscreen(); EXPECT_TRUE(IsFullscreen()); EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(), EvalJs(shell(), "(async () => {" - " let e = await self.chooseFileSystemEntries();" + " let [e] = await self.showOpenFilePicker();" " self.selected_entry = e;" " return e.name; })()")); EXPECT_FALSE(IsFullscreen()); @@ -194,8 +194,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, SaveFile_NonExistingFile) { EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(), EvalJs(shell(), "(async () => {" - " let e = await self.chooseFileSystemEntries(" - " {type: 'save-file'});" + " let e = await self.showSaveFilePicker();" " self.entry = e;" " return e.name; })()")); EXPECT_EQ(ui::SelectFileDialog::SELECT_SAVEAS_FILE, dialog_params.type); @@ -227,8 +226,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(), EvalJs(shell(), "(async () => {" - " let e = await self.chooseFileSystemEntries(" - " {type: 'save-file'});" + " let e = await self.showSaveFilePicker();" " self.entry = e;" " return e.name; })()")); EXPECT_EQ(ui::SelectFileDialog::SELECT_SAVEAS_FILE, dialog_params.type); @@ -260,8 +258,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, ASSERT_TRUE( NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); - auto result = - EvalJs(shell(), "self.chooseFileSystemEntries({type: 'save-file'})"); + auto result = EvalJs(shell(), "self.showSaveFilePicker()"); EXPECT_TRUE(result.error.find("not allowed") != std::string::npos) << result.error; EXPECT_EQ(ui::SelectFileDialog::SELECT_NONE, dialog_params.type); @@ -275,12 +272,11 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, FullscreenSaveFile) { new FakeSelectFileDialogFactory({test_file}, &dialog_params)); ASSERT_TRUE( NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); - EnterFullscreen(embedded_test_server()->GetURL("/title1.html")); + EnterFullscreen(); EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(), EvalJs(shell(), "(async () => {" - " let e = await self.chooseFileSystemEntries(" - " {type: 'save-file'});" + " let e = await self.showSaveFilePicker();" " self.entry = e;" " return e.name; })()")); EXPECT_FALSE(IsFullscreen()); @@ -298,7 +294,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenMultipleFiles) { test_file2.BaseName().AsUTF8Unsafe()), EvalJs(shell(), "(async () => {" - " let e = await self.chooseFileSystemEntries(" + " let e = await self.showOpenFilePicker(" " {multiple: true});" " return e.map(x => x.name); })()")); EXPECT_EQ(ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE, dialog_params.type); @@ -313,12 +309,12 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, {test_file1, test_file2}, &dialog_params)); ASSERT_TRUE( NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); - EnterFullscreen(embedded_test_server()->GetURL("/title1.html")); + EnterFullscreen(); EXPECT_EQ(ListValueOf(test_file1.BaseName().AsUTF8Unsafe(), test_file2.BaseName().AsUTF8Unsafe()), EvalJs(shell(), "(async () => {" - " let e = await self.chooseFileSystemEntries(" + " let e = await self.showOpenFilePicker(" " {multiple: true});" " return e.map(x => x.name); })()")); EXPECT_FALSE(IsFullscreen()); @@ -334,8 +330,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenDirectory) { EXPECT_EQ(test_dir.BaseName().AsUTF8Unsafe(), EvalJs(shell(), "(async () => {" - " let e = await self.chooseFileSystemEntries(" - " {type: 'open-directory'});" + " let e = await self.showDirectoryPicker();" " self.selected_entry = e;" " return e.name; })()")); EXPECT_EQ(ui::SelectFileDialog::SELECT_FOLDER, dialog_params.type); @@ -348,12 +343,11 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, FullscreenOpenDirectory) { new FakeSelectFileDialogFactory({test_dir}, &dialog_params)); ASSERT_TRUE( NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); - EnterFullscreen(embedded_test_server()->GetURL("/title1.html")); + EnterFullscreen(); EXPECT_EQ(test_dir.BaseName().AsUTF8Unsafe(), EvalJs(shell(), "(async () => {" - " let e = await self.chooseFileSystemEntries(" - " {type: 'open-directory'});" + " let e = await self.showDirectoryPicker();" " self.selected_entry = e;" " return e.name; })()")); EXPECT_FALSE(IsFullscreen()); @@ -373,24 +367,25 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenDirectory_DenyAccess) { ->GetNativeFileSystemEntryFactory()) ->SetPermissionContextForTesting(&permission_context); - EXPECT_CALL(permission_context, ConfirmSensitiveDirectoryAccess_( - testing::_, testing::_, testing::_, - testing::_, testing::_, testing::_)) - .WillOnce(RunOnceCallback<5>(SensitiveDirectoryResult::kAllowed)); + EXPECT_CALL(permission_context, + ConfirmSensitiveDirectoryAccess_( + testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(RunOnceCallback<4>(SensitiveDirectoryResult::kAllowed)); EXPECT_CALL( permission_context, ConfirmDirectoryReadAccess_( url::Origin::Create(embedded_test_server()->GetURL("/title1.html")), test_dir, - shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(), - shell()->web_contents()->GetMainFrame()->GetRoutingID(), testing::_)) - .WillOnce(RunOnceCallback<4>(PermissionStatus::DENIED)); + GlobalFrameRoutingId( + shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(), + shell()->web_contents()->GetMainFrame()->GetRoutingID()), + testing::_)) + .WillOnce(RunOnceCallback<3>(PermissionStatus::DENIED)); ASSERT_TRUE( NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); - auto result = - EvalJs(shell(), "self.chooseFileSystemEntries({type: 'open-directory'})"); + auto result = EvalJs(shell(), "self.showDirectoryPicker()"); EXPECT_TRUE(result.error.find("aborted") != std::string::npos) << result.error; } @@ -412,10 +407,10 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, ->GetNativeFileSystemEntryFactory()) ->SetPermissionContextForTesting(&permission_context); - EXPECT_CALL(permission_context, ConfirmSensitiveDirectoryAccess_( - testing::_, testing::_, testing::_, - testing::_, testing::_, testing::_)) - .WillOnce(RunOnceCallback<5>(SensitiveDirectoryResult::kAbort)); + EXPECT_CALL(permission_context, + ConfirmSensitiveDirectoryAccess_( + testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(RunOnceCallback<4>(SensitiveDirectoryResult::kAbort)); EXPECT_CALL(permission_context, CanObtainWritePermission(url::Origin::Create( @@ -424,8 +419,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, ASSERT_TRUE( NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); - auto result = - EvalJs(shell(), "self.chooseFileSystemEntries({type: 'save-file'})"); + auto result = EvalJs(shell(), "self.showSaveFilePicker()"); EXPECT_TRUE(result.error.find("aborted") != std::string::npos) << result.error; @@ -460,10 +454,10 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, ->GetNativeFileSystemEntryFactory()) ->SetPermissionContextForTesting(&permission_context); - EXPECT_CALL(permission_context, ConfirmSensitiveDirectoryAccess_( - testing::_, testing::_, testing::_, - testing::_, testing::_, testing::_)) - .WillOnce(RunOnceCallback<5>(SensitiveDirectoryResult::kAbort)); + EXPECT_CALL(permission_context, + ConfirmSensitiveDirectoryAccess_( + testing::_, testing::_, testing::_, testing::_, testing::_)) + .WillOnce(RunOnceCallback<4>(SensitiveDirectoryResult::kAbort)); EXPECT_CALL(permission_context, CanObtainWritePermission(url::Origin::Create( @@ -472,8 +466,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, ASSERT_TRUE( NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); - auto result = - EvalJs(shell(), "self.chooseFileSystemEntries({type: 'save-file'})"); + auto result = EvalJs(shell(), "self.showSaveFilePicker()"); EXPECT_TRUE(result.error.find("aborted") != std::string::npos) << result.error; @@ -490,12 +483,12 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, AcceptsOptions) { new CancellingSelectFileDialogFactory(&dialog_params)); ASSERT_TRUE( NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); - auto result = EvalJs(shell(), - "self.chooseFileSystemEntries({accepts: [" - " {description: 'no-extensions'}," - " {description: 'foo', extensions: ['txt', 'Js']}," - " {mimeTypes: ['image/jpeg']}" - "]})"); + auto result = + EvalJs(shell(), + "self.showOpenFilePicker({types: [" + " {description: 'foo', accept: {'text/custom': ['txt', 'Js']}}," + " {accept: {'image/jpeg': []}}" + "]})"); EXPECT_TRUE(result.error.find("aborted") != std::string::npos) << result.error; @@ -533,7 +526,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(), EvalJs(shell(), "(async () => {" - " let e = await self.chooseFileSystemEntries();" + " let [e] = await self.showOpenFilePicker();" " self.selected_entry = e;" " return e.name; })()")); EXPECT_TRUE(tester.IsDisabledForFrameWithReason( diff --git a/chromium/content/browser/native_file_system/fixed_native_file_system_permission_grant.cc b/chromium/content/browser/native_file_system/fixed_native_file_system_permission_grant.cc index dc86f36f6f4..d372b0fe814 100644 --- a/chromium/content/browser/native_file_system/fixed_native_file_system_permission_grant.cc +++ b/chromium/content/browser/native_file_system/fixed_native_file_system_permission_grant.cc @@ -19,8 +19,7 @@ FixedNativeFileSystemPermissionGrant::GetStatus() { } void FixedNativeFileSystemPermissionGrant::RequestPermission( - int process_id, - int frame_id, + GlobalFrameRoutingId frame_id, base::OnceCallback<void(PermissionRequestOutcome)> callback) { std::move(callback).Run(PermissionRequestOutcome::kRequestAborted); } diff --git a/chromium/content/browser/native_file_system/fixed_native_file_system_permission_grant.h b/chromium/content/browser/native_file_system/fixed_native_file_system_permission_grant.h index cce35598570..064150c5411 100644 --- a/chromium/content/browser/native_file_system/fixed_native_file_system_permission_grant.h +++ b/chromium/content/browser/native_file_system/fixed_native_file_system_permission_grant.h @@ -24,8 +24,7 @@ class CONTENT_EXPORT FixedNativeFileSystemPermissionGrant // NativeFileSystemPermissionGrant: PermissionStatus GetStatus() override; void RequestPermission( - int process_id, - int frame_id, + GlobalFrameRoutingId frame_id, base::OnceCallback<void(PermissionRequestOutcome)> callback) override; protected: diff --git a/chromium/content/browser/native_file_system/mock_native_file_system_permission_context.cc b/chromium/content/browser/native_file_system/mock_native_file_system_permission_context.cc index 7133f72c71a..b48bc5a7261 100644 --- a/chromium/content/browser/native_file_system/mock_native_file_system_permission_context.cc +++ b/chromium/content/browser/native_file_system/mock_native_file_system_permission_context.cc @@ -14,29 +14,26 @@ MockNativeFileSystemPermissionContext:: void MockNativeFileSystemPermissionContext::ConfirmDirectoryReadAccess( const url::Origin& origin, const base::FilePath& path, - int process_id, - int frame_id, + GlobalFrameRoutingId frame_id, base::OnceCallback<void(PermissionStatus)> callback) { - ConfirmDirectoryReadAccess_(origin, path, process_id, frame_id, callback); + ConfirmDirectoryReadAccess_(origin, path, frame_id, callback); } void MockNativeFileSystemPermissionContext::ConfirmSensitiveDirectoryAccess( const url::Origin& origin, const std::vector<base::FilePath>& paths, bool is_directory, - int process_id, - int frame_id, + GlobalFrameRoutingId frame_id, base::OnceCallback<void(SensitiveDirectoryResult)> callback) { - ConfirmSensitiveDirectoryAccess_(origin, paths, is_directory, process_id, - frame_id, callback); + ConfirmSensitiveDirectoryAccess_(origin, paths, is_directory, frame_id, + callback); } void MockNativeFileSystemPermissionContext::PerformAfterWriteChecks( std::unique_ptr<NativeFileSystemWriteItem> item, - int process_id, - int frame_id, + GlobalFrameRoutingId frame_id, base::OnceCallback<void(AfterWriteCheckResult)> callback) { - PerformAfterWriteChecks_(item.get(), process_id, frame_id, callback); + PerformAfterWriteChecks_(item.get(), frame_id, callback); } } // namespace content diff --git a/chromium/content/browser/native_file_system/mock_native_file_system_permission_context.h b/chromium/content/browser/native_file_system/mock_native_file_system_permission_context.h index 59240af8754..a98923e07bb 100644 --- a/chromium/content/browser/native_file_system/mock_native_file_system_permission_context.h +++ b/chromium/content/browser/native_file_system/mock_native_file_system_permission_context.h @@ -16,62 +16,54 @@ class MockNativeFileSystemPermissionContext MockNativeFileSystemPermissionContext(); ~MockNativeFileSystemPermissionContext(); - MOCK_METHOD6(GetReadPermissionGrant, + MOCK_METHOD4(GetReadPermissionGrant, scoped_refptr<NativeFileSystemPermissionGrant>( const url::Origin& origin, const base::FilePath& path, bool is_directory, - int process_id, - int frame_id, + NativeFileSystemPermissionContext::UserAction user_action)); - MOCK_METHOD6(GetWritePermissionGrant, + MOCK_METHOD4(GetWritePermissionGrant, scoped_refptr<NativeFileSystemPermissionGrant>( const url::Origin& origin, const base::FilePath& path, bool is_directory, - int process_id, - int frame_id, + NativeFileSystemPermissionContext::UserAction user_action)); void ConfirmDirectoryReadAccess( const url::Origin& origin, const base::FilePath& path, - int process_id, - int frame_id, + GlobalFrameRoutingId frame_id, base::OnceCallback<void(PermissionStatus)> callback) override; - MOCK_METHOD5(ConfirmDirectoryReadAccess_, + MOCK_METHOD4(ConfirmDirectoryReadAccess_, void(const url::Origin& origin, const base::FilePath& path, - int process_id, - int frame_id, + GlobalFrameRoutingId frame_id, base::OnceCallback<void(PermissionStatus)>& callback)); void ConfirmSensitiveDirectoryAccess( const url::Origin& origin, const std::vector<base::FilePath>& paths, bool is_directory, - int process_id, - int frame_id, + GlobalFrameRoutingId frame_id, base::OnceCallback<void(SensitiveDirectoryResult)> callback) override; - MOCK_METHOD6( + MOCK_METHOD5( ConfirmSensitiveDirectoryAccess_, void(const url::Origin& origin, const std::vector<base::FilePath>& paths, bool is_directory, - int process_id, - int frame_id, + GlobalFrameRoutingId frame_id, base::OnceCallback<void(SensitiveDirectoryResult)>& callback)); void PerformAfterWriteChecks( std::unique_ptr<NativeFileSystemWriteItem> item, - int process_id, - int frame_id, + GlobalFrameRoutingId frame_id, base::OnceCallback<void(AfterWriteCheckResult)> callback) override; - MOCK_METHOD4(PerformAfterWriteChecks_, + MOCK_METHOD3(PerformAfterWriteChecks_, void(NativeFileSystemWriteItem* item, - int process_id, - int frame_id, + GlobalFrameRoutingId frame_id, base::OnceCallback<void(AfterWriteCheckResult)>& callback)); MOCK_METHOD1(CanObtainWritePermission, bool(const url::Origin& origin)); diff --git a/chromium/content/browser/native_file_system/mock_native_file_system_permission_grant.cc b/chromium/content/browser/native_file_system/mock_native_file_system_permission_grant.cc index 85699ded77a..7698d079824 100644 --- a/chromium/content/browser/native_file_system/mock_native_file_system_permission_grant.cc +++ b/chromium/content/browser/native_file_system/mock_native_file_system_permission_grant.cc @@ -12,10 +12,9 @@ MockNativeFileSystemPermissionGrant::~MockNativeFileSystemPermissionGrant() = default; void MockNativeFileSystemPermissionGrant::RequestPermission( - int process_id, - int frame_id, + GlobalFrameRoutingId frame_id, base::OnceCallback<void(PermissionRequestOutcome)> callback) { - RequestPermission_(process_id, frame_id, callback); + RequestPermission_(frame_id, callback); } } // namespace content diff --git a/chromium/content/browser/native_file_system/mock_native_file_system_permission_grant.h b/chromium/content/browser/native_file_system/mock_native_file_system_permission_grant.h index 77ef9501e6a..7e185e745dc 100644 --- a/chromium/content/browser/native_file_system/mock_native_file_system_permission_grant.h +++ b/chromium/content/browser/native_file_system/mock_native_file_system_permission_grant.h @@ -18,12 +18,10 @@ class MockNativeFileSystemPermissionGrant MOCK_METHOD0(GetStatus, PermissionStatus()); void RequestPermission( - int process_id, - int frame_id, + GlobalFrameRoutingId frame_id, base::OnceCallback<void(PermissionRequestOutcome)> callback) override; - MOCK_METHOD3(RequestPermission_, - void(int process_id, - int frame_id, + MOCK_METHOD2(RequestPermission_, + void(GlobalFrameRoutingId frame_id, base::OnceCallback<void(PermissionRequestOutcome)>&)); using NativeFileSystemPermissionGrant::NotifyPermissionStatusChanged; diff --git a/chromium/content/browser/native_file_system/native_file_system_directory_handle_impl.cc b/chromium/content/browser/native_file_system/native_file_system_directory_handle_impl.cc index b9f04c45e5e..89ea8eaf065 100644 --- a/chromium/content/browser/native_file_system/native_file_system_directory_handle_impl.cc +++ b/chromium/content/browser/native_file_system/native_file_system_directory_handle_impl.cc @@ -229,7 +229,7 @@ void NativeFileSystemDirectoryHandleImpl::Resolve( void NativeFileSystemDirectoryHandleImpl::ResolveImpl( ResolveCallback callback, NativeFileSystemTransferTokenImpl* possible_child) { - if (!possible_child) { + if (!possible_child || !possible_child->GetAsFileSystemURL()) { std::move(callback).Run( native_file_system_error::FromStatus( blink::mojom::NativeFileSystemStatus::kOperationFailed), @@ -238,7 +238,8 @@ void NativeFileSystemDirectoryHandleImpl::ResolveImpl( } const storage::FileSystemURL& parent_url = url(); - const storage::FileSystemURL& child_url = possible_child->url(); + const storage::FileSystemURL& child_url = + *possible_child->GetAsFileSystemURL(); // If two URLs are of a different type they are definitely not related. if (parent_url.type() != child_url.type()) { diff --git a/chromium/content/browser/native_file_system/native_file_system_file_handle_impl.cc b/chromium/content/browser/native_file_system/native_file_system_file_handle_impl.cc index 535ef4f4c59..6de257db371 100644 --- a/chromium/content/browser/native_file_system/native_file_system_file_handle_impl.cc +++ b/chromium/content/browser/native_file_system/native_file_system_file_handle_impl.cc @@ -7,10 +7,10 @@ #include "base/guid.h" #include "base/logging.h" #include "base/strings/stringprintf.h" -#include "base/task/post_task.h" #include "content/browser/native_file_system/native_file_system_error.h" #include "content/browser/native_file_system/native_file_system_transfer_token_impl.h" #include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "net/base/mime_util.h" #include "storage/browser/blob/blob_data_builder.h" @@ -108,7 +108,7 @@ void NativeFileSystemFileHandleImpl::IsSameEntry( void NativeFileSystemFileHandleImpl::IsSameEntryImpl( IsSameEntryCallback callback, NativeFileSystemTransferTokenImpl* other) { - if (!other) { + if (!other || !other->GetAsFileSystemURL()) { std::move(callback).Run( native_file_system_error::FromStatus( blink::mojom::NativeFileSystemStatus::kOperationFailed), @@ -122,7 +122,7 @@ void NativeFileSystemFileHandleImpl::IsSameEntryImpl( } const storage::FileSystemURL& url1 = url(); - const storage::FileSystemURL& url2 = other->url(); + const storage::FileSystemURL& url2 = *other->GetAsFileSystemURL(); // If two URLs are of a different type they are definitely not related. if (url1.type() != url2.type()) { @@ -216,8 +216,8 @@ void NativeFileSystemFileHandleImpl::DidGetMetaDataForBlob( blink::mojom::SerializedBlob::New(uuid, content_type, info.size, std::move(blob_remote))); - base::PostTask( - FROM_HERE, {BrowserThread::IO}, + GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&CreateBlobOnIOThread, base::WrapRefCounted(file_system_context()), base::WrapRefCounted(manager()->blob_context()), diff --git a/chromium/content/browser/native_file_system/native_file_system_file_handle_impl_unittest.cc b/chromium/content/browser/native_file_system/native_file_system_file_handle_impl_unittest.cc index f2d7a88eda5..2cb03f2ad02 100644 --- a/chromium/content/browser/native_file_system/native_file_system_file_handle_impl_unittest.cc +++ b/chromium/content/browser/native_file_system/native_file_system_file_handle_impl_unittest.cc @@ -71,8 +71,7 @@ class NativeFileSystemFileHandleImplTest : public testing::Test { handle_ = std::make_unique<NativeFileSystemFileHandleImpl>( manager_.get(), NativeFileSystemManagerImpl::BindingContext( - test_src_origin_, test_src_url_, /*process_id=*/1, - /*frame_id=*/MSG_ROUTING_NONE), + test_src_origin_, test_src_url_, /*process_id=*/1), test_file_url_, NativeFileSystemManagerImpl::SharedHandleState( allow_grant_, allow_grant_, /*file_system=*/{})); diff --git a/chromium/content/browser/native_file_system/native_file_system_file_writer_impl.cc b/chromium/content/browser/native_file_system/native_file_system_file_writer_impl.cc index ccaadc6301e..d7ce4e05b9e 100644 --- a/chromium/content/browser/native_file_system/native_file_system_file_writer_impl.cc +++ b/chromium/content/browser/native_file_system/native_file_system_file_writer_impl.cc @@ -326,8 +326,7 @@ void NativeFileSystemFileWriterImpl::DoAfterWriteCheck( // swap file and invoke the callback. base::ThreadPool::PostTask( FROM_HERE, {base::MayBlock()}, - base::BindOnce(base::IgnoreResult(&base::DeleteFile), swap_path, - /*recursive=*/false)); + base::BindOnce(base::GetDeleteFileCallback(), swap_path)); std::move(callback).Run(native_file_system_error::FromStatus( NativeFileSystemStatus::kOperationAborted, "Failed to perform Safe Browsing check.")); @@ -344,8 +343,7 @@ void NativeFileSystemFileWriterImpl::DoAfterWriteCheck( item->frame_url = file_writer->context().url; item->has_user_gesture = file_writer->has_transient_user_activation_; file_writer->manager()->permission_context()->PerformAfterWriteChecks( - std::move(item), file_writer->context().process_id, - file_writer->context().frame_id, + std::move(item), file_writer->context().frame_id, base::BindOnce(&NativeFileSystemFileWriterImpl::DidAfterWriteCheck, file_writer, swap_path, std::move(callback))); } @@ -368,8 +366,7 @@ void NativeFileSystemFileWriterImpl::DidAfterWriteCheck( // failed. base::ThreadPool::PostTask( FROM_HERE, {base::MayBlock()}, - base::BindOnce(base::IgnoreResult(&base::DeleteFile), swap_path, - /*recursive=*/false)); + base::BindOnce(base::GetDeleteFileCallback(), swap_path)); std::move(callback).Run(native_file_system_error::FromStatus( NativeFileSystemStatus::kOperationAborted, "Write operation blocked by Safe Browsing.")); @@ -447,7 +444,16 @@ void NativeFileSystemFileWriterImpl::DidAnnotateFile( void NativeFileSystemFileWriterImpl::ComputeHashForSwapFile( HashCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + +#if defined(OS_CHROMEOS) + DCHECK(swap_url().type() == storage::kFileSystemTypeNativeLocal || + swap_url().type() == storage::kFileSystemTypeProvided || + swap_url().type() == storage::kFileSystemTypeNativeForPlatformApp) + << swap_url().type(); +#else DCHECK_EQ(swap_url().type(), storage::kFileSystemTypeNativeLocal); +#endif + base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::MayBlock()}, base::BindOnce(&ReadAndComputeSHA256ChecksumAndSize, swap_url().path()), diff --git a/chromium/content/browser/native_file_system/native_file_system_file_writer_impl.h b/chromium/content/browser/native_file_system/native_file_system_file_writer_impl.h index 3aa0bca88bd..3975cecf5d0 100644 --- a/chromium/content/browser/native_file_system/native_file_system_file_writer_impl.h +++ b/chromium/content/browser/native_file_system/native_file_system_file_writer_impl.h @@ -99,15 +99,23 @@ class CONTENT_EXPORT NativeFileSystemFileWriterImpl void DidAnnotateFile(CloseCallback callback, quarantine::mojom::QuarantineFileResult result); - // After write checks only apply to native local paths. + // After write checks apply to native local paths, file system provider paths, + // and platform app native paths. bool RequireAfterWriteCheck() const { - return url().type() == storage::kFileSystemTypeNativeLocal; + return url().type() == storage::kFileSystemTypeNativeLocal || + url().type() == storage::kFileSystemTypeProvided || + url().type() == storage::kFileSystemTypeNativeForPlatformApp; } - // Quarantine checks only apply to native local paths. + // Quarantine checks apply to native local paths, file system provider paths, + // and platform app native paths. bool CanSkipQuarantineCheck() const { - return skip_quarantine_check_for_testing_ || - url().type() != storage::kFileSystemTypeNativeLocal; + bool need_quarantine_check = + url().type() == storage::kFileSystemTypeNativeLocal || + url().type() == storage::kFileSystemTypeProvided || + url().type() == storage::kFileSystemTypeNativeForPlatformApp; + + return skip_quarantine_check_for_testing_ || !need_quarantine_check; } void ComputeHashForSwapFile(HashCallback callback); diff --git a/chromium/content/browser/native_file_system/native_file_system_file_writer_impl_browsertest.cc b/chromium/content/browser/native_file_system/native_file_system_file_writer_impl_browsertest.cc index 5af79124fe6..04be7cb90c9 100644 --- a/chromium/content/browser/native_file_system/native_file_system_file_writer_impl_browsertest.cc +++ b/chromium/content/browser/native_file_system/native_file_system_file_writer_impl_browsertest.cc @@ -67,15 +67,13 @@ class NativeFileSystemFileWriterBrowserTest : public ContentBrowserTest { ui::SelectFileDialog::SetFactory( new FakeSelectFileDialogFactory({test_file})); EXPECT_TRUE(NavigateToURL(shell(), test_url_)); - EXPECT_EQ( - test_file.BaseName().AsUTF8Unsafe(), - EvalJs( - shell(), - "(async () => {" - " let e = await self.chooseFileSystemEntries({type: 'open-file'});" - " self.entry = e;" - " self.writers = [];" - " return e.name; })()")); + EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(), + EvalJs(shell(), + "(async () => {" + " let [e] = await self.showOpenFilePicker();" + " self.entry = e;" + " self.writers = [];" + " return e.name; })()")); const base::FilePath swap_file = base::FilePath(test_file).AddExtensionASCII(".crswap"); @@ -93,15 +91,13 @@ class NativeFileSystemFileWriterBrowserTest : public ContentBrowserTest { ui::SelectFileDialog::SetFactory( new FakeSelectFileDialogFactory({test_file})); EXPECT_TRUE(NavigateToURL(shell(), test_url_)); - EXPECT_EQ( - test_file.BaseName().AsUTF8Unsafe(), - EvalJs( - shell(), - "(async () => {" - " let e = await self.chooseFileSystemEntries({type: 'open-file'});" - " self.entry = e;" - " self.writers = [];" - " return e.name; })()")); + EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(), + EvalJs(shell(), + "(async () => {" + " let [e] = await self.showOpenFilePicker();" + " self.entry = e;" + " self.writers = [];" + " return e.name; })()")); const base::FilePath swap_file = base::FilePath(test_file).AddExtensionASCII(".crswap"); diff --git a/chromium/content/browser/native_file_system/native_file_system_file_writer_impl_unittest.cc b/chromium/content/browser/native_file_system/native_file_system_file_writer_impl_unittest.cc index bd740cd99b3..e12ba77ab8a 100644 --- a/chromium/content/browser/native_file_system/native_file_system_file_writer_impl_unittest.cc +++ b/chromium/content/browser/native_file_system/native_file_system_file_writer_impl_unittest.cc @@ -105,7 +105,7 @@ class NativeFileSystemFileWriterImplTest : public testing::Test { handle_ = std::make_unique<NativeFileSystemFileWriterImpl>( manager_.get(), NativeFileSystemManagerImpl::BindingContext(kTestOrigin, kTestURL, - kProcessId, kFrameId), + kFrameId), test_file_url_, test_swap_url_, NativeFileSystemManagerImpl::SharedHandleState( permission_grant_, permission_grant_, std::move(fs)), @@ -254,7 +254,8 @@ class NativeFileSystemFileWriterImplTest : public testing::Test { const GURL kTestURL = GURL("https://example.com/test"); const url::Origin kTestOrigin = url::Origin::Create(kTestURL); const int kProcessId = 1; - const int kFrameId = 2; + const int kFrameRoutingId = 2; + const GlobalFrameRoutingId kFrameId{kProcessId, kFrameRoutingId}; base::test::ScopedFeatureList scoped_feature_list_; BrowserTaskEnvironment task_environment_; @@ -543,8 +544,8 @@ TEST_F(NativeFileSystemFileWriterAfterWriteChecksTest, Allow) { Field(&NativeFileSystemWriteItem::size, Eq(3)), Field(&NativeFileSystemWriteItem::frame_url, Eq(kTestURL)), Field(&NativeFileSystemWriteItem::has_user_gesture, Eq(false))), - kProcessId, kFrameId, _)) - .WillOnce(base::test::RunOnceCallback<3>( + kFrameId, _)) + .WillOnce(base::test::RunOnceCallback<2>( NativeFileSystemPermissionContext::AfterWriteCheckResult::kAllow)); result = CloseSync(); @@ -564,9 +565,8 @@ TEST_F(NativeFileSystemFileWriterAfterWriteChecksTest, Block) { EXPECT_EQ(result, NativeFileSystemStatus::kOk); EXPECT_EQ(bytes_written, 3u); - EXPECT_CALL(permission_context_, - PerformAfterWriteChecks_(_, kProcessId, kFrameId, _)) - .WillOnce(base::test::RunOnceCallback<3>( + EXPECT_CALL(permission_context_, PerformAfterWriteChecks_(_, kFrameId, _)) + .WillOnce(base::test::RunOnceCallback<2>( NativeFileSystemPermissionContext::AfterWriteCheckResult::kBlock)); result = CloseSync(); @@ -591,12 +591,12 @@ TEST_F(NativeFileSystemFileWriterAfterWriteChecksTest, HandleCloseDuringCheck) { SBCallback sb_callback; base::RunLoop loop; EXPECT_CALL(permission_context_, PerformAfterWriteChecks_) - .WillOnce( - testing::Invoke([&](NativeFileSystemWriteItem* item, int process_id, - int frame_id, SBCallback& callback) { - sb_callback = std::move(callback); - loop.Quit(); - })); + .WillOnce(testing::Invoke([&](NativeFileSystemWriteItem* item, + GlobalFrameRoutingId frame_id, + SBCallback& callback) { + sb_callback = std::move(callback); + loop.Quit(); + })); handle_->Close(base::DoNothing()); loop.Run(); diff --git a/chromium/content/browser/native_file_system/native_file_system_handle_base.cc b/chromium/content/browser/native_file_system/native_file_system_handle_base.cc index a21abf35a91..a33641663cb 100644 --- a/chromium/content/browser/native_file_system/native_file_system_handle_base.cc +++ b/chromium/content/browser/native_file_system/native_file_system_handle_base.cc @@ -9,6 +9,7 @@ #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/back_forward_cache.h" #include "content/public/browser/browser_task_traits.h" +#include "storage/common/file_system/file_system_types.h" namespace content { @@ -26,66 +27,42 @@ NativeFileSystemHandleBase::NativeFileSystemHandleBase( DCHECK_EQ(url_.mount_type() == storage::kFileSystemTypeIsolated, handle_state_.file_system.is_valid()) << url_.mount_type(); - // For now only support sandboxed file system and native file system. + + // We support sandboxed file system and native file systems on all platforms. DCHECK(url_.type() == storage::kFileSystemTypeNativeLocal || - url_.type() == storage::kFileSystemTypePersistent || url_.type() == storage::kFileSystemTypeTemporary || +#if defined(OS_CHROMEOS) + // On Chrome OS, we additionally support File System Provider API, and + // file systems available to platform Apps. + url_.type() == storage::kFileSystemTypeNativeForPlatformApp || + url_.type() == storage::kFileSystemTypeProvided || +#endif url_.type() == storage::kFileSystemTypeTest) << url_.type(); if (ShouldTrackUsage()) { - DCHECK_EQ(url_.type(), storage::kFileSystemTypeNativeLocal); + DCHECK(url_.type() == storage::kFileSystemTypeNativeLocal || + url_.type() == storage::kFileSystemTypeNativeForPlatformApp || + url_.type() == storage::kFileSystemTypeProvided) + << url.type(); DCHECK_EQ(url_.mount_type(), storage::kFileSystemTypeIsolated); - handle_state_.read_grant->AddObserver(this); - // In some cases we use the same grant for read and write access. In that - // case only add an observer once. - if (handle_state_.read_grant != handle_state_.write_grant) - handle_state_.write_grant->AddObserver(this); - - Observe(WebContentsImpl::FromRenderFrameHostID(context_.process_id, - context_.frame_id)); + Observe(WebContentsImpl::FromRenderFrameHostID(context_.frame_id)); // Disable back-forward cache as native file system's usage of // RenderFrameHost::IsCurrent at the moment is not compatible with bfcache. - BackForwardCache::DisableForRenderFrameHost( - GlobalFrameRoutingId(context_.process_id, context_.frame_id), - "NativeFileSystem"); - - if (is_directory) { - // For usage reporting purposes try to get the root path of the isolated - // file system, i.e. the path the user picked in a directory picker. - auto* isolated_context = storage::IsolatedContext::GetInstance(); - if (!isolated_context->GetRegisteredPath( - handle_state_.file_system.id(), &directory_for_usage_tracking_)) { - // If for some reason the isolated file system no longer exists, fall - // back to the path of the handle itself, which could be a child of - // the originally picked path. - directory_for_usage_tracking_ = url.path(); - } - } - + BackForwardCache::DisableForRenderFrameHost(context_.frame_id, + "NativeFileSystem"); if (web_contents()) web_contents()->IncrementNativeFileSystemHandleCount(); - UpdateUsage(); } } NativeFileSystemHandleBase::~NativeFileSystemHandleBase() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // It is fine to remove an observer that never was added, so no need to check - // for URL type and/or the same grant being used for read and write access. - handle_state_.read_grant->RemoveObserver(this); - handle_state_.write_grant->RemoveObserver(this); if (ShouldTrackUsage() && web_contents()) { web_contents()->DecrementNativeFileSystemHandleCount(); - if (!directory_for_usage_tracking_.empty() && was_readable_at_last_check_) { - web_contents()->RemoveNativeFileSystemDirectoryHandle( - directory_for_usage_tracking_); - } - if (was_writable_at_last_check_) - web_contents()->DecrementWritableNativeFileSystemHandleCount(); } } @@ -98,7 +75,6 @@ NativeFileSystemHandleBase::GetReadPermissionStatus() { NativeFileSystemHandleBase::PermissionStatus NativeFileSystemHandleBase::GetWritePermissionStatus() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - UpdateUsage(); // It is not currently possible to have write only handles, so first check the // read permission status. See also: // http://wicg.github.io/native-file-system/#api-filesystemhandle-querypermission @@ -138,7 +114,7 @@ void NativeFileSystemHandleBase::DoRequestPermission( } if (!writable) { handle_state_.read_grant->RequestPermission( - context().process_id, context().frame_id, + context().frame_id, base::BindOnce(&NativeFileSystemHandleBase::DidRequestPermission, AsWeakPtr(), writable, std::move(callback))); return; @@ -151,12 +127,12 @@ void NativeFileSystemHandleBase::DoRequestPermission( // the write permission request probably fails the same way. And we check // the final permission status after the permission request completes // anyway. - handle_state_.read_grant->RequestPermission( - context().process_id, context().frame_id, base::DoNothing()); + handle_state_.read_grant->RequestPermission(context().frame_id, + base::DoNothing()); } handle_state_.write_grant->RequestPermission( - context().process_id, context().frame_id, + context().frame_id, base::BindOnce(&NativeFileSystemHandleBase::DidRequestPermission, AsWeakPtr(), writable, std::move(callback))); } @@ -198,40 +174,4 @@ void NativeFileSystemHandleBase::DidRequestPermission( NOTREACHED(); } -void NativeFileSystemHandleBase::UpdateUsage() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!ShouldTrackUsage() || !web_contents()) - return; - - bool is_readable = - handle_state_.read_grant->GetStatus() == PermissionStatus::GRANTED; - if (is_readable != was_readable_at_last_check_) { - was_readable_at_last_check_ = is_readable; - if (!directory_for_usage_tracking_.empty()) { - if (is_readable) { - web_contents()->AddNativeFileSystemDirectoryHandle( - directory_for_usage_tracking_); - } else { - web_contents()->RemoveNativeFileSystemDirectoryHandle( - directory_for_usage_tracking_); - } - } - } - - bool is_writable = is_readable && handle_state_.write_grant->GetStatus() == - PermissionStatus::GRANTED; - if (is_writable != was_writable_at_last_check_) { - was_writable_at_last_check_ = is_writable; - if (is_writable) - web_contents()->IncrementWritableNativeFileSystemHandleCount(); - else - web_contents()->DecrementWritableNativeFileSystemHandleCount(); - } -} - -void NativeFileSystemHandleBase::OnPermissionStatusChanged() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - UpdateUsage(); -} - } // namespace content diff --git a/chromium/content/browser/native_file_system/native_file_system_handle_base.h b/chromium/content/browser/native_file_system/native_file_system_handle_base.h index 42986983606..72a88b56431 100644 --- a/chromium/content/browser/native_file_system/native_file_system_handle_base.h +++ b/chromium/content/browser/native_file_system/native_file_system_handle_base.h @@ -35,9 +35,7 @@ namespace content { // sequence. That sequence also has to be the same sequence on which the // NativeFileSystemPermissionContext expects to be interacted with, which // is the UI thread. -class CONTENT_EXPORT NativeFileSystemHandleBase - : public NativeFileSystemPermissionGrant::Observer, - public WebContentsObserver { +class CONTENT_EXPORT NativeFileSystemHandleBase : public WebContentsObserver { public: using BindingContext = NativeFileSystemManagerImpl::BindingContext; using SharedHandleState = NativeFileSystemManagerImpl::SharedHandleState; @@ -93,9 +91,6 @@ class CONTENT_EXPORT NativeFileSystemHandleBase virtual base::WeakPtr<NativeFileSystemHandleBase> AsWeakPtr() = 0; - // NativeFileSystemPermissionGrant::Observer: - void OnPermissionStatusChanged() override; - // Invokes |method| on the correct sequence on this handle's // FileSystemOperationRunner, passing |args| and a callback to the method. The // passed in |callback| is wrapped to make sure it is called on the correct @@ -195,7 +190,8 @@ class CONTENT_EXPORT NativeFileSystemHandleBase NativeFileSystemPermissionGrant::PermissionRequestOutcome outcome); bool ShouldTrackUsage() const { - return url_.type() == storage::kFileSystemTypeNativeLocal; + return url_.type() != storage::kFileSystemTypeTemporary && + url_.type() != storage::kFileSystemTypeTest; } // The NativeFileSystemManagerImpl that owns this instance. @@ -204,12 +200,6 @@ class CONTENT_EXPORT NativeFileSystemHandleBase const storage::FileSystemURL url_; const SharedHandleState handle_state_; - base::FilePath directory_for_usage_tracking_; - bool was_readable_at_last_check_ = false; - bool was_writable_at_last_check_ = false; - - void UpdateUsage(); - DISALLOW_COPY_AND_ASSIGN(NativeFileSystemHandleBase); }; diff --git a/chromium/content/browser/native_file_system/native_file_system_handle_base_unittest.cc b/chromium/content/browser/native_file_system/native_file_system_handle_base_unittest.cc index f5f15a72b64..0fbb5e10e6e 100644 --- a/chromium/content/browser/native_file_system/native_file_system_handle_base_unittest.cc +++ b/chromium/content/browser/native_file_system/native_file_system_handle_base_unittest.cc @@ -92,11 +92,11 @@ TEST_F(NativeFileSystemHandleBaseTest, GetReadPermissionStatus) { auto url = FileSystemURL::CreateForTest(kTestOrigin, storage::kFileSystemTypeTest, base::FilePath::FromUTF8Unsafe("/test")); - TestNativeFileSystemHandle handle(manager_.get(), - NativeFileSystemManagerImpl::BindingContext( - kTestOrigin, kTestURL, /*process_id=*/1, - /*frame_id=*/MSG_ROUTING_NONE), - url, handle_state_); + TestNativeFileSystemHandle handle( + manager_.get(), + NativeFileSystemManagerImpl::BindingContext(kTestOrigin, kTestURL, + /*worker_process_id=*/1), + url, handle_state_); EXPECT_CALL(*read_grant_, GetStatus()) .WillOnce(testing::Return(PermissionStatus::ASK)); @@ -112,11 +112,11 @@ TEST_F(NativeFileSystemHandleBaseTest, auto url = FileSystemURL::CreateForTest(kTestOrigin, storage::kFileSystemTypeTest, base::FilePath::FromUTF8Unsafe("/test")); - TestNativeFileSystemHandle handle(manager_.get(), - NativeFileSystemManagerImpl::BindingContext( - kTestOrigin, kTestURL, /*process_id=*/1, - /*frame_id=*/MSG_ROUTING_NONE), - url, handle_state_); + TestNativeFileSystemHandle handle( + manager_.get(), + NativeFileSystemManagerImpl::BindingContext(kTestOrigin, kTestURL, + /*worker_process_id=*/1), + url, handle_state_); EXPECT_CALL(*read_grant_, GetStatus()) .WillOnce(testing::Return(PermissionStatus::ASK)); @@ -132,11 +132,11 @@ TEST_F(NativeFileSystemHandleBaseTest, auto url = FileSystemURL::CreateForTest(kTestOrigin, storage::kFileSystemTypeTest, base::FilePath::FromUTF8Unsafe("/test")); - TestNativeFileSystemHandle handle(manager_.get(), - NativeFileSystemManagerImpl::BindingContext( - kTestOrigin, kTestURL, /*process_id=*/1, - /*frame_id=*/MSG_ROUTING_NONE), - url, handle_state_); + TestNativeFileSystemHandle handle( + manager_.get(), + NativeFileSystemManagerImpl::BindingContext(kTestOrigin, kTestURL, + /*worker_process_id=*/1), + url, handle_state_); EXPECT_CALL(*read_grant_, GetStatus()) .WillOnce(testing::Return(PermissionStatus::GRANTED)); @@ -149,11 +149,11 @@ TEST_F(NativeFileSystemHandleBaseTest, RequestWritePermission_AlreadyGranted) { auto url = FileSystemURL::CreateForTest(kTestOrigin, storage::kFileSystemTypeTest, base::FilePath::FromUTF8Unsafe("/test")); - TestNativeFileSystemHandle handle(manager_.get(), - NativeFileSystemManagerImpl::BindingContext( - kTestOrigin, kTestURL, /*process_id=*/1, - /*frame_id=*/MSG_ROUTING_NONE), - url, handle_state_); + TestNativeFileSystemHandle handle( + manager_.get(), + NativeFileSystemManagerImpl::BindingContext(kTestOrigin, kTestURL, + /*worker_process_id=*/1), + url, handle_state_); EXPECT_CALL(*read_grant_, GetStatus()) .WillOnce(testing::Return(PermissionStatus::GRANTED)); @@ -175,16 +175,16 @@ TEST_F(NativeFileSystemHandleBaseTest, RequestWritePermission_AlreadyGranted) { TEST_F(NativeFileSystemHandleBaseTest, RequestWritePermission) { const int kProcessId = 1; - const int kFrameId = 2; + const int kFrameRoutingId = 2; + const GlobalFrameRoutingId kFrameId(kProcessId, kFrameRoutingId); auto url = FileSystemURL::CreateForTest(kTestOrigin, storage::kFileSystemTypeTest, base::FilePath::FromUTF8Unsafe("/test")); - TestNativeFileSystemHandle handle( - manager_.get(), - NativeFileSystemManagerImpl::BindingContext(kTestOrigin, kTestURL, - kProcessId, kFrameId), - url, handle_state_); + TestNativeFileSystemHandle handle(manager_.get(), + NativeFileSystemManagerImpl::BindingContext( + kTestOrigin, kTestURL, kFrameId), + url, handle_state_); EXPECT_CALL(*read_grant_, GetStatus()) .WillRepeatedly(testing::Return(PermissionStatus::GRANTED)); @@ -192,10 +192,9 @@ TEST_F(NativeFileSystemHandleBaseTest, RequestWritePermission) { testing::InSequence sequence; EXPECT_CALL(*write_grant_, GetStatus()) .WillOnce(testing::Return(PermissionStatus::ASK)); - EXPECT_CALL(*write_grant_, - RequestPermission_(kProcessId, kFrameId, testing::_)) + EXPECT_CALL(*write_grant_, RequestPermission_(kFrameId, testing::_)) .WillOnce( - RunOnceCallback<2>(NativeFileSystemPermissionGrant:: + RunOnceCallback<1>(NativeFileSystemPermissionGrant:: PermissionRequestOutcome::kUserGranted)); EXPECT_CALL(*write_grant_, GetStatus()) .WillOnce(testing::Return(PermissionStatus::GRANTED)); diff --git a/chromium/content/browser/native_file_system/native_file_system_manager_impl.cc b/chromium/content/browser/native_file_system/native_file_system_manager_impl.cc index 2258316ff17..0be4b9e64fe 100644 --- a/chromium/content/browser/native_file_system/native_file_system_manager_impl.cc +++ b/chromium/content/browser/native_file_system/native_file_system_manager_impl.cc @@ -10,7 +10,6 @@ #include "base/metrics/histogram_functions.h" #include "base/notreached.h" #include "base/strings/strcat.h" -#include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "content/browser/native_file_system/file_system_chooser.h" #include "content/browser/native_file_system/fixed_native_file_system_permission_grant.h" @@ -25,6 +24,7 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_switches.h" +#include "content/public/common/url_utils.h" #include "mojo/public/cpp/bindings/callback_helpers.h" #include "net/base/escape.h" #include "services/network/public/cpp/is_potentially_trustworthy.h" @@ -47,13 +47,20 @@ using storage::FileSystemContext; namespace { +#if defined(OS_CHROMEOS) +// Path prefix for Chrome OS File System Provider (FSP) file systems. Copied +// here to avoid complex dependencies. See |kProvidedMountPointRoot| in +// chrome/browser/chromeos/file_system_provider/mount_path_util.cc. +// Files and directories provided by FSP API resides in this directory. +static constexpr char kProvidedMountPointRoot[] = "/provided"; +#endif // OS_CHROMEOS + void ShowFilePickerOnUIThread(const url::Origin& requesting_origin, - int render_process_id, - int frame_id, + GlobalFrameRoutingId frame_id, const FileSystemChooser::Options& options, FileSystemChooser::ResultCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - RenderFrameHost* rfh = RenderFrameHost::FromID(render_process_id, frame_id); + RenderFrameHost* rfh = RenderFrameHost::FromID(frame_id); WebContents* web_contents = WebContents::FromRenderFrameHost(rfh); if (!web_contents) { @@ -101,7 +108,7 @@ bool IsValidTransferToken( return false; } - if (token->url().origin() != expected_origin) { + if (!token->MatchesOrigin(expected_origin)) { return false; } return true; @@ -183,8 +190,8 @@ void NativeFileSystemManagerImpl::GetSandboxedFileSystem( weak_factory_.GetWeakPtr(), receivers_.current_context(), std::move(callback), base::SequencedTaskRunnerHandle::Get()); - base::PostTask(FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&FileSystemContext::OpenFileSystem, context(), + GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&FileSystemContext::OpenFileSystem, context(), receivers_.current_context().origin, storage::kFileSystemTypeTemporary, storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT, @@ -218,8 +225,7 @@ void NativeFileSystemManagerImpl::ChooseEntries( return; } - RenderFrameHost* rfh = - RenderFrameHost::FromID(context.process_id, context.frame_id); + RenderFrameHost* rfh = RenderFrameHost::FromID(context.frame_id); if (!rfh) { std::move(callback).Run( native_file_system_error::FromStatus( @@ -244,7 +250,7 @@ void NativeFileSystemManagerImpl::ChooseEntries( FileSystemChooser::Options options(type, std::move(accepts), include_accepts_all); ShowFilePickerOnUIThread( - context.origin, context.process_id, context.frame_id, options, + context.origin, context.frame_id, options, base::BindOnce(&NativeFileSystemManagerImpl::DidChooseEntries, weak_factory_.GetWeakPtr(), context, options, std::move(callback))); @@ -306,11 +312,13 @@ base::FilePath DeserializePath(const std::string& bytes) { void NativeFileSystemManagerImpl::DidResolveForSerializeHandle( SerializeHandleCallback callback, NativeFileSystemTransferTokenImpl* resolved_token) { - if (!resolved_token) { + if (!resolved_token || !resolved_token->GetAsFileSystemURL()) { std::move(callback).Run({}); return; } + const storage::FileSystemURL& url = *resolved_token->GetAsFileSystemURL(); + NativeFileSystemHandleData data; data.set_handle_type( resolved_token->type() == @@ -318,13 +326,12 @@ void NativeFileSystemManagerImpl::DidResolveForSerializeHandle( ? NativeFileSystemHandleData::kFile : NativeFileSystemHandleData::kDirectory); - switch (resolved_token->url().type()) { + switch (url.type()) { case storage::kFileSystemTypeNativeLocal: { - DCHECK_EQ(resolved_token->url().mount_type(), - storage::kFileSystemTypeIsolated); + DCHECK_EQ(url.mount_type(), storage::kFileSystemTypeIsolated); base::FilePath root_path; storage::IsolatedContext::GetInstance()->GetRegisteredPath( - resolved_token->shared_handle_state().file_system.id(), &root_path); + url.filesystem_id(), &root_path); data.mutable_native()->set_root_path(SerializePath(root_path)); base::FilePath relative_path; @@ -333,19 +340,29 @@ void NativeFileSystemManagerImpl::DidResolveForSerializeHandle( // but fails if the path we're looking for is equal to the |root_path|. // So special case that case (in which case relative path would be empty // anyway). - if (root_path != resolved_token->url().path()) { - bool relative_path_result = root_path.AppendRelativePath( - resolved_token->url().path(), &relative_path); + if (root_path != url.path()) { + bool relative_path_result = + root_path.AppendRelativePath(url.path(), &relative_path); DCHECK(relative_path_result); } data.mutable_native()->set_relative_path(SerializePath(relative_path)); break; } case storage::kFileSystemTypeTemporary: { - base::FilePath virtual_path = resolved_token->url().virtual_path(); + base::FilePath virtual_path = url.virtual_path(); data.mutable_sandboxed()->set_virtual_path(SerializePath(virtual_path)); break; } + +#if defined(OS_CHROMEOS) + // For now, we don't support serializing handles for Chrome OS specific + // types, run |callback| with an empty vector to indicate an error. + case storage::kFileSystemTypeProvided: + case storage::kFileSystemTypeNativeForPlatformApp: + std::move(callback).Run({}); + return; +#endif + default: NOTREACHED(); } @@ -399,35 +416,13 @@ void NativeFileSystemManagerImpl::DeserializeHandle( const bool is_directory = data.handle_type() == NativeFileSystemHandleData::kDirectory; - scoped_refptr<NativeFileSystemPermissionGrant> read_grant, write_grant; - if (permission_context_) { - const bool permission_is_directory = - is_directory || !relative_path.empty(); - read_grant = permission_context_->GetReadPermissionGrant( - origin, root_path, permission_is_directory, - /*process_id=*/ChildProcessHost::kInvalidUniqueID, - /*frame_id=*/MSG_ROUTING_NONE, - NativeFileSystemPermissionContext::UserAction::kLoadFromStorage); - write_grant = permission_context_->GetWritePermissionGrant( - origin, root_path, permission_is_directory, - /*process_id=*/ChildProcessHost::kInvalidUniqueID, - /*frame_id=*/MSG_ROUTING_NONE, - NativeFileSystemPermissionContext::UserAction::kLoadFromStorage); - } else { - // Auto-deny all grants if no permission context is available, - // unless Experimental Web Platform features are enabled. - // This happens for example in content_shell. - read_grant = write_grant = - base::MakeRefCounted<FixedNativeFileSystemPermissionGrant>( - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableExperimentalWebPlatformFeatures) - ? PermissionStatus::GRANTED - : PermissionStatus::DENIED); - } + SharedHandleState handle_state = GetSharedHandleStateForPath( + root_path, origin, std::move(root.file_system), + is_directory || !relative_path.empty(), + NativeFileSystemPermissionContext::UserAction::kLoadFromStorage); - CreateTransferTokenImpl( - child, SharedHandleState(read_grant, write_grant, root.file_system), - is_directory, std::move(token)); + CreateTransferTokenImpl(child, handle_state, is_directory, + std::move(token)); break; } case NativeFileSystemHandleData::DATA_NOT_SET: @@ -447,42 +442,18 @@ NativeFileSystemManagerImpl::CreateFileEntryFromPath( blink::mojom::NativeFileSystemEntryPtr NativeFileSystemManagerImpl::CreateDirectoryEntryFromPath( const BindingContext& binding_context, - const base::FilePath& directory_path) { + const base::FilePath& file_path) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - auto url = - CreateFileSystemURLFromPath(binding_context.origin, directory_path); + auto url = CreateFileSystemURLFromPath(binding_context.origin, file_path); - scoped_refptr<NativeFileSystemPermissionGrant> read_grant, write_grant; - if (permission_context_) { - read_grant = permission_context_->GetReadPermissionGrant( - binding_context.origin, directory_path, /*is_directory=*/true, - binding_context.process_id, binding_context.frame_id, - NativeFileSystemPermissionContext::UserAction::kOpen); - write_grant = permission_context_->GetWritePermissionGrant( - binding_context.origin, directory_path, /*is_directory=*/true, - binding_context.process_id, binding_context.frame_id, - NativeFileSystemPermissionContext::UserAction::kOpen); - } else { - // Grant read permission even without a permission_context_, as the picker - // itself is enough UI to assume user intent. - read_grant = base::MakeRefCounted<FixedNativeFileSystemPermissionGrant>( - PermissionStatus::GRANTED); - // Auto-deny all write grants if no permisson context is available, unless - // Experimental Web Platform features are enabled. - // TODO(mek): Remove experimental web platform check when permission UI is - // implemented. - write_grant = base::MakeRefCounted<FixedNativeFileSystemPermissionGrant>( - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableExperimentalWebPlatformFeatures) - ? PermissionStatus::GRANTED - : PermissionStatus::DENIED); - } + SharedHandleState shared_handle_state = GetSharedHandleStateForPath( + file_path, binding_context.origin, std::move(url.file_system), + /*is_directory=*/true, + NativeFileSystemPermissionContext::UserAction::kOpen); return blink::mojom::NativeFileSystemEntry::New( - blink::mojom::NativeFileSystemHandle::NewDirectory(CreateDirectoryHandle( - binding_context, url.url, - SharedHandleState(std::move(read_grant), std::move(write_grant), - std::move(url.file_system)))), + blink::mojom::NativeFileSystemHandle::NewDirectory( + CreateDirectoryHandle(binding_context, url.url, shared_handle_state)), url.base_name); } @@ -542,8 +513,7 @@ NativeFileSystemManagerImpl::CreateFileWriter( mojo::PendingRemote<blink::mojom::NativeFileSystemFileWriter> result; - RenderFrameHost* rfh = RenderFrameHost::FromID(binding_context.process_id, - binding_context.frame_id); + RenderFrameHost* rfh = RenderFrameHost::FromID(binding_context.frame_id); bool has_transient_user_activation = rfh && rfh->HasTransientUserActivation(); writer_receivers_.Add(std::make_unique<NativeFileSystemFileWriterImpl>( this, binding_context, url, swap_url, handle_state, @@ -605,9 +575,7 @@ void NativeFileSystemManagerImpl::DidResolveTransferTokenForFileHandle( return; } - file_receivers_.Add(std::make_unique<NativeFileSystemFileHandleImpl>( - this, binding_context, resolved_token->url(), - resolved_token->shared_handle_state()), + file_receivers_.Add(resolved_token->CreateFileHandle(binding_context), std::move(file_handle_receiver)); } @@ -627,9 +595,7 @@ void NativeFileSystemManagerImpl::DidResolveTransferTokenForDirectoryHandle( } directory_receivers_.Add( - std::make_unique<NativeFileSystemDirectoryHandleImpl>( - this, binding_context, resolved_token->url(), - resolved_token->shared_handle_state()), + resolved_token->CreateDirectoryHandle(binding_context), std::move(directory_handle_receiver)); } @@ -696,7 +662,7 @@ void NativeFileSystemManagerImpl::DidChooseEntries( options.type() == blink::mojom::ChooseFileSystemEntryType::kOpenDirectory; permission_context_->ConfirmSensitiveDirectoryAccess( binding_context.origin, entries_copy, is_directory, - binding_context.process_id, binding_context.frame_id, + binding_context.frame_id, base::BindOnce( &NativeFileSystemManagerImpl::DidVerifySensitiveDirectoryAccess, weak_factory_.GetWeakPtr(), binding_context, options, @@ -722,8 +688,7 @@ void NativeFileSystemManagerImpl::DidVerifySensitiveDirectoryAccess( } if (result == SensitiveDirectoryResult::kTryAgain) { ShowFilePickerOnUIThread( - binding_context.origin, binding_context.process_id, - binding_context.frame_id, options, + binding_context.origin, binding_context.frame_id, options, base::BindOnce(&NativeFileSystemManagerImpl::DidChooseEntries, weak_factory_.GetWeakPtr(), binding_context, options, std::move(callback))); @@ -735,8 +700,7 @@ void NativeFileSystemManagerImpl::DidVerifySensitiveDirectoryAccess( DCHECK_EQ(entries.size(), 1u); if (permission_context_) { permission_context_->ConfirmDirectoryReadAccess( - binding_context.origin, entries.front(), binding_context.process_id, - binding_context.frame_id, + binding_context.origin, entries.front(), binding_context.frame_id, base::BindOnce(&NativeFileSystemManagerImpl::DidChooseDirectory, this, binding_context, entries.front(), std::move(callback))); @@ -818,7 +782,7 @@ void NativeFileSystemManagerImpl::CreateTransferTokenImpl( receiver) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - auto token_impl = std::make_unique<NativeFileSystemTransferTokenImpl>( + auto token_impl = NativeFileSystemTransferTokenImpl::Create( url, handle_state, is_directory ? NativeFileSystemTransferTokenImpl::HandleType::kDirectory : NativeFileSystemTransferTokenImpl::HandleType::kFile, @@ -859,10 +823,22 @@ NativeFileSystemManagerImpl::CreateFileSystemURLFromPath( DCHECK(isolated_context); FileSystemURLAndFSHandle result; + storage::FileSystemType fs_type = storage::kFileSystemTypeNativeLocal; + +#if defined(OS_CHROMEOS) + // TODO(crbug.com/1093653): Support Chrome OS File System Provider in all Web + // Apps. For now, we only support FSP for WebUIs. + bool is_web_ui = HasWebUIScheme(origin.GetURL()); + // Check the path prefix to determine if a file is provided by FSP API. + bool is_provided_path = + base::StartsWith(path.AsUTF8Unsafe(), kProvidedMountPointRoot, + base::CompareCase::SENSITIVE); + if (is_web_ui && is_provided_path) + fs_type = storage::kFileSystemTypeNativeForPlatformApp; +#endif result.file_system = isolated_context->RegisterFileSystemForPath( - storage::kFileSystemTypeNativeLocal, std::string(), path, - &result.base_name); + fs_type, std::string(), path, &result.base_name); base::FilePath root_path = isolated_context->CreateVirtualRootPath(result.file_system.id()); @@ -884,19 +860,30 @@ NativeFileSystemManagerImpl::CreateFileEntryFromPathImpl( DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto url = CreateFileSystemURLFromPath(binding_context.origin, file_path); + SharedHandleState shared_handle_state = GetSharedHandleStateForPath( + file_path, binding_context.origin, std::move(url.file_system), + /*is_directory=*/false, user_action); + + return blink::mojom::NativeFileSystemEntry::New( + blink::mojom::NativeFileSystemHandle::NewFile( + CreateFileHandle(binding_context, url.url, shared_handle_state)), + url.base_name); +} + +NativeFileSystemManagerImpl::SharedHandleState +NativeFileSystemManagerImpl::GetSharedHandleStateForPath( + const base::FilePath& path, + const url::Origin& origin, + storage::IsolatedContext::ScopedFSHandle file_system, + bool is_directory, + NativeFileSystemPermissionContext::UserAction user_action) { scoped_refptr<NativeFileSystemPermissionGrant> read_grant, write_grant; if (permission_context_) { read_grant = permission_context_->GetReadPermissionGrant( - binding_context.origin, file_path, /*is_directory=*/false, - binding_context.process_id, binding_context.frame_id, user_action); + origin, path, is_directory, user_action); write_grant = permission_context_->GetWritePermissionGrant( - binding_context.origin, file_path, /*is_directory=*/false, - binding_context.process_id, binding_context.frame_id, user_action); + origin, path, is_directory, user_action); } else { - // Grant read permission even without a permission_context_, as the picker - // itself is enough UI to assume user intent. - read_grant = base::MakeRefCounted<FixedNativeFileSystemPermissionGrant>( - PermissionStatus::GRANTED); // Auto-deny all write grants if no permisson context is available, unless // Experimental Web Platform features are enabled. // TODO(mek): Remove experimental web platform check when permission UI is @@ -906,14 +893,18 @@ NativeFileSystemManagerImpl::CreateFileEntryFromPathImpl( switches::kEnableExperimentalWebPlatformFeatures) ? PermissionStatus::GRANTED : PermissionStatus::DENIED); + if (user_action == + NativeFileSystemPermissionContext::UserAction::kLoadFromStorage) { + read_grant = write_grant; + } else { + // Grant read permission even without a permission_context_, as the picker + // itself is enough UI to assume user intent. + read_grant = base::MakeRefCounted<FixedNativeFileSystemPermissionGrant>( + PermissionStatus::GRANTED); + } } - - return blink::mojom::NativeFileSystemEntry::New( - blink::mojom::NativeFileSystemHandle::NewFile(CreateFileHandle( - binding_context, url.url, - SharedHandleState(std::move(read_grant), std::move(write_grant), - std::move(url.file_system)))), - url.base_name); + return SharedHandleState(std::move(read_grant), std::move(write_grant), + file_system); } } // namespace content diff --git a/chromium/content/browser/native_file_system/native_file_system_manager_impl.h b/chromium/content/browser/native_file_system/native_file_system_manager_impl.h index 8f74ad42c64..2339ee90a6b 100644 --- a/chromium/content/browser/native_file_system/native_file_system_manager_impl.h +++ b/chromium/content/browser/native_file_system/native_file_system_manager_impl.h @@ -172,17 +172,6 @@ class CONTENT_EXPORT NativeFileSystemManagerImpl mojo::PendingRemote<blink::mojom::NativeFileSystemTransferToken> token, ResolvedTokenCallback callback); - void DidResolveTransferTokenForFileHandle( - const BindingContext& binding_context, - mojo::PendingReceiver<blink::mojom::NativeFileSystemFileHandle> - file_handle_receiver, - NativeFileSystemTransferTokenImpl* resolved_token); - void DidResolveTransferTokenForDirectoryHandle( - const BindingContext& binding_context, - mojo::PendingReceiver<blink::mojom::NativeFileSystemDirectoryHandle> - directory_handle_receiver, - NativeFileSystemTransferTokenImpl* resolved_token); - storage::FileSystemContext* context() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return context_.get(); @@ -206,6 +195,23 @@ class CONTENT_EXPORT NativeFileSystemManagerImpl // token that doesn't exist. void RemoveToken(const base::UnguessableToken& token); + SharedHandleState GetSharedHandleStateForPath( + const base::FilePath& path, + const url::Origin& origin, + storage::IsolatedContext::ScopedFSHandle file_system, + bool is_directory, + NativeFileSystemPermissionContext::UserAction user_action); + + // Creates a FileSystemURL which corresponds to a FilePath and Origin. + struct FileSystemURLAndFSHandle { + storage::FileSystemURL url; + std::string base_name; + storage::IsolatedContext::ScopedFSHandle file_system; + }; + FileSystemURLAndFSHandle CreateFileSystemURLFromPath( + const url::Origin& origin, + const base::FilePath& path); + private: friend class NativeFileSystemFileHandleImpl; @@ -248,20 +254,20 @@ class CONTENT_EXPORT NativeFileSystemManagerImpl ResolvedTokenCallback callback, const base::UnguessableToken& token); + void DidResolveTransferTokenForFileHandle( + const BindingContext& binding_context, + mojo::PendingReceiver<blink::mojom::NativeFileSystemFileHandle> + file_handle_receiver, + NativeFileSystemTransferTokenImpl* resolved_token); + void DidResolveTransferTokenForDirectoryHandle( + const BindingContext& binding_context, + mojo::PendingReceiver<blink::mojom::NativeFileSystemDirectoryHandle> + directory_handle_receiver, + NativeFileSystemTransferTokenImpl* resolved_token); void DidResolveForSerializeHandle( SerializeHandleCallback callback, NativeFileSystemTransferTokenImpl* resolved_token); - // Creates a FileSystemURL which corresponds to a FilePath and Origin. - struct FileSystemURLAndFSHandle { - storage::FileSystemURL url; - std::string base_name; - storage::IsolatedContext::ScopedFSHandle file_system; - }; - FileSystemURLAndFSHandle CreateFileSystemURLFromPath( - const url::Origin& origin, - const base::FilePath& path); - blink::mojom::NativeFileSystemEntryPtr CreateFileEntryFromPathImpl( const BindingContext& binding_context, const base::FilePath& file_path, @@ -295,8 +301,8 @@ class CONTENT_EXPORT NativeFileSystemManagerImpl bool off_the_record_; - // NativeFileSystemTransferTokenImpl owns a Transfer token receiver and is - // removed from this map when the mojo connection is closed. + // NativeFileSystemTransferTokenImpl owns a Transfer token receiver set and is + // removed from this map when all mojo connections are closed. std::map<base::UnguessableToken, std::unique_ptr<NativeFileSystemTransferTokenImpl>> transfer_tokens_; diff --git a/chromium/content/browser/native_file_system/native_file_system_manager_impl_unittest.cc b/chromium/content/browser/native_file_system/native_file_system_manager_impl_unittest.cc index a8e0a1f57b5..72c9f5364a2 100644 --- a/chromium/content/browser/native_file_system/native_file_system_manager_impl_unittest.cc +++ b/chromium/content/browser/native_file_system/native_file_system_manager_impl_unittest.cc @@ -76,17 +76,15 @@ class NativeFileSystemManagerImplTest : public testing::Test { mojo::Remote<blink::mojom::NativeFileSystemDirectoryHandle> GetHandleForDirectory(const base::FilePath& path) { - EXPECT_CALL( - permission_context_, - GetReadPermissionGrant( - kTestOrigin, path, /*is_directory=*/true, kProcessId, kFrameId, - NativeFileSystemPermissionContext::UserAction::kOpen)) + EXPECT_CALL(permission_context_, + GetReadPermissionGrant( + kTestOrigin, path, /*is_directory=*/true, + NativeFileSystemPermissionContext::UserAction::kOpen)) .WillOnce(testing::Return(allow_grant_)); - EXPECT_CALL( - permission_context_, - GetWritePermissionGrant( - kTestOrigin, path, /*is_directory=*/true, kProcessId, kFrameId, - NativeFileSystemPermissionContext::UserAction::kOpen)) + EXPECT_CALL(permission_context_, + GetWritePermissionGrant( + kTestOrigin, path, /*is_directory=*/true, + NativeFileSystemPermissionContext::UserAction::kOpen)) .WillOnce(testing::Return(allow_grant_)); blink::mojom::NativeFileSystemEntryPtr entry = @@ -128,9 +126,10 @@ class NativeFileSystemManagerImplTest : public testing::Test { const GURL kTestURL = GURL("https://example.com/test"); const url::Origin kTestOrigin = url::Origin::Create(kTestURL); const int kProcessId = 1; - const int kFrameId = 2; + const int kFrameRoutingId = 2; + const GlobalFrameRoutingId kFrameId{kProcessId, kFrameRoutingId}; const NativeFileSystemManagerImpl::BindingContext kBindingContext = { - kTestOrigin, kTestURL, kProcessId, kFrameId}; + kTestOrigin, kTestURL, kFrameId}; base::test::ScopedFeatureList scoped_feature_list_; BrowserTaskEnvironment task_environment_; @@ -180,17 +179,15 @@ TEST_F(NativeFileSystemManagerImplTest, GetSandboxedFileSystem_Permissions) { TEST_F(NativeFileSystemManagerImplTest, CreateFileEntryFromPath_Permissions) { const base::FilePath kTestPath(dir_.GetPath().AppendASCII("foo")); - EXPECT_CALL( - permission_context_, - GetReadPermissionGrant( - kTestOrigin, kTestPath, /*is_directory=*/false, kProcessId, kFrameId, - NativeFileSystemPermissionContext::UserAction::kOpen)) + EXPECT_CALL(permission_context_, + GetReadPermissionGrant( + kTestOrigin, kTestPath, /*is_directory=*/false, + NativeFileSystemPermissionContext::UserAction::kOpen)) .WillOnce(testing::Return(allow_grant_)); - EXPECT_CALL( - permission_context_, - GetWritePermissionGrant( - kTestOrigin, kTestPath, /*is_directory=*/false, kProcessId, kFrameId, - NativeFileSystemPermissionContext::UserAction::kOpen)) + EXPECT_CALL(permission_context_, + GetWritePermissionGrant( + kTestOrigin, kTestPath, /*is_directory=*/false, + NativeFileSystemPermissionContext::UserAction::kOpen)) .WillOnce(testing::Return(ask_grant_)); blink::mojom::NativeFileSystemEntryPtr entry = @@ -208,17 +205,15 @@ TEST_F(NativeFileSystemManagerImplTest, CreateWritableFileEntryFromPath_Permissions) { const base::FilePath kTestPath(dir_.GetPath().AppendASCII("foo")); - EXPECT_CALL( - permission_context_, - GetReadPermissionGrant( - kTestOrigin, kTestPath, /*is_directory=*/false, kProcessId, kFrameId, - NativeFileSystemPermissionContext::UserAction::kSave)) + EXPECT_CALL(permission_context_, + GetReadPermissionGrant( + kTestOrigin, kTestPath, /*is_directory=*/false, + NativeFileSystemPermissionContext::UserAction::kSave)) .WillOnce(testing::Return(allow_grant_)); - EXPECT_CALL( - permission_context_, - GetWritePermissionGrant( - kTestOrigin, kTestPath, /*is_directory=*/false, kProcessId, kFrameId, - NativeFileSystemPermissionContext::UserAction::kSave)) + EXPECT_CALL(permission_context_, + GetWritePermissionGrant( + kTestOrigin, kTestPath, /*is_directory=*/false, + NativeFileSystemPermissionContext::UserAction::kSave)) .WillOnce(testing::Return(allow_grant_)); blink::mojom::NativeFileSystemEntryPtr entry = @@ -236,17 +231,15 @@ TEST_F(NativeFileSystemManagerImplTest, CreateDirectoryEntryFromPath_Permissions) { const base::FilePath kTestPath(dir_.GetPath().AppendASCII("foo")); - EXPECT_CALL( - permission_context_, - GetReadPermissionGrant( - kTestOrigin, kTestPath, /*is_directory=*/true, kProcessId, kFrameId, - NativeFileSystemPermissionContext::UserAction::kOpen)) + EXPECT_CALL(permission_context_, + GetReadPermissionGrant( + kTestOrigin, kTestPath, /*is_directory=*/true, + NativeFileSystemPermissionContext::UserAction::kOpen)) .WillOnce(testing::Return(allow_grant_)); - EXPECT_CALL( - permission_context_, - GetWritePermissionGrant( - kTestOrigin, kTestPath, /*is_directory=*/true, kProcessId, kFrameId, - NativeFileSystemPermissionContext::UserAction::kOpen)) + EXPECT_CALL(permission_context_, + GetWritePermissionGrant( + kTestOrigin, kTestPath, /*is_directory=*/true, + NativeFileSystemPermissionContext::UserAction::kOpen)) .WillOnce(testing::Return(ask_grant_)); blink::mojom::NativeFileSystemEntryPtr entry = @@ -346,16 +339,17 @@ TEST_F(NativeFileSystemManagerImplTest, SerializeHandle_SandboxedFile) { NativeFileSystemTransferTokenImpl* token = SerializeAndDeserializeToken(std::move(token_remote)); ASSERT_TRUE(token); - EXPECT_EQ(test_file_url, token->url()); + ASSERT_TRUE(token->GetAsFileSystemURL()); + EXPECT_EQ(test_file_url, *token->GetAsFileSystemURL()); EXPECT_EQ(NativeFileSystemTransferTokenImpl::HandleType::kFile, token->type()); // Deserialized sandboxed filesystem handles should always be readable and // writable. - EXPECT_EQ(PermissionStatus::GRANTED, - token->shared_handle_state().read_grant->GetStatus()); - EXPECT_EQ(PermissionStatus::GRANTED, - token->shared_handle_state().write_grant->GetStatus()); + ASSERT_TRUE(token->GetReadGrant()); + EXPECT_EQ(PermissionStatus::GRANTED, token->GetReadGrant()->GetStatus()); + ASSERT_TRUE(token->GetWriteGrant()); + EXPECT_EQ(PermissionStatus::GRANTED, token->GetWriteGrant()->GetStatus()); } TEST_F(NativeFileSystemManagerImplTest, SerializeHandle_SandboxedDirectory) { @@ -372,33 +366,32 @@ TEST_F(NativeFileSystemManagerImplTest, SerializeHandle_SandboxedDirectory) { NativeFileSystemTransferTokenImpl* token = SerializeAndDeserializeToken(std::move(token_remote)); ASSERT_TRUE(token); - EXPECT_EQ(test_file_url, token->url()); + ASSERT_TRUE(token->GetAsFileSystemURL()); + EXPECT_EQ(test_file_url, *token->GetAsFileSystemURL()); EXPECT_EQ(NativeFileSystemTransferTokenImpl::HandleType::kDirectory, token->type()); // Deserialized sandboxed filesystem handles should always be readable and // writable. - EXPECT_EQ(PermissionStatus::GRANTED, - token->shared_handle_state().read_grant->GetStatus()); - EXPECT_EQ(PermissionStatus::GRANTED, - token->shared_handle_state().write_grant->GetStatus()); + ASSERT_TRUE(token->GetReadGrant()); + EXPECT_EQ(PermissionStatus::GRANTED, token->GetReadGrant()->GetStatus()); + ASSERT_TRUE(token->GetWriteGrant()); + EXPECT_EQ(PermissionStatus::GRANTED, token->GetWriteGrant()->GetStatus()); } TEST_F(NativeFileSystemManagerImplTest, SerializeHandle_Native_SingleFile) { const base::FilePath kTestPath(dir_.GetPath().AppendASCII("foo")); // Expect calls to get grants when creating the initial handle. - EXPECT_CALL( - permission_context_, - GetReadPermissionGrant( - kTestOrigin, kTestPath, /*is_directory=*/false, kProcessId, kFrameId, - NativeFileSystemPermissionContext::UserAction::kOpen)) + EXPECT_CALL(permission_context_, + GetReadPermissionGrant( + kTestOrigin, kTestPath, /*is_directory=*/false, + NativeFileSystemPermissionContext::UserAction::kOpen)) .WillOnce(testing::Return(allow_grant_)); - EXPECT_CALL( - permission_context_, - GetWritePermissionGrant( - kTestOrigin, kTestPath, /*is_directory=*/false, kProcessId, kFrameId, - NativeFileSystemPermissionContext::UserAction::kOpen)) + EXPECT_CALL(permission_context_, + GetWritePermissionGrant( + kTestOrigin, kTestPath, /*is_directory=*/false, + NativeFileSystemPermissionContext::UserAction::kOpen)) .WillOnce(testing::Return(allow_grant_)); blink::mojom::NativeFileSystemEntryPtr entry = @@ -414,30 +407,28 @@ TEST_F(NativeFileSystemManagerImplTest, SerializeHandle_Native_SingleFile) { permission_context_, GetReadPermissionGrant( kTestOrigin, kTestPath, /*is_directory=*/false, - /*process_id=*/ChildProcessHost::kInvalidUniqueID, - /*frame_id=*/MSG_ROUTING_NONE, NativeFileSystemPermissionContext::UserAction::kLoadFromStorage)) .WillOnce(testing::Return(ask_grant_)); EXPECT_CALL( permission_context_, GetWritePermissionGrant( kTestOrigin, kTestPath, /*is_directory=*/false, - /*process_id=*/ChildProcessHost::kInvalidUniqueID, - /*frame_id=*/MSG_ROUTING_NONE, NativeFileSystemPermissionContext::UserAction::kLoadFromStorage)) .WillOnce(testing::Return(ask_grant2_)); NativeFileSystemTransferTokenImpl* token = SerializeAndDeserializeToken(std::move(token_remote)); ASSERT_TRUE(token); - EXPECT_EQ(kTestOrigin, token->url().origin()); - EXPECT_EQ(kTestPath, token->url().path()); - EXPECT_EQ(storage::kFileSystemTypeNativeLocal, token->url().type()); - EXPECT_EQ(storage::kFileSystemTypeIsolated, token->url().mount_type()); + ASSERT_TRUE(token->GetAsFileSystemURL()); + const storage::FileSystemURL& url = *token->GetAsFileSystemURL(); + EXPECT_EQ(kTestOrigin, url.origin()); + EXPECT_EQ(kTestPath, url.path()); + EXPECT_EQ(storage::kFileSystemTypeNativeLocal, url.type()); + EXPECT_EQ(storage::kFileSystemTypeIsolated, url.mount_type()); EXPECT_EQ(NativeFileSystemTransferTokenImpl::HandleType::kFile, token->type()); - EXPECT_EQ(ask_grant_, token->shared_handle_state().read_grant); - EXPECT_EQ(ask_grant2_, token->shared_handle_state().write_grant); + EXPECT_EQ(ask_grant_, token->GetReadGrant()); + EXPECT_EQ(ask_grant2_, token->GetWriteGrant()); } TEST_F(NativeFileSystemManagerImplTest, @@ -454,30 +445,28 @@ TEST_F(NativeFileSystemManagerImplTest, permission_context_, GetReadPermissionGrant( kTestOrigin, kTestPath, /*is_directory=*/true, - /*process_id=*/ChildProcessHost::kInvalidUniqueID, - /*frame_id=*/MSG_ROUTING_NONE, NativeFileSystemPermissionContext::UserAction::kLoadFromStorage)) .WillOnce(testing::Return(ask_grant_)); EXPECT_CALL( permission_context_, GetWritePermissionGrant( kTestOrigin, kTestPath, /*is_directory=*/true, - /*process_id=*/ChildProcessHost::kInvalidUniqueID, - /*frame_id=*/MSG_ROUTING_NONE, NativeFileSystemPermissionContext::UserAction::kLoadFromStorage)) .WillOnce(testing::Return(ask_grant2_)); NativeFileSystemTransferTokenImpl* token = SerializeAndDeserializeToken(std::move(token_remote)); ASSERT_TRUE(token); - EXPECT_EQ(kTestOrigin, token->url().origin()); - EXPECT_EQ(kTestPath, token->url().path()); - EXPECT_EQ(storage::kFileSystemTypeNativeLocal, token->url().type()); - EXPECT_EQ(storage::kFileSystemTypeIsolated, token->url().mount_type()); + ASSERT_TRUE(token->GetAsFileSystemURL()); + const storage::FileSystemURL& url = *token->GetAsFileSystemURL(); + EXPECT_EQ(kTestOrigin, url.origin()); + EXPECT_EQ(kTestPath, url.path()); + EXPECT_EQ(storage::kFileSystemTypeNativeLocal, url.type()); + EXPECT_EQ(storage::kFileSystemTypeIsolated, url.mount_type()); EXPECT_EQ(NativeFileSystemTransferTokenImpl::HandleType::kDirectory, token->type()); - EXPECT_EQ(ask_grant_, token->shared_handle_state().read_grant); - EXPECT_EQ(ask_grant2_, token->shared_handle_state().write_grant); + EXPECT_EQ(ask_grant_, token->GetReadGrant()); + EXPECT_EQ(ask_grant2_, token->GetWriteGrant()); } TEST_F(NativeFileSystemManagerImplTest, @@ -513,31 +502,29 @@ TEST_F(NativeFileSystemManagerImplTest, permission_context_, GetReadPermissionGrant( kTestOrigin, kDirectoryPath, /*is_directory=*/true, - /*process_id=*/ChildProcessHost::kInvalidUniqueID, - /*frame_id=*/MSG_ROUTING_NONE, NativeFileSystemPermissionContext::UserAction::kLoadFromStorage)) .WillOnce(testing::Return(ask_grant_)); EXPECT_CALL( permission_context_, GetWritePermissionGrant( kTestOrigin, kDirectoryPath, /*is_directory=*/true, - /*process_id=*/ChildProcessHost::kInvalidUniqueID, - /*frame_id=*/MSG_ROUTING_NONE, NativeFileSystemPermissionContext::UserAction::kLoadFromStorage)) .WillOnce(testing::Return(ask_grant2_)); NativeFileSystemTransferTokenImpl* token = SerializeAndDeserializeToken(std::move(token_remote)); ASSERT_TRUE(token); - EXPECT_EQ(kTestOrigin, token->url().origin()); + ASSERT_TRUE(token->GetAsFileSystemURL()); + const storage::FileSystemURL& url = *token->GetAsFileSystemURL(); + EXPECT_EQ(kTestOrigin, url.origin()); EXPECT_EQ(kDirectoryPath.Append(base::FilePath::FromUTF8Unsafe(kTestName)), - token->url().path()); - EXPECT_EQ(storage::kFileSystemTypeNativeLocal, token->url().type()); - EXPECT_EQ(storage::kFileSystemTypeIsolated, token->url().mount_type()); + url.path()); + EXPECT_EQ(storage::kFileSystemTypeNativeLocal, url.type()); + EXPECT_EQ(storage::kFileSystemTypeIsolated, url.mount_type()); EXPECT_EQ(NativeFileSystemTransferTokenImpl::HandleType::kFile, token->type()); - EXPECT_EQ(ask_grant_, token->shared_handle_state().read_grant); - EXPECT_EQ(ask_grant2_, token->shared_handle_state().write_grant); + EXPECT_EQ(ask_grant_, token->GetReadGrant()); + EXPECT_EQ(ask_grant2_, token->GetWriteGrant()); } TEST_F(NativeFileSystemManagerImplTest, @@ -573,30 +560,28 @@ TEST_F(NativeFileSystemManagerImplTest, permission_context_, GetReadPermissionGrant( kTestOrigin, kDirectoryPath, /*is_directory=*/true, - /*process_id=*/ChildProcessHost::kInvalidUniqueID, - /*frame_id=*/MSG_ROUTING_NONE, NativeFileSystemPermissionContext::UserAction::kLoadFromStorage)) .WillOnce(testing::Return(ask_grant_)); EXPECT_CALL( permission_context_, GetWritePermissionGrant( kTestOrigin, kDirectoryPath, /*is_directory=*/true, - /*process_id=*/ChildProcessHost::kInvalidUniqueID, - /*frame_id=*/MSG_ROUTING_NONE, NativeFileSystemPermissionContext::UserAction::kLoadFromStorage)) .WillOnce(testing::Return(ask_grant2_)); NativeFileSystemTransferTokenImpl* token = SerializeAndDeserializeToken(std::move(token_remote)); ASSERT_TRUE(token); - EXPECT_EQ(kTestOrigin, token->url().origin()); - EXPECT_EQ(kDirectoryPath.AppendASCII(kTestName), token->url().path()); - EXPECT_EQ(storage::kFileSystemTypeNativeLocal, token->url().type()); - EXPECT_EQ(storage::kFileSystemTypeIsolated, token->url().mount_type()); + ASSERT_TRUE(token->GetAsFileSystemURL()); + const storage::FileSystemURL& url = *token->GetAsFileSystemURL(); + EXPECT_EQ(kTestOrigin, url.origin()); + EXPECT_EQ(kDirectoryPath.AppendASCII(kTestName), url.path()); + EXPECT_EQ(storage::kFileSystemTypeNativeLocal, url.type()); + EXPECT_EQ(storage::kFileSystemTypeIsolated, url.mount_type()); EXPECT_EQ(NativeFileSystemTransferTokenImpl::HandleType::kDirectory, token->type()); - EXPECT_EQ(ask_grant_, token->shared_handle_state().read_grant); - EXPECT_EQ(ask_grant2_, token->shared_handle_state().write_grant); + EXPECT_EQ(ask_grant_, token->GetReadGrant()); + EXPECT_EQ(ask_grant2_, token->GetWriteGrant()); } } // namespace content diff --git a/chromium/content/browser/native_file_system/native_file_system_transfer_token_impl.cc b/chromium/content/browser/native_file_system/native_file_system_transfer_token_impl.cc index 98feef0f5d3..0108ed52154 100644 --- a/chromium/content/browser/native_file_system/native_file_system_transfer_token_impl.cc +++ b/chromium/content/browser/native_file_system/native_file_system_transfer_token_impl.cc @@ -4,23 +4,96 @@ #include "content/browser/native_file_system/native_file_system_transfer_token_impl.h" +#include "content/browser/native_file_system/native_file_system_directory_handle_impl.h" +#include "content/browser/native_file_system/native_file_system_file_handle_impl.h" + namespace content { -NativeFileSystemTransferTokenImpl::NativeFileSystemTransferTokenImpl( +namespace { + +// Concrete implementation for Transfer Tokens created from a +// NativeFileSystemFileHandleImpl or DirectoryHandleImpl. These tokens +// share permission grants with the handle, and are tied to the origin the +// handles were associated with. +class NativeFileSystemTransferTokenImplForHandles + : public NativeFileSystemTransferTokenImpl { + public: + using SharedHandleState = NativeFileSystemManagerImpl::SharedHandleState; + + NativeFileSystemTransferTokenImplForHandles( + const storage::FileSystemURL& url, + const NativeFileSystemManagerImpl::SharedHandleState& handle_state, + HandleType type, + NativeFileSystemManagerImpl* manager, + mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> + receiver) + : NativeFileSystemTransferTokenImpl(type, manager, std::move(receiver)), + url_(url), + handle_state_(handle_state) { + DCHECK_EQ(url_.mount_type() == storage::kFileSystemTypeIsolated, + handle_state_.file_system.is_valid()) + << url_.mount_type(); + } + ~NativeFileSystemTransferTokenImplForHandles() override = default; + + bool MatchesOrigin(const url::Origin& origin) const override { + return url_.origin() == origin; + } + + const storage::FileSystemURL* GetAsFileSystemURL() const override { + return &url_; + } + + NativeFileSystemPermissionGrant* GetReadGrant() const override { + return handle_state_.read_grant.get(); + } + + NativeFileSystemPermissionGrant* GetWriteGrant() const override { + return handle_state_.write_grant.get(); + } + + std::unique_ptr<NativeFileSystemFileHandleImpl> CreateFileHandle( + const NativeFileSystemManagerImpl::BindingContext& binding_context) + override { + DCHECK_EQ(type_, HandleType::kFile); + return std::make_unique<NativeFileSystemFileHandleImpl>( + manager_, binding_context, url_, handle_state_); + } + + std::unique_ptr<NativeFileSystemDirectoryHandleImpl> CreateDirectoryHandle( + const NativeFileSystemManagerImpl::BindingContext& binding_context) + override { + DCHECK_EQ(type_, HandleType::kDirectory); + return std::make_unique<NativeFileSystemDirectoryHandleImpl>( + manager_, binding_context, url_, handle_state_); + } + + private: + const storage::FileSystemURL url_; + const NativeFileSystemManagerImpl::SharedHandleState handle_state_; +}; + +} // namespace + +// static +std::unique_ptr<NativeFileSystemTransferTokenImpl> +NativeFileSystemTransferTokenImpl::Create( const storage::FileSystemURL& url, - const SharedHandleState& handle_state, + const NativeFileSystemManagerImpl::SharedHandleState& handle_state, + HandleType type, + NativeFileSystemManagerImpl* manager, + mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> + receiver) { + return std::make_unique<NativeFileSystemTransferTokenImplForHandles>( + url, handle_state, type, manager, std::move(receiver)); +} + +NativeFileSystemTransferTokenImpl::NativeFileSystemTransferTokenImpl( HandleType type, NativeFileSystemManagerImpl* manager, mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> receiver) - : token_(base::UnguessableToken::Create()), - url_(url), - handle_state_(handle_state), - type_(type), - manager_(manager) { + : token_(base::UnguessableToken::Create()), type_(type), manager_(manager) { DCHECK(manager_); - DCHECK_EQ(url_.mount_type() == storage::kFileSystemTypeIsolated, - handle_state_.file_system.is_valid()) - << url_.mount_type(); receivers_.set_disconnect_handler( base::BindRepeating(&NativeFileSystemTransferTokenImpl::OnMojoDisconnect, diff --git a/chromium/content/browser/native_file_system/native_file_system_transfer_token_impl.h b/chromium/content/browser/native_file_system/native_file_system_transfer_token_impl.h index 5db37107e49..f7222f7fa86 100644 --- a/chromium/content/browser/native_file_system/native_file_system_transfer_token_impl.h +++ b/chromium/content/browser/native_file_system/native_file_system_transfer_token_impl.h @@ -15,21 +15,28 @@ namespace content { -// This is the browser side implementation of the NativeFileSystemTransferToken -// mojom interface. +// Base class for blink::mojom::NativeFileSystemTransferToken implementations. // -// Instances of this class are immutable, but since this implements a mojo -// interface all its methods are called on the same sequence anyway. +// Instances of this class should always be used from the sequence they were +// created on. class CONTENT_EXPORT NativeFileSystemTransferTokenImpl : public blink::mojom::NativeFileSystemTransferToken { public: - using SharedHandleState = NativeFileSystemManagerImpl::SharedHandleState; - enum class HandleType { kFile, kDirectory }; - NativeFileSystemTransferTokenImpl( + // Create a token that is tied to a particular origin (the origin of |url|, + // and uses the permission grants in |handle_state| when creating new handles + // out of the token. This is used for postMessage and IndexedDB serialization, + // as well as a couple of other APIs. + static std::unique_ptr<NativeFileSystemTransferTokenImpl> Create( const storage::FileSystemURL& url, - const SharedHandleState& handle_state, + const NativeFileSystemManagerImpl::SharedHandleState& handle_state, + HandleType type, + NativeFileSystemManagerImpl* manager, + mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> + receiver); + + NativeFileSystemTransferTokenImpl( HandleType type, NativeFileSystemManagerImpl* manager, mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> @@ -37,25 +44,39 @@ class CONTENT_EXPORT NativeFileSystemTransferTokenImpl ~NativeFileSystemTransferTokenImpl() override; const base::UnguessableToken& token() const { return token_; } - const SharedHandleState& shared_handle_state() const { return handle_state_; } - const storage::FileSystemURL& url() const { return url_; } HandleType type() const { return type_; } + // Returns true if |origin| is allowed to use this token. + virtual bool MatchesOrigin(const url::Origin& origin) const = 0; + + // Can return nullptr if this token isn't represented by a FileSystemURL. + virtual const storage::FileSystemURL* GetAsFileSystemURL() const = 0; + + // Returns permission grants associated with this token. These can + // return nullptr if this token does not have associated permission grants. + virtual NativeFileSystemPermissionGrant* GetReadGrant() const = 0; + virtual NativeFileSystemPermissionGrant* GetWriteGrant() const = 0; + + virtual std::unique_ptr<NativeFileSystemFileHandleImpl> CreateFileHandle( + const NativeFileSystemManagerImpl::BindingContext& binding_context) = 0; + virtual std::unique_ptr<NativeFileSystemDirectoryHandleImpl> + CreateDirectoryHandle( + const NativeFileSystemManagerImpl::BindingContext& binding_context) = 0; + // blink::mojom::NativeFileSystemTransferToken: void GetInternalID(GetInternalIDCallback callback) override; void Clone(mojo::PendingReceiver<blink::mojom::NativeFileSystemTransferToken> clone_receiver) override; - private: - void OnMojoDisconnect(); - + protected: const base::UnguessableToken token_; - const storage::FileSystemURL url_; - const SharedHandleState handle_state_; const HandleType type_; // Raw pointer since NativeFileSystemManagerImpl owns |this|. NativeFileSystemManagerImpl* const manager_; + private: + void OnMojoDisconnect(); + // This token may contain multiple receivers, which includes a receiver for // the originally constructed instance and then additional receivers for // each clone. |manager_| must not remove this token until |receivers_| is |