1 // Copyright 2013 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_TEST_TEST_RENDER_FRAME_HOST_H_
6 #define CONTENT_TEST_TEST_RENDER_FRAME_HOST_H_
7 
8 #include <stdint.h>
9 
10 #include <map>
11 #include <string>
12 #include <vector>
13 
14 #include "base/macros.h"
15 #include "base/optional.h"
16 #include "content/browser/renderer_host/render_frame_host_impl.h"
17 #include "content/common/frame_messages.h"
18 #include "content/common/navigation_client.mojom-forward.h"
19 #include "content/common/navigation_params.mojom-forward.h"
20 #include "content/public/browser/web_contents_observer.h"
21 #include "content/public/test/mock_render_process_host.h"
22 #include "content/public/test/test_renderer_host.h"
23 #include "content/test/test_render_view_host.h"
24 #include "content/test/test_render_widget_host.h"
25 #include "mojo/public/cpp/bindings/pending_receiver.h"
26 #include "mojo/public/cpp/bindings/pending_remote.h"
27 #include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom-forward.h"
28 #include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-forward.h"
29 #include "ui/base/page_transition_types.h"
30 
31 namespace net {
32 class IPEndPoint;
33 }
34 
35 namespace content {
36 
37 class TestRenderFrameHostCreationObserver : public WebContentsObserver {
38  public:
39   explicit TestRenderFrameHostCreationObserver(WebContents* web_contents);
40   ~TestRenderFrameHostCreationObserver() override;
41 
42   // WebContentsObserver implementation.
43   void RenderFrameCreated(RenderFrameHost* render_frame_host) override;
44 
last_created_frame()45   RenderFrameHost* last_created_frame() const { return last_created_frame_; }
46 
47  private:
48   RenderFrameHost* last_created_frame_;
49 };
50 
51 class TestRenderFrameHost : public RenderFrameHostImpl,
52                             public RenderFrameHostTester {
53  public:
54   TestRenderFrameHost(SiteInstance* site_instance,
55                       scoped_refptr<RenderViewHostImpl> render_view_host,
56                       RenderFrameHostDelegate* delegate,
57                       FrameTree* frame_tree,
58                       FrameTreeNode* frame_tree_node,
59                       int32_t routing_id,
60                       const base::UnguessableToken& frame_token,
61                       LifecycleState lifecyle_state);
62   ~TestRenderFrameHost() override;
63 
64   // RenderFrameHostImpl overrides (same values, but in Test*/Mock* types)
65   TestRenderViewHost* GetRenderViewHost() override;
66   MockRenderProcessHost* GetProcess() override;
67   TestRenderWidgetHost* GetRenderWidgetHost() override;
68   void AddMessageToConsole(blink::mojom::ConsoleMessageLevel level,
69                            const std::string& message) override;
70   void ReportHeavyAdIssue(blink::mojom::HeavyAdResolutionStatus resolution,
71                           blink::mojom::HeavyAdReason reason) override;
72   bool IsTestRenderFrameHost() const override;
73 
74   // Public overrides to expose RenderFrameHostImpl's mojo methods to tests.
75   void DidFailLoadWithError(const GURL& url, int error_code) override;
76 
77   // RenderFrameHostTester implementation.
78   void InitializeRenderFrameIfNeeded() override;
79   TestRenderFrameHost* AppendChild(const std::string& frame_name) override;
80   TestRenderFrameHost* AppendChildWithPolicy(
81       const std::string& frame_name,
82       const blink::ParsedFeaturePolicy& allow) override;
83   void Detach() override;
84   void SendNavigateWithTransition(int nav_entry_id,
85                                   bool did_create_new_entry,
86                                   const GURL& url,
87                                   ui::PageTransition transition);
88   void SimulateBeforeUnloadCompleted(bool proceed) override;
89   void SimulateUnloadACK() override;
90   void SimulateFeaturePolicyHeader(
91       blink::mojom::FeaturePolicyFeature feature,
92       const std::vector<url::Origin>& allowlist) override;
93   void SimulateUserActivation() override;
94   const std::vector<std::string>& GetConsoleMessages() override;
95   int GetHeavyAdIssueCount(HeavyAdIssueType type) override;
96 
97   void SendNavigate(int nav_entry_id,
98                     bool did_create_new_entry,
99                     const GURL& url);
100   void SendNavigateWithParams(
101       FrameHostMsg_DidCommitProvisionalLoad_Params* params,
102       bool was_within_same_document);
103   void SendNavigateWithParamsAndInterfaceParams(
104       FrameHostMsg_DidCommitProvisionalLoad_Params* params,
105       mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params,
106       bool was_within_same_document);
107 
108   // With the current navigation logic this method is a no-op.
109   // Simulates a renderer-initiated navigation to |url| starting in the
110   // RenderFrameHost.
111   // DEPRECATED: use NavigationSimulator instead.
112   void SimulateNavigationStart(const GURL& url);
113 
114   // Simulates a redirect to |new_url| for the navigation in the
115   // RenderFrameHost.
116   // DEPRECATED: use NavigationSimulator instead.
117   void SimulateRedirect(const GURL& new_url);
118 
119   // Simulates a navigation to |url| committing in the RenderFrameHost.
120   // DEPRECATED: use NavigationSimulator instead.
121   void SimulateNavigationCommit(const GURL& url);
122 
123   // This method simulates receiving a BeginNavigation IPC.
124   // DEPRECATED: use NavigationSimulator instead.
125   void SendRendererInitiatedNavigationRequest(const GURL& url,
126                                               bool has_user_gesture);
127 
128   void SimulateDidChangeOpener(
129       const base::Optional<base::UnguessableToken>& opener_frame_token);
130 
131   void DidEnforceInsecureRequestPolicy(
132       blink::mojom::InsecureRequestPolicy policy);
133 
134   // If set, navigations will appear to have cleared the history list in the
135   // RenderFrame
136   // (FrameHostMsg_DidCommitProvisionalLoad_Params::history_list_was_cleared).
137   // False by default.
set_simulate_history_list_was_cleared(bool cleared)138   void set_simulate_history_list_was_cleared(bool cleared) {
139     simulate_history_list_was_cleared_ = cleared;
140   }
141 
142   // Advances the RenderFrameHost (and through it the RenderFrameHostManager) to
143   // a state where a new navigation can be committed by a renderer. This
144   // simulates a BeforeUnload completion callback from the renderer, and the
145   // interaction with the IO thread up until the response is ready to commit.
146   void PrepareForCommit();
147 
148   // Like PrepareForCommit, but with the socket address when needed.
149   // TODO(clamy): Have NavigationSimulator make the relevant calls directly and
150   // remove this function.
151   void PrepareForCommitDeprecatedForNavigationSimulator(
152       const net::IPEndPoint& remote_endpoint,
153       bool was_fetched_via_cache,
154       bool is_signed_exchange_inner_response,
155       net::HttpResponseInfo::ConnectionInfo connection_info,
156       base::Optional<net::SSLInfo> ssl_info,
157       scoped_refptr<net::HttpResponseHeaders> response_headers);
158 
159   // Used to simulate the commit of a navigation having been processed in the
160   // renderer. If parameters required to commit are not provided, they will be
161   // set to default null values.
162   void SimulateCommitProcessed(
163       NavigationRequest* navigation_request,
164       std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
165       mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
166           interface_provider_receiver,
167       mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
168           browser_interface_broker_receiver,
169       bool same_document);
170 
171   // Send a message with the sandbox flags and feature policy
172   void SendFramePolicy(network::mojom::WebSandboxFlags sandbox_flags,
173                        const blink::ParsedFeaturePolicy& fp_header,
174                        const blink::DocumentPolicyFeatureState& dp_header);
175 
176   // Creates a WebBluetooth Service with a dummy InterfaceRequest.
177   WebBluetoothServiceImpl* CreateWebBluetoothServiceForTesting();
178 
last_commit_was_error_page()179   bool last_commit_was_error_page() const {
180     return last_commit_was_error_page_;
181   }
182 
183   // Returns a PendingReceiver<InterfaceProvider> that is safe to bind to an
184   // implementation, but will never receive any interface receivers.
185   static mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
186   CreateStubInterfaceProviderReceiver();
187 
188   // Returns a PendingReceiver<BrowserInterfaceBroker> that is safe to bind to
189   // an implementation, but will never receive any interface requests.
190   static mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
191   CreateStubBrowserInterfaceBrokerReceiver();
192 
193   // This simulates aborting a cross document navigation.
194   // Will abort the navigation with the given |navigation_id|.
195   void AbortCommit(NavigationRequest* navigation_request);
196 
197   // Returns the navigations that are trying to commit.
198   const std::map<NavigationRequest*, std::unique_ptr<NavigationRequest>>&
navigation_requests()199   navigation_requests() {
200     return navigation_requests_;
201   }
202 
203   enum class LoadingScenario {
204     NewDocumentNavigation,
205     kSameDocumentNavigation,
206 
207     // TODO(altimin): Improve handling for the scenarios where navigation or
208     // page load have failed.
209     kOther
210   };
211 
212   // Simulates RenderFrameHost finishing loading and dispatching all relevant
213   // callbacks.
214   void SimulateLoadingCompleted(LoadingScenario loading_scenario);
215 
216  protected:
217   void SendCommitNavigation(
218       mojom::NavigationClient* navigation_client,
219       NavigationRequest* navigation_request,
220       mojom::CommonNavigationParamsPtr common_params,
221       mojom::CommitNavigationParamsPtr commit_params,
222       network::mojom::URLResponseHeadPtr response_head,
223       mojo::ScopedDataPipeConsumerHandle response_body,
224       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
225       std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
226           subresource_loader_factories,
227       base::Optional<std::vector<blink::mojom::TransferrableURLLoaderPtr>>
228           subresource_overrides,
229       blink::mojom::ControllerServiceWorkerInfoPtr
230           controller_service_worker_info,
231       blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info,
232       mojo::PendingRemote<network::mojom::URLLoaderFactory>
233           prefetch_loader_factory,
234       blink::mojom::PolicyContainerPtr policy_container,
235       const base::UnguessableToken& devtools_navigation_token) override;
236   void SendCommitFailedNavigation(
237       mojom::NavigationClient* navigation_client,
238       NavigationRequest* navigation_request,
239       mojom::CommonNavigationParamsPtr common_params,
240       mojom::CommitNavigationParamsPtr commit_params,
241       bool has_stale_copy_in_cache,
242       int32_t error_code,
243       const base::Optional<std::string>& error_page_content,
244       std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
245           subresource_loader_factories) override;
246 
247  private:
248   void SendNavigateWithParameters(int nav_entry_id,
249                                   bool did_create_new_entry,
250                                   const GURL& url,
251                                   ui::PageTransition transition,
252                                   int response_code);
253 
254   void PrepareForCommitInternal(
255       const net::IPEndPoint& remote_endpoint,
256       bool was_fetched_via_cache,
257       bool is_signed_exchange_inner_response,
258       net::HttpResponseInfo::ConnectionInfo connection_info,
259       base::Optional<net::SSLInfo> ssl_info,
260       scoped_refptr<net::HttpResponseHeaders> response_headers);
261 
262   // Computes the page ID for a pending navigation in this RenderFrameHost;
263   int32_t ComputeNextPageID();
264 
265   std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
266   BuildDidCommitParams(int nav_entry_id,
267                        bool did_create_new_entry,
268                        const GURL& url,
269                        ui::PageTransition transition,
270                        int response_code);
271 
272   mojom::DidCommitProvisionalLoadInterfaceParamsPtr
273   BuildDidCommitInterfaceParams(bool is_same_document);
274 
275   // Keeps a running vector of messages sent to AddMessageToConsole.
276   std::vector<std::string> console_messages_;
277 
278   // Keep a count of the heavy ad issues sent to ReportHeavyAdIssue.
279   int heavy_ad_issue_network_count_ = 0;
280   int heavy_ad_issue_cpu_total_count_ = 0;
281   int heavy_ad_issue_cpu_peak_count_ = 0;
282 
283   TestRenderFrameHostCreationObserver child_creation_observer_;
284 
285   // See set_simulate_history_list_was_cleared() above.
286   bool simulate_history_list_was_cleared_;
287 
288   // The last commit was for an error page.
289   bool last_commit_was_error_page_;
290 
291   std::map<NavigationRequest*,
292            mojom::NavigationClient::CommitNavigationCallback>
293       commit_callback_;
294   std::map<NavigationRequest*,
295            mojom::NavigationClient::CommitFailedNavigationCallback>
296       commit_failed_callback_;
297 
298   mojo::PendingRemote<blink::mojom::WebBluetoothService>
299       dummy_web_bluetooth_service_remote_;
300 
301   DISALLOW_COPY_AND_ASSIGN(TestRenderFrameHost);
302 };
303 
304 }  // namespace content
305 
306 #endif  // CONTENT_TEST_TEST_RENDER_FRAME_HOST_H_
307