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

Side by Side Diff: lib/child/objectTabs.js

Issue 29329839: Issue 3228 - Unbreak object tabs (Closed)
Patch Set: Created Nov. 6, 2015, 7:45 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
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-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
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
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
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
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
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
Wladimir Palant 2015/11/06 19:52:43 Making filter assistant work with nodes correctly
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
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;
OLDNEW

Powered by Google App Engine
This is Rietveld