From 81f15a784f8de84b69253688432a24158d404258 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 25 Apr 2024 18:07:52 +0400 Subject: [PATCH] Support separate storages. --- CMakeLists.txt | 1 + webview/platform/linux/webview_linux.cpp | 15 +++++++ webview/platform/mac/webview_mac.mm | 51 ++++++++++++++++++++++++ webview/platform/win/webview_win.cpp | 15 +++++++ webview/webview_common.h | 39 ++++++++++++++++++ webview/webview_embed.cpp | 3 +- webview/webview_embed.h | 3 +- webview/webview_interface.h | 16 ++++---- 8 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 webview/webview_common.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b40f4e..b1d3299 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,7 @@ get_filename_component(src_loc . REALPATH) nice_target_sources(lib_webview ${src_loc} PRIVATE + webview/webview_common.h webview/webview_data_stream.h webview/webview_data_stream_memory.cpp webview/webview_data_stream_memory.h diff --git a/webview/platform/linux/webview_linux.cpp b/webview/platform/linux/webview_linux.cpp index b300ce8..5bc597e 100644 --- a/webview/platform/linux/webview_linux.cpp +++ b/webview/platform/linux/webview_linux.cpp @@ -6,6 +6,7 @@ // #include "webview/platform/linux/webview_linux.h" +#include "base/random.h" #include "webview/platform/linux/webview_linux_webkitgtk.h" namespace Webview { @@ -22,8 +23,22 @@ bool NavigateToDataSupported() { return false; } +bool SeparateStorageIdSupported() { + return true; +} + std::unique_ptr CreateInstance(Config config) { return WebKitGTK::CreateInstance(std::move(config)); } +std::string GenerateStorageToken() { + constexpr auto kSize = 16; + auto result = std::string(kSize, ' '); + base::RandomFill(result.data(), result.size()); + return result; +} + +void ClearStorageDataByToken(const std::string &token) { +} + } // namespace Webview diff --git a/webview/platform/mac/webview_mac.mm b/webview/platform/mac/webview_mac.mm index 657c5a4..e7808fc 100644 --- a/webview/platform/mac/webview_mac.mm +++ b/webview/platform/mac/webview_mac.mm @@ -27,6 +27,7 @@ constexpr auto kDataUrlScheme = std::string_view("desktop-app-resource"); constexpr auto kFullDomain = std::string_view("desktop-app-resource://domain/"); constexpr auto kPartsCacheLimit = 32 * 1024 * 1024; +constexpr auto kUuidSize = 16; [[nodiscard]] NSString *stdToNS(std::string_view value) { return [[NSString alloc] @@ -301,6 +302,23 @@ void taskDone( }; +[[nodiscard]] NSUUID *UuidFromToken(const std::string &token) { + const auto bytes = reinterpret_cast(token.data()); + return (token.size() == kUuidSize) + ? [[NSUUID alloc] initWithUUIDBytes:bytes] + : nil; +} + +[[nodiscard]] std::string UuidToToken(NSUUID *uuid) { + if (!uuid) { + return std::string(); + } + auto result = std::string(kUuidSize, ' '); + const auto bytes = reinterpret_cast(result.data()); + [uuid getUUIDBytes:bytes]; + return result; +} + Instance::Instance(Config config) { const auto weak = base::make_weak(this); const auto handleDataRequest = [=](id task, bool started) { @@ -316,6 +334,13 @@ void taskDone( _handler = [[Handler alloc] initWithMessageHandler:config.messageHandler navigationStartHandler:config.navigationStartHandler navigationDoneHandler:config.navigationDoneHandler dialogHandler:config.dialogHandler dataRequested:handleDataRequest]; _dataRequestHandler = std::move(config.dataRequestHandler); [configuration setURLSchemeHandler:_handler forURLScheme:stdToNS(kDataUrlScheme)]; + if (@available(macOS 14, *)) { + if (config.userDataToken != LegacyStorageIdToken().toStdString()) { + NSUUID *uuid = UuidFromToken(config.userDataToken); + [configuration setWebsiteDataStore:[WKWebsiteDataStore dataStoreForIdentifier:uuid]]; + [uuid release]; + } + } _webview = [[WKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]; if (@available(macOS 13.3, *)) { _webview.inspectable = config.debug ? YES : NO; @@ -698,6 +723,10 @@ bool NavigateToDataSupported() { return true; } +bool SeparateStorageIdSupported() { + return true; +} + std::unique_ptr CreateInstance(Config config) { if (!Supported()) { return nullptr; @@ -705,4 +734,26 @@ bool NavigateToDataSupported() { return std::make_unique(std::move(config)); } +std::string GenerateStorageToken() { + return UuidToToken([NSUUID UUID]); +} + +void ClearStorageDataByToken(const std::string &token) { + if (@available(macOS 14, *)) { + if (!token.empty() && token != LegacyStorageIdToken().toStdString()) { + if (NSUUID *uuid = UuidFromToken(token)) { + // removeDataStoreForIdentifier crashes without that (if not created first). + WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init]; + [configuration setWebsiteDataStore:[WKWebsiteDataStore dataStoreForIdentifier:uuid]]; + [configuration release]; + + [WKWebsiteDataStore + removeDataStoreForIdentifier:uuid + completionHandler:^(NSError *error) {}]; + [uuid release]; + } + } + } +} + } // namespace Webview diff --git a/webview/platform/win/webview_win.cpp b/webview/platform/win/webview_win.cpp index ee2b8c1..363c15d 100644 --- a/webview/platform/win/webview_win.cpp +++ b/webview/platform/win/webview_win.cpp @@ -6,6 +6,7 @@ // #include "webview/platform/win/webview_win.h" +#include "base/random.h" #include "base/platform/base_platform_info.h" #include "webview/platform/win/webview_windows_edge_chromium.h" #include "webview/platform/win/webview_windows_edge_html.h" @@ -36,6 +37,10 @@ bool NavigateToDataSupported() { return EdgeChromium::Supported(); } +bool SeparateStorageIdSupported() { + return EdgeChromium::Supported(); +} + std::unique_ptr CreateInstance(Config config) { if (!Platform::IsWindows8Point1OrGreater()) { return nullptr; @@ -46,4 +51,14 @@ std::unique_ptr CreateInstance(Config config) { return EdgeHtml::CreateInstance(config); } +std::string GenerateStorageToken() { + constexpr auto kSize = 16; + auto result = std::string(kSize, ' '); + base::RandomFill(result.data(), result.size()); + return result; +} + +void ClearStorageDataByToken(const std::string &token) { +} + } // namespace Webview diff --git a/webview/webview_common.h b/webview/webview_common.h new file mode 100644 index 0000000..3338f49 --- /dev/null +++ b/webview/webview_common.h @@ -0,0 +1,39 @@ +// This file is part of Desktop App Toolkit, +// a set of libraries for developing nice desktop applications. +// +// For license and copyright information please follow this link: +// https://github.com/desktop-app/legal/blob/master/LEGAL +// +#pragma once + +#include "base/basic_types.h" + +#include +#include +#include + +namespace Webview { + +struct StorageId { + QString path; + QByteArray token; + + explicit operator bool() const { + return !path.isEmpty() && !token.isEmpty(); + } +}; + +[[nodiscard]] inline QByteArray LegacyStorageIdToken() { + return ""_q; +} + +struct ThemeParams { + QColor opaqueBg; + QColor scrollBg; + QColor scrollBgOver; + QColor scrollBarBg; + QColor scrollBarBgOver; + QByteArray json; +}; + +} // namespace Webview diff --git a/webview/webview_embed.cpp b/webview/webview_embed.cpp index 1669f21..f3a9f77 100644 --- a/webview/webview_embed.cpp +++ b/webview/webview_embed.cpp @@ -99,7 +99,8 @@ bool Window::createWebView(QWidget *parent, const WindowConfig &config) { .navigationDoneHandler = navigationDoneHandler(), .dialogHandler = dialogHandler(), .dataRequestHandler = dataRequestHandler(), - .userDataPath = config.userDataPath.toStdString(), + .userDataPath = config.storageId.path.toStdString(), + .userDataToken = config.storageId.token.toStdString(), .debug = OptionWebviewDebugEnabled.value(), }); } diff --git a/webview/webview_embed.h b/webview/webview_embed.h index bf8183e..bfd3158 100644 --- a/webview/webview_embed.h +++ b/webview/webview_embed.h @@ -8,6 +8,7 @@ #include "base/unique_qptr.h" #include "base/basic_types.h" +#include "webview/webview_common.h" #include #include @@ -29,7 +30,7 @@ enum class DataResult; struct WindowConfig { QColor opaqueBg; - QString userDataPath; + StorageId storageId; }; class Window final { diff --git a/webview/webview_interface.h b/webview/webview_interface.h index 226428e..cd9b8a8 100644 --- a/webview/webview_interface.h +++ b/webview/webview_interface.h @@ -6,6 +6,8 @@ // #pragma once +#include "webview/webview_common.h" + #include #include #include @@ -21,15 +23,6 @@ namespace Webview { class DataStream; -struct ThemeParams { - QColor opaqueBg; - QColor scrollBg; - QColor scrollBgOver; - QColor scrollBarBg; - QColor scrollBarBgOver; - QByteArray json; -}; - class Interface { public: virtual ~Interface() = default; @@ -102,6 +95,7 @@ struct Config { std::function dialogHandler; std::function dataRequestHandler; std::string userDataPath; + std::string userDataToken; bool debug = false; }; @@ -124,8 +118,12 @@ void ParseRangeHeaderFor(DataRequest &request, std::string_view header); } [[nodiscard]] bool SupportsEmbedAfterCreate(); [[nodiscard]] bool NavigateToDataSupported(); +[[nodiscard]] bool SeparateStorageIdSupported(); // HWND on Windows, nullptr on macOS, GtkWindow on Linux. [[nodiscard]] std::unique_ptr CreateInstance(Config config); +[[nodiscard]] std::string GenerateStorageToken(); +void ClearStorageDataByToken(const std::string &token); + } // namespace Webview