|
5 | 5 | var { ExtensionCommon } = ChromeUtils.import("resource://gre/modules/ExtensionCommon.jsm"); |
6 | 6 | var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); |
7 | 7 | var { cal } = ChromeUtils.import("resource:///modules/calendar/calUtils.jsm"); |
| 8 | +var { jsmime } = ChromeUtils.import("resource:///modules/jsmime.jsm"); |
8 | 9 |
|
9 | 10 | var { ExtensionAPI, EventManager } = ExtensionCommon; |
10 | 11 |
|
11 | 12 | class ExtCalendarProvider extends cal.provider.BaseClass { |
12 | | - QueryInterface = ChromeUtils.generateQI(["calICalendar", "calIChangeLog", "calISchedulingSupport"]); |
| 13 | + QueryInterface = ChromeUtils.generateQI(["calICalendar", "calIChangeLog", "calISchedulingSupport", "calIItipTransport"]); |
13 | 14 |
|
14 | 15 | static register(extension) { |
15 | 16 | let calmgr = cal.getCalendarManager(); |
@@ -116,11 +117,49 @@ class ExtCalendarProvider extends cal.provider.BaseClass { |
116 | 117 | : ["unsubscribe"]; |
117 | 118 | case "requiresNetwork": |
118 | 119 | return !(this.capabilities.requires_network === false); |
| 120 | + case "itip.transport": |
| 121 | + if (this.extension.emitter.has("calendar.provider.onSend")) { |
| 122 | + return this; |
| 123 | + } |
| 124 | + break; |
119 | 125 | } |
120 | 126 |
|
121 | 127 | return super.getProperty(name); |
122 | 128 | } |
123 | 129 |
|
| 130 | + scheme = "mailto"; |
| 131 | + |
| 132 | + async sendItems(aRecipients, aItipItem) { |
| 133 | + let method = aItipItem.responseMethod; |
| 134 | + let transport = super.getProperty("itip.transport").wrappedJSObject; |
| 135 | + let { subject, body } = transport._prepareItems(aItipItem); |
| 136 | + let serializer = Cc["@mozilla.org/calendar/ics-serializer;1"].createInstance(Ci.calIIcsSerializer); |
| 137 | + let itemList = aItipItem.getItemList(); |
| 138 | + serializer.addItems(itemList, itemList.length); |
| 139 | + let methodProp = cal.getIcsService().createIcalProperty("METHOD"); |
| 140 | + methodProp.value = method; |
| 141 | + serializer.addProperty(methodProp); |
| 142 | + let icsText = serializer.serializeToString(); |
| 143 | + let boundary = Array.from({ length: 24 }, () => Math.floor(Math.random() * 16).toString(16)).join(""); |
| 144 | + let headers = new Map(); |
| 145 | + headers.set("Date", [new Date()]); |
| 146 | + headers.set("Subject", [subject]); |
| 147 | + headers.set("To", aRecipients.map(attendee => ({ name: attendee.commonName, email: attendee.id.replace(/^mailto:/, "")}))); |
| 148 | + headers.set("Content-Type", ["multipart/mixed; boundary=\"" + boundary + "\""]); |
| 149 | + let mimeContent = jsmime.headeremitter.emitStructuredHeaders(headers, { hardMargin: 800 }) + "\r\n"; |
| 150 | + mimeContent += "--" + boundary + "\r\n"; |
| 151 | + mimeContent += "Content-Type: text/plain; charset=UTF-8\r\n\r\n"; |
| 152 | + mimeContent += body + "\r\n"; |
| 153 | + mimeContent += "--" + boundary + "\r\n"; |
| 154 | + mimeContent += "Content-Type: text/calendar; method=" + aItipItem.responseMethod + "; charset=UTF-8\r\nContent-Transfer-Encoding: 8BIT\r\n\r\n"; |
| 155 | + mimeContent += icsText; |
| 156 | + mimeContent += "--" + boundary + "\r\n"; |
| 157 | + mimeContent += "Content-Type: application/ics; name=\"invite.ics\"\r\nContent-Disposition: attachment; filename=\"invite.ics\"\r\nContent-Transfer-Encoding: 8BIT\r\n\r\n"; |
| 158 | + mimeContent += icsText; |
| 159 | + mimeContent += "--" + boundary + "--\r\n"; |
| 160 | + await this.extension.emit("calendar.provider.onSend", this, mimeContent, aRecipients.map(attendee => attendee.id.replace(/^mailto:/, ""))); |
| 161 | + } |
| 162 | + |
124 | 163 | addItem(aItem, aListener) { |
125 | 164 | return this.adoptItem(aItem.clone(), aListener); |
126 | 165 | } |
@@ -409,6 +448,21 @@ this.calendar_provider = class extends ExtensionAPI { |
409 | 448 | }; |
410 | 449 | }, |
411 | 450 | }).api(), |
| 451 | + |
| 452 | + onSend: new EventManager({ |
| 453 | + context, |
| 454 | + name: "calendar.provider.onSend", |
| 455 | + register: fire => { |
| 456 | + let listener = (event, calendar, content) => { |
| 457 | + return fire.async(convertCalendar(context.extension, calendar), content); |
| 458 | + }; |
| 459 | + |
| 460 | + context.extension.on("calendar.provider.onSend", listener); |
| 461 | + return () => { |
| 462 | + context.extension.off("calendar.provider.onSend", listener); |
| 463 | + }; |
| 464 | + }, |
| 465 | + }).api(), |
412 | 466 | }, |
413 | 467 | }, |
414 | 468 | }; |
|
0 commit comments