diff --git a/content/browser/web_contents/file_chooser_impl.cc b/content/browser/web_contents/file_chooser_impl.cc index 5b5799c285ecfb6cfa6775aca26144e2e17978d3..f40aa0454903d3a846cc5b5ff8873bae0fa13bf1 100644 --- a/content/browser/web_contents/file_chooser_impl.cc +++ b/content/browser/web_contents/file_chooser_impl.cc @@ -177,7 +177,8 @@ void FileChooserImpl::OpenFileChooser(blink::mojom::FileChooserParamsPtr params, BackForwardCacheDisable::DisabledReasonId::kFileChooser)); static_cast(web_contents()) - ->RunFileChooser(render_frame_host_, std::move(listener), *params); + ->RunFileChooser(GetWeakPtr(), render_frame_host_, std::move(listener), + *params); } void FileChooserImpl::EnumerateChosenDirectory( @@ -194,8 +195,8 @@ void FileChooserImpl::EnumerateChosenDirectory( if (policy->CanReadFile(render_frame_host_->GetProcess()->GetID(), directory_path)) { static_cast(web_contents()) - ->EnumerateDirectory(render_frame_host_, std::move(listener), - directory_path); + ->EnumerateDirectory(GetWeakPtr(), render_frame_host_, + std::move(listener), directory_path); } else { listener->FileSelectionCanceled(); } diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index d6c9e59da6a739273ce377d459fab5c43e980536..73ea6b046e72ea8119ee1a0502eb4717627b78ae 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -3936,6 +3937,16 @@ FrameTree* WebContentsImpl::CreateNewWindow( "opener", opener, "params", params); DCHECK(opener); + if (active_file_chooser_) { + // Do not allow opening a new window or tab while a file select is active + // file chooser to avoid user confusion over which tab triggered the file + // chooser. + opener->AddMessageToConsole( + blink::mojom::ConsoleMessageLevel::kWarning, + "window.open blocked due to active file chooser."); + return nullptr; + } + int render_process_id = opener->GetProcess()->GetID(); auto* source_site_instance = @@ -6235,21 +6246,35 @@ void WebContentsImpl::OnPageScaleFactorChanged(PageImpl& source) { } void WebContentsImpl::EnumerateDirectory( + base::WeakPtr file_chooser, RenderFrameHost* render_frame_host, scoped_refptr listener, const base::FilePath& directory_path) { OPTIONAL_TRACE_EVENT2("content", "WebContentsImpl::EnumerateDirectory", "render_frame_host", render_frame_host, "directory_path", directory_path); + base::ScopedClosureRunner cancel_chooser(base::BindOnce( + &FileChooserImpl::FileSelectListenerImpl::FileSelectionCanceled, + listener)); + if (visibility_ == Visibility::HIDDEN) { + // Do not allow background tab to open file chooser. + return; + } + if (active_file_chooser_) { + // Only allow one active file chooser at one time. + return; + } + // Any explicit focusing of another window while this WebContents is in // fullscreen can be used to confuse the user, so drop fullscreen. base::ScopedClosureRunner fullscreen_block = ForSecurityDropFullscreen(); listener->SetFullscreenBlock(std::move(fullscreen_block)); - if (delegate_) + if (delegate_) { + active_file_chooser_ = std::move(file_chooser); delegate_->EnumerateDirectory(this, std::move(listener), directory_path); - else - listener->FileSelectionCanceled(); + std::ignore = cancel_chooser.Release(); + } } void WebContentsImpl::RegisterProtocolHandler(RenderFrameHostImpl* source, @@ -7052,20 +7077,35 @@ void WebContentsImpl::RunBeforeUnloadConfirm( } void WebContentsImpl::RunFileChooser( + base::WeakPtr file_chooser, RenderFrameHost* render_frame_host, scoped_refptr listener, const blink::mojom::FileChooserParams& params) { OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::RunFileChooser", "render_frame_host", render_frame_host); + + base::ScopedClosureRunner cancel_chooser(base::BindOnce( + &FileChooserImpl::FileSelectListenerImpl::FileSelectionCanceled, + listener)); + if (visibility_ == Visibility::HIDDEN) { + // Do not allow background tab to open file chooser. + return; + } + if (active_file_chooser_) { + // Only allow one active file chooser at one time. + return; + } + // Any explicit focusing of another window while this WebContents is in // fullscreen can be used to confuse the user, so drop fullscreen. base::ScopedClosureRunner fullscreen_block = ForSecurityDropFullscreen(); listener->SetFullscreenBlock(std::move(fullscreen_block)); - if (delegate_) + if (delegate_) { + active_file_chooser_ = std::move(file_chooser); delegate_->RunFileChooser(render_frame_host, std::move(listener), params); - else - listener->FileSelectionCanceled(); + std::ignore = cancel_chooser.Release(); + } } double WebContentsImpl::GetPendingPageZoomLevel() { diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 271a4873b7ba5c0cd60c852ce661584ae0874e48..0b0ff5930de9d790b123c0e7fbae3e82bff0f3a6 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h @@ -1250,6 +1250,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, // Called when a file selection is to be done. void RunFileChooser( + base::WeakPtr file_chooser, RenderFrameHost* render_frame_host, scoped_refptr listener, const blink::mojom::FileChooserParams& params); @@ -1258,6 +1259,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, // chooser in directory-enumeration mode and having the user select the given // directory. void EnumerateDirectory( + base::WeakPtr file_chooser, RenderFrameHost* render_frame_host, scoped_refptr listener, const base::FilePath& directory_path); @@ -2384,6 +2386,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, std::unique_ptr form_to_save_; #endif // OHOS_NWEB_EX + base::WeakPtr active_file_chooser_; + base::WeakPtrFactory loading_weak_factory_{this}; base::WeakPtrFactory weak_factory_{this}; }; diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index a9401841c16c7ca3a92953a06c9a5c4a0f21d11d..bd5b14fc7f3ab937d56eb2712d289e6b9f2bc36d 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc @@ -2767,7 +2767,10 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, FileChooserEndsFullscreen) { wc->EnterFullscreenMode(wc->GetMainFrame(), {}); EXPECT_TRUE(wc->IsFullscreen()); - wc->RunFileChooser(wc->GetMainFrame(), + + auto [chooser, remote] = + FileChooserImpl::CreateForTesting(wc->GetMainFrame()); + wc->RunFileChooser(chooser->GetWeakPtr(), wc->GetMainFrame(), base::MakeRefCounted(), blink::mojom::FileChooserParams()); EXPECT_FALSE(wc->IsFullscreen());