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

Side by Side Diff: safari/ext/content.js

Issue 29339314: Issue 3870 - Rewrite legacy options page to use async messages (Closed)
Patch Set: Avoid another race condition Created April 7, 2016, 1:27 p.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/ext/background.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 })();
OLDNEW
« no previous file with comments | « safari/ext/background.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld