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 #ifndef CONTENT_PUBLIC_TEST_CONTENT_BROWSER_TEST_UTILS_H_
6 #define CONTENT_PUBLIC_TEST_CONTENT_BROWSER_TEST_UTILS_H_
7 
8 #include <map>
9 #include <string>
10 
11 #include "base/callback.h"
12 #include "base/macros.h"
13 #include "base/run_loop.h"
14 #include "content/public/common/page_type.h"
15 #include "ui/gfx/native_widget_types.h"
16 #include "url/gurl.h"
17 
18 namespace base {
19 class FilePath;
20 
21 namespace mac {
22 class ScopedObjCClassSwizzler;
23 }  // namespace mac
24 }  // namespace base
25 
26 namespace gfx {
27 class Point;
28 class Range;
29 class Rect;
30 }  // namespace gfx
31 
32 namespace net {
33 namespace test_server {
34 class EmbeddedTestServer;
35 }  // namespace test_server
36 }  // namespace net
37 
38 // A collections of functions designed for use with content_shell based browser
39 // tests.
40 // Note: if a function here also works with browser_tests, it should be in
41 // content\public\test\browser_test_utils.h
42 
43 namespace content {
44 class RenderFrameHost;
45 class RenderWidgetHost;
46 class Shell;
47 class ToRenderFrameHost;
48 class WebContents;
49 
50 // Generate the file path for testing a particular test.
51 // The file for the tests is all located in
52 // content/test/data/dir/<file>
53 // The returned path is FilePath format.
54 //
55 // A null |dir| indicates the root directory - i.e.
56 // content/test/data/<file>
57 base::FilePath GetTestFilePath(const char* dir, const char* file);
58 
59 // Generate the URL for testing a particular test.
60 // HTML for the tests is all located in
61 // test_root_directory/dir/<file>
62 // The returned path is GURL format.
63 //
64 // A null |dir| indicates the root directory - i.e.
65 // content/test/data/<file>
66 GURL GetTestUrl(const char* dir, const char* file);
67 
68 // Navigates |window| to |url|, blocking until the navigation finishes. Returns
69 // true if the page was loaded successfully and the last committed URL matches
70 // |url|.  This is a browser-initiated navigation that simulates a user typing
71 // |url| into the address bar.
72 //
73 // Tests should ensure that NavigateToURL succeeds.  If the URL that will
74 // eventually commit is different from |url|, such as with redirects, use the
75 // version below which also takes the expected commit URL.  If the navigation
76 // will not result in a commit, such as a download or a 204 response, use
77 // NavigateToURLAndExpectNoCommit() instead.
78 WARN_UNUSED_RESULT bool NavigateToURL(Shell* window, const GURL& url);
79 
80 // Same as above, but takes in an additional URL, |expected_commit_url|, to
81 // which the navigation should eventually commit.  This is useful for cases
82 // like redirects, where navigation starts on one URL but ends up committing a
83 // different URL.  This function will return true if navigating to |url|
84 // results in a successful commit to |expected_commit_url|.
85 WARN_UNUSED_RESULT bool NavigateToURL(Shell* window,
86                                       const GURL& url,
87                                       const GURL& expected_commit_url);
88 
89 // Navigates |window| to |url|, blocking until the given number of navigations
90 // finishes.
91 void NavigateToURLBlockUntilNavigationsComplete(Shell* window,
92                                                 const GURL& url,
93                                                 int number_of_navigations);
94 
95 // Navigates |window| to |url|, blocks until the navigation finishes, and
96 // checks that the navigation did not commit (e.g., due to a crash or
97 // download).
98 WARN_UNUSED_RESULT bool NavigateToURLAndExpectNoCommit(Shell* window,
99                                                        const GURL& url);
100 
101 // Reloads |window|, blocking until the given number of navigations finishes.
102 void ReloadBlockUntilNavigationsComplete(Shell* window,
103                                          int number_of_navigations);
104 
105 // Reloads |window| with bypassing cache flag, and blocks until the given number
106 // of navigations finishes.
107 void ReloadBypassingCacheBlockUntilNavigationsComplete(
108     Shell* window,
109     int number_of_navigations);
110 
111 // A class to help with waiting for at least one javascript dialog to be
112 // requested.
113 //
114 // On creation or Restart, it uses set_dialog_request_callback to
115 // capture any future dialog request. Calling Wait() will
116 // either return immediately because a dialog has already been called or it will
117 // wait, processing events until one is requested.
118 //
119 // That means, object should be constructed, or Restart() called, before section
120 // that could request a modal dialog.
121 class AppModalDialogWaiter {
122  public:
123   explicit AppModalDialogWaiter(Shell* shell);
124   void Restart();
125   void Wait();
126 
WasDialogRequestedCallbackCalled()127   bool WasDialogRequestedCallbackCalled() {
128     return was_dialog_request_callback_called_;
129   }
130 
131  private:
132   void EarlyCallback();
133   bool was_dialog_request_callback_called_ = false;
134   Shell* shell_;
135 };
136 
137 // Extends the ToRenderFrameHost mechanism to content::Shells.
138 RenderFrameHost* ConvertToRenderFrameHost(Shell* shell);
139 
140 // Writes an entry with the name and id of the first camera to the logs or
141 // an entry indicating that no camera is available. This must be invoked from
142 // the test method body, because at the time of invocation of
143 // testing::Test::SetUp() the BrowserMainLoop does not yet exist.
144 void LookupAndLogNameAndIdOfFirstCamera();
145 
146 // Used to wait for a new Shell window to be created. Instantiate this object
147 // before the operation that will create the window.
148 class ShellAddedObserver {
149  public:
150   ShellAddedObserver();
151   ~ShellAddedObserver();
152 
153   // Will run a message loop to wait for the new window if it hasn't been
154   // created since the constructor.
155   Shell* GetShell();
156 
157  private:
158   void ShellCreated(Shell* shell);
159 
160   Shell* shell_ = nullptr;
161   std::unique_ptr<base::RunLoop> runner_;
162 
163   DISALLOW_COPY_AND_ASSIGN(ShellAddedObserver);
164 };
165 
166 #if defined(OS_MAC)
167 // An observer of the RenderWidgetHostViewCocoa which is the NSView
168 // corresponding to the page.
169 class RenderWidgetHostViewCocoaObserver {
170  public:
171   // The method name for 'didAddSubview'.
172   static constexpr char kDidAddSubview[] = "didAddSubview:";
173   static constexpr char kShowDefinitionForAttributedString[] =
174       "showDefinitionForAttributedString:atPoint:";
175 
176   // Returns the method swizzler for the given |method_name|. This is useful
177   // when the original implementation of the method is needed.
178   static base::mac::ScopedObjCClassSwizzler* GetSwizzler(
179       const std::string& method_name);
180 
181   // Returns the unique RenderWidgetHostViewCocoaObserver instance (if any) for
182   // the given WebContents. There can be at most one observer per WebContents
183   // and to create a new observer the older one has to be deleted first.
184   static RenderWidgetHostViewCocoaObserver* GetObserver(
185       WebContents* web_contents);
186 
187   explicit RenderWidgetHostViewCocoaObserver(WebContents* web_contents);
188   virtual ~RenderWidgetHostViewCocoaObserver();
189 
190   // Called when a new NSView is added as a subview of RWHVCocoa.
191   // |rect_in_root_view| represents the bounds of the NSView in RWHVCocoa
192   // coordinates. The view will be dismissed shortly after this call.
DidAddSubviewWillBeDismissed(const gfx::Rect & rect_in_root_view)193   virtual void DidAddSubviewWillBeDismissed(
194       const gfx::Rect& rect_in_root_view) {}
195   // Called when RenderWidgeHostViewCocoa is asked to show definition of
196   // |for_word| using Mac's dictionary popup.
OnShowDefinitionForAttributedString(const std::string & for_word)197   virtual void OnShowDefinitionForAttributedString(
198       const std::string& for_word) {}
199 
web_contents()200   WebContents* web_contents() const { return web_contents_; }
201 
202  private:
203   static void SetUpSwizzlers();
204 
205   static std::map<std::string,
206                   std::unique_ptr<base::mac::ScopedObjCClassSwizzler>>
207       rwhvcocoa_swizzlers_;
208   static std::map<WebContents*, RenderWidgetHostViewCocoaObserver*> observers_;
209 
210   WebContents* const web_contents_;
211 
212   DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewCocoaObserver);
213 };
214 
215 void SetWindowBounds(gfx::NativeWindow window, const gfx::Rect& bounds);
216 
217 // This method will request the string (word) at |point| inside the |rwh| where
218 // |point| is with respect to the |rwh| coordinates. |result_callback| is called
219 // with the word as well as |baselinePoint| when the result comes back from the
220 // renderer. The baseline point is the position of the pop-up in AppKit
221 // coordinate system (inverted y-axis).
222 void GetStringAtPointForRenderWidget(
223     RenderWidgetHost* rwh,
224     const gfx::Point& point,
225     base::OnceCallback<void(const std::string&, const gfx::Point&)>
226         result_callback);
227 
228 // This method will request the string identified by |range| inside the |rwh|.
229 // When the result comes back, |result_callback| is invoked with the given text
230 // and its position in AppKit coordinates (inverted-y axis).
231 void GetStringFromRangeForRenderWidget(
232     RenderWidgetHost* rwh,
233     const gfx::Range& range,
234     base::OnceCallback<void(const std::string&, const gfx::Point&)>
235         result_callback);
236 
237 #endif
238 
239 // Adds http://<hostname_to_isolate>/ to the list of origins that require
240 // isolation (for each of the hostnames in the |hostnames_to_isolate| vector).
241 //
242 // To ensure that the isolation applies to subsequent navigations in
243 // |web_contents|, this function forces a BrowsingInstance swap by performing
244 // one or two browser-initiated navigations in |web_contents| to another,
245 // random, guid-based hostname.
246 void IsolateOriginsForTesting(
247     net::test_server::EmbeddedTestServer* embedded_test_server,
248     WebContents* web_contents,
249     std::vector<std::string> hostnames_to_isolate);
250 
251 #if defined(OS_WIN)
252 
253 void SetMockCursorPositionForTesting(WebContents* web_contents,
254                                      const gfx::Point& position);
255 
256 #endif  // defined(OS_WIN)
257 
258 }  // namespace content
259 
260 #endif  // CONTENT_PUBLIC_TEST_CONTENT_BROWSER_TEST_UTILS_H_
261