| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 /* | 
|  | 2  * This file is part of Adblock Plus <http://adblockplus.org/>, | 
|  | 3  * Copyright (C) 2006-2013 Eyeo GmbH | 
|  | 4  * | 
|  | 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 | 
|  | 7  * published by the Free Software Foundation. | 
|  | 8  * | 
|  | 9  * Adblock Plus is distributed in the hope that it will be useful, | 
|  | 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 12  * GNU General Public License for more details. | 
|  | 13  * | 
|  | 14  * You should have received a copy of the GNU General Public License | 
|  | 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
|  | 16  */ | 
|  | 17 | 
|  | 18 (function() | 
|  | 19 { | 
|  | 20   /* Events */ | 
|  | 21 | 
|  | 22   var TabEventTarget = function() | 
|  | 23   { | 
|  | 24     WrappedEventTarget.apply(this, arguments); | 
|  | 25 | 
|  | 26     this._tabs = {}; | 
|  | 27 | 
|  | 28     this._sharedListener = this._sharedListener.bind(this); | 
|  | 29     this._removeTab = this._removeTab.bind(this); | 
|  | 30   }; | 
|  | 31   TabEventTarget.prototype = { | 
|  | 32     __proto__: WrappedEventTarget.prototype, | 
|  | 33     _bindToTab: function(tab) | 
|  | 34     { | 
|  | 35       return { | 
|  | 36         addListener: function(listener) | 
|  | 37         { | 
|  | 38           var listeners = this._tabs[tab._id]; | 
|  | 39 | 
|  | 40           if (!listeners) | 
|  | 41           { | 
|  | 42             this._tabs[tab._id] = listeners = []; | 
|  | 43 | 
|  | 44             if (Object.keys(this._tabs).length == 1) | 
|  | 45               this.addListener(this._sharedListener); | 
|  | 46 | 
|  | 47             tab.onRemoved.addListener(this._removeTab); | 
|  | 48           } | 
|  | 49 | 
|  | 50           listeners.push(listener); | 
|  | 51         }.bind(this), | 
|  | 52         removeListener: function(listener) | 
|  | 53         { | 
|  | 54           var listeners = this._tabs[tab._id]; | 
|  | 55           if (!listeners) | 
|  | 56             return; | 
|  | 57 | 
|  | 58           var idx = listeners.indexOf(listener); | 
|  | 59           if (idx == -1) | 
|  | 60             return; | 
|  | 61 | 
|  | 62           listeners.splice(idx, 1); | 
|  | 63 | 
|  | 64           if (listeners.length == 0) | 
|  | 65             tab.onRemoved.removeListener(this._removeTab); | 
|  | 66           else | 
|  | 67           { | 
|  | 68             if (listeners.length > 1) | 
|  | 69               return; | 
|  | 70             if (listeners[0] != this._removeTab) | 
|  | 71               return; | 
|  | 72           } | 
|  | 73 | 
|  | 74           this._removeTab(tab); | 
|  | 75         }.bind(this) | 
|  | 76       }; | 
|  | 77     }, | 
|  | 78     _sharedListener: function(tab) | 
|  | 79     { | 
|  | 80       var listeners = this._tabs[tab._id]; | 
|  | 81 | 
|  | 82       if (!listeners) | 
|  | 83         return; | 
|  | 84 | 
|  | 85       // copy listeners before calling them, because they might | 
|  | 86       // add or remove other listeners, which must not be taken | 
|  | 87       // into account before the next occurrence of the event | 
|  | 88       listeners = listeners.slice(0); | 
|  | 89 | 
|  | 90       for (var i = 0; i < listeners.length; i++) | 
|  | 91         listeners[i](tab); | 
|  | 92     }, | 
|  | 93     _removeTab: function(tab) | 
|  | 94     { | 
|  | 95       delete this._tabs[tab._id]; | 
|  | 96 | 
|  | 97       if (Object.keys(this._tabs).length == 0) | 
|  | 98         this.removeListener(this._sharedListener); | 
|  | 99     } | 
|  | 100   }; | 
|  | 101 | 
|  | 102   var BeforeNavigateTabEventTarget = function() | 
|  | 103   { | 
|  | 104     TabEventTarget.call(this, chrome.tabs.onUpdated); | 
|  | 105   }; | 
|  | 106   BeforeNavigateTabEventTarget.prototype = { | 
|  | 107     __proto__: TabEventTarget.prototype, | 
|  | 108     _wrapListener: function(listener) | 
|  | 109     { | 
|  | 110       return function(id, info, tab) | 
|  | 111       { | 
|  | 112         if ("url" in info) | 
|  | 113           listener(new Tab(tab)); | 
|  | 114       }; | 
|  | 115     } | 
|  | 116   }; | 
|  | 117 | 
|  | 118   var CompletedTabEventTarget = function() | 
|  | 119   { | 
|  | 120     TabEventTarget.call(this, chrome.tabs.onUpdated); | 
|  | 121   }; | 
|  | 122   CompletedTabEventTarget.prototype = { | 
|  | 123     __proto__: TabEventTarget.prototype, | 
|  | 124     _wrapListener: function(listener) | 
|  | 125     { | 
|  | 126       return function(id, info, tab) | 
|  | 127       { | 
|  | 128         if (info.status == "complete") | 
|  | 129           listener(new Tab(tab)); | 
|  | 130       }; | 
|  | 131     } | 
|  | 132   }; | 
|  | 133 | 
|  | 134   var ActivatedTabEventTarget = function() | 
|  | 135   { | 
|  | 136     TabEventTarget.call(this, chrome.tabs.onActivated); | 
|  | 137   }; | 
|  | 138   ActivatedTabEventTarget.prototype = { | 
|  | 139     __proto__: TabEventTarget.prototype, | 
|  | 140     _wrapListener: function(listener) | 
|  | 141     { | 
|  | 142       return function(info) | 
|  | 143       { | 
|  | 144         chrome.tabs.get(info.tabId, function(tab) | 
|  | 145         { | 
|  | 146           listener(new Tab(tab)); | 
|  | 147         }); | 
|  | 148       }; | 
|  | 149     } | 
|  | 150   } | 
|  | 151 | 
|  | 152   var RemovedTabEventTarget = function() | 
|  | 153   { | 
|  | 154     TabEventTarget.call(this, chrome.tabs.onRemoved); | 
|  | 155   }; | 
|  | 156   RemovedTabEventTarget.prototype = { | 
|  | 157     __proto__: TabEventTarget.prototype, | 
|  | 158     _wrapListener: function(listener) | 
|  | 159     { | 
|  | 160       return function(id) { listener(new Tab({id: id})); }; | 
|  | 161     } | 
|  | 162   }; | 
|  | 163 | 
|  | 164   var BeforeRequestEventTarget = function() | 
|  | 165   { | 
|  | 166     WrappedEventTarget.call(this, chrome.webRequest.onBeforeRequest); | 
|  | 167   }; | 
|  | 168   BeforeRequestEventTarget.prototype = { | 
|  | 169     __proto__: WrappedEventTarget.prototype, | 
|  | 170     _wrapListener: function(listener) | 
|  | 171     { | 
|  | 172       return function(details) | 
|  | 173       { | 
|  | 174         var tab = null; | 
|  | 175 | 
|  | 176         if (details.tabId != -1) | 
|  | 177           tab = new Tab({id: details.tabId}); | 
|  | 178 | 
|  | 179         return {cancel: listener( | 
|  | 180           details.url, | 
|  | 181           details.type, | 
|  | 182           tab, | 
|  | 183           details.frameId, | 
|  | 184           details.parentFrameId | 
|  | 185         ) === false}; | 
|  | 186       }; | 
|  | 187     }, | 
|  | 188     _prepareExtraArguments: function(urls) | 
|  | 189     { | 
|  | 190       return [urls ? {urls: urls} : {}, ["blocking"]]; | 
|  | 191     } | 
|  | 192   }; | 
|  | 193 | 
|  | 194 | 
|  | 195   /* Tabs */ | 
|  | 196 | 
|  | 197   var PageAction = function(tabId) | 
|  | 198   { | 
|  | 199     this._tabId = tabId; | 
|  | 200   }; | 
|  | 201   PageAction.prototype = { | 
|  | 202     setIcon: function(path) | 
|  | 203     { | 
|  | 204       chrome.pageAction.setIcon({tabId: this._tabId, path: path}); | 
|  | 205     }, | 
|  | 206     setTitle: function(title) | 
|  | 207     { | 
|  | 208       chrome.pageAction.setTitle({tabId: this._tabId, title: title}); | 
|  | 209     }, | 
|  | 210     hide: function() | 
|  | 211     { | 
|  | 212       chrome.pageAction.hide(this._tabId); | 
|  | 213     }, | 
|  | 214     show: function() | 
|  | 215     { | 
|  | 216       chrome.pageAction.show(this._tabId); | 
|  | 217     } | 
|  | 218   }; | 
|  | 219 | 
|  | 220   Tab = function(tab) | 
|  | 221   { | 
|  | 222     this._id = tab.id; | 
|  | 223 | 
|  | 224     this.url = tab.url; | 
|  | 225     this.pageAction = new PageAction(tab.id); | 
|  | 226 | 
|  | 227     this.onBeforeNavigate = ext.tabs.onBeforeNavigate._bindToTab(this); | 
|  | 228     this.onCompleted = ext.tabs.onCompleted._bindToTab(this); | 
|  | 229     this.onActivated = ext.tabs.onActivated._bindToTab(this); | 
|  | 230     this.onRemoved = ext.tabs.onRemoved._bindToTab(this); | 
|  | 231   }; | 
|  | 232   Tab.prototype = { | 
|  | 233     close: function() | 
|  | 234     { | 
|  | 235       chrome.tabs.remove(this._id); | 
|  | 236     }, | 
|  | 237     activate: function() | 
|  | 238     { | 
|  | 239       chrome.tabs.update(this._id, {selected: true}); | 
|  | 240     }, | 
|  | 241     sendMessage: function(message, responseCallback) | 
|  | 242     { | 
|  | 243       chrome.tabs.sendMessage(this._id, message, responseCallback); | 
|  | 244     } | 
|  | 245   }; | 
|  | 246 | 
|  | 247   TabMap = function() | 
|  | 248   { | 
|  | 249     this._map = {}; | 
|  | 250     this.delete = this.delete.bind(this); | 
|  | 251   }; | 
|  | 252   TabMap.prototype = { | 
|  | 253     get: function(tab) | 
|  | 254     { | 
|  | 255       return (this._map[tab._id] || {}).value; | 
|  | 256     }, | 
|  | 257     set: function(tab, value) | 
|  | 258     { | 
|  | 259       if (!(tab._id in this._map)) | 
|  | 260         tab.onRemoved.addListener(this.delete); | 
|  | 261 | 
|  | 262       this._map[tab._id] = {tab: tab, value: value}; | 
|  | 263     }, | 
|  | 264     has: function(tab) | 
|  | 265     { | 
|  | 266       return tab._id in this._map; | 
|  | 267     }, | 
|  | 268     clear: function() | 
|  | 269     { | 
|  | 270       for (var id in this._map) | 
|  | 271         this.delete(this._map[id].tab); | 
|  | 272     } | 
|  | 273   }; | 
|  | 274   TabMap.prototype["delete"] = function(tab) | 
|  | 275   { | 
|  | 276     delete this._map[tab._id]; | 
|  | 277     tab.onRemoved.removeListener(this.delete); | 
|  | 278   }; | 
|  | 279 | 
|  | 280 | 
|  | 281   /* Windows */ | 
|  | 282 | 
|  | 283   Window = function(win) | 
|  | 284   { | 
|  | 285     this._id = win.id; | 
|  | 286     this.visible = win.status != "minimized"; | 
|  | 287   }; | 
|  | 288   Window.prototype = { | 
|  | 289     getAllTabs: function(callback) | 
|  | 290     { | 
|  | 291       chrome.tabs.query({windowId: this._id}, function(tabs) | 
|  | 292       { | 
|  | 293         callback(tabs.map(function(tab) { return new Tab(tab); })); | 
|  | 294       }); | 
|  | 295     }, | 
|  | 296     getActiveTab: function(callback) | 
|  | 297     { | 
|  | 298       chrome.tabs.query({windowId: this._id, active: true}, function(tabs) | 
|  | 299       { | 
|  | 300         callback(new Tab(tabs[0])); | 
|  | 301       }); | 
|  | 302     }, | 
|  | 303     openTab: function(url, callback) | 
|  | 304     { | 
|  | 305       var props = {windowId: this._id, url: url}; | 
|  | 306 | 
|  | 307       if (!callback) | 
|  | 308         chrome.tabs.create(props); | 
|  | 309       else | 
|  | 310         chrome.tabs.create(props, function(tab) | 
|  | 311         { | 
|  | 312           callback(new Tab(tab)); | 
|  | 313         }); | 
|  | 314     } | 
|  | 315   }; | 
|  | 316 | 
|  | 317 | 
|  | 318   /* API */ | 
|  | 319 | 
|  | 320   ext.windows = { | 
|  | 321     getAll: function(callback) | 
|  | 322     { | 
|  | 323       chrome.windows.getAll(function(windows) | 
|  | 324       { | 
|  | 325         callback(windows.map(function(win) | 
|  | 326         { | 
|  | 327           return new Window(win); | 
|  | 328         })); | 
|  | 329       }); | 
|  | 330     }, | 
|  | 331     getLastFocused: function(callback) | 
|  | 332     { | 
|  | 333       chrome.windows.getLastFocused(function(win) | 
|  | 334       { | 
|  | 335         callback(new Window(win)); | 
|  | 336       }); | 
|  | 337     } | 
|  | 338   }; | 
|  | 339 | 
|  | 340   ext.tabs = { | 
|  | 341     onBeforeNavigate: new BeforeNavigateTabEventTarget(), | 
|  | 342     onCompleted: new CompletedTabEventTarget(), | 
|  | 343     onActivated: new ActivatedTabEventTarget(), | 
|  | 344     onRemoved: new RemovedTabEventTarget() | 
|  | 345   }; | 
|  | 346 | 
|  | 347   ext.webRequest = { | 
|  | 348     onBeforeRequest: new BeforeRequestEventTarget(), | 
|  | 349     handlerBehaviorChanged: chrome.webRequest.handlerBehaviorChanged | 
|  | 350   }; | 
|  | 351 })(); | 
| OLD | NEW | 
|---|