Skip to content

Commit

Permalink
Access Context Auditing: Record origin keyed storage API accesses
Browse files Browse the repository at this point in the history
Extends the PageSpecificContentSettings & associated delegegate to
inform the audit service of access to:
	- DOM (Local) storage
	- File System
	- Service Workers
	- Web Database

The CookiesTreeModel is also updated to report deletion events for these
storage types to the audit service.

Bug: 1101675
Change-Id: Idf332624cac0260a1bdc4c99c01057cda10b42a2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2363749
Reviewed-by: Scott Violet <sky@chromium.org>
Reviewed-by: Martin Šrámek <msramek@chromium.org>
Commit-Queue: Theodore Olsauskas-Warren <sauski@google.com>
Cr-Commit-Position: refs/heads/master@{#800010}
  • Loading branch information
sauski-alternative authored and Commit Bot committed Aug 20, 2020
1 parent 8d8fcbd commit 8e0838c
Show file tree
Hide file tree
Showing 14 changed files with 219 additions and 26 deletions.
19 changes: 19 additions & 0 deletions chrome/browser/browsing_data/access_context_audit_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#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/browser/web_contents.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"
Expand All @@ -43,6 +44,10 @@ constexpr char kEmbeddedHost[] = "b.test";
// embedded pages in testing.
const std::set<AccessContextAuditDatabase::StorageAPIType>&
kOriginStorageTypes = {
AccessContextAuditDatabase::StorageAPIType::kLocalStorage,
AccessContextAuditDatabase::StorageAPIType::kFileSystem,
AccessContextAuditDatabase::StorageAPIType::kWebDatabase,
AccessContextAuditDatabase::StorageAPIType::kServiceWorker,
AccessContextAuditDatabase::StorageAPIType::kCacheStorage,
AccessContextAuditDatabase::StorageAPIType::kIndexedDB};

Expand Down Expand Up @@ -121,6 +126,18 @@ void CheckContainsOriginStorageRecords(
}
}

// Calls the accessStorage javascript function and awaits its completion for
// each frame in the active web contents for |browser|.
void EnsurePageAccessedStorage(Browser* browser) {
auto frames =
browser->tab_strip_model()->GetActiveWebContents()->GetAllFrames();
for (auto* frame : frames) {
ASSERT_TRUE(content::EvalJs(
frame, "(async () => { return await accessStorage();})()")
.value.GetBool());
}
}

} // namespace

