/**
 * StopFlash
 *
 * https://github.com/JWhile/StopFlash
 *
 * background.js
 */

// class BackgroundFlashCollection(id)
function BackgroundFlashCollection(id)
{
    this.id = id;
};

// class BackgroundFlashData
function BackgroundFlashData(id)
{
    this.id = id; // :int

    this.data = []; // :Array<Object>

    this.popupPort = null; // :chrome.runtime.Port
    this.contentPorts = []; // :Array<chrome.runtime.Port>
}
// function setData(Object data):void
BackgroundFlashData.prototype.setData = function(data)
{
    if(data.length > 0)
    {
        Array.prototype.unshift.apply(this.data, data);

        this.sendToPopup();
    }
};
// function setPopup(chrome.runtime.Port popupPort):void
BackgroundFlashData.prototype.setPopup = function(popupPort)
{
    this.popupPort = popupPort;

    var self = this;

    this.popupPort.onDisconnect.addListener(function()
    {
        self.popupPort = null;
    });

    this.sendToPopup();
};
// function setContentScript(chrome.runtime.Port contentPort):void
BackgroundFlashData.prototype.setContentScript = function(contentPort)
{
    this.contentPorts.push(contentPort);

    var self = this;

    contentPort.onDisconnect.addListener(function()
    {
        var index = self.contentPorts.indexOf(contentPort);

        if(index >= 0)
        {
            self.contentPorts.splice(index, 1);
        }
    });

    contentPort.postMessage({'stopflashWhitelist': whitelist, 'stopflashContentId': 0});
};
// function sendToPopup():void
BackgroundFlashData.prototype.sendToPopup = function()
{
    if(this.popupPort != null)
    {
        this.popupPort.postMessage({'stopflashData': this.data});
    }
};
// function sendToContent(Object data):void
BackgroundFlashData.prototype.sendToContent = function(data)
{
    for(var i = 0; i < this.contentPorts.length; ++i)
    {
        this.contentPorts[i].postMessage(data);
    }
};
// function clear():void
BackgroundFlashData.prototype.clear = function()
{
    this.data = null;

    if(this.popupPort != null)
    {
        this.popupPort.disconnect();
    }

    this.popupPort = null;

    if(this.contentPorts.length > 0)
    {
        for(var i = 0; i < this.contentPorts.length; ++i)
        {
            this.contentPorts[i].disconnect();
        }
    }

    this.contentPort = [];
};

var flashData = []; // :Array<BackgroundFlashData>
var whitelist = []; // :Array<String>
var collectionId = 0; // :int

// function getFlashData(int id):BackgroundFlashData
var getFlashData = function(id)
{
    for(var i = 0; i < flashData.length; ++i)
    {
        if(flashData[i].id === id)
        {
            return flashData[i];
        }
    }

    return null;
};

chrome.runtime.onConnect.addListener(function(port)
{
    if(port.name === 'stopflashContentScript' && port.sender.tab != null)
    {
        var data = null;

        port.onMessage.addListener(function(rep)
        {
            if(rep['stopflashInit'])
            {
                data = getFlashData(port.sender.tab.id);

                if(data != null)
                {
                    if(rep['stopflashIsMainFrame'])
                    {
                        data.clear();
                    }
                }
                else
                {
                    data = new BackgroundFlashData(port.sender.tab.id);

                    flashData.push(data);
                }

                data.setContentScript(port);
            }

            if(rep['stopflashHaveChange'])
            {
                if(rep['stopflashIsMainFrame'])
                {
                    data.data = [];
                }

                data.sendToContent({'stopflashDataUpdate': true});
            }

            if(rep['stopflashDataUpdate'] && rep['stopflashData'])
            {
                data.setData(rep.stopflashData);
            }
        });
    }
    else if(port.name === 'stopflashPopup')
    {
        var data = null;

        port.onMessage.addListener(function(rep)
        {
            if(rep['stopflashInit'])
            {
                data = getFlashData(rep['stopflashInit']);

                if(data != null)
                {
                    data.setPopup(port);
                }
            }

            if(rep['stopflashBlock'])
            {

                data.sendToContent({'stopflashBlock': rep['stopflashBlock']});
            }

            if(rep['stopflashUnblock'])
            {
                data.sendToContent({'stopflashUnblock': rep['stopflashUnblock']});
            }
        });
    }
});

@@ -111,20 +111,16 @@
 llection
-(id)
 %0Afunctio
@@ -141,32 +141,38 @@
 ashCollection(id
+, port
 )%0A%7B%0A    this.id 
@@ -176,16 +176,179 @@
 id = id;
+ // :int%0A%0A    this.port = port; // :chrome.runtime.Port%0A%0A    var self = this;%0A%0A    port.onDisconnect.addListener(function()%0A    %7B%0A        self.port = null;%0A    %7D);
 %0A%7D;%0A%0A// 
@@ -487,49 +487,63 @@
 his.
-popupPort = null; // :chrome.runtime.Port
+collections = %5B%5D; // :Array%3CBackgroundFlashCollection%3E%0A
 %0A   
@@ -552,37 +552,30 @@
 his.
-content
+popup
 Port
-s
  = 
-%5B%5D
+null
 ; // :
-Array%3C
 chro
@@ -589,17 +589,16 @@
 ime.Port
-%3E
 %0A%7D%0A// fu
@@ -1269,276 +1269,81 @@
 s.co
-ntentPorts.push(contentPort);%0A%0A    var self = this;%0A%0A    contentPort.onDisconnect.addListener(function()%0A    %7B%0A        var index = self.contentPorts.indexOf(contentPort);%0A%0A        if(index %3E= 0)%0A        %7B%0A            self.contentPorts.splice(index, 1);%0A        %7D%0A    %7D
+llections.push(new BackgroundFlashCollection(++collectionId, contentPort)
 );%0A%0A

Put port into BackgroundFlashCollection + Add BackgroundFlashData::collections & remove contentPorts