OLD | NEW |
1 /* | 1 /* |
2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
3 * Copyright (C) 2006-2016 Eyeo GmbH | 3 * Copyright (C) 2006-2016 Eyeo GmbH |
4 * | 4 * |
5 * Adblock Plus is free software: you can redistribute it and/or modify | 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 | 6 * it under the terms of the GNU General Public License version 3 as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
8 * | 8 * |
9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 var element = event.srcElement; | 128 var element = event.srcElement; |
129 safari.self.tab.setContextMenuEventUserInfo(event, { | 129 safari.self.tab.setContextMenuEventUserInfo(event, { |
130 documentId: documentId, | 130 documentId: documentId, |
131 tagName: element.localName | 131 tagName: element.localName |
132 }); | 132 }); |
133 }); | 133 }); |
134 | 134 |
135 | 135 |
136 /* Background page */ | 136 /* Background page */ |
137 | 137 |
138 var backgroundPageProxy = { | |
139 objects: [], | |
140 callbacks: [], | |
141 | |
142 send: function(message) | |
143 { | |
144 message.category = "proxy"; | |
145 message.documentId = documentId; | |
146 | |
147 return safari.self.tab.canLoad(beforeLoadEvent, message); | |
148 }, | |
149 checkResult: function(result) | |
150 { | |
151 if (!result.succeed) | |
152 throw result.error; | |
153 }, | |
154 deserializeResult: function(result) | |
155 { | |
156 this.checkResult(result); | |
157 return this.deserialize(result.result); | |
158 }, | |
159 serialize: function(obj, memo) | |
160 { | |
161 if (typeof obj == "object" && obj != null || typeof obj == "function") | |
162 { | |
163 if ("__proxyObjectId" in obj) | |
164 return {type: "hosted", objectId: obj.__proxyObjectId}; | |
165 | |
166 if (typeof obj == "function") | |
167 { | |
168 var callbackId; | |
169 if ("__proxyCallbackId" in obj) | |
170 callbackId = obj.__proxyCallbackId; | |
171 else | |
172 { | |
173 callbackId = this.callbacks.push(obj) - 1; | |
174 Object.defineProperty(obj, "__proxyCallbackId", {value: callbackId})
; | |
175 } | |
176 | |
177 return {type: "callback", callbackId: callbackId, | |
178 documentId: documentId}; | |
179 } | |
180 | |
181 if (obj.constructor != Date && obj.constructor != RegExp) | |
182 { | |
183 if (!memo) | |
184 memo = {specs: [], objects: []}; | |
185 | |
186 var idx = memo.objects.indexOf(obj); | |
187 if (idx != -1) | |
188 return memo.specs[idx]; | |
189 | |
190 var spec = {}; | |
191 memo.specs.push(spec); | |
192 memo.objects.push(obj); | |
193 | |
194 if (obj.constructor == Array) | |
195 { | |
196 spec.type = "array"; | |
197 spec.items = []; | |
198 | |
199 for (var i = 0; i < obj.length; i++) | |
200 spec.items.push(this.serialize(obj[i], memo)); | |
201 } | |
202 else | |
203 { | |
204 spec.type = "object"; | |
205 spec.properties = {}; | |
206 | |
207 for (var k in obj) | |
208 spec.properties[k] = this.serialize(obj[k], memo); | |
209 } | |
210 | |
211 return spec; | |
212 } | |
213 } | |
214 | |
215 return {type: "value", value: obj}; | |
216 }, | |
217 deserializeSequence: function(specs, array, memo) | |
218 { | |
219 if (!array) | |
220 array = []; | |
221 | |
222 if (!memo) | |
223 memo = {specs: [], arrays: []}; | |
224 | |
225 for (var i = 0; i < specs.length; i++) | |
226 array.push(this.deserialize(specs[i], memo)); | |
227 | |
228 return array; | |
229 }, | |
230 deserialize: function(spec, memo) | |
231 { | |
232 switch (spec.type) | |
233 { | |
234 case "value": | |
235 return spec.value; | |
236 case "object": | |
237 return this.getObject(spec.objectId); | |
238 case "array": | |
239 if (!memo) | |
240 memo = {specs: [], arrays: []}; | |
241 | |
242 var idx = memo.specs.indexOf(spec); | |
243 if (idx != -1) | |
244 return memo.arrays[idx]; | |
245 | |
246 var array = []; | |
247 memo.specs.push(spec); | |
248 memo.arrays.push(array); | |
249 | |
250 return this.deserializeSequence(spec.items, array, memo); | |
251 } | |
252 }, | |
253 getProperty: function(objectId, property) | |
254 { | |
255 return this.deserializeResult( | |
256 this.send( | |
257 { | |
258 type: "getProperty", | |
259 objectId: objectId, | |
260 property: property | |
261 }) | |
262 ); | |
263 }, | |
264 createProperty: function(property, enumerable) | |
265 { | |
266 var proxy = this; | |
267 return { | |
268 get: function() | |
269 { | |
270 return proxy.getProperty(this.__proxyObjectId, property); | |
271 }, | |
272 set: function(value) | |
273 { | |
274 proxy.checkResult( | |
275 proxy.send( | |
276 { | |
277 type: "setProperty", | |
278 objectId: this.__proxyObjectId, | |
279 property: property, | |
280 value: proxy.serialize(value) | |
281 }) | |
282 ); | |
283 }, | |
284 enumerable: enumerable, | |
285 configurable: true | |
286 }; | |
287 }, | |
288 createFunction: function(objectId) | |
289 { | |
290 var proxy = this; | |
291 return function() | |
292 { | |
293 return proxy.deserializeResult( | |
294 proxy.send( | |
295 { | |
296 type: "callFunction", | |
297 functionId: objectId, | |
298 contextId: this.__proxyObjectId, | |
299 args: Array.prototype.map.call( | |
300 arguments, | |
301 proxy.serialize.bind(proxy) | |
302 ) | |
303 }) | |
304 ); | |
305 }; | |
306 }, | |
307 handleCallback: function(message) | |
308 { | |
309 this.callbacks[message.callbackId].apply( | |
310 this.getObject(message.contextId), | |
311 this.deserializeSequence(message.args) | |
312 ); | |
313 }, | |
314 getObject: function(objectId) | |
315 { | |
316 var objectInfo = this.send({ | |
317 type: "inspectObject", | |
318 objectId: objectId | |
319 }); | |
320 | |
321 var obj = this.objects[objectId]; | |
322 if (obj) | |
323 Object.getOwnPropertyNames(obj).forEach(function(prop) { delete obj[prop
]; }); | |
324 else | |
325 { | |
326 if (objectInfo.isFunction) | |
327 obj = this.createFunction(objectId); | |
328 else | |
329 obj = {}; | |
330 | |
331 this.objects[objectId] = obj; | |
332 Object.defineProperty(obj, "__proxyObjectId", {value: objectId}); | |
333 } | |
334 | |
335 var excluded = []; | |
336 var included = []; | |
337 if ("prototypeOf" in objectInfo) | |
338 { | |
339 var prototype = window[objectInfo.prototypeOf].prototype; | |
340 | |
341 excluded = Object.getOwnPropertyNames(prototype); | |
342 included = ["constructor"]; | |
343 | |
344 obj.__proto__ = prototype; | |
345 } | |
346 else | |
347 { | |
348 if (objectInfo.isFunction) | |
349 { | |
350 excluded = Object.getOwnPropertyNames(function() {}); | |
351 included = ["prototype"]; | |
352 } | |
353 | |
354 if ("prototypeId" in objectInfo) | |
355 obj.__proto__ = this.getObject(objectInfo.prototypeId); | |
356 else | |
357 obj.__proto__ = null; | |
358 } | |
359 | |
360 for (var property in objectInfo.properties) | |
361 { | |
362 if (excluded.indexOf(property) == -1 || included.indexOf(property) != -1
) | |
363 { | |
364 var desc = Object.getOwnPropertyDescriptor(obj, property); | |
365 | |
366 if (!desc || desc.configurable) | |
367 { | |
368 Object.defineProperty(obj, property, this.createProperty( | |
369 property, objectInfo.properties[property].enumerable | |
370 )); | |
371 } | |
372 else if (desc.writable) | |
373 obj[property] = this.getProperty(objectId, property); | |
374 } | |
375 } | |
376 | |
377 return obj; | |
378 } | |
379 }; | |
380 | |
381 ext.backgroundPage = { | 138 ext.backgroundPage = { |
382 sendMessage: function(message, responseCallback) | 139 sendMessage: function(message, responseCallback) |
383 { | 140 { |
384 messageProxy.sendMessage(message, responseCallback, | 141 messageProxy.sendMessage(message, responseCallback, |
385 {documentId: documentId}); | 142 {documentId: documentId}); |
386 }, | 143 }, |
387 sendMessageSync: function(message) | 144 sendMessageSync: function(message) |
388 { | 145 { |
389 return safari.self.tab.canLoad( | 146 return safari.self.tab.canLoad( |
390 beforeLoadEvent, | 147 beforeLoadEvent, |
391 { | 148 { |
392 category: "request", | 149 category: "request", |
393 documentId: documentId, | 150 documentId: documentId, |
394 payload: message | 151 payload: message |
395 } | 152 } |
396 ); | 153 ); |
397 }, | |
398 getWindow: function() | |
399 { | |
400 return backgroundPageProxy.getObject(0); | |
401 } | 154 } |
402 }; | 155 }; |
403 | 156 |
404 | 157 |
405 /* Message processing */ | 158 /* Message processing */ |
406 | 159 |
407 var messageProxy = new ext._MessageProxy(safari.self.tab); | 160 var messageProxy = new ext._MessageProxy(safari.self.tab); |
408 | 161 |
409 safari.self.addEventListener("message", function(event) | 162 safari.self.addEventListener("message", function(event) |
410 { | 163 { |
411 if (event.name == "requestDocumentId" && isTopLevel) | 164 if (event.name == "requestDocumentId" && isTopLevel) |
412 { | 165 { |
413 safari.self.tab.dispatchMessage("documentId", { | 166 safari.self.tab.dispatchMessage("documentId", { |
414 pageId: event.message.pageId, | 167 pageId: event.message.pageId, |
415 documentId: documentId | 168 documentId: documentId |
416 }); | 169 }); |
417 } | 170 } |
418 else if (event.message.targetDocuments.indexOf(documentId) != -1) | 171 else if (event.message.targetDocuments.indexOf(documentId) != -1) |
419 { | 172 { |
420 switch (event.name) | 173 switch (event.name) |
421 { | 174 { |
422 case "request": | 175 case "request": |
423 messageProxy.handleRequest(event.message, {}); | 176 messageProxy.handleRequest(event.message, {}); |
424 break; | 177 break; |
425 case "response": | 178 case "response": |
426 messageProxy.handleResponse(event.message); | 179 messageProxy.handleResponse(event.message); |
427 break; | 180 break; |
428 case "proxyCallback": | |
429 backgroundPageProxy.handleCallback(event.message); | |
430 break; | |
431 } | 181 } |
432 } | 182 } |
433 }); | 183 }); |
434 | 184 |
435 | 185 |
436 /* Detecting extension reload/disable/uninstall (not supported on Safari) */ | 186 /* Detecting extension reload/disable/uninstall (not supported on Safari) */ |
437 | 187 |
438 ext.onExtensionUnloaded = { | 188 ext.onExtensionUnloaded = { |
439 addListener: function() {}, | 189 addListener: function() {}, |
440 removeListener: function() {} | 190 removeListener: function() {} |
441 }; | 191 }; |
442 })(); | 192 })(); |
OLD | NEW |