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

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

Issue 5220277533278208: Made the bubble use the ext object from the background page instead of including ext/background.js (Closed)
Patch Set: Rebased and moved imports to the bottom Created Jan. 15, 2014, 4:38 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 | « popup.html ('k') | safari/ext/popup.js » ('j') | 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 <http://adblockplus.org/>, 2 * This file is part of Adblock Plus <http://adblockplus.org/>,
3 * Copyright (C) 2006-2013 Eyeo GmbH 3 * Copyright (C) 2006-2013 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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 openTab: function(url, callback) 181 openTab: function(url, callback)
182 { 182 {
183 var tab = this._win.openTab(); 183 var tab = this._win.openTab();
184 tab.url = url; 184 tab.url = url;
185 185
186 if (callback) 186 if (callback)
187 callback(new Tab(tab)); 187 callback(new Tab(tab));
188 } 188 }
189 }; 189 };
190 190
191 if (safari.extension.globalPage.contentWindow == window) 191
192 /* Background page proxy */
193
194 var proxy = {
195 tabs: [],
196 objects: [],
197
198 registerObject: function(obj, objects)
199 {
200 var objectId = objects.indexOf(obj);
201
202 if (objectId == -1)
203 objectId = objects.push(obj) - 1;
204
205 return objectId;
206 },
207 serializeSequence: function(sequence, objects, memo)
208 {
209 if (!memo)
210 memo = {specs: [], arrays: []};
211
212 var items = [];
213 for (var i = 0; i < sequence.length; i++)
214 items.push(this.serialize(sequence[i], objects, memo));
215
216 return items;
217 },
218 serialize: function(obj, objects, memo)
219 {
220 if (typeof obj == "object" && obj != null || typeof obj == "function")
221 {
222 if (obj.constructor == Array)
223 {
224 if (!memo)
225 memo = {specs: [], arrays: []};
226
227 var idx = memo.arrays.indexOf(obj);
228 if (idx != -1)
229 return memo.specs[idx];
230
231 var spec = {type: "array"};
232 memo.specs.push(spec);
233 memo.arrays.push(obj);
234
235 spec.items = this.serializeSequence(obj, objects, memo);
236 return spec;
237 }
238
239 if (obj.constructor != Date && obj.constructor != RegExp)
240 return {type: "object", objectId: this.registerObject(obj, objects)};
241 }
242
243 return {type: "value", value: obj};
244 },
245 createCallback: function(callbackId, tab)
246 {
247 var proxy = this;
248
249 return function()
250 {
251 var idx = proxy.tabs.indexOf(tab);
252
253 if (idx != -1) {
254 var objects = proxy.objects[idx];
255
256 tab.page.dispatchMessage("proxyCallback",
257 {
258 callbackId: callbackId,
259 contextId: proxy.registerObject(this, objects),
260 args: proxy.serializeSequence(arguments, objects)
261 });
262 }
263 };
264 },
265 deserialize: function(spec, objects, tab, memo)
266 {
267 switch (spec.type)
268 {
269 case "value":
270 return spec.value;
271 case "hosted":
272 return objects[spec.objectId];
273 case "callback":
274 return this.createCallback(spec.callbackId, tab);
275 case "object":
276 case "array":
277 if (!memo)
278 memo = {specs: [], objects: []};
279
280 var idx = memo.specs.indexOf(spec);
281 if (idx != -1)
282 return memo.objects[idx];
283
284 var obj;
285 if (spec.type == "array")
286 obj = [];
287 else
288 obj = {};
289
290 memo.specs.push(spec);
291 memo.objects.push(obj);
292
293 if (spec.type == "array")
294 for (var i = 0; i < spec.items.length; i++)
295 obj.push(this.deserialize(spec.items[i], objects, tab, memo));
296 else
297 for (var k in spec.properties)
298 obj[k] = this.deserialize(spec.properties[k], objects, tab, memo);
299
300 return obj;
301 }
302 },
303 createObjectCache: function(tab)
304 {
305 var objects = [window];
306
307 this.tabs.push(tab);
308 this.objects.push(objects);
309
310 tab.addEventListener("close", function()
311 {
312 var idx = this.tabs.indexOf(tab);
313
314 if (idx != -1)
315 {
316 this.tabs.splice(idx, 1);
317 this.objects.splice(idx, 1);
318 }
319 }.bind(this));
320
321 return objects;
322 },
323 getObjectCache: function(tab)
324 {
325 var idx = this.tabs.indexOf(tab);
326 var objects;
327
328 if (idx != -1)
329 objects = this.objects[idx];
330 else
331 objects = this.objects[idx] = this.createObjectCache(tab);
332
333 return objects;
334 },
335 fail: function(error)
336 {
337 if (error instanceof Error)
338 error = error.message;
339 return {succeed: false, error: error};
340 },
341 _handleMessage: function(message, tab)
342 {
343 var objects = this.getObjectCache(tab);
344
345 switch (message.type)
346 {
347 case "getProperty":
348 var obj = objects[message.objectId];
349
350 try
351 {
352 var value = obj[message.property];
353 }
354 catch (e)
355 {
356 return this.fail(e);
357 }
358
359 return {succeed: true, result: this.serialize(value, objects)};
360 case "setProperty":
361 var obj = objects[message.objectId];
362 var value = this.deserialize(message.value, objects, tab);
363
364 try
365 {
366 obj[message.property] = value;
367 }
368 catch (e)
369 {
370 return this.fail(e);
371 }
372
373 return {succeed: true};
374 case "callFunction":
375 var func = objects[message.functionId];
376 var context = objects[message.contextId];
377
378 var args = [];
379 for (var i = 0; i < message.args.length; i++)
380 args.push(this.deserialize(message.args[i], objects, tab));
381
382 try
383 {
384 var result = func.apply(context, args);
385 }
386 catch (e)
387 {
388 return this.fail(e);
389 }
390
391 return {succeed: true, result: this.serialize(result, objects)};
392 case "inspectObject":
393 var obj = objects[message.objectId];
394 var objectInfo = {properties: {}, isFunction: typeof obj == "function" };
395
396 Object.getOwnPropertyNames(obj).forEach(function(prop)
397 {
398 objectInfo.properties[prop] = {
399 enumerable: Object.prototype.propertyIsEnumerable.call(obj, prop)
400 };
401 });
402
403 if (obj.__proto__)
404 objectInfo.prototypeId = this.registerObject(obj.__proto__, objects) ;
405
406 if (obj == Object.prototype)
407 objectInfo.prototypeOf = "Object";
408 if (obj == Function.prototype)
409 objectInfo.prototypeOf = "Function";
410
411 return objectInfo;
412 }
413 }
414 };
415
416
417 /* Web request blocking */
418
419 ext.webRequest = {
420 onBeforeRequest: {
421 _listeners: [],
422 _urlPatterns: [],
423
424 _handleMessage: function(message, tab)
425 {
426 tab = new Tab(tab);
427
428 for (var i = 0; i < this._listeners.length; i++)
429 {
430 var regex = this._urlPatterns[i];
431
432 if ((!regex || regex.test(message.url)) && this._listeners[i](message. url, message.type, tab, 0, -1) === false)
433 return false;
434 }
435
436 return true;
437 },
438 addListener: function(listener, urls)
439 {
440 var regex;
441
442 if (urls)
443 regex = new RegExp("^(?:" + urls.map(function(url)
444 {
445 return url.split("*").map(function(s)
446 {
447 return s.replace(/([.?+^$[\]\\(){}|-])/g, "\\$1");
448 }).join(".*");
449 }).join("|") + ")($|[?#])");
450
451 this._listeners.push(listener);
452 this._urlPatterns.push(regex);
453 },
454 removeListener: function(listener)
455 {
456 var idx = this._listeners.indexOf(listener);
457
458 if (idx != -1)
459 {
460 this._listeners.splice(idx, 1);
461 this._urlPatterns.splice(idx, 1);
462 }
463 }
464 },
465 handlerBehaviorChanged: function() {}
466 };
467
468
469 /* Synchronous messaging */
470
471 safari.application.addEventListener("message", function(event)
192 { 472 {
193 /* Background page proxy */ 473 if (event.name == "canLoad")
194 474 {
195 var proxy = { 475 var handler;
196 tabs: [], 476
197 objects: [], 477 switch (event.message.type)
198 478 {
199 registerObject: function(obj, objects) 479 case "proxy":
200 { 480 handler = proxy;
201 var objectId = objects.indexOf(obj); 481 break;
202 482 case "webRequest":
203 if (objectId == -1) 483 handler = ext.webRequest.onBeforeRequest;
204 objectId = objects.push(obj) - 1; 484 break;
205 485 }
206 return objectId; 486
207 }, 487 event.message = handler._handleMessage(event.message.payload, event.target );
208 serializeSequence: function(sequence, objects, memo) 488 }
209 { 489 }, true);
210 if (!memo)
211 memo = {specs: [], arrays: []};
212
213 var items = [];
214 for (var i = 0; i < sequence.length; i++)
215 items.push(this.serialize(sequence[i], objects, memo));
216
217 return items;
218 },
219 serialize: function(obj, objects, memo)
220 {
221 if (typeof obj == "object" && obj != null || typeof obj == "function")
222 {
223 if (obj.constructor == Array)
224 {
225 if (!memo)
226 memo = {specs: [], arrays: []};
227
228 var idx = memo.arrays.indexOf(obj);
229 if (idx != -1)
230 return memo.specs[idx];
231
232 var spec = {type: "array"};
233 memo.specs.push(spec);
234 memo.arrays.push(obj);
235
236 spec.items = this.serializeSequence(obj, objects, memo);
237 return spec;
238 }
239
240 if (obj.constructor != Date && obj.constructor != RegExp)
241 return {type: "object", objectId: this.registerObject(obj, objects)} ;
242 }
243
244 return {type: "value", value: obj};
245 },
246 createCallback: function(callbackId, tab)
247 {
248 var proxy = this;
249
250 return function()
251 {
252 var idx = proxy.tabs.indexOf(tab);
253
254 if (idx != -1) {
255 var objects = proxy.objects[idx];
256
257 tab.page.dispatchMessage("proxyCallback",
258 {
259 callbackId: callbackId,
260 contextId: proxy.registerObject(this, objects),
261 args: proxy.serializeSequence(arguments, objects)
262 });
263 }
264 };
265 },
266 deserialize: function(spec, objects, tab, memo)
267 {
268 switch (spec.type)
269 {
270 case "value":
271 return spec.value;
272 case "hosted":
273 return objects[spec.objectId];
274 case "callback":
275 return this.createCallback(spec.callbackId, tab);
276 case "object":
277 case "array":
278 if (!memo)
279 memo = {specs: [], objects: []};
280
281 var idx = memo.specs.indexOf(spec);
282 if (idx != -1)
283 return memo.objects[idx];
284
285 var obj;
286 if (spec.type == "array")
287 obj = [];
288 else
289 obj = {};
290
291 memo.specs.push(spec);
292 memo.objects.push(obj);
293
294 if (spec.type == "array")
295 for (var i = 0; i < spec.items.length; i++)
296 obj.push(this.deserialize(spec.items[i], objects, tab, memo));
297 else
298 for (var k in spec.properties)
299 obj[k] = this.deserialize(spec.properties[k], objects, tab, memo );
300
301 return obj;
302 }
303 },
304 createObjectCache: function(tab)
305 {
306 var objects = [window];
307
308 this.tabs.push(tab);
309 this.objects.push(objects);
310
311 tab.addEventListener("close", function()
312 {
313 var idx = this.tabs.indexOf(tab);
314
315 if (idx != -1)
316 {
317 this.tabs.splice(idx, 1);
318 this.objects.splice(idx, 1);
319 }
320 }.bind(this));
321
322 return objects;
323 },
324 getObjectCache: function(tab)
325 {
326 var idx = this.tabs.indexOf(tab);
327 var objects;
328
329 if (idx != -1)
330 objects = this.objects[idx];
331 else
332 objects = this.objects[idx] = this.createObjectCache(tab);
333
334 return objects;
335 },
336 fail: function(error)
337 {
338 if (error instanceof Error)
339 error = error.message;
340 return {succeed: false, error: error};
341 },
342 _handleMessage: function(message, tab)
343 {
344 var objects = this.getObjectCache(tab);
345
346 switch (message.type)
347 {
348 case "getProperty":
349 var obj = objects[message.objectId];
350
351 try
352 {
353 var value = obj[message.property];
354 }
355 catch (e)
356 {
357 return this.fail(e);
358 }
359
360 return {succeed: true, result: this.serialize(value, objects)};
361 case "setProperty":
362 var obj = objects[message.objectId];
363 var value = this.deserialize(message.value, objects, tab);
364
365 try
366 {
367 obj[message.property] = value;
368 }
369 catch (e)
370 {
371 return this.fail(e);
372 }
373
374 return {succeed: true};
375 case "callFunction":
376 var func = objects[message.functionId];
377 var context = objects[message.contextId];
378
379 var args = [];
380 for (var i = 0; i < message.args.length; i++)
381 args.push(this.deserialize(message.args[i], objects, tab));
382
383 try
384 {
385 var result = func.apply(context, args);
386 }
387 catch (e)
388 {
389 return this.fail(e);
390 }
391
392 return {succeed: true, result: this.serialize(result, objects)};
393 case "inspectObject":
394 var obj = objects[message.objectId];
395 var objectInfo = {properties: {}, isFunction: typeof obj == "functio n"};
396
397 Object.getOwnPropertyNames(obj).forEach(function(prop)
398 {
399 objectInfo.properties[prop] = {
400 enumerable: Object.prototype.propertyIsEnumerable.call(obj, prop )
401 };
402 });
403
404 if (obj.__proto__)
405 objectInfo.prototypeId = this.registerObject(obj.__proto__, object s);
406
407 if (obj == Object.prototype)
408 objectInfo.prototypeOf = "Object";
409 if (obj == Function.prototype)
410 objectInfo.prototypeOf = "Function";
411
412 return objectInfo;
413 }
414 }
415 };
416
417
418 /* Web request blocking */
419
420 ext.webRequest = {
421 onBeforeRequest: {
422 _listeners: [],
423 _urlPatterns: [],
424
425 _handleMessage: function(message, tab)
426 {
427 tab = new Tab(tab);
428
429 for (var i = 0; i < this._listeners.length; i++)
430 {
431 var regex = this._urlPatterns[i];
432
433 if ((!regex || regex.test(message.url)) && this._listeners[i](messag e.url, message.type, tab, 0, -1) === false)
434 return false;
435 }
436
437 return true;
438 },
439 addListener: function(listener, urls)
440 {
441 var regex;
442
443 if (urls)
444 regex = new RegExp("^(?:" + urls.map(function(url)
445 {
446 return url.split("*").map(function(s)
447 {
448 return s.replace(/([.?+^$[\]\\(){}|-])/g, "\\$1");
449 }).join(".*");
450 }).join("|") + ")($|[?#])");
451
452 this._listeners.push(listener);
453 this._urlPatterns.push(regex);
454 },
455 removeListener: function(listener)
456 {
457 var idx = this._listeners.indexOf(listener);
458
459 if (idx != -1)
460 {
461 this._listeners.splice(idx, 1);
462 this._urlPatterns.splice(idx, 1);
463 }
464 }
465 },
466 handlerBehaviorChanged: function() {}
467 };
468
469
470 /* Synchronous messaging */
471
472 safari.application.addEventListener("message", function(event)
473 {
474 if (event.name == "canLoad")
475 {
476 var handler;
477
478 switch (event.message.type)
479 {
480 case "proxy":
481 handler = proxy;
482 break;
483 case "webRequest":
484 handler = ext.webRequest.onBeforeRequest;
485 break;
486 }
487
488 event.message = handler._handleMessage(event.message.payload, event.targ et);
489 }
490 }, true);
491 }
492 490
493 491
494 /* API */ 492 /* API */
495 493
496 ext.windows = { 494 ext.windows = {
497 getAll: function(callback) 495 getAll: function(callback)
498 { 496 {
499 callback(safari.application.browserWindows.map(function(win) 497 callback(safari.application.browserWindows.map(function(win)
500 { 498 {
501 return new Window(win); 499 return new Window(win);
(...skipping 19 matching lines...) Expand all
521 } 519 }
522 }; 520 };
523 521
524 ext.onMessage = new MessageEventTarget(safari.application); 522 ext.onMessage = new MessageEventTarget(safari.application);
525 523
526 // TODO: Implement context menu 524 // TODO: Implement context menu
527 ext.contextMenus = { 525 ext.contextMenus = {
528 create: function(title, contexts, onclick) {}, 526 create: function(title, contexts, onclick) {},
529 removeAll: function(callback) {} 527 removeAll: function(callback) {}
530 }; 528 };
531
532 // Safari will load the bubble once, and then show it everytime the icon is
533 // clicked. While Chrome loads it everytime you click the icon. So in order to
534 // force the same behavior in Safari, we are going to reload the page of the
535 // bubble everytime it is shown.
536 if (safari.extension.globalPage.contentWindow != window)
537 safari.application.addEventListener("popover", function()
538 {
539 document.documentElement.style.display = "none";
540 document.location.reload();
541 }, true);
542 })(); 529 })();
OLDNEW
« no previous file with comments | « popup.html ('k') | safari/ext/popup.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld