summaryrefslogtreecommitdiff
path: root/chromium/content/browser/conversions
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/content/browser/conversions
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-chromium-85-based.tar.gz
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/content/browser/conversions')
-rw-r--r--chromium/content/browser/conversions/conversion_host.cc14
-rw-r--r--chromium/content/browser/conversions/conversion_host.h2
-rw-r--r--chromium/content/browser/conversions/conversion_host_unittest.cc35
-rw-r--r--chromium/content/browser/conversions/conversion_manager_impl.cc16
-rw-r--r--chromium/content/browser/conversions/conversion_manager_impl.h10
-rw-r--r--chromium/content/browser/conversions/conversion_manager_impl_unittest.cc10
-rw-r--r--chromium/content/browser/conversions/conversion_registration_browsertest.cc93
-rw-r--r--chromium/content/browser/conversions/conversion_reporter_impl.cc23
-rw-r--r--chromium/content/browser/conversions/conversion_reporter_impl.h5
-rw-r--r--chromium/content/browser/conversions/conversion_reporter_impl_unittest.cc17
-rw-r--r--chromium/content/browser/conversions/conversion_storage.h3
-rw-r--r--chromium/content/browser/conversions/conversion_storage_sql.cc159
-rw-r--r--chromium/content/browser/conversions/conversion_storage_sql.h23
-rw-r--r--chromium/content/browser/conversions/conversion_storage_sql_unittest.cc19
-rw-r--r--chromium/content/browser/conversions/conversion_storage_unittest.cc25
-rw-r--r--chromium/content/browser/conversions/conversion_test_utils.cc5
-rw-r--r--chromium/content/browser/conversions/conversion_test_utils.h11
-rw-r--r--chromium/content/browser/conversions/conversions_browsertest.cc74
-rw-r--r--chromium/content/browser/conversions/conversions_origin_trial_browsertest.cc106
-rw-r--r--chromium/content/browser/conversions/impression_declaration_browsertest.cc118
20 files changed, 657 insertions, 111 deletions
diff --git a/chromium/content/browser/conversions/conversion_host.cc b/chromium/content/browser/conversions/conversion_host.cc
index 0a695271ca4..f20c780d2f8 100644
--- a/chromium/content/browser/conversions/conversion_host.cc
+++ b/chromium/content/browser/conversions/conversion_host.cc
@@ -17,8 +17,12 @@
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_client.h"
#include "mojo/public/cpp/bindings/message.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
@@ -150,6 +154,11 @@ void ConversionHost::DidFinishNavigation(NavigationHandle* navigation_handle) {
return;
}
+ if (!GetContentClient()->browser()->AllowConversionMeasurement(
+ web_contents()->GetBrowserContext())) {
+ return;
+ }
+
// Convert |impression| into a StorableImpression that can be forwarded to
// storage. If a reporting origin was not provided, default to the conversion
// destination for reporting.
@@ -208,6 +217,11 @@ void ConversionHost::RegisterConversion(
return;
}
+ if (!GetContentClient()->browser()->AllowConversionMeasurement(
+ web_contents()->GetBrowserContext())) {
+ return;
+ }
+
StorableConversion storable_conversion(
conversion_manager->GetConversionPolicy().GetSanitizedConversionData(
conversion->conversion_data),
diff --git a/chromium/content/browser/conversions/conversion_host.h b/chromium/content/browser/conversions/conversion_host.h
index 169c08a8042..8f004115658 100644
--- a/chromium/content/browser/conversions/conversion_host.h
+++ b/chromium/content/browser/conversions/conversion_host.h
@@ -46,6 +46,8 @@ class CONTENT_EXPORT ConversionHost : public WebContentsObserver,
FRIEND_TEST_ALL_PREFIXES(ConversionHostTest, PerPageConversionMetrics);
FRIEND_TEST_ALL_PREFIXES(ConversionHostTest,
NoManager_NoPerPageConversionMetrics);
+ FRIEND_TEST_ALL_PREFIXES(ConversionHostTest,
+ ValidConversionWithEmbedderDisable_NoConversion);
ConversionHost(
WebContents* web_contents,
diff --git a/chromium/content/browser/conversions/conversion_host_unittest.cc b/chromium/content/browser/conversions/conversion_host_unittest.cc
index 2769ef893d8..644ff248b09 100644
--- a/chromium/content/browser/conversions/conversion_host_unittest.cc
+++ b/chromium/content/browser/conversions/conversion_host_unittest.cc
@@ -11,6 +11,7 @@
#include "content/browser/conversions/conversion_manager.h"
#include "content/browser/conversions/conversion_test_utils.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/test/test_renderer_host.h"
#include "content/test/fake_mojo_message_dispatch_context.h"
@@ -149,6 +150,40 @@ TEST_F(ConversionHostTest, ValidConversion_NoBadMessage) {
EXPECT_EQ(1u, test_manager_.num_conversions());
}
+TEST_F(ConversionHostTest, ValidConversionWithEmbedderDisable_NoConversion) {
+ ConversionDisallowingContentBrowserClient disallowed_browser_client;
+ ContentBrowserClient* old_browser_client =
+ SetBrowserClientForTesting(&disallowed_browser_client);
+
+ // Create a page with a secure origin.
+ contents()->NavigateAndCommit(GURL("https://www.example.com"));
+ conversion_host()->SetCurrentTargetFrameForTesting(main_rfh());
+
+ blink::mojom::ConversionPtr conversion = blink::mojom::Conversion::New();
+ conversion->reporting_origin =
+ url::Origin::Create(GURL("https://secure.com"));
+ conversion_host()->RegisterConversion(std::move(conversion));
+
+ EXPECT_EQ(0u, test_manager_.num_conversions());
+ SetBrowserClientForTesting(old_browser_client);
+}
+
+TEST_F(ConversionHostTest, ValidImpressionWithEmbedderDisable_NoImpression) {
+ ConversionDisallowingContentBrowserClient disallowed_browser_client;
+ ContentBrowserClient* old_browser_client =
+ SetBrowserClientForTesting(&disallowed_browser_client);
+
+ contents()->NavigateAndCommit(GURL("https://secure_impression.com"));
+ auto navigation = NavigationSimulatorImpl::CreateRendererInitiated(
+ GURL(kConversionUrl), main_rfh());
+ navigation->SetInitiatorFrame(main_rfh());
+ navigation->set_impression(CreateValidImpression());
+ navigation->Commit();
+
+ EXPECT_EQ(0u, test_manager_.num_impressions());
+ SetBrowserClientForTesting(old_browser_client);
+}
+
TEST_F(ConversionHostTest, PerPageConversionMetrics) {
base::HistogramTester histograms;
diff --git a/chromium/content/browser/conversions/conversion_manager_impl.cc b/chromium/content/browser/conversions/conversion_manager_impl.cc
index 4f3f9ca7e5a..7ef0173fbd5 100644
--- a/chromium/content/browser/conversions/conversion_manager_impl.cc
+++ b/chromium/content/browser/conversions/conversion_manager_impl.cc
@@ -35,6 +35,11 @@ ConversionManager* ConversionManagerProviderImpl::GetManager(
}
// static
+void ConversionManagerImpl::RunInMemoryForTesting() {
+ ConversionStorageSql::RunInMemoryForTesting();
+}
+
+// static
std::unique_ptr<ConversionManagerImpl> ConversionManagerImpl::CreateForTesting(
std::unique_ptr<ConversionReporter> reporter,
std::unique_ptr<ConversionPolicy> policy,
@@ -93,9 +98,6 @@ ConversionManagerImpl::~ConversionManagerImpl() = default;
void ConversionManagerImpl::HandleImpression(
const StorableImpression& impression) {
- if (!storage_)
- return;
-
// Add the impression to storage.
storage_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&ConversionStorage::StoreImpression,
@@ -104,9 +106,6 @@ void ConversionManagerImpl::HandleImpression(
void ConversionManagerImpl::HandleConversion(
const StorableConversion& conversion) {
- if (!storage_)
- return;
-
// TODO(https://crbug.com/1043345): Add UMA for the number of conversions we
// are logging to storage, and the number of new reports logged to storage.
// Unretained is safe because any task to delete |storage_| will be posted
@@ -166,8 +165,11 @@ void ConversionManagerImpl::ClearData(
}
void ConversionManagerImpl::OnInitCompleted(bool success) {
+ // The storage layer is robust to initialization failures, so ignore the case
+ // where it failed to setup.
if (!success) {
- storage_.reset();
+ // TODO(https://crbug.com/1099812): Log metrics on storage initialization
+ // success.
return;
}
diff --git a/chromium/content/browser/conversions/conversion_manager_impl.h b/chromium/content/browser/conversions/conversion_manager_impl.h
index 03bcd94688f..a7357b5bb98 100644
--- a/chromium/content/browser/conversions/conversion_manager_impl.h
+++ b/chromium/content/browser/conversions/conversion_manager_impl.h
@@ -64,6 +64,10 @@ class CONTENT_EXPORT ConversionManagerImpl : public ConversionManager {
base::RepeatingCallback<void(int64_t)> report_sent_callback) = 0;
};
+ // Configures underlying storage to be setup in memory, rather than on
+ // disk. This speeds up initialization to avoid timeouts in test environments.
+ static void RunInMemoryForTesting();
+
static std::unique_ptr<ConversionManagerImpl> CreateForTesting(
std::unique_ptr<ConversionReporter> reporter,
std::unique_ptr<ConversionPolicy> policy,
@@ -72,6 +76,9 @@ class CONTENT_EXPORT ConversionManagerImpl : public ConversionManager {
scoped_refptr<base::SequencedTaskRunner> storage_task_runner);
// |storage_task_runner| should run with base::TaskPriority::BEST_EFFORT.
+ // TODO(https://crbug.com/1080764): The storage task runner is instead run
+ // with base::TaskPriority::USER_VISIBLE to address some timeouts.
+ // Documentation should be updated.
ConversionManagerImpl(
StoragePartition* storage_partition,
const base::FilePath& user_data_directory,
@@ -162,8 +169,7 @@ class CONTENT_EXPORT ConversionManagerImpl : public ConversionManager {
// ConversionStorage instance which is scoped to lifetime of
// |storage_task_runner_|. |storage_| should be accessed by calling
// base::PostTask with |storage_task_runner_|, and should not be accessed
- // directly. |storage_| can be null if the storage initialization did not
- // succeed.
+ // directly. |storage_| should never be nullptr.
//
// TODO(https://crbug.com/1066920): This should use base::SequenceBound to
// avoid having to call PostTask manually, as well as use base::Unretained on
diff --git a/chromium/content/browser/conversions/conversion_manager_impl_unittest.cc b/chromium/content/browser/conversions/conversion_manager_impl_unittest.cc
index 3ca019fd0d1..03e6245f9f8 100644
--- a/chromium/content/browser/conversions/conversion_manager_impl_unittest.cc
+++ b/chromium/content/browser/conversions/conversion_manager_impl_unittest.cc
@@ -18,6 +18,7 @@
#include "base/test/bind_test_util.h"
#include "base/time/clock.h"
#include "base/time/time.h"
+#include "build/build_config.h"
#include "content/browser/conversions/conversion_report.h"
#include "content/browser/conversions/conversion_test_utils.h"
#include "content/browser/conversions/storable_conversion.h"
@@ -313,7 +314,14 @@ TEST_F(ConversionManagerImplTest, ConversionsSentFromUI_ReportedImmediately) {
EXPECT_EQ(2u, test_reporter_->num_reports());
}
-TEST_F(ConversionManagerImplTest, ExpiredReportsAtStartup_Delayed) {
+// TODO(crbug.com/1088449): Flaky on Linux and Android.
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+#define MAYBE_ExpiredReportsAtStartup_Delayed \
+ DISABLED_ExpiredReportsAtStartup_Delayed
+#else
+#define MAYBE_ExpiredReportsAtStartup_Delayed ExpiredReportsAtStartup_Delayed
+#endif
+TEST_F(ConversionManagerImplTest, MAYBE_ExpiredReportsAtStartup_Delayed) {
// Create a report that will be reported at t= 2 days.
base::Time start_time = clock().Now();
conversion_manager_->HandleImpression(
diff --git a/chromium/content/browser/conversions/conversion_registration_browsertest.cc b/chromium/content/browser/conversions/conversion_registration_browsertest.cc
index 8b6fce9261d..b0251de1802 100644
--- a/chromium/content/browser/conversions/conversion_registration_browsertest.cc
+++ b/chromium/content/browser/conversions/conversion_registration_browsertest.cc
@@ -8,8 +8,10 @@
#include "base/bind.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/conversions/conversion_host.h"
+#include "content/browser/conversions/conversion_manager_impl.h"
#include "content/browser/web_contents/web_contents_impl.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"
@@ -75,9 +77,10 @@ class TestConversionHost : public ConversionHost {
base::RunLoop conversion_waiter_;
};
-class ConversionRegistrationBrowserTest : public ContentBrowserTest {
+class ConversionDisabledBrowserTest : public ContentBrowserTest {
public:
- ConversionRegistrationBrowserTest() {
+ ConversionDisabledBrowserTest() {
+ ConversionManagerImpl::RunInMemoryForTesting();
feature_list_.InitAndEnableFeature(features::kConversionMeasurement);
}
@@ -102,15 +105,41 @@ class ConversionRegistrationBrowserTest : public ContentBrowserTest {
net::EmbeddedTestServer* https_server() { return https_server_.get(); }
- private:
+ protected:
base::test::ScopedFeatureList feature_list_;
+
+ private:
std::unique_ptr<net::EmbeddedTestServer> https_server_;
};
+IN_PROC_BROWSER_TEST_F(
+ ConversionDisabledBrowserTest,
+ ConversionRegisteredWithoutOTEnabled_NoConversionDataReceived) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(),
+ embedded_test_server()->GetURL("/page_with_conversion_redirect.html")));
+ std::unique_ptr<TestConversionHost> host =
+ TestConversionHost::ReplaceAndGetConversionHost(web_contents());
+
+ EXPECT_TRUE(ExecJs(web_contents(), "registerConversion(123)"));
+
+ EXPECT_TRUE(NavigateToURL(shell(), GURL("about:blank")));
+ EXPECT_EQ(0u, host->num_conversions());
+}
+
+class ConversionRegistrationBrowserTest : public ConversionDisabledBrowserTest {
+ public:
+ ConversionRegistrationBrowserTest() = default;
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ // Sets up the blink runtime feature for ConversionMeasurement.
+ command_line->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+ }
+};
+
// Test that full conversion path does not cause any failure when a conversion
// registration mojo is received.
-// TODO(johnidel): This should really be testing internals of ConversionHost.
-// That is trivial when reporting for conversions is added.
IN_PROC_BROWSER_TEST_F(ConversionRegistrationBrowserTest,
ConversionRegistration_NoCrash) {
EXPECT_TRUE(NavigateToURL(
@@ -180,6 +209,60 @@ IN_PROC_BROWSER_TEST_F(ConversionRegistrationBrowserTest,
EXPECT_EQ(0u, host->num_conversions());
}
+IN_PROC_BROWSER_TEST_F(
+ ConversionRegistrationBrowserTest,
+ ConversionRegistrationNotSameOriginRedirect_NotReceived) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(),
+ https_server()->GetURL("c.test", "/page_with_conversion_redirect.html")));
+ std::unique_ptr<TestConversionHost> host =
+ TestConversionHost::ReplaceAndGetConversionHost(web_contents());
+
+ // Create a url that does the following redirect chain b.test ->
+ // a.test/.well-known/...; this conversion registration should not be allowed,
+ // a.test did not initiate the redirect to the reporting endpoint.
+ GURL redirect_url = https_server()->GetURL(
+ "a.test", "/" + kWellKnownUrl + "?conversion-data=200");
+ GURL registration_url = https_server()->GetURL(
+ "b.test", "/server-redirect?" + redirect_url.spec());
+
+ // Create a load observer that will wait for the redirect to complete. If a
+ // conversion was registered, this redirect would never complete.
+ ResourceLoadObserver load_observer(shell());
+ EXPECT_TRUE(ExecJs(web_contents(),
+ JsReplace("createTrackingPixel($1);", registration_url)));
+ load_observer.WaitForResourceCompletion(registration_url);
+
+ // Conversion mojo messages are sent on the same message pipe as navigation
+ // messages. Because the conversion would have been sequenced prior to the
+ // navigation message, it would be observed before the NavigateToURL() call
+ // finishes.
+ EXPECT_TRUE(NavigateToURL(shell(), GURL("about:blank")));
+ EXPECT_EQ(0u, host->num_conversions());
+}
+
+IN_PROC_BROWSER_TEST_F(ConversionRegistrationBrowserTest,
+ ConversionRegistrationIsSameOriginRedirect_Received) {
+ EXPECT_TRUE(NavigateToURL(
+ shell(),
+ https_server()->GetURL("c.test", "/page_with_conversion_redirect.html")));
+ std::unique_ptr<TestConversionHost> host =
+ TestConversionHost::ReplaceAndGetConversionHost(web_contents());
+
+ // Create a url that does the following redirect chain b.test -> a.test ->
+ // a.test/.well-known/...; this conversion registration should be allowed.
+ GURL well_known_url = https_server()->GetURL(
+ "a.test", "/" + kWellKnownUrl + "?conversion-data=200");
+ GURL redirect_url = https_server()->GetURL(
+ "a.test", "/server-redirect?" + well_known_url.spec());
+ GURL registration_url = https_server()->GetURL(
+ "b.test", "/server-redirect?" + redirect_url.spec());
+
+ EXPECT_TRUE(ExecJs(web_contents(),
+ JsReplace("createTrackingPixel($1);", registration_url)));
+ EXPECT_EQ(200UL, host->WaitForNumConversions(1));
+}
+
IN_PROC_BROWSER_TEST_F(ConversionRegistrationBrowserTest,
ConversionRegistrationInPreload_NotReceived) {
std::unique_ptr<TestConversionHost> host =
diff --git a/chromium/content/browser/conversions/conversion_reporter_impl.cc b/chromium/content/browser/conversions/conversion_reporter_impl.cc
index 3011e2efc51..76797a44d71 100644
--- a/chromium/content/browser/conversions/conversion_reporter_impl.cc
+++ b/chromium/content/browser/conversions/conversion_reporter_impl.cc
@@ -10,6 +10,9 @@
#include "base/time/clock.h"
#include "content/browser/conversions/conversion_manager.h"
#include "content/browser/conversions/conversion_network_sender_impl.h"
+#include "content/browser/storage_partition_impl.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
namespace content {
@@ -17,6 +20,7 @@ ConversionReporterImpl::ConversionReporterImpl(
StoragePartition* storage_partition,
const base::Clock* clock)
: clock_(clock),
+ partition_(static_cast<StoragePartitionImpl*>(storage_partition)),
network_sender_(
std::make_unique<ConversionNetworkSenderImpl>(storage_partition)) {}
@@ -60,11 +64,20 @@ void ConversionReporterImpl::SendNextReport() {
// Send the next report and remove it from the queue. Bind the conversion id
// to the sent callback so we know which conversion report has finished
// sending.
- network_sender_->SendReport(
- report_queue_.top().get(),
- base::BindOnce(&ConversionReporterImpl::OnReportSent,
- base::Unretained(this),
- *report_queue_.top()->conversion_id));
+ if (GetContentClient()->browser()->AllowConversionMeasurement(
+ partition_->browser_context())) {
+ network_sender_->SendReport(
+ report_queue_.top().get(),
+ base::BindOnce(&ConversionReporterImpl::OnReportSent,
+ base::Unretained(this),
+ *report_queue_.top()->conversion_id));
+ } else {
+ // If measurement is disallowed, just drop the report on the floor. We need
+ // to make sure we forward that the report was "sent" to ensure it is
+ // deleted from storage, etc. This simulate sending the report through a
+ // null channel.
+ OnReportSent(*report_queue_.top()->conversion_id);
+ }
report_queue_.pop();
MaybeScheduleNextReport();
}
diff --git a/chromium/content/browser/conversions/conversion_reporter_impl.h b/chromium/content/browser/conversions/conversion_reporter_impl.h
index 855a2b3a4f4..d1ba6c77acb 100644
--- a/chromium/content/browser/conversions/conversion_reporter_impl.h
+++ b/chromium/content/browser/conversions/conversion_reporter_impl.h
@@ -26,6 +26,7 @@ class Clock;
namespace content {
class StoragePartition;
+class StoragePartitionImpl;
// This class is responsible for managing the dispatch of conversion reports to
// a ConversionReporterImpl::NetworkSender. It maintains a queue of reports and
@@ -96,6 +97,10 @@ class CONTENT_EXPORT ConversionReporterImpl
const base::Clock* clock_;
+ // Should never be nullptr, since StoragePartition owns the ConversionManager
+ // which owns |this|.
+ StoragePartitionImpl* partition_;
+
// Timer which signals the next report in |report_queue_| should be sent.
base::OneShotTimer send_report_timer_;
diff --git a/chromium/content/browser/conversions/conversion_reporter_impl_unittest.cc b/chromium/content/browser/conversions/conversion_reporter_impl_unittest.cc
index a2b030ed8f6..d9e40dece4d 100644
--- a/chromium/content/browser/conversions/conversion_reporter_impl_unittest.cc
+++ b/chromium/content/browser/conversions/conversion_reporter_impl_unittest.cc
@@ -16,6 +16,7 @@
#include "content/browser/conversions/conversion_test_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/storage_partition.h"
+#include "content/public/common/content_client.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -200,4 +201,20 @@ TEST_F(ConversionReporterImplTest, ManyReportsAddedSeparately_SentInOrder) {
}
}
+TEST_F(ConversionReporterImplTest, EmbedderDisallowsConversions_ReportNotSent) {
+ ConversionDisallowingContentBrowserClient disallowed_browser_client;
+ ContentBrowserClient* old_browser_client =
+ SetBrowserClientForTesting(&disallowed_browser_client);
+ reporter_->AddReportsToQueue({GetReport(clock().Now(), /*conversion_id=*/1)},
+ base::BindRepeating([](int64_t conversion_id) {
+ EXPECT_EQ(1L, conversion_id);
+ }));
+
+ // Fast forward by 0, as we yield the thread when a report is scheduled to be
+ // sent.
+ task_environment_.FastForwardBy(base::TimeDelta());
+ EXPECT_EQ(0u, sender_->num_reports_sent());
+ SetBrowserClientForTesting(old_browser_client);
+}
+
} // namespace content
diff --git a/chromium/content/browser/conversions/conversion_storage.h b/chromium/content/browser/conversions/conversion_storage.h
index 1c8feed1ccf..3d999f3179d 100644
--- a/chromium/content/browser/conversions/conversion_storage.h
+++ b/chromium/content/browser/conversions/conversion_storage.h
@@ -61,6 +61,9 @@ class ConversionStorage {
};
virtual ~ConversionStorage() = default;
+ // When adding a new method, also add it to
+ // ConversionStorageTest.StorageUsedAfterFailedInitilization_FailsSilently.
+
// Initializes the storage. Returns true on success, otherwise the storage
// should not be used.
virtual bool Initialize() = 0;
diff --git a/chromium/content/browser/conversions/conversion_storage_sql.cc b/chromium/content/browser/conversions/conversion_storage_sql.cc
index a921f883991..80604e1ca3d 100644
--- a/chromium/content/browser/conversions/conversion_storage_sql.cc
+++ b/chromium/content/browser/conversions/conversion_storage_sql.cc
@@ -26,9 +26,6 @@ namespace content {
namespace {
-const base::FilePath::CharType kDatabaseName[] =
- FILE_PATH_LITERAL("Conversions");
-
std::string SerializeOrigin(const url::Origin& origin) {
// Conversion API is only designed to be used for secure
// contexts (targets and reporting endpoints). We should have filtered out bad
@@ -50,13 +47,28 @@ base::Time DeserializeTime(int64_t microseconds) {
base::TimeDelta::FromMicroseconds(microseconds));
}
+const base::FilePath::CharType kInMemoryPath[] = FILE_PATH_LITERAL(":memory");
+
+const base::FilePath::CharType kDatabasePath[] =
+ FILE_PATH_LITERAL("Conversions");
+
} // namespace
+// static
+void ConversionStorageSql::RunInMemoryForTesting() {
+ g_run_in_memory_ = true;
+}
+
+// static
+bool ConversionStorageSql::g_run_in_memory_ = false;
+
ConversionStorageSql::ConversionStorageSql(
- const base::FilePath& path_to_database_dir,
+ const base::FilePath& path_to_database,
std::unique_ptr<Delegate> delegate,
const base::Clock* clock)
- : path_to_database_(path_to_database_dir.Append(kDatabaseName)),
+ : path_to_database_(g_run_in_memory_
+ ? base::FilePath(kInMemoryPath)
+ : path_to_database.Append(kDatabasePath)),
clock_(clock),
delegate_(std::move(delegate)),
weak_factory_(this) {
@@ -71,22 +83,37 @@ ConversionStorageSql::~ConversionStorageSql() {
bool ConversionStorageSql::Initialize() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- db_.set_histogram_tag("Conversions");
+ db_ = std::make_unique<sql::Database>();
+ db_->set_histogram_tag("Conversions");
// Supply this callback with a weak_ptr to avoid calling the error callback
// after |this| has been deleted.
- db_.set_error_callback(
+ db_->set_error_callback(
base::BindRepeating(&ConversionStorageSql::DatabaseErrorCallback,
weak_factory_.GetWeakPtr()));
- db_.set_page_size(4096);
- db_.set_cache_size(32);
- db_.set_exclusive_locking();
- return db_.Open(path_to_database_) && InitializeSchema();
+ db_->set_page_size(4096);
+ db_->set_cache_size(32);
+ db_->set_exclusive_locking();
+
+ bool opened = (path_to_database_.value() == kInMemoryPath)
+ ? db_->OpenInMemory()
+ : db_->Open(path_to_database_);
+
+ if (!opened || !InitializeSchema()) {
+ db_.reset();
+ db_is_open_ = false;
+ return false;
+ }
+
+ db_is_open_ = true;
+ return true;
}
void ConversionStorageSql::StoreImpression(
const StorableImpression& impression) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!db_is_open_)
+ return;
// Cleanup any impression that may be expired by this point. This is done when
// an impression is added to prevent additional logic for cleaning the table
@@ -104,7 +131,7 @@ void ConversionStorageSql::StoreImpression(
// Wrap the deactivation and insertion in the same transaction. If the
// deactivation fails, we do not want to store the new impression as we may
// return the wrong set of impressions for a conversion.
- sql::Transaction transaction(&db_);
+ sql::Transaction transaction(db_.get());
if (!transaction.Begin())
return;
@@ -120,7 +147,7 @@ void ConversionStorageSql::StoreImpression(
"UPDATE impressions SET active = 0 "
"WHERE conversion_origin = ? AND reporting_origin = ? AND "
"active = 1 AND num_conversions > 0";
- sql::Statement deactivate_statement(db_.GetCachedStatement(
+ sql::Statement deactivate_statement(db_->GetCachedStatement(
SQL_FROM_HERE, kDeactivateMatchingConvertedImpressionsSql));
deactivate_statement.BindString(0, serialized_conversion_origin);
deactivate_statement.BindString(1, serialized_reporting_origin);
@@ -132,7 +159,7 @@ void ConversionStorageSql::StoreImpression(
"reporting_origin, impression_time, expiry_time) "
"VALUES (?,?,?,?,?,?)";
sql::Statement statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kInsertImpressionSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kInsertImpressionSql));
statement.BindString(0, impression.impression_data());
statement.BindString(1, serialized_impression_origin);
statement.BindString(2, serialized_conversion_origin);
@@ -147,6 +174,8 @@ void ConversionStorageSql::StoreImpression(
int ConversionStorageSql::MaybeCreateAndStoreConversionReports(
const StorableConversion& conversion) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!db_is_open_)
+ return 0;
const url::Origin& conversion_origin = conversion.conversion_origin();
const std::string serialized_conversion_origin =
@@ -171,7 +200,7 @@ int ConversionStorageSql::MaybeCreateAndStoreConversionReports(
"ORDER BY impression_time DESC";
sql::Statement statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kGetMatchingImpressionsSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kGetMatchingImpressionsSql));
statement.BindString(0, serialized_conversion_origin);
statement.BindString(1, SerializeOrigin(reporting_origin));
statement.BindInt64(2, serialized_current_time);
@@ -212,7 +241,7 @@ int ConversionStorageSql::MaybeCreateAndStoreConversionReports(
if (new_reports.empty())
return 0;
- sql::Transaction transaction(&db_);
+ sql::Transaction transaction(db_.get());
if (!transaction.Begin())
return 0;
@@ -221,7 +250,7 @@ int ConversionStorageSql::MaybeCreateAndStoreConversionReports(
"(impression_id, conversion_data, conversion_time, report_time, "
"attribution_credit) VALUES(?,?,?,?,?)";
sql::Statement store_conversion_statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kStoreConversionSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kStoreConversionSql));
// Mark impressions inactive if they hit the max conversions allowed limit
// supplied by the delegate. Because only active impressions log conversions,
@@ -233,8 +262,8 @@ int ConversionStorageSql::MaybeCreateAndStoreConversionReports(
"UPDATE impressions SET num_conversions = num_conversions + 1, "
"active = num_conversions < ? "
"WHERE impression_id = ?";
- sql::Statement impression_update_statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kUpdateImpressionForConversionSql));
+ sql::Statement impression_update_statement(db_->GetCachedStatement(
+ SQL_FROM_HERE, kUpdateImpressionForConversionSql));
// Subtract one from the max number of conversions per the query comment
// above. We need to account for the new conversion in this comparison so we
@@ -270,6 +299,8 @@ int ConversionStorageSql::MaybeCreateAndStoreConversionReports(
std::vector<ConversionReport> ConversionStorageSql::GetConversionsToReport(
base::Time max_report_time) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!db_is_open_)
+ return {};
// Get all entries in the conversions table with a |report_time| less than
// |expired_at| and their matching information from the impression table.
@@ -281,7 +312,7 @@ std::vector<ConversionReport> ConversionStorageSql::GetConversionsToReport(
"FROM conversions C JOIN impressions I ON "
"C.impression_id = I.impression_id WHERE C.report_time <= ?";
sql::Statement statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kGetExpiredConversionsSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kGetExpiredConversionsSql));
statement.BindInt64(0, SerializeTime(max_report_time));
std::vector<ConversionReport> conversions;
@@ -328,12 +359,16 @@ std::vector<ConversionReport> ConversionStorageSql::GetConversionsToReport(
}
std::vector<StorableImpression> ConversionStorageSql::GetActiveImpressions() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!db_is_open_)
+ return {};
+
const char kGetImpressionsSql[] =
"SELECT impression_data, impression_origin, conversion_origin, "
"reporting_origin, impression_time, expiry_time, impression_id "
"FROM impressions WHERE active = 1 AND expiry_time > ?";
sql::Statement statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kGetImpressionsSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kGetImpressionsSql));
statement.BindInt64(0, SerializeTime(clock_->Now()));
std::vector<StorableImpression> impressions;
@@ -359,17 +394,21 @@ std::vector<StorableImpression> ConversionStorageSql::GetActiveImpressions() {
}
int ConversionStorageSql::DeleteExpiredImpressions() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!db_is_open_)
+ return 0;
+
// Delete all impressions that have no associated conversions and are past
// their expiry time. Optimized by |kImpressionExpiryIndexSql|.
const char kDeleteExpiredImpressionsSql[] =
"DELETE FROM impressions WHERE expiry_time <= ? AND "
"impression_id NOT IN (SELECT impression_id FROM conversions)";
sql::Statement delete_expired_statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kDeleteExpiredImpressionsSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kDeleteExpiredImpressionsSql));
delete_expired_statement.BindInt64(0, SerializeTime(clock_->Now()));
if (!delete_expired_statement.Run())
return 0;
- int change_count = db_.GetLastChangeCount();
+ int change_count = db_->GetLastChangeCount();
// Delete all impressions that have no associated conversions and are
// inactive. This is done in a separate statement from
@@ -379,31 +418,39 @@ int ConversionStorageSql::DeleteExpiredImpressions() {
"DELETE FROM impressions WHERE active = 0 AND "
"impression_id NOT IN (SELECT impression_id FROM conversions)";
sql::Statement delete_inactive_statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kDeleteInactiveImpressionsSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kDeleteInactiveImpressionsSql));
if (!delete_inactive_statement.Run())
return change_count;
- return change_count + db_.GetLastChangeCount();
+ return change_count + db_->GetLastChangeCount();
}
bool ConversionStorageSql::DeleteConversion(int64_t conversion_id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!db_is_open_)
+ return false;
+
// Delete the row identified by |conversion_id|.
const char kDeleteSentConversionSql[] =
"DELETE FROM conversions WHERE conversion_id = ?";
sql::Statement statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kDeleteSentConversionSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kDeleteSentConversionSql));
statement.BindInt64(0, conversion_id);
if (!statement.Run())
return false;
- return db_.GetLastChangeCount() > 0;
+ return db_->GetLastChangeCount() > 0;
}
void ConversionStorageSql::ClearData(
base::Time delete_begin,
base::Time delete_end,
base::RepeatingCallback<bool(const url::Origin&)> filter) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!db_is_open_)
+ return;
+
SCOPED_UMA_HISTOGRAM_TIMER("Conversions.ClearDataTime");
if (filter.is_null()) {
ClearAllDataInRange(delete_begin, delete_end);
@@ -422,7 +469,7 @@ void ConversionStorageSql::ClearData(
"(I.impression_time BETWEEN ?1 AND ?2) OR"
"(C.conversion_time BETWEEN ?1 AND ?2)";
sql::Statement statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kScanCandidateData));
+ db_->GetCachedStatement(SQL_FROM_HERE, kScanCandidateData));
statement.BindInt64(0, SerializeTime(delete_begin));
statement.BindInt64(1, SerializeTime(delete_end));
@@ -455,7 +502,7 @@ void ConversionStorageSql::ClearData(
// Delete the data in a transaction to avoid cases where the impression part
// of a conversion is deleted without deleting the associated conversion, or
// vice versa.
- sql::Transaction transaction(&db_);
+ sql::Transaction transaction(db_.get());
if (!transaction.Begin())
return;
@@ -463,7 +510,7 @@ void ConversionStorageSql::ClearData(
const char kDeleteImpressionSql[] =
"DELETE FROM impressions WHERE impression_id = ?";
sql::Statement impression_statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kDeleteImpressionSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kDeleteImpressionSql));
impression_statement.BindInt64(0, impression_id);
if (!impression_statement.Run())
return;
@@ -473,7 +520,7 @@ void ConversionStorageSql::ClearData(
const char kDeleteConversionSql[] =
"DELETE FROM conversions WHERE conversion_id = ?";
sql::Statement conversion_statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kDeleteConversionSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kDeleteConversionSql));
conversion_statement.BindInt64(0, conversion_id);
if (!conversion_statement.Run())
return;
@@ -489,7 +536,7 @@ void ConversionStorageSql::ClearData(
const char kDeleteVestigialConversionSql[] =
"DELETE FROM conversions WHERE impression_id = ?";
sql::Statement delete_vestigial_statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kDeleteVestigialConversionSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kDeleteVestigialConversionSql));
delete_vestigial_statement.BindInt64(0, impression_id);
if (!delete_vestigial_statement.Run())
return;
@@ -508,7 +555,7 @@ void ConversionStorageSql::ClearAllDataInRange(base::Time delete_begin,
return;
}
- sql::Transaction transaction(&db_);
+ sql::Transaction transaction(db_.get());
if (!transaction.Begin())
return;
@@ -524,7 +571,7 @@ void ConversionStorageSql::ClearAllDataInRange(base::Time delete_begin,
"impression_id in (SELECT impression_id FROM conversions "
"WHERE conversion_time BETWEEN ?1 AND ?2)";
sql::Statement delete_impressions_statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kDeleteImpressionRangeSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kDeleteImpressionRangeSql));
delete_impressions_statement.BindInt64(0, SerializeTime(delete_begin));
delete_impressions_statement.BindInt64(1, SerializeTime(delete_end));
if (!delete_impressions_statement.Run())
@@ -534,7 +581,7 @@ void ConversionStorageSql::ClearAllDataInRange(base::Time delete_begin,
"DELETE FROM conversions WHERE (conversion_time BETWEEN ? AND ?) "
"OR impression_id NOT IN (SELECT impression_id FROM impressions)";
sql::Statement delete_conversions_statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kDeleteConversionRangeSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kDeleteConversionRangeSql));
delete_conversions_statement.BindInt64(0, SerializeTime(delete_begin));
delete_conversions_statement.BindInt64(1, SerializeTime(delete_end));
if (!delete_conversions_statement.Run())
@@ -543,15 +590,15 @@ void ConversionStorageSql::ClearAllDataInRange(base::Time delete_begin,
}
void ConversionStorageSql::ClearAllDataAllTime() {
- sql::Transaction transaction(&db_);
+ sql::Transaction transaction(db_.get());
if (!transaction.Begin())
return;
const char kDeleteAllConversionsSql[] = "DELETE FROM conversions";
const char kDeleteAllImpressionsSql[] = "DELETE FROM impressions";
sql::Statement delete_all_conversions_statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kDeleteAllConversionsSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kDeleteAllConversionsSql));
sql::Statement delete_all_impressions_statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kDeleteAllImpressionsSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kDeleteAllImpressionsSql));
if (!delete_all_conversions_statement.Run())
return;
if (!delete_all_impressions_statement.Run())
@@ -566,7 +613,7 @@ bool ConversionStorageSql::HasCapacityForStoringImpression(
"SELECT COUNT(impression_origin) FROM impressions WHERE "
"impression_origin = ?";
sql::Statement statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kCountImpressionsSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kCountImpressionsSql));
statement.BindString(0, serialized_origin);
if (!statement.Step())
return false;
@@ -588,7 +635,7 @@ bool ConversionStorageSql::HasCapacityForStoringConversion(
" I.impression_id = C.impression_id"
" WHERE I.conversion_origin = ? AND (active BETWEEN 0 AND 1)";
sql::Statement statement(
- db_.GetCachedStatement(SQL_FROM_HERE, kCountConversionsSql));
+ db_->GetCachedStatement(SQL_FROM_HERE, kCountConversionsSql));
statement.BindString(0, serialized_origin);
if (!statement.Step())
return false;
@@ -629,7 +676,7 @@ bool ConversionStorageSql::InitializeSchema() {
" expiry_time INTEGER NOT NULL,"
" num_conversions INTEGER DEFAULT 0,"
" active INTEGER DEFAULT 1)";
- if (!db_.Execute(kImpressionTableSql))
+ if (!db_->Execute(kImpressionTableSql))
return false;
// Optimizes impression lookup by conversion/reporting origin during calls to
@@ -640,7 +687,7 @@ bool ConversionStorageSql::InitializeSchema() {
const char kConversionUrlIndexSql[] =
"CREATE INDEX IF NOT EXISTS conversion_origin_idx "
"ON impressions(active, conversion_origin, reporting_origin)";
- if (!db_.Execute(kConversionUrlIndexSql))
+ if (!db_->Execute(kConversionUrlIndexSql))
return false;
// Optimizes calls to DeleteExpiredImpressions() and
@@ -650,14 +697,14 @@ bool ConversionStorageSql::InitializeSchema() {
const char kImpressionExpiryIndexSql[] =
"CREATE INDEX IF NOT EXISTS impression_expiry_idx "
"ON impressions(expiry_time)";
- if (!db_.Execute(kImpressionExpiryIndexSql))
+ if (!db_->Execute(kImpressionExpiryIndexSql))
return false;
// Optimizes counting impressions by impression origin.
const char kImpressionOriginIndexSql[] =
"CREATE INDEX IF NOT EXISTS impression_origin_idx "
"ON impressions(impression_origin)";
- if (!db_.Execute(kImpressionOriginIndexSql))
+ if (!db_->Execute(kImpressionOriginIndexSql))
return false;
// All columns in this table are const. |impression_id| is the primary key of
@@ -675,7 +722,7 @@ bool ConversionStorageSql::InitializeSchema() {
" conversion_time INTEGER NOT NULL,"
" report_time INTEGER NOT NULL,"
" attribution_credit INTEGER NOT NULL)";
- if (!db_.Execute(kConversionTableSql))
+ if (!db_->Execute(kConversionTableSql))
return false;
// Optimize sorting conversions by report time for calls to
@@ -684,7 +731,7 @@ bool ConversionStorageSql::InitializeSchema() {
const char kConversionReportTimeIndexSql[] =
"CREATE INDEX IF NOT EXISTS conversion_report_idx "
"ON conversions(report_time)";
- if (!db_.Execute(kConversionReportTimeIndexSql))
+ if (!db_->Execute(kConversionReportTimeIndexSql))
return false;
// Want to optimize conversion look up by click id. This allows us to
@@ -694,20 +741,21 @@ bool ConversionStorageSql::InitializeSchema() {
const char kConversionClickIdIndexSql[] =
"CREATE INDEX IF NOT EXISTS conversion_impression_id_idx "
"ON conversions(impression_id)";
- return db_.Execute(kConversionClickIdIndexSql);
+ return db_->Execute(kConversionClickIdIndexSql);
}
void ConversionStorageSql::DatabaseErrorCallback(int extended_error,
sql::Statement* stmt) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- // Attempt to recover corrupt databases.
- if (sql::Recovery::ShouldRecover(extended_error)) {
+ // Attempt to recover a corrupt database, unless it is setup in memory.
+ if (sql::Recovery::ShouldRecover(extended_error) &&
+ (path_to_database_.value() != kInMemoryPath)) {
// Prevent reentrant calls.
- db_.reset_error_callback();
+ db_->reset_error_callback();
// After this call, the |db_| handle is poisoned so that future calls will
// return errors until the handle is re-opened.
- sql::Recovery::RecoverDatabase(&db_, path_to_database_);
+ sql::Recovery::RecoverDatabase(db_.get(), path_to_database_);
// The DLOG(FATAL) below is intended to draw immediate attention to errors
// in newly-written code. Database corruption is generally a result of OS
@@ -719,8 +767,13 @@ void ConversionStorageSql::DatabaseErrorCallback(int extended_error,
}
// The default handling is to assert on debug and to ignore on release.
- if (!sql::Database::IsExpectedSqliteError(extended_error))
- DLOG(FATAL) << db_.GetErrorMessage();
+ if (!sql::Database::IsExpectedSqliteError(extended_error) &&
+ !ignore_errors_for_testing_)
+ DLOG(FATAL) << db_->GetErrorMessage();
+
+ // Consider the database closed if we did not attempt to recover so we did
+ // not produce further errors.
+ db_is_open_ = false;
}
} // namespace content
diff --git a/chromium/content/browser/conversions/conversion_storage_sql.h b/chromium/content/browser/conversions/conversion_storage_sql.h
index 686df2f1658..69144beb5b9 100644
--- a/chromium/content/browser/conversions/conversion_storage_sql.h
+++ b/chromium/content/browser/conversions/conversion_storage_sql.h
@@ -28,13 +28,19 @@ namespace content {
// destroyed on the same sequence. The sequence must outlive |this|.
class CONTENT_EXPORT ConversionStorageSql : public ConversionStorage {
public:
- ConversionStorageSql(const base::FilePath& path_to_database_dir,
+ static void RunInMemoryForTesting();
+
+ ConversionStorageSql(const base::FilePath& path_to_database,
std::unique_ptr<Delegate> delegate,
const base::Clock* clock);
ConversionStorageSql(const ConversionStorageSql& other) = delete;
ConversionStorageSql& operator=(const ConversionStorageSql& other) = delete;
~ConversionStorageSql() override;
+ void set_ignore_errors_for_testing(bool ignore_for_testing) {
+ ignore_errors_for_testing_ = ignore_for_testing;
+ }
+
private:
// ConversionStorage
bool Initialize() override;
@@ -62,8 +68,21 @@ class CONTENT_EXPORT ConversionStorageSql : public ConversionStorage {
void DatabaseErrorCallback(int extended_error, sql::Statement* stmt);
+ static bool g_run_in_memory_;
+
+ // If set, database errors will not crash the client when run in debug mode.
+ bool ignore_errors_for_testing_ = false;
+
const base::FilePath path_to_database_;
- sql::Database db_;
+
+ // Whether the db is open and should be accessed. False if database
+ // initialization failed, or if the db suffered from an unrecoverable error.
+ bool db_is_open_ = false;
+
+ // May be null if the database:
+ // - could not be opened
+ // - table/index initialization failed
+ std::unique_ptr<sql::Database> db_;
// Must outlive |this|.
const base::Clock* clock_;
diff --git a/chromium/content/browser/conversions/conversion_storage_sql_unittest.cc b/chromium/content/browser/conversions/conversion_storage_sql_unittest.cc
index ca408b729c3..5b501d80bd9 100644
--- a/chromium/content/browser/conversions/conversion_storage_sql_unittest.cc
+++ b/chromium/content/browser/conversions/conversion_storage_sql_unittest.cc
@@ -8,6 +8,7 @@
#include <memory>
#include "base/bind.h"
+#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "base/test/simple_test_clock.h"
@@ -55,8 +56,10 @@ class ConversionStorageSqlTest : public testing::Test {
ConfigurableStorageDelegate* delegate() { return delegate_; }
- private:
+ protected:
base::ScopedTempDir temp_directory_;
+
+ private:
std::unique_ptr<ConversionStorage> storage_;
ConfigurableStorageDelegate* delegate_ = nullptr;
base::SimpleTestClock clock_;
@@ -259,4 +262,18 @@ TEST_F(ConversionStorageSqlTest, MaxConversionsPerOrigin) {
EXPECT_EQ(2u, conversion_rows);
}
+TEST_F(ConversionStorageSqlTest, CantOpenDb_FailsSilentlyInRelease) {
+ base::CreateDirectoryAndGetError(db_path(), nullptr);
+
+ auto sql_storage = std::make_unique<ConversionStorageSql>(
+ temp_directory_.GetPath(),
+ std::make_unique<ConfigurableStorageDelegate>(), clock());
+ sql_storage->set_ignore_errors_for_testing(true);
+
+ // Initialize() is private on ConserionStorageSql, so convert to
+ // ConversionStorage.
+ std::unique_ptr<ConversionStorage> storage = std::move(sql_storage);
+ EXPECT_FALSE(storage->Initialize());
+}
+
} // namespace content
diff --git a/chromium/content/browser/conversions/conversion_storage_unittest.cc b/chromium/content/browser/conversions/conversion_storage_unittest.cc
index b8089b96a06..7b17142cfe0 100644
--- a/chromium/content/browser/conversions/conversion_storage_unittest.cc
+++ b/chromium/content/browser/conversions/conversion_storage_unittest.cc
@@ -88,13 +88,36 @@ class ConversionStorageTest : public testing::Test {
ConfigurableStorageDelegate* delegate() { return delegate_; }
+ protected:
+ base::ScopedTempDir dir_;
+
private:
ConfigurableStorageDelegate* delegate_;
base::SimpleTestClock clock_;
- base::ScopedTempDir dir_;
std::unique_ptr<ConversionStorage> storage_;
};
+TEST_F(ConversionStorageTest,
+ StorageUsedAfterFailedInitilization_FailsSilently) {
+ // We fake a failed initialization by never initializing |storage|.
+ std::unique_ptr<ConversionStorage> storage =
+ std::make_unique<ConversionStorageSql>(
+ dir_.GetPath(), std::make_unique<ConfigurableStorageDelegate>(),
+ clock());
+
+ // Test all public methods on ConversionStorage.
+ EXPECT_NO_FATAL_FAILURE(
+ storage->StoreImpression(ImpressionBuilder(clock()->Now()).Build()));
+ EXPECT_EQ(0,
+ storage->MaybeCreateAndStoreConversionReports(DefaultConversion()));
+ EXPECT_TRUE(storage->GetConversionsToReport(clock()->Now()).empty());
+ EXPECT_TRUE(storage->GetActiveImpressions().empty());
+ EXPECT_EQ(0, storage->DeleteExpiredImpressions());
+ EXPECT_EQ(0, storage->DeleteConversion(0UL));
+ EXPECT_NO_FATAL_FAILURE(storage->ClearData(
+ base::Time::Min(), base::Time::Max(), base::NullCallback()));
+}
+
TEST_F(ConversionStorageTest, ImpressionStoredAndRetrieved_ValuesIdentical) {
auto impression = ImpressionBuilder(clock()->Now()).Build();
storage()->StoreImpression(impression);
diff --git a/chromium/content/browser/conversions/conversion_test_utils.cc b/chromium/content/browser/conversions/conversion_test_utils.cc
index 10f95f365bf..3dc13c9b8aa 100644
--- a/chromium/content/browser/conversions/conversion_test_utils.cc
+++ b/chromium/content/browser/conversions/conversion_test_utils.cc
@@ -29,6 +29,11 @@ const int64_t kExpiryTime = 30;
} // namespace
+bool ConversionDisallowingContentBrowserClient::AllowConversionMeasurement(
+ BrowserContext* context) {
+ return false;
+}
+
ConfigurableStorageDelegate::ConfigurableStorageDelegate() = default;
ConfigurableStorageDelegate::~ConfigurableStorageDelegate() = default;
diff --git a/chromium/content/browser/conversions/conversion_test_utils.h b/chromium/content/browser/conversions/conversion_test_utils.h
index 80e569b5cfb..bae9cea4329 100644
--- a/chromium/content/browser/conversions/conversion_test_utils.h
+++ b/chromium/content/browser/conversions/conversion_test_utils.h
@@ -18,11 +18,22 @@
#include "content/browser/conversions/conversion_storage.h"
#include "content/browser/conversions/storable_conversion.h"
#include "content/browser/conversions/storable_impression.h"
+#include "content/test/test_content_browser_client.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "url/origin.h"
namespace content {
+class ConversionDisallowingContentBrowserClient
+ : public TestContentBrowserClient {
+ public:
+ ConversionDisallowingContentBrowserClient() = default;
+ ~ConversionDisallowingContentBrowserClient() override = default;
+
+ // ContentBrowserClient:
+ bool AllowConversionMeasurement(BrowserContext* context) override;
+};
+
class ConfigurableStorageDelegate : public ConversionStorage::Delegate {
public:
using AttributionCredits = std::list<int>;
diff --git a/chromium/content/browser/conversions/conversions_browsertest.cc b/chromium/content/browser/conversions/conversions_browsertest.cc
index dedcf5a42ec..6df8d3c536f 100644
--- a/chromium/content/browser/conversions/conversions_browsertest.cc
+++ b/chromium/content/browser/conversions/conversions_browsertest.cc
@@ -5,7 +5,12 @@
#include <memory>
#include "base/command_line.h"
+#include "base/sequenced_task_runner.h"
#include "base/test/scoped_feature_list.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "content/browser/conversions/conversion_manager_impl.h"
+#include "content/browser/conversions/conversion_test_utils.h"
+#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
@@ -14,6 +19,7 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
+#include "content/test/test_content_browser_client.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/default_handlers.h"
@@ -45,6 +51,8 @@ struct ExpectedReportWaiter {
GURL expected_url;
std::unique_ptr<net::test_server::ControllableHttpResponse> response;
+ bool HasRequest() { return !!response->http_request(); }
+
// Returns the url for the HttpRequest handled by |response|. This returns a
// URL formatted with the host defined in the headers. This would not match
// |expected_url| if the host for report url was not set properly.
@@ -74,10 +82,15 @@ class ConversionsBrowserTest : public ContentBrowserTest {
public:
ConversionsBrowserTest() {
feature_list_.InitAndEnableFeature(features::kConversionMeasurement);
+ ConversionManagerImpl::RunInMemoryForTesting();
}
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(switches::kConversionsDebugMode);
+
+ // Sets up the blink runtime feature for ConversionMeasurement.
+ command_line->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
}
void SetUpOnMainThread() override {
@@ -95,11 +108,19 @@ class ConversionsBrowserTest : public ContentBrowserTest {
net::EmbeddedTestServer* https_server() { return https_server_.get(); }
+ protected:
+ ConversionDisallowingContentBrowserClient disallowed_browser_client_;
+
private:
base::test::ScopedFeatureList feature_list_;
std::unique_ptr<net::EmbeddedTestServer> https_server_;
};
+// Verifies that storage initialization does not hang when initialized in a
+// browsertest context, see https://crbug.com/1080764).
+IN_PROC_BROWSER_TEST_F(ConversionsBrowserTest,
+ FeatureEnabled_StorageInitWithoutHang) {}
+
IN_PROC_BROWSER_TEST_F(ConversionsBrowserTest,
ImpressionConversion_ReportSent) {
// Expected reports must be registered before the server starts.
@@ -251,4 +272,57 @@ IN_PROC_BROWSER_TEST_F(
}
}
+IN_PROC_BROWSER_TEST_F(ConversionsBrowserTest,
+ ConversionRegisteredWithEmbedderDisallow_NoData) {
+ ContentBrowserClient* old_browser_client =
+ SetBrowserClientForTesting(&disallowed_browser_client_);
+
+ // Expected reports must be registered before the server starts.
+ ExpectedReportWaiter expected_report(
+ GURL(
+ "https://a.test/.well-known/"
+ "register-conversion?impression-data=1&conversion-data=7&credit=100"),
+ https_server());
+ ASSERT_TRUE(https_server()->Start());
+
+ GURL impression_url = https_server()->GetURL(
+ "a.test", "/conversions/page_with_impression_creator.html");
+ EXPECT_TRUE(NavigateToURL(web_contents(), impression_url));
+
+ // Create an anchor tag with impression attributes and click the link. By
+ // default the target is set to "_top".
+ GURL conversion_url = https_server()->GetURL(
+ "b.test", "/conversions/page_with_conversion_redirect.html");
+ EXPECT_TRUE(
+ ExecJs(web_contents(),
+ JsReplace(R"(
+ createImpressionTag("link" /* id */,
+ $1 /* url */,
+ "1" /* impression data */,
+ $2 /* conversion_destination */);)",
+ conversion_url, url::Origin::Create(conversion_url))));
+
+ TestNavigationObserver observer(web_contents());
+ EXPECT_TRUE(ExecJs(shell(), "simulateClick('link');"));
+ observer.Wait();
+
+ // Register a conversion with the original page as the reporting origin.
+ EXPECT_TRUE(
+ ExecJs(web_contents(), JsReplace("registerConversionForOrigin(7, $1)",
+ url::Origin::Create(impression_url))));
+
+ // Since we want to verify that a report _isn't_ sent, we can't really wait on
+ // any event here. The best thing we can do is just impose a short delay and
+ // verify the browser didn't send anything. Worst case, this should start
+ // flakily failing if the logic breaks.
+ base::RunLoop run_loop;
+ base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(),
+ base::TimeDelta::FromMilliseconds(100));
+ run_loop.Run();
+ EXPECT_FALSE(expected_report.HasRequest());
+
+ SetBrowserClientForTesting(old_browser_client);
+}
+
} // namespace content
diff --git a/chromium/content/browser/conversions/conversions_origin_trial_browsertest.cc b/chromium/content/browser/conversions/conversions_origin_trial_browsertest.cc
new file mode 100644
index 00000000000..d4dc3e137f5
--- /dev/null
+++ b/chromium/content/browser/conversions/conversions_origin_trial_browsertest.cc
@@ -0,0 +1,106 @@
+// 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_test_util.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 ConversionsOriginTrialBrowserTest : public ContentBrowserTest {
+ public:
+ ConversionsOriginTrialBrowserTest() {
+ feature_list_.InitAndEnableFeature(features::kConversionMeasurement);
+ }
+
+ 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:
+ base::test::ScopedFeatureList feature_list_;
+ std::unique_ptr<URLLoaderInterceptor> url_loader_interceptor_;
+};
+
+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.
+
+} // namespace content
diff --git a/chromium/content/browser/conversions/impression_declaration_browsertest.cc b/chromium/content/browser/conversions/impression_declaration_browsertest.cc
index 9e12221ca75..c593b0cf956 100644
--- a/chromium/content/browser/conversions/impression_declaration_browsertest.cc
+++ b/chromium/content/browser/conversions/impression_declaration_browsertest.cc
@@ -9,13 +9,17 @@
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
+#include "build/build_config.h"
+#include "content/browser/conversions/conversion_manager_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/navigation_handle.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/shell/browser/shell.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/default_handlers.h"
@@ -26,13 +30,15 @@ namespace content {
// WebContentsObserver that waits until an impression is available on a
// navigation handle for a finished navigation.
-class ImpressionObserver : public WebContentsObserver {
+class ImpressionObserver : public TestNavigationObserver {
public:
- explicit ImpressionObserver(WebContents* contents)
- : WebContentsObserver(contents) {}
+ explicit ImpressionObserver(WebContents* contents,
+ size_t num_impressions = 1u)
+ : TestNavigationObserver(contents),
+ expected_num_impressions_(num_impressions) {}
// WebContentsObserver
- void DidFinishNavigation(NavigationHandle* navigation_handle) override {
+ void OnDidFinishNavigation(NavigationHandle* navigation_handle) override {
if (!navigation_handle->GetImpression()) {
if (waiting_for_null_impression_)
impression_loop_.Quit();
@@ -40,14 +46,21 @@ class ImpressionObserver : public WebContentsObserver {
}
last_impression_ = *(navigation_handle->GetImpression());
+ num_impressions_++;
- if (!waiting_for_null_impression_)
+ if (!waiting_for_null_impression_ &&
+ num_impressions_ >= expected_num_impressions_) {
impression_loop_.Quit();
+ }
}
const Impression& last_impression() { return *last_impression_; }
- const Impression& WaitForImpression() {
+ // Waits for |expected_num_impressions_| navigations with impressions, and
+ // returns the last impression.
+ const Impression& Wait() {
+ if (num_impressions_ >= expected_num_impressions_)
+ return *last_impression_;
impression_loop_.Run();
return last_impression();
}
@@ -60,15 +73,18 @@ class ImpressionObserver : public WebContentsObserver {
}
private:
+ size_t num_impressions_ = 0u;
+ const size_t expected_num_impressions_ = 0u;
base::Optional<Impression> last_impression_;
bool waiting_for_null_impression_ = false;
base::RunLoop impression_loop_;
};
-class ImpressionDeclarationBrowserTest : public ContentBrowserTest {
+class ImpressionDisabledBrowserTest : public ContentBrowserTest {
public:
- ImpressionDeclarationBrowserTest() {
+ ImpressionDisabledBrowserTest() {
feature_list_.InitAndEnableFeature(features::kConversionMeasurement);
+ ConversionManagerImpl::RunInMemoryForTesting();
}
void SetUpOnMainThread() override {
@@ -99,6 +115,37 @@ class ImpressionDeclarationBrowserTest : public ContentBrowserTest {
std::unique_ptr<net::EmbeddedTestServer> https_server_;
};
+// Verifies that impressions are not logged when the Runtime feature isn't
+// enabled.
+IN_PROC_BROWSER_TEST_F(ImpressionDisabledBrowserTest,
+ ImpressionWithoutFeatureEnabled_NotReceived) {
+ ImpressionObserver impression_observer(web_contents());
+ EXPECT_TRUE(NavigateToURL(
+ web_contents(),
+ https_server()->GetURL("b.test", "/page_with_impression_creator.html")));
+
+ EXPECT_TRUE(ExecJs(web_contents(), R"(
+ createImpressionTag("link",
+ "page_with_conversion_redirect.html",
+ "1" /* impression data */,
+ "https://a.com" /* conversion_destination */);)"));
+ EXPECT_TRUE(ExecJs(shell(), "simulateClick(\'link\');"));
+
+ // No impression should be observed.
+ EXPECT_TRUE(impression_observer.WaitForNavigationWithNoImpression());
+}
+
+class ImpressionDeclarationBrowserTest : public ImpressionDisabledBrowserTest {
+ public:
+ ImpressionDeclarationBrowserTest() = default;
+
+ // Sets up the blink runtime feature for ConversionMeasurement.
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+ }
+};
+
IN_PROC_BROWSER_TEST_F(ImpressionDeclarationBrowserTest,
ImpressionTagClicked_ImpressionReceived) {
ImpressionObserver impression_observer(web_contents());
@@ -118,7 +165,7 @@ IN_PROC_BROWSER_TEST_F(ImpressionDeclarationBrowserTest,
EXPECT_TRUE(ExecJs(shell(), "simulateClick(\'link\');"));
// Wait for the impression to be seen by the observer.
- Impression last_impression = impression_observer.WaitForImpression();
+ Impression last_impression = impression_observer.Wait();
// Verify the attributes of the impression are set as expected.
EXPECT_EQ(1UL, last_impression.impression_data);
@@ -135,8 +182,6 @@ IN_PROC_BROWSER_TEST_F(ImpressionDeclarationBrowserTest,
web_contents(),
https_server()->GetURL("b.test", "/page_with_impression_creator.html")));
- ShellAddedObserver new_shell_observer;
-
// Create an impression tag with a target frame that does not exist, which
// will open a new window to navigate.
EXPECT_TRUE(ExecJs(web_contents(), R"(
@@ -145,20 +190,27 @@ IN_PROC_BROWSER_TEST_F(ImpressionDeclarationBrowserTest,
"1" /* impression data */,
"https://a.com" /* conversion_destination */,
"target" /* target */);)"));
- EXPECT_TRUE(ExecJs(shell(), "simulateClick(\'link\');"));
- ImpressionObserver impression_observer(
- new_shell_observer.GetShell()->web_contents());
+ ImpressionObserver impression_observer(nullptr);
+ impression_observer.StartWatchingNewWebContents();
+ EXPECT_TRUE(ExecJs(shell(), "simulateClick(\'link\');"));
// Wait for the impression to be seen by the observer.
- Impression last_impression = impression_observer.WaitForImpression();
+ Impression last_impression = impression_observer.Wait();
EXPECT_EQ(1UL, impression_observer.last_impression().impression_data);
}
-// Test frequently flakes due to timeout. ( https://crbug.com/1084201 )
+// Flaky on Mac: crbug.com/1099410
+#if defined(OS_MACOSX)
+#define MAYBE_ImpressionTagNavigatesExistingRemoteFrame_ImpressionReceived \
+ DISABLED_ImpressionTagNavigatesExistingRemoteFrame_ImpressionReceived
+#else
+#define MAYBE_ImpressionTagNavigatesExistingRemoteFrame_ImpressionReceived \
+ ImpressionTagNavigatesExistingRemoteFrame_ImpressionReceived
+#endif
IN_PROC_BROWSER_TEST_F(
ImpressionDeclarationBrowserTest,
- DISABLED_ImpressionTagNavigatesExistingRemoteFrame_ImpressionReceived) {
+ MAYBE_ImpressionTagNavigatesExistingRemoteFrame_ImpressionReceived) {
EXPECT_TRUE(NavigateToURL(
web_contents(),
https_server()->GetURL("b.test", "/page_with_impression_creator.html")));
@@ -181,12 +233,12 @@ IN_PROC_BROWSER_TEST_F(
"1" /* impression data */,
"https://a.com" /* conversion_destination */,
"target" /* target */);)"));
- EXPECT_TRUE(ExecJs(shell(), "simulateClick(\'link\');"));
ImpressionObserver impression_observer(remote_web_contents);
+ EXPECT_TRUE(ExecJs(shell(), "simulateClick(\'link\');"));
// Wait for the impression to be seen by the observer.
- Impression last_impression = impression_observer.WaitForImpression();
+ Impression last_impression = impression_observer.Wait();
EXPECT_EQ(1UL, impression_observer.last_impression().impression_data);
}
@@ -207,7 +259,7 @@ IN_PROC_BROWSER_TEST_F(ImpressionDeclarationBrowserTest,
EXPECT_TRUE(ExecJs(shell(), "simulateClick(\'link\');"));
// Wait for the impression to be seen by the observer.
- Impression last_impression = impression_observer.WaitForImpression();
+ Impression last_impression = impression_observer.Wait();
EXPECT_EQ(0UL, impression_observer.last_impression().impression_data);
}
@@ -218,8 +270,6 @@ IN_PROC_BROWSER_TEST_F(
https_server()->GetURL("b.test", "/page_with_impression_creator.html");
EXPECT_TRUE(NavigateToURL(web_contents(), page_url));
- ShellAddedObserver new_shell_observer;
-
// Create an impression tag that is opened via middle click. This navigates in
// a new WebContents.
EXPECT_TRUE(ExecJs(web_contents(), R"(
@@ -227,12 +277,12 @@ IN_PROC_BROWSER_TEST_F(
"page_with_conversion_redirect.html",
"1" /* impression data */,
"https://a.com" /* conversion_destination */);)"));
- EXPECT_TRUE(ExecJs(shell(), "simulateMiddleClick(\'link\');"));
- ImpressionObserver impression_observer(
- new_shell_observer.GetShell()->web_contents());
+ ImpressionObserver impression_observer(nullptr);
+ impression_observer.StartWatchingNewWebContents();
+ EXPECT_TRUE(ExecJs(shell(), "simulateMiddleClick(\'link\');"));
- Impression last_impression = impression_observer.WaitForImpression();
+ Impression last_impression = impression_observer.Wait();
// Verify the attributes of the impression are set as expected.
EXPECT_EQ(1UL, last_impression.impression_data);
@@ -260,12 +310,13 @@ IN_PROC_BROWSER_TEST_F(
link.addEventListener('focus', function() { document.title = 'focused'; });
link.focus();)"));
EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+
+ ImpressionObserver impression_observer(web_contents());
content::SimulateKeyPress(web_contents(), ui::DomKey::ENTER,
ui::DomCode::ENTER, ui::VKEY_RETURN, false, false,
false, false);
- ImpressionObserver impression_observer(web_contents());
- Impression last_impression = impression_observer.WaitForImpression();
+ Impression last_impression = impression_observer.Wait();
// Verify the attributes of the impression are set as expected.
EXPECT_EQ(1UL, last_impression.impression_data);
@@ -393,7 +444,7 @@ IN_PROC_BROWSER_TEST_F(ImpressionDeclarationBrowserTest,
EXPECT_TRUE(ExecJs(subframe, "simulateClick('link');"));
// We should see a null impression on the navigation
- EXPECT_EQ(1u, impression_observer.WaitForImpression().impression_data);
+ EXPECT_EQ(1u, impression_observer.Wait().impression_data);
}
IN_PROC_BROWSER_TEST_F(ImpressionDeclarationBrowserTest,
@@ -409,7 +460,7 @@ IN_PROC_BROWSER_TEST_F(ImpressionDeclarationBrowserTest,
"1" /* impression data */,
"https://a.com" /* conversion_destination */);)"));
EXPECT_TRUE(ExecJs(shell(), "simulateClick(\'link\');"));
- EXPECT_EQ(1UL, impression_observer.WaitForImpression().impression_data);
+ EXPECT_EQ(1UL, impression_observer.Wait().impression_data);
ImpressionObserver reload_observer(web_contents());
shell()->Reload();
@@ -432,7 +483,7 @@ IN_PROC_BROWSER_TEST_F(ImpressionDeclarationBrowserTest,
"1" /* impression data */,
"https://a.com" /* conversion_destination */);)"));
EXPECT_TRUE(ExecJs(shell(), "simulateClick(\'link\');"));
- EXPECT_EQ(1UL, impression_observer.WaitForImpression().impression_data);
+ EXPECT_EQ(1UL, impression_observer.Wait().impression_data);
ImpressionObserver reload_observer(web_contents());
EXPECT_TRUE(ExecJs(web_contents(), "window.location.reload()"));
@@ -451,7 +502,7 @@ IN_PROC_BROWSER_TEST_F(ImpressionDeclarationBrowserTest,
// Click the default impression on the page.
EXPECT_TRUE(ExecJs(shell(), "simulateClick(\'impression_tag\');"));
- EXPECT_EQ(1UL, impression_observer.WaitForImpression().impression_data);
+ EXPECT_EQ(1UL, impression_observer.Wait().impression_data);
// Navigate away so we can back navigate to the impression's navigated page.
EXPECT_TRUE(NavigateToURL(web_contents(), GURL("about:blank")));
@@ -471,8 +522,7 @@ IN_PROC_BROWSER_TEST_F(ImpressionDeclarationBrowserTest,
WaitForLoadStop(web_contents());
ImpressionObserver second_impression_observer(web_contents());
EXPECT_TRUE(ExecJs(shell(), "simulateClick(\'impression_tag\');"));
- EXPECT_EQ(1UL,
- second_impression_observer.WaitForImpression().impression_data);
+ EXPECT_EQ(1UL, second_impression_observer.Wait().impression_data);
}
} // namespace content