blob: 2d4650f64972da4504738e401f574bcc61770f73 [file] [log] [blame]
// Copyright 2019 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 <vector>
#include "base/strings/strcat.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/conversions/conversion_manager_impl.h"
#include "content/browser/conversions/storable_impression.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/url_loader_interceptor.h"
#include "content/shell/browser/shell.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace content {
namespace {
constexpr char kBaseDataDir[] = "content/test/data/conversions/";
}
class ConversionsOriginTrialBrowserTestBase : public ContentBrowserTest {
public:
ConversionsOriginTrialBrowserTestBase() = default;
void SetUpOnMainThread() override {
ContentBrowserTest::SetUpOnMainThread();
// We use a URLLoaderInterceptor, rather than the EmbeddedTestServer, since
// the origin trial token in the response is associated with a fixed
// origin, whereas EmbeddedTestServer serves content on a random port.
url_loader_interceptor_ =
std::make_unique<URLLoaderInterceptor>(base::BindLambdaForTesting(
[&](URLLoaderInterceptor::RequestParams* params) -> bool {
URLLoaderInterceptor::WriteResponse(
base::StrCat(
{kBaseDataDir, params->url_request.url.path_piece()}),
params->client.get());
return true;
}));
}
void TearDownOnMainThread() override { url_loader_interceptor_.reset(); }
WebContents* web_contents() { return shell()->web_contents(); }
private:
std::unique_ptr<URLLoaderInterceptor> url_loader_interceptor_;
};
class ConversionsOriginTrialBrowserTest
: public ConversionsOriginTrialBrowserTestBase {
public:
ConversionsOriginTrialBrowserTest() {
feature_list_.InitAndEnableFeature(features::kConversionMeasurement);
}
private:
base::test::ScopedFeatureList feature_list_;
};
IN_PROC_BROWSER_TEST_F(ConversionsOriginTrialBrowserTest,
OriginTrialEnabled_FeatureDetected) {
EXPECT_TRUE(NavigateToURL(
shell(), GURL("https://example.test/impression_with_origin_trial.html")));
EXPECT_EQ(true, EvalJs(shell(),
"document.featurePolicy.features().includes('"
"conversion-measurement')"));
}
IN_PROC_BROWSER_TEST_F(ConversionsOriginTrialBrowserTest,
OriginTrialDisabled_FeatureNotDetected) {
// Navigate to a page without an OT token.
EXPECT_TRUE(NavigateToURL(
shell(), GURL("https://example.test/page_with_impression_creator.html")));
EXPECT_EQ(false, EvalJs(shell(),
"document.featurePolicy.features().includes('"
"conversion-measurement')"));
}
IN_PROC_BROWSER_TEST_F(ConversionsOriginTrialBrowserTest,
OriginTrialEnabled_ImpressionRegistered) {
EXPECT_TRUE(NavigateToURL(
shell(), GURL("https://example.test/impression_with_origin_trial.html")));
EXPECT_TRUE(ExecJs(shell(), R"(
createImpressionTag("link" /* id */,
"https://example.test/page_with_conversion_redirect.html" /* url */,
"1" /* impression data */,
"https://example.test/" /* conversion_destination */);)"));
TestNavigationObserver observer(web_contents());
EXPECT_TRUE(ExecJs(shell(), "simulateClick('link');"));
observer.Wait();
ConversionManagerImpl* conversion_manager =
static_cast<StoragePartitionImpl*>(
BrowserContext::GetDefaultStoragePartition(
web_contents()->GetBrowserContext()))
->GetConversionManager();
base::RunLoop run_loop;
// Verify we have received and logged an impression for the origin trial.
conversion_manager->GetActiveImpressionsForWebUI(base::BindLambdaForTesting(
[&](std::vector<StorableImpression> impressions) -> void {
EXPECT_EQ(1u, impressions.size());
run_loop.Quit();
}));
run_loop.Run();
}
// TODO(johnidel): Add tests that exercise the conversion side logic as well.
// This requires also using an embedded test server because the
// UrlLoadInterceptor cannot properly redirect the conversion pings.
class ConversionsOriginTrialNoBrowserFeatureBrowserTest
: public ConversionsOriginTrialBrowserTestBase {
public:
ConversionsOriginTrialNoBrowserFeatureBrowserTest() {
feature_list_.InitAndDisableFeature(features::kConversionMeasurement);
}
private:
base::test::ScopedFeatureList feature_list_;
};
IN_PROC_BROWSER_TEST_F(ConversionsOriginTrialNoBrowserFeatureBrowserTest,
BrowserSideLogicNotEnabled_FeatureNotDetected) {
EXPECT_TRUE(NavigateToURL(
shell(), GURL("https://example.test/impression_with_origin_trial.html")));
EXPECT_EQ(false, EvalJs(shell(),
"document.featurePolicy.features().includes('"
"conversion-measurement')"));
}
} // namespace content