Content settings: remove some plugin-related code/resources when... there are no...
[chromium-blink-merge.git] / content / test / content_browser_test_utils_internal.cc
blobaae51eab04f74a0e7f8c242aa5ae2c1765d8d95d
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/public/test/browser_test_utils.h"
17 #include "content/public/test/content_browser_test_utils.h"
18 #include "content/shell/browser/shell.h"
19 #include "content/test/test_frame_navigation_observer.h"
20 #include "url/gurl.h"
22 namespace content {
24 void NavigateFrameToURL(FrameTreeNode* node, const GURL& url) {
25 TestFrameNavigationObserver observer(node);
26 NavigationController::LoadURLParams params(url);
27 params.transition_type = ui::PAGE_TRANSITION_LINK;
28 params.frame_tree_node_id = node->frame_tree_node_id();
29 node->navigator()->GetController()->LoadURLWithParams(params);
30 observer.Wait();
33 FrameTreeVisualizer::FrameTreeVisualizer() {
36 FrameTreeVisualizer::~FrameTreeVisualizer() {
39 std::string FrameTreeVisualizer::DepictFrameTree(FrameTreeNode* root) {
40 // Tracks the sites actually used in this depiction.
41 std::map<std::string, SiteInstance*> legend;
43 // Traversal 1: Assign names to current frames. This ensures that the first
44 // call to the pretty-printer will result in a naming of the site instances
45 // that feels natural and stable.
46 std::stack<FrameTreeNode*> to_explore;
47 for (to_explore.push(root); !to_explore.empty();) {
48 FrameTreeNode* node = to_explore.top();
49 to_explore.pop();
50 for (size_t i = node->child_count(); i-- != 0;) {
51 to_explore.push(node->child_at(i));
54 RenderFrameHost* current = node->render_manager()->current_frame_host();
55 legend[GetName(current->GetSiteInstance())] = current->GetSiteInstance();
58 // Traversal 2: Assign names to the pending/speculative frames. For stability
59 // of assigned names it's important to do this before trying to name the
60 // proxies, which have a less well defined order.
61 for (to_explore.push(root); !to_explore.empty();) {
62 FrameTreeNode* node = to_explore.top();
63 to_explore.pop();
64 for (size_t i = node->child_count(); i-- != 0;) {
65 to_explore.push(node->child_at(i));
68 RenderFrameHost* pending = node->render_manager()->pending_frame_host();
69 RenderFrameHost* spec = node->render_manager()->speculative_frame_host();
70 if (pending)
71 legend[GetName(pending->GetSiteInstance())] = pending->GetSiteInstance();
72 if (spec)
73 legend[GetName(spec->GetSiteInstance())] = spec->GetSiteInstance();
76 // Traversal 3: Assign names to the proxies and add them to |legend| too.
77 // Typically, only openers should have their names assigned this way.
78 for (to_explore.push(root); !to_explore.empty();) {
79 FrameTreeNode* node = to_explore.top();
80 to_explore.pop();
81 for (size_t i = node->child_count(); i-- != 0;) {
82 to_explore.push(node->child_at(i));
85 // Sort the proxies by SiteInstance ID to avoid hash_map ordering.
86 std::map<int, RenderFrameProxyHost*> sorted_proxy_hosts =
87 node->render_manager()->GetAllProxyHostsForTesting();
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 = node->render_manager()->speculative_frame_host();
142 base::StringAppendF(&line, "Site %s",
143 GetName(current->GetSiteInstance()).c_str());
144 if (pending) {
145 base::StringAppendF(&line, " (%s pending)",
146 GetName(pending->GetSiteInstance()).c_str());
148 if (spec) {
149 base::StringAppendF(&line, " (%s speculative)",
150 GetName(spec->GetSiteInstance()).c_str());
153 // Show the SiteInstances of the RenderFrameProxyHosts of this node.
154 std::map<int, RenderFrameProxyHost*> sorted_proxy_host_map =
155 node->render_manager()->GetAllProxyHostsForTesting();
156 if (!sorted_proxy_host_map.empty()) {
157 // Show a dashed line of variable length before the proxy list. Always at
158 // least two dashes.
159 line.append(" --");
161 // To make proxy lists align vertically for the first three tree levels,
162 // pad with dashes up to a first tab stop at column 19 (which works out to
163 // text editor column 28 in the typical diagram fed to EXPECT_EQ as a
164 // string literal). Lining the lists up vertically makes differences in
165 // the proxy sets easier to spot visually. We choose not to use the
166 // *actual* tree height here, because that would make the diagram's
167 // appearance less stable as the tree's shape evolves.
168 while (line.length() < 20) {
169 line.append("-");
171 line.append(" proxies for");
173 // Sort these alphabetically, to avoid hash_map ordering dependency.
174 std::vector<std::string> sorted_proxy_hosts;
175 for (auto& proxy_pair : sorted_proxy_host_map) {
176 sorted_proxy_hosts.push_back(
177 GetName(proxy_pair.second->GetSiteInstance()));
179 std::sort(sorted_proxy_hosts.begin(), sorted_proxy_hosts.end());
180 for (std::string& proxy_name : sorted_proxy_hosts) {
181 base::StringAppendF(&line, " %s", proxy_name.c_str());
184 if (node != root)
185 result.append("\n");
186 result.append(line);
189 // Finally, show a legend with details of the site instances.
190 const char* prefix = "Where ";
191 for (auto& legend_entry : legend) {
192 SiteInstanceImpl* site_instance =
193 static_cast<SiteInstanceImpl*>(legend_entry.second);
194 base::StringAppendF(&result, "\n%s%s = %s", prefix,
195 legend_entry.first.c_str(),
196 site_instance->GetSiteURL().spec().c_str());
197 // Highlight some exceptionable conditions.
198 if (site_instance->active_frame_count() == 0)
199 result.append(" (active_frame_count == 0)");
200 if (!site_instance->GetProcess()->HasConnection())
201 result.append(" (no process)");
202 prefix = " ";
204 return result;
207 std::string FrameTreeVisualizer::GetName(SiteInstance* site_instance) {
208 // Indices into the vector correspond to letters of the alphabet.
209 size_t index =
210 std::find(seen_site_instance_ids_.begin(), seen_site_instance_ids_.end(),
211 site_instance->GetId()) -
212 seen_site_instance_ids_.begin();
213 if (index == seen_site_instance_ids_.size())
214 seen_site_instance_ids_.push_back(site_instance->GetId());
216 // Whosoever writes a test using >=26 site instances shall be a lucky ducky.
217 if (index < 25)
218 return base::StringPrintf("%c", 'A' + static_cast<char>(index));
219 else
220 return base::StringPrintf("Z%d", static_cast<int>(index - 25));
223 Shell* OpenPopup(const ToRenderFrameHost& opener,
224 const GURL& url,
225 const std::string& name) {
226 ShellAddedObserver new_shell_observer;
227 bool did_create_popup = false;
228 bool did_execute_script = ExecuteScriptAndExtractBool(
229 opener,
230 "window.domAutomationController.send("
231 " !!window.open('" + url.spec() + "', '" + name + "'));",
232 &did_create_popup);
233 if (!did_execute_script || !did_create_popup)
234 return nullptr;
236 Shell* new_shell = new_shell_observer.GetShell();
237 WaitForLoadStop(new_shell->web_contents());
238 return new_shell;
241 } // namespace content