blob: 650acff2b128e78bcab3c155fe417d33b51e9186 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// A collection of functions designed for use with content_shell based browser
// tests internal to the content/ module.
// Note: If a function here also works with browser_tests, it should be in
// the content public API.
#include <memory>
#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/test/histogram_tester.h"
#include "content/browser/bad_message.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/file_chooser_params.h"
#include "content/public/test/browser_test_utils.h"
#include "url/gurl.h"
namespace content {
class FrameTreeNode;
class RenderFrameHost;
class Shell;
class SiteInstance;
class ToRenderFrameHost;
struct ScreenInfo;
// Navigates the frame represented by |node| to |url|, blocking until the
// navigation finishes.
void NavigateFrameToURL(FrameTreeNode* node, const GURL& url);
// Sets the DialogManager to proceed by default or not when showing a
// BeforeUnload dialog, and if it proceeds, what value to return.
void SetShouldProceedOnBeforeUnload(Shell* shell, bool proceed, bool success);
// Extends the ToRenderFrameHost mechanism to FrameTreeNodes.
RenderFrameHost* ConvertToRenderFrameHost(FrameTreeNode* frame_tree_node);
// Creates compact textual representations of the state of the frame tree that
// is appropriate for use in assertions.
// The diagrams show frame tree structure, the SiteInstance of current frames,
// presence of pending frames, and the SiteInstances of any and all proxies.
// They look like this:
// Site A (D pending) -- proxies for B C
// |--Site B --------- proxies for A C
// +--Site C --------- proxies for B A
// |--Site A ---- proxies for B
// +--Site A ---- proxies for B
// +--Site A -- proxies for B
// Where A =
// B = (no process)
// C =
// D =
// SiteInstances are assigned single-letter names (A, B, C) which are remembered
// across invocations of the pretty-printer.
class FrameTreeVisualizer {
// Formats and returns a diagram for the provided FrameTreeNode.
std::string DepictFrameTree(FrameTreeNode* root);
// Assign or retrive the abbreviated short name (A, B, C) for a site instance.
std::string GetName(SiteInstance* site_instance);
// Elements are site instance ids. The index of the SiteInstance in the vector
// determines the abbreviated name (0->A, 1->B) for that SiteInstance.
std::vector<int> seen_site_instance_ids_;
// Uses to open a popup from the frame |opener| with the specified
// |url| and |name|. Waits for the navigation to |url| to finish and then
// returns the new popup's Shell. Note that since this navigation to |url| is
// renderer-initiated, it won't cause a process swap unless used in
// --site-per-process mode.
Shell* OpenPopup(const ToRenderFrameHost& opener,
const GURL& url,
const std::string& name);
// This class can be used to stall any resource request, based on an URL match.
// There is no explicit way to resume the request; it should be used carefully.
// Note: This class likely doesn't work with PlzNavigate.
// TODO(nasko): Reimplement this class using NavigationThrottle, once it has
// the ability to defer navigation requests.
class NavigationStallDelegate : public ResourceDispatcherHostDelegate {
explicit NavigationStallDelegate(const GURL& url);
// ResourceDispatcherHostDelegate
void RequestBeginning(net::URLRequest* request,
content::ResourceContext* resource_context,
content::AppCacheService* appcache_service,
ResourceType resource_type,
throttles) override;
GURL url_;
// Helper for mocking choosing a file via a file dialog.
class FileChooserDelegate : public WebContentsDelegate {
// Constructs a WebContentsDelegate that mocks a file dialog.
// The mocked file dialog will always reply that the user selected |file|.
explicit FileChooserDelegate(const base::FilePath& file);
// Implementation of WebContentsDelegate::RunFileChooser.
void RunFileChooser(RenderFrameHost* render_frame_host,
const FileChooserParams& params) override;
// Whether the file dialog was shown.
bool file_chosen() const { return file_chosen_; }
// Copy of the params passed to RunFileChooser.
FileChooserParams params() const { return params_; }
base::FilePath file_;
bool file_chosen_;
FileChooserParams params_;
// This class is a TestNavigationManager that only monitors notifications within
// the given frame tree node.
class FrameTestNavigationManager : public TestNavigationManager {
FrameTestNavigationManager(int frame_tree_node_id,
WebContents* web_contents,
const GURL& url);
// TestNavigationManager:
bool ShouldMonitorNavigation(NavigationHandle* handle) override;
// Notifications are filtered so only this frame is monitored.
int filtering_frame_tree_node_id_;
// An observer that can wait for a specific URL to be committed in a specific
// frame.
// Note: it does not track the start of a navigation, unlike other observers.
class UrlCommitObserver : WebContentsObserver {
explicit UrlCommitObserver(FrameTreeNode* frame_tree_node, const GURL& url);
~UrlCommitObserver() override;
void Wait();
void DidFinishNavigation(NavigationHandle* navigation_handle) override;
// The id of the FrameTreeNode in which navigations are peformed.
int frame_tree_node_id_;
// The URL this observer is expecting to be committed.
GURL url_;
// The RunLoop used to spin the message loop.
base::RunLoop run_loop_;
// Class to sniff incoming IPCs for FrameHostMsg_UpdateResizeParams messages.
// This allows the message to continue to the target child so that processing
// can be verified by tests.
class UpdateResizeParamsMessageFilter : public content::BrowserMessageFilter {
gfx::Rect last_rect() const { return last_rect_; }
void WaitForRect();
void ResetRectRunLoop();
// Returns the new viz::FrameSinkId immediately if the IPC has been received.
// Otherwise this will block the UI thread until it has been received, then it
// will return the new viz::FrameSinkId.
viz::FrameSinkId GetOrWaitForId();
~UpdateResizeParamsMessageFilter() override;
void OnUpdateResizeParams(const gfx::Rect& screen_space_rect,
const gfx::Size& local_frame_size,
const ScreenInfo& screen_info,
uint64_t sequence_number,
const viz::SurfaceId& surface_id);
void OnUpdatedFrameRectOnUI(const gfx::Rect& rect);
void OnUpdatedFrameSinkIdOnUI();
bool OnMessageReceived(const IPC::Message& message) override;
viz::FrameSinkId frame_sink_id_;
base::RunLoop frame_sink_id_run_loop_;
std::unique_ptr<base::RunLoop> screen_space_rect_run_loop_;
bool screen_space_rect_received_;
gfx::Rect last_rect_;
// Waits for a kill of the given RenderProcessHost and returns the
// BadMessageReason that caused a //content-triggerred kill.
// Example usage:
// RenderProcessHostKillWaiter kill_waiter(render_process_host);
// ... test code that triggers a renderer kill ...
// EXPECT_EQ(bad_message::RFH_INVALID_ORIGIN_ON_COMMIT, kill_waiter.Wait());
// Tests that don't expect kills (e.g. tests where a renderer process exits
// normally, like RenderFrameHostManagerTest.ProcessExitWithSwappedOutViews)
// should use RenderProcessHostWatcher instead of RenderProcessHostKillWaiter.
class RenderProcessHostKillWaiter {
explicit RenderProcessHostKillWaiter(RenderProcessHost* render_process_host);
// Waits until the renderer process exits. Returns the bad message that made
// //content kill the renderer. |base::nullopt| is returned if the renderer
// was killed outside of //content or exited normally.
base::Optional<bad_message::BadMessageReason> Wait() WARN_UNUSED_RESULT;
RenderProcessHostWatcher exit_watcher_;
base::HistogramTester histogram_tester_;
} // namespace content