File: hung_renderer_core.cc

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (132 lines) | stat: -rw-r--r-- 5,300 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/hung_renderer/hung_renderer_core.h"

#include <algorithm>

#include "base/i18n/rtl.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/tab_contents/core_tab_helper.h"
#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
#include "chrome/grit/generated_resources.h"
#include "components/url_formatter/url_formatter.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"

namespace {

// Author's Note:
//
// The inefficiency of walking the frame tree repeatedly has not gone unnoticed.
// Given the different requirements of the Cocoa and Views implementations of
// the Hung Page dialog, this is the simplest way. When we consolidate
// implementations, it will be a good idea to reconsider this approach.

// Returns the first RenderFrameHost that has a process that matches
// `hung_process`.
content::RenderFrameHost* FindFirstRenderFrameHostMatchingProcess(
    content::WebContents* web_contents,
    content::RenderProcessHost* hung_process) {
  content::RenderFrameHost* result = nullptr;
  // We only consider frames visible to the user for hung frames. This is
  // fine because only frames receiving input are considered hung.
  web_contents->GetPrimaryMainFrame()->ForEachRenderFrameHostWithAction(
      [hung_process, &result](content::RenderFrameHost* render_frame_host) {
        if (render_frame_host->GetProcess() == hung_process) {
          result = render_frame_host;
          return content::RenderFrameHost::FrameIterationAction::kStop;
        }
        return content::RenderFrameHost::FrameIterationAction::kContinue;
      });
  return result;
}

// Returns whether the WebContents has a frame that is backed by the hung
// process.
bool IsWebContentsHung(content::WebContents* web_contents,
                       content::RenderProcessHost* hung_process) {
  return FindFirstRenderFrameHostMatchingProcess(web_contents, hung_process) !=
         nullptr;
}

// Returns the URL of the first hung frame encountered in the WebContents.
GURL GetURLOfAnyHungFrame(content::WebContents* web_contents,
                          content::RenderProcessHost* hung_process) {
  content::RenderFrameHost* render_frame_host =
      FindFirstRenderFrameHostMatchingProcess(web_contents, hung_process);
  // If a frame is attempting to commit a navigation into a hung renderer
  // process, then its |frame->GetProcess()| will still return the process
  // hosting the previously committed navigation.  In such case, the
  // FindFirstRenderFrameHostMatchingProcess above might not find any matching
  // frame.
  if (!render_frame_host) {
    return GURL();
  }
  return render_frame_host->GetLastCommittedURL();
}

}  // namespace

std::vector<content::WebContents*> GetHungWebContentsList(
    content::WebContents* hung_web_contents,
    content::RenderProcessHost* hung_process) {
  std::vector<content::WebContents*> result;

  auto is_hung = [hung_process](content::WebContents* web_contents) {
    return IsWebContentsHung(web_contents, hung_process) &&
           !web_contents->IsCrashed();
  };
  std::ranges::copy_if(AllTabContentses(), std::back_inserter(result), is_hung);

  // Move |hung_web_contents| to the front.  It might be missing from the
  // initial |results| when it hasn't yet committed a navigation into the hung
  // process.
  auto first = std::ranges::find(result, hung_web_contents);
  if (first != result.end()) {
    std::rotate(result.begin(), first, std::next(first));
  } else {
    result.insert(result.begin(), hung_web_contents);
  }

  return result;
}

// Given a WebContents that is affected by the hang, and the RenderProcessHost
// of the hung process, returns the title of the WebContents that should be used
// in the "Hung Page" dialog.
std::u16string GetHungWebContentsTitle(
    content::WebContents* affected_web_contents,
    content::RenderProcessHost* hung_process) {
  std::u16string page_title = affected_web_contents->GetTitle();
  if (page_title.empty()) {
    page_title = CoreTabHelper::GetDefaultTitle();
  }
  // TODO(xji): Consider adding a special case if the title text is a URL,
  // since those should always have LTR directionality. Please refer to
  // http://crbug.com/6726 for more information.
  base::i18n::AdjustStringForLocaleDirection(&page_title);

  if (affected_web_contents->GetPrimaryMainFrame()->GetProcess() ==
      hung_process) {
    return page_title;
  }

  GURL hung_url = GetURLOfAnyHungFrame(affected_web_contents, hung_process);
  if (!hung_url.is_valid() || !hung_url.has_host()) {
    return page_title;
  }

  // N.B. using just the host here is OK since this is a notification and the
  // user doesn't need to make a security critical decision about the page in
  // this dialog.
  std::u16string host_string;
  url_formatter::AppendFormattedHost(hung_url, &host_string);

  return l10n_util::GetStringFUTF16(IDS_BROWSER_HANGMONITOR_IFRAME_TITLE,
                                    host_string, page_title);
}