feat: WebFrameMain.collectJavaScriptCallStack() (#44938)

* feat: WebFrameMain.unresponsiveDocumentJSCallStack

Co-authored-by: Samuel Maddock <smaddock@slack-corp.com>

* Revert "feat: WebFrameMain.unresponsiveDocumentJSCallStack"

This reverts commit e0612bc1a00a5282cba5df97da3c9c90e96ef244.

Co-authored-by: Samuel Maddock <smaddock@slack-corp.com>

* feat: frame.collectJavaScriptCallStack()

Co-authored-by: Samuel Maddock <smaddock@slack-corp.com>

* feat: frame.collectJavaScriptCallStack()

Co-authored-by: Samuel Maddock <smaddock@slack-corp.com>

* Update web-frame-main.md

Co-authored-by: Sam Maddock <smaddock@slack-corp.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Maddock <smaddock@slack-corp.com>
This commit is contained in:
trop[bot] 2024-12-03 09:55:52 -08:00 committed by GitHub
parent ed0946c880
commit f383391c0e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 131 additions and 1 deletions

View file

@ -9,9 +9,11 @@
#include <utility>
#include <vector>
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/no_destructor.h"
#include "content/browser/renderer_host/render_frame_host_impl.h" // nogncheck
#include "content/browser/renderer_host/render_process_host_impl.h" // nogncheck
#include "content/public/browser/frame_tree_node_id.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/common/isolated_world_ids.h"
@ -429,6 +431,61 @@ std::vector<content::RenderFrameHost*> WebFrameMain::FramesInSubtree() const {
return frame_hosts;
}
v8::Local<v8::Promise> WebFrameMain::CollectDocumentJSCallStack(
gin::Arguments* args) {
gin_helper::Promise<base::Value> promise(args->isolate());
v8::Local<v8::Promise> handle = promise.GetHandle();
if (render_frame_disposed_) {
promise.RejectWithErrorMessage(
"Render frame was disposed before WebFrameMain could be accessed");
return handle;
}
if (!base::FeatureList::IsEnabled(
blink::features::kDocumentPolicyIncludeJSCallStacksInCrashReports)) {
promise.RejectWithErrorMessage(
"DocumentPolicyIncludeJSCallStacksInCrashReports is not enabled");
return handle;
}
content::RenderProcessHostImpl* rph_impl =
static_cast<content::RenderProcessHostImpl*>(render_frame_->GetProcess());
rph_impl->GetJavaScriptCallStackGeneratorInterface()
->CollectJavaScriptCallStack(
base::BindOnce(&WebFrameMain::CollectedJavaScriptCallStack,
weak_factory_.GetWeakPtr(), std::move(promise)));
return handle;
}
void WebFrameMain::CollectedJavaScriptCallStack(
gin_helper::Promise<base::Value> promise,
const std::string& untrusted_javascript_call_stack,
const std::optional<blink::LocalFrameToken>& remote_frame_token) {
if (render_frame_disposed_) {
promise.RejectWithErrorMessage(
"Render frame was disposed before call stack was received");
return;
}
const blink::LocalFrameToken& frame_token = render_frame_->GetFrameToken();
if (remote_frame_token == frame_token) {
base::Value base_value(untrusted_javascript_call_stack);
promise.Resolve(base_value);
} else if (!remote_frame_token) {
// Failed to collect call stack. See logic in:
// third_party/blink/renderer/controller/javascript_call_stack_collector.cc
promise.Resolve(base::Value());
} else {
// Requests for call stacks can be initiated on an old RenderProcessHost
// then be received after a frame swap.
LOG(ERROR) << "Received call stack from old RPH";
promise.Resolve(base::Value());
}
}
void WebFrameMain::DOMContentLoaded() {
Emit("dom-ready");
}
@ -461,6 +518,8 @@ void WebFrameMain::FillObjectTemplate(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> templ) {
gin_helper::ObjectTemplateBuilder(isolate, templ)
.SetMethod("executeJavaScript", &WebFrameMain::ExecuteJavaScript)
.SetMethod("collectJavaScriptCallStack",
&WebFrameMain::CollectDocumentJSCallStack)
.SetMethod("reload", &WebFrameMain::Reload)
.SetMethod("isDestroyed", &WebFrameMain::IsDestroyed)
.SetMethod("_send", &WebFrameMain::Send)