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