0
Files
src/content/browser/browser_plugin/browser_plugin_guest.cc
Daniel Cheng 37d22722f7 [MSan] Avoid use-after-dtor errors when tracing in ~RenderFrameHostImpl
RenderFrameHostImpl::WriteIntoTrace() is called in ~RenderFrameHostImpl
and can reach up into its owning WebContents to get the outer document
(if any). This needs to reference `browser_plugin_guest_`, so order this
field before `frame_tree_` to ensure it is still live and valid when
tracing uses it. For consistency, move `browser_plugin_embedder_` as
well.

==696896==WARNING: MemorySanitizer: use-of-uninitialized-value
     0x55d39fa495c5 in GetProspectiveOuterDocument content/browser/web_contents/web_contents_impl.cc:10751:7
     0x55d39fa495c5 in non-virtual thunk to content::WebContentsImpl::GetProspectiveOuterDocument() content/browser/web_contents/web_contents_impl.cc
     0x55d39f0de815 in content::FrameTreeNode::GetParentOrOuterDocumentHelper(bool, bool) const content/browser/renderer_host/frame_tree_node.cc:367:34
     0x55d39f387f7b in content::RenderFrameHostImpl::WriteIntoTrace(perfetto::TracedProto<perfetto::protos::pbzero::RenderFrameHost>) const content/browser/renderer_host/render_frame_host_impl.cc:6441:31
     0x55d39f3ef779 in WriteIntoTracedProtoImpl<perfetto::protos::pbzero::RenderFrameHost, content::RenderFrameHostImpl &> third_party/perfetto/include/perfetto/tracing/traced_proto.h:316:9
    ...
     0x55d39f3521cd in operator() content/browser/renderer_host/render_frame_host_impl.cc:1848:3
     0x55d39f3521cd in content::RenderFrameHostImpl::~RenderFrameHostImpl() content/browser/renderer_host/render_frame_host_impl.cc:1848:3
     0x55d3a80abda7 in content::TestRenderFrameHost::~TestRenderFrameHost() content/test/test_render_frame_host.cc:106:43
     0x55d3a80abf05 in content::TestRenderFrameHost::~TestRenderFrameHost() content/test/test_render_frame_host.cc:106:43
     0x55d39f445d82 in operator() third_party/libc++/src/include/__memory/unique_ptr.h:67:5
     0x55d39f445d82 in reset third_party/libc++/src/include/__memory/unique_ptr.h:278:7
     0x55d39f445d82 in ~unique_ptr third_party/libc++/src/include/__memory/unique_ptr.h:248:71
     0x55d39f445d82 in content::RenderFrameHostManager::~RenderFrameHostManager() content/browser/renderer_host/render_frame_host_manager.cc:569:3
     0x55d39f0dc875 in content::FrameTreeNode::~FrameTreeNode() content/browser/renderer_host/frame_tree_node.cc:309:1
     0x55d39f0c790f in content::FrameTree::~FrameTree() content/browser/renderer_host/frame_tree.cc:229:1
     0x55d39f9dca05 in content::WebContentsImpl::~WebContentsImpl() content/browser/web_contents/web_contents_impl.cc:1393:1
     0x55d3a80ccace in content::TestWebContents::~TestWebContents() content/test/test_web_contents.cc:85:35
     0x55d3a80ccbe7 in content::TestWebContents::~TestWebContents() content/test/test_web_contents.cc:85:35
    ...

  Member fields were destroyed
     0x55d3825b29bd in __sanitizer_dtor_callback_fields /b/s/w/ir/cache/builder/src/third_party/llvm/compiler-rt/lib/msan/msan_interceptors.cpp:1048:5
     0x55d39f9dc82e in ~unique_ptr third_party/libc++/src/include/__memory/unique_ptr.h:145:44
     0x55d39f9dc82e in ~unique_ptr third_party/libc++/src/include/__memory/unique_ptr.h:248:80
     0x55d39f9dc82e in content::WebContentsImpl::~WebContentsImpl() content/browser/web_contents/web_contents_impl.cc:1393:1
     0x55d3a80ccace in content::TestWebContents::~TestWebContents() content/test/test_web_contents.cc:85:35
     0x55d3a80ccbe7 in content::TestWebContents::~TestWebContents() content/test/test_web_contents.cc:85:35
    ...

This reordering requires an additional null check in BrowserPluginGuest,
since WriteintoTrace() now calls into BrowserPluginGuest rather than
simply using a destroyed (but most likely, null) `browser_plugin_guest_`
field.

Bug: 40222690
Change-Id: If63c6766a8b6339b938bfc8e9d458ae3ec4bd00a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5664131
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1321272}
2024-06-29 00:43:44 +00:00

