var ArrayExtensions = {
    init: function() {
        if (!Array.prototype.remove) {
            Array.prototype.remove = function(value) {
                var index = this.indexOf(value);
                if (index === -1)
                    return false;

                this.splice(index, 1);
                return true;
            };
        }

        if (!Array.prototype.addDistinct) {
            Array.prototype.addDistinct = function(value) {
                var index = this.indexOf(value);
                if (index !== -1)
                    return false;
                this.push(value);
                return true;
            };
        }
    }
};

var Filters = {
    pinnedTabs: function(x) {
        return !!x.pinned;
    },
    tabsWithUrl: function(url) {
        return function(x) {
            return x.url == url;
        };
    }
};

var GlobalPinnedTabs = {

    globalPinnedTabUrls: [],

    tabIdToUrlMapping: {},
    urlToTabIdMapping: {},

    init: function() {

        ArrayExtensions.init();
        GlobalPinnedTabs.loadData();

        chrome.windows.onFocusChanged.addListener(GlobalPinnedTabs.activeWindowChanged);
        chrome.tabs.onUpdated.addListener(GlobalPinnedTabs.onTabUpdate);
        chrome.tabs.onRemoved.addListener(GlobalPinnedTabs.onTabClose);

        chrome.windows.getCurrent({
            populate: true
        }, function(window) {
            GlobalPinnedTabs.displayTabs(window);
        });
    },

    pinTab: function(tab) {
        chrome.tabs.update(tab.id, {
            pinned: true
        });
    },

    moveTab: function(windowId, tabId) {
        chrome.tabs.move(parseInt(tabId), {
            windowId: windowId,
            index: 0
        }, GlobalPinnedTabs.pinTab);
    },

    activeWindowChanged: function(windowId) {
        if (windowId === chrome.windows.WINDOW_ID_NONE)
            return;
        chrome.windows.get(parseInt(windowId), {
            populate: true
        }, function(window) {
            GlobalPinnedTabs.displayTabs(window);
        });
    },

    displayTabs: function(window) {
        if (window.type === 'popup')
            return;

        var url;
        for (var key in GlobalPinnedTabs.tabIdToUrlMapping) {
            url = GlobalPinnedTabs.tabIdToUrlMapping[key];
            if (GlobalPinnedTabs.getMatchingTab(url, window) === undefined)
                GlobalPinnedTabs.moveTab(window.id, key);
        }

        for (var i = 0; i < GlobalPinnedTabs.globalPinnedTabUrls.length; i++) {
            url = GlobalPinnedTabs.globalPinnedTabUrls[i];
            if (GlobalPinnedTabs.urlToTabIdMapping[url] === undefined)
                GlobalPinnedTabs.createTab(url, window);
        }
    },

    createTabCallback: function(tab) {
        GlobalPinnedTabs.tabIdToUrlMapping[tab.id] = tab.url;
        GlobalPinnedTabs.urlToTabIdMapping[tab.url] = tab.id;
    },

    onTabUpdate: function(tabId, changeInfo, tab) {
        if (GlobalPinnedTabs.disableTabUpdateHandling)
            return;
        if (changeInfo.pinned !== undefined) {
            if (changeInfo.pinned === true) {
                if (GlobalPinnedTabs.tabIdToUrlMapping[tabId] === undefined && confirm('Make this a globally pinned tab that is visible in all windows?')) {
                    GlobalPinnedTabs.tabIdToUrlMapping[tabId] = tab.url;
                    GlobalPinnedTabs.urlToTabIdMapping[tab.url] = tabId;
                    GlobalPinnedTabs.globalPinnedTabUrls.addDistinct(tab.url);
                    GlobalPinnedTabs.persistData();
                }
            } else {
                GlobalPinnedTabs.handleRemovedTab(tabId);
            }
        }
    },

    disableTabCloseHandling: false,
    disableTabUpdateHandling: false,

    onTabClose: function(tabId, removeInfo) {
        if (!removeInfo.isWindowClosing && !GlobalPinnedTabs.disableTabCloseHandling)
            GlobalPinnedTabs.handleRemovedTab(tabId);
    },

    handleRemovedTab: function(tabId) {
        var url = GlobalPinnedTabs.tabIdToUrlMapping[tabId];
        if (url) {
            delete GlobalPinnedTabs.tabIdToUrlMapping[tabId];
            delete GlobalPinnedTabs.urlToTabIdMapping[tabId];
            GlobalPinnedTabs.globalPinnedTabUrls.remove(url);
            GlobalPinnedTabs.persistData();
        }
    },

    getMatchingTab: function(url, window) {
        return window.tabs.filter(function(x) {
            return x.pinned && x.url === url;
        })[0];
    },

    createTab: function(url, window) {
        var matchingTab = GlobalPinnedTabs.getMatchingTab(url, window);
        if (matchingTab !== undefined)
            GlobalPinnedTabs.createTabCallback(matchingTab);
        else {
            chrome.tabs.create({
                'url': url,
                'pinned': true,
                'active': false,
                'windowId': window.id
            }, GlobalPinnedTabs.createTabCallback);
        }
    },

    loadData: function() {
        chrome.storage.sync.get('globalPinnedTabUrls', function(items) {
            GlobalPinnedTabs.globalPinnedTabUrls = items.globalPinnedTabUrls;
        });
    },

    persistData: function() {
        chrome.storage.sync.set({
            globalPinnedTabUrls: GlobalPinnedTabs.globalPinnedTabUrls
        });
    }
};

GlobalPinnedTabs.init();
@@ -2291,36 +2291,50 @@
 y%5D;%0A            
-if (
+var matchingTab = 
 GlobalPinnedTabs
@@ -2361,16 +2361,45 @@
  window)
+;%0A            if (matchingTab
  === und
@@ -2464,16 +2464,312 @@
 , key);%0A
+            else %7B%0A                delete GlobalPinnedTabs.tabIdToUrlMapping%5Bkey%5D;%0A                GlobalPinnedTabs.tabIdToUrlMapping%5BmatchingTab.id%5D = url;%0A                GlobalPinnedTabs.urlToTabIdMapping%5Burl%5D = matchingTab.id;%0A                chrome.tabs.remove(parseInt(key));%0A            %7D%0A
         
@@ -4018,214 +4018,50 @@
     
-disableTabCloseHandling: false,%0A    disableTabUpdateHandling: false,%0A%0A    onTabClose: function(tabId, removeInfo) %7B%0A        if (!removeInfo.isWindowClosing && !GlobalPinnedTabs.disableTabCloseHandling)%0A    
+onTabClose: function(tabId, removeInfo) %7B%0A
     
@@ -4099,24 +4099,53 @@
 vedTab(tabId
+, !removeInfo.isWindowClosing
 );%0A    %7D,%0A%0A 
@@ -4175,24 +4175,35 @@
 nction(tabId
+, removeUrl
 ) %7B%0A        
@@ -4390,32 +4390,64 @@
 Mapping%5BtabId%5D;%0A
+            if(removeUrl) %7B%0A    
             Glob
@@ -4496,32 +4496,36 @@
 l);%0A            
+    
 GlobalPinnedTabs
@@ -4532,32 +4532,46 @@
 .persistData();%0A
+            %7D%0A
         %7D%0A    %7D,

Fix some issues with removed tabs