diff options
Diffstat (limited to 'chromium/content/browser/web_contents')
26 files changed, 1191 insertions, 595 deletions
diff --git a/chromium/content/browser/web_contents/color_chooser_unittest.cc b/chromium/content/browser/web_contents/color_chooser_unittest.cc new file mode 100644 index 00000000000..26b37c96188 --- /dev/null +++ b/chromium/content/browser/web_contents/color_chooser_unittest.cc @@ -0,0 +1,151 @@ +// Copyright (c) 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/test/scoped_feature_list.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/common/content_navigation_policy.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents_delegate.h" +#include "content/public/common/content_features.h" +#include "content/public/test/navigation_simulator.h" +#include "content/test/test_render_frame_host.h" +#include "content/test/test_render_view_host.h" +#include "content/test/test_web_contents.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace content { + +namespace { + +// Mock content::ColorChooser to test whether End() is called. +class MockColorChooser : public content::ColorChooser { + public: + MockColorChooser() = default; + ~MockColorChooser() override = default; + + MOCK_METHOD0(End, void()); + MOCK_METHOD1(SetSelectedColor, void(SkColor color)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockColorChooser); +}; + +// Delegate to override OpenColorChooser. +class OpenColorChooserDelegate : public WebContentsDelegate { + public: + explicit OpenColorChooserDelegate( + std::unique_ptr<MockColorChooser> mock_color_chooser) + : mock_color_chooser_(std::move(mock_color_chooser)) {} + + ~OpenColorChooserDelegate() override = default; + + // WebContentsDelegate: + ColorChooser* OpenColorChooser( + WebContents* web_contents, + SkColor color, + const std::vector<blink::mojom::ColorSuggestionPtr>& suggestions) + override { + return std::move(mock_color_chooser_).release(); + } + + private: + std::unique_ptr<MockColorChooser> mock_color_chooser_; + + DISALLOW_COPY_AND_ASSIGN(OpenColorChooserDelegate); +}; + +} // namespace + +class ColorChooserUnitTest : public RenderViewHostImplTestHarness {}; + +TEST_F(ColorChooserUnitTest, ColorChooserCallsEndOnNavigatingAway) { + GURL kUrl1("https://foo.com"); + GURL kUrl2("https://bar.com"); + + // Navigate to A. + NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl1); + + // End should be called at least once on navigating to a new URL. + std::unique_ptr<MockColorChooser> mock_color_chooser = + std::make_unique<MockColorChooser>(); + EXPECT_CALL(*mock_color_chooser.get(), End()).Times(testing::AtLeast(1)); + + // Set OpenColorChooserDelegate as the new WebContentsDelegate. + std::unique_ptr<OpenColorChooserDelegate> delegate = + std::make_unique<OpenColorChooserDelegate>(std::move(mock_color_chooser)); + contents()->SetDelegate(delegate.get()); + + mojo::PendingRemote<blink::mojom::ColorChooserClient> pending_client; + mojo::Remote<blink::mojom::ColorChooser> pending_remote; + mojo::PendingReceiver<blink::mojom::ColorChooser> pending_receiver = + pending_remote.BindNewPipeAndPassReceiver(); + + // Call WebContentsImpl::OpenColorChooser. + static_cast<WebContentsImpl*>(contents()) + ->OpenColorChooser(std::move(pending_receiver), std::move(pending_client), + SkColorSetRGB(0, 0, 1), {}); + + // Navigate to B. + NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl2); + + contents()->SetDelegate(nullptr); +} + +// Run tests with BackForwardCache. +class ColorChooserTestWithBackForwardCache : public ColorChooserUnitTest { + public: + ColorChooserTestWithBackForwardCache() { + scoped_feature_list_.InitWithFeaturesAndParameters( + {{features::kBackForwardCache, {GetFeatureParams()}}}, + /*disabled_features=*/{}); + } + + protected: + base::FieldTrialParams GetFeatureParams() { + return {{"TimeToLiveInBackForwardCacheInSeconds", "3600"}, + {"service_worker_supported", "true"}}; + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +TEST_F(ColorChooserTestWithBackForwardCache, + ColorChooserCallsEndOnEnteringBackForwardCache) { + ASSERT_TRUE(IsBackForwardCacheEnabled()); + GURL kUrl1("https://foo.com"); + GURL kUrl2("https://bar.com"); + + // Navigate to A. + NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl1); + RenderFrameHost* rfh_a = contents()->GetMainFrame(); + + // End should be called at least once on navigating to a new URL. + std::unique_ptr<MockColorChooser> mock_color_chooser = + std::make_unique<MockColorChooser>(); + EXPECT_CALL(*mock_color_chooser.get(), End()).Times(testing::AtLeast(1)); + + // Set OpenColorChooserDelegate as the new WebContentsDelegate. + std::unique_ptr<OpenColorChooserDelegate> delegate = + std::make_unique<OpenColorChooserDelegate>(std::move(mock_color_chooser)); + contents()->SetDelegate(delegate.get()); + + mojo::PendingRemote<blink::mojom::ColorChooserClient> pending_client; + mojo::Remote<blink::mojom::ColorChooser> pending_remote; + mojo::PendingReceiver<blink::mojom::ColorChooser> pending_receiver = + pending_remote.BindNewPipeAndPassReceiver(); + + // Call WebContentsImpl::OpenColorChooser. + static_cast<WebContentsImpl*>(contents()) + ->OpenColorChooser(std::move(pending_receiver), std::move(pending_client), + SkColorSetRGB(0, 0, 1), {}); + + // Navigate to B, A enters BackForwardCache. + NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl2); + EXPECT_TRUE(rfh_a->IsInBackForwardCache()); + + contents()->SetDelegate(nullptr); +} + +} // namespace content diff --git a/chromium/content/browser/web_contents/file_chooser_impl.cc b/chromium/content/browser/web_contents/file_chooser_impl.cc new file mode 100644 index 00000000000..5a229b48c44 --- /dev/null +++ b/chromium/content/browser/web_contents/file_chooser_impl.cc @@ -0,0 +1,211 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/web_contents/file_chooser_impl.h" + +#include "base/memory/ptr_util.h" +#include "content/browser/child_process_security_policy_impl.h" +#include "content/browser/frame_host/render_frame_host_delegate.h" +#include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/storage_partition.h" +#include "content/public/browser/web_contents.h" +#include "mojo/public/cpp/bindings/self_owned_receiver.h" + +namespace content { + +FileChooserImpl::FileSelectListenerImpl::~FileSelectListenerImpl() { +#if DCHECK_IS_ON() + DCHECK(was_file_select_listener_function_called_) + << "Must call either FileSelectListener::FileSelected() or " + "FileSelectListener::FileSelectionCanceled()"; + // TODO(avi): Turn on the DCHECK on the following line. This cannot yet be + // done because I can't say for sure that I know who all the callers who bind + // blink::mojom::FileChooser are. https://crbug.com/1054811 + /* DCHECK(was_fullscreen_block_set_) << "The fullscreen block was not set"; */ +#endif + if (owner_) + owner_->ResetListenerImpl(); +} + +void FileChooserImpl::FileSelectListenerImpl::SetFullscreenBlock( + base::ScopedClosureRunner fullscreen_block) { +#if DCHECK_IS_ON() + DCHECK(!was_fullscreen_block_set_) + << "Fullscreen block must only be set once"; + was_fullscreen_block_set_ = true; +#endif + fullscreen_block_ = std::move(fullscreen_block); +} + +void FileChooserImpl::FileSelectListenerImpl::FileSelected( + std::vector<blink::mojom::FileChooserFileInfoPtr> files, + const base::FilePath& base_dir, + blink::mojom::FileChooserParams::Mode mode) { +#if DCHECK_IS_ON() + DCHECK(!was_file_select_listener_function_called_) + << "Must not call both of FileSelectListener::FileSelected() and " + "FileSelectListener::FileSelectionCanceled()"; + was_file_select_listener_function_called_ = true; +#endif + if (owner_) + owner_->FileSelected(std::move(files), base_dir, mode); +} + +void FileChooserImpl::FileSelectListenerImpl::FileSelectionCanceled() { +#if DCHECK_IS_ON() + DCHECK(!was_file_select_listener_function_called_) + << "Should not call both of FileSelectListener::FileSelected() and " + "FileSelectListener::FileSelectionCanceled()"; + was_file_select_listener_function_called_ = true; +#endif + if (owner_) + owner_->FileSelectionCanceled(); +} + +void FileChooserImpl::FileSelectListenerImpl:: + SetListenerFunctionCalledTrueForTesting() { +#if DCHECK_IS_ON() + was_file_select_listener_function_called_ = true; +#endif +} + +// static +void FileChooserImpl::Create( + RenderFrameHostImpl* render_frame_host, + mojo::PendingReceiver<blink::mojom::FileChooser> receiver) { + mojo::MakeSelfOwnedReceiver( + base::WrapUnique(new FileChooserImpl(render_frame_host)), + std::move(receiver)); +} + +// static +mojo::Remote<blink::mojom::FileChooser> FileChooserImpl::CreateBoundForTesting( + RenderFrameHostImpl* render_frame_host) { + mojo::Remote<blink::mojom::FileChooser> chooser; + Create(render_frame_host, chooser.BindNewPipeAndPassReceiver()); + return chooser; +} + +FileChooserImpl::FileChooserImpl(RenderFrameHostImpl* render_frame_host) + : render_frame_host_(render_frame_host) { + Observe(WebContents::FromRenderFrameHost(render_frame_host)); +} + +FileChooserImpl::~FileChooserImpl() { + if (listener_impl_) + listener_impl_->ResetOwner(); +} + +void FileChooserImpl::OpenFileChooser(blink::mojom::FileChooserParamsPtr params, + OpenFileChooserCallback callback) { + if (listener_impl_ || !render_frame_host_) { + std::move(callback).Run(nullptr); + return; + } + callback_ = std::move(callback); + auto listener = std::make_unique<FileSelectListenerImpl>(this); + listener_impl_ = listener.get(); + // Do not allow messages with absolute paths in them as this can permit a + // renderer to coerce the browser to perform I/O on a renderer controlled + // path. + if (params->default_file_name != params->default_file_name.BaseName()) { + mojo::ReportBadMessage( + "FileChooser: The default file name must not be an absolute path."); + listener->FileSelectionCanceled(); + return; + } + + // Don't allow page with open FileChooser to enter BackForwardCache to avoid + // any unexpected behaviour from BackForwardCache. + BackForwardCache::DisableForRenderFrameHost(render_frame_host_, + "FileChooser"); + + static_cast<WebContentsImpl*>(web_contents()) + ->RunFileChooser(render_frame_host_, std::move(listener), *params); +} + +void FileChooserImpl::EnumerateChosenDirectory( + const base::FilePath& directory_path, + EnumerateChosenDirectoryCallback callback) { + if (listener_impl_ || !render_frame_host_) { + std::move(callback).Run(nullptr); + return; + } + callback_ = std::move(callback); + auto listener = std::make_unique<FileSelectListenerImpl>(this); + listener_impl_ = listener.get(); + auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); + if (policy->CanReadFile(render_frame_host_->GetProcess()->GetID(), + directory_path)) { + static_cast<WebContentsImpl*>(web_contents()) + ->EnumerateDirectory(render_frame_host_, std::move(listener), + directory_path); + } else { + listener->FileSelectionCanceled(); + } +} + +void FileChooserImpl::FileSelected( + std::vector<blink::mojom::FileChooserFileInfoPtr> files, + const base::FilePath& base_dir, + blink::mojom::FileChooserParams::Mode mode) { + listener_impl_ = nullptr; + if (!render_frame_host_) + return; + storage::FileSystemContext* file_system_context = nullptr; + const int pid = render_frame_host_->GetProcess()->GetID(); + auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); + // Grant the security access requested to the given files. + for (const auto& file : files) { + if (mode == blink::mojom::FileChooserParams::Mode::kSave) { + policy->GrantCreateReadWriteFile(pid, file->get_native_file()->file_path); + } else { + if (file->is_file_system()) { + if (!file_system_context) { + file_system_context = + BrowserContext::GetStoragePartition( + render_frame_host_->GetProcess()->GetBrowserContext(), + render_frame_host_->GetSiteInstance()) + ->GetFileSystemContext(); + } + policy->GrantReadFileSystem( + pid, file_system_context->CrackURL(file->get_file_system()->url) + .mount_filesystem_id()); + } else { + policy->GrantReadFile(pid, file->get_native_file()->file_path); + } + } + } + std::move(callback_).Run(FileChooserResult::New(std::move(files), base_dir)); +} + +void FileChooserImpl::FileSelectionCanceled() { + listener_impl_ = nullptr; + if (!render_frame_host_) + return; + std::move(callback_).Run(nullptr); +} + +void FileChooserImpl::ResetListenerImpl() { + listener_impl_ = nullptr; +} + +void FileChooserImpl::RenderFrameHostChanged(RenderFrameHost* old_host, + RenderFrameHost* new_host) { + if (old_host == render_frame_host_) + render_frame_host_ = nullptr; +} + +void FileChooserImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) { + if (render_frame_host == render_frame_host_) + render_frame_host_ = nullptr; +} + +void FileChooserImpl::WebContentsDestroyed() { + render_frame_host_ = nullptr; +} + +} // namespace content diff --git a/chromium/content/browser/web_contents/file_chooser_impl.h b/chromium/content/browser/web_contents/file_chooser_impl.h new file mode 100644 index 00000000000..97ea05e582b --- /dev/null +++ b/chromium/content/browser/web_contents/file_chooser_impl.h @@ -0,0 +1,97 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_WEB_CONTENTS_FILE_CHOOSER_IMPL_H_ +#define CONTENT_BROWSER_WEB_CONTENTS_FILE_CHOOSER_IMPL_H_ + +#include "base/callback_helpers.h" +#include "content/common/content_export.h" +#include "content/public/browser/file_select_listener.h" +#include "content/public/browser/web_contents_observer.h" +#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h" + +namespace content { + +class RenderFrameHostImpl; + +// An implementation of blink::mojom::FileChooser and FileSelectListener +// associated to RenderFrameHost. +// TODO(sreejakshetty): Make FileChooserImpl per-frame and associate with +// RenderDocumentHostUserData to ensure that the state is correctly tracked and +// deleted. +class CONTENT_EXPORT FileChooserImpl : public blink::mojom::FileChooser, + public WebContentsObserver { + using FileChooserResult = blink::mojom::FileChooserResult; + + public: + class CONTENT_EXPORT FileSelectListenerImpl : public FileSelectListener { + public: + explicit FileSelectListenerImpl(FileChooserImpl* owner) : owner_(owner) {} + ~FileSelectListenerImpl() override; + void SetFullscreenBlock(base::ScopedClosureRunner fullscreen_block); + void ResetOwner() { owner_ = nullptr; } + + // FileSelectListener overrides: + + void FileSelected(std::vector<blink::mojom::FileChooserFileInfoPtr> files, + const base::FilePath& base_dir, + blink::mojom::FileChooserParams::Mode mode) override; + + void FileSelectionCanceled() override; + + protected: + // This sets |was_file_select_listener_function_called_| to true so that + // tests can pass with mocked overrides of this class. + void SetListenerFunctionCalledTrueForTesting(); + + private: + FileChooserImpl* owner_; + base::ScopedClosureRunner fullscreen_block_; +#if DCHECK_IS_ON() + bool was_file_select_listener_function_called_ = false; + bool was_fullscreen_block_set_ = false; +#endif + }; + + static void Create(RenderFrameHostImpl* render_frame_host, + mojo::PendingReceiver<blink::mojom::FileChooser> receiver); + static mojo::Remote<blink::mojom::FileChooser> CreateBoundForTesting( + RenderFrameHostImpl* render_frame_host); + + ~FileChooserImpl() override; + + void FileSelected(std::vector<blink::mojom::FileChooserFileInfoPtr> files, + const base::FilePath& base_dir, + blink::mojom::FileChooserParams::Mode mode); + + void FileSelectionCanceled(); + + void ResetListenerImpl(); + + // blink::mojom::FileChooser overrides: + + void OpenFileChooser(blink::mojom::FileChooserParamsPtr params, + OpenFileChooserCallback callback) override; + void EnumerateChosenDirectory( + const base::FilePath& directory_path, + EnumerateChosenDirectoryCallback callback) override; + + private: + explicit FileChooserImpl(RenderFrameHostImpl* render_frame_host); + + // WebContentsObserver overrides: + + void RenderFrameHostChanged(RenderFrameHost* old_host, + RenderFrameHost* new_host) override; + void RenderFrameDeleted(RenderFrameHost* render_frame_host) override; + void WebContentsDestroyed() override; + + RenderFrameHostImpl* render_frame_host_; + FileSelectListenerImpl* listener_impl_ = nullptr; + base::OnceCallback<void(blink::mojom::FileChooserResultPtr)> callback_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_WEB_CONTENTS_FILE_CHOOSER_IMPL_H_ diff --git a/chromium/content/browser/web_contents/file_chooser_impl_browsertest.cc b/chromium/content/browser/web_contents/file_chooser_impl_browsertest.cc new file mode 100644 index 00000000000..ba15c375791 --- /dev/null +++ b/chromium/content/browser/web_contents/file_chooser_impl_browsertest.cc @@ -0,0 +1,54 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/web_contents/file_chooser_impl.h" + +#include "base/bind.h" +#include "base/run_loop.h" +#include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/content_browser_test.h" +#include "content/public/test/content_browser_test_utils.h" +#include "content/shell/browser/shell.h" +#include "url/gurl.h" +#include "url/url_constants.h" + +namespace content { + +using FileChooserImplBrowserTest = ContentBrowserTest; + +IN_PROC_BROWSER_TEST_F(FileChooserImplBrowserTest, FileChooserAfterRfhDeath) { + EXPECT_TRUE(NavigateToURL(shell(), GURL(url::kAboutBlankURL))); + auto* rfh = static_cast<RenderFrameHostImpl*>( + shell()->web_contents()->GetMainFrame()); + mojo::Remote<blink::mojom::FileChooser> chooser = + FileChooserImpl::CreateBoundForTesting(rfh); + + // Kill the renderer process. + RenderProcessHostWatcher crash_observer( + rfh->GetProcess(), RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); + rfh->GetProcess()->Shutdown(0); + crash_observer.Wait(); + + auto quit_run_loop = [](base::RunLoop* run_loop, + blink::mojom::FileChooserResultPtr result) { + run_loop->Quit(); + }; + + // Call FileChooser methods. The browser process should not crash. + base::RunLoop run_loop1; + chooser->OpenFileChooser(blink::mojom::FileChooserParams::New(), + base::BindOnce(quit_run_loop, &run_loop1)); + run_loop1.Run(); + + base::RunLoop run_loop2; + chooser->EnumerateChosenDirectory(base::FilePath(), + base::BindOnce(quit_run_loop, &run_loop2)); + run_loop2.Run(); + + // Pass if this didn't crash. +} + +} // namespace content diff --git a/chromium/content/browser/web_contents/frame_tree_node_id_registry.h b/chromium/content/browser/web_contents/frame_tree_node_id_registry.h index 54c380a0eef..fd20f36feda 100644 --- a/chromium/content/browser/web_contents/frame_tree_node_id_registry.h +++ b/chromium/content/browser/web_contents/frame_tree_node_id_registry.h @@ -19,8 +19,8 @@ class WebContents; // A global map of UnguessableToken to FrameTreeNode id. This registry lives and // is used only on the thread identified by -// ServiceWorkerContext::GetCoreThreadId(), as that's the thread the -// class that adds/removes from this registry is on (ServiceWorkerProviderHost). +// ServiceWorkerContext::GetCoreThreadId(), as that's the thread the class that +// adds/removes from this registry is on (ServiceWorkerContainerHost). // TODO(crbug.com/824858): Make this live on the UI thread once the service // worker core thread moves to the UI thread. // diff --git a/chromium/content/browser/web_contents/web_contents_android.cc b/chromium/content/browser/web_contents/web_contents_android.cc index fdcf78a8b29..c8c30978be6 100644 --- a/chromium/content/browser/web_contents/web_contents_android.cc +++ b/chromium/content/browser/web_contents/web_contents_android.cc @@ -445,12 +445,6 @@ void WebContentsAndroid::SetAudioMuted(JNIEnv* env, web_contents_->SetAudioMuted(mute); } -jboolean WebContentsAndroid::IsShowingInterstitialPage( - JNIEnv* env, - const JavaParamRef<jobject>& obj) { - return web_contents_->ShowingInterstitialPage(); -} - jboolean WebContentsAndroid::FocusLocationBarByDefault( JNIEnv* env, const JavaParamRef<jobject>& obj) { @@ -471,7 +465,7 @@ void WebContentsAndroid::ExitFullscreen(JNIEnv* env, void WebContentsAndroid::ScrollFocusedEditableNodeIntoView( JNIEnv* env, const JavaParamRef<jobject>& obj) { - auto* input_handler = web_contents_->GetFocusedFrameInputHandler(); + auto* input_handler = web_contents_->GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; input_handler->ScrollFocusedEditableNodeIntoRect(gfx::Rect()); @@ -488,7 +482,7 @@ void WebContentsAndroid::SelectWordAroundCaretAck(bool did_select, void WebContentsAndroid::SelectWordAroundCaret( JNIEnv* env, const JavaParamRef<jobject>& obj) { - auto* input_handler = web_contents_->GetFocusedFrameInputHandler(); + auto* input_handler = web_contents_->GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; input_handler->SelectWordAroundCaret( @@ -510,7 +504,7 @@ bool WebContentsAndroid::InitializeRenderFrameForJavaScript() { if (!web_contents_->GetFrameTree() ->root() ->render_manager() - ->InitializeRenderFrameForImmediateUse()) { + ->InitializeMainRenderFrameForImmediateUse()) { LOG(ERROR) << "Failed to initialize RenderFrame to evaluate javascript"; return false; } diff --git a/chromium/content/browser/web_contents/web_contents_android.h b/chromium/content/browser/web_contents/web_contents_android.h index b846fb0758a..d8baeeefb32 100644 --- a/chromium/content/browser/web_contents/web_contents_android.h +++ b/chromium/content/browser/web_contents/web_contents_android.h @@ -111,9 +111,6 @@ class CONTENT_EXPORT WebContentsAndroid { const base::android::JavaParamRef<jobject>& jobj, jboolean mute); - jboolean IsShowingInterstitialPage( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj); jboolean FocusLocationBarByDefault( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); diff --git a/chromium/content/browser/web_contents/web_contents_impl.cc b/chromium/content/browser/web_contents/web_contents_impl.cc index 7908a60e174..1db46cd9bee 100644 --- a/chromium/content/browser/web_contents/web_contents_impl.cc +++ b/chromium/content/browser/web_contents/web_contents_impl.cc @@ -6,12 +6,14 @@ #include <stddef.h> +#include <algorithm> #include <cmath> #include <utility> #include <vector> #include "base/bind.h" #include "base/command_line.h" +#include "base/containers/flat_set.h" #include "base/debug/dump_without_crashing.h" #include "base/feature_list.h" #include "base/files/file_path.h" @@ -33,7 +35,6 @@ #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "base/task/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" @@ -72,6 +73,7 @@ #include "content/browser/media/media_web_contents_observer.h" #include "content/browser/media/session/media_session_impl.h" #include "content/browser/plugin_content_origin_allowlist.h" +#include "content/browser/portal/portal.h" #include "content/browser/renderer_host/frame_token_message_queue.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_view_host_delegate_view.h" @@ -196,6 +198,8 @@ namespace { const int kMinimumDelayBetweenLoadingUpdatesMS = 100; const char kDotGoogleDotCom[] = ".google.com"; +using LifecycleState = RenderFrameHostImpl::LifecycleState; + // TODO(crbug.com/1059903): Clean up after the initial investigation. constexpr base::Feature kCheckWebContentsAccessFromNonCurrentFrame{ "CheckWebContentsAccessFromNonCurrentFrame", @@ -307,6 +311,120 @@ void RecordMaxFrameCountUMA(size_t max_frame_count) { max_frame_count); } +// Returns whether the condition provided applies to any inner contents. +// This check is not recursive (however, the predicate provided may itself +// recurse each contents' own inner contents). +// +// For example, if this is used to aggregate state from inner contents to outer +// contents, then that propagation will gather transitive descendants without +// need for this helper to do so. In fact, in such cases recursing on inner +// contents here would make that operation quadratic rather than linear. +template <typename Functor> +bool AnyInnerWebContents(WebContents* web_contents, const Functor& f) { + const auto& inner_contents = web_contents->GetInnerWebContents(); + return std::any_of(inner_contents.begin(), inner_contents.end(), f); +} + +std::vector<RenderFrameHost*> GetAllFramesImpl(FrameTree& frame_tree, + bool include_pending) { + std::vector<RenderFrameHost*> frame_hosts; + for (FrameTreeNode* node : frame_tree.Nodes()) { + frame_hosts.push_back(node->current_frame_host()); + if (include_pending) { + RenderFrameHostImpl* pending_frame_host = + node->render_manager()->speculative_frame_host(); + if (pending_frame_host) + frame_hosts.push_back(pending_frame_host); + } + } + return frame_hosts; +} + +int SendToAllFramesImpl(FrameTree& frame_tree, + bool include_pending, + IPC::Message* message) { + int number_of_messages = 0; + std::vector<RenderFrameHost*> frame_hosts = + GetAllFramesImpl(frame_tree, include_pending); + for (RenderFrameHost* rfh : frame_hosts) { + if (!rfh->IsRenderFrameLive()) + continue; + + ++number_of_messages; + IPC::Message* message_copy = new IPC::Message(*message); + message_copy->set_routing_id(rfh->GetRoutingID()); + rfh->Send(message_copy); + } + delete message; + return number_of_messages; +} + +// Returns the set of all WebContentses that are reachable from |web_contents| +// by applying some combination of WebContents::GetOriginalOpener() and +// WebContents::GetOuterWebContents(). The |web_contents| parameter will be +// included in the returned set. +base::flat_set<WebContentsImpl*> GetAllOpeningWebContents( + WebContentsImpl* web_contents) { + base::flat_set<WebContentsImpl*> result; + base::flat_set<WebContentsImpl*> current; + + current.insert(web_contents); + + while (!current.empty()) { + WebContentsImpl* current_contents = *current.begin(); + current.erase(current.begin()); + auto insert_result = result.insert(current_contents); + + if (insert_result.second) { + RenderFrameHostImpl* opener_rfh = current_contents->GetOriginalOpener(); + if (opener_rfh) { + current.insert(static_cast<WebContentsImpl*>( + WebContents::FromRenderFrameHost(opener_rfh))); + } + + WebContentsImpl* outer_contents = current_contents->GetOuterWebContents(); + if (outer_contents) + current.insert(outer_contents); + } + } + + return result; +} + +// Used to attach the "set of fullscreen contents" to a browser context. Storing +// sets of WebContents on their browser context is done for two reasons. One, +// related WebContentses must necessarily share a browser context, so this saves +// lookup time by restricting to one specific browser context. Two, separating +// by browser context is preemptive paranoia about keeping things separate. +class FullscreenContentsHolder : public base::SupportsUserData::Data { + public: + FullscreenContentsHolder() = default; + ~FullscreenContentsHolder() override = default; + + FullscreenContentsHolder(const FullscreenContentsHolder&) = delete; + FullscreenContentsHolder& operator=(const FullscreenContentsHolder&) = delete; + + base::flat_set<WebContentsImpl*>* set() { return &set_; } + + private: + base::flat_set<WebContentsImpl*> set_; +}; + +const char kFullscreenContentsSet[] = "fullscreen-contents"; + +base::flat_set<WebContentsImpl*>* FullscreenContentsSet( + BrowserContext* browser_context) { + auto* set_holder = static_cast<FullscreenContentsHolder*>( + browser_context->GetUserData(kFullscreenContentsSet)); + if (!set_holder) { + auto new_holder = std::make_unique<FullscreenContentsHolder>(); + set_holder = new_holder.get(); + browser_context->SetUserData(kFullscreenContentsSet, std::move(new_holder)); + } + + return set_holder->set(); +} + } // namespace CreatedWindow::CreatedWindow() = default; @@ -340,8 +458,8 @@ std::unique_ptr<WebContents> WebContents::CreateWithSessionStorage( for (auto it = session_storage_namespace_map.begin(); it != session_storage_namespace_map.end(); ++it) { - new_contents->GetController() - .SetSessionStorageNamespace(it->first, it->second.get()); + new_contents->GetController().SetSessionStorageNamespace(it->first, + it->second.get()); } WebContentsImpl* outer_web_contents = nullptr; @@ -410,9 +528,7 @@ void WebContents::SetScreenOrientationDelegate( class WebContentsImpl::DestructionObserver : public WebContentsObserver { public: DestructionObserver(WebContentsImpl* owner, WebContents* watched_contents) - : WebContentsObserver(watched_contents), - owner_(owner) { - } + : WebContentsObserver(watched_contents), owner_(owner) {} // WebContentsObserver: void WebContentsDestroyed() override { @@ -426,6 +542,8 @@ class WebContentsImpl::DestructionObserver : public WebContentsObserver { DISALLOW_COPY_AND_ASSIGN(DestructionObserver); }; +// TODO(sreejakshetty): Make |WebContentsImpl::ColorChooser| per-frame instead +// of WebContents-owned. // WebContentsImpl::ColorChooser ---------------------------------------------- class WebContentsImpl::ColorChooser : public blink::mojom::ColorChooser { public: @@ -497,6 +615,7 @@ void WebContentsImpl::WebContentsTreeNode::AttachInnerWebContents( inner_web_contents_.push_back(std::move(inner_web_contents)); render_frame_host->frame_tree_node()->AddObserver(&inner_web_contents_node); + current_web_contents_->InnerWebContentsAttached(inner_web_contents_impl); } std::unique_ptr<WebContents> @@ -508,6 +627,7 @@ WebContentsImpl::WebContentsTreeNode::DetachInnerWebContents( detached_contents = std::move(web_contents); std::swap(web_contents, inner_web_contents_.back()); inner_web_contents_.pop_back(); + current_web_contents_->InnerWebContentsDetached(inner_web_contents); return detached_contents; } } @@ -568,7 +688,7 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context) render_view_host_delegate_view_(nullptr), created_with_opener_(false), node_(this), - frame_tree_(new Navigator(&controller_, this), this, this, this, this), + frame_tree_(&controller_, this, this, this, this, this), is_load_to_different_document_(false), crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING), crashed_error_code_(0), @@ -650,6 +770,8 @@ WebContentsImpl::~WebContentsImpl() { // observers. CHECK(!is_notifying_observers_); + FullscreenContentsSet(GetBrowserContext())->erase(this); + rwh_input_event_router_.reset(); for (auto& entry : receiver_sets_) @@ -1033,25 +1155,19 @@ void WebContentsImpl::ForEachFrame( } std::vector<RenderFrameHost*> WebContentsImpl::GetAllFrames() { - std::vector<RenderFrameHost*> frame_hosts; - for (FrameTreeNode* node : frame_tree_.Nodes()) - frame_hosts.push_back(node->current_frame_host()); - return frame_hosts; + return GetAllFramesImpl(frame_tree_, /*include_pending=*/false); +} + +std::vector<RenderFrameHost*> WebContentsImpl::GetAllFramesIncludingPending() { + return GetAllFramesImpl(frame_tree_, /*include_pending=*/true); } int WebContentsImpl::SendToAllFrames(IPC::Message* message) { - int number_of_messages = 0; - for (RenderFrameHost* rfh : GetAllFrames()) { - if (!rfh->IsRenderFrameLive()) - continue; + return SendToAllFramesImpl(frame_tree_, /*include_pending=*/false, message); +} - ++number_of_messages; - IPC::Message* message_copy = new IPC::Message(*message); - message_copy->set_routing_id(rfh->GetRoutingID()); - rfh->Send(message_copy); - } - delete message; - return number_of_messages; +int WebContentsImpl::SendToAllFramesIncludingPending(IPC::Message* message) { + return SendToAllFramesImpl(frame_tree_, /*include_pending=*/true, message); } void WebContentsImpl::SendPageMessage(IPC::Message* msg) { @@ -1274,9 +1390,10 @@ std::vector<WebContentsImpl*> WebContentsImpl::GetWebContentsAndAllInner() { } void WebContentsImpl::NotifyManifestUrlChanged( + RenderFrameHost* rfh, const base::Optional<GURL>& manifest_url) { for (auto& observer : observers_) - observer.DidUpdateWebManifestURL(manifest_url); + observer.DidUpdateWebManifestURL(rfh, manifest_url); } WebUI* WebContentsImpl::GetWebUI() { @@ -1389,20 +1506,13 @@ void WebContentsImpl::SetDisplayCutoutSafeArea(gfx::Insets insets) { #endif const base::string16& WebContentsImpl::GetTitle() { - // Transient entries take precedence. They are used for interstitial pages - // that are shown on top of existing pages. - NavigationEntry* entry = controller_.GetTransientEntry(); - if (entry) { - return entry->GetTitleForDisplay(); - } - WebUI* our_web_ui = GetRenderManager()->speculative_frame_host() ? GetRenderManager()->speculative_frame_host()->web_ui() : GetRenderManager()->current_frame_host()->web_ui(); if (our_web_ui) { // Don't override the title in view source mode. - entry = controller_.GetVisibleEntry(); + NavigationEntry* entry = controller_.GetVisibleEntry(); if (!(entry && entry->IsViewSourceMode())) { // Give the Web UI the chance to override our title. const base::string16& title = our_web_ui->GetOverriddenTitle(); @@ -1415,7 +1525,7 @@ const base::string16& WebContentsImpl::GetTitle() { // navigation entry. For example, when the user types in a URL, we want to // keep the old page's title until the new load has committed and we get a new // title. - entry = controller_.GetLastCommittedEntry(); + NavigationEntry* entry = controller_.GetLastCommittedEntry(); // We make an exception for initial navigations. We only want to use the title // from the visible entry if: @@ -1539,6 +1649,10 @@ bool WebContentsImpl::IsBeingCaptured() { return visible_capturer_count_ + hidden_capturer_count_ > 0; } +bool WebContentsImpl::IsBeingVisiblyCaptured() { + return visible_capturer_count_ > 0; +} + bool WebContentsImpl::IsAudioMuted() { return audio_stream_factory_ && audio_stream_factory_->IsMuted(); } @@ -1578,22 +1692,6 @@ bool WebContentsImpl::IsConnectedToHidDevice() { bool WebContentsImpl::HasNativeFileSystemHandles() { return native_file_system_handle_count_ > 0; } -bool WebContentsImpl::HasNativeFileSystemDirectoryHandles() { - return !native_file_system_directory_handles_.empty(); -} - -std::vector<base::FilePath> -WebContentsImpl::GetNativeFileSystemDirectoryHandles() { - std::vector<base::FilePath> result; - result.reserve(native_file_system_directory_handles_.size()); - for (auto const& entry : native_file_system_directory_handles_) - result.push_back(entry.first); - return result; -} - -bool WebContentsImpl::HasWritableNativeFileSystemHandles() { - return native_file_system_writable_handle_count_ > 0; -} bool WebContentsImpl::HasPictureInPictureVideo() { return has_picture_in_picture_video_; @@ -1691,10 +1789,16 @@ void WebContentsImpl::OnAudioStateChanged() { // This notification can come from any embedded contents or from this // WebContents' stream monitor. Aggregate these signals to get the actual // state. + // + // Note that guests may not be attached as inner contents, and so may need to + // be checked separately. bool is_currently_audible = audio_stream_monitor_.IsCurrentlyAudible() || (browser_plugin_embedder_ && - browser_plugin_embedder_->AreAnyGuestsCurrentlyAudible()); + browser_plugin_embedder_->AreAnyGuestsCurrentlyAudible()) || + AnyInnerWebContents(this, [](WebContents* inner_contents) { + return inner_contents->IsCurrentlyAudible(); + }); if (is_currently_audible == is_currently_audible_) return; @@ -1760,11 +1864,7 @@ Visibility WebContentsImpl::GetVisibility() { } bool WebContentsImpl::NeedToFireBeforeUnloadOrUnload() { - // TODO(creis): Should we fire even for interstitial pages? - if (ShowingInterstitialPage()) - return false; - - if (!WillNotifyDisconnection()) + if (!notify_disconnection_) return false; // Don't fire if the main frame's RenderViewHost indicates that beforeunload @@ -1814,8 +1914,10 @@ void WebContentsImpl::AttachInnerWebContents( DCHECK(!inner_web_contents_impl->node_.outer_web_contents()); auto* render_frame_host_impl = static_cast<RenderFrameHostImpl*>(render_frame_host); - DCHECK_EQ(&frame_tree_, - render_frame_host_impl->frame_tree_node()->frame_tree()); + DCHECK_EQ(&frame_tree_, render_frame_host_impl->frame_tree()); + + // Mark |render_frame_host_impl| as outer delegate frame. + render_frame_host_impl->SetIsOuterDelegateFrame(true); RenderFrameHostManager* inner_render_manager = inner_web_contents_impl->GetRenderManager(); @@ -1883,23 +1985,39 @@ void WebContentsImpl::AttachInnerWebContents( DCHECK_EQ(1u, node_.GetInnerWebContents().size()); inner_web_contents_impl->SetAsFocusedWebContentsIfNecessary(); } + + for (auto& observer : observers_) { + observer.InnerWebContentsAttached(inner_web_contents_impl, + render_frame_host, is_full_page); + } } std::unique_ptr<WebContents> WebContentsImpl::DetachFromOuterWebContents() { - DCHECK(node_.outer_web_contents()); + auto* outer_web_contents = GetOuterWebContents(); + DCHECK(outer_web_contents); + GetMainFrame()->ParentOrOuterDelegateFrame()->SetIsOuterDelegateFrame(false); + RecursivelyUnregisterFrameSinkIds(); - if (RenderWidgetHostViewBase* view = - static_cast<RenderWidgetHostViewBase*>(GetMainFrame()->GetView())) { - DCHECK(view->IsRenderWidgetHostViewChildFrame()); - view->Destroy(); - } - if (GetPendingMainFrame()) { - if (RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( - GetPendingMainFrame()->GetView())) { - DCHECK(view->IsRenderWidgetHostViewChildFrame()); - view->Destroy(); + + // Each RenderViewHost has a RenderWidgetHost which can have a + // RenderWidgetHostView, and it needs to be re-created with the appropriate + // platform view. It is important to re-create all child views, not only the + // current one, since the view can be swapped due to a cross-origin + // navigation. + std::set<RenderViewHostImpl*> render_view_hosts; + for (auto& render_view_host : GetFrameTree()->render_view_hosts()) { + if (render_view_host.second->GetWidget() && + render_view_host.second->GetWidget()->GetView()) { + DCHECK(render_view_host.second->GetWidget() + ->GetView() + ->IsRenderWidgetHostViewChildFrame()); + render_view_hosts.insert(render_view_host.second); } } + + for (auto* render_view_host : render_view_hosts) + render_view_host->GetWidget()->GetView()->Destroy(); + GetRenderManager()->DeleteOuterDelegateProxy( node_.OuterContentsFrameTreeNode() ->current_frame_host() @@ -1912,16 +2030,20 @@ std::unique_ptr<WebContents> WebContentsImpl::DetachFromOuterWebContents() { node_.DisconnectFromOuterWebContents(); DCHECK_EQ(web_contents.get(), this); node_.SetFocusedWebContents(this); - CreateRenderWidgetHostViewForRenderManager(GetRenderViewHost()); - if (GetPendingMainFrame()) { - CreateRenderWidgetHostViewForRenderManager( - GetPendingMainFrame()->render_view_host()); - } + + for (auto* render_view_host : render_view_hosts) + CreateRenderWidgetHostViewForRenderManager(render_view_host); + RecursivelyRegisterFrameSinkIds(); // TODO(adithyas): |browser_plugin_embedder_ax_tree_id| should either not be // used for portals, or it should get a different name. GetMainFrame()->set_browser_plugin_embedder_ax_tree_id(ui::AXTreeIDUnknown()); GetMainFrame()->UpdateAXTreeData(); + + // Invoke on the *outer* web contents observers for symmetry. + for (auto& observer : outer_web_contents->observers_) + observer.InnerWebContentsDetached(this); + return web_contents; } @@ -1959,12 +2081,15 @@ void WebContentsImpl::ReattachToOuterWebContentsFrame() { GetMainFrame()->UpdateAXTreeData(); } -void WebContentsImpl::DidActivatePortal(WebContents* predecessor_contents) { - DCHECK(predecessor_contents); +void WebContentsImpl::DidActivatePortal( + WebContentsImpl* predecessor_web_contents, + base::TimeTicks activation_time) { + DCHECK(predecessor_web_contents); NotifyInsidePortal(false); - GetDelegate()->WebContentsBecamePortal(predecessor_contents); for (auto& observer : observers_) - observer.DidActivatePortal(predecessor_contents); + observer.DidActivatePortal(predecessor_web_contents, activation_time); + + GetDelegate()->WebContentsBecamePortal(predecessor_web_contents); } void WebContentsImpl::NotifyInsidePortal(bool inside_portal) { @@ -2022,7 +2147,9 @@ void WebContentsImpl::SetPageFrozen(bool frozen) { // A visible page is never frozen. DCHECK_NE(Visibility::VISIBLE, GetVisibility()); - SendPageMessage(new PageMsg_SetPageFrozen(MSG_ROUTING_NONE, frozen)); + for (auto& entry : frame_tree_.render_view_hosts()) { + entry.second->SetIsFrozen(frozen); + } } std::unique_ptr<WebContents> WebContentsImpl::Clone() { @@ -2144,8 +2271,7 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) { // corresponding RenderView and main RenderFrame have already been created. // Ensure observers are notified about this. if (params.renderer_initiated_creation) { - GetRenderViewHost()->GetWidget()->SetRendererInitialized( - true, RenderWidgetHostImpl::RendererInitializer::kWebContentsInit); + GetRenderViewHost()->GetWidget()->set_renderer_initialized(true); GetRenderViewHost()->DispatchRenderViewCreated(); GetRenderManager()->current_frame_host()->SetRenderFrameCreated(true); } @@ -2214,17 +2340,12 @@ void WebContentsImpl::RemoveObserver(WebContentsObserver* observer) { std::set<RenderWidgetHostView*> WebContentsImpl::GetRenderWidgetHostViewsInTree() { std::set<RenderWidgetHostView*> set; - if (ShowingInterstitialPage()) { - if (RenderWidgetHostView* rwhv = GetRenderWidgetHostView()) + for (RenderFrameHost* rfh : GetAllFrames()) { + if (RenderWidgetHostView* rwhv = static_cast<RenderFrameHostImpl*>(rfh) + ->frame_tree_node() + ->render_manager() + ->GetRenderWidgetHostView()) { set.insert(rwhv); - } else { - for (RenderFrameHost* rfh : GetAllFrames()) { - if (RenderWidgetHostView* rwhv = static_cast<RenderFrameHostImpl*>(rfh) - ->frame_tree_node() - ->render_manager() - ->GetRenderWidgetHostView()) { - set.insert(rwhv); - } } } return set; @@ -2476,11 +2597,18 @@ RenderWidgetHostImpl* WebContentsImpl::GetRenderWidgetHostWithPageFocus() { } bool WebContentsImpl::CanEnterFullscreenMode() { - return fullscreen_blocker_count_ == 0; + // It's possible that this WebContents was spawned while blocking UI was on + // the screen, or that it was downstream from a WebContents when UI was + // blocked. Therefore, disqualify it from fullscreen if it or any upstream + // WebContents has an active blocker. + auto openers = GetAllOpeningWebContents(this); + return std::all_of(openers.begin(), openers.end(), [](auto* opener) { + return opener->fullscreen_blocker_count_ == 0; + }); } void WebContentsImpl::EnterFullscreenMode( - const GURL& origin, + RenderFrameHost* requesting_frame, const blink::mojom::FullscreenOptions& options) { DCHECK(CanEnterFullscreenMode()); @@ -2493,7 +2621,7 @@ void WebContentsImpl::EnterFullscreenMode( } if (delegate_) { - delegate_->EnterFullscreenModeForTab(this, origin, options); + delegate_->EnterFullscreenModeForTab(requesting_frame, options); if (keyboard_lock_widget_) delegate_->RequestKeyboardLock(this, esc_key_locked_); @@ -2501,6 +2629,8 @@ void WebContentsImpl::EnterFullscreenMode( for (auto& observer : observers_) observer.DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab(), false); + + FullscreenContentsSet(GetBrowserContext())->insert(this); } void WebContentsImpl::ExitFullscreenMode(bool will_cause_resize) { @@ -2543,6 +2673,8 @@ void WebContentsImpl::ExitFullscreenMode(bool will_cause_resize) { if (display_cutout_host_impl_) display_cutout_host_impl_->DidExitFullscreen(); + + FullscreenContentsSet(GetBrowserContext())->erase(this); } void WebContentsImpl::FullscreenStateChanged(RenderFrameHost* rfh, @@ -2631,11 +2763,8 @@ void WebContentsImpl::UpdateVisibilityAndNotifyPageAndView( // as soon as they are shown. But the Page and other classes do not expect // to be producing frames when the Page is hidden. So we make sure the Page // is shown first. - // TODO(yuzus): We should include RenderViewHosts in BackForwardCache in - // this iteration. Add a special method to get all RenderViewHosts in - // BackForwardCache in WebContentsImpl. - for (auto& entry : frame_tree_.render_view_hosts()) { - entry.second->SetVisibility(page_visibility); + for (auto* rvh : GetRenderViewHostsIncludingBackForwardCached()) { + rvh->SetVisibility(page_visibility); } } @@ -2655,8 +2784,7 @@ void WebContentsImpl::UpdateVisibilityAndNotifyPageAndView( } } - if (!ShowingInterstitialPage()) - SetVisibilityForChildViews(view_is_visible); + SetVisibilityForChildViews(view_is_visible); // Make sure to call SetVisibilityAndNotifyObservers(VISIBLE) before notifying // the CrossProcessFrameConnector. @@ -2668,8 +2796,8 @@ void WebContentsImpl::UpdateVisibilityAndNotifyPageAndView( if (page_visibility == PageVisibilityState::kHidden) { // Similar to when showing the page, we only hide the page after // hiding the individual RenderWidgets. - for (auto& entry : frame_tree_.render_view_hosts()) { - entry.second->SetVisibility(page_visibility); + for (auto* rvh : GetRenderViewHostsIncludingBackForwardCached()) { + rvh->SetVisibility(page_visibility); } } else { @@ -3030,30 +3158,25 @@ RenderFrameHostDelegate* WebContentsImpl::CreateNewWindow( void WebContentsImpl::CreateNewWidget( int32_t render_process_id, int32_t widget_route_id, - mojo::PendingRemote<mojom::Widget> widget, mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host, mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) { CreateNewWidget(render_process_id, widget_route_id, /*is_fullscreen=*/false, - std::move(widget), std::move(blink_widget_host), - std::move(blink_widget)); + std::move(blink_widget_host), std::move(blink_widget)); } void WebContentsImpl::CreateNewFullscreenWidget( int32_t render_process_id, int32_t widget_route_id, - mojo::PendingRemote<mojom::Widget> widget, mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host, mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) { CreateNewWidget(render_process_id, widget_route_id, /*is_fullscreen=*/true, - std::move(widget), std::move(blink_widget_host), - std::move(blink_widget)); + std::move(blink_widget_host), std::move(blink_widget)); } void WebContentsImpl::CreateNewWidget( int32_t render_process_id, int32_t route_id, bool is_fullscreen, - mojo::PendingRemote<mojom::Widget> widget, mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host, mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) { RenderProcessHost* process = RenderProcessHost::FromID(render_process_id); @@ -3065,9 +3188,9 @@ void WebContentsImpl::CreateNewWidget( return; } - RenderWidgetHostImpl* widget_host = new RenderWidgetHostImpl( - this, process, route_id, std::move(widget), IsHidden(), - std::make_unique<FrameTokenMessageQueue>()); + RenderWidgetHostImpl* widget_host = + new RenderWidgetHostImpl(this, process, route_id, IsHidden(), + std::make_unique<FrameTokenMessageQueue>()); widget_host->BindWidgetInterfaces(std::move(blink_widget_host), std::move(blink_widget)); @@ -3192,7 +3315,7 @@ void WebContentsImpl::ShowCreatedWidget(int process_id, fullscreen_widget_routing_id_ = route_id; if (delegate_ && delegate_->EmbedsFullscreenWidget()) { widget_host_view->InitAsChild(GetRenderWidgetHostView()->GetNativeView()); - delegate_->EnterFullscreenModeForTab(this, GURL(), + delegate_->EnterFullscreenModeForTab(GetMainFrame(), blink::mojom::FullscreenOptions()); } else { widget_host_view->InitAsFullscreen(view); @@ -3357,20 +3480,23 @@ base::string16 WebContentsImpl::DumpAccessibilityTree( } void WebContentsImpl::RecordAccessibilityEvents( - AccessibilityEventCallback callback, - bool start) { - if (start) { + bool start_recording, + base::Optional<AccessibilityEventCallback> callback) { + // Only pass a callback to RecordAccessibilityEvents when starting to record. + DCHECK_EQ(start_recording, callback.has_value()); + if (start_recording) { SetAccessibilityMode(ui::AXMode::kWebContents); auto* ax_mgr = GetOrCreateRootBrowserAccessibilityManager(); DCHECK(ax_mgr); base::ProcessId pid = base::Process::Current().Pid(); event_recorder_ = content::AccessibilityEventRecorder::Create( ax_mgr, pid, base::StringPiece{}); - event_recorder_->ListenToEvents(callback); + event_recorder_->ListenToEvents(*callback); } else { - DCHECK(event_recorder_); - event_recorder_->FlushAsyncEvents(); - event_recorder_ = nullptr; + if (event_recorder_) { + event_recorder_->FlushAsyncEvents(); + event_recorder_.reset(nullptr); + } } } @@ -3391,6 +3517,13 @@ RenderFrameHost* WebContentsImpl::GetGuestByInstanceID( } device::mojom::GeolocationContext* WebContentsImpl::GetGeolocationContext() { + if (delegate_) { + auto* installed_webapp_context = + delegate_->GetInstalledWebappGeolocationContext(); + if (installed_webapp_context) + return installed_webapp_context; + } + if (!geolocation_context_) { GetDeviceService().BindGeolocationContext( geolocation_context_.BindNewPipeAndPassReceiver()); @@ -3470,7 +3603,7 @@ BrowserAccessibilityManager* void WebContentsImpl::ExecuteEditCommand( const std::string& command, const base::Optional<base::string16>& value) { - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3478,7 +3611,7 @@ void WebContentsImpl::ExecuteEditCommand( } void WebContentsImpl::MoveRangeSelectionExtent(const gfx::Point& extent) { - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3487,7 +3620,7 @@ void WebContentsImpl::MoveRangeSelectionExtent(const gfx::Point& extent) { void WebContentsImpl::SelectRange(const gfx::Point& base, const gfx::Point& extent) { - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3495,7 +3628,7 @@ void WebContentsImpl::SelectRange(const gfx::Point& base, } void WebContentsImpl::MoveCaret(const gfx::Point& extent) { - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3506,7 +3639,7 @@ void WebContentsImpl::AdjustSelectionByCharacterOffset( int start_adjust, int end_adjust, bool show_selection_menu) { - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3596,20 +3729,8 @@ void WebContentsImpl::ReloadFocusedFrame() { focused_frame->Reload(); } -std::vector<mojo::Remote<blink::mojom::PauseSubresourceLoadingHandle>> -WebContentsImpl::PauseSubresourceLoading() { - std::vector<mojo::Remote<blink::mojom::PauseSubresourceLoadingHandle>> - handles; - for (RenderFrameHost* rfh : GetAllFrames()) { - if (!rfh->IsRenderFrameLive()) - continue; - handles.push_back(rfh->PauseSubresourceLoading()); - } - return handles; -} - void WebContentsImpl::Undo() { - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3618,7 +3739,7 @@ void WebContentsImpl::Undo() { } void WebContentsImpl::Redo() { - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3627,7 +3748,7 @@ void WebContentsImpl::Redo() { } void WebContentsImpl::Cut() { - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3636,7 +3757,7 @@ void WebContentsImpl::Cut() { } void WebContentsImpl::Copy() { - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3646,7 +3767,7 @@ void WebContentsImpl::Copy() { void WebContentsImpl::CopyToFindPboard() { #if defined(OS_MACOSX) - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3657,7 +3778,7 @@ void WebContentsImpl::CopyToFindPboard() { } void WebContentsImpl::Paste() { - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3668,7 +3789,7 @@ void WebContentsImpl::Paste() { } void WebContentsImpl::PasteAndMatchStyle() { - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3679,7 +3800,7 @@ void WebContentsImpl::PasteAndMatchStyle() { } void WebContentsImpl::Delete() { - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3688,7 +3809,7 @@ void WebContentsImpl::Delete() { } void WebContentsImpl::SelectAll() { - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3697,7 +3818,7 @@ void WebContentsImpl::SelectAll() { } void WebContentsImpl::CollapseSelection() { - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3705,7 +3826,7 @@ void WebContentsImpl::CollapseSelection() { } void WebContentsImpl::Replace(const base::string16& word) { - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3713,7 +3834,7 @@ void WebContentsImpl::Replace(const base::string16& word) { } void WebContentsImpl::ReplaceMisspelling(const base::string16& word) { - auto* input_handler = GetFocusedFrameInputHandler(); + auto* input_handler = GetFocusedFrameWidgetInputHandler(); if (!input_handler) return; @@ -3757,9 +3878,7 @@ gfx::Rect WebContentsImpl::GetViewBounds() { } gfx::Rect WebContentsImpl::GetContainerBounds() { - gfx::Rect rv; - view_->GetContainerBounds(&rv); - return rv; + return view_->GetContainerBounds(); } DropData* WebContentsImpl::GetDropData() { @@ -3786,19 +3905,14 @@ void WebContentsImpl::FocusThroughTabTraversal(bool reverse) { view_->FocusThroughTabTraversal(reverse); } -bool WebContentsImpl::ShowingInterstitialPage() { - return false; -} - bool WebContentsImpl::IsSavable() { // WebKit creates Document object when MIME type is application/xhtml+xml, // so we also support this MIME type. - return contents_mime_type_ == "text/html" || - contents_mime_type_ == "text/xml" || - contents_mime_type_ == "application/xhtml+xml" || - contents_mime_type_ == "text/plain" || - contents_mime_type_ == "text/css" || - blink::IsSupportedJavascriptMimeType(contents_mime_type_); + std::string mime_type = GetContentsMimeType(); + return mime_type == "text/html" || mime_type == "text/xml" || + mime_type == "application/xhtml+xml" || mime_type == "text/plain" || + mime_type == "text/css" || + blink::IsSupportedJavascriptMimeType(mime_type); } void WebContentsImpl::OnSavePage() { @@ -3950,11 +4064,7 @@ void WebContentsImpl::GenerateWebBundle( } const std::string& WebContentsImpl::GetContentsMimeType() { - return contents_mime_type_; -} - -bool WebContentsImpl::WillNotifyDisconnection() { - return notify_disconnection_; + return GetRenderViewHost()->contents_mime_type(); } blink::mojom::RendererPreferences* WebContentsImpl::GetMutableRendererPrefs() { @@ -4168,8 +4278,8 @@ int WebContentsImpl::DownloadImageInFrame( // Android), the downloader service will be invalid. Pre-Mojo, this would // hang the callback indefinitely since the IPC would be dropped. Now, // respond with a 400 HTTP error code to indicate that something went wrong. - base::PostTask( - FROM_HERE, {BrowserThread::UI}, + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&WebContentsImpl::OnDidDownloadImage, weak_factory_.GetWeakPtr(), std::move(callback), download_id, url, 400, std::vector<SkBitmap>(), @@ -4222,37 +4332,47 @@ void WebContentsImpl::ExitFullscreen(bool will_cause_resize) { } base::ScopedClosureRunner WebContentsImpl::ForSecurityDropFullscreen() { - // There are two chains of WebContents to kick out of fullscreen. - // - // Chain 1, the inner/outer WebContents chain. If an inner WebContents has - // done something that requires the browser to drop fullscreen, drop - // fullscreen from it and any outer WebContents that may be in fullscreen. - // - // Chain 2, the opener WebContents chain. If a WebContents has done something - // that requires the browser to drop fullscreen, drop fullscreen from any - // WebContents that was involved in the chain of opening it. - // - // Note that these two chains don't interact, as only a top-level WebContents - // can have an opener. This simplifies things. + // Kick WebContentses that are "related" to this WebContents out of + // fullscreen. This needs to be done with two passes, because it is simple to + // walk _up_ the chain of openers and outer contents, but it not simple to + // walk _down_ the chain. + + // First, determine if any WebContents that is in fullscreen has this + // WebContents as an upstream contents. Drop that WebContents out of + // fullscreen if it does. This is theoretically quadratic-ish (fullscreen + // contentses x each one's opener length) but neither of those is expected to + // ever be a large number. + + auto fullscreen_set_copy = *FullscreenContentsSet(GetBrowserContext()); + for (auto* fullscreen_contents : fullscreen_set_copy) { + // Checking IsFullscreenForCurrentTab() for tabs in the fullscreen set may + // seem redundant, but teeeeechnically fullscreen is run by the delegate, + // and it's possible that the delegate's notion of fullscreen may have + // changed outside of WebContents's notice. + if (fullscreen_contents->IsFullscreenForCurrentTab()) { + auto opener_contentses = GetAllOpeningWebContents(fullscreen_contents); + if (opener_contentses.count(this)) + fullscreen_contents->ExitFullscreen(true); + } + } + + // Second, walk upstream from this WebContents, and drop the fullscreen of + // all WebContentses that are in fullscreen. Block all the WebContentses in + // the chain from entering fullscreen while the returned closure runner is + // alive. It's OK that this set doesn't contain downstream WebContentses, as + // any request to enter fullscreen will have the upstream of the WebContents + // checked. (See CanEnterFullscreenMode().) std::vector<base::WeakPtr<WebContentsImpl>> blocked_contentses; - WebContentsImpl* web_contents = this; - while (web_contents) { + for (auto* opener : GetAllOpeningWebContents(this)) { // Drop fullscreen if the WebContents is in it, and... - if (web_contents->IsFullscreenForCurrentTab()) - web_contents->ExitFullscreen(true); + if (opener->IsFullscreenForCurrentTab()) + opener->ExitFullscreen(true); // ...block the WebContents from entering fullscreen until further notice. - ++web_contents->fullscreen_blocker_count_; - blocked_contentses.push_back(web_contents->weak_factory_.GetWeakPtr()); - - if (web_contents->HasOriginalOpener()) { - web_contents = static_cast<WebContentsImpl*>( - FromRenderFrameHost(web_contents->GetOriginalOpener())); - } else { - web_contents = web_contents->GetOuterWebContents(); - } + ++opener->fullscreen_blocker_count_; + blocked_contentses.push_back(opener->weak_factory_.GetWeakPtr()); } return base::ScopedClosureRunner(base::BindOnce( @@ -4312,9 +4432,6 @@ void WebContentsImpl::DidStartNavigation(NavigationHandle* navigation_handle) { for (auto& observer : observers_) observer.DidStartNavigation(navigation_handle); - if (display_cutout_host_impl_) - display_cutout_host_impl_->DidStartNavigation(navigation_handle); - if (navigation_handle->IsInMainFrame()) { // When the browser is started with about:blank as the startup URL, focus // the location bar (which will also select its contents) so people can @@ -4567,10 +4684,6 @@ void WebContentsImpl::DidNavigateAnyFramePostCommit( } } -void WebContentsImpl::SetMainFrameMimeType(const std::string& mime_type) { - contents_mime_type_ = mime_type; -} - bool WebContentsImpl::CanOverscrollContent() const { // Disable overscroll when touch emulation is on. See crbug.com/369938. if (force_disable_overscroll_content_) @@ -4648,13 +4761,12 @@ void WebContentsImpl::PassiveInsecureContentFound(const GURL& resource_url) { } bool WebContentsImpl::ShouldAllowRunningInsecureContent( - WebContents* web_contents, bool allowed_per_prefs, const url::Origin& origin, const GURL& resource_url) { if (delegate_) { - return delegate_->ShouldAllowRunningInsecureContent( - web_contents, allowed_per_prefs, origin, resource_url); + return delegate_->ShouldAllowRunningInsecureContent(this, allowed_per_prefs, + origin, resource_url); } return allowed_per_prefs; @@ -4671,10 +4783,7 @@ void WebContentsImpl::ViewSource(RenderFrameHostImpl* frame) { // Use the last committed entry, since the pending entry hasn't loaded yet and // won't be copied into the cloned tab. NavigationEntryImpl* last_committed_entry = - static_cast<NavigationEntryImpl*>(frame->frame_tree_node() - ->navigator() - ->GetController() - ->GetLastCommittedEntry()); + GetController().GetLastCommittedEntry(); if (!last_committed_entry) return; @@ -4806,15 +4915,22 @@ void WebContentsImpl::OnDidDisplayContentWithCertificateErrors( void WebContentsImpl::OnDidRunContentWithCertificateErrors( RenderFrameHostImpl* source) { - // TODO(nick, estark): Do we need to consider |source| here somehow? - NavigationEntry* entry = controller_.GetVisibleEntry(); - if (!entry) + // For RenderFrameHosts that are inactive and going to be discarded, we can + // disregard this message; there's no need to update the UI if the UI will + // never be shown again. + // + // We still process this message for speculative RenderFrameHosts. This can + // happen when a subframe's main resource has a certificate error. The + // currently committed navigation entry will get marked as having run insecure + // content and that will carry over to the navigation entry for the + // speculative RFH when it commits. + if (source->lifecycle_state() != + RenderFrameHostImpl::LifecycleState::kSpeculative && + source->IsInactiveAndDisallowReactivation()) { return; - - // TODO(estark): check that this does something reasonable for - // about:blank and sandboxed origins. https://crbug.com/609527 + } controller_.ssl_manager()->DidRunContentWithCertErrors( - entry->GetURL().GetOrigin()); + source->GetMainFrame()->GetLastCommittedOrigin().GetURL()); } void WebContentsImpl::DOMContentLoaded(RenderFrameHost* render_frame_host) { @@ -4985,6 +5101,19 @@ void WebContentsImpl::DomOperationResponse(const std::string& json_string) { Details<const std::string>(&json_string)); } +void WebContentsImpl::SavableResourceLinksResponse( + RenderFrameHostImpl* source, + const std::vector<GURL>& resources_list, + blink::mojom::ReferrerPtr referrer, + const std::vector<blink::mojom::SavableSubframePtr>& subframes) { + save_package_->SavableResourceLinksResponse(source, resources_list, + std::move(referrer), subframes); +} + +void WebContentsImpl::SavableResourceLinksError(RenderFrameHostImpl* source) { + save_package_->SavableResourceLinksError(source); +} + void WebContentsImpl::OnServiceWorkerAccessed( RenderFrameHost* render_frame_host, const GURL& scope, @@ -5117,7 +5246,7 @@ void WebContentsImpl::UpdateFaviconURL( favicon_urls_ = std::move(candidates); for (auto& observer : observers_) - observer.DidUpdateFaviconURL(favicon_urls_); + observer.DidUpdateFaviconURL(source, favicon_urls_); } void WebContentsImpl::SetIsOverlayContent(bool is_overlay_content) { @@ -5143,6 +5272,10 @@ bool WebContentsImpl::IsPortal() { return portal(); } +WebContentsImpl* WebContentsImpl::GetPortalHostWebContents() { + return portal() ? portal()->GetPortalHostContents() : nullptr; +} + void WebContentsImpl::NotifyBeforeFormRepostWarningShow() { for (auto& observer : observers_) observer.BeforeFormRepostWarningShow(); @@ -5207,7 +5340,6 @@ void WebContentsImpl::ResetLoadProgressState() { // Notifies the RenderWidgetHost instance about the fact that the page is // loading, or done loading. void WebContentsImpl::LoadingStateChanged(bool to_different_document, - bool due_to_interstitial, LoadNotificationDetails* details) { if (is_being_destroyed_) return; @@ -5490,11 +5622,8 @@ void WebContentsImpl::RunJavaScriptDialog( javascript_dialog_navigation_deferrer_ = std::make_unique<JavaScriptDialogNavigationDeferrer>(); - // Suppress JavaScript dialogs when requested. Also suppress messages when - // showing an interstitial as it's shown over the previous page and we don't - // want the hidden page's dialogs to interfere with the interstitial. - bool should_suppress = ShowingInterstitialPage() || - (delegate_ && delegate_->ShouldSuppressDialogs(this)); + // Suppress JavaScript dialogs when requested. + bool should_suppress = delegate_ && delegate_->ShouldSuppressDialogs(this); bool has_non_devtools_handlers = delegate_ && dialog_manager_; bool has_handlers = page_handlers.size() || has_non_devtools_handlers; bool suppress_this_message = should_suppress || !has_handlers; @@ -5573,7 +5702,7 @@ void WebContentsImpl::RunBeforeUnloadConfirm( javascript_dialog_navigation_deferrer_ = std::make_unique<JavaScriptDialogNavigationDeferrer>(); - bool should_suppress = ShowingInterstitialPage() || !rfhi->is_active() || + bool should_suppress = !rfhi->IsCurrent() || (delegate_ && delegate_->ShouldSuppressDialogs(this)); bool has_non_devtools_handlers = delegate_ && dialog_manager_; bool has_handlers = page_handlers.size() || has_non_devtools_handlers; @@ -5787,6 +5916,18 @@ void WebContentsImpl::InnerWebContentsCreated(WebContents* inner_web_contents) { observer.InnerWebContentsCreated(inner_web_contents); } +void WebContentsImpl::InnerWebContentsAttached( + WebContents* inner_web_contents) { + if (inner_web_contents->IsCurrentlyAudible()) + OnAudioStateChanged(); +} + +void WebContentsImpl::InnerWebContentsDetached( + WebContents* inner_web_contents) { + if (!is_being_destroyed_) + OnAudioStateChanged(); +} + void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) { if (delegate_) view_->SetOverscrollControllerEnabled(CanOverscrollContent()); @@ -5924,7 +6065,7 @@ void WebContentsImpl::RequestSetBounds(const gfx::Rect& new_bounds) { void WebContentsImpl::DidStartLoading(FrameTreeNode* frame_tree_node, bool to_different_document) { LoadingStateChanged(frame_tree_node->IsMainFrame() && to_different_document, - false, nullptr); + nullptr); // Reset the focus state from DidStartNavigation to false if a new load starts // afterward, in case loading logic triggers a FocusLocationBarByDefault call. @@ -5956,7 +6097,7 @@ void WebContentsImpl::DidStopLoading() { controller_.GetCurrentEntryIndex())); } - LoadingStateChanged(true, false, details.get()); + LoadingStateChanged(true, details.get()); } void WebContentsImpl::DidChangeLoadProgress() { @@ -6322,8 +6463,8 @@ void WebContentsImpl::OnFocusedElementChangedInFrame( static_cast<RenderWidgetHostViewBase*>(GetRenderWidgetHostView()); if (!root_view || !frame->GetView()) return; - - // Converting to screen coordinates. + // Convert to screen coordinates from window coordinates by adding the + // window's origin. gfx::Point origin = bounds_in_root_view.origin(); origin += root_view->GetViewBounds().OffsetFromOrigin(); gfx::Rect bounds_in_screen(origin, bounds_in_root_view.size()); @@ -6558,11 +6699,8 @@ void WebContentsImpl::CreateRenderWidgetHostViewForRenderManager( bool WebContentsImpl::CreateRenderViewForRenderManager( RenderViewHost* render_view_host, - int opener_frame_routing_id, - int proxy_routing_id, - const base::UnguessableToken& frame_token, - const base::UnguessableToken& devtools_frame_token, - const FrameReplicationState& replicated_frame_state) { + const base::Optional<base::UnguessableToken>& opener_frame_token, + int proxy_routing_id) { TRACE_EVENT0("browser,navigation", "WebContentsImpl::CreateRenderViewForRenderManager"); @@ -6570,9 +6708,8 @@ bool WebContentsImpl::CreateRenderViewForRenderManager( CreateRenderWidgetHostViewForRenderManager(render_view_host); if (!static_cast<RenderViewHostImpl*>(render_view_host) - ->CreateRenderView(opener_frame_routing_id, proxy_routing_id, - frame_token, devtools_frame_token, - replicated_frame_state, created_with_opener_)) { + ->CreateRenderView(opener_frame_token, proxy_routing_id, + created_with_opener_)) { return false; } // Set the TextAutosizer state from the main frame's renderer on the new view, @@ -6608,7 +6745,7 @@ bool WebContentsImpl::CreateRenderViewForRenderManager( bool WebContentsImpl::CreateRenderFrameForRenderManager( RenderFrameHost* render_frame_host, int previous_routing_id, - int opener_routing_id, + const base::Optional<base::UnguessableToken>& opener_frame_token, int parent_routing_id, int previous_sibling_routing_id) { TRACE_EVENT0("browser,navigation", @@ -6616,9 +6753,10 @@ bool WebContentsImpl::CreateRenderFrameForRenderManager( RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(render_frame_host); - if (!rfh->CreateRenderFrame(previous_routing_id, opener_routing_id, - parent_routing_id, previous_sibling_routing_id)) + if (!rfh->CreateRenderFrame(previous_routing_id, opener_frame_token, + parent_routing_id, previous_sibling_routing_id)) { return false; + } // TODO(nasko): When RenderWidgetHost is owned by RenderFrameHost, the passed // RenderFrameHost will have to be associated with the appropriate @@ -6980,79 +7118,6 @@ void WebContentsImpl::DecrementNativeFileSystemHandleCount() { } } -void WebContentsImpl::AddNativeFileSystemDirectoryHandle( - const base::FilePath& path) { - // Trying to invalidate the tab state while being destroyed could result in a - // use after free. - if (IsBeingDestroyed()) - return; - - // Notify for UI updates if the state changes. Need both TYPE_TAB and TYPE_URL - // to update both the tab-level usage indicator and the usage indicator in the - // omnibox. - const bool was_empty = native_file_system_directory_handles_.empty(); - native_file_system_directory_handles_[path]++; - if (was_empty) { - NotifyNavigationStateChanged(static_cast<content::InvalidateTypes>( - INVALIDATE_TYPE_TAB | INVALIDATE_TYPE_URL)); - } -} - -void WebContentsImpl::RemoveNativeFileSystemDirectoryHandle( - const base::FilePath& path) { - // Trying to invalidate the tab state while being destroyed could result in a - // use after free. - if (IsBeingDestroyed()) - return; - - // Notify for UI updates if the state changes. Need both TYPE_TAB and TYPE_URL - // to update both the tab-level usage indicator and the usage indicator in the - // omnibox. - auto it = native_file_system_directory_handles_.find(path); - DCHECK(it != native_file_system_directory_handles_.end()); - DCHECK_NE(0u, it->second); - it->second--; - if (it->second == 0) - native_file_system_directory_handles_.erase(it); - if (native_file_system_directory_handles_.empty()) { - NotifyNavigationStateChanged(static_cast<content::InvalidateTypes>( - INVALIDATE_TYPE_TAB | INVALIDATE_TYPE_URL)); - } -} - -void WebContentsImpl::IncrementWritableNativeFileSystemHandleCount() { - // Trying to invalidate the tab state while being destroyed could result in a - // use after free. - if (IsBeingDestroyed()) - return; - - // Notify for UI updates if the state changes. Need both TYPE_TAB and TYPE_URL - // to update both the tab-level usage indicator and the usage indicator in the - // omnibox. - native_file_system_writable_handle_count_++; - if (native_file_system_writable_handle_count_ == 1) { - NotifyNavigationStateChanged(static_cast<content::InvalidateTypes>( - INVALIDATE_TYPE_TAB | INVALIDATE_TYPE_URL)); - } -} - -void WebContentsImpl::DecrementWritableNativeFileSystemHandleCount() { - // Trying to invalidate the tab state while being destroyed could result in a - // use after free. - if (IsBeingDestroyed()) - return; - - // Notify for UI updates if the state changes. Need both TYPE_TAB and TYPE_URL - // to update both the tab-level usage indicator and the usage indicator in the - // omnibox. - DCHECK_NE(0u, native_file_system_writable_handle_count_); - native_file_system_writable_handle_count_--; - if (native_file_system_writable_handle_count_ == 0) { - NotifyNavigationStateChanged(static_cast<content::InvalidateTypes>( - INVALIDATE_TYPE_TAB | INVALIDATE_TYPE_URL)); - } -} - void WebContentsImpl::SetHasPersistentVideo(bool has_persistent_video) { if (has_persistent_video_ == has_persistent_video) return; @@ -7178,6 +7243,11 @@ void WebContentsImpl::MediaResized(const gfx::Size& size, observer.MediaResized(size, id); } +void WebContentsImpl::MediaBufferUnderflow(const MediaPlayerId& id) { + for (auto& observer : observers_) + observer.MediaBufferUnderflow(id); +} + void WebContentsImpl::MediaEffectivelyFullscreenChanged(bool is_fullscreen) { for (auto& observer : observers_) observer.MediaEffectivelyFullscreenChanged(is_fullscreen); @@ -7209,6 +7279,12 @@ void WebContentsImpl::AudioContextPlaybackStopped(RenderFrameHost* host, observer.AudioContextPlaybackStopped(audio_context_id); } +void WebContentsImpl::OnFrameAudioStateChanged(RenderFrameHost* host, + bool is_audible) { + for (auto& observer : observers_) + observer.OnFrameAudioStateChanged(host, is_audible); +} + media::MediaMetricsProvider::RecordAggregateWatchTimeCallback WebContentsImpl::GetRecordAggregateWatchTimeCallback() { if (!delegate_ || !delegate_->GetDelegateWeakPtr()) @@ -7436,15 +7512,53 @@ void WebContentsImpl::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) { NotifyPreferencesChanged(); } -mojom::FrameInputHandler* WebContentsImpl::GetFocusedFrameInputHandler() { - auto* focused_frame = GetFocusedFrame(); - if (!focused_frame) +blink::mojom::FrameWidgetInputHandler* +WebContentsImpl::GetFocusedFrameWidgetInputHandler() { + auto* focused_render_widget_host = + GetFocusedRenderWidgetHost(GetMainFrame()->GetRenderWidgetHost()); + if (!focused_render_widget_host) return nullptr; - return focused_frame->GetFrameInputHandler(); + return focused_render_widget_host->GetFrameWidgetInputHandler(); } ukm::SourceId WebContentsImpl::GetCurrentPageUkmSourceId() { return GetMainFrame()->GetPageUkmSourceId(); } +std::set<RenderViewHostImpl*> +WebContentsImpl::GetRenderViewHostsIncludingBackForwardCached() { + std::set<RenderViewHostImpl*> render_view_hosts; + + // Add RenderViewHostImpls outside of BackForwardCache. + for (auto& render_view_host : frame_tree_.render_view_hosts()) { + render_view_hosts.insert(render_view_host.second); + } + + // Add RenderViewHostImpls in BackForwardCache. + const auto& entries = GetController().GetBackForwardCache().GetEntries(); + for (const auto& entry : entries) { + std::set<RenderViewHostImpl*> bfcached_hosts = entry->render_view_hosts; + render_view_hosts.insert(bfcached_hosts.begin(), bfcached_hosts.end()); + } + + return render_view_hosts; +} + +void WebContentsImpl::RenderFrameHostStateChanged( + RenderFrameHost* render_frame_host, + LifecycleState old_state, + LifecycleState new_state) { + if (render_frame_host->GetParent()) + return; + + if (old_state == LifecycleState::kActive && + new_state != LifecycleState::kActive) { + // TODO(sreejakshetty): Remove this reset when ColorChooser becomes + // per-frame. + // Close the color chooser popup when RenderFrameHost changes state from + // kActive. + color_chooser_.reset(); + } +} + } // namespace content diff --git a/chromium/content/browser/web_contents/web_contents_impl.h b/chromium/content/browser/web_contents/web_contents_impl.h index 29125641f89..a52e45b40c8 100644 --- a/chromium/content/browser/web_contents/web_contents_impl.h +++ b/chromium/content/browser/web_contents/web_contents_impl.h @@ -28,7 +28,6 @@ #include "build/build_config.h" #include "components/download/public/common/download_url_parameters.h" #include "content/browser/accessibility/accessibility_event_recorder.h" -#include "content/browser/frame_host/file_chooser_impl.h" #include "content/browser/frame_host/frame_tree.h" #include "content/browser/frame_host/frame_tree_node.h" #include "content/browser/frame_host/navigation_controller_delegate.h" @@ -42,6 +41,7 @@ #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" #include "content/browser/wake_lock/wake_lock_context_host.h" +#include "content/browser/web_contents/file_chooser_impl.h" #include "content/common/content_export.h" #include "content/public/browser/accessibility_tree_formatter.h" #include "content/public/browser/color_chooser.h" @@ -65,6 +65,7 @@ #include "services/device/public/mojom/geolocation_context.mojom.h" #include "services/metrics/public/cpp/ukm_recorder.h" #include "services/network/public/mojom/fetch_api.mojom-forward.h" +#include "third_party/blink/public/common/page/web_drag_operation.h" #include "third_party/blink/public/mojom/choosers/color_chooser.mojom.h" #include "third_party/blink/public/mojom/choosers/popup_menu.mojom.h" #include "third_party/blink/public/mojom/frame/blocked_navigation_types.mojom.h" @@ -73,7 +74,6 @@ #include "third_party/blink/public/mojom/page/display_cutout.mojom.h" #include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h" #include "third_party/blink/public/mojom/renderer_preferences.mojom.h" -#include "third_party/blink/public/platform/web_drag_operation.h" #include "ui/accessibility/ax_mode.h" #include "ui/base/page_transition_types.h" #include "ui/gfx/geometry/rect_f.h" @@ -309,7 +309,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, // within it (recursively). std::vector<WebContentsImpl*> GetWebContentsAndAllInner(); - void NotifyManifestUrlChanged(const base::Optional<GURL>& manifest_url); + void NotifyManifestUrlChanged(RenderFrameHost* rfh, + const base::Optional<GURL>& manifest_url); #if defined(OS_ANDROID) void SetMainFrameImportance(ChildProcessImportance importance); @@ -372,6 +373,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, bool stay_hidden) override; void DecrementCapturerCount(bool stay_hidden) override; bool IsBeingCaptured() override; + bool IsBeingVisiblyCaptured() override; bool IsAudioMuted() override; void SetAudioMuted(bool mute) override; bool IsCurrentlyAudible() override; @@ -379,9 +381,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, bool IsConnectedToSerialPort() override; bool IsConnectedToHidDevice() override; bool HasNativeFileSystemHandles() override; - bool HasNativeFileSystemDirectoryHandles() override; - std::vector<base::FilePath> GetNativeFileSystemDirectoryHandles() override; - bool HasWritableNativeFileSystemHandles() override; bool HasPictureInPictureVideo() override; bool IsCrashed() override; void SetIsCrashed(base::TerminationStatus status, int error_code) override; @@ -402,6 +401,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, bool is_full_page) override; bool IsInnerWebContentsForGuest() override; bool IsPortal() override; + WebContentsImpl* GetPortalHostWebContents() override; RenderFrameHostImpl* GetOuterWebContentsFrame() override; WebContentsImpl* GetOuterWebContents() override; WebContentsImpl* GetOutermostWebContents() override; @@ -429,8 +429,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, void ReplaceMisspelling(const base::string16& word) override; void NotifyContextMenuClosed( const CustomContextMenuContext& context) override; - std::vector<mojo::Remote<blink::mojom::PauseSubresourceLoadingHandle>> - PauseSubresourceLoading() override; void ExecuteCustomContextMenuCommand( int action, const CustomContextMenuContext& context) override; @@ -445,7 +443,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, void StoreFocus() override; void RestoreFocus() override; void FocusThroughTabTraversal(bool reverse) override; - bool ShowingInterstitialPage() override; bool IsSavable() override; void OnSavePage() override; bool SavePage(const base::FilePath& main_file, @@ -466,10 +463,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, base::OnceCallback<void(uint64_t, data_decoder::mojom::WebBundlerError)> callback) override; const std::string& GetContentsMimeType() override; - bool WillNotifyDisconnection() override; blink::mojom::RendererPreferences* GetMutableRendererPrefs() override; void Close() override; - void SystemDragEnded(RenderWidgetHost* source_rwh) override; void SetClosedByUserGesture(bool value) override; bool GetClosedByUserGesture() override; int GetMinimumZoomPercent() override; @@ -570,14 +565,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, RenderFrameHost* render_frame_host, bool is_reload, JavaScriptDialogCallback response_callback) override; - void RunFileChooser( - RenderFrameHost* render_frame_host, - std::unique_ptr<FileChooserImpl::FileSelectListenerImpl> listener, - const blink::mojom::FileChooserParams& params) override; - void EnumerateDirectory( - RenderFrameHost* render_frame_host, - std::unique_ptr<FileChooserImpl::FileSelectListenerImpl> listener, - const base::FilePath& directory_path) override; void DidCancelLoading() override; void DidAccessInitialDocument() override; void DidChangeName(RenderFrameHost* render_frame_host, @@ -608,8 +595,9 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, bool internal, std::vector<content::AccessibilityTreeFormatter::PropertyFilter> property_filters) override; - void RecordAccessibilityEvents(AccessibilityEventCallback callback, - bool start) override; + void RecordAccessibilityEvents( + bool start_recording, + base::Optional<AccessibilityEventCallback> callback) override; RenderFrameHost* GetGuestByInstanceID( RenderFrameHost* render_frame_host, int browser_plugin_instance_id) override; @@ -621,7 +609,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, #endif bool CanEnterFullscreenMode() override; void EnterFullscreenMode( - const GURL& origin, + RenderFrameHost* requesting_frame, const blink::mojom::FullscreenOptions& options) override; void ExitFullscreenMode(bool will_cause_resize) override; void FullscreenStateChanged(RenderFrameHost* rfh, @@ -659,8 +647,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, void DidRunInsecureContent(const GURL& security_origin, const GURL& target_url) override; void PassiveInsecureContentFound(const GURL& resource_url) override; - bool ShouldAllowRunningInsecureContent(content::WebContents* web_contents, - bool allowed_per_prefs, + bool ShouldAllowRunningInsecureContent(bool allowed_per_prefs, const url::Origin& origin, const GURL& resource_url) override; void ViewSource(RenderFrameHostImpl* frame) override; @@ -690,6 +677,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, int context_id) override; void AudioContextPlaybackStopped(RenderFrameHost* host, int context_id) override; + void OnFrameAudioStateChanged(RenderFrameHost* host, + bool is_audible) override; media::MediaMetricsProvider::RecordAggregateWatchTimeCallback GetRecordAggregateWatchTimeCallback() override; RenderFrameHostImpl* GetMainFrameForInnerDelegate( @@ -720,7 +709,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, bool HasSeenRecentScreenOrientationChange() override; void CreateNewWidget(int32_t render_process_id, int32_t route_id, - mojo::PendingRemote<mojom::Widget> widget, mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host, mojo::PendingAssociatedRemote<blink::mojom::Widget> @@ -728,7 +716,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, void CreateNewFullscreenWidget( int32_t render_process_id, int32_t widget_route_id, - mojo::PendingRemote<mojom::Widget> widget, mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host, mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) @@ -750,6 +737,18 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, const std::string& mime_type, network::mojom::RequestDestination request_destination) override; void DomOperationResponse(const std::string& json_string) override; + void SavableResourceLinksResponse( + RenderFrameHostImpl* source, + const std::vector<GURL>& resources_list, + blink::mojom::ReferrerPtr referrer, + const std::vector<blink::mojom::SavableSubframePtr>& subframes) override; + void SavableResourceLinksError(RenderFrameHostImpl* source) override; + + // Called when the |RenderFrameHostImpl::lifecycle_state()| changes. + void RenderFrameHostStateChanged( + RenderFrameHost* render_frame_host, + RenderFrameHostImpl::LifecycleState old_state, + RenderFrameHostImpl::LifecycleState new_state) override; // RenderViewHostDelegate ---------------------------------------------------- RenderViewHostDelegateView* GetDelegateView() override; @@ -825,7 +824,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, RenderFrameHostImpl* render_frame_host, const LoadCommittedDetails& details, const FrameHostMsg_DidCommitProvisionalLoad_Params& params) override; - void SetMainFrameMimeType(const std::string& mime_type) override; bool CanOverscrollContent() const override; void NotifyChangedNavigationState(InvalidateTypes changed_flags) override; bool ShouldTransferNavigation(bool is_main_frame_navigation) override; @@ -927,22 +925,22 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, bool AddDomainInfoToRapporSample(rappor::Sample* sample) override; bool IsShowingContextMenuOnPage() const override; void DidChangeScreenOrientation() override; + // The following function is already listed under RenderViewHostDelegate + // overrides: + // FrameTree* GetFrameTree() override; // RenderFrameHostManager::Delegate ------------------------------------------ bool CreateRenderViewForRenderManager( RenderViewHost* render_view_host, - int opener_frame_routing_id, - int proxy_routing_id, - const base::UnguessableToken& frame_token, - const base::UnguessableToken& devtools_frame_token, - const FrameReplicationState& replicated_frame_state) override; + const base::Optional<base::UnguessableToken>& opener_frame_token, + int proxy_routing_id) override; void CreateRenderWidgetHostViewForRenderManager( RenderViewHost* render_view_host) override; bool CreateRenderFrameForRenderManager( RenderFrameHost* render_frame_host, int previous_routing_id, - int opener_routing_id, + const base::Optional<base::UnguessableToken>& opener_frame_token, int parent_routing_id, int previous_sibling_routing_id) override; void BeforeUnloadFiredFromRenderManager( @@ -1041,6 +1039,10 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, void MediaResized(const gfx::Size& size, const MediaPlayerId& id); void MediaEffectivelyFullscreenChanged(bool is_fullscreen); + // Called by MediaWebContentsObserver when a buffer underflow occurs. See the + // WebContentsObserver function stubs for more details. + void MediaBufferUnderflow(const MediaPlayerId& id); + int GetCurrentlyPlayingVideoCount() override; base::Optional<gfx::Size> GetFullscreenVideoSize() override; bool IsFullscreen() override; @@ -1083,17 +1085,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, void IncrementNativeFileSystemHandleCount(); void DecrementNativeFileSystemHandleCount(); - // Add and remove a reference for a native file system directory handle for a - // certain |path|. Multiple Add calls should be balanced by the same number of - // Remove calls for the same |path|. - void AddNativeFileSystemDirectoryHandle(const base::FilePath& path); - void RemoveNativeFileSystemDirectoryHandle(const base::FilePath& path); - - // Modify the counter of native file system handles with write access for this - // WebContents. - void IncrementWritableNativeFileSystemHandleCount(); - void DecrementWritableNativeFileSystemHandleCount(); - // Called when the WebContents gains or loses a persistent video. void SetHasPersistentVideo(bool has_persistent_video); @@ -1138,6 +1129,20 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, // Sets the spatial navigation state. void SetSpatialNavigationDisabled(bool disabled); + // Called when a file selection is to be done. + void RunFileChooser( + RenderFrameHost* render_frame_host, + std::unique_ptr<FileChooserImpl::FileSelectListenerImpl> listener, + const blink::mojom::FileChooserParams& params); + + // Request to enumerate a directory. This is equivalent to running the file + // chooser in directory-enumeration mode and having the user select the given + // directory. + void EnumerateDirectory( + RenderFrameHost* render_frame_host, + std::unique_ptr<FileChooserImpl::FileSelectListenerImpl> listener, + const base::FilePath& directory_path); + #if defined(OS_ANDROID) // Called by FindRequestManager when all of the find match rects are in. void NotifyFindMatchRectsReply(int version, @@ -1163,7 +1168,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, std::unique_ptr<WebContents> DetachFromOuterWebContents(); // Reattaches this inner WebContents to its outer WebContents. - void ReattachToOuterWebContentsFrame(); + virtual void ReattachToOuterWebContentsFrame(); // Getter/setter for the Portal associated with this WebContents. If non-null // then this WebContents is embedded in a portal and its outer WebContents can @@ -1171,15 +1176,17 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, void set_portal(Portal* portal) { portal_ = portal; } Portal* portal() const { return portal_; } - // Notifies observers that this WebContents was activated. This contents' - // former portal host, |predecessor_contents|, has become a portal pending - // adoption. - void DidActivatePortal(WebContents* predecessor_contents); - // Sends a page message to notify every process in the frame tree if the // web contents is a portal web contents. void NotifyInsidePortal(bool inside_portal); + // Notifies observers that this WebContents was activated. This contents' + // former portal host, |predecessor_web_contents|, has become a portal pending + // adoption. + // |activation_time| is the time the activation happened, in wall time. + void DidActivatePortal(WebContentsImpl* predecessor_web_contents, + base::TimeTicks activation_time); + // Notifies observers that AppCache was accessed. Public so AppCache code can // call this directly. void OnAppCacheAccessed(const GURL& manifest_url, bool blocked_by_policy); @@ -1193,7 +1200,17 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, } // Returns the focused frame's input handler. - mojom::FrameInputHandler* GetFocusedFrameInputHandler(); + blink::mojom::FrameWidgetInputHandler* GetFocusedFrameWidgetInputHandler(); + + // A render view-originated drag has ended. Informs the render view host and + // WebContentsDelegate. + void SystemDragEnded(RenderWidgetHost* source_rwh); + + // They are similar to functions GetAllFrames() and SendToAllFrames() in + // WebContents interface, but also include pendings frames. See bug: + // http://crbug.com/1087806 + std::vector<RenderFrameHost*> GetAllFramesIncludingPending(); + int SendToAllFramesIncludingPending(IPC::Message* message); private: friend class WebContentsObserver; @@ -1484,6 +1501,12 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, // guarantee that |inner_web_contents| has been added to the WebContents tree. void InnerWebContentsCreated(WebContents* inner_web_contents); + // Called just after an inner web contents is attached. + void InnerWebContentsAttached(WebContents* inner_web_contents); + + // Called just after an inner web contents is detached. + void InnerWebContentsDetached(WebContents* inner_web_contents); + // Navigation helpers -------------------------------------------------------- // // These functions are helpers for Navigate() and DidNavigate(). @@ -1498,7 +1521,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, int32_t render_process_id, int32_t route_id, bool is_fullscreen, - mojo::PendingRemote<mojom::Widget> widget, mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host, mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget); @@ -1536,10 +1558,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, // Notifies the delegate of a change in loading state. // |details| is used to provide details on the load that just finished // (but can be null if not applicable). - // |due_to_interstitial| is true if the change in load state occurred because - // an interstitial page started showing/proceeded. void LoadingStateChanged(bool to_different_document, - bool due_to_interstitial, LoadNotificationDetails* details); // Misc non-view stuff ------------------------------------------------------- @@ -1635,6 +1654,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, // if you don't. ukm::SourceId GetCurrentPageUkmSourceId() override; + std::set<RenderViewHostImpl*> GetRenderViewHostsIncludingBackForwardCached(); + // Data for core operation --------------------------------------------------- // Delegate for notifying our owner about stuff. Not owned by us. @@ -1729,10 +1750,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, // When a title cannot be taken from any entry, this title will be used. base::string16 page_title_when_no_navigation_entry_; - // When a navigation occurs, we record its contents MIME type. It can be - // used to check whether we can do something for some special contents. - std::string contents_mime_type_; - // Whether the initial empty page has been accessed by another page, making it // unsafe to show the pending URL. Usually false unless another window tries // to modify the blank page. Always false after the first commit. @@ -1915,8 +1932,6 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, size_t hid_active_frame_count_ = 0; size_t native_file_system_handle_count_ = 0; - std::map<base::FilePath, size_t> native_file_system_directory_handles_; - size_t native_file_system_writable_handle_count_ = 0; bool has_picture_in_picture_video_ = false; @@ -2020,7 +2035,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, bool using_dark_colors_ = false; ui::NativeTheme::PreferredColorScheme preferred_color_scheme_ = - ui::NativeTheme::PreferredColorScheme::kNoPreference; + ui::NativeTheme::PreferredColorScheme::kLight; // Prevents navigations in this contents while a javascript modal dialog is // showing. diff --git a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc index da87aa9b97e..e2b647f07de 100644 --- a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc @@ -1518,7 +1518,7 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager, std::string last_message() { return last_message_; } - WebContents* last_popup() { return popup_.get(); } + WebContents* last_popup() { return popups_.back().get(); } // WebContentsDelegate @@ -1528,8 +1528,7 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager, } void EnterFullscreenModeForTab( - WebContents* web_contents, - const GURL& origin, + RenderFrameHost* requesting_frame, const blink::mojom::FullscreenOptions& options) override { is_fullscreen_ = true; } @@ -1554,7 +1553,7 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager, const gfx::Rect& initial_rect, bool user_gesture, bool* was_blocked) override { - popup_ = std::move(new_contents); + popups_.push_back(std::move(new_contents)); if (waiting_for_ == kNewContents) { waiting_for_ = kNothing; @@ -1616,7 +1615,7 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager, bool is_fullscreen_ = false; - std::unique_ptr<WebContents> popup_; + std::vector<std::unique_ptr<WebContents>> popups_; std::unique_ptr<base::RunLoop> run_loop_ = std::make_unique<base::RunLoop>(); @@ -2385,7 +2384,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, EXPECT_TRUE(NavigateToURL(shell(), url)); // alert - wc->EnterFullscreenMode(url, blink::mojom::FullscreenOptions()); + wc->EnterFullscreenMode(wc->GetMainFrame(), {}); EXPECT_TRUE(wc->IsFullscreenForCurrentTab()); std::string script = "alert('hi')"; test_delegate.WillWaitForDialog(); @@ -2394,7 +2393,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, EXPECT_FALSE(wc->IsFullscreenForCurrentTab()); // confirm - wc->EnterFullscreenMode(url, blink::mojom::FullscreenOptions()); + wc->EnterFullscreenMode(wc->GetMainFrame(), {}); EXPECT_TRUE(wc->IsFullscreenForCurrentTab()); script = "confirm('hi')"; test_delegate.WillWaitForDialog(); @@ -2403,7 +2402,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, EXPECT_FALSE(wc->IsFullscreenForCurrentTab()); // prompt - wc->EnterFullscreenMode(url, blink::mojom::FullscreenOptions()); + wc->EnterFullscreenMode(wc->GetMainFrame(), {}); EXPECT_TRUE(wc->IsFullscreenForCurrentTab()); script = "prompt('hi')"; test_delegate.WillWaitForDialog(); @@ -2412,7 +2411,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, EXPECT_FALSE(wc->IsFullscreenForCurrentTab()); // beforeunload - wc->EnterFullscreenMode(url, blink::mojom::FullscreenOptions()); + wc->EnterFullscreenMode(wc->GetMainFrame(), {}); EXPECT_TRUE(wc->IsFullscreenForCurrentTab()); // Disable the hang monitor (otherwise there will be a race between the // beforeunload dialog and the beforeunload hang timer) and give the page a @@ -2456,7 +2455,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, // A dialog from the inner WebContents should make the outer contents lose // fullscreen. - top_contents->EnterFullscreenMode(url, blink::mojom::FullscreenOptions()); + top_contents->EnterFullscreenMode(top_contents->GetMainFrame(), {}); EXPECT_TRUE(top_contents->IsFullscreenForCurrentTab()); script = "alert('hi')"; inner_test_delegate.WillWaitForDialog(); @@ -2472,7 +2471,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, FileChooserEndsFullscreen) { GURL url("about:blank"); EXPECT_TRUE(NavigateToURL(shell(), url)); - wc->EnterFullscreenMode(url, blink::mojom::FullscreenOptions()); + wc->EnterFullscreenMode(wc->GetMainFrame(), {}); EXPECT_TRUE(wc->IsFullscreenForCurrentTab()); wc->RunFileChooser(wc->GetMainFrame(), std::make_unique<MockFileSelectListener>(), @@ -2489,7 +2488,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, EXPECT_TRUE(NavigateToURL(shell(), url)); // popup - wc->EnterFullscreenMode(url, blink::mojom::FullscreenOptions()); + wc->EnterFullscreenMode(wc->GetMainFrame(), {}); EXPECT_TRUE(wc->IsFullscreenForCurrentTab()); std::string script = "window.open('', '', 'width=200,height=100')"; test_delegate.WillWaitForNewContents(); @@ -2498,7 +2497,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, EXPECT_FALSE(wc->IsFullscreenForCurrentTab()); } -// Tests that if a popup is opened, all WebContentses down the opener chain are +// Tests that if a popup is opened, a WebContents *up* the opener chain is // kicked out of fullscreen. IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, PopupsOfPopupsFromJavaScriptEndFullscreen) { @@ -2517,7 +2516,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, static_cast<WebContentsImpl*>(test_delegate.last_popup()); // Put the original page into fullscreen. - wc->EnterFullscreenMode(url, blink::mojom::FullscreenOptions()); + wc->EnterFullscreenMode(wc->GetMainFrame(), {}); EXPECT_TRUE(wc->IsFullscreenForCurrentTab()); // Have the popup open a popup. @@ -2530,6 +2529,38 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, EXPECT_FALSE(wc->IsFullscreenForCurrentTab()); } +// Tests that if a popup is opened, a WebContents *down* the opener chain is +// kicked out of fullscreen. +IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, + PopupsFromJavaScriptEndFullscreenDownstream) { + WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents()); + TestWCDelegateForDialogsAndFullscreen test_delegate(wc); + + GURL url("about:blank"); + EXPECT_TRUE(NavigateToURL(shell(), url)); + + // Make a popup. + std::string popup_script = "window.open('', '', 'width=200,height=100')"; + test_delegate.WillWaitForNewContents(); + EXPECT_TRUE(content::ExecuteScript(wc, popup_script)); + test_delegate.Wait(); + WebContentsImpl* popup = + static_cast<WebContentsImpl*>(test_delegate.last_popup()); + + // Put the popup into fullscreen. + TestWCDelegateForDialogsAndFullscreen popup_test_delegate(popup); + popup->EnterFullscreenMode(popup->GetMainFrame(), {}); + EXPECT_TRUE(popup->IsFullscreenForCurrentTab()); + + // Have the original page open a new popup. + test_delegate.WillWaitForNewContents(); + EXPECT_TRUE(content::ExecuteScript(wc, popup_script)); + test_delegate.Wait(); + + // Ensure the popup, being downstream from the opener, loses fullscreen. + EXPECT_FALSE(popup->IsFullscreenForCurrentTab()); +} + IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, FocusFromJavaScriptEndsFullscreen) { WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents()); @@ -2547,7 +2578,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, test_delegate.Wait(); // Put the main contents into fullscreen ... - wc->EnterFullscreenMode(url, blink::mojom::FullscreenOptions()); + wc->EnterFullscreenMode(wc->GetMainFrame(), {}); EXPECT_TRUE(wc->IsFullscreenForCurrentTab()); // ... and ensure that a call to window.focus() from it causes loss of @@ -3930,6 +3961,19 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, EXPECT_EQ(shell()->web_contents()->GetThemeColor(), 0xFFFF0000u); } +IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, + MimeTypeResetWhenNavigatingAway) { + ASSERT_TRUE(embedded_test_server()->Start()); + const GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html")); + const GURL url_b(embedded_test_server()->GetURL("b.com", "/single_face.jpg")); + + EXPECT_TRUE(NavigateToURL(shell(), url_a)); + EXPECT_EQ(shell()->web_contents()->GetContentsMimeType(), "text/html"); + + EXPECT_TRUE(NavigateToURL(shell(), url_b)); + EXPECT_EQ(shell()->web_contents()->GetContentsMimeType(), "image/jpeg"); +} + namespace { // A WebContentsObserver which caches the total number of calls to diff --git a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc index 26cfcade0cc..f7d652c880f 100644 --- a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc +++ b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc @@ -9,8 +9,8 @@ #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/check.h" #include "base/command_line.h" -#include "base/logging.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" @@ -30,7 +30,6 @@ #include "content/browser/webui/web_ui_controller_factory_registry.h" #include "content/common/content_navigation_policy.h" #include "content/common/frame_messages.h" -#include "content/common/input/synthetic_web_input_event_builders.h" #include "content/common/page_messages.h" #include "content/common/view_messages.h" #include "content/public/browser/child_process_security_policy.h" @@ -68,6 +67,7 @@ #include "services/network/public/cpp/web_sandbox_flags.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" #include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h" #include "third_party/blink/public/mojom/frame/fullscreen.mojom.h" #include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h" @@ -210,10 +210,9 @@ class FakeFullscreenDelegate : public WebContentsDelegate { ~FakeFullscreenDelegate() override {} void EnterFullscreenModeForTab( - WebContents* web_contents, - const GURL& origin, + RenderFrameHost* requesting_frame, const blink::mojom::FullscreenOptions& options) override { - fullscreened_contents_ = web_contents; + fullscreened_contents_ = WebContents::FromRenderFrameHost(requesting_frame); } void ExitFullscreenModeForTab(WebContents* web_contents) override { @@ -286,6 +285,15 @@ TEST_F(WebContentsImplTest, UpdateTitleBeforeFirstNavigation) { EXPECT_EQ(title, contents()->GetTitle()); } +TEST_F(WebContentsImplTest, SetMainFrameMimeType) { + ASSERT_TRUE(controller().IsInitialNavigation()); + std::string mime = "text/html"; + RenderViewHostImpl* rvh = + static_cast<RenderViewHostImpl*>(main_test_rfh()->GetRenderViewHost()); + rvh->SetContentsMimeType(mime); + EXPECT_EQ(mime, contents()->GetContentsMimeType()); +} + TEST_F(WebContentsImplTest, DontUseTitleFromPendingEntry) { const GURL kGURL(GetWebUIURL("blah")); controller().LoadURL( @@ -837,12 +845,12 @@ TEST_F(WebContentsImplTest, FindOpenerRVHWhenPending) { // If swapped out is forbidden, a new proxy should be created for the opener // in |instance|, and we should ensure that its routing ID is returned here. // Otherwise, we should find the pending RFH and not create a new proxy. - int opener_frame_routing_id = - popup->GetRenderManager()->GetOpenerRoutingID(instance); + auto opener_frame_token = + popup->GetRenderManager()->GetOpenerFrameToken(instance); RenderFrameProxyHost* proxy = contents()->GetRenderManager()->GetRenderFrameProxyHost(instance); EXPECT_TRUE(proxy); - EXPECT_EQ(proxy->GetRoutingID(), opener_frame_routing_id); + EXPECT_EQ(proxy->GetFrameToken(), opener_frame_token); // Ensure that committing the navigation removes the proxy. navigation->Commit(); @@ -1746,8 +1754,9 @@ TEST_F(WebContentsImplTest, HandleWheelEvent) { int modifiers = 0; // Verify that normal mouse wheel events do nothing to change the zoom level. - blink::WebMouseWheelEvent event = SyntheticWebMouseWheelEventBuilder::Build( - 0, 0, 0, 1, modifiers, ui::ScrollGranularity::kScrollByPixel); + blink::WebMouseWheelEvent event = + blink::SyntheticWebMouseWheelEventBuilder::Build( + 0, 0, 0, 1, modifiers, ui::ScrollGranularity::kScrollByPixel); EXPECT_FALSE(contents()->HandleWheelEvent(event)); EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount()); @@ -1755,7 +1764,7 @@ TEST_F(WebContentsImplTest, HandleWheelEvent) { // decreased. Except on MacOS where we never want to adjust zoom // with mousewheel. modifiers = WebInputEvent::kControlKey; - event = SyntheticWebMouseWheelEventBuilder::Build( + event = blink::SyntheticWebMouseWheelEventBuilder::Build( 0, 0, 0, 1, modifiers, ui::ScrollGranularity::kScrollByPixel); bool handled = contents()->HandleWheelEvent(event); #if defined(USE_AURA) @@ -1769,7 +1778,7 @@ TEST_F(WebContentsImplTest, HandleWheelEvent) { modifiers = WebInputEvent::kControlKey | WebInputEvent::kShiftKey | WebInputEvent::kAltKey; - event = SyntheticWebMouseWheelEventBuilder::Build( + event = blink::SyntheticWebMouseWheelEventBuilder::Build( 0, 0, 2, -5, modifiers, ui::ScrollGranularity::kScrollByPixel); handled = contents()->HandleWheelEvent(event); #if defined(USE_AURA) @@ -1782,7 +1791,7 @@ TEST_F(WebContentsImplTest, HandleWheelEvent) { #endif // Unless there is no vertical movement. - event = SyntheticWebMouseWheelEventBuilder::Build( + event = blink::SyntheticWebMouseWheelEventBuilder::Build( 0, 0, 2, 0, modifiers, ui::ScrollGranularity::kScrollByPixel); EXPECT_FALSE(contents()->HandleWheelEvent(event)); EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount()); @@ -1791,7 +1800,7 @@ TEST_F(WebContentsImplTest, HandleWheelEvent) { // zoom being adjusted, to avoid accidental adjustments caused by // two-finger-scrolling on a touchpad. modifiers = WebInputEvent::kControlKey; - event = SyntheticWebMouseWheelEventBuilder::Build( + event = blink::SyntheticWebMouseWheelEventBuilder::Build( 0, 0, 0, 5, modifiers, ui::ScrollGranularity::kScrollByPrecisePixel); EXPECT_FALSE(contents()->HandleWheelEvent(event)); EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount()); @@ -2035,6 +2044,9 @@ TEST_F(WebContentsImplTestWithSiteIsolation, StartStopEventsBalance) { EXPECT_TRUE(observer.is_loading()); EXPECT_TRUE(observer.did_receive_response()); + // After navigation, the RenderFrameHost may change. + subframe = static_cast<TestRenderFrameHost*>( + contents()->GetFrameTree()->root()->child_at(0)->current_frame_host()); // Navigate the frame again, this time using LoadURLWithParams. This causes // RenderFrameHost to call into WebContents::DidStartLoading, which starts // the spinner. diff --git a/chromium/content/browser/web_contents/web_contents_view.h b/chromium/content/browser/web_contents/web_contents_view.h index 2277fc44cf2..d722cbe0806 100644 --- a/chromium/content/browser/web_contents/web_contents_view.h +++ b/chromium/content/browser/web_contents/web_contents_view.h @@ -41,7 +41,7 @@ class WebContentsView { // Computes the rectangle for the native widget that contains the contents of // the tab in the screen coordinate system. - virtual void GetContainerBounds(gfx::Rect* out) const = 0; + virtual gfx::Rect GetContainerBounds() const = 0; // Sets focus to the native widget for this tab. virtual void Focus() = 0; diff --git a/chromium/content/browser/web_contents/web_contents_view_android.cc b/chromium/content/browser/web_contents/web_contents_view_android.cc index eb490b5c03c..45ec0a1978d 100644 --- a/chromium/content/browser/web_contents/web_contents_view_android.cc +++ b/chromium/content/browser/web_contents/web_contents_view_android.cc @@ -9,6 +9,7 @@ #include "base/android/jni_string.h" #include "base/check.h" #include "base/notreached.h" +#include "base/optional.h" #include "cc/layers/layer.h" #include "content/browser/accessibility/browser_accessibility_manager_android.h" #include "content/browser/android/content_feature_list.h" @@ -148,8 +149,8 @@ gfx::NativeWindow WebContentsViewAndroid::GetTopLevelNativeWindow() const { return view_.GetWindowAndroid(); } -void WebContentsViewAndroid::GetContainerBounds(gfx::Rect* out) const { - *out = GetViewBounds(); +gfx::Rect WebContentsViewAndroid::GetContainerBounds() const { + return GetViewBounds(); } void WebContentsViewAndroid::SetPageTitle(const base::string16& title) { @@ -309,7 +310,7 @@ void WebContentsViewAndroid::StartDragging( const gfx::Vector2d& image_offset, const DragEventSourceInfo& event_info, RenderWidgetHostImpl* source_rwh) { - if (drop_data.text.is_null()) { + if (!drop_data.text) { // Need to clear drag and drop state in blink. OnSystemDragEnded(); return; @@ -337,7 +338,7 @@ void WebContentsViewAndroid::StartDragging( JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jstring> jtext = - ConvertUTF16ToJavaString(env, drop_data.text.string()); + ConvertUTF16ToJavaString(env, *drop_data.text); if (!native_view->StartDragAndDrop(jtext, gfx::ConvertToJavaBitmap(bitmap))) { // Need to clear drag and drop state in blink. @@ -382,9 +383,9 @@ bool WebContentsViewAndroid::OnDragEvent(const ui::DragEventAndroid& event) { if (base::EqualsASCII(mime_type, ui::kMimeTypeURIList)) { drop_data.url = GURL(drop_content); } else if (base::EqualsASCII(mime_type, ui::kMimeTypeText)) { - drop_data.text = base::NullableString16(drop_content, false); + drop_data.text = drop_content; } else { - drop_data.html = base::NullableString16(drop_content, false); + drop_data.html = drop_content; } } diff --git a/chromium/content/browser/web_contents/web_contents_view_android.h b/chromium/content/browser/web_contents/web_contents_view_android.h index 2a6dcf7ed06..54a203530d4 100644 --- a/chromium/content/browser/web_contents/web_contents_view_android.h +++ b/chromium/content/browser/web_contents/web_contents_view_android.h @@ -60,7 +60,7 @@ class WebContentsViewAndroid : public WebContentsView, gfx::NativeView GetNativeView() const override; gfx::NativeView GetContentNativeView() const override; gfx::NativeWindow GetTopLevelNativeWindow() const override; - void GetContainerBounds(gfx::Rect* out) const override; + gfx::Rect GetContainerBounds() const override; void Focus() override; void SetInitialFocus() override; void StoreFocus() override; diff --git a/chromium/content/browser/web_contents/web_contents_view_aura.cc b/chromium/content/browser/web_contents/web_contents_view_aura.cc index 950dc1931b4..b332c568cb3 100644 --- a/chromium/content/browser/web_contents/web_contents_view_aura.cc +++ b/chromium/content/browser/web_contents/web_contents_view_aura.cc @@ -71,6 +71,7 @@ #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/base/dragdrop/os_exchange_data_provider_factory.h" #include "ui/base/hit_test.h" +#include "ui/base/ui_base_features.h" #include "ui/compositor/layer.h" #include "ui/display/screen.h" #include "ui/events/blink/web_input_event.h" @@ -238,22 +239,26 @@ void PrepareDragData(const DropData& drop_data, PrepareDragForDownload(drop_data, provider, web_contents); #endif #if defined(USE_X11) || defined(OS_WIN) + bool should_check_file_contents = true; +#if defined(USE_X11) + should_check_file_contents = !features::IsUsingOzonePlatform(); +#endif // We set the file contents before the URL because the URL also sets file // contents (to a .URL shortcut). We want to prefer file content data over // a shortcut so we add it first. - if (!drop_data.file_contents.empty()) + if (should_check_file_contents && !drop_data.file_contents.empty()) PrepareDragForFileContents(drop_data, provider); #endif // Call SetString() before SetURL() when we actually have a custom string. // SetURL() will itself do SetString() when a string hasn't been set yet, // but we want to prefer drop_data.text.string() over the URL string if it // exists. - if (!drop_data.text.string().empty()) - provider->SetString(drop_data.text.string()); + if (drop_data.text && !drop_data.text->empty()) + provider->SetString(*drop_data.text); if (drop_data.url.is_valid()) provider->SetURL(drop_data.url, drop_data.url_title); - if (!drop_data.html.string().empty()) - provider->SetHtml(drop_data.html.string(), drop_data.html_base_url); + if (drop_data.html && !drop_data.html->empty()) + provider->SetHtml(*drop_data.html, drop_data.html_base_url); if (!drop_data.filenames.empty()) provider->SetFilenames(drop_data.filenames); if (!drop_data.file_system_files.empty()) { @@ -309,11 +314,12 @@ void PrepareDropData(DropData* drop_data, const ui::OSExchangeData& data) { base::string16 plain_text; data.GetString(&plain_text); if (!plain_text.empty()) - drop_data->text = base::NullableString16(plain_text, false); + drop_data->text = plain_text; GURL url; base::string16 url_title; - data.GetURLAndTitle(ui::DO_NOT_CONVERT_FILENAMES, &url, &url_title); + data.GetURLAndTitle(ui::FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES, &url, + &url_title); if (url.is_valid()) { drop_data->url = url; drop_data->url_title = url_title; @@ -323,7 +329,7 @@ void PrepareDropData(DropData* drop_data, const ui::OSExchangeData& data) { GURL html_base_url; data.GetHtml(&html, &html_base_url); if (!html.empty()) - drop_data->html = base::NullableString16(html, false); + drop_data->html = html; if (html_base_url.is_valid()) drop_data->html_base_url = html_base_url; @@ -521,8 +527,7 @@ void WebContentsViewAura::AsyncDropTempFileDeleter::DeleteFileAsync( FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT, base::TaskShutdownBehavior::BLOCK_SHUTDOWN}, - base::BindOnce(base::IgnoreResult(&base::DeleteFile), std::move(path), - false)); + base::BindOnce(base::GetDeleteFileCallback(), std::move(path))); } #endif @@ -806,8 +811,8 @@ gfx::NativeWindow WebContentsViewAura::GetTopLevelNativeWindow() const { return window ? window : delegate_->GetNativeWindow(); } -void WebContentsViewAura::GetContainerBounds(gfx::Rect* out) const { - *out = GetNativeView()->GetBoundsInScreen(); +gfx::Rect WebContentsViewAura::GetContainerBounds() const { + return GetNativeView()->GetBoundsInScreen(); } void WebContentsViewAura::Focus() { diff --git a/chromium/content/browser/web_contents/web_contents_view_aura.h b/chromium/content/browser/web_contents/web_contents_view_aura.h index 3a3d0b9073f..63c1a9b5731 100644 --- a/chromium/content/browser/web_contents/web_contents_view_aura.h +++ b/chromium/content/browser/web_contents/web_contents_view_aura.h @@ -137,7 +137,7 @@ class CONTENT_EXPORT WebContentsViewAura gfx::NativeView GetNativeView() const override; gfx::NativeView GetContentNativeView() const override; gfx::NativeWindow GetTopLevelNativeWindow() const override; - void GetContainerBounds(gfx::Rect* out) const override; + gfx::Rect GetContainerBounds() const override; void Focus() override; void SetInitialFocus() override; void StoreFocus() override; diff --git a/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc index 66f1ce72a47..cc5b494e8c0 100644 --- a/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc +++ b/chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc @@ -25,7 +25,6 @@ #include "content/browser/renderer_host/render_widget_host_view_aura.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/browser/web_contents/web_contents_view.h" -#include "content/common/input/synthetic_web_input_event_builders.h" #include "content/common/input_messages.h" #include "content/common/view_messages.h" #include "content/public/browser/browser_message_filter.h" @@ -46,6 +45,7 @@ #include "content/shell/browser/shell.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "third_party/blink/public/common/input/synthetic_web_input_event_builders.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/base/dragdrop/drop_target_event.h" @@ -881,7 +881,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, state == blink::mojom::InputEventResultState::kNotConsumed; })); // Send touch press. - SyntheticWebTouchEvent touch; + blink::SyntheticWebTouchEvent touch; touch.PressPoint(bounds.x() + 2, bounds.y() + 10); GetRenderWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo()); @@ -903,7 +903,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, touch_move_waiter.Wait(); blink::WebGestureEvent scroll_begin = - SyntheticWebGestureEventBuilder::BuildScrollBegin( + blink::SyntheticWebGestureEventBuilder::BuildScrollBegin( 1, 1, blink::WebGestureDevice::kTouchscreen); GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo( scroll_begin, ui::LatencyInfo()); @@ -919,7 +919,7 @@ IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, WaitAFrame(); blink::WebGestureEvent scroll_update = - SyntheticWebGestureEventBuilder::BuildScrollUpdate( + blink::SyntheticWebGestureEventBuilder::BuildScrollUpdate( dx, 5, 0, blink::WebGestureDevice::kTouchscreen); GetRenderWidgetHost()->ForwardGestureEventWithLatencyInfo( diff --git a/chromium/content/browser/web_contents/web_contents_view_aura_unittest.cc b/chromium/content/browser/web_contents/web_contents_view_aura_unittest.cc index ca77acc3ef5..35b56425c45 100644 --- a/chromium/content/browser/web_contents/web_contents_view_aura_unittest.cc +++ b/chromium/content/browser/web_contents/web_contents_view_aura_unittest.cc @@ -10,6 +10,7 @@ #include "base/command_line.h" #include "base/files/file_util.h" #include "base/macros.h" +#include "base/optional.h" #include "base/run_loop.h" #include "base/test/scoped_command_line.h" #include "base/test/scoped_feature_list.h" @@ -34,6 +35,10 @@ #include "ui/base/dragdrop/os_exchange_data_provider_win.h" #endif +#if defined(USE_X11) +#include "ui/base/ui_base_features.h" +#endif + namespace content { namespace { @@ -184,10 +189,13 @@ TEST_F(WebContentsViewAuraTest, WebContentsDestroyedDuringClick) { #if defined(USE_X11) // The web-content is not activated during mouse-press on X11. // See comment in WebContentsViewAura::OnMouseEvent() for more details. - EXPECT_NE(web_contents(), nullptr); -#else - EXPECT_EQ(web_contents(), nullptr); + if (!features::IsUsingOzonePlatform()) { + EXPECT_NE(web_contents(), nullptr); + } else #endif + { + EXPECT_EQ(web_contents(), nullptr); + } } TEST_F(WebContentsViewAuraTest, OccludeView) { @@ -253,10 +261,14 @@ TEST_F(WebContentsViewAuraTest, DragDropFiles) { #if defined(USE_X11) // By design, OSExchangeDataProviderX11::GetString returns an empty string // if file data is also present. - EXPECT_TRUE(view->current_drop_data_->text.string().empty()); -#else - EXPECT_EQ(string_data, view->current_drop_data_->text.string()); + if (!features::IsUsingOzonePlatform()) { + EXPECT_TRUE(!view->current_drop_data_->text || + view->current_drop_data_->text->empty()); + } else #endif + { + EXPECT_EQ(string_data, view->current_drop_data_->text); + } std::vector<ui::FileInfo> retrieved_file_infos = view->current_drop_data_->filenames; @@ -283,10 +295,14 @@ TEST_F(WebContentsViewAuraTest, DragDropFiles) { #if defined(USE_X11) // By design, OSExchangeDataProviderX11::GetString returns an empty string // if file data is also present. - EXPECT_TRUE(drop_complete_data_->drop_data.text.string().empty()); -#else - EXPECT_EQ(string_data, drop_complete_data_->drop_data.text.string()); + if (!features::IsUsingOzonePlatform()) { + EXPECT_TRUE(!drop_complete_data_->drop_data.text || + drop_complete_data_->drop_data.text->empty()); + } else #endif + { + EXPECT_EQ(string_data, drop_complete_data_->drop_data.text); + } retrieved_file_infos = drop_complete_data_->drop_data.filenames; ASSERT_EQ(test_file_infos.size(), retrieved_file_infos.size()); @@ -342,9 +358,10 @@ TEST_F(WebContentsViewAuraTest, DragDropFilesOriginateFromRenderer) { #if defined(USE_X11) // By design, OSExchangeDataProviderX11::GetString returns an empty string // if file data is also present. - EXPECT_TRUE(view->current_drop_data_->text.string().empty()); + EXPECT_TRUE(!view->current_drop_data_->text || + view->current_drop_data_->text->empty()); #else - EXPECT_EQ(string_data, view->current_drop_data_->text.string()); + EXPECT_EQ(string_data, view->current_drop_data_->text); #endif ASSERT_TRUE(view->current_drop_data_->filenames.empty()); @@ -365,9 +382,10 @@ TEST_F(WebContentsViewAuraTest, DragDropFilesOriginateFromRenderer) { #if defined(USE_X11) // By design, OSExchangeDataProviderX11::GetString returns an empty string // if file data is also present. - EXPECT_TRUE(drop_complete_data_->drop_data.text.string().empty()); + EXPECT_TRUE(!drop_complete_data_->drop_data.text || + drop_complete_data_->drop_data.text->empty()); #else - EXPECT_EQ(string_data, drop_complete_data_->drop_data.text.string()); + EXPECT_EQ(string_data, drop_complete_data_->drop_data.text); #endif ASSERT_TRUE(drop_complete_data_->drop_data.filenames.empty()); @@ -404,7 +422,7 @@ TEST_F(WebContentsViewAuraTest, DragDropVirtualFiles) { view->OnDragEntered(event); ASSERT_NE(nullptr, view->current_drop_data_); - EXPECT_EQ(string_data, view->current_drop_data_->text.string()); + EXPECT_EQ(string_data, view->current_drop_data_->text); const base::FilePath path_placeholder(FILE_PATH_LITERAL("temp.tmp")); std::vector<ui::FileInfo> retrieved_file_infos = @@ -430,7 +448,7 @@ TEST_F(WebContentsViewAuraTest, DragDropVirtualFiles) { CheckDropData(view); - EXPECT_EQ(string_data, drop_complete_data_->drop_data.text.string()); + EXPECT_EQ(string_data, drop_complete_data_->drop_data.text); std::string read_contents; base::FilePath temp_dir; @@ -487,7 +505,7 @@ TEST_F(WebContentsViewAuraTest, DragDropVirtualFilesOriginateFromRenderer) { view->OnDragEntered(event); ASSERT_NE(nullptr, view->current_drop_data_); - EXPECT_EQ(string_data, view->current_drop_data_->text.string()); + EXPECT_EQ(string_data, view->current_drop_data_->text); ASSERT_TRUE(view->current_drop_data_->filenames.empty()); @@ -505,7 +523,7 @@ TEST_F(WebContentsViewAuraTest, DragDropVirtualFilesOriginateFromRenderer) { CheckDropData(view); - EXPECT_EQ(string_data, drop_complete_data_->drop_data.text.string()); + EXPECT_EQ(string_data, drop_complete_data_->drop_data.text); ASSERT_TRUE(drop_complete_data_->drop_data.filenames.empty()); } diff --git a/chromium/content/browser/web_contents/web_contents_view_child_frame.cc b/chromium/content/browser/web_contents/web_contents_view_child_frame.cc index cbbc29fa522..54c12459601 100644 --- a/chromium/content/browser/web_contents/web_contents_view_child_frame.cc +++ b/chromium/content/browser/web_contents/web_contents_view_child_frame.cc @@ -57,12 +57,11 @@ gfx::NativeWindow WebContentsViewChildFrame::GetTopLevelNativeWindow() const { return GetOuterView()->GetTopLevelNativeWindow(); } -void WebContentsViewChildFrame::GetContainerBounds(gfx::Rect* out) const { - RenderWidgetHostView* view = web_contents_->GetRenderWidgetHostView(); - if (view) - *out = view->GetViewBounds(); - else - *out = gfx::Rect(); +gfx::Rect WebContentsViewChildFrame::GetContainerBounds() const { + if (RenderWidgetHostView* view = web_contents_->GetRenderWidgetHostView()) + return view->GetViewBounds(); + + return gfx::Rect(); } void WebContentsViewChildFrame::SetInitialFocus() { diff --git a/chromium/content/browser/web_contents/web_contents_view_child_frame.h b/chromium/content/browser/web_contents/web_contents_view_child_frame.h index c387257e579..628005114f7 100644 --- a/chromium/content/browser/web_contents/web_contents_view_child_frame.h +++ b/chromium/content/browser/web_contents/web_contents_view_child_frame.h @@ -27,7 +27,7 @@ class WebContentsViewChildFrame : public WebContentsView, gfx::NativeView GetNativeView() const override; gfx::NativeView GetContentNativeView() const override; gfx::NativeWindow GetTopLevelNativeWindow() const override; - void GetContainerBounds(gfx::Rect* out) const override; + gfx::Rect GetContainerBounds() const override; void Focus() override; void SetInitialFocus() override; void StoreFocus() override; diff --git a/chromium/content/browser/web_contents/web_contents_view_mac.h b/chromium/content/browser/web_contents/web_contents_view_mac.h index a1f76e3f293..3cc4cda5ea6 100644 --- a/chromium/content/browser/web_contents/web_contents_view_mac.h +++ b/chromium/content/browser/web_contents/web_contents_view_mac.h @@ -66,7 +66,7 @@ class WebContentsViewMac : public WebContentsView, gfx::NativeView GetNativeView() const override; gfx::NativeView GetContentNativeView() const override; gfx::NativeWindow GetTopLevelNativeWindow() const override; - void GetContainerBounds(gfx::Rect* out) const override; + gfx::Rect GetContainerBounds() const override; void Focus() override; void SetInitialFocus() override; void StoreFocus() override; diff --git a/chromium/content/browser/web_contents/web_contents_view_mac.mm b/chromium/content/browser/web_contents/web_contents_view_mac.mm index 8d4a118ee82..88aa049ff6e 100644 --- a/chromium/content/browser/web_contents/web_contents_view_mac.mm +++ b/chromium/content/browser/web_contents/web_contents_view_mac.mm @@ -122,7 +122,7 @@ gfx::NativeWindow WebContentsViewMac::GetTopLevelNativeWindow() const { return window ? window : delegate_->GetNativeWindow(); } -void WebContentsViewMac::GetContainerBounds(gfx::Rect* out) const { +gfx::Rect WebContentsViewMac::GetContainerBounds() const { NSWindow* window = [GetInProcessNSView() window]; NSRect bounds = [GetInProcessNSView() bounds]; if (window) { @@ -133,7 +133,7 @@ void WebContentsViewMac::GetContainerBounds(gfx::Rect* out) const { bounds = [window convertRectToScreen:bounds]; } - *out = gfx::ScreenRectFromNSRect(bounds); + return gfx::ScreenRectFromNSRect(bounds); } void WebContentsViewMac::StartDragging( diff --git a/chromium/content/browser/web_contents/web_drag_dest_mac.mm b/chromium/content/browser/web_contents/web_drag_dest_mac.mm index b874b3c4b16..a964f38b830 100644 --- a/chromium/content/browser/web_contents/web_drag_dest_mac.mm +++ b/chromium/content/browser/web_contents/web_drag_dest_mac.mm @@ -6,6 +6,7 @@ #import <Carbon/Carbon.h> +#include "base/optional.h" #include "base/strings/sys_string_conversions.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/renderer_host/render_widget_host_impl.h" @@ -161,15 +162,6 @@ void DropCompletionCallback( return screenPoint; } -// Return YES if the drop site only allows drops that would navigate. If this -// is the case, we don't want to pass messages to the renderer because there's -// really no point (i.e., there's nothing that cares about the mouse position or -// entering and exiting). One example is an interstitial page (e.g., safe -// browsing warning). -- (BOOL)onlyAllowsNavigation { - return _webContents->ShowingInterstitialPage(); -} - // Messages to send during the tracking of a drag, usually upon receiving // calls from the view system. Communicates the drag messages to WebCore. @@ -218,12 +210,6 @@ void DropCompletionCallback( if (_canceled) return NSDragOperationNone; - if ([self onlyAllowsNavigation]) { - if (info->url) - return NSDragOperationCopy; - return NSDragOperationNone; - } - if (_delegate) { _delegate->DragInitialize(_webContents); _delegate->OnDragEnter(); @@ -255,9 +241,6 @@ void DropCompletionCallback( if (_canceled) return; - if ([self onlyAllowsNavigation]) - return; - if (_delegate) _delegate->OnDragLeave(); @@ -315,12 +298,6 @@ void DropCompletionCallback( if (_canceled) return NSDragOperationNone; - if ([self onlyAllowsNavigation]) { - if (info->url) - return NSDragOperationCopy; - return NSDragOperationNone; - } - NSDragOperation mask = info->operation_mask; targetRWH->DragTargetDragOver(transformedPt, info->location_in_screen, static_cast<WebDragOperationsMask>(mask), @@ -353,18 +330,6 @@ void DropCompletionCallback( [self draggingEntered:info]; } - // Check if we only allow navigation and navigate to a url on the pasteboard. - if ([self onlyAllowsNavigation]) { - if (info->url) { - _webContents->OpenURL(OpenURLParams( - *info->url, Referrer(), WindowOpenDisposition::CURRENT_TAB, - ui::PAGE_TRANSITION_AUTO_BOOKMARK, false)); - return YES; - } else { - return NO; - } - } - _currentRVH = NULL; _webContents->Focus(); @@ -446,21 +411,20 @@ void PopulateDropDataFromPasteboard(content::DropData* data, // Get plain text. if ([types containsObject:NSStringPboardType]) { - data->text = base::NullableString16( - base::SysNSStringToUTF16([pboard stringForType:NSStringPboardType]), - false); + data->text = + base::SysNSStringToUTF16([pboard stringForType:NSStringPboardType]); } // Get HTML. If there's no HTML, try RTF. if ([types containsObject:NSHTMLPboardType]) { NSString* html = [pboard stringForType:NSHTMLPboardType]; - data->html = base::NullableString16(base::SysNSStringToUTF16(html), false); + data->html = base::SysNSStringToUTF16(html); } else if ([types containsObject:ui::kChromeDragImageHTMLPboardType]) { NSString* html = [pboard stringForType:ui::kChromeDragImageHTMLPboardType]; - data->html = base::NullableString16(base::SysNSStringToUTF16(html), false); + data->html = base::SysNSStringToUTF16(html); } else if ([types containsObject:NSRTFPboardType]) { NSString* html = ui::ClipboardUtil::GetHTMLFromRTFOnPasteboard(pboard); - data->html = base::NullableString16(base::SysNSStringToUTF16(html), false); + data->html = base::SysNSStringToUTF16(html); } // Get files. diff --git a/chromium/content/browser/web_contents/web_drag_dest_mac_unittest.mm b/chromium/content/browser/web_contents/web_drag_dest_mac_unittest.mm index b837cbdb2fa..70342717707 100644 --- a/chromium/content/browser/web_contents/web_drag_dest_mac_unittest.mm +++ b/chromium/content/browser/web_contents/web_drag_dest_mac_unittest.mm @@ -141,6 +141,6 @@ TEST_F(WebDragDestTest, Data) { [pboard->get() setString:textString forType:NSStringPboardType]; content::PopulateDropDataFromPasteboard(&data, pboard->get()); EXPECT_EQ(data.url.spec(), "http://www.google.com/"); - EXPECT_EQ(base::SysNSStringToUTF16(textString), data.text.string()); - EXPECT_EQ(base::SysNSStringToUTF16(htmlString), data.html.string()); + EXPECT_EQ(base::SysNSStringToUTF16(textString), data.text); + EXPECT_EQ(base::SysNSStringToUTF16(htmlString), data.html); } diff --git a/chromium/content/browser/web_contents/web_drag_utils_win.cc b/chromium/content/browser/web_contents/web_drag_utils_win.cc deleted file mode 100644 index 06e3a3c0ef6..00000000000 --- a/chromium/content/browser/web_contents/web_drag_utils_win.cc +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/web_contents/web_drag_utils_win.h" - -#include <oleidl.h> -#include "base/check.h" - -using blink::WebDragOperation; -using blink::WebDragOperationsMask; -using blink::kWebDragOperationNone; -using blink::kWebDragOperationCopy; -using blink::kWebDragOperationLink; -using blink::kWebDragOperationMove; -using blink::kWebDragOperationGeneric; - -namespace content { - -WebDragOperation WinDragOpToWebDragOp(DWORD effect) { - DCHECK(effect == DROPEFFECT_NONE || effect == DROPEFFECT_COPY || - effect == DROPEFFECT_LINK || effect == DROPEFFECT_MOVE); - - return WinDragOpMaskToWebDragOpMask(effect); -} - -WebDragOperationsMask WinDragOpMaskToWebDragOpMask(DWORD effects) { - WebDragOperationsMask ops = kWebDragOperationNone; - if (effects & DROPEFFECT_COPY) - ops = static_cast<WebDragOperationsMask>(ops | kWebDragOperationCopy); - if (effects & DROPEFFECT_LINK) - ops = static_cast<WebDragOperationsMask>(ops | kWebDragOperationLink); - if (effects & DROPEFFECT_MOVE) - ops = static_cast<WebDragOperationsMask>(ops | kWebDragOperationMove | - kWebDragOperationGeneric); - return ops; -} - -DWORD WebDragOpToWinDragOp(WebDragOperation op) { - DCHECK(op == kWebDragOperationNone || op == kWebDragOperationCopy || - op == kWebDragOperationLink || op == kWebDragOperationMove || - op == (kWebDragOperationMove | kWebDragOperationGeneric)); - - return WebDragOpMaskToWinDragOpMask(op); -} - -DWORD WebDragOpMaskToWinDragOpMask(WebDragOperationsMask ops) { - DWORD win_ops = DROPEFFECT_NONE; - if (ops & kWebDragOperationCopy) - win_ops |= DROPEFFECT_COPY; - if (ops & kWebDragOperationLink) - win_ops |= DROPEFFECT_LINK; - if (ops & (kWebDragOperationMove | kWebDragOperationGeneric)) - win_ops |= DROPEFFECT_MOVE; - return win_ops; -} - -} // namespace content diff --git a/chromium/content/browser/web_contents/web_drag_utils_win.h b/chromium/content/browser/web_contents/web_drag_utils_win.h deleted file mode 100644 index d1330205140..00000000000 --- a/chromium/content/browser/web_contents/web_drag_utils_win.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_WEB_CONTENTS_WEB_DRAG_UTILS_WIN_H_ -#define CONTENT_BROWSER_WEB_CONTENTS_WEB_DRAG_UTILS_WIN_H_ - -#include "third_party/blink/public/platform/web_drag_operation.h" - -#include <windows.h> - -namespace content { - -blink::WebDragOperation WinDragOpToWebDragOp(DWORD effect); -blink::WebDragOperationsMask WinDragOpMaskToWebDragOpMask(DWORD effects); - -DWORD WebDragOpToWinDragOp(blink::WebDragOperation op); -DWORD WebDragOpMaskToWinDragOpMask(blink::WebDragOperationsMask ops); - -} // namespace content - -#endif // CONTENT_BROWSER_WEB_CONTENTS_WEB_DRAG_UTILS_WIN_H_ |