Skip to content

Commit

Permalink
Add portal fixes & unified extension point
Browse files Browse the repository at this point in the history
Fixes #49, #53, #78.
  • Loading branch information
refi64 committed Apr 14, 2021
1 parent 60fe20e commit eaa74f8
Show file tree
Hide file tree
Showing 24 changed files with 90 additions and 70 deletions.
41 changes: 16 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,27 @@
### Extension points

To avoid having to expose more of the host filesystem in the sandbox but still
allowing extending Chromium, the following extension points are defined:
- org.chromium.Chromium.Policy
- org.chromium.Chromium.Extension
- org.chromium.Chromium.NativeMessagingHost
allowing extending Chromium, the `org.chromium.Chromium.Extension` extension
point is defined.

#### org.chromium.Chromium.Policy
This extension point is currently on version '1' and will expose any extension
manifests under the `extensions` subdirectory, policy files under
`policies/managed` and `policies/recommended`, and [native messaging host
manifests](https://developer.chrome.com/docs/apps/nativeMessaging/) under
`native-messaging-hosts`.

This extension point can be used to configure custom Chromium policies and is
currently on version '1' and will make any policy under the `policies/managed` and
`policies/recommended` subdirectories available to Chromium.
#### Legacy extension points

#### org.chromium.Chromium.Extension

Similarly to the above, but for Chromium extensions, this extension point is
also currently on version '1' and will make any extension under the `extensions`
subdirectory available to Chromium.

#### org.chromium.Chromium.NativeMessagingHost

Also as above, but for [native messaging host](https://developer.chrome.com/docs/apps/nativeMessaging/)
support. As the other extension points, this extension point is also currently
on version '1' and exposes the `native-messaging-hosts` subdirectory to Chromium.
This application also supports two other extension points:
`org.chromium.Chromium.Policy` and `org.chromium.Chromium.NativeMessagingHost`.
These primarily exist for compatibility reasons and should not be used.

#### Using extension points

Extension points can be provided as regular flatpaks and an example is provided
under `examples/policies/google-safe-search`. Important to note that extension points'
name must follow the syntax of `<ExtensionPointName>.<id>`, where `<ExtensionPointName>`
is one of the supported extension points above and `<id>` is a generic id for this
specific extension point.
under `examples/policies/google-safe-search`. Important to note that extension
points' name must follow the syntax of `Extension.<id>`, where `<id>` is a
generic id for this specific extension point.

Flatpak also supports “unmanaged extensions”, allowing loading extensions installed
into `/var/lib/flatpak/extension` and `$XDG_DATA_HOME/flatpak/extension`.
Expand All @@ -42,8 +33,8 @@ policies, extensions, etc.
One example of such "unmanaged extension" could be an extension point that exposes
all system policies installed under `/etc/chromium-browser/policies/{managed,recommended}`.
This could be done for example by creating an extension point under
`/var/lib/flatpak/extension/org.chromium.Chromium.Policy.system-policies`, with
`/var/lib/flatpak/extension/org.chromium.Chromium.Policy.system-policies/<arch>/<version>`
`/var/lib/flatpak/extension/org.chromium.Chromium.Extension.system-policies`, with
`/var/lib/flatpak/extension/org.chromium.Chromium.Extension.system-policies/<arch>/<version>`
being a symlink to `/etc/chromium-browser`. Note that `<version>` must match the
extension point version.

Expand Down
19 changes: 19 additions & 0 deletions chromium.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ get_int32_property() {
| awk 'match($0, /uint32 ([0-9]+)/, m){print m[1];}'
}

merge_extensions() {
(
shopt -s nullglob
dest=/app/chromium/extensions/$1
mkdir -p $dest
for ext in /app/chromium/${1%/*}/$1/*; do
ln -s $ext $dest
done
)
}

# Check the portal version & make sure it supports expose-pids.
if [[ $(get_int32_property version) -lt 4 || \
$(($(get_int32_property supports) & 1)) -eq 0 ]]; then
Expand All @@ -26,6 +37,14 @@ if [[ -f "$XDG_CONFIG_HOME/chromium-flags.conf" ]]; then
set -- "${flags[@]}" "$@"
fi

if [[ ! -f /app/chromium/extensions/no-mount-stamp ]]; then
# Merge all legacy extension points if the symlinks had a tmpfs mounted over
# them.
merge_extensions native-messaging-hosts
merge_extensions policies/managed
merge_extensions policies/recommended
fi

flextop-init

export TMPDIR="$XDG_RUNTIME_DIR/app/$FLATPAK_ID"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
app-id: org.chromium.Chromium.Policy.google-safe-search
app-id: org.chromium.Chromium.Extension.google-safe-search-policy
# This should match the extension point version
branch: '1'
runtime: org.chromium.Chromium
runtime-version: 'stable'
runtime-version: stable
sdk: org.freedesktop.Sdk//20.08
build-extension: true
appstream-compose: false
Expand Down
4 changes: 3 additions & 1 deletion org.chromium.Chromium.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ add-extensions:
org.chromium.Chromium.Extension:
version: '1'
directory: chromium/extensions
merge-dirs: extensions
merge-dirs: 'extensions;native-messaging-hosts;policies/managed;policies/recommended'
subdirectories: true
no-autodownload: true
autodelete: true
Expand Down Expand Up @@ -155,6 +155,8 @@ modules:
buildsystem: simple
build-commands:
- mkdir -p /app/chromium/{extensions,native-messaging-hosts,policies}
- for dir in native-messaging-hosts policies; do ln -s /app/chromium/{$dir,extensions}/$dir; done
- touch /app/chromium/extensions/no-mount-stamp

- name: pipewire
buildsystem: meson
Expand Down
2 changes: 1 addition & 1 deletion patches/0005-flatpak-Add-initial-sandbox-support.patch
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From 6c8bdf84df2da131cfe6a848d6a257aeae059979 Mon Sep 17 00:00:00 2001
From b81f8bc8d0c50b901d285b2c738316a1fc796865 Mon Sep 17 00:00:00 2001
From: Ryan Gonzalez <[email protected]>
Date: Tue, 17 Mar 2020 13:18:27 -0500
Subject: [PATCH 05/24] flatpak: Add initial sandbox support
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From 65328e65e68c1d909dbfc6c7615d0e3e57c07b07 Mon Sep 17 00:00:00 2001
From c7421a7caf08140059c50b071257405159acb3e4 Mon Sep 17 00:00:00 2001
From: Ryan Gonzalez <[email protected]>
Date: Tue, 17 Nov 2020 13:00:39 -0600
Subject: [PATCH 06/24] flatpak: Expose Widevine into the sandbox
Expand Down
23 changes: 12 additions & 11 deletions patches/0007-flatpak-Adjust-paths-for-the-sandbox.patch
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
From c29002a8fd98a7855b0e402b803db9e74edc2a7f Mon Sep 17 00:00:00 2001
From d8033a1ec89dfe9d8a1804a4dea82f31e0082a8a Mon Sep 17 00:00:00 2001
From: Ryan Gonzalez <[email protected]>
Date: Tue, 25 Aug 2020 19:26:07 -0500
Subject: [PATCH 07/24] flatpak: Adjust paths for the sandbox

---
chrome/common/BUILD.gn | 4 +++
chrome/common/chrome_paths.cc | 51 +++++++++++++++++++++++++----------
2 files changed, 41 insertions(+), 14 deletions(-)
chrome/common/chrome_paths.cc | 52 +++++++++++++++++++++++++----------
2 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index 737d5ea55058d..b208c819e1001 100644
Expand All @@ -24,7 +24,7 @@ index 737d5ea55058d..b208c819e1001 100644

# Use a static library here because many test binaries depend on this but don't
diff --git a/chrome/common/chrome_paths.cc b/chrome/common/chrome_paths.cc
index fef80b760915b..5e6117ae4bbd2 100644
index fef80b760915b..7b86e93f9708d 100644
--- a/chrome/common/chrome_paths.cc
+++ b/chrome/common/chrome_paths.cc
@@ -4,6 +4,7 @@
Expand Down Expand Up @@ -66,21 +66,22 @@ index fef80b760915b..5e6117ae4bbd2 100644
break;
#elif defined(OS_ANDROID)
if (!base::PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID, &cur))
@@ -445,6 +450,13 @@ bool PathProvider(int key, base::FilePath* result) {
@@ -445,6 +450,14 @@ bool PathProvider(int key, base::FilePath* result) {
break;
#if defined(OS_POSIX) && !defined(OS_MAC) && !defined(OS_OPENBSD)
case chrome::DIR_POLICY_FILES: {
+#if defined(OS_LINUX)
+ if (sandbox::FlatpakSandbox::GetInstance()->GetSandboxLevel() >
+ sandbox::FlatpakSandbox::SandboxLevel::kNone) {
+ cur = base::FilePath(FILE_PATH_LITERAL("/app/chromium/policies"));
+ cur = base::FilePath(
+ FILE_PATH_LITERAL("/app/chromium/extensions/policies"));
+ break;
+ }
+#endif
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
cur = base::FilePath(FILE_PATH_LITERAL("/etc/opt/chrome/policies"));
#else
@@ -468,7 +480,13 @@ bool PathProvider(int key, base::FilePath* result) {
@@ -468,7 +481,13 @@ bool PathProvider(int key, base::FilePath* result) {
#endif
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
case chrome::DIR_STANDALONE_EXTERNAL_EXTENSIONS: {
Expand All @@ -95,7 +96,7 @@ index fef80b760915b..5e6117ae4bbd2 100644
break;
}
#endif
@@ -478,8 +496,8 @@ bool PathProvider(int key, base::FilePath* result) {
@@ -478,8 +497,8 @@ bool PathProvider(int key, base::FilePath* result) {
return false;

cur = cur.Append(FILE_PATH_LITERAL("Google"))
Expand All @@ -106,7 +107,7 @@ index fef80b760915b..5e6117ae4bbd2 100644
create_dir = false;
#else
if (!base::PathService::Get(base::DIR_MODULE, &cur))
@@ -505,19 +523,25 @@ bool PathProvider(int key, base::FilePath* result) {
@@ -505,19 +524,25 @@ bool PathProvider(int key, base::FilePath* result) {
case chrome::DIR_NATIVE_MESSAGING:
#if defined(OS_MAC)
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
Expand All @@ -122,7 +123,7 @@ index fef80b760915b..5e6117ae4bbd2 100644
+ if (sandbox::FlatpakSandbox::GetInstance()->GetSandboxLevel() >
+ sandbox::FlatpakSandbox::SandboxLevel::kNone) {
+ cur = base::FilePath(FILE_PATH_LITERAL(
+ "/app/chromium/native-messaging-hosts/native-messaging-hosts"));
+ "/app/chromium/extensions/native-messaging-hosts"));
+ break;
+ }
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
Expand All @@ -138,7 +139,7 @@ index fef80b760915b..5e6117ae4bbd2 100644
#endif
#endif // !defined(OS_MAC)
break;
@@ -567,8 +591,7 @@ bool PathProvider(int key, base::FilePath* result) {
@@ -567,8 +592,7 @@ bool PathProvider(int key, base::FilePath* result) {

// TODO(bauerb): http://crbug.com/259796
base::ThreadRestrictions::ScopedAllowIO allow_io;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From eaa4091f834c7322b57bfe37b1b04a198ce611ec Mon Sep 17 00:00:00 2001
From 9f99dee0801b83308f4d96203c2df76647b4f56f Mon Sep 17 00:00:00 2001
From: Ryan Gonzalez <[email protected]>
Date: Tue, 17 Nov 2020 22:57:29 -0600
Subject: [PATCH 08/24] Import chromium-71.0.3578.98-widevine-r3.patch
Expand Down
2 changes: 1 addition & 1 deletion patches/0009-Enable-Chromecast-by-default.patch
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From a7511505c0c5773503fe8d2cb9fdb05a880eb477 Mon Sep 17 00:00:00 2001
From d43cdbc2e17a25b4b869d1ba4bbaaeaf3bd5099e Mon Sep 17 00:00:00 2001
From: Ryan Gonzalez <[email protected]>
Date: Wed, 26 Aug 2020 20:30:35 -0500
Subject: [PATCH 09/24] Enable Chromecast by default
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From a38712e54302a4b6b76203095c244dd918286921 Mon Sep 17 00:00:00 2001
From 605a0e6d60d796edbc369864511438717cbd249d Mon Sep 17 00:00:00 2001
From: Daniel Drake <[email protected]>
Date: Fri, 3 Jul 2015 14:59:24 -0600
Subject: [PATCH 10/24] x11: Set _NET_WM_BYPASS_COMPOSITOR for fullscreen
Expand Down
2 changes: 1 addition & 1 deletion patches/0011-memory-Enable-the-tab-discards-feature.patch
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From 8ef08edffc7029d28d26bace847ac69f4d4f90fa Mon Sep 17 00:00:00 2001
From 3bcbeb527a4e16d628a104c26351c0f37285b20c Mon Sep 17 00:00:00 2001
From: Mario Sanchez Prada <[email protected]>
Date: Thu, 28 Jan 2016 13:53:08 +0000
Subject: [PATCH 11/24] memory: Enable the tab discards feature
Expand Down
6 changes: 3 additions & 3 deletions patches/0012-Enable-accelerated-mjpeg-decode-on-Linux.patch
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From f16e60d330e850f646d4ee3f9b4f800acf59e3bd Mon Sep 17 00:00:00 2001
From 4127d847c04a9eb5c4277b1c108c52fd088e9c30 Mon Sep 17 00:00:00 2001
From: Ryan Gonzalez <[email protected]>
Date: Tue, 19 Jan 2021 15:41:16 -0600
Subject: [PATCH 12/24] Enable accelerated mjpeg decode on Linux
Expand Down Expand Up @@ -37,7 +37,7 @@ index 1f7e7ced6a98a..9ba75ccc991e5 100644
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
{"system-keyboard-lock", flag_descriptions::kSystemKeyboardLockName,
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index f9d48948f9824..da89b557079bd 100644
index 5990170b110ad..1afe76e601684 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3693,6 +3693,16 @@ const char kVideoToolboxVp9DecodingDescription[] =
Expand Down Expand Up @@ -99,7 +99,7 @@ index 9ca53437280a4..b022cc15548ee 100644
extern const char kAllowDisableMouseAccelerationDescription[];

diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 61d9578e2ed79..61ea5a3f22eff 100644
index f8b848e7283b7..e14e4d03bb87f 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -861,7 +861,7 @@ bool IsVideoCaptureAcceleratedJpegDecodingEnabled() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From ac6f7a9e10a233359f6e35647cc92351fc7ea03c Mon Sep 17 00:00:00 2001
From 41c94ee9eef1f381cd1d3ebee6315fb2ffa14ee3 Mon Sep 17 00:00:00 2001
From: Mario Sanchez Prada <[email protected]>
Date: Tue, 25 Oct 2016 16:57:00 +0000
Subject: [PATCH 13/24] ffmpeg: Don't lie about AAC and H264 decoders when not
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From aa12f3b1a054acd2e9077d6181bca308b8c4128f Mon Sep 17 00:00:00 2001
From 4849553e64f5f41ef63c526f6540658da10d8c22 Mon Sep 17 00:00:00 2001
From: Ryan Gonzalez <[email protected]>
Date: Wed, 11 Nov 2020 16:51:49 -0600
Subject: [PATCH 14/24] Remove the ability to create desktop shortcuts
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From 64f0a3462bcfdd2eb29beafbc4c0251d00b71661 Mon Sep 17 00:00:00 2001
From 390271e96ffeb8bf54997d9bd87a247a90d88467 Mon Sep 17 00:00:00 2001
From: Ryan Gonzalez <[email protected]>
Date: Wed, 11 Nov 2020 16:53:24 -0600
Subject: [PATCH 15/24] [webhid] Properly handle lack of platform support
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From 0cd9656529014323ca5edc24b3cfbff5c4e26768 Mon Sep 17 00:00:00 2001
From 0f1493d40f4fc8035838f40fdf4f364f5fb1e668 Mon Sep 17 00:00:00 2001
From: Ryan Gonzalez <[email protected]>
Date: Wed, 11 Nov 2020 16:54:18 -0600
Subject: [PATCH 16/24] [webusb] Properly handle lack of platform support
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From c67a84fbdb8e6e7c07128f6e8ddfff50466778b5 Mon Sep 17 00:00:00 2001
From f3e2a5b38b0bb6ddeaae2885f824e53c0d61f110 Mon Sep 17 00:00:00 2001
From: Ryan Gonzalez <[email protected]>
Date: Wed, 11 Nov 2020 17:13:38 -0600
Subject: [PATCH 17/24] Use CHROME_WRAPPER as the executable on restart
Expand Down
29 changes: 18 additions & 11 deletions patches/0018-Add-support-for-the-XDG-file-chooser-portal.patch
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From e55ba047b513752b3ea6dce77c12119dd8e17c01 Mon Sep 17 00:00:00 2001
From 94dc70b2c8267157b661f1a30791acf6a7ec6bea Mon Sep 17 00:00:00 2001
From: Ryan Gonzalez <[email protected]>
Date: Mon, 31 Aug 2020 15:26:52 -0500
Subject: [PATCH 18/24] Add support for the XDG file chooser portal
Expand All @@ -13,9 +13,9 @@ Subject: [PATCH 18/24] Add support for the XDG file chooser portal
ui/gtk/gtk_ui.cc | 4 +
ui/gtk/select_file_dialog_impl.cc | 68 +-
ui/gtk/select_file_dialog_impl.h | 9 +
ui/gtk/select_file_dialog_impl_portal.cc | 734 ++++++++++++++++++++++
ui/gtk/select_file_dialog_impl_portal.cc | 741 ++++++++++++++++++++++
ui/gtk/select_file_dialog_impl_portal.h | 134 ++++
11 files changed, 977 insertions(+), 19 deletions(-)
11 files changed, 984 insertions(+), 19 deletions(-)
create mode 100644 ui/gtk/select_file_dialog_impl_portal.cc
create mode 100644 ui/gtk/select_file_dialog_impl_portal.h

Expand All @@ -38,7 +38,7 @@ index 9ba75ccc991e5..a5e3735579264 100644
{"calculate-native-win-occlusion",
flag_descriptions::kCalculateNativeWinOcclusionName,
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index da89b557079bd..850ff27d0d428 100644
index 1afe76e601684..93d8fcb0f856d 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3537,6 +3537,17 @@ const char kTabFreezeDescription[] =
Expand Down Expand Up @@ -317,10 +317,10 @@ index 3cb8ee5d6a972..412a4394a8d65 100644
// NewSelectFileDialogImplKDE will actually work.
diff --git a/ui/gtk/select_file_dialog_impl_portal.cc b/ui/gtk/select_file_dialog_impl_portal.cc
new file mode 100644
index 0000000000000..93df4e03f6313
index 0000000000000..fca5f7b700c94
--- /dev/null
+++ b/ui/gtk/select_file_dialog_impl_portal.cc
@@ -0,0 +1,734 @@
@@ -0,0 +1,741 @@
+#include "ui/gtk/select_file_dialog_impl_portal.h"
+
+#include <gdk/gdkx.h>
Expand Down Expand Up @@ -378,7 +378,7 @@ index 0000000000000..93df4e03f6313
+constexpr char kFileChooserOptionFilters[] = "filters";
+constexpr char kFileChooserOptionCurrentFilter[] = "current_filter";
+constexpr char kFileChooserOptionCurrentFolder[] = "current_folder";
+constexpr char kFileChooserOptionCurrentFile[] = "current_file";
+constexpr char kFileChooserOptionCurrentName[] = "current_name";
+
+constexpr int kFileChooserFilterKindGlob = 0;
+
Expand Down Expand Up @@ -682,7 +682,7 @@ index 0000000000000..93df4e03f6313
+ if (info->parent) {
+ GdkWindow* window = gtk::GtkUi::GetDelegate()->GetGdkWindow(*info->parent);
+ if (window != nullptr && GDK_IS_X11_WINDOW(window)) {
+ parent_handle = gdk_x11_window_get_xid(window);
+ parent_handle = "x11:" + std::to_string(gdk_x11_window_get_xid(window));
+ }
+ }
+
Expand Down Expand Up @@ -749,13 +749,20 @@ index 0000000000000..93df4e03f6313
+ options_writer.CloseContainer(&option_writer);
+ }
+
+ if (info->type == SELECT_SAVEAS_FILE) {
+ if (info->type == SELECT_SAVEAS_FILE && !default_path.empty()) {
+ if (CallDirectoryExistsOnUIThread(default_path)) {
+ // If this is an existing directory, navigate to that directory, with no
+ // filename.
+ AppendByteStringOption(&options_writer, kFileChooserOptionCurrentFolder,
+ default_path.value());
+ } else {
+ AppendByteStringOption(&options_writer, kFileChooserOptionCurrentFile,
+ default_path.value());
+ // The default path does not exist, or is an existing file. We use
+ // current_folder followed by current_name, as per the recommendation of
+ // the GTK docs and the pattern followed by SelectFileDialogImplGTK.
+ AppendByteStringOption(&options_writer, kFileChooserOptionCurrentFolder,
+ default_path.DirName().value());
+ AppendByteStringOption(&options_writer, kFileChooserOptionCurrentName,
+ default_path.BaseName().value());
+ }
+ }
+
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From a0ffd30a1132a3f1bd7eb5b86f6af5e239ab17ce Mon Sep 17 00:00:00 2001
From 49a0798ac64635d0d024e89cb04e1fe7a2671089 Mon Sep 17 00:00:00 2001
From: Ryan Gonzalez <[email protected]>
Date: Tue, 17 Nov 2020 22:35:26 -0600
Subject: [PATCH 19/24] Add OpenURI portal support for opening directories
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From 66084c39a657f39e6dadee930f1fd057b631b0ac Mon Sep 17 00:00:00 2001
From 8f20f0f419deb3bb703e516539b9c48e08d93000 Mon Sep 17 00:00:00 2001
From: Ryan Gonzalez <[email protected]>
Date: Tue, 17 Nov 2020 23:33:35 -0600
Subject: [PATCH 20/24] Remove references to enable-dse-memoryssa
Expand Down
Loading

0 comments on commit eaa74f8

Please sign in to comment.