Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: safari/content.js

Issue 16067002: Added Safari Support (Closed)
Patch Set: Bugfixes Created Nov. 15, 2013, 8:58 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « safari/common.js ('k') | stats.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * This file is part of Adblock Plus <http://adblockplus.org/>,
3 * Copyright (C) 2006-2013 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 /* Background page proxy */
21 var proxy = {
22 objects: [],
23 callbacks: [],
24
25 send: function(message)
26 {
27 var evt = document.createEvent("Event");
28 evt.initEvent("beforeload");
29 return safari.self.tab.canLoad(evt, {type: "proxy", payload: message});
30 },
31 checkResult: function(result)
32 {
33 if (!result.succeed)
34 throw result.error;
35 },
36 deserializeResult: function(result)
37 {
38 this.checkResult(result);
39 return this.deserialize(result.result);
40 },
41 serialize: function(obj, memo)
42 {
43 var objectId = this.objects.indexOf(obj);
44 if (objectId != -1)
45 return {type: "hosted", objectId: objectId};
46
47 if (typeof obj == "function")
48 {
49 var callbackId = this.callbacks.indexOf(obj);
50
51 if (callbackId == -1)
52 {
53 callbackId = this.callbacks.push(obj) - 1;
54
55 safari.self.addEventListener("message", function(event)
56 {
57 if (event.name == "proxyCallback")
58 if (event.message.callbackId == callbackId)
59 obj.apply(
60 this.getObject(event.message.contextId),
61 this.deserializeSequence(event.message.args)
62 );
63 }.bind(this));
64 }
65
66 return {type: "callback", callbackId: callbackId};
67 }
68
69 if (typeof obj == "object" &&
70 obj != null &&
71 obj.constructor != Date &&
72 obj.constructor != RegExp)
73 {
74 if (!memo)
75 memo = {specs: [], objects: []};
76
77 var idx = memo.objects.indexOf(obj);
78 if (idx != -1)
79 return memo.specs[idx];
80
81 var spec = {};
82 memo.specs.push(spec);
83 memo.objects.push(obj);
84
85 if (obj.constructor == Array)
86 {
87 spec.type = "array";
88 spec.items = [];
89
90 for (var i = 0; i < obj.length; i++)
91 spec.items.push(this.serialize(obj[i], memo));
92 }
93 else
94 {
95 spec.type = "object";
96 spec.properties = {};
97
98 for (var k in obj)
99 spec.properties[k] = this.serialize(obj[k], memo);
100 }
101
102 return spec;
103 }
104
105 return {type: "value", value: obj};
106 },
107 deserializeSequence: function(specs, array, memo)
108 {
109 if (!array)
110 array = [];
111
112 if (!memo)
113 memo = {specs: [], arrays: []};
114
115 for (var i = 0; i < specs.length; i++)
116 array.push(this.deserialize(specs[i], memo));
117
118 return array;
119 },
120 deserialize: function(spec, memo)
121 {
122 switch (spec.type)
123 {
124 case "value":
125 return spec.value;
126 case "object":
127 return this.getObject(spec.objectId);
128 case "array":
129 if (!memo)
130 memo = {specs: [], arrays: []};
131
132 var idx = memo.specs.indexOf(spec);
133 if (idx != -1)
134 return memo.arrays[idx];
135
136 var array = [];
137 memo.specs.push(spec);
138 memo.arrays.push(array);
139
140 return this.deserializeSequence(spec.items, array, memo);
141 }
142 },
143 getProperty: function(objectId, property)
144 {
145 return this.deserializeResult(
146 this.send(
147 {
148 type: "getProperty",
149 objectId: objectId,
150 property: property
151 })
152 );
153 },
154 createProperty: function(objectId, property, enumerable)
155 {
156 return {
157 get: function()
158 {
159 return this.getProperty(objectId, property);
160 }.bind(this),
161 set: function(value)
162 {
163 this.checkResult(
164 this.send(
165 {
166 type: "setProperty",
167 objectId: objectId,
168 property: property,
169 value: this.serialize(value)
170 })
171 );
172 }.bind(this),
173 enumerable: enumerable,
174 configurable: true
175 };
176 },
177 createFunction: function(objectId)
178 {
179 var proxy = this;
180 return function()
181 {
182 return proxy.deserializeResult(
183 proxy.send(
184 {
185 type: "callFunction",
186 functionId: objectId,
187 contextId: proxy.objects.indexOf(this),
188 args: Array.prototype.map.call(
189 arguments,
190 proxy.serialize.bind(proxy)
191 )
192 })
193 );
194 };
195 },
196 getObject: function(objectId) {
197 var objectInfo = this.send({
198 type: "inspectObject",
199 objectId: objectId
200 });
201
202 var obj = this.objects[objectId];
203 if (obj)
204 Object.getOwnPropertyNames(obj).forEach(function(prop) { delete obj[prop ]; });
205 else
206 {
207 if (objectInfo.isFunction)
208 obj = this.createFunction(objectId);
209 else
210 obj = {};
211
212 this.objects[objectId] = obj;
213 }
214
215 var ignored = [];
216 if ("prototypeOf" in objectInfo)
217 {
218 var prototype = window[objectInfo.prototypeOf].prototype;
219
220 ignored = Object.getOwnPropertyNames(prototype);
221 ignored.splice(ignored.indexOf("constructor"), 1);
222
223 obj.__proto__ = prototype;
224 }
225 else
226 {
227 if (objectInfo.isFunction)
228 ignored = Object.getOwnPropertyNames(function() {});
229 else
230 ignored = [];
231
232 if ("prototypeId" in objectInfo)
233 obj.__proto__ = this.getObject(objectInfo.prototypeId);
234 else
235 obj.__proto__ = null;
236 }
237
238 for (var property in objectInfo.properties)
239 if (ignored.indexOf(property) == -1)
240 Object.defineProperty(obj, property, this.createProperty(
241 objectId, property,
242 objectInfo.properties[property].enumerable
243 ));
244
245 if (objectInfo.isFunction)
246 obj.prototype = this.getProperty(objectId, "prototype");
247
248 return obj;
249 }
250 };
251
252
253 /* Web request blocking */
254
255 document.addEventListener("beforeload", function(event)
256 {
257 var type;
258
259 switch(event.target.nodeName)
260 {
261 case "FRAME":
262 case "IFRAME":
263 type = "frame";
264 break;
265 case "IMG":
266 type = "image";
267 break;
268 case "OBJECT":
269 case "EMBED":
270 type = "object";
271 break;
272 case "SCRIPT":
273 type = "script";
274 break;
275 case "LINK":
276 if (/(^|\s)stylesheet($|\s)/i.test(event.target.rel))
277 {
278 type = "stylesheet";
279 break;
280 }
281 default:
282 type = "other";
283 }
284
285 if (!safari.self.tab.canLoad(event, {type: "webRequest", payload: {url: even t.url, type: type}}))
286 event.preventDefault();
287 }, true);
288
289
290 /* API */
291
292 ext.backgroundPage = {
293 _eventTarget: safari.self,
294 _messageDispatcher: safari.self.tab,
295
296 sendMessage: sendMessage,
297 getWindow: function() { return proxy.getObject(0); }
298 };
299
300 ext.onMessage = new MessageEventTarget(safari.self);
301 })();
OLDNEW
« no previous file with comments | « safari/common.js ('k') | stats.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld