1 // Copyright (c) 2012 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.
4
5 #include "content/public/test/content_browser_test_utils.h"
6
7 #include <string>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/files/file_path.h"
12 #include "base/guid.h"
13 #include "base/path_service.h"
14 #include "base/run_loop.h"
15 #include "base/threading/thread_restrictions.h"
16 #include "content/browser/browser_main_loop.h"
17 #include "content/browser/child_process_security_policy_impl.h"
18 #include "content/browser/renderer_host/media/media_stream_manager.h"
19 #include "content/browser/renderer_host/media/video_capture_manager.h"
20 #include "content/browser/site_instance_impl.h"
21 #include "content/public/browser/browser_task_traits.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/navigation_controller.h"
24 #include "content/public/browser/navigation_entry.h"
25 #include "content/public/browser/notification_source.h"
26 #include "content/public/browser/render_frame_host.h"
27 #include "content/public/browser/web_contents.h"
28 #include "content/public/common/content_paths.h"
29 #include "content/public/test/browser_test_utils.h"
30 #include "content/public/test/test_frame_navigation_observer.h"
31 #include "content/public/test/test_navigation_observer.h"
32 #include "content/shell/browser/shell.h"
33 #include "content/shell/browser/shell_javascript_dialog_manager.h"
34 #include "net/base/filename_util.h"
35 #include "net/test/embedded_test_server/embedded_test_server.h"
36
37 #if defined(OS_WIN)
38 #include "ui/views/test/desktop_window_tree_host_win_test_api.h" // nogncheck
39 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
40 #endif // defined(OS_WIN)
41
42 namespace content {
43
GetTestFilePath(const char * dir,const char * file)44 base::FilePath GetTestFilePath(const char* dir, const char* file) {
45 base::FilePath path;
46 base::ScopedAllowBlockingForTesting allow_blocking;
47 base::PathService::Get(DIR_TEST_DATA, &path);
48 if (dir)
49 path = path.AppendASCII(dir);
50 return path.AppendASCII(file);
51 }
52
GetTestUrl(const char * dir,const char * file)53 GURL GetTestUrl(const char* dir, const char* file) {
54 return net::FilePathToFileURL(GetTestFilePath(dir, file));
55 }
56
NavigateToURLBlockUntilNavigationsComplete(Shell * window,const GURL & url,int number_of_navigations)57 void NavigateToURLBlockUntilNavigationsComplete(Shell* window,
58 const GURL& url,
59 int number_of_navigations) {
60 NavigateToURLBlockUntilNavigationsComplete(window->web_contents(), url,
61 number_of_navigations);
62 }
63
ReloadBlockUntilNavigationsComplete(Shell * window,int number_of_navigations)64 void ReloadBlockUntilNavigationsComplete(Shell* window,
65 int number_of_navigations) {
66 WaitForLoadStop(window->web_contents());
67 TestNavigationObserver same_tab_observer(window->web_contents(),
68 number_of_navigations);
69
70 window->Reload();
71 same_tab_observer.Wait();
72 }
73
ReloadBypassingCacheBlockUntilNavigationsComplete(Shell * window,int number_of_navigations)74 void ReloadBypassingCacheBlockUntilNavigationsComplete(
75 Shell* window,
76 int number_of_navigations) {
77 WaitForLoadStop(window->web_contents());
78 TestNavigationObserver same_tab_observer(window->web_contents(),
79 number_of_navigations);
80
81 window->ReloadBypassingCache();
82 same_tab_observer.Wait();
83 }
84
NavigateToURL(Shell * window,const GURL & url)85 bool NavigateToURL(Shell* window, const GURL& url) {
86 return NavigateToURL(window, url, url);
87 }
88
NavigateToURL(Shell * window,const GURL & url,const GURL & expected_commit_url)89 bool NavigateToURL(Shell* window,
90 const GURL& url,
91 const GURL& expected_commit_url) {
92 return NavigateToURL(window->web_contents(), url, expected_commit_url);
93 }
94
NavigateToURLAndExpectNoCommit(Shell * window,const GURL & url)95 bool NavigateToURLAndExpectNoCommit(Shell* window, const GURL& url) {
96 NavigationEntry* old_entry =
97 window->web_contents()->GetController().GetLastCommittedEntry();
98 NavigateToURLBlockUntilNavigationsComplete(window, url, 1);
99 NavigationEntry* new_entry =
100 window->web_contents()->GetController().GetLastCommittedEntry();
101 return old_entry == new_entry;
102 }
103
AppModalDialogWaiter(Shell * shell)104 AppModalDialogWaiter::AppModalDialogWaiter(Shell* shell) : shell_(shell) {
105 Restart();
106 }
107
Restart()108 void AppModalDialogWaiter::Restart() {
109 was_dialog_request_callback_called_ = false;
110 ShellJavaScriptDialogManager* dialog_manager =
111 static_cast<ShellJavaScriptDialogManager*>(
112 shell_->GetJavaScriptDialogManager(shell_->web_contents()));
113 dialog_manager->set_dialog_request_callback(base::BindOnce(
114 &AppModalDialogWaiter::EarlyCallback, base::Unretained(this)));
115 }
116
Wait()117 void AppModalDialogWaiter::Wait() {
118 if (!was_dialog_request_callback_called_) {
119 ShellJavaScriptDialogManager* dialog_manager =
120 static_cast<ShellJavaScriptDialogManager*>(
121 shell_->GetJavaScriptDialogManager(shell_->web_contents()));
122
123 base::RunLoop runner;
124 dialog_manager->set_dialog_request_callback(runner.QuitClosure());
125 runner.Run();
126 was_dialog_request_callback_called_ = true;
127 }
128 }
129
EarlyCallback()130 void AppModalDialogWaiter::EarlyCallback() {
131 was_dialog_request_callback_called_ = true;
132 }
133
ConvertToRenderFrameHost(Shell * shell)134 RenderFrameHost* ConvertToRenderFrameHost(Shell* shell) {
135 return shell->web_contents()->GetMainFrame();
136 }
137
LookupAndLogNameAndIdOfFirstCamera()138 void LookupAndLogNameAndIdOfFirstCamera() {
139 DCHECK(BrowserMainLoop::GetInstance());
140 MediaStreamManager* media_stream_manager =
141 BrowserMainLoop::GetInstance()->media_stream_manager();
142 base::RunLoop run_loop;
143 content::GetIOThreadTaskRunner({})->PostTask(
144 FROM_HERE,
145 base::BindOnce(
146 [](MediaStreamManager* media_stream_manager,
147 base::OnceClosure quit_closure) {
148 media_stream_manager->video_capture_manager()->EnumerateDevices(
149 base::BindOnce(
150 [](base::OnceClosure quit_closure,
151 const media::VideoCaptureDeviceDescriptors&
152 descriptors) {
153 if (descriptors.empty()) {
154 LOG(WARNING) << "No camera found";
155 return;
156 }
157 LOG(INFO) << "Using camera "
158 << descriptors.front().display_name() << " ("
159 << descriptors.front().model_id << ")";
160 std::move(quit_closure).Run();
161 },
162 std::move(quit_closure)));
163 },
164 media_stream_manager, run_loop.QuitClosure()));
165 run_loop.Run();
166 }
167
ShellAddedObserver()168 ShellAddedObserver::ShellAddedObserver() {
169 Shell::SetShellCreatedCallback(base::BindOnce(
170 &ShellAddedObserver::ShellCreated, base::Unretained(this)));
171 }
172
173 ShellAddedObserver::~ShellAddedObserver() = default;
174
GetShell()175 Shell* ShellAddedObserver::GetShell() {
176 if (shell_)
177 return shell_;
178
179 runner_ = std::make_unique<base::RunLoop>();
180 runner_->Run();
181 return shell_;
182 }
183
ShellCreated(Shell * shell)184 void ShellAddedObserver::ShellCreated(Shell* shell) {
185 DCHECK(!shell_);
186 shell_ = shell;
187 if (runner_)
188 runner_->Quit();
189 }
190
IsolateOriginsForTesting(net::test_server::EmbeddedTestServer * embedded_test_server,WebContents * web_contents,std::vector<std::string> hostnames_to_isolate)191 void IsolateOriginsForTesting(
192 net::test_server::EmbeddedTestServer* embedded_test_server,
193 WebContents* web_contents,
194 std::vector<std::string> hostnames_to_isolate) {
195 std::vector<url::Origin> origins_to_isolate;
196 for (const std::string& hostname : hostnames_to_isolate) {
197 origins_to_isolate.push_back(
198 url::Origin::Create(GURL(std::string("http://") + hostname + "/")));
199 }
200
201 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
202 policy->AddIsolatedOrigins(
203 origins_to_isolate,
204 ChildProcessSecurityPolicy::IsolatedOriginSource::TEST);
205
206 // Force a BrowsingInstance swap by navigating cross-site (the newly
207 // isolated origin only affects *future* BrowsingInstances).
208 scoped_refptr<SiteInstanceImpl> old_site_instance;
209 scoped_refptr<SiteInstanceImpl> new_site_instance;
210 do {
211 old_site_instance = static_cast<SiteInstanceImpl*>(
212 web_contents->GetMainFrame()->GetSiteInstance());
213 std::string cross_site_hostname = base::GenerateGUID() + ".com";
214 EXPECT_TRUE(NavigateToURL(
215 web_contents,
216 embedded_test_server->GetURL(cross_site_hostname, "/title1.html")));
217 new_site_instance = static_cast<SiteInstanceImpl*>(
218 web_contents->GetMainFrame()->GetSiteInstance());
219
220 // The navigation might need to be repeated until we actually swap the
221 // SiteInstance (no swap might happen when navigating away from the initial,
222 // empty frame).
223 } while (new_site_instance.get() == old_site_instance.get());
224 EXPECT_FALSE(
225 new_site_instance->IsRelatedSiteInstance(old_site_instance.get()));
226 for (const url::Origin& origin : origins_to_isolate) {
227 EXPECT_FALSE(policy->IsIsolatedOrigin(
228 old_site_instance->GetIsolationContext(), origin,
229 false /* origin_requests_isolation */));
230 EXPECT_TRUE(policy->IsIsolatedOrigin(
231 new_site_instance->GetIsolationContext(), origin,
232 false /* origin_requests_isolation */));
233 }
234 }
235
236 #if defined(OS_WIN)
237
SetMockCursorPositionForTesting(WebContents * web_contents,const gfx::Point & position)238 void SetMockCursorPositionForTesting(WebContents* web_contents,
239 const gfx::Point& position) {
240 views::test::DesktopWindowTreeHostWinTestApi host(
241 static_cast<views::DesktopWindowTreeHostWin*>(
242 web_contents->GetNativeView()->GetHost()));
243 host.SetMockCursorPositionForTesting(position);
244 }
245
246 #endif // defined(OS_WIN)
247
248 } // namespace content
249