Introduce a loading policy to the renderer scheduler
[chromium-blink-merge.git] / content / test / content_browser_test_utils_internal.cc
blob9097a8955fe6a5e4fbc0791d04f124d981adb587
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/test/content_browser_test_utils_internal.h"
7 #include <algorithm>
8 #include <map>
9 #include <set>
10 #include <vector>
12 #include "base/strings/stringprintf.h"
13 #include "content/browser/frame_host/frame_tree_node.h"
14 #include "content/browser/frame_host/navigator.h"
15 #include "content/browser/frame_host/render_frame_proxy_host.h"
16 #include "content/test/test_frame_navigation_observer.h"
17 #include "url/gurl.h"
19 namespace content {
21 void NavigateFrameToURL(FrameTreeNode* node, const GURL& url) {
22 TestFrameNavigationObserver observer(node);
23 NavigationController::LoadURLParams params(url);
24 params.transition_type = ui::PAGE_TRANSITION_LINK;
25 params.frame_tree_node_id = node->frame_tree_node_id();
26 node->navigator()->GetController()->LoadURLWithParams(params);
27 observer.Wait();
30 FrameTreeVisualizer::FrameTreeVisualizer() {
33 FrameTreeVisualizer::~FrameTreeVisualizer() {
36 std::string FrameTreeVisualizer::DepictFrameTree(FrameTreeNode* root) {
37 // Tracks the sites actually used in this depiction.
38 std::map<std::string, SiteInstance*> legend;
40 // Traversal 1: Assign names to current frames. This ensures that the first
41 // call to the pretty-printer will result in a naming of the site instances
42 // that feels natural and stable.
43 std::stack<FrameTreeNode*> to_explore;
44 for (to_explore.push(root); !to_explore.empty();) {
45 FrameTreeNode* node = to_explore.top();
46 to_explore.pop();
47 for (size_t i = node->child_count(); i-- != 0;) {
48 to_explore.push(node->child_at(i));
51 RenderFrameHost* current = node->render_manager()->current_frame_host();
52 legend[GetName(current->GetSiteInstance())] = current->GetSiteInstance();
55 // Traversal 2: Assign names to the pending/speculative frames. For stability
56 // of assigned names it's important to do this before trying to name the
57 // proxies, which have a less well defined order.
58 for (to_explore.push(root); !to_explore.empty();) {
59 FrameTreeNode* node = to_explore.top();
60 to_explore.pop();
61 for (size_t i = node->child_count(); i-- != 0;) {
62 to_explore.push(node->child_at(i));
65 RenderFrameHost* pending = node->render_manager()->pending_frame_host();
66 RenderFrameHost* spec =
67 node->render_manager()->speculative_render_frame_host_.get();
68 if (pending)
69 legend[GetName(pending->GetSiteInstance())] = pending->GetSiteInstance();
70 if (spec)
71 legend[GetName(spec->GetSiteInstance())] = spec->GetSiteInstance();
74 // Traversal 3: Assign names to the proxies and add them to |legend| too.
75 // Typically, only openers should have their names assigned this way.
76 for (to_explore.push(root); !to_explore.empty();) {
77 FrameTreeNode* node = to_explore.top();
78 to_explore.pop();
79 for (size_t i = node->child_count(); i-- != 0;) {
80 to_explore.push(node->child_at(i));
83 // Sort the proxies by SiteInstance ID to avoid hash_map ordering.
84 std::map<int, RenderFrameProxyHost*> sorted_proxy_hosts;
85 for (auto& proxy_pair : node->render_manager()->proxy_hosts_) {
86 sorted_proxy_hosts.insert(proxy_pair);
88 for (auto& proxy_pair : sorted_proxy_hosts) {
89 RenderFrameProxyHost* proxy = proxy_pair.second;
90 legend[GetName(proxy->GetSiteInstance())] = proxy->GetSiteInstance();
94 // Traversal 4: Now that all names are assigned, make a big loop to pretty-
95 // print the tree. Each iteration produces exactly one line of format.
96 std::string result;
97 for (to_explore.push(root); !to_explore.empty();) {
98 FrameTreeNode* node = to_explore.top();
99 to_explore.pop();
100 for (size_t i = node->child_count(); i-- != 0;) {
101 to_explore.push(node->child_at(i));
104 // Draw the feeler line tree graphics by walking up to the root. A feeler
105 // line is needed for each ancestor that is the last child of its parent.
106 // This creates the ASCII art that looks like:
107 // Foo
108 // |--Foo
109 // |--Foo
110 // | |--Foo
111 // | +--Foo
112 // | +--Foo
113 // +--Foo
114 // +--Foo
116 // TODO(nick): Make this more elegant.
117 std::string line;
118 if (node != root) {
119 if (node->parent()->child_at(node->parent()->child_count() - 1) != node)
120 line = " |--";
121 else
122 line = " +--";
123 for (FrameTreeNode* up = node->parent(); up != root; up = up->parent()) {
124 if (up->parent()->child_at(up->parent()->child_count() - 1) != up)
125 line = " | " + line;
126 else
127 line = " " + line;
131 // Prefix one extra space of padding for two reasons. First, this helps the
132 // diagram aligns nicely with the legend. Second, this makes it easier to
133 // read the diffs that gtest spits out on EXPECT_EQ failure.
134 line = " " + line;
136 // Summarize the FrameTreeNode's state. Always show the site of the current
137 // RenderFrameHost, and show any exceptional state of the node, like a
138 // pending or speculative RenderFrameHost.
139 RenderFrameHost* current = node->render_manager()->current_frame_host();
140 RenderFrameHost* pending = node->render_manager()->pending_frame_host();
141 RenderFrameHost* spec =
142 node->render_manager()->speculative_render_frame_host_.get();
143 base::StringAppendF(&line, "Site %s",
144 GetName(current->GetSiteInstance()).c_str());
145 if (pending) {
146 base::StringAppendF(&line, " (%s pending)",
147 GetName(pending->GetSiteInstance()).c_str());
149 if (spec) {
150 base::StringAppendF(&line, " (%s speculative)",
151 GetName(spec->GetSiteInstance()).c_str());
154 // Show the SiteInstances of the RenderFrameProxyHosts of this node.
155 if (!node->render_manager()->proxy_hosts_.empty()) {
156 // Show a dashed line of variable length before the proxy list. Always at
157 // least two dashes.
158 line.append(" --");
160 // To make proxy lists align vertically for the first three tree levels,
161 // pad with dashes up to a first tab stop at column 19 (which works out to
162 // text editor column 28 in the typical diagram fed to EXPECT_EQ as a
163 // string literal). Lining the lists up vertically makes differences in
164 // the proxy sets easier to spot visually. We choose not to use the
165 // *actual* tree height here, because that would make the diagram's
166 // appearance less stable as the tree's shape evolves.
167 while (line.length() < 20) {
168 line.append("-");
170 line.append(" proxies for");
172 // Sort these alphabetically, to avoid hash_map ordering dependency.
173 std::vector<std::string> sorted_proxy_hosts;
174 for (auto& proxy_pair : node->render_manager()->proxy_hosts_) {
175 sorted_proxy_hosts.push_back(
176 GetName(proxy_pair.second->GetSiteInstance()));
178 std::sort(sorted_proxy_hosts.begin(), sorted_proxy_hosts.end());
179 for (std::string& proxy_name : sorted_proxy_hosts) {
180 base::StringAppendF(&line, " %s", proxy_name.c_str());
183 if (node != root)
184 result.append("\n");
185 result.append(line);
188 // Finally, show a legend with details of the site instances.
189 const char* prefix = "Where ";
190 for (auto& legend_entry : legend) {
191 SiteInstanceImpl* site_instance =
192 static_cast<SiteInstanceImpl*>(legend_entry.second);
193 base::StringAppendF(&result, "\n%s%s = %s", prefix,
194 legend_entry.first.c_str(),
195 site_instance->GetSiteURL().spec().c_str());
196 // Highlight some exceptionable conditions.
197 if (site_instance->active_frame_count() == 0)
198 result.append(" (active_frame_count == 0)");
199 if (!site_instance->GetProcess()->HasConnection())
200 result.append(" (no process)");
201 prefix = " ";
203 return result;
206 std::string FrameTreeVisualizer::GetName(SiteInstance* site_instance) {
207 // Indices into the vector correspond to letters of the alphabet.
208 size_t index =
209 std::find(seen_site_instance_ids_.begin(), seen_site_instance_ids_.end(),
210 site_instance->GetId()) -
211 seen_site_instance_ids_.begin();
212 if (index == seen_site_instance_ids_.size())
213 seen_site_instance_ids_.push_back(site_instance->GetId());
215 // Whosoever writes a test using >=26 site instances shall be a lucky ducky.
216 if (index < 25)
217 return base::StringPrintf("%c", 'A' + static_cast<char>(index));
218 else
219 return base::StringPrintf("Z%d", static_cast<int>(index - 25));
222 } // namespace content