class CookiesTreeObserver : public CookiesTreeModel::Observer {
Expand Down Expand Up @@ -196,12 +213,14 @@ class AccessContextAuditBrowserTest : public InProcessBrowserTest {
void NavigateToTopLevelPage() {
ui_test_utils::NavigateToURL(browser(), top_level_url());
base::RunLoop().RunUntilIdle();
EnsurePageAccessedStorage(browser());
}

// Navigate directly to the embedded page.
void NavigateToEmbeddedPage() {
ui_test_utils::NavigateToURL(browser(), embedded_url());
base::RunLoop().RunUntilIdle();
EnsurePageAccessedStorage(browser());
}

url::Origin top_level_origin() {
Expand Down
56 changes: 40 additions & 16 deletions chrome/browser/browsing_data/cookies_tree_model.cc
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,16 @@ void CookieTreeNode::AddChildSortedByTitle(
size_t{iter - children().begin()});
}

#if !defined(OS_ANDROID)
void CookieTreeNode::ReportDeletionToAuditService(
const url::Origin& origin,
AccessContextAuditDatabase::StorageAPIType type) {
auto* audit_service = GetModel()->access_context_audit_service();
if (audit_service)
audit_service->RemoveAllRecordsForOriginKeyedStorage(origin, type);
}
#endif // !defined(OS_ANDROID)

///////////////////////////////////////////////////////////////////////////////
// CookieTreeCookieNode

Expand Down Expand Up @@ -434,6 +444,12 @@ class CookieTreeDatabaseNode : public CookieTreeNode {
LocalDataContainer* container = GetLocalDataContainerForNode(this);

if (container) {
#if !defined(OS_ANDROID)
ReportDeletionToAuditService(
usage_info_->origin,
AccessContextAuditDatabase::StorageAPIType::kWebDatabase);
#endif // !defined(OS_ANDROID)

container->database_helper_->DeleteDatabase(usage_info_->origin);
container->database_info_list_.erase(usage_info_);
}
Expand Down Expand Up @@ -475,6 +491,12 @@ class CookieTreeLocalStorageNode : public CookieTreeNode {
LocalDataContainer* container = GetLocalDataContainerForNode(this);

if (container) {
#if !defined(OS_ANDROID)
ReportDeletionToAuditService(
local_storage_info_->origin,
AccessContextAuditDatabase::StorageAPIType::kLocalStorage);
#endif // !defined(OS_ANDROID)

container->local_storage_helper_->DeleteOrigin(
local_storage_info_->origin, base::DoNothing());
container->local_storage_info_list_.erase(local_storage_info_);
Expand Down Expand Up @@ -555,14 +577,9 @@ class CookieTreeIndexedDBNode : public CookieTreeNode {

if (container) {
#if !defined(OS_ANDROID)
// TODO (crbug.com/1113602): Remove this when all storage deletions from
// the browser process use the StoragePartition directly.
auto* audit_service = GetModel()->access_context_audit_service();
if (audit_service) {
audit_service->RemoveAllRecordsForOriginKeyedStorage(
usage_info_->origin,
AccessContextAuditDatabase::StorageAPIType::kIndexedDB);
}
ReportDeletionToAuditService(
usage_info_->origin,
AccessContextAuditDatabase::StorageAPIType::kIndexedDB);
#endif // !defined(OS_ANDROID)

container->indexed_db_helper_->DeleteIndexedDB(usage_info_->origin,
Expand Down Expand Up @@ -607,6 +624,12 @@ class CookieTreeFileSystemNode : public CookieTreeNode {
LocalDataContainer* container = GetLocalDataContainerForNode(this);

if (container) {
#if !defined(OS_ANDROID)
ReportDeletionToAuditService(
file_system_info_->origin,
AccessContextAuditDatabase::StorageAPIType::kFileSystem);
#endif // !defined(OS_ANDROID)

container->file_system_helper_->DeleteFileSystemOrigin(
file_system_info_->origin);
container->file_system_info_list_.erase(file_system_info_);
Expand Down Expand Up @@ -690,6 +713,12 @@ class CookieTreeServiceWorkerNode : public CookieTreeNode {
LocalDataContainer* container = GetLocalDataContainerForNode(this);

if (container) {
#if !defined(OS_ANDROID)
ReportDeletionToAuditService(
usage_info_->origin,
AccessContextAuditDatabase::StorageAPIType::kServiceWorker);
#endif // !defined(OS_ANDROID)

container->service_worker_helper_->DeleteServiceWorkers(
usage_info_->origin);
container->service_worker_info_list_.erase(usage_info_);
Expand Down Expand Up @@ -772,14 +801,9 @@ class CookieTreeCacheStorageNode : public CookieTreeNode {

if (container) {
#if !defined(OS_ANDROID)
// TODO (crbug.com/1113602): Remove this when all storage deletions from
// the browser process use the StoragePartition directly.
auto* audit_service = GetModel()->access_context_audit_service();
if (audit_service) {
audit_service->RemoveAllRecordsForOriginKeyedStorage(
usage_info_->origin,
AccessContextAuditDatabase::StorageAPIType::kCacheStorage);
}
ReportDeletionToAuditService(
usage_info_->origin,
AccessContextAuditDatabase::StorageAPIType::kCacheStorage);
#endif // !defined(OS_ANDROID)

container->cache_storage_helper_->DeleteCacheStorage(usage_info_->origin);
Expand Down
13 changes: 13 additions & 0 deletions chrome/browser/browsing_data/cookies_tree_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,16 @@
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
#include "chrome/browser/browsing_data/local_data_container.h"
#include "components/content_settings/core/common/content_settings.h"
#include "extensions/buildflags/buildflags.h"
#include "ui/base/models/tree_node_model.h"

#if !defined(OS_ANDROID)
#include "chrome/browser/browsing_data/access_context_audit_database.h"
#endif // !defined(OS_ANDROID)

class AccessContextAuditService;
class CookiesTreeModel;
class CookieTreeAppCacheNode;
Expand Down Expand Up @@ -173,6 +178,14 @@ class CookieTreeNode : public ui::TreeNode<CookieTreeNode> {
protected:
void AddChildSortedByTitle(std::unique_ptr<CookieTreeNode> new_child);

#if !defined(OS_ANDROID)
// TODO (crbug.com/1113602): Remove this when all storage deletions from
// the browser process use the StoragePartition directly.
void ReportDeletionToAuditService(
const url::Origin& origin,
AccessContextAuditDatabase::StorageAPIType type);
#endif // !defined(OS_ANDROID)

private:
DISALLOW_COPY_AND_ASSIGN(CookieTreeNode);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,24 @@ void PageSpecificContentSettingsDelegate::OnCookieAccessAllowed(
#endif // !defined(OS_ANDROID)
}

void PageSpecificContentSettingsDelegate::OnDomStorageAccessAllowed(
const url::Origin& origin) {
#if !defined(OS_ANDROID)
RecordOriginStorageAccess(
origin, AccessContextAuditDatabase::StorageAPIType::kLocalStorage,
web_contents());
#endif // !defined(OS_ANDROID)
}

void PageSpecificContentSettingsDelegate::OnFileSystemAccessAllowed(
const url::Origin& origin) {
#if !defined(OS_ANDROID)
RecordOriginStorageAccess(
origin, AccessContextAuditDatabase::StorageAPIType::kFileSystem,
web_contents());
#endif // !defined(OS_ANDROID)
}

void PageSpecificContentSettingsDelegate::OnIndexedDBAccessAllowed(
const url::Origin& origin) {
#if !defined(OS_ANDROID)
Expand All @@ -201,6 +219,24 @@ void PageSpecificContentSettingsDelegate::OnIndexedDBAccessAllowed(
#endif // !defined(OS_ANDROID)
}

void PageSpecificContentSettingsDelegate::OnServiceWorkerAccessAllowed(
const url::Origin& origin) {
#if !defined(OS_ANDROID)
RecordOriginStorageAccess(
origin, AccessContextAuditDatabase::StorageAPIType::kServiceWorker,
web_contents());
#endif // !defined(OS_ANDROID)
}

void PageSpecificContentSettingsDelegate::OnWebDatabaseAccessAllowed(
const url::Origin& origin) {
#if !defined(OS_ANDROID)
RecordOriginStorageAccess(
origin, AccessContextAuditDatabase::StorageAPIType::kWebDatabase,
web_contents());
#endif // !defined(OS_ANDROID)
}

void PageSpecificContentSettingsDelegate::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
if (!navigation_handle->IsInMainFrame() ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ class PageSpecificContentSettingsDelegate
void OnContentBlocked(ContentSettingsType type) override;
void OnCacheStorageAccessAllowed(const url::Origin& origin) override;
void OnCookieAccessAllowed(const net::CookieList& accessed_cookies) override;
void OnDomStorageAccessAllowed(const url::Origin& origin) override;
void OnFileSystemAccessAllowed(const url::Origin& origin) override;
void OnIndexedDBAccessAllowed(const url::Origin& origin) override;
void OnServiceWorkerAccessAllowed(const url::Origin& origin) override;
void OnWebDatabaseAccessAllowed(const url::Origin& origin) override;

// content::WebContentsObserver:
void DidFinishNavigation(
Expand Down
30 changes: 26 additions & 4 deletions chrome/test/data/browsing_data/embeds_storage_accessor.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
<html>
<script>
// Set a cookie at the embedder level.
document.cookie = `embedder=embedder; max-age=3600;path=/`
async function accessStorage() {
// Set a cookie at the embedder level.
document.cookie = `embedder=embedder; max-age=3600;path=/`;

// Access local storage.
localStorage.setItem('bar', 'bar');

// Access web database.
window.openDatabase('bar', '1.0', 'bar DB', 1024);

// Access file system.
const file_system_promise = new Promise(function(resolve, reject) {
window.webkitRequestFileSystem(TEMPORARY, 1024, fs => {
fs.root.getFile("foo.txt");
resolve();
});
});
await file_system_promise;

// Access service worker.
await navigator.serviceWorker.register("empty.js");

// Access cache storage.
caches.open('test');
await caches.open('test');

// Access Indexed DB.
indexedDB.open("test");
await indexedDB.open("bar");

return true;
}
</script>
<body>
<iframe src="
Expand Down
Empty file.
30 changes: 26 additions & 4 deletions chrome/test/data/browsing_data/storage_accessor.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<html>
<script>
// Set cookie which persists across restart.
async function accessStorage() {
// Set cookie which persists across restart.
document.cookie = `persistent=persistent;max-age=3600;` +
'path=/;SameSite=None;Secure'
'path=/;SameSite=None;Secure';

// Set a non-persistent cookie.
document.cookie = 'session_only=session_only; path=/;' +
Expand All @@ -12,11 +13,32 @@
document.cookie = 'expired=;expires=Thu, 01 Jan 1970 00:00:00 GMT;' +
'SameSite=None; Secure';

// Access local storage.
localStorage.setItem('foo', 'bar');

// Access web database.
window.openDatabase('foo', '1.0', 'foo DB', 1024);

// Access file system.
const file_system_promise = new Promise(function(resolve, reject) {
window.webkitRequestFileSystem(TEMPORARY, 1024, fs => {
fs.root.getFile("foo.txt");
resolve();
});
});
await file_system_promise;

// Access service worker.
await navigator.serviceWorker.register("empty.js");

// Access cache storage.
caches.open('test');
await caches.open('test');

// Access Indexed DB.
indexedDB.open("test");
await indexedDB.open("test");

return true;
}
</script>
<body>
</body>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -594,10 +594,12 @@ void PageSpecificContentSettings::OnDomStorageAccessed(const GURL& url,
local ? container.local_storages() : container.session_storages();
helper->Add(url::Origin::Create(url));

if (blocked_by_policy)
if (blocked_by_policy) {
OnContentBlocked(ContentSettingsType::COOKIES);
else
} else {
delegate_->OnDomStorageAccessAllowed(url::Origin::Create(url));
OnContentAllowed(ContentSettingsType::COOKIES);
}

handler_.NotifySiteDataObservers();
}
Expand Down Expand Up @@ -656,6 +658,7 @@ void PageSpecificContentSettings::OnServiceWorkerAccessed(
if (allowed) {
allowed_local_shared_objects_.service_workers()->Add(
url::Origin::Create(scope));
delegate_->OnServiceWorkerAccessAllowed(url::Origin::Create(scope));
} else {
blocked_local_shared_objects_.service_workers()->Add(
url::Origin::Create(scope));
Expand Down Expand Up @@ -698,6 +701,7 @@ void PageSpecificContentSettings::OnWebDatabaseAccessed(
OnContentBlocked(ContentSettingsType::COOKIES);
} else {
allowed_local_shared_objects_.databases()->Add(url::Origin::Create(url));
delegate_->OnWebDatabaseAccessAllowed(url::Origin::Create(url));
OnContentAllowed(ContentSettingsType::COOKIES);
}

Expand All @@ -714,6 +718,7 @@ void PageSpecificContentSettings::OnFileSystemAccessed(const GURL& url,
OnContentBlocked(ContentSettingsType::COOKIES);
} else {
allowed_local_shared_objects_.file_systems()->Add(url::Origin::Create(url));
delegate_->OnFileSystemAccessAllowed(url::Origin::Create(url));
OnContentAllowed(ContentSettingsType::COOKIES);
}

Expand Down
Loading

0 comments on commit 8e0838c

Please sign in to comment.