* WIP: Session.clearBrowsingData API

* impl API method

* clean up

* tidy types and comments

* add docs

* add barebones test

* forgot a `#` :(

* tidy: address review comments

* use format macro for cross-platform build

* add another test

* amend docs to disambiguate

* Rename to `clearData`
This commit is contained in:
Calvin 2024-02-25 17:39:17 -07:00 коммит произвёл GitHub
Родитель e95673b052
Коммит 12d7a8ff66
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
4 изменённых файлов: 106 добавлений и 0 удалений

Просмотреть файл

@ -1424,6 +1424,26 @@ is emitted.
Returns `string | null` - The absolute file system path where data for this
session is persisted on disk. For in memory sessions this returns `null`.
#### `ses.clearData()`
Returns `Promise<void>` - resolves when all data has been cleared.
This method clears many different types of data, inlcuding:
* Cache
* Cookies
* Downloads
* IndexedDB
* Local Storage
* Service Workers
* And more...
This method clears more types of data and is more thourough than the
`clearStorageData` method, however it is currently less configurable than that
method.
For more information, refer to Chromium's [`BrowsingDataRemover` interface](https://source.chromium.org/chromium/chromium/src/+/main:content/public/browser/browsing_data_remover.h).
### Instance Properties
The following properties are available on instances of `Session`:

Просмотреть файл

@ -16,6 +16,7 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/uuid.h"
@ -32,6 +33,7 @@
#include "content/browser/code_cache/generated_code_cache_context.h" // nogncheck
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/download_item_utils.h"
#include "content/public/browser/download_manager_delegate.h"
#include "content/public/browser/network_service_instance.h"
@ -77,6 +79,7 @@
#include "shell/common/gin_converters/value_converter.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/object_template_builder.h"
#include "shell/common/gin_helper/promise.h"
#include "shell/common/node_includes.h"
#include "shell/common/options_switches.h"
#include "shell/common/process_util.h"
@ -149,6 +152,40 @@ uint32_t GetQuotaMask(const std::vector<std::string>& quota_types) {
return quota_mask;
}
constexpr content::BrowsingDataRemover::DataType kClearDataTypeAll = ~0ULL;
constexpr content::BrowsingDataRemover::OriginType kClearOriginTypeAll =
content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB |
content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB;
// Observes the BrowsingDataRemover that backs the `clearData` method and
// fulfills that API's promise once it's done. This type manages its own
// lifetime, deleting itself once it's done.
class ClearDataObserver : public content::BrowsingDataRemover::Observer {
public:
ClearDataObserver(gin_helper::Promise<void> promise,
content::BrowsingDataRemover* remover)
: promise_(std::move(promise)) {
observation_.Observe(remover);
}
void OnBrowsingDataRemoverDone(
content::BrowsingDataRemover::DataType failed_data_types) override {
if (failed_data_types == 0ULL) {
promise_.Resolve();
} else {
promise_.RejectWithErrorMessage(base::StringPrintf(
"Failed to clear browsing data (%" PRIu64 ")", failed_data_types));
}
delete this;
}
private:
gin_helper::Promise<void> promise_;
base::ScopedObservation<content::BrowsingDataRemover,
content::BrowsingDataRemover::Observer>
observation_{this};
};
base::Value::Dict createProxyConfig(ProxyPrefs::ProxyMode proxy_mode,
std::string const& pac_url,
std::string const& proxy_server,
@ -1101,6 +1138,21 @@ v8::Local<v8::Promise> Session::ClearCodeCaches(
return handle;
}
v8::Local<v8::Promise> Session::ClearData(gin::Arguments* args) {
auto* isolate = JavascriptEnvironment::GetIsolate();
gin_helper::Promise<void> promise(isolate);
v8::Local<v8::Promise> promise_handle = promise.GetHandle();
content::BrowsingDataRemover* remover =
browser_context_->GetBrowsingDataRemover();
auto* observer = new ClearDataObserver(std::move(promise), remover);
remover->RemoveAndReply(base::Time::Min(), base::Time::Max(),
kClearDataTypeAll, kClearOriginTypeAll, observer);
return promise_handle;
}
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
base::Value Session::GetSpellCheckerLanguages() {
return browser_context_->prefs()
@ -1370,6 +1422,7 @@ void Session::FillObjectTemplate(v8::Isolate* isolate,
.SetMethod("getStoragePath", &Session::GetPath)
.SetMethod("setCodeCachePath", &Session::SetCodeCachePath)
.SetMethod("clearCodeCaches", &Session::ClearCodeCaches)
.SetMethod("clearData", &Session::ClearData)
.SetProperty("cookies", &Session::Cookies)
.SetProperty("netLog", &Session::NetLog)
.SetProperty("protocol", &Session::Protocol)

Просмотреть файл

@ -147,6 +147,7 @@ class Session : public gin::Wrappable<Session>,
v8::Local<v8::Value> GetPath(v8::Isolate* isolate);
void SetCodeCachePath(gin::Arguments* args);
v8::Local<v8::Promise> ClearCodeCaches(const gin_helper::Dictionary& options);
v8::Local<v8::Promise> ClearData(gin::Arguments* args);
#if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
base::Value GetSpellCheckerLanguages();
void SetSpellCheckerLanguages(gin_helper::ErrorThrower thrower,

Просмотреть файл

@ -1607,4 +1607,36 @@ describe('session module', () => {
await expect(request()).to.be.rejectedWith(/ERR_SSL_VERSION_OR_CIPHER_MISMATCH/);
});
});
describe('ses.clearData()', () => {
afterEach(closeAllWindows);
// NOTE: This API clears more than localStorage, but localStorage is a
// convenient test target for this API
it('clears localstorage data', async () => {
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } });
await w.loadFile(path.join(fixtures, 'api', 'localstorage.html'));
expect(await w.webContents.executeJavaScript('localStorage.length')).to.be.greaterThan(0);
await w.webContents.session.clearData();
expect(await w.webContents.executeJavaScript('localStorage.length')).to.equal(0);
});
it('clears localstorage data when called twice in parallel', async () => {
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } });
await w.loadFile(path.join(fixtures, 'api', 'localstorage.html'));
expect(await w.webContents.executeJavaScript('localStorage.length')).to.be.greaterThan(0);
// This first call is not awaited immediately
const clearDataPromise = w.webContents.session.clearData();
await w.webContents.session.clearData();
expect(await w.webContents.executeJavaScript('localStorage.length')).to.equal(0);
// Await the first promise so it doesn't creep into another test
await clearDataPromise;
});
});
});