Skip to content

Commit

Permalink
Shared Storage: Add methods to DevTools for deleting entries.
Browse files Browse the repository at this point in the history
The standard DevTools Frontend storage items view has buttons to delete
all entries and to delete selected entries. Thus, in order to have a
similar interface for the Shared Storage items view, we need to add
methods that hook into `SharedStorageManager::Clear()` and
`SharedStorageManager::Delete()`.

Bug: 1372007,1218540
Change-Id: Ie92efd58a31d8332077b6f54d16a2fcb9aedc0d7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3991337
Reviewed-by: Danil Somsikov <dsv@chromium.org>
Reviewed-by: Andrey Kosyakov <caseq@chromium.org>
Reviewed-by: Philip Rogers <pdr@chromium.org>
Commit-Queue: Cammie Smith Barnes <cammie@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1067323}
  • Loading branch information
pythagoraskitty authored and Chromium LUCI CQ committed Nov 4, 2022
1 parent cc36d28 commit f659a28
Show file tree
Hide file tree
Showing 9 changed files with 352 additions and 1 deletion.
73 changes: 73 additions & 0 deletions content/browser/devtools/protocol/storage_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,79 @@ void StorageHandler::GetSharedStorageEntries(
base::BindOnce(&RetrieveSharedStorageEntries, std::move(callback)));
}

namespace {

template <typename CallbackType>
void DispatchSharedStorageCallback(
std::unique_ptr<CallbackType> callback,
storage::SharedStorageManager::OperationResult result) {
if (result != storage::SharedStorageManager::OperationResult::kSuccess) {
callback->sendFailure(Response::ServerError("Database error"));
return;
}

callback->sendSuccess();
}

} // namespace

void StorageHandler::DeleteSharedStorageEntry(
const std::string& owner_origin_string,
const std::string& key,
std::unique_ptr<DeleteSharedStorageEntryCallback> callback) {
auto manager_or_response = GetSharedStorageManager();
if (absl::holds_alternative<protocol::Response>(manager_or_response)) {
callback->sendFailure(absl::get<protocol::Response>(manager_or_response));
return;
}

storage::SharedStorageManager* manager =
absl::get<storage::SharedStorageManager*>(manager_or_response);
DCHECK(manager);

GURL owner_origin_url(owner_origin_string);
if (!owner_origin_url.is_valid()) {
callback->sendFailure(Response::InvalidParams("Invalid owner origin"));
return;
}
url::Origin owner_origin = url::Origin::Create(owner_origin_url);
DCHECK(!owner_origin.opaque());

manager->Delete(
owner_origin, base::UTF8ToUTF16(key),
base::BindOnce(
&DispatchSharedStorageCallback<DeleteSharedStorageEntryCallback>,
std::move(callback)));
}

void StorageHandler::ClearSharedStorageEntries(
const std::string& owner_origin_string,
std::unique_ptr<ClearSharedStorageEntriesCallback> callback) {
auto manager_or_response = GetSharedStorageManager();
if (absl::holds_alternative<protocol::Response>(manager_or_response)) {
callback->sendFailure(absl::get<protocol::Response>(manager_or_response));
return;
}

storage::SharedStorageManager* manager =
absl::get<storage::SharedStorageManager*>(manager_or_response);
DCHECK(manager);

GURL owner_origin_url(owner_origin_string);
if (!owner_origin_url.is_valid()) {
callback->sendFailure(Response::InvalidParams("Invalid owner origin"));
return;
}
url::Origin owner_origin = url::Origin::Create(owner_origin_url);
DCHECK(!owner_origin.opaque());

manager->Clear(
owner_origin,
base::BindOnce(
&DispatchSharedStorageCallback<ClearSharedStorageEntriesCallback>,
std::move(callback)));
}

