Skip to content

Commit

Permalink
Access Context Auditing: Store non-persistent cookie records
Browse files Browse the repository at this point in the history
To support recording access for non-persistent cookies, the Access
Context Audit service and databases are extended to store non-
persistent cookies alongside persistent cookies. These records are
cleared on startup unless restoring the previous session.

Bug: 1101675
Change-Id: I7ee7a47530f8f0d6b05fc8890b94c605f839c2ab
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2273057
Reviewed-by: Martin Šrámek <msramek@chromium.org>
Reviewed-by: Christian Dullweber <dullweber@chromium.org>
Commit-Queue: Theodore Olsauskas-Warren <sauski@google.com>
Cr-Commit-Position: refs/heads/master@{#785843}
  • Loading branch information
sauski-alternative authored and Commit Bot committed Jul 7, 2020
1 parent f25cbd8 commit 13e4dfc
Show file tree
Hide file tree
Showing 7 changed files with 455 additions and 118 deletions.
176 changes: 150 additions & 26 deletions chrome/browser/browsing_data/access_context_audit_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
#include <memory>

#include "base/path_service.h"
#include "base/test/bind_test_util.h"
#include "chrome/browser/browsing_data/access_context_audit_service.h"
#include "chrome/browser/browsing_data/access_context_audit_service_factory.h"
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_features.h"
Expand All @@ -19,17 +21,21 @@
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/browsing_data_remover_test_util.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/request_handler_util.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"

namespace {

// Use host names that are explicitly included in test certificates.
constexpr char kTopLevelHost[] = "a.test";
constexpr char kEmbeddedHost[] = "b.test";
constexpr char kTopLevelHostAsOrigin[] = "https://a.test";
constexpr char kEmbeddedHostAsOrigin[] = "https://b.test";

std::string GetPathWithHostAndPortReplaced(const std::string& original_path,
net::HostPortPair host_port_pair) {
Expand All @@ -39,23 +45,40 @@ std::string GetPathWithHostAndPortReplaced(const std::string& original_path,
replacement_text);
}

void CheckContainsCookieRecord(
// Checks if the cookie defined by |name|, |domain| and |path| is present in
// |cookies|, and that the record associating access to it to |top_frame_origin|
// is present in |record_list|. If |compare_host_only| is set, only the host
// portion of |top_frame_origin| will be used for comparison.
void CheckContainsCookieAndRecord(
const std::vector<net::CanonicalCookie>& cookies,
const std::vector<AccessContextAuditDatabase::AccessRecord>& record_list,
const GURL& top_frame_origin,
const std::string& name,
const std::string& domain,
const std::string& path) {
const std::string& path,
bool compare_host_only = false) {
EXPECT_NE(
std::find_if(
record_list.begin(), record_list.end(),
[=](const AccessContextAuditDatabase::AccessRecord& record) {
return record.type ==
AccessContextAuditDatabase::StorageAPIType::kCookie &&
record.top_frame_origin == top_frame_origin &&
(compare_host_only
? record.top_frame_origin.host() ==
top_frame_origin.host()
: record.top_frame_origin == top_frame_origin) &&
record.name == name && record.domain == domain &&
record.path == path;
}),
record_list.end());

EXPECT_NE(std::find_if(cookies.begin(), cookies.end(),
[=](const net::CanonicalCookie& cookie) {
return cookie.Name() == name &&
cookie.Domain() == domain &&
cookie.Path() == path;
}),
cookies.end());
}

} // namespace
Expand All @@ -78,21 +101,30 @@ class AccessContextAuditBrowserTest : public InProcessBrowserTest {
}

std::vector<AccessContextAuditDatabase::AccessRecord> GetAllAccessRecords() {
base::RunLoop run_loop;
std::vector<AccessContextAuditDatabase::AccessRecord> records_out;
AccessContextAuditServiceFactory::GetForProfile(browser()->profile())
->GetAllAccessRecords(
base::BindOnce(&AccessContextAuditBrowserTest::AccessRecordCallback,
base::Unretained(this)));
run_loop_ = std::make_unique<base::RunLoop>();
run_loop_->Run();

return records_;
->GetAllAccessRecords(base::BindLambdaForTesting(
[&](std::vector<AccessContextAuditDatabase::AccessRecord> records) {
records_out = records;
run_loop.QuitWhenIdle();
}));
run_loop.Run();
return records_out;
}

void AccessRecordCallback(
std::vector<AccessContextAuditDatabase::AccessRecord> records) {
records_ = records;
if (run_loop_)
run_loop_->QuitWhenIdle();
std::vector<net::CanonicalCookie> GetAllCookies() {
base::RunLoop run_loop;
std::vector<net::CanonicalCookie> cookies_out;
content::BrowserContext::GetDefaultStoragePartition(browser()->profile())
->GetCookieManagerForBrowserProcess()
->GetAllCookies(base::BindLambdaForTesting(
[&](const std::vector<net::CanonicalCookie>& cookies) {
cookies_out = cookies;
run_loop.QuitWhenIdle();
}));
run_loop.Run();
return cookies_out;
}

GURL top_level_origin() { return top_level_.GetURL(kTopLevelHost, "/"); }
Expand All @@ -104,8 +136,6 @@ class AccessContextAuditBrowserTest : public InProcessBrowserTest {
net::EmbeddedTestServer embedded_{net::EmbeddedTestServer::TYPE_HTTPS};

std::vector<AccessContextAuditDatabase::AccessRecord> records_;

std::unique_ptr<base::RunLoop> run_loop_;
};

IN_PROC_BROWSER_TEST_F(AccessContextAuditBrowserTest, PRE_PRE_RemoveRecords) {
Expand All @@ -122,22 +152,43 @@ IN_PROC_BROWSER_TEST_F(AccessContextAuditBrowserTest, PRE_PRE_RemoveRecords) {
ui_test_utils::NavigateToURL(
browser(),
embedded_.GetURL(kEmbeddedHost, "/browsing_data/storage_accessor.html"));
base::RunLoop().RunUntilIdle();

// Check storage accesses have been correctly recorded.
auto records = GetAllAccessRecords();
EXPECT_EQ(records.size(), 3u);
CheckContainsCookieRecord(records, top_level_origin(), "embedder",
kTopLevelHost, "/");
CheckContainsCookieRecord(records, top_level_origin(), "persistent",
kEmbeddedHost, "/");
CheckContainsCookieRecord(records, embedded_origin(), "persistent",
kEmbeddedHost, "/");
auto cookies = GetAllCookies();
EXPECT_EQ(records.size(), 5u);
EXPECT_EQ(cookies.size(), 3u);
CheckContainsCookieAndRecord(cookies, records, top_level_origin(), "embedder",
kTopLevelHost, "/");
CheckContainsCookieAndRecord(cookies, records, top_level_origin(),
"persistent", kEmbeddedHost, "/");
CheckContainsCookieAndRecord(cookies, records, top_level_origin(),
"session_only", kEmbeddedHost, "/");
CheckContainsCookieAndRecord(cookies, records, embedded_origin(),
"persistent", kEmbeddedHost, "/");
CheckContainsCookieAndRecord(cookies, records, embedded_origin(),
"session_only", kEmbeddedHost, "/");
}

IN_PROC_BROWSER_TEST_F(AccessContextAuditBrowserTest, PRE_RemoveRecords) {
// Check that records have been persisted across restart.
// Check that only persistent records have been persisted across restart.
// Unfortunately the correct top frame origin is lost in the test as the
// embedded test servers will have changed port, so only the host can be
// reliably compared.
auto records = GetAllAccessRecords();
auto cookies = GetAllCookies();
EXPECT_EQ(records.size(), 3u);
EXPECT_EQ(cookies.size(), 2u);
CheckContainsCookieAndRecord(cookies, records, GURL(kTopLevelHostAsOrigin),
"embedder", kTopLevelHost, "/",
/*compare_host_only*/ true);
CheckContainsCookieAndRecord(cookies, records, GURL(kTopLevelHostAsOrigin),
"persistent", kEmbeddedHost, "/",
/*compare_host_only*/ true);
CheckContainsCookieAndRecord(cookies, records, GURL(kEmbeddedHostAsOrigin),
"persistent", kEmbeddedHost, "/",
/*compare_host_only*/ true);
}

IN_PROC_BROWSER_TEST_F(AccessContextAuditBrowserTest, RemoveRecords) {
Expand All @@ -152,7 +203,9 @@ IN_PROC_BROWSER_TEST_F(AccessContextAuditBrowserTest, RemoveRecords) {
completion_observer.BlockUntilCompletion();

auto records = GetAllAccessRecords();
auto cookies = GetAllCookies();
EXPECT_EQ(records.size(), 0u);
EXPECT_EQ(cookies.size(), 0u);
}

IN_PROC_BROWSER_TEST_F(AccessContextAuditBrowserTest, PRE_CheckSessionOnly) {
Expand All @@ -170,12 +223,83 @@ IN_PROC_BROWSER_TEST_F(AccessContextAuditBrowserTest, PRE_CheckSessionOnly) {
ui_test_utils::NavigateToURL(
browser(),
embedded_.GetURL(kEmbeddedHost, "/browsing_data/storage_accessor.html"));
base::RunLoop().RunUntilIdle();

auto records = GetAllAccessRecords();
EXPECT_EQ(records.size(), 3u);
auto cookies = GetAllCookies();
EXPECT_EQ(records.size(), 5u);
EXPECT_EQ(cookies.size(), 3u);
}

IN_PROC_BROWSER_TEST_F(AccessContextAuditBrowserTest, CheckSessionOnly) {
auto records = GetAllAccessRecords();
auto cookies = GetAllCookies();
EXPECT_EQ(records.size(), 0u);
EXPECT_EQ(cookies.size(), 0u);
}

class AccessContextAuditSessionRestoreBrowserTest
: public AccessContextAuditBrowserTest {
public:
void SetUpOnMainThread() override {
SessionStartupPref::SetStartupPref(
browser()->profile(), SessionStartupPref(SessionStartupPref::LAST));
AccessContextAuditBrowserTest::SetUpOnMainThread();
}
};

IN_PROC_BROWSER_TEST_F(AccessContextAuditSessionRestoreBrowserTest,
PRE_RestoreSession) {
// Navigate to test URLS which set a mixture of persistent and non-persistent
// cookies.
std::string replacement_path = GetPathWithHostAndPortReplaced(
"/browsing_data/embeds_storage_accessor.html",
net::HostPortPair::FromURL(embedded_.GetURL(kEmbeddedHost, "/")));
ui_test_utils::NavigateToURL(
browser(), top_level_.GetURL(kTopLevelHost, replacement_path));

ui_test_utils::NavigateToURL(
browser(),
embedded_.GetURL(kEmbeddedHost, "/browsing_data/storage_accessor.html"));
base::RunLoop().RunUntilIdle();

// Check storage accesses have been correctly recorded.
auto records = GetAllAccessRecords();
auto cookies = GetAllCookies();
EXPECT_EQ(records.size(), 5u);
EXPECT_EQ(cookies.size(), 3u);
CheckContainsCookieAndRecord(cookies, records, top_level_origin(), "embedder",
kTopLevelHost, "/");
CheckContainsCookieAndRecord(cookies, records, top_level_origin(),
"persistent", kEmbeddedHost, "/");
CheckContainsCookieAndRecord(cookies, records, top_level_origin(),
"session_only", kEmbeddedHost, "/");
CheckContainsCookieAndRecord(cookies, records, embedded_origin(),
"persistent", kEmbeddedHost, "/");
CheckContainsCookieAndRecord(cookies, records, embedded_origin(),
"session_only", kEmbeddedHost, "/");
}

IN_PROC_BROWSER_TEST_F(AccessContextAuditSessionRestoreBrowserTest,
RestoreSession) {
// Check all access records have been correctly persisted across restarts.
auto records = GetAllAccessRecords();
auto cookies = GetAllCookies();
EXPECT_EQ(records.size(), 5u);
EXPECT_EQ(cookies.size(), 3u);
CheckContainsCookieAndRecord(cookies, records, GURL(kTopLevelHostAsOrigin),
"embedder", kTopLevelHost, "/",
/*compare_host_only*/ true);
CheckContainsCookieAndRecord(cookies, records, GURL(kTopLevelHostAsOrigin),
"session_only", kEmbeddedHost, "/",
/*compare_host_only*/ true);
CheckContainsCookieAndRecord(cookies, records, GURL(kTopLevelHostAsOrigin),
"persistent", kEmbeddedHost, "/",
/*compare_host_only*/ true);
CheckContainsCookieAndRecord(cookies, records, GURL(kEmbeddedHostAsOrigin),
"persistent", kEmbeddedHost, "/",
/*compare_host_only*/ true);
CheckContainsCookieAndRecord(cookies, records, GURL(kEmbeddedHostAsOrigin),
"session_only", kEmbeddedHost, "/",
/*compare_host_only*/ true);
}

0 comments on commit 13e4dfc

Please sign in to comment.