
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 #0 0x55d39fa495c5 in GetProspectiveOuterDocument content/browser/web_contents/web_contents_impl.cc:10751:7 #1 0x55d39fa495c5 in non-virtual thunk to content::WebContentsImpl::GetProspectiveOuterDocument() content/browser/web_contents/web_contents_impl.cc #2 0x55d39f0de815 in content::FrameTreeNode::GetParentOrOuterDocumentHelper(bool, bool) const content/browser/renderer_host/frame_tree_node.cc:367:34 #3 0x55d39f387f7b in content::RenderFrameHostImpl::WriteIntoTrace(perfetto::TracedProto<perfetto::protos::pbzero::RenderFrameHost>) const content/browser/renderer_host/render_frame_host_impl.cc:6441:31 #4 0x55d39f3ef779 in WriteIntoTracedProtoImpl<perfetto::protos::pbzero::RenderFrameHost, content::RenderFrameHostImpl &> third_party/perfetto/include/perfetto/tracing/traced_proto.h:316:9 ... #23 0x55d39f3521cd in operator() content/browser/renderer_host/render_frame_host_impl.cc:1848:3 #24 0x55d39f3521cd in content::RenderFrameHostImpl::~RenderFrameHostImpl() content/browser/renderer_host/render_frame_host_impl.cc:1848:3 #25 0x55d3a80abda7 in content::TestRenderFrameHost::~TestRenderFrameHost() content/test/test_render_frame_host.cc:106:43 #26 0x55d3a80abf05 in content::TestRenderFrameHost::~TestRenderFrameHost() content/test/test_render_frame_host.cc:106:43 #27 0x55d39f445d82 in operator() third_party/libc++/src/include/__memory/unique_ptr.h:67:5 #28 0x55d39f445d82 in reset third_party/libc++/src/include/__memory/unique_ptr.h:278:7 #29 0x55d39f445d82 in ~unique_ptr third_party/libc++/src/include/__memory/unique_ptr.h:248:71 #30 0x55d39f445d82 in content::RenderFrameHostManager::~RenderFrameHostManager() content/browser/renderer_host/render_frame_host_manager.cc:569:3 #31 0x55d39f0dc875 in content::FrameTreeNode::~FrameTreeNode() content/browser/renderer_host/frame_tree_node.cc:309:1 #32 0x55d39f0c790f in content::FrameTree::~FrameTree() content/browser/renderer_host/frame_tree.cc:229:1 #33 0x55d39f9dca05 in content::WebContentsImpl::~WebContentsImpl() content/browser/web_contents/web_contents_impl.cc:1393:1 #34 0x55d3a80ccace in content::TestWebContents::~TestWebContents() content/test/test_web_contents.cc:85:35 #35 0x55d3a80ccbe7 in content::TestWebContents::~TestWebContents() content/test/test_web_contents.cc:85:35 ... Member fields were destroyed #0 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 #1 0x55d39f9dc82e in ~unique_ptr third_party/libc++/src/include/__memory/unique_ptr.h:145:44 #2 0x55d39f9dc82e in ~unique_ptr third_party/libc++/src/include/__memory/unique_ptr.h:248:80 #3 0x55d39f9dc82e in content::WebContentsImpl::~WebContentsImpl() content/browser/web_contents/web_contents_impl.cc:1393:1 #4 0x55d3a80ccace in content::TestWebContents::~TestWebContents() content/test/test_web_contents.cc:85:35 #5 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}
150 lines
5.6 KiB
C++
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
|