diff options
Diffstat (limited to '')
-rw-r--r-- | comm/calendar/test/ICSServer.jsm | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/comm/calendar/test/ICSServer.jsm b/comm/calendar/test/ICSServer.jsm new file mode 100644 index 0000000000..c0f120ec2a --- /dev/null +++ b/comm/calendar/test/ICSServer.jsm @@ -0,0 +1,153 @@ +/* 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/. */ + +const EXPORTED_SYMBOLS = ["ICSServer"]; + +const { Assert } = ChromeUtils.importESModule("resource://testing-common/Assert.sys.mjs"); +const { CommonUtils } = ChromeUtils.importESModule("resource://services-common/utils.sys.mjs"); +const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js"); + +var ICSServer = { + server: null, + isOpen: false, + + ics: "", + etag: "", + open(username, password) { + this.server = new HttpServer(); + this.server.start(-1); + this.isOpen = true; + + this.username = username; + this.password = password; + this.server.registerPathHandler("/ping", this.ping); + this.server.registerPathHandler(this.path, this.handleICS.bind(this)); + + this.reset(); + }, + + reset() { + this.ics = ""; + this.etag = ""; + }, + + close() { + if (!this.isOpen) { + return Promise.resolve(); + } + return new Promise(resolve => + this.server.stop({ + onStopped: () => { + this.isOpen = false; + resolve(); + }, + }) + ); + }, + + get origin() { + return `http://localhost:${this.server.identity.primaryPort}`; + }, + + get path() { + return "/test.ics"; + }, + + get url() { + return `${this.origin}${this.path}`; + }, + + get altPath() { + return "/addressbooks/me/default/"; + }, + + get altURL() { + return `${this.origin}${this.altPath}`; + }, + + checkAuth(request, response) { + if (!this.username || !this.password) { + return true; + } + if (!request.hasHeader("Authorization")) { + response.setStatusLine("1.1", 401, "Unauthorized"); + response.setHeader("WWW-Authenticate", `Basic realm="test"`); + return false; + } + + let value = request.getHeader("Authorization"); + if (!value.startsWith("Basic ")) { + response.setStatusLine("1.1", 401, "Unauthorized"); + response.setHeader("WWW-Authenticate", `Basic realm="test"`); + return false; + } + + let [username, password] = atob(value.substring(6)).split(":"); + if (username != this.username || password != this.password) { + response.setStatusLine("1.1", 401, "Unauthorized"); + response.setHeader("WWW-Authenticate", `Basic realm="test"`); + return false; + } + + return true; + }, + + ping(request, response) { + response.setStatusLine("1.1", 200, "OK"); + response.setHeader("Content-Type", "text/plain"); + response.write("pong"); + }, + + handleICS(request, response) { + if (!this.checkAuth(request, response)) { + return; + } + + switch (request.method) { + case "HEAD": + this.headICS(request, response); + return; + case "GET": + this.getICS(request, response); + return; + case "PUT": + this.putICS(request, response); + return; + } + + Assert.report(true, undefined, undefined, "Should not have reached here"); + response.setStatusLine("1.1", 405, "Method Not Allowed"); + response.setHeader("Content-Type", "text/plain"); + response.write(`Method not allowed: ${request.method}`); + }, + + headICS(request, response) { + response.setStatusLine("1.1", 200, "OK"); + response.setHeader("Content-Type", "text/calendar"); + response.setHeader("ETag", this.etag); + }, + + getICS(request, response) { + this.headICS(request, response); + response.write(this.ics); + }, + + async putICS(request, response) { + response.processAsync(); + + await this.putICSInternal(CommonUtils.readBytesFromInputStream(request.bodyInputStream)); + + response.setStatusLine("1.1", 204, "No Content"); + response.setHeader("ETag", this.etag); + + response.finish(); + }, + + async putICSInternal(ics) { + this.ics = ics; + + let hash = await crypto.subtle.digest("sha-1", new TextEncoder().encode(this.ics)); + this.etag = Array.from(new Uint8Array(hash), c => c.toString(16).padStart(2, "0")).join(""); + }, +}; |