Response StorageHandler::SetSharedStorageTracking(bool enable) {
if (enable) {
if (!GetSharedStorageWorkletHostManager())
Expand Down
7 changes: 7 additions & 0 deletions content/browser/devtools/protocol/storage_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ class StorageHandler : public DevToolsDomainHandler,
void GetSharedStorageEntries(
const std::string& owner_origin_string,
std::unique_ptr<GetSharedStorageEntriesCallback> callback) override;
void DeleteSharedStorageEntry(
const std::string& owner_origin_string,
const std::string& key,
std::unique_ptr<DeleteSharedStorageEntryCallback> callback) override;
void ClearSharedStorageEntries(
const std::string& owner_origin_string,
std::unique_ptr<ClearSharedStorageEntriesCallback> callback) override;
Response SetSharedStorageTracking(bool enable) override;

private:
Expand Down
2 changes: 1 addition & 1 deletion content/browser/devtools/protocol_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
},
{
"domain": "Storage",
"async": ["getUsageAndQuota", "clearDataForOrigin", "clearDataForStorageKey", "getCookies", "setCookies", "clearCookies", "overrideQuotaForOrigin", "getTrustTokens", "clearTrustTokens", "getInterestGroupDetails", "getSharedStorageMetadata", "getSharedStorageEntries"]
"async": ["getUsageAndQuota", "clearDataForOrigin", "clearDataForStorageKey", "getCookies", "setCookies", "clearCookies", "overrideQuotaForOrigin", "getTrustTokens", "clearTrustTokens", "getInterestGroupDetails", "getSharedStorageMetadata", "getSharedStorageEntries", "deleteSharedStorageEntry", "clearSharedStorageEntries"]
},
{
"domain": "SystemInfo",
Expand Down
11 changes: 11 additions & 0 deletions third_party/blink/public/devtools_protocol/browser_protocol.pdl
Original file line number Diff line number Diff line change
Expand Up @@ -9300,6 +9300,17 @@ experimental domain Storage
returns
array of SharedStorageEntry entries

# Deletes entry for `key` (if it exists) for a given origin's shared storage.
experimental command deleteSharedStorageEntry
parameters
string ownerOrigin
string key

# Clears all entries for a given origin's shared storage.
experimental command clearSharedStorageEntries
parameters
string ownerOrigin

# Enables/disables issuing of sharedStorageAccessed events.
experimental command setSharedStorageTracking
parameters
Expand Down
2 changes: 2 additions & 0 deletions third_party/blink/web_tests/VirtualTestSuites
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,7 @@
"wpt_internal/shared_storage",
"external/wpt/shared-storage",
"http/tests/inspector-protocol/storage/shared-storage.js",
"http/tests/inspector-protocol/storage/shared-storage-delete.js",
"http/tests/inspector-protocol/storage/shared-storage-tracking-disabled.js"
],
"args": ["--enable-features=SharedStorageAPI,FencedFrames:implementation_type/mparch,PrivacySandboxAdsAPIsOverride"]
Expand All @@ -1098,6 +1099,7 @@
"wpt_internal/shared_storage",
"external/wpt/shared-storage",
"http/tests/inspector-protocol/storage/shared-storage.js",
"http/tests/inspector-protocol/storage/shared-storage-delete.js",
"http/tests/inspector-protocol/storage/shared-storage-tracking-disabled.js"
],
"args": ["--enable-features=SharedStorageAPI,FencedFrames:implementation_type/shadow_dom,PrivacySandboxAdsAPIsOverride"]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Tests shared storage item deletion & clearing via devtools.

Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
(async function(testRunner) {
const {dp, session, page} = await testRunner.startBlank(
`Tests shared storage item deletion & clearing via devtools.`);

if (typeof self.sharedStorage === 'undefined') {
testRunner.completeTest();
return;
}

const baseOrigin = 'http://127.0.0.1:8000/';

async function getSharedStorageMetadata(dp, testRunner, origin) {
const data =
await dp.Storage.getSharedStorageMetadata({ownerOrigin: origin});
testRunner.log(data.result?.metadata, 'Metadata: ', ['creationTime']);
}

async function getSharedStorageEntries(dp, testRunner, origin) {
const entriesResult =
await dp.Storage.getSharedStorageEntries({ownerOrigin: baseOrigin});
testRunner.log(entriesResult.result?.entries, 'Entries:');
}

async function getSharedStorageEvents(testRunner, events) {
testRunner.log(events, 'Events: ', ['accessTime', 'mainFrameId']);
}

const events = [];
let totalEventsSoFar = 0;

async function getPromiseForEventCount(numEvents) {
totalEventsSoFar += numEvents;
return dp.Storage.onceSharedStorageAccessed(messageObject => {
events.push(messageObject.params);
return (events.length === totalEventsSoFar);
});
}

await dp.Storage.setSharedStorageTracking({enable: true});

eventPromise = getPromiseForEventCount(4);

// The following calls should trigger events if shared storage is enabled, as
// tracking is now enabled.
//
// Generates 4 events.
await session.evaluateAsync(`
sharedStorage.set('key0-set-from-document', 'value0');
sharedStorage.set('key1-set-from-document', 'value1');
sharedStorage.append('key1-set-from-document', 'value1');
sharedStorage.set('key2-set-from-document', 'value2');
`);

// We wait to ensure that metadata and entries are done updating before we
// retrieve them.
await eventPromise;

await getSharedStorageMetadata(dp, testRunner, baseOrigin);
await getSharedStorageEntries(dp, testRunner, baseOrigin);

testRunner.log(`Delete an existing entry via devtools`);
await dp.Storage.deleteSharedStorageEntry(
{ownerOrigin: baseOrigin, key: 'key2-set-from-document'});

testRunner.log(`Delete a non-existing entry via devtools`);
await dp.Storage.deleteSharedStorageEntry(
{ownerOrigin: baseOrigin, key: 'key3-set-from-document'});

await getSharedStorageMetadata(dp, testRunner, baseOrigin);
await getSharedStorageEntries(dp, testRunner, baseOrigin);

testRunner.log(`Clear entries via devtools`);
await dp.Storage.clearSharedStorageEntries({ownerOrigin: baseOrigin});

await getSharedStorageMetadata(dp, testRunner, baseOrigin);
await getSharedStorageEntries(dp, testRunner, baseOrigin);
await getSharedStorageEvents(testRunner, events);

testRunner.completeTest();
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
Tests shared storage item deletion & clearing via devtools.
Metadata: {
creationTime : <number>
length : 3
remainingBudget : 12
}
Entries:[
[0] : {
key : key0-set-from-document
value : value0
}
[1] : {
key : key1-set-from-document
value : value1value1
}
[2] : {
key : key2-set-from-document
value : value2
}
]
Delete an existing entry via devtools
Delete a non-existing entry via devtools
Metadata: {
creationTime : <number>
length : 2
remainingBudget : 12
}
Entries:[
[0] : {
key : key0-set-from-document
value : value0
}
[1] : {
key : key1-set-from-document
value : value1value1
}
]
Clear entries via devtools
Metadata: {
creationTime : <number>
length : 0
remainingBudget : 12
}
Entries:[
]
Events: [
[0] : {
accessTime : <number>
mainFrameId : <string>
ownerOrigin : http://127.0.0.1:8000
params : {
key : key0-set-from-document
value : value0
}
type : documentSet
}
[1] : {
accessTime : <number>
mainFrameId : <string>
ownerOrigin : http://127.0.0.1:8000
params : {
key : key1-set-from-document
value : value1
}
type : documentSet
}
[2] : {
accessTime : <number>
mainFrameId : <string>
ownerOrigin : http://127.0.0.1:8000
params : {
key : key1-set-from-document
value : value1
}
type : documentAppend
}
[3] : {
accessTime : <number>
mainFrameId : <string>
ownerOrigin : http://127.0.0.1:8000
params : {
key : key2-set-from-document
value : value2
}
type : documentSet
}
]

Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
Tests shared storage item deletion & clearing via devtools.
Metadata: {
creationTime : <number>
length : 3
remainingBudget : 12
}
Entries:[
[0] : {
key : key0-set-from-document
value : value0
}
[1] : {
key : key1-set-from-document
value : value1value1
}
[2] : {
key : key2-set-from-document
value : value2
}
]
Delete an existing entry via devtools
Delete a non-existing entry via devtools
Metadata: {
creationTime : <number>
length : 2
remainingBudget : 12
}
Entries:[
[0] : {
key : key0-set-from-document
value : value0
}
[1] : {
key : key1-set-from-document
value : value1value1
}
]
Clear entries via devtools
Metadata: {
creationTime : <number>
length : 0
remainingBudget : 12
}
Entries:[
]
Events: [
[0] : {
accessTime : <number>
mainFrameId : <string>
ownerOrigin : http://127.0.0.1:8000
params : {
key : key0-set-from-document
value : value0
}
type : documentSet
}
[1] : {
accessTime : <number>
mainFrameId : <string>
ownerOrigin : http://127.0.0.1:8000
params : {
key : key1-set-from-document
value : value1
}
type : documentSet
}
[2] : {
accessTime : <number>
mainFrameId : <string>
ownerOrigin : http://127.0.0.1:8000
params : {
key : key1-set-from-document
value : value1
}
type : documentAppend
}
[3] : {
accessTime : <number>
mainFrameId : <string>
ownerOrigin : http://127.0.0.1:8000
params : {
key : key2-set-from-document
value : value2
}
type : documentSet
}
]

0 comments on commit f659a28

Please sign in to comment.