150 lines
5.6 KiB
C++

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/browser_plugin/browser_plugin_guest.h"
#include <stddef.h>
#include <utility>
#include "base/memory/ptr_util.h"
#include "base/metrics/user_metrics.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents_observer.h"
#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
namespace content {
BrowserPluginGuest::BrowserPluginGuest(WebContentsImpl* web_contents,
BrowserPluginGuestDelegate* delegate)
: WebContentsObserver(web_contents),
delegate_(delegate->GetGuestDelegateWeakPtr()) {
CHECK(web_contents);
CHECK(delegate_);
RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Create"));
}
void BrowserPluginGuest::Init() {
WebContentsImpl* owner_web_contents = static_cast<WebContentsImpl*>(
delegate_->GetOwnerWebContents());
owner_web_contents->CreateBrowserPluginEmbedderIfNecessary();
InitInternal(owner_web_contents);
}
std::unique_ptr<WebContentsImpl> BrowserPluginGuest::CreateNewGuestWindow(
const WebContents::CreateParams& params) {
std::unique_ptr<WebContents> new_contents =
delegate_->CreateNewGuestWindow(params);
DCHECK(new_contents);
return base::WrapUnique(
static_cast<WebContentsImpl*>(new_contents.release()));
}
void BrowserPluginGuest::InitInternal(WebContentsImpl* owner_web_contents) {
RenderWidgetHostImpl* rwhi =
GetWebContents()->GetPrimaryMainFrame()->GetRenderWidgetHost();
DCHECK(rwhi);
// The initial state will not be focused but the plugin may be active so
// set that appropriately.
rwhi->GetWidgetInputHandler()->SetFocus(
rwhi->is_active() ? blink::mojom::FocusState::kNotFocusedAndActive
: blink::mojom::FocusState::kNotFocusedAndNotActive);
blink::RendererPreferences* renderer_prefs =
GetWebContents()->GetMutableRendererPrefs();
blink::UserAgentOverride guest_user_agent_override =
renderer_prefs->user_agent_override;
// Copy renderer preferences (and nothing else) from the embedder's
// WebContents to the guest.
//
// For GTK and Aura this is necessary to get proper renderer configuration
// values for caret blinking interval, colors related to selection and
// focus.
*renderer_prefs = *owner_web_contents->GetMutableRendererPrefs();
renderer_prefs->user_agent_override = std::move(guest_user_agent_override);
// Navigation is disabled in Chrome Apps. We want to make sure guest-initiated
// navigations still continue to function inside the app.
renderer_prefs->browser_handles_all_top_level_requests = false;
// Also disable drag/drop navigations.
renderer_prefs->can_accept_load_drops = false;
}
BrowserPluginGuest::~BrowserPluginGuest() = default;
// static
void BrowserPluginGuest::CreateInWebContents(
WebContentsImpl* web_contents,
BrowserPluginGuestDelegate* delegate) {
auto guest = base::WrapUnique(new BrowserPluginGuest(web_contents, delegate));
web_contents->SetBrowserPluginGuest(std::move(guest));
}
WebContentsImpl* BrowserPluginGuest::GetWebContents() const {
return static_cast<WebContentsImpl*>(web_contents());
}
RenderFrameHostImpl* BrowserPluginGuest::GetProspectiveOuterDocument() {
if (!delegate_) {
// The guest delegate may only be null during some destruction scenarios.
CHECK(!web_contents() || web_contents()->IsBeingDestroyed());
return nullptr;
}
return static_cast<RenderFrameHostImpl*>(
delegate_->GetProspectiveOuterDocument());
}
void BrowserPluginGuest::DidStartNavigation(
NavigationHandle* navigation_handle) {
// Originally added to suppress the error page when a navigation is blocked
// using the webrequest API in a <webview> guest: https://crbug.com/284741.
//
// TODO(crbug.com/40148437): net::ERR_BLOCKED_BY_CLIENT is used for
// many other errors. Figure out what suppression policy is desirable here.
//
// TODO(mcnee): Investigate moving this out to WebViewGuest.
NavigationRequest::From(navigation_handle)
->SetSilentlyIgnoreBlockedByClient();
}
void BrowserPluginGuest::DidFinishNavigation(
NavigationHandle* navigation_handle) {
if (navigation_handle->HasCommitted())
RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.DidNavigate"));
}
void BrowserPluginGuest::PrimaryMainFrameRenderProcessGone(
base::TerminationStatus status) {
switch (status) {
#if BUILDFLAG(IS_CHROMEOS)
case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
#endif
case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Killed"));
break;
case base::TERMINATION_STATUS_PROCESS_CRASHED:
RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Crashed"));
break;
case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
RecordAction(
base::UserMetricsAction("BrowserPlugin.Guest.AbnormalDeath"));
break;
case base::TERMINATION_STATUS_LAUNCH_FAILED:
RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.LaunchFailed"));
break;
default:
break;
}
}
} // namespace content