blob: 51268a14448181490d6de59f578222edeb1ed7de [file] [log] [blame]
// Copyright 2021 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.
#include "content/public/test/fenced_frame_test_util.h"
#include "base/trace_event/typed_macros.h"
#include "content/browser/fenced_frame/fenced_frame.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_frame_navigation_observer.h"
#include "content/test/fenced_frame_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "url/gurl.h"
namespace content {
namespace test {
namespace {
constexpr char kAddFencedFrameScript[] = R"({
const fenced_frame = document.createElement('fencedframe');
document.body.appendChild(fenced_frame);
})";
constexpr char kAddAndNavigateFencedFrameScript[] = R"({
const fenced_frame = document.createElement('fencedframe');
fenced_frame.src = $1;
document.body.appendChild(fenced_frame);
})";
constexpr char kNavigateFrameScript[] = R"({location.href = $1;})";
} // namespace
FencedFrameTestHelper::FencedFrameTestHelper() {
scoped_feature_list_.InitAndEnableFeatureWithParameters(
blink::features::kFencedFrames, {{"implementation_type", "mparch"}});
}
FencedFrameTestHelper::~FencedFrameTestHelper() = default;
RenderFrameHost* FencedFrameTestHelper::CreateFencedFrame(
RenderFrameHost* fenced_frame_parent,
const GURL& url,
net::Error expected_error_code) {
TRACE_EVENT("test", "FencedFrameTestHelper::CreateAndGetFencedFrame",
"fenced_frame_parent", fenced_frame_parent, "url", url);
RenderFrameHostImpl* fenced_frame_parent_rfh =
static_cast<RenderFrameHostImpl*>(fenced_frame_parent);
size_t previous_fenced_frame_count =
fenced_frame_parent_rfh->GetFencedFrames().size();
EXPECT_TRUE(ExecJs(fenced_frame_parent_rfh, JsReplace(kAddFencedFrameScript),
EvalJsOptions::EXECUTE_SCRIPT_NO_USER_GESTURE));
std::vector<FencedFrame*> fenced_frames =
fenced_frame_parent_rfh->GetFencedFrames();
EXPECT_EQ(previous_fenced_frame_count + 1, fenced_frames.size());
FencedFrame* fenced_frame = fenced_frames.back();
// It is possible that we got the did stop loading notification because the
// fenced frame was actually being destroyed. Check to make sure that's not
// the case. TODO(crbug.com/1123606): Consider weakly referencing the fenced
// frame if the removal-and-stop-loading scenario is a useful one to test.
EXPECT_EQ(previous_fenced_frame_count + 1,
fenced_frame_parent_rfh->GetFencedFrames().size());
return NavigateFrameInFencedFrameTree(fenced_frame->GetInnerRoot(), url,
expected_error_code);
}
void FencedFrameTestHelper::CreateFencedFrameAsync(
RenderFrameHost* fenced_frame_parent_rfh,
const GURL& url) {
EXPECT_TRUE(ExecJs(fenced_frame_parent_rfh,
JsReplace(kAddAndNavigateFencedFrameScript, url),
EvalJsOptions::EXECUTE_SCRIPT_NO_USER_GESTURE));
}
RenderFrameHost* FencedFrameTestHelper::NavigateFrameInFencedFrameTree(
RenderFrameHost* rfh,
const GURL& url,
net::Error expected_error_code) {
TRACE_EVENT("test", "FencedFrameTestHelper::NavigateFrameInsideFencedFrame",
"rfh", rfh, "url", url);
// TODO(domfarolino): Consider adding |url| to the relevant
// `FencedFrameURLMapping` and then actually passing in the urn:uuid to the
// script below, so that we exercise the "real" navigation path.
FrameTreeNode* target_node =
static_cast<RenderFrameHostImpl*>(rfh)->frame_tree_node();
TestFrameNavigationObserver fenced_frame_observer(rfh);
EXPECT_EQ(url.spec(), EvalJs(rfh, JsReplace(kNavigateFrameScript, url)));
fenced_frame_observer.Wait();
EXPECT_EQ(target_node->current_frame_host()->IsErrorDocument(),
expected_error_code != net::OK);
return target_node->current_frame_host();
}
// static
RenderFrameHost* FencedFrameTestHelper::GetMostRecentlyAddedFencedFrame(
RenderFrameHost* rfh) {
std::vector<FencedFrame*> fenced_frames =
static_cast<RenderFrameHostImpl*>(rfh)->GetFencedFrames();
if (fenced_frames.empty())
return nullptr;
return fenced_frames.back()->GetInnerRoot();
}
GURL CreateFencedFrameURLMapping(RenderFrameHost* rfh, const GURL& url) {
FrameTreeNode* target_node =
static_cast<RenderFrameHostImpl*>(rfh)->frame_tree_node();
FencedFrameURLMapping& url_mapping =
target_node->current_frame_host()->GetPage().fenced_frame_urls_map();
GURL urn_uuid = url_mapping.AddFencedFrameURL(url);
EXPECT_TRUE(urn_uuid.is_valid());
return urn_uuid;
}
} // namespace test
} // namespace content