entries = await rs.get(); } catch (e) {} this._onUpdateEntries(entries || []); }, _onUpdateEntries(aEntries) { aEntries.map(entry => { this._entries[entry.Name] = entry; }); }, // Parse the update request. See UrlClassifierListManager.sys.mjs makeUpdateRequest // for more details about how we build the update request. // // @param aRequest the request payload of the update request // @return array The array of requested tables. Each item in the array is composed // with [table name, chunk numner] _parseRequest(aRequest) { let lines = aRequest.split("\n"); let requests = []; for (let line of lines) { let fields = line.split(";"); let chunkNum = fields[1]?.match(/(?<=a:).*/); requests.push([fields[0], chunkNum]); } return requests; }, async _getLists(aRequest, aListener) { await this.lazyInit(); let rs = lazy.RemoteSettings(COLLECTION_NAME); let payload = "n:" + SBRS_UPDATE_MINIMUM_DELAY + "\n"; let requests = this._parseRequest(aRequest); for (let request of requests) { let [reqTableName, reqChunkNum] = request; let entry = this._entries[reqTableName]; if (!entry?.attachment) { continue; } // If the request version is the same as what we have in Remote Settings, // we are up-to-date now. if (entry.Version == reqChunkNum) { continue; } let downloadError = false; try { // SafeBrowsing maintains its own files, so we can remove the downloaded // files after SafeBrowsing processes the data. let buffer = await rs.attachments.downloadAsBytes(entry); let bytes = new Uint8Array(buffer); let strData = ""; for (let i = 0; i < bytes.length; i++) { strData += String.fromCharCode(bytes[i]); } // Construct the payload payload += "i:" + reqTableName + "\n"; // Add adddel directive to clear the old chunks. if (reqChunkNum) { payload += "ad:" + reqChunkNum.toString() + "\n"; } payload += strData; } catch (e) { downloadError = true; } if (downloadError) { try { aListener.onStartRequest(null); aListener.onStopRequest(null, Cr.NS_ERROR_FAILURE); } catch (e) {} return; } } // Send the update response over stream listener interface let stream = Cc["@mozilla.org/io/string-input-stream;1"].createInstance( Ci.nsIStringInputStream ); stream.setByteStringData(payload); try { aListener.onStartRequest(null); aListener.onDataAvailable(null, stream, 0, payload.length); aListener.onStopRequest(null, Cr.NS_OK); } catch (e) {} }, fetchList(aPayload, aListener) { this._getLists(aPayload, aListener); }, clear() { this._initialized = false; this._entries = {}; }, }; PK