summaryrefslogtreecommitdiffstats
path: root/toolkit/components/cascade_bloom_filter
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /toolkit/components/cascade_bloom_filter
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/cascade_bloom_filter')
-rw-r--r--toolkit/components/cascade_bloom_filter/Cargo.toml12
-rw-r--r--toolkit/components/cascade_bloom_filter/CascadeFilter.cpp25
-rw-r--r--toolkit/components/cascade_bloom_filter/CascadeFilter.h17
-rw-r--r--toolkit/components/cascade_bloom_filter/components.conf15
-rw-r--r--toolkit/components/cascade_bloom_filter/moz.build26
-rw-r--r--toolkit/components/cascade_bloom_filter/nsICascadeFilter.idl28
-rw-r--r--toolkit/components/cascade_bloom_filter/src/lib.rs56
-rw-r--r--toolkit/components/cascade_bloom_filter/test/xpcshell/test_cascade_bindings.js51
-rw-r--r--toolkit/components/cascade_bloom_filter/test/xpcshell/xpcshell.toml3
9 files changed, 233 insertions, 0 deletions
diff --git a/toolkit/components/cascade_bloom_filter/Cargo.toml b/toolkit/components/cascade_bloom_filter/Cargo.toml
new file mode 100644
index 0000000000..69eb7bd901
--- /dev/null
+++ b/toolkit/components/cascade_bloom_filter/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "cascade_bloom_filter"
+version = "0.1.0"
+authors = ["Rob Wu <rob@robwu.nl>"]
+license = "MPL-2.0"
+
+[dependencies]
+nserror = { path = "../../../xpcom/rust/nserror" }
+nsstring = { path = "../../../xpcom/rust/nsstring" }
+rust_cascade = "1.4.0"
+thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
+xpcom = { path = "../../../xpcom/rust/xpcom" }
diff --git a/toolkit/components/cascade_bloom_filter/CascadeFilter.cpp b/toolkit/components/cascade_bloom_filter/CascadeFilter.cpp
new file mode 100644
index 0000000000..db24e9b168
--- /dev/null
+++ b/toolkit/components/cascade_bloom_filter/CascadeFilter.cpp
@@ -0,0 +1,25 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsCOMPtr.h"
+
+#include "CascadeFilter.h"
+
+namespace {
+extern "C" {
+
+// Implemented in Rust.
+void cascade_filter_construct(nsICascadeFilter** aResult);
+}
+} // namespace
+
+namespace mozilla {
+
+already_AddRefed<nsICascadeFilter> ConstructCascadeFilter() {
+ nsCOMPtr<nsICascadeFilter> filter;
+ cascade_filter_construct(getter_AddRefs(filter));
+ return filter.forget();
+}
+
+} // namespace mozilla
diff --git a/toolkit/components/cascade_bloom_filter/CascadeFilter.h b/toolkit/components/cascade_bloom_filter/CascadeFilter.h
new file mode 100644
index 0000000000..bcfd236302
--- /dev/null
+++ b/toolkit/components/cascade_bloom_filter/CascadeFilter.h
@@ -0,0 +1,17 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef CASCADE_BLOOM_FILTER_CASCADE_FILTER_H_
+#define CASCADE_BLOOM_FILTER_CASCADE_FILTER_H_
+
+#include "mozilla/AlreadyAddRefed.h"
+#include "nsICascadeFilter.h"
+
+namespace mozilla {
+
+already_AddRefed<nsICascadeFilter> ConstructCascadeFilter();
+
+} // namespace mozilla
+
+#endif // CASCADE_BLOOM_FILTER_CASCADE_FILTER_H_
diff --git a/toolkit/components/cascade_bloom_filter/components.conf b/toolkit/components/cascade_bloom_filter/components.conf
new file mode 100644
index 0000000000..cede5e216d
--- /dev/null
+++ b/toolkit/components/cascade_bloom_filter/components.conf
@@ -0,0 +1,15 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+Classes = [
+ {
+ 'cid': '{c8d0b0b3-17f8-458b-9264-7b67b288fe79}',
+ 'contract_ids': ['@mozilla.org/cascade-filter;1'],
+ 'type': 'nsICascadeFilter',
+ 'headers': ['mozilla/CascadeFilter.h'],
+ 'constructor': 'mozilla::ConstructCascadeFilter',
+ },
+]
diff --git a/toolkit/components/cascade_bloom_filter/moz.build b/toolkit/components/cascade_bloom_filter/moz.build
new file mode 100644
index 0000000000..7df5325bff
--- /dev/null
+++ b/toolkit/components/cascade_bloom_filter/moz.build
@@ -0,0 +1,26 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Toolkit", "Blocklist Implementation")
+
+XPCSHELL_TESTS_MANIFESTS += ["test/xpcshell/xpcshell.toml"]
+
+XPIDL_SOURCES += [
+ "nsICascadeFilter.idl",
+]
+
+XPIDL_MODULE = "cascade_bindings"
+
+EXPORTS.mozilla += ["CascadeFilter.h"]
+
+SOURCES += ["CascadeFilter.cpp"]
+
+XPCOM_MANIFESTS += [
+ "components.conf",
+]
+
+FINAL_LIBRARY = "xul"
diff --git a/toolkit/components/cascade_bloom_filter/nsICascadeFilter.idl b/toolkit/components/cascade_bloom_filter/nsICascadeFilter.idl
new file mode 100644
index 0000000000..2f6dc37f90
--- /dev/null
+++ b/toolkit/components/cascade_bloom_filter/nsICascadeFilter.idl
@@ -0,0 +1,28 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+/**
+ * A consumer of a filter cascade, i.e. a cascaded bloom filter as generated by
+ * https://github.com/mozilla/filter-cascade
+ */
+[scriptable, uuid(c8d0b0b3-17f8-458b-9264-7b67b288fe79)]
+interface nsICascadeFilter : nsISupports {
+ /**
+ * Initialize with the data that represents the filter cascade.
+ * This method can be called repeatedly.
+ *
+ * @throws NS_ERROR_INVALID_ARG if the input is malformed.
+ */
+ void setFilterData(in Array<octet> data);
+
+ /**
+ * Check whether a given key is a member of the filter cascade.
+ * The result can only be relied upon if the key was known at the time of the
+ * filter generation. If the key is unknown, the method may incorrectly
+ * return true (due to the probabilistic nature of bloom filters).
+ */
+ boolean has(in ACString key);
+};
diff --git a/toolkit/components/cascade_bloom_filter/src/lib.rs b/toolkit/components/cascade_bloom_filter/src/lib.rs
new file mode 100644
index 0000000000..494b67b68d
--- /dev/null
+++ b/toolkit/components/cascade_bloom_filter/src/lib.rs
@@ -0,0 +1,56 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+extern crate nserror;
+extern crate nsstring;
+extern crate rust_cascade;
+extern crate thin_vec;
+#[macro_use]
+extern crate xpcom;
+
+use nserror::{nsresult, NS_ERROR_INVALID_ARG, NS_ERROR_NOT_INITIALIZED, NS_OK};
+use nsstring::nsACString;
+use rust_cascade::Cascade;
+use std::cell::RefCell;
+use thin_vec::ThinVec;
+use xpcom::interfaces::nsICascadeFilter;
+use xpcom::{xpcom_method, RefPtr};
+
+#[xpcom(implement(nsICascadeFilter), nonatomic)]
+pub struct CascadeFilter {
+ filter: RefCell<Option<Cascade>>,
+}
+
+impl CascadeFilter {
+ fn new() -> RefPtr<CascadeFilter> {
+ CascadeFilter::allocate(InitCascadeFilter {
+ filter: RefCell::new(None),
+ })
+ }
+ xpcom_method!(set_filter_data => SetFilterData(data: *const ThinVec<u8>));
+
+ fn set_filter_data(&self, data: &ThinVec<u8>) -> Result<(), nsresult> {
+ let filter = Cascade::from_bytes(data.to_vec())
+ .unwrap_or(None)
+ .ok_or(NS_ERROR_INVALID_ARG)?;
+ self.filter.borrow_mut().replace(filter);
+ Ok(())
+ }
+
+ xpcom_method!(has => Has(key: *const nsACString) -> bool);
+
+ fn has(&self, key: &nsACString) -> Result<bool, nsresult> {
+ match self.filter.borrow().as_ref() {
+ None => Err(NS_ERROR_NOT_INITIALIZED),
+ Some(filter) => Ok(filter.has(key.to_vec())),
+ }
+ }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn cascade_filter_construct(result: &mut *const nsICascadeFilter) {
+ let inst: RefPtr<CascadeFilter> = CascadeFilter::new();
+ *result = inst.coerce::<nsICascadeFilter>();
+ std::mem::forget(inst);
+}
diff --git a/toolkit/components/cascade_bloom_filter/test/xpcshell/test_cascade_bindings.js b/toolkit/components/cascade_bloom_filter/test/xpcshell/test_cascade_bindings.js
new file mode 100644
index 0000000000..c326df2018
--- /dev/null
+++ b/toolkit/components/cascade_bloom_filter/test/xpcshell/test_cascade_bindings.js
@@ -0,0 +1,51 @@
+"use strict";
+
+const CASCADE_CID = "@mozilla.org/cascade-filter;1";
+const CASCADE_IID = Ci.nsICascadeFilter;
+const CascadeFilter = Components.Constructor(CASCADE_CID, CASCADE_IID);
+
+add_task(function CascadeFilter_uninitialized() {
+ let filter = new CascadeFilter();
+ Assert.throws(
+ () => filter.has(""),
+ e => e.result === Cr.NS_ERROR_NOT_INITIALIZED,
+ "Cannot use has() if the filter is not initialized"
+ );
+});
+
+add_task(function CascadeFilter_with_setFilterData() {
+ let filter = new CascadeFilter();
+ Assert.throws(
+ () => filter.setFilterData(),
+ e => e.result === Cr.NS_ERROR_XPC_NOT_ENOUGH_ARGS,
+ "setFilterData without parameters should throw"
+ );
+ Assert.throws(
+ () => filter.setFilterData(null),
+ e => e.result === Cr.NS_ERROR_XPC_CANT_CONVERT_PRIMITIVE_TO_ARRAY,
+ "setFilterData with null parameter is invalid"
+ );
+ Assert.throws(
+ () => filter.setFilterData(new Uint8Array()),
+ e => e.result === Cr.NS_ERROR_INVALID_ARG,
+ "setFilterData with empty array is invalid"
+ );
+
+ // Test data based on rust_cascade's unit tests (bloom_v1_test_from_bytes),
+ // with two bytes in front to have a valid format.
+ const TEST_DATA = [1, 0, 1, 9, 0, 0, 0, 1, 0, 0, 0, 1, 0x41, 0];
+ Assert.throws(
+ () => filter.setFilterData(new Uint8Array(TEST_DATA.slice(1))),
+ e => e.result === Cr.NS_ERROR_INVALID_ARG,
+ "setFilterData with invalid data (missing head) is invalid"
+ );
+ Assert.throws(
+ () => filter.setFilterData(new Uint8Array(TEST_DATA.slice(0, -1))),
+ e => e.result === Cr.NS_ERROR_INVALID_ARG,
+ "setFilterData with invalid data (missing tail) is invalid"
+ );
+ filter.setFilterData(new Uint8Array(TEST_DATA));
+ Assert.equal(filter.has("this"), true, "has(this) should be true");
+ Assert.equal(filter.has("that"), true, "has(that) should be true");
+ Assert.equal(filter.has("other"), false, "has(other) should be false");
+});
diff --git a/toolkit/components/cascade_bloom_filter/test/xpcshell/xpcshell.toml b/toolkit/components/cascade_bloom_filter/test/xpcshell/xpcshell.toml
new file mode 100644
index 0000000000..5c102ce23f
--- /dev/null
+++ b/toolkit/components/cascade_bloom_filter/test/xpcshell/xpcshell.toml
@@ -0,0 +1,3 @@
+[DEFAULT]
+
+["test_cascade_bindings.js"]