summaryrefslogtreecommitdiffstats
path: root/netwerk/dns/PublicSuffixList.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/dns/PublicSuffixList.jsm')
-rw-r--r--netwerk/dns/PublicSuffixList.jsm108
1 files changed, 108 insertions, 0 deletions
diff --git a/netwerk/dns/PublicSuffixList.jsm b/netwerk/dns/PublicSuffixList.jsm
new file mode 100644
index 0000000000..1759053fc4
--- /dev/null
+++ b/netwerk/dns/PublicSuffixList.jsm
@@ -0,0 +1,108 @@
+/* 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/. */
+"use strict";
+
+const { RemoteSettings } = ChromeUtils.import(
+ "resource://services-settings/remote-settings.js"
+);
+const FileUtils = ChromeUtils.importESModule(
+ "resource://gre/modules/FileUtils.sys.mjs"
+).FileUtils;
+
+const EXPORTED_SYMBOLS = ["PublicSuffixList"];
+
+const RECORD_ID = "tld-dafsa";
+const SIGNAL = "public-suffix-list-updated";
+
+const PublicSuffixList = {
+ CLIENT: RemoteSettings("public-suffix-list"),
+
+ init() {
+ // Only initialize once.
+ if (this._initialized) {
+ return;
+ }
+ this._initialized = true;
+
+ this.CLIENT.on("sync", this.onUpdate.bind(this));
+ /* We have a single record for this collection. Let's see if we already have it locally.
+ * Note that on startup, we don't need to synchronize immediately on new profiles.
+ */
+ this.CLIENT.get({ syncIfEmpty: false, filters: { id: RECORD_ID } })
+ .then(async records => {
+ if (records.length == 1) {
+ // Get the downloaded file URI (most likely to be a no-op here, since file will exist).
+ const fileURI = await this.CLIENT.attachments.downloadToDisk(
+ records[0]
+ );
+ // Send a signal so that the C++ code loads the updated list on startup.
+ this.notifyUpdate(fileURI);
+ }
+ })
+ .catch(err => console.error(err));
+ },
+
+ /**
+ * This method returns the path to the file based on the file uri received
+ * Example:
+ * On windows "file://C:/Users/AppData/main/public-suffix-list/dafsa.bin"
+ * will be converted to "C:\\Users\\main\\public-suffix-list\\dafsa.bin
+ *
+ * On macOS/linux "file:///home/main/public-suffix-list/dafsa.bin"
+ * will be converted to "/home/main/public-suffix-list/dafsa.bin"
+ */
+ getFilePath(fileURI) {
+ const uri = Services.io.newURI(fileURI);
+ const file = uri.QueryInterface(Ci.nsIFileURL).file;
+ return file.path;
+ },
+
+ notifyUpdate(fileURI) {
+ if (!Services.prefs.getBoolPref("network.psl.onUpdate_notify", false)) {
+ // Updating the PSL while Firefox is running could cause principals to
+ // have a different base domain before/after the update.
+ // See bug 1582647 comment 30
+ return;
+ }
+
+ const filePath = this.getFilePath(fileURI);
+ const nsifile = new FileUtils.File(filePath);
+ /* Send a signal to be read by the C++, the method
+ * ::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
+ * at netwerk/dns/nsEffectiveTLDService.cpp
+ */
+ Services.obs.notifyObservers(
+ nsifile, // aSubject
+ SIGNAL, // aTopic
+ filePath // aData
+ );
+ },
+
+ async onUpdate({ data: { created, updated, deleted } }) {
+ // In theory, this will never happen, we will never delete the record.
+ if (deleted.length == 1) {
+ await this.CLIENT.attachments.deleteFromDisk(deleted[0]);
+ }
+ // Handle creation and update the same way
+ const changed = created.concat(updated.map(u => u.new));
+ /* In theory, we should never have more than one record. And if we receive
+ * this event, it's because the single record was updated.
+ */
+ if (changed.length != 1) {
+ console.warn("Unsupported sync event for Public Suffix List");
+ return;
+ }
+ // Download the updated file.
+ let fileURI;
+ try {
+ fileURI = await this.CLIENT.attachments.downloadToDisk(changed[0]);
+ } catch (err) {
+ console.error(err);
+ return;
+ }
+
+ // Notify the C++ part to reload it from disk.
+ this.notifyUpdate(fileURI);
+ },
+};