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

Side by Side Diff: safari/ext/background.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 | « options.js ('k') | safari/ext/content.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 <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 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 onBeforeRequest: new ext._EventTarget(), 375 onBeforeRequest: new ext._EventTarget(),
376 handlerBehaviorChanged: function() 376 handlerBehaviorChanged: function()
377 { 377 {
378 }, 378 },
379 getIndistinguishableTypes: function() 379 getIndistinguishableTypes: function()
380 { 380 {
381 return []; 381 return [];
382 } 382 }
383 }; 383 };
384 384
385
386 /* Background page proxy (for access from content scripts) */
387
388 var backgroundPageProxy = {
389 cache: new ext.PageMap(),
390
391 registerObject: function(obj, objects)
392 {
393 var objectId = objects.indexOf(obj);
394
395 if (objectId == -1)
396 objectId = objects.push(obj) - 1;
397
398 return objectId;
399 },
400 serializeSequence: function(sequence, objects, memo)
401 {
402 if (!memo)
403 memo = {specs: [], arrays: []};
404
405 var items = [];
406 for (var i = 0; i < sequence.length; i++)
407 items.push(this.serialize(sequence[i], objects, memo));
408
409 return items;
410 },
411 serialize: function(obj, objects, memo)
412 {
413 if (typeof obj == "object" && obj != null || typeof obj == "function")
414 {
415 if (obj.constructor == Array)
416 {
417 if (!memo)
418 memo = {specs: [], arrays: []};
419
420 var idx = memo.arrays.indexOf(obj);
421 if (idx != -1)
422 return memo.specs[idx];
423
424 var spec = {type: "array"};
425 memo.specs.push(spec);
426 memo.arrays.push(obj);
427
428 spec.items = this.serializeSequence(obj, objects, memo);
429 return spec;
430 }
431
432 if (obj.constructor != Date && obj.constructor != RegExp)
433 return {type: "object", objectId: this.registerObject(obj, objects)};
434 }
435
436 return {type: "value", value: obj};
437 },
438 createCallback: function(callbackId, pageId, frameId)
439 {
440 var proxy = this;
441
442 return function()
443 {
444 var page = pages[pageId];
445 if (!page)
446 return;
447
448 var objects = proxy.cache.get(page);
449 if (!objects)
450 return;
451
452 var targetDocument;
453 for (var documentId in page._tab._documentLookup)
454 {
455 var result = page._tab._documentLookup[documentId];
456 if (result.pageId == pageId && result.frameId == frameId)
457 {
458 targetDocument = documentId;
459 break;
460 }
461 }
462 if (!targetDocument)
463 return;
464
465 page._tab.page.dispatchMessage("proxyCallback",
466 {
467 targetDocuments: [targetDocument],
468 callbackId: callbackId,
469 contextId: proxy.registerObject(this, objects),
470 args: proxy.serializeSequence(arguments, objects)
471 });
472 };
473 },
474 deserialize: function(spec, objects, pageId, frameId, memo)
475 {
476 switch (spec.type)
477 {
478 case "value":
479 return spec.value;
480 case "hosted":
481 return objects[spec.objectId];
482 case "callback":
483 return this.createCallback(spec.callbackId, pageId, frameId);
484 case "object":
485 case "array":
486 if (!memo)
487 memo = {specs: [], objects: []};
488
489 var idx = memo.specs.indexOf(spec);
490 if (idx != -1)
491 return memo.objects[idx];
492
493 var obj;
494 if (spec.type == "array")
495 obj = [];
496 else
497 obj = {};
498
499 memo.specs.push(spec);
500 memo.objects.push(obj);
501
502 if (spec.type == "array")
503 for (var i = 0; i < spec.items.length; i++)
504 obj.push(this.deserialize(spec.items[i], objects,
505 pageId, frameId, memo));
506 else
507 for (var k in spec.properties)
508 obj[k] = this.deserialize(spec.properties[k], objects,
509 pageId, frameId, memo);
510
511 return obj;
512 }
513 },
514 getObjectCache: function(page)
515 {
516 var objects = this.cache.get(page);
517 if (!objects)
518 {
519 objects = [window];
520 this.cache.set(page, objects);
521 }
522 return objects;
523 },
524 fail: function(error)
525 {
526 if (error instanceof Error)
527 error = error.message;
528 return {succeed: false, error: error};
529 },
530 handleMessage: function(message)
531 {
532 var objects = this.getObjectCache(pages[message.pageId]);
533
534 switch (message.type)
535 {
536 case "getProperty":
537 var obj = objects[message.objectId];
538
539 try
540 {
541 var value = obj[message.property];
542 }
543 catch (e)
544 {
545 return this.fail(e);
546 }
547
548 return {succeed: true, result: this.serialize(value, objects)};
549 case "setProperty":
550 var obj = objects[message.objectId];
551 var value = this.deserialize(message.value, objects,
552 message.pageId, message.frameId);
553
554 try
555 {
556 obj[message.property] = value;
557 }
558 catch (e)
559 {
560 return this.fail(e);
561 }
562
563 return {succeed: true};
564 case "callFunction":
565 var func = objects[message.functionId];
566 var context = objects[message.contextId];
567
568 var args = [];
569 for (var i = 0; i < message.args.length; i++)
570 args.push(this.deserialize(message.args[i], objects,
571 message.pageId, message.frameId));
572
573 try
574 {
575 var result = func.apply(context, args);
576 }
577 catch (e)
578 {
579 return this.fail(e);
580 }
581
582 return {succeed: true, result: this.serialize(result, objects)};
583 case "inspectObject":
584 var obj = objects[message.objectId];
585 var objectInfo = {properties: {}, isFunction: typeof obj == "function" };
586
587 Object.getOwnPropertyNames(obj).forEach(function(prop)
588 {
589 objectInfo.properties[prop] = {
590 enumerable: Object.prototype.propertyIsEnumerable.call(obj, prop)
591 };
592 });
593
594 var proto = Object.getPrototypeOf(obj);
595 if (proto)
596 objectInfo.prototypeId = this.registerObject(proto, objects);
597
598 if (obj == Object.prototype)
599 objectInfo.prototypeOf = "Object";
600 if (obj == Function.prototype)
601 objectInfo.prototypeOf = "Function";
602
603 return objectInfo;
604 }
605 }
606 };
607
608
609 /* Message processing */ 385 /* Message processing */
610 386
611 safari.application.addEventListener("message", function(event) 387 safari.application.addEventListener("message", function(event)
612 { 388 {
613 var tab = event.target; 389 var tab = event.target;
614 var message = event.message; 390 var message = event.message;
615 var sender; 391 var sender;
616 if ("documentId" in message && "_documentLookup" in tab) 392 if ("documentId" in message && "_documentLookup" in tab)
617 { 393 {
618 sender = tab._documentLookup[message.documentId]; 394 sender = tab._documentLookup[message.documentId];
(...skipping 10 matching lines...) Expand all
629 switch (message.category) 405 switch (message.category)
630 { 406 {
631 case "webRequest": 407 case "webRequest":
632 var results = ext.webRequest.onBeforeRequest._dispatch( 408 var results = ext.webRequest.onBeforeRequest._dispatch(
633 new URL(message.url, sender.frame.url), 409 new URL(message.url, sender.frame.url),
634 message.type, sender.page, sender.frame 410 message.type, sender.page, sender.frame
635 ); 411 );
636 412
637 event.message = (results.indexOf(false) == -1); 413 event.message = (results.indexOf(false) == -1);
638 break; 414 break;
639 case "proxy":
640 message.pageId = sender.pageId;
641 message.frameId = sender.frameId;
642 event.message = backgroundPageProxy.handleMessage(message);
643 break;
644 case "request": 415 case "request":
645 var response = null; 416 var response = null;
646 var sendResponse = function(message) { response = message; }; 417 var sendResponse = function(message) { response = message; };
647 418
648 ext.onMessage._dispatch(message.payload, sender, sendResponse); 419 ext.onMessage._dispatch(message.payload, sender, sendResponse);
649 420
650 event.message = response; 421 event.message = response;
651 break; 422 break;
652 } 423 }
653 break; 424 break;
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
816 /* Windows */ 587 /* Windows */
817 ext.windows = { 588 ext.windows = {
818 // Safari doesn't provide as rich a windows API as Chrome does, so instead 589 // Safari doesn't provide as rich a windows API as Chrome does, so instead
819 // of chrome.windows.create we have to fall back to just opening a new tab. 590 // of chrome.windows.create we have to fall back to just opening a new tab.
820 create: function(createData, callback) 591 create: function(createData, callback)
821 { 592 {
822 ext.pages.open(createData.url, callback); 593 ext.pages.open(createData.url, callback);
823 } 594 }
824 }; 595 };
825 })(); 596 })();
OLDNEW
« no previous file with comments | « options.js ('k') | safari/ext/content.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld