| OLD | NEW | 
|---|
| 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-2015 Eyeo GmbH | 3  * Copyright (C) 2006-2015 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 14 matching lines...) Expand all  Loading... | 
| 25  */ | 25  */ | 
| 26 var objTabs = | 26 var objTabs = | 
| 27 { | 27 { | 
| 28   /** | 28   /** | 
| 29    * Number of milliseconds to wait until hiding tab after the mouse moves away. | 29    * Number of milliseconds to wait until hiding tab after the mouse moves away. | 
| 30    * @type Integer | 30    * @type Integer | 
| 31    */ | 31    */ | 
| 32   HIDE_DELAY: 1000, | 32   HIDE_DELAY: 1000, | 
| 33 | 33 | 
| 34   /** | 34   /** | 
| 35    * Flag used to trigger object tabs initialization first time object tabs are |  | 
| 36    * used. |  | 
| 37    * @type Boolean |  | 
| 38    */ |  | 
| 39   initialized: false, |  | 
| 40 |  | 
| 41   /** |  | 
| 42    * Will be set to true while initialization is in progress. |  | 
| 43    * @type Boolean |  | 
| 44    */ |  | 
| 45   initializing: false, |  | 
| 46 |  | 
| 47   /** |  | 
| 48    * Parameters for _showTab, to be called once initialization is complete. |  | 
| 49    */ |  | 
| 50   delayedShowParams: null, |  | 
| 51 |  | 
| 52   /** |  | 
| 53    * Randomly generated class to be used for visible object tabs on top of objec
     t. |  | 
| 54    * @type String |  | 
| 55    */ |  | 
| 56   objTabClassVisibleTop: null, |  | 
| 57 |  | 
| 58   /** |  | 
| 59    * Randomly generated class to be used for visible object tabs at the bottom o
     f the object. |  | 
| 60    * @type String |  | 
| 61    */ |  | 
| 62   objTabClassVisibleBottom: null, |  | 
| 63 |  | 
| 64   /** |  | 
| 65    * Randomly generated class to be used for invisible object tabs. |  | 
| 66    * @type String |  | 
| 67    */ |  | 
| 68   objTabClassHidden: null, |  | 
| 69 |  | 
| 70   /** |  | 
| 71    * Document element the object tab is currently being displayed for. | 35    * Document element the object tab is currently being displayed for. | 
| 72    * @type Element | 36    * @type Element | 
| 73    */ | 37    */ | 
| 74   currentElement: null, | 38   currentElement: null, | 
| 75 | 39 | 
| 76   /** | 40   /** | 
| 77    * Windows that the window event handler is currently registered for. | 41    * Windows that the window event handler is currently registered for. | 
| 78    * @type Window[] | 42    * @type Window[] | 
| 79    */ | 43    */ | 
| 80   windowListeners: null, | 44   windowListeners: null, | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
| 103    */ | 67    */ | 
| 104   hideTimer: null, | 68   hideTimer: null, | 
| 105 | 69 | 
| 106   /** | 70   /** | 
| 107    * Used when hideTimer is running, time when the tab should be hidden. | 71    * Used when hideTimer is running, time when the tab should be hidden. | 
| 108    * @type Integer | 72    * @type Integer | 
| 109    */ | 73    */ | 
| 110   hideTargetTime: 0, | 74   hideTargetTime: 0, | 
| 111 | 75 | 
| 112   /** | 76   /** | 
| 113    * Initializes object tabs (generates random classes and registers stylesheet)
     . | 77    * Localized texts and class names to be used for the tab. | 
|  | 78    * @type Object | 
| 114    */ | 79    */ | 
| 115   _initCSS: function() | 80   texts: null, | 
| 116   { |  | 
| 117     function processCSSData(request) |  | 
| 118     { |  | 
| 119       if (onShutdown.done) |  | 
| 120         return; |  | 
| 121 |  | 
| 122       let data = request.responseText; |  | 
| 123 |  | 
| 124       let rnd = []; |  | 
| 125       let offset = "a".charCodeAt(0); |  | 
| 126       for (let i = 0; i < 60; i++) |  | 
| 127         rnd.push(offset + Math.random() * 26); |  | 
| 128 |  | 
| 129       this.objTabClassVisibleTop = String.fromCharCode.apply(String, rnd.slice(0
     , 20)); |  | 
| 130       this.objTabClassVisibleBottom = String.fromCharCode.apply(String, rnd.slic
     e(20, 40)); |  | 
| 131       this.objTabClassHidden = String.fromCharCode.apply(String, rnd.slice(40, 6
     0)); |  | 
| 132 |  | 
| 133       let {Utils} = require("utils"); |  | 
| 134       let url = Utils.makeURI("data:text/css," + encodeURIComponent(data.replace
     (/%%CLASSVISIBLETOP%%/g, this.objTabClassVisibleTop) |  | 
| 135                                                                         .replace
     (/%%CLASSVISIBLEBOTTOM%%/g, this.objTabClassVisibleBottom) |  | 
| 136                                                                         .replace
     (/%%CLASSHIDDEN%%/g, this.objTabClassHidden))); |  | 
| 137       Utils.styleService.loadAndRegisterSheet(url, Ci.nsIStyleSheetService.USER_
     SHEET); |  | 
| 138       onShutdown.add(function() |  | 
| 139       { |  | 
| 140         Utils.styleService.unregisterSheet(url, Ci.nsIStyleSheetService.USER_SHE
     ET); |  | 
| 141       }); |  | 
| 142 |  | 
| 143       this.initializing = false; |  | 
| 144       this.initialized = true; |  | 
| 145 |  | 
| 146       if (this.delayedShowParams) |  | 
| 147         this._showTab.apply(this, this.delayedShowParams); |  | 
| 148     } |  | 
| 149 |  | 
| 150     this.delayedShowParams = arguments; |  | 
| 151 |  | 
| 152     if (!this.initializing) |  | 
| 153     { |  | 
| 154       this.initializing = true; |  | 
| 155 |  | 
| 156       // Load CSS asynchronously |  | 
| 157       try { |  | 
| 158         let request = new XMLHttpRequest(); |  | 
| 159         request.mozBackgroundRequest = true; |  | 
| 160         request.open("GET", "chrome://adblockplus/content/objtabs.css"); |  | 
| 161         request.overrideMimeType("text/plain"); |  | 
| 162 |  | 
| 163         request.addEventListener("load", processCSSData.bind(this, request), fal
     se); |  | 
| 164         request.send(null); |  | 
| 165       } |  | 
| 166       catch (e) |  | 
| 167       { |  | 
| 168         Cu.reportError(e); |  | 
| 169         this.initializing = false; |  | 
| 170       } |  | 
| 171     } |  | 
| 172   }, |  | 
| 173 | 81 | 
| 174   /** | 82   /** | 
| 175    * Called to show object tab for an element. | 83    * Called to show object tab for an element. | 
| 176    */ | 84    */ | 
| 177   showTabFor: function(/**Element*/ element) | 85   showTabFor: function(/**Element*/ element) | 
| 178   { | 86   { | 
| 179     // Object tabs aren't usable in Fennec | 87     // Object tabs aren't usable in Fennec | 
| 180     let {application} = require("info"); | 88     let {application} = require("info"); | 
| 181     if (application == "fennec" || application == "fennec2" || | 89     if (application == "fennec" || application == "fennec2" || | 
| 182         application == "adblockbrowser") | 90         application == "adblockbrowser") | 
| 183       return; | 91       return; | 
| 184 | 92 | 
| 185     let {Prefs} = require("prefs"); | 93     if (!sendSyncMessage("AdblockPlus:GetObjectTabsStatus")) | 
| 186     if (!Prefs.frameobjects) |  | 
| 187       return; | 94       return; | 
| 188 | 95 | 
| 189     if (this.hideTimer) | 96     if (this.hideTimer) | 
| 190     { | 97     { | 
| 191       this.hideTimer.cancel(); | 98       this.hideTimer.cancel(); | 
| 192       this.hideTimer = null; | 99       this.hideTimer = null; | 
| 193     } | 100     } | 
| 194 | 101 | 
| 195     if (this.objtabElement) | 102     if (this.objtabElement) | 
| 196       this.objtabElement.style.setProperty("opacity", "1", "important"); | 103       this.objtabElement.style.setProperty("opacity", "1", "important"); | 
| 197 | 104 | 
| 198     if (this.currentElement != element) | 105     if (this.currentElement != element) | 
| 199     { | 106     { | 
| 200       this._hideTab(); | 107       this._hideTab(); | 
| 201 | 108 | 
| 202       let {Policy} = require("contentPolicy"); | 109       let {RequestNotifier} = require("child/requestNotifier"); | 
| 203       let {RequestNotifier} = require("requestNotifier"); |  | 
| 204       let data = RequestNotifier.getDataForNode(element, true, "OBJECT"); | 110       let data = RequestNotifier.getDataForNode(element, true, "OBJECT"); | 
| 205       if (data) | 111       if (data) | 
| 206       { | 112         this._showTab(element, data[1]); | 
| 207         if (this.initialized) |  | 
| 208           this._showTab(element, data[1]); |  | 
| 209         else |  | 
| 210           this._initCSS(element, data[1]); |  | 
| 211       } |  | 
| 212     } | 113     } | 
| 213   }, | 114   }, | 
| 214 | 115 | 
| 215   /** | 116   /** | 
| 216    * Called to hide object tab for an element (actual hiding happens delayed). | 117    * Called to hide object tab for an element (actual hiding happens delayed). | 
| 217    */ | 118    */ | 
| 218   hideTabFor: function(/**Element*/ element) | 119   hideTabFor: function(/**Element*/ element) | 
| 219   { | 120   { | 
| 220     if (element != this.currentElement || this.hideTimer) | 121     if (element != this.currentElement || this.hideTimer) | 
| 221       return; | 122       return; | 
| 222 | 123 | 
| 223     this.hideTargetTime = Date.now() + this.HIDE_DELAY; | 124     this.hideTargetTime = Date.now() + this.HIDE_DELAY; | 
| 224     this.hideTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); | 125     this.hideTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); | 
| 225     this.hideTimer.init(this, 40, Ci.nsITimer.TYPE_REPEATING_SLACK); | 126     this.hideTimer.init(this, 40, Ci.nsITimer.TYPE_REPEATING_SLACK); | 
| 226   }, | 127   }, | 
| 227 | 128 | 
| 228   /** | 129   /** | 
| 229    * Makes the tab element visible. | 130    * Makes the tab element visible. | 
| 230    * @param {Element} element | 131    * @param {Element} element | 
| 231    * @param {RequestEntry} data | 132    * @param {RequestEntry} data | 
| 232    */ | 133    */ | 
| 233   _showTab: function(element, data) | 134   _showTab: function(element, data) | 
| 234   { | 135   { | 
| 235     let {UI} = require("ui"); | 136     if (!this.texts) | 
| 236     if (!UI.overlay) | 137       this.texts = sendSyncMessage("AdblockPlus:GetObjectTabsTexts"); | 
| 237       return; |  | 
| 238 | 138 | 
| 239     let doc = element.ownerDocument.defaultView.top.document; | 139     let doc = element.ownerDocument.defaultView.top.document; | 
| 240 | 140 | 
| 241     this.objtabElement = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"
     ); | 141     this.objtabElement = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"
     ); | 
| 242     this.objtabElement.textContent = UI.overlay.attributes.objtabtext; | 142     this.objtabElement.textContent = this.texts.label; | 
| 243     this.objtabElement.setAttribute("title", UI.overlay.attributes.objtabtooltip
     ); | 143     this.objtabElement.setAttribute("title", this.texts.tooltip); | 
| 244     this.objtabElement.setAttribute("href", data.location); | 144     this.objtabElement.setAttribute("href", data.location); | 
| 245     this.objtabElement.setAttribute("class", this.objTabClassHidden); | 145     this.objtabElement.setAttribute("class", this.texts.classHidden); | 
| 246     this.objtabElement.style.setProperty("opacity", "1", "important"); | 146     this.objtabElement.style.setProperty("opacity", "1", "important"); | 
| 247     this.objtabElement.nodeData = data; | 147     this.objtabElement.nodeData = data; | 
| 248 | 148 | 
| 249     this.currentElement = element; | 149     this.currentElement = element; | 
| 250 | 150 | 
| 251     // Register paint listeners for the relevant windows | 151     // Register paint listeners for the relevant windows | 
| 252     this.windowListeners = []; | 152     this.windowListeners = []; | 
| 253     let wnd = element.ownerDocument.defaultView; | 153     let wnd = element.ownerDocument.defaultView; | 
| 254     while (wnd) | 154     while (wnd) | 
| 255     { | 155     { | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 271       this.positionTimer.init(this, 200, Ci.nsITimer.TYPE_REPEATING_SLACK); | 171       this.positionTimer.init(this, 200, Ci.nsITimer.TYPE_REPEATING_SLACK); | 
| 272     } | 172     } | 
| 273     this._positionTab(); | 173     this._positionTab(); | 
| 274   }, | 174   }, | 
| 275 | 175 | 
| 276   /** | 176   /** | 
| 277    * Hides the tab element. | 177    * Hides the tab element. | 
| 278    */ | 178    */ | 
| 279   _hideTab: function() | 179   _hideTab: function() | 
| 280   { | 180   { | 
| 281     this.delayedShowParams = null; |  | 
| 282 |  | 
| 283     if (this.objtabElement) | 181     if (this.objtabElement) | 
| 284     { | 182     { | 
| 285       // Prevent recursive calls via popuphidden handler | 183       // Prevent recursive calls via popuphidden handler | 
| 286       let objtab = this.objtabElement; | 184       let objtab = this.objtabElement; | 
| 287       this.objtabElement = null; | 185       this.objtabElement = null; | 
| 288       this.currentElement = null; | 186       this.currentElement = null; | 
| 289 | 187 | 
| 290       if (this.hideTimer) | 188       if (this.hideTimer) | 
| 291       { | 189       { | 
| 292         this.hideTimer.cancel(); | 190         this.hideTimer.cancel(); | 
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 325     } catch (e) {}  // Ignore "can't access dead object" error | 223     } catch (e) {}  // Ignore "can't access dead object" error | 
| 326     if (!elementDoc || !this.currentElement.offsetWidth || !this.currentElement.
     offsetHeight || | 224     if (!elementDoc || !this.currentElement.offsetWidth || !this.currentElement.
     offsetHeight || | 
| 327         !elementDoc.defaultView || !elementDoc.documentElement) | 225         !elementDoc.defaultView || !elementDoc.documentElement) | 
| 328     { | 226     { | 
| 329       this._hideTab(); | 227       this._hideTab(); | 
| 330       return; | 228       return; | 
| 331     } | 229     } | 
| 332 | 230 | 
| 333     let objRect = this._getElementPosition(this.currentElement); | 231     let objRect = this._getElementPosition(this.currentElement); | 
| 334 | 232 | 
| 335     let className = this.objTabClassVisibleTop; | 233     let className = this.texts.classVisibleTop; | 
| 336     let left = objRect.right - this.objtabElement.offsetWidth; | 234     let left = objRect.right - this.objtabElement.offsetWidth; | 
| 337     let top = objRect.top - this.objtabElement.offsetHeight; | 235     let top = objRect.top - this.objtabElement.offsetHeight; | 
| 338     if (top < 0) | 236     if (top < 0) | 
| 339     { | 237     { | 
| 340       top = objRect.bottom; | 238       top = objRect.bottom; | 
| 341       className = this.objTabClassVisibleBottom; | 239       className = this.texts.classVisibleBottom; | 
| 342     } | 240     } | 
| 343 | 241 | 
| 344     if (this.objtabElement.style.left != left + "px") | 242     if (this.objtabElement.style.left != left + "px") | 
| 345       this.objtabElement.style.setProperty("left", left + "px", "important"); | 243       this.objtabElement.style.setProperty("left", left + "px", "important"); | 
| 346     if (this.objtabElement.style.top != top + "px") | 244     if (this.objtabElement.style.top != top + "px") | 
| 347       this.objtabElement.style.setProperty("top", top + "px", "important"); | 245       this.objtabElement.style.setProperty("top", top + "px", "important"); | 
| 348 | 246 | 
| 349     if (this.objtabElement.getAttribute("class") != className) | 247     if (this.objtabElement.getAttribute("class") != className) | 
| 350       this.objtabElement.setAttribute("class", className); | 248       this.objtabElement.setAttribute("class", className); | 
| 351 | 249 | 
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 408       rect.right += relLeft; | 306       rect.right += relLeft; | 
| 409       rect.top += relTop; | 307       rect.top += relTop; | 
| 410       rect.bottom += relTop; | 308       rect.bottom += relTop; | 
| 411     } | 309     } | 
| 412 | 310 | 
| 413     return rect; | 311     return rect; | 
| 414   }, | 312   }, | 
| 415 | 313 | 
| 416   doBlock: function() | 314   doBlock: function() | 
| 417   { | 315   { | 
| 418     let {UI} = require("ui"); | 316     // TODO: Store this.currentElement for the filter assistant | 
| 419     let {Utils} = require("utils"); | 317     sendAsyncMessage("AdblockPlus:BlockItem", this.objtabElement.nodeData); | 
| 420     let chromeWindow = Utils.getChromeWindow(this.currentElement.ownerDocument.d
     efaultView); |  | 
| 421     UI.blockItem(chromeWindow, this.currentElement, this.objtabElement.nodeData)
     ; |  | 
| 422   }, | 318   }, | 
| 423 | 319 | 
| 424   /** | 320   /** | 
| 425    * Called whenever a timer fires. | 321    * Called whenever a timer fires. | 
| 426    * @param {nsISupport} subject | 322    * @param {nsISupport} subject | 
| 427    * @param {string} topic | 323    * @param {string} topic | 
| 428    * @param {string} data | 324    * @param {string} data | 
| 429    */ | 325    */ | 
| 430   observe: function(subject, topic, data) | 326   observe: function(subject, topic, data) | 
| 431   { | 327   { | 
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 489     event.stopPropagation(); | 385     event.stopPropagation(); | 
| 490 | 386 | 
| 491     objTabs.doBlock(); | 387     objTabs.doBlock(); | 
| 492   } | 388   } | 
| 493   else if (event.type == "mouseover") | 389   else if (event.type == "mouseover") | 
| 494     objTabs.showTabFor(objTabs.currentElement); | 390     objTabs.showTabFor(objTabs.currentElement); | 
| 495   else if (event.type == "mouseout") | 391   else if (event.type == "mouseout") | 
| 496     objTabs.hideTabFor(objTabs.currentElement); | 392     objTabs.hideTabFor(objTabs.currentElement); | 
| 497 } | 393 } | 
| 498 exports.objectMouseEventHander = objectMouseEventHander; | 394 exports.objectMouseEventHander = objectMouseEventHander; | 
| OLD | NEW | 
|---|