OLD | NEW |
| (Empty) |
1 /* | |
2 * This file is part of Adblock Plus <https://adblockplus.org/>, | |
3 * Copyright (C) 2006-2016 Eyeo GmbH | |
4 * | |
5 * Adblock Plus is free software: you can redistribute it and/or modify | |
6 * it under the terms of the GNU General Public License version 3 as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * Adblock Plus is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 * GNU General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU General Public License | |
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | |
16 */ | |
17 | |
18 (function() | |
19 { | |
20 /* Message passing */ | |
21 | |
22 var MessageProxy = ext._MessageProxy = function(messageDispatcher) | |
23 { | |
24 this._messageDispatcher = messageDispatcher; | |
25 this._responseCallbacks = Object.create(null); | |
26 this._responseCallbackCounter = 0; | |
27 }; | |
28 MessageProxy.prototype = { | |
29 _sendResponse: function(request, message) | |
30 { | |
31 var response = {}; | |
32 | |
33 if ("documentId" in request) | |
34 response["targetDocuments"] = [request["documentId"]]; | |
35 | |
36 for (var prop in request) | |
37 response[prop] = request[prop]; | |
38 response.payload = message; | |
39 | |
40 this._messageDispatcher.dispatchMessage("response", response); | |
41 }, | |
42 handleRequest: function(request, sender) | |
43 { | |
44 if ("callbackId" in request) | |
45 { | |
46 var sent = false; | |
47 var sendResponse = function(message) | |
48 { | |
49 this._sendResponse(request, message); | |
50 sent = true; | |
51 }.bind(this); | |
52 | |
53 var results = ext.onMessage._dispatch(request.payload, sender, sendRespo
nse); | |
54 | |
55 // The onMessage listener has to return true to indicate that a response | |
56 // is sent later asynchronously. Otherwise if no response was sent yet, | |
57 // we sent a response indicating that there is no response, that | |
58 // the other end can remove the callback and doesn't leak memory. | |
59 if (!sent && results.indexOf(true) == -1) | |
60 this._sendResponse(request, undefined); | |
61 } | |
62 else | |
63 { | |
64 ext.onMessage._dispatch(request.payload, sender, function() {}); | |
65 } | |
66 }, | |
67 handleResponse: function(response) | |
68 { | |
69 var callbackId = response.callbackId; | |
70 var callback = this._responseCallbacks[callbackId]; | |
71 if (callback) | |
72 { | |
73 delete this._responseCallbacks[callbackId]; | |
74 | |
75 if (typeof response.payload != "undefined") | |
76 callback(response.payload); | |
77 } | |
78 }, | |
79 sendMessage: function(message, responseCallback, extra) | |
80 { | |
81 var request = {payload: message}; | |
82 | |
83 if (responseCallback) | |
84 { | |
85 request.callbackId = ++this._responseCallbackCounter; | |
86 this._responseCallbacks[request.callbackId] = responseCallback; | |
87 } | |
88 | |
89 for (var prop in extra) | |
90 request[prop] = extra[prop]; | |
91 | |
92 this._messageDispatcher.dispatchMessage("request", request); | |
93 } | |
94 }; | |
95 | |
96 ext.onMessage = new ext._EventTarget(); | |
97 | |
98 | |
99 /* I18n */ | |
100 | |
101 var getLocaleCandidates = function() | |
102 { | |
103 var candidates = []; | |
104 var defaultLocale = "en_US"; | |
105 | |
106 // e.g. "ja-jp-mac" -> "ja_JP", note that the part after the second | |
107 // dash is dropped, since we only support language and region | |
108 var [language, region] = navigator.language.split("-"); | |
109 | |
110 if (region) | |
111 { | |
112 region = region.toUpperCase(); | |
113 | |
114 // e.g. "es-AR" -> "es_419", note that we combine all dialects of | |
115 // Spanish outside of Spain, the same way Google Chrome does, | |
116 // since we use the same translations as for the Chrome extension | |
117 if (language == "es" && region != "ES") | |
118 region = "419"; | |
119 | |
120 candidates.push(language + "_" + region); | |
121 } | |
122 | |
123 candidates.push(language); | |
124 | |
125 if (candidates.indexOf(defaultLocale) == -1) | |
126 candidates.push(defaultLocale); | |
127 | |
128 return candidates; | |
129 }; | |
130 | |
131 var initCatalog = function(uiLocale) | |
132 { | |
133 var bidiDir = /^(ar|fa|he|ug|ur)(_|$)/.test(uiLocale) ? "rtl" : "ltr"; | |
134 var catalog = Object.create(null); | |
135 | |
136 catalog["@@ui_locale"] = [uiLocale, []]; | |
137 catalog["@@bidi_dir" ] = [bidiDir, []]; | |
138 | |
139 return catalog; | |
140 }; | |
141 | |
142 var locales = getLocaleCandidates(); | |
143 var catalog = initCatalog(locales[0]); | |
144 | |
145 var replacePlaceholder = function(text, placeholder, content) | |
146 { | |
147 return text.split("$" + placeholder + "$").join(content || ""); | |
148 }; | |
149 | |
150 var parseMessage = function(rawMessage) | |
151 { | |
152 var text = rawMessage.message; | |
153 var placeholders = []; | |
154 | |
155 for (var placeholder in rawMessage.placeholders) | |
156 { | |
157 var content = rawMessage.placeholders[placeholder].content; | |
158 | |
159 if (/^\$\d+$/.test(content)) | |
160 placeholders[parseInt(content.substr(1), 10) - 1] = placeholder; | |
161 else | |
162 text = replacePlaceholder(text, placeholder, content); | |
163 } | |
164 | |
165 return [text, placeholders]; | |
166 }; | |
167 | |
168 var readCatalog = function(locale) | |
169 { | |
170 var xhr = new XMLHttpRequest(); | |
171 xhr.open("GET", safari.extension.baseURI + "_locales/" + locale + "/messages
.json", false); | |
172 | |
173 try | |
174 { | |
175 xhr.send(); | |
176 } | |
177 catch (e) | |
178 { | |
179 return; | |
180 } | |
181 | |
182 if (xhr.status != 200 && xhr.status != 0) | |
183 return; | |
184 | |
185 var rawCatalog = JSON.parse(xhr.responseText); | |
186 for (var msgId in rawCatalog) | |
187 { | |
188 if (!(msgId in catalog)) | |
189 catalog[msgId] = parseMessage(rawCatalog[msgId]); | |
190 } | |
191 }; | |
192 | |
193 ext.i18n = { | |
194 getMessage: function(msgId, substitutions) | |
195 { | |
196 while (true) | |
197 { | |
198 var message = catalog[msgId]; | |
199 if (message) | |
200 { | |
201 var [text, placeholders] = message; | |
202 | |
203 if (!(substitutions instanceof Array)) | |
204 substitutions = [substitutions]; | |
205 | |
206 for (var i = 0; i < placeholders.length; i++) | |
207 text = replacePlaceholder(text, placeholders[i], substitutions[i]); | |
208 | |
209 return text; | |
210 } | |
211 | |
212 if (locales.length == 0) | |
213 return ""; | |
214 | |
215 readCatalog(locales.shift()); | |
216 } | |
217 } | |
218 }; | |
219 | |
220 | |
221 /* Utils */ | |
222 | |
223 ext.getURL = function(path) | |
224 { | |
225 return safari.extension.baseURI + path; | |
226 }; | |
227 })(); | |
OLD | NEW |