OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * This Source Code is subject to the terms of the Mozilla Public License |
| 3 * version 2.0 (the "License"). You can obtain a copy of the License at |
| 4 * http://mozilla.org/MPL/2.0/. |
| 5 */ |
| 6 |
| 7 // |
| 8 // This file has been generated automatically from Adblock Plus for Firefox |
| 9 // source code. DO NOT MODIFY, change the original source code instead. |
| 10 // |
| 11 // Relevant repositories: |
| 12 // * https://hg.adblockplus.org/adblockplus/ |
| 13 // * https://hg.adblockplus.org/jshydra/ |
| 14 // |
| 15 |
| 16 require.scopes["filterNotifier"] = (function() |
| 17 { |
| 18 var exports = {}; |
| 19 var listeners = []; |
| 20 var FilterNotifier = exports.FilterNotifier = |
| 21 { |
| 22 addListener: function(listener) |
| 23 { |
| 24 if (listeners.indexOf(listener) >= 0) |
| 25 { |
| 26 return; |
| 27 } |
| 28 listeners.push(listener); |
| 29 }, |
| 30 removeListener: function(listener) |
| 31 { |
| 32 var index = listeners.indexOf(listener); |
| 33 if (index >= 0) |
| 34 { |
| 35 listeners.splice(index, 1); |
| 36 } |
| 37 }, |
| 38 triggerListeners: function(action, item, param1, param2, param3) |
| 39 { |
| 40 for (var _loopIndex0 = 0; _loopIndex0 < listeners.length; ++_loopIndex0) |
| 41 { |
| 42 var listener = listeners[_loopIndex0]; |
| 43 listener(action, item, param1, param2, param3); |
| 44 } |
| 45 } |
| 46 }; |
| 47 return exports; |
| 48 })(); |
| 49 require.scopes["filterClasses"] = (function() |
| 50 { |
| 51 var exports = {}; |
| 52 var FilterNotifier = require("filterNotifier").FilterNotifier; |
| 53 |
| 54 function Filter(text) |
| 55 { |
| 56 this.text = text; |
| 57 this.subscriptions = []; |
| 58 } |
| 59 exports.Filter = Filter; |
| 60 Filter.prototype = |
| 61 { |
| 62 text: null, |
| 63 subscriptions: null, |
| 64 serialize: function(buffer) |
| 65 { |
| 66 buffer.push("[Filter]"); |
| 67 buffer.push("text=" + this.text); |
| 68 }, |
| 69 toString: function() |
| 70 { |
| 71 return this.text; |
| 72 } |
| 73 }; |
| 74 Filter.knownFilters = |
| 75 { |
| 76 __proto__: null |
| 77 }; |
| 78 Filter.elemhideRegExp = /^([^\/\*\|\@"!]*?)#(\@)?(?:([\w\-]+|\*)((?:\([\w\-]+(
?:[$^*]?=[^\(\)"]*)?\))*)|#([^{}]+))$/; |
| 79 Filter.regexpRegExp = /^(@@)?\/.*\/(?:\$~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:
=[^,\s]+)?)*)?$/; |
| 80 Filter.optionsRegExp = /\$(~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[^,\s]+)?)*)
$/; |
| 81 Filter.fromText = function(text) |
| 82 { |
| 83 if (text in Filter.knownFilters) |
| 84 { |
| 85 return Filter.knownFilters[text]; |
| 86 } |
| 87 var ret; |
| 88 var match = text.indexOf("#") >= 0 ? Filter.elemhideRegExp.exec(text) : null
; |
| 89 if (match) |
| 90 { |
| 91 ret = ElemHideBase.fromText(text, match[1], match[2], match[3], match[4],
match[5]); |
| 92 } |
| 93 else if (text[0] == "!") |
| 94 { |
| 95 ret = new CommentFilter(text); |
| 96 } |
| 97 else |
| 98 { |
| 99 ret = RegExpFilter.fromText(text); |
| 100 } |
| 101 Filter.knownFilters[ret.text] = ret; |
| 102 return ret; |
| 103 }; |
| 104 Filter.fromObject = function(obj) |
| 105 { |
| 106 var ret = Filter.fromText(obj.text); |
| 107 if (ret instanceof ActiveFilter) |
| 108 { |
| 109 if ("disabled" in obj) |
| 110 { |
| 111 ret._disabled = obj.disabled == "true"; |
| 112 } |
| 113 if ("hitCount" in obj) |
| 114 { |
| 115 ret._hitCount = parseInt(obj.hitCount) || 0; |
| 116 } |
| 117 if ("lastHit" in obj) |
| 118 { |
| 119 ret._lastHit = parseInt(obj.lastHit) || 0; |
| 120 } |
| 121 } |
| 122 return ret; |
| 123 }; |
| 124 Filter.normalize = function(text) |
| 125 { |
| 126 if (!text) |
| 127 { |
| 128 return text; |
| 129 } |
| 130 text = text.replace(/[^\S ]/g, ""); |
| 131 if (/^\s*!/.test(text)) |
| 132 { |
| 133 return text.replace(/^\s+/, "").replace(/\s+$/, ""); |
| 134 } |
| 135 else if (Filter.elemhideRegExp.test(text)) |
| 136 { |
| 137 var _tempVar1 = /^(.*?)(#\@?#?)(.*)$/.exec(text); |
| 138 var domain = _tempVar1[1]; |
| 139 var separator = _tempVar1[2]; |
| 140 var selector = _tempVar1[3]; |
| 141 return domain.replace(/\s/g, "") + separator + selector.replace(/^\s+/, ""
).replace(/\s+$/, ""); |
| 142 } |
| 143 else |
| 144 { |
| 145 return text.replace(/\s/g, ""); |
| 146 } |
| 147 }; |
| 148 |
| 149 function InvalidFilter(text, reason) |
| 150 { |
| 151 Filter.call(this, text); |
| 152 this.reason = reason; |
| 153 } |
| 154 exports.InvalidFilter = InvalidFilter; |
| 155 InvalidFilter.prototype = |
| 156 { |
| 157 __proto__: Filter.prototype, |
| 158 reason: null, |
| 159 serialize: function(buffer){} |
| 160 }; |
| 161 |
| 162 function CommentFilter(text) |
| 163 { |
| 164 Filter.call(this, text); |
| 165 } |
| 166 exports.CommentFilter = CommentFilter; |
| 167 CommentFilter.prototype = |
| 168 { |
| 169 __proto__: Filter.prototype, |
| 170 serialize: function(buffer){} |
| 171 }; |
| 172 |
| 173 function ActiveFilter(text, domains) |
| 174 { |
| 175 Filter.call(this, text); |
| 176 this.domainSource = domains; |
| 177 } |
| 178 exports.ActiveFilter = ActiveFilter; |
| 179 ActiveFilter.prototype = |
| 180 { |
| 181 __proto__: Filter.prototype, |
| 182 _disabled: false, |
| 183 _hitCount: 0, |
| 184 _lastHit: 0, |
| 185 get disabled() |
| 186 { |
| 187 return this._disabled; |
| 188 }, |
| 189 set disabled(value) |
| 190 { |
| 191 if (value != this._disabled) |
| 192 { |
| 193 var oldValue = this._disabled; |
| 194 this._disabled = value; |
| 195 FilterNotifier.triggerListeners("filter.disabled", this, value, oldValue
); |
| 196 } |
| 197 return this._disabled; |
| 198 }, |
| 199 get hitCount() |
| 200 { |
| 201 return this._hitCount; |
| 202 }, |
| 203 set hitCount(value) |
| 204 { |
| 205 if (value != this._hitCount) |
| 206 { |
| 207 var oldValue = this._hitCount; |
| 208 this._hitCount = value; |
| 209 FilterNotifier.triggerListeners("filter.hitCount", this, value, oldValue
); |
| 210 } |
| 211 return this._hitCount; |
| 212 }, |
| 213 get lastHit() |
| 214 { |
| 215 return this._lastHit; |
| 216 }, |
| 217 set lastHit(value) |
| 218 { |
| 219 if (value != this._lastHit) |
| 220 { |
| 221 var oldValue = this._lastHit; |
| 222 this._lastHit = value; |
| 223 FilterNotifier.triggerListeners("filter.lastHit", this, value, oldValue)
; |
| 224 } |
| 225 return this._lastHit; |
| 226 }, |
| 227 domainSource: null, |
| 228 domainSeparator: null, |
| 229 ignoreTrailingDot: true, |
| 230 get domains() |
| 231 { |
| 232 var domains = null; |
| 233 if (this.domainSource) |
| 234 { |
| 235 var list = this.domainSource.split(this.domainSeparator); |
| 236 if (list.length == 1 && list[0][0] != "~") |
| 237 { |
| 238 domains = |
| 239 { |
| 240 __proto__: null, |
| 241 "": false |
| 242 }; |
| 243 if (this.ignoreTrailingDot) |
| 244 { |
| 245 list[0] = list[0].replace(/\.+$/, ""); |
| 246 } |
| 247 domains[list[0]] = true; |
| 248 } |
| 249 else |
| 250 { |
| 251 var hasIncludes = false; |
| 252 for (var i = 0; i < list.length; i++) |
| 253 { |
| 254 var domain = list[i]; |
| 255 if (this.ignoreTrailingDot) |
| 256 { |
| 257 domain = domain.replace(/\.+$/, ""); |
| 258 } |
| 259 if (domain == "") |
| 260 { |
| 261 continue; |
| 262 } |
| 263 var include; |
| 264 if (domain[0] == "~") |
| 265 { |
| 266 include = false; |
| 267 domain = domain.substr(1); |
| 268 } |
| 269 else |
| 270 { |
| 271 include = true; |
| 272 hasIncludes = true; |
| 273 } |
| 274 if (!domains) |
| 275 { |
| 276 domains = |
| 277 { |
| 278 __proto__: null |
| 279 }; |
| 280 } |
| 281 domains[domain] = include; |
| 282 } |
| 283 domains[""] = !hasIncludes; |
| 284 } |
| 285 delete this.domainSource; |
| 286 } |
| 287 this.__defineGetter__("domains", function() |
| 288 { |
| 289 return domains; |
| 290 }); |
| 291 return this.domains; |
| 292 }, |
| 293 isActiveOnDomain: function(docDomain) |
| 294 { |
| 295 if (!this.domains) |
| 296 { |
| 297 return true; |
| 298 } |
| 299 if (!docDomain) |
| 300 { |
| 301 return this.domains[""]; |
| 302 } |
| 303 if (this.ignoreTrailingDot) |
| 304 { |
| 305 docDomain = docDomain.replace(/\.+$/, ""); |
| 306 } |
| 307 docDomain = docDomain.toUpperCase(); |
| 308 while (true) |
| 309 { |
| 310 if (docDomain in this.domains) |
| 311 { |
| 312 return this.domains[docDomain]; |
| 313 } |
| 314 var nextDot = docDomain.indexOf("."); |
| 315 if (nextDot < 0) |
| 316 { |
| 317 break; |
| 318 } |
| 319 docDomain = docDomain.substr(nextDot + 1); |
| 320 } |
| 321 return this.domains[""]; |
| 322 }, |
| 323 isActiveOnlyOnDomain: function(docDomain) |
| 324 { |
| 325 if (!docDomain || !this.domains || this.domains[""]) |
| 326 { |
| 327 return false; |
| 328 } |
| 329 if (this.ignoreTrailingDot) |
| 330 { |
| 331 docDomain = docDomain.replace(/\.+$/, ""); |
| 332 } |
| 333 docDomain = docDomain.toUpperCase(); |
| 334 for (var domain in this.domains) |
| 335 { |
| 336 if (this.domains[domain] && domain != docDomain && (domain.length <= doc
Domain.length || domain.indexOf("." + docDomain) != domain.length - docDomain.le
ngth - 1)) |
| 337 { |
| 338 return false; |
| 339 } |
| 340 } |
| 341 return true; |
| 342 }, |
| 343 serialize: function(buffer) |
| 344 { |
| 345 if (this._disabled || this._hitCount || this._lastHit) |
| 346 { |
| 347 Filter.prototype.serialize.call(this, buffer); |
| 348 if (this._disabled) |
| 349 { |
| 350 buffer.push("disabled=true"); |
| 351 } |
| 352 if (this._hitCount) |
| 353 { |
| 354 buffer.push("hitCount=" + this._hitCount); |
| 355 } |
| 356 if (this._lastHit) |
| 357 { |
| 358 buffer.push("lastHit=" + this._lastHit); |
| 359 } |
| 360 } |
| 361 } |
| 362 }; |
| 363 |
| 364 function RegExpFilter(text, regexpSource, contentType, matchCase, domains, thi
rdParty) |
| 365 { |
| 366 ActiveFilter.call(this, text, domains); |
| 367 if (contentType != null) |
| 368 { |
| 369 this.contentType = contentType; |
| 370 } |
| 371 if (matchCase) |
| 372 { |
| 373 this.matchCase = matchCase; |
| 374 } |
| 375 if (thirdParty != null) |
| 376 { |
| 377 this.thirdParty = thirdParty; |
| 378 } |
| 379 if (regexpSource.length >= 2 && regexpSource[0] == "/" && regexpSource[regex
pSource.length - 1] == "/") |
| 380 { |
| 381 var regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2), t
his.matchCase ? "" : "i"); |
| 382 this.__defineGetter__("regexp", function() |
| 383 { |
| 384 return regexp; |
| 385 }); |
| 386 } |
| 387 else |
| 388 { |
| 389 this.regexpSource = regexpSource; |
| 390 } |
| 391 } |
| 392 exports.RegExpFilter = RegExpFilter; |
| 393 RegExpFilter.prototype = |
| 394 { |
| 395 __proto__: ActiveFilter.prototype, |
| 396 length: 1, |
| 397 domainSeparator: "|", |
| 398 regexpSource: null, |
| 399 get regexp() |
| 400 { |
| 401 var source = this.regexpSource.replace(/\*+/g, "*"); |
| 402 if (source[0] == "*") |
| 403 { |
| 404 source = source.substr(1); |
| 405 } |
| 406 var pos = source.length - 1; |
| 407 if (pos >= 0 && source[pos] == "*") |
| 408 { |
| 409 source = source.substr(0, pos); |
| 410 } |
| 411 source = source.replace(/\^\|$/, "^").replace(/\W/g, "\\$&").replace(/\\\*
/g, ".*").replace(/\\\^/g, "(?:[\\x00-\\x24\\x26-\\x2C\\x2F\\x3A-\\x40\\x5B-\\x5
E\\x60\\x7B-\\x80]|$)").replace(/^\\\|\\\|/, "^[\\w\\-]+:\\/+(?!\\/)(?:[^.\\/]+\
\.)*?").replace(/^\\\|/, "^").replace(/\\\|$/, "$"); |
| 412 var regexp = new RegExp(source, this.matchCase ? "" : "i"); |
| 413 delete this.regexpSource; |
| 414 this.__defineGetter__("regexp", function() |
| 415 { |
| 416 return regexp; |
| 417 }); |
| 418 return this.regexp; |
| 419 }, |
| 420 contentType: 2147483647, |
| 421 matchCase: false, |
| 422 thirdParty: null, |
| 423 matches: function(location, contentType, docDomain, thirdParty) |
| 424 { |
| 425 if (this.regexp.test(location) && (RegExpFilter.typeMap[contentType] & thi
s.contentType) != 0 && (this.thirdParty == null || this.thirdParty == thirdParty
) && this.isActiveOnDomain(docDomain)) |
| 426 { |
| 427 return true; |
| 428 } |
| 429 return false; |
| 430 } |
| 431 }; |
| 432 RegExpFilter.prototype.__defineGetter__("0", function() |
| 433 { |
| 434 return this; |
| 435 }); |
| 436 RegExpFilter.fromText = function(text) |
| 437 { |
| 438 var blocking = true; |
| 439 var origText = text; |
| 440 if (text.indexOf("@@") == 0) |
| 441 { |
| 442 blocking = false; |
| 443 text = text.substr(2); |
| 444 } |
| 445 var contentType = null; |
| 446 var matchCase = null; |
| 447 var domains = null; |
| 448 var siteKeys = null; |
| 449 var thirdParty = null; |
| 450 var collapse = null; |
| 451 var options; |
| 452 var match = text.indexOf("$") >= 0 ? Filter.optionsRegExp.exec(text) : null; |
| 453 if (match) |
| 454 { |
| 455 options = match[1].toUpperCase().split(","); |
| 456 text = match.input.substr(0, match.index); |
| 457 for (var _loopIndex2 = 0; _loopIndex2 < options.length; ++_loopIndex2) |
| 458 { |
| 459 var option = options[_loopIndex2]; |
| 460 var value = null; |
| 461 var separatorIndex = option.indexOf("="); |
| 462 if (separatorIndex >= 0) |
| 463 { |
| 464 value = option.substr(separatorIndex + 1); |
| 465 option = option.substr(0, separatorIndex); |
| 466 } |
| 467 option = option.replace(/-/, "_"); |
| 468 if (option in RegExpFilter.typeMap) |
| 469 { |
| 470 if (contentType == null) |
| 471 { |
| 472 contentType = 0; |
| 473 } |
| 474 contentType |= RegExpFilter.typeMap[option]; |
| 475 } |
| 476 else if (option[0] == "~" && option.substr(1) in RegExpFilter.typeMap) |
| 477 { |
| 478 if (contentType == null) |
| 479 { |
| 480 contentType = RegExpFilter.prototype.contentType; |
| 481 } |
| 482 contentType &= ~RegExpFilter.typeMap[option.substr(1)]; |
| 483 } |
| 484 else if (option == "MATCH_CASE") |
| 485 { |
| 486 matchCase = true; |
| 487 } |
| 488 else if (option == "DOMAIN" && typeof value != "undefined") |
| 489 { |
| 490 domains = value; |
| 491 } |
| 492 else if (option == "THIRD_PARTY") |
| 493 { |
| 494 thirdParty = true; |
| 495 } |
| 496 else if (option == "~THIRD_PARTY") |
| 497 { |
| 498 thirdParty = false; |
| 499 } |
| 500 else if (option == "COLLAPSE") |
| 501 { |
| 502 collapse = true; |
| 503 } |
| 504 else if (option == "~COLLAPSE") |
| 505 { |
| 506 collapse = false; |
| 507 } |
| 508 else if (option == "SITEKEY" && typeof value != "undefined") |
| 509 { |
| 510 siteKeys = value.split(/\|/); |
| 511 } |
| 512 } |
| 513 } |
| 514 if (!blocking && (contentType == null || contentType & RegExpFilter.typeMap.
DOCUMENT) && (!options || options.indexOf("DOCUMENT") < 0) && !/^\|?[\w\-]+:/.te
st(text)) |
| 515 { |
| 516 if (contentType == null) |
| 517 { |
| 518 contentType = RegExpFilter.prototype.contentType; |
| 519 } |
| 520 contentType &= ~RegExpFilter.typeMap.DOCUMENT; |
| 521 } |
| 522 if (!blocking && siteKeys) |
| 523 { |
| 524 contentType = RegExpFilter.typeMap.DOCUMENT; |
| 525 } |
| 526 try |
| 527 { |
| 528 if (blocking) |
| 529 { |
| 530 return new BlockingFilter(origText, text, contentType, matchCase, domain
s, thirdParty, collapse); |
| 531 } |
| 532 else |
| 533 { |
| 534 return new WhitelistFilter(origText, text, contentType, matchCase, domai
ns, thirdParty, siteKeys); |
| 535 } |
| 536 } |
| 537 catch (e) |
| 538 { |
| 539 return new InvalidFilter(text, e); |
| 540 } |
| 541 }; |
| 542 RegExpFilter.typeMap = |
| 543 { |
| 544 OTHER: 1, |
| 545 SCRIPT: 2, |
| 546 IMAGE: 4, |
| 547 STYLESHEET: 8, |
| 548 OBJECT: 16, |
| 549 SUBDOCUMENT: 32, |
| 550 DOCUMENT: 64, |
| 551 XBL: 1, |
| 552 PING: 1, |
| 553 XMLHTTPREQUEST: 2048, |
| 554 OBJECT_SUBREQUEST: 4096, |
| 555 DTD: 1, |
| 556 MEDIA: 16384, |
| 557 FONT: 32768, |
| 558 BACKGROUND: 4, |
| 559 POPUP: 268435456, |
| 560 DONOTTRACK: 536870912, |
| 561 ELEMHIDE: 1073741824 |
| 562 }; |
| 563 RegExpFilter.prototype.contentType &= ~ (RegExpFilter.typeMap.ELEMHIDE | RegEx
pFilter.typeMap.DONOTTRACK | RegExpFilter.typeMap.POPUP); |
| 564 |
| 565 function BlockingFilter(text, regexpSource, contentType, matchCase, domains, t
hirdParty, collapse) |
| 566 { |
| 567 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains,
thirdParty); |
| 568 this.collapse = collapse; |
| 569 } |
| 570 exports.BlockingFilter = BlockingFilter; |
| 571 BlockingFilter.prototype = |
| 572 { |
| 573 __proto__: RegExpFilter.prototype, |
| 574 collapse: null |
| 575 }; |
| 576 |
| 577 function WhitelistFilter(text, regexpSource, contentType, matchCase, domains,
thirdParty, siteKeys) |
| 578 { |
| 579 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains,
thirdParty); |
| 580 if (siteKeys != null) |
| 581 { |
| 582 this.siteKeys = siteKeys; |
| 583 } |
| 584 } |
| 585 exports.WhitelistFilter = WhitelistFilter; |
| 586 WhitelistFilter.prototype = |
| 587 { |
| 588 __proto__: RegExpFilter.prototype, |
| 589 siteKeys: null |
| 590 }; |
| 591 |
| 592 function ElemHideBase(text, domains, selector) |
| 593 { |
| 594 ActiveFilter.call(this, text, domains ? domains.toUpperCase() : null); |
| 595 if (domains) |
| 596 { |
| 597 this.selectorDomain = domains.replace(/,~[^,]+/g, "").replace(/^~[^,]+,?/,
"").toLowerCase(); |
| 598 } |
| 599 this.selector = selector; |
| 600 } |
| 601 exports.ElemHideBase = ElemHideBase; |
| 602 ElemHideBase.prototype = |
| 603 { |
| 604 __proto__: ActiveFilter.prototype, |
| 605 domainSeparator: ",", |
| 606 ignoreTrailingDot: false, |
| 607 selectorDomain: null, |
| 608 selector: null |
| 609 }; |
| 610 ElemHideBase.fromText = function(text, domain, isException, tagName, attrRules
, selector) |
| 611 { |
| 612 if (!selector) |
| 613 { |
| 614 if (tagName == "*") |
| 615 { |
| 616 tagName = ""; |
| 617 } |
| 618 var id = null; |
| 619 var additional = ""; |
| 620 if (attrRules) |
| 621 { |
| 622 attrRules = attrRules.match(/\([\w\-]+(?:[$^*]?=[^\(\)"]*)?\)/g); |
| 623 for (var _loopIndex3 = 0; _loopIndex3 < attrRules.length; ++_loopIndex3) |
| 624 { |
| 625 var rule = attrRules[_loopIndex3]; |
| 626 rule = rule.substr(1, rule.length - 2); |
| 627 var separatorPos = rule.indexOf("="); |
| 628 if (separatorPos > 0) |
| 629 { |
| 630 rule = rule.replace(/=/, "=\"") + "\""; |
| 631 additional += "[" + rule + "]"; |
| 632 } |
| 633 else |
| 634 { |
| 635 if (id) |
| 636 { |
| 637 var Utils = require("utils").Utils; |
| 638 return new InvalidFilter(text, Utils.getString("filter_elemhide_du
plicate_id")); |
| 639 } |
| 640 else |
| 641 { |
| 642 id = rule; |
| 643 } |
| 644 } |
| 645 } |
| 646 } |
| 647 if (id) |
| 648 { |
| 649 selector = tagName + "." + id + additional + "," + tagName + "#" + id +
additional; |
| 650 } |
| 651 else if (tagName || additional) |
| 652 { |
| 653 selector = tagName + additional; |
| 654 } |
| 655 else |
| 656 { |
| 657 var Utils = require("utils").Utils; |
| 658 return new InvalidFilter(text, Utils.getString("filter_elemhide_nocriter
ia")); |
| 659 } |
| 660 } |
| 661 if (isException) |
| 662 { |
| 663 return new ElemHideException(text, domain, selector); |
| 664 } |
| 665 else |
| 666 { |
| 667 return new ElemHideFilter(text, domain, selector); |
| 668 } |
| 669 }; |
| 670 |
| 671 function ElemHideFilter(text, domains, selector) |
| 672 { |
| 673 ElemHideBase.call(this, text, domains, selector); |
| 674 } |
| 675 exports.ElemHideFilter = ElemHideFilter; |
| 676 ElemHideFilter.prototype = |
| 677 { |
| 678 __proto__: ElemHideBase.prototype |
| 679 }; |
| 680 |
| 681 function ElemHideException(text, domains, selector) |
| 682 { |
| 683 ElemHideBase.call(this, text, domains, selector); |
| 684 } |
| 685 exports.ElemHideException = ElemHideException; |
| 686 ElemHideException.prototype = |
| 687 { |
| 688 __proto__: ElemHideBase.prototype |
| 689 }; |
| 690 return exports; |
| 691 })(); |
| 692 require.scopes["subscriptionClasses"] = (function() |
| 693 { |
| 694 var exports = {}; |
| 695 var _tempVar4 = require("filterClasses"); |
| 696 var ActiveFilter = _tempVar4.ActiveFilter; |
| 697 var BlockingFilter = _tempVar4.BlockingFilter; |
| 698 var WhitelistFilter = _tempVar4.WhitelistFilter; |
| 699 var ElemHideBase = _tempVar4.ElemHideBase; |
| 700 var FilterNotifier = require("filterNotifier").FilterNotifier; |
| 701 |
| 702 function Subscription(url, title) |
| 703 { |
| 704 this.url = url; |
| 705 this.filters = []; |
| 706 if (title) |
| 707 { |
| 708 this._title = title; |
| 709 } |
| 710 else |
| 711 { |
| 712 var Utils = require("utils").Utils; |
| 713 this._title = Utils.getString("newGroup_title"); |
| 714 } |
| 715 Subscription.knownSubscriptions[url] = this; |
| 716 } |
| 717 exports.Subscription = Subscription; |
| 718 Subscription.prototype = |
| 719 { |
| 720 url: null, |
| 721 filters: null, |
| 722 _title: null, |
| 723 _fixedTitle: false, |
| 724 _disabled: false, |
| 725 get title() |
| 726 { |
| 727 return this._title; |
| 728 }, |
| 729 set title(value) |
| 730 { |
| 731 if (value != this._title) |
| 732 { |
| 733 var oldValue = this._title; |
| 734 this._title = value; |
| 735 FilterNotifier.triggerListeners("subscription.title", this, value, oldVa
lue); |
| 736 } |
| 737 return this._title; |
| 738 }, |
| 739 get fixedTitle() |
| 740 { |
| 741 return this._fixedTitle; |
| 742 }, |
| 743 set fixedTitle(value) |
| 744 { |
| 745 if (value != this._fixedTitle) |
| 746 { |
| 747 var oldValue = this._fixedTitle; |
| 748 this._fixedTitle = value; |
| 749 FilterNotifier.triggerListeners("subscription.fixedTitle", this, value,
oldValue); |
| 750 } |
| 751 return this._fixedTitle; |
| 752 }, |
| 753 get disabled() |
| 754 { |
| 755 return this._disabled; |
| 756 }, |
| 757 set disabled(value) |
| 758 { |
| 759 if (value != this._disabled) |
| 760 { |
| 761 var oldValue = this._disabled; |
| 762 this._disabled = value; |
| 763 FilterNotifier.triggerListeners("subscription.disabled", this, value, ol
dValue); |
| 764 } |
| 765 return this._disabled; |
| 766 }, |
| 767 serialize: function(buffer) |
| 768 { |
| 769 buffer.push("[Subscription]"); |
| 770 buffer.push("url=" + this.url); |
| 771 buffer.push("title=" + this._title); |
| 772 if (this._fixedTitle) |
| 773 { |
| 774 buffer.push("fixedTitle=true"); |
| 775 } |
| 776 if (this._disabled) |
| 777 { |
| 778 buffer.push("disabled=true"); |
| 779 } |
| 780 }, |
| 781 serializeFilters: function(buffer) |
| 782 { |
| 783 for (var _loopIndex5 = 0; _loopIndex5 < this.filters.length; ++_loopIndex5
) |
| 784 { |
| 785 var filter = this.filters[_loopIndex5]; |
| 786 buffer.push(filter.text.replace(/\[/g, "\\[")); |
| 787 } |
| 788 }, |
| 789 toString: function() |
| 790 { |
| 791 var buffer = []; |
| 792 this.serialize(buffer); |
| 793 return buffer.join("\n"); |
| 794 } |
| 795 }; |
| 796 Subscription.knownSubscriptions = |
| 797 { |
| 798 __proto__: null |
| 799 }; |
| 800 Subscription.fromURL = function(url) |
| 801 { |
| 802 if (url in Subscription.knownSubscriptions) |
| 803 { |
| 804 return Subscription.knownSubscriptions[url]; |
| 805 } |
| 806 try |
| 807 { |
| 808 url = Services.io.newURI(url, null, null).spec; |
| 809 return new DownloadableSubscription(url, null); |
| 810 } |
| 811 catch (e) |
| 812 { |
| 813 return new SpecialSubscription(url); |
| 814 } |
| 815 }; |
| 816 Subscription.fromObject = function(obj) |
| 817 { |
| 818 var result; |
| 819 try |
| 820 { |
| 821 obj.url = Services.io.newURI(obj.url, null, null).spec; |
| 822 result = new DownloadableSubscription(obj.url, obj.title); |
| 823 if ("nextURL" in obj) |
| 824 { |
| 825 result.nextURL = obj.nextURL; |
| 826 } |
| 827 if ("downloadStatus" in obj) |
| 828 { |
| 829 result._downloadStatus = obj.downloadStatus; |
| 830 } |
| 831 if ("lastModified" in obj) |
| 832 { |
| 833 result.lastModified = obj.lastModified; |
| 834 } |
| 835 if ("lastSuccess" in obj) |
| 836 { |
| 837 result.lastSuccess = parseInt(obj.lastSuccess) || 0; |
| 838 } |
| 839 if ("lastCheck" in obj) |
| 840 { |
| 841 result._lastCheck = parseInt(obj.lastCheck) || 0; |
| 842 } |
| 843 if ("expires" in obj) |
| 844 { |
| 845 result.expires = parseInt(obj.expires) || 0; |
| 846 } |
| 847 if ("softExpiration" in obj) |
| 848 { |
| 849 result.softExpiration = parseInt(obj.softExpiration) || 0; |
| 850 } |
| 851 if ("errors" in obj) |
| 852 { |
| 853 result._errors = parseInt(obj.errors) || 0; |
| 854 } |
| 855 if ("requiredVersion" in obj) |
| 856 { |
| 857 var addonVersion = require("info").addonVersion; |
| 858 result.requiredVersion = obj.requiredVersion; |
| 859 if (Services.vc.compare(result.requiredVersion, addonVersion) > 0) |
| 860 { |
| 861 result.upgradeRequired = true; |
| 862 } |
| 863 } |
| 864 if ("alternativeLocations" in obj) |
| 865 { |
| 866 result.alternativeLocations = obj.alternativeLocations; |
| 867 } |
| 868 if ("homepage" in obj) |
| 869 { |
| 870 result._homepage = obj.homepage; |
| 871 } |
| 872 if ("lastDownload" in obj) |
| 873 { |
| 874 result._lastDownload = parseInt(obj.lastDownload) || 0; |
| 875 } |
| 876 } |
| 877 catch (e) |
| 878 { |
| 879 if (!("title" in obj)) |
| 880 { |
| 881 if (obj.url == "~wl~") |
| 882 { |
| 883 obj.defaults = "whitelist"; |
| 884 } |
| 885 else if (obj.url == "~fl~") |
| 886 { |
| 887 obj.defaults = "blocking"; |
| 888 } |
| 889 else if (obj.url == "~eh~") |
| 890 { |
| 891 obj.defaults = "elemhide"; |
| 892 } |
| 893 if ("defaults" in obj) |
| 894 { |
| 895 var Utils = require("utils").Utils; |
| 896 obj.title = Utils.getString(obj.defaults + "Group_title"); |
| 897 } |
| 898 } |
| 899 result = new SpecialSubscription(obj.url, obj.title); |
| 900 if ("defaults" in obj) |
| 901 { |
| 902 result.defaults = obj.defaults.split(" "); |
| 903 } |
| 904 } |
| 905 if ("fixedTitle" in obj) |
| 906 { |
| 907 result._fixedTitle = obj.fixedTitle == "true"; |
| 908 } |
| 909 if ("disabled" in obj) |
| 910 { |
| 911 result._disabled = obj.disabled == "true"; |
| 912 } |
| 913 return result; |
| 914 }; |
| 915 |
| 916 function SpecialSubscription(url, title) |
| 917 { |
| 918 Subscription.call(this, url, title); |
| 919 } |
| 920 exports.SpecialSubscription = SpecialSubscription; |
| 921 SpecialSubscription.prototype = |
| 922 { |
| 923 __proto__: Subscription.prototype, |
| 924 defaults: null, |
| 925 isDefaultFor: function(filter) |
| 926 { |
| 927 if (this.defaults && this.defaults.length) |
| 928 { |
| 929 for (var _loopIndex6 = 0; _loopIndex6 < this.defaults.length; ++_loopInd
ex6) |
| 930 { |
| 931 var type = this.defaults[_loopIndex6]; |
| 932 if (filter instanceof SpecialSubscription.defaultsMap[type]) |
| 933 { |
| 934 return true; |
| 935 } |
| 936 if (!(filter instanceof ActiveFilter) && type == "blacklist") |
| 937 { |
| 938 return true; |
| 939 } |
| 940 } |
| 941 } |
| 942 return false; |
| 943 }, |
| 944 serialize: function(buffer) |
| 945 { |
| 946 Subscription.prototype.serialize.call(this, buffer); |
| 947 if (this.defaults && this.defaults.length) |
| 948 { |
| 949 buffer.push("defaults=" + this.defaults.filter(function(type) |
| 950 { |
| 951 return type in SpecialSubscription.defaultsMap; |
| 952 }).join(" ")); |
| 953 } |
| 954 if (this._lastDownload) |
| 955 { |
| 956 buffer.push("lastDownload=" + this._lastDownload); |
| 957 } |
| 958 } |
| 959 }; |
| 960 SpecialSubscription.defaultsMap = |
| 961 { |
| 962 __proto__: null, |
| 963 "whitelist": WhitelistFilter, |
| 964 "blocking": BlockingFilter, |
| 965 "elemhide": ElemHideBase |
| 966 }; |
| 967 SpecialSubscription.create = function(title) |
| 968 { |
| 969 var url; |
| 970 do |
| 971 { |
| 972 url = "~user~" + Math.round(Math.random() * 1000000); |
| 973 } |
| 974 while (url in Subscription.knownSubscriptions); |
| 975 return new SpecialSubscription(url, title); |
| 976 }; |
| 977 SpecialSubscription.createForFilter = function(filter) |
| 978 { |
| 979 var subscription = SpecialSubscription.create(); |
| 980 subscription.filters.push(filter); |
| 981 for (var type in SpecialSubscription.defaultsMap) |
| 982 { |
| 983 if (filter instanceof SpecialSubscription.defaultsMap[type]) |
| 984 { |
| 985 subscription.defaults = [type]; |
| 986 } |
| 987 } |
| 988 if (!subscription.defaults) |
| 989 { |
| 990 subscription.defaults = ["blocking"]; |
| 991 } |
| 992 var Utils = require("utils").Utils; |
| 993 subscription.title = Utils.getString(subscription.defaults[0] + "Group_title
"); |
| 994 return subscription; |
| 995 }; |
| 996 |
| 997 function RegularSubscription(url, title) |
| 998 { |
| 999 Subscription.call(this, url, title || url); |
| 1000 } |
| 1001 exports.RegularSubscription = RegularSubscription; |
| 1002 RegularSubscription.prototype = |
| 1003 { |
| 1004 __proto__: Subscription.prototype, |
| 1005 _homepage: null, |
| 1006 _lastDownload: 0, |
| 1007 get homepage() |
| 1008 { |
| 1009 return this._homepage; |
| 1010 }, |
| 1011 set homepage(value) |
| 1012 { |
| 1013 if (value != this._homepage) |
| 1014 { |
| 1015 var oldValue = this._homepage; |
| 1016 this._homepage = value; |
| 1017 FilterNotifier.triggerListeners("subscription.homepage", this, value, ol
dValue); |
| 1018 } |
| 1019 return this._homepage; |
| 1020 }, |
| 1021 get lastDownload() |
| 1022 { |
| 1023 return this._lastDownload; |
| 1024 }, |
| 1025 set lastDownload(value) |
| 1026 { |
| 1027 if (value != this._lastDownload) |
| 1028 { |
| 1029 var oldValue = this._lastDownload; |
| 1030 this._lastDownload = value; |
| 1031 FilterNotifier.triggerListeners("subscription.lastDownload", this, value
, oldValue); |
| 1032 } |
| 1033 return this._lastDownload; |
| 1034 }, |
| 1035 serialize: function(buffer) |
| 1036 { |
| 1037 Subscription.prototype.serialize.call(this, buffer); |
| 1038 if (this._homepage) |
| 1039 { |
| 1040 buffer.push("homepage=" + this._homepage); |
| 1041 } |
| 1042 if (this._lastDownload) |
| 1043 { |
| 1044 buffer.push("lastDownload=" + this._lastDownload); |
| 1045 } |
| 1046 } |
| 1047 }; |
| 1048 |
| 1049 function ExternalSubscription(url, title) |
| 1050 { |
| 1051 RegularSubscription.call(this, url, title); |
| 1052 } |
| 1053 exports.ExternalSubscription = ExternalSubscription; |
| 1054 ExternalSubscription.prototype = |
| 1055 { |
| 1056 __proto__: RegularSubscription.prototype, |
| 1057 serialize: function(buffer) |
| 1058 { |
| 1059 throw new Error("Unexpected call, external subscriptions should not be ser
ialized"); |
| 1060 } |
| 1061 }; |
| 1062 |
| 1063 function DownloadableSubscription(url, title) |
| 1064 { |
| 1065 RegularSubscription.call(this, url, title); |
| 1066 } |
| 1067 exports.DownloadableSubscription = DownloadableSubscription; |
| 1068 DownloadableSubscription.prototype = |
| 1069 { |
| 1070 __proto__: RegularSubscription.prototype, |
| 1071 _downloadStatus: null, |
| 1072 _lastCheck: 0, |
| 1073 _errors: 0, |
| 1074 nextURL: null, |
| 1075 get downloadStatus() |
| 1076 { |
| 1077 return this._downloadStatus; |
| 1078 }, |
| 1079 set downloadStatus(value) |
| 1080 { |
| 1081 var oldValue = this._downloadStatus; |
| 1082 this._downloadStatus = value; |
| 1083 FilterNotifier.triggerListeners("subscription.downloadStatus", this, value
, oldValue); |
| 1084 return this._downloadStatus; |
| 1085 }, |
| 1086 lastModified: null, |
| 1087 lastSuccess: 0, |
| 1088 get lastCheck() |
| 1089 { |
| 1090 return this._lastCheck; |
| 1091 }, |
| 1092 set lastCheck(value) |
| 1093 { |
| 1094 if (value != this._lastCheck) |
| 1095 { |
| 1096 var oldValue = this._lastCheck; |
| 1097 this._lastCheck = value; |
| 1098 FilterNotifier.triggerListeners("subscription.lastCheck", this, value, o
ldValue); |
| 1099 } |
| 1100 return this._lastCheck; |
| 1101 }, |
| 1102 expires: 0, |
| 1103 softExpiration: 0, |
| 1104 get errors() |
| 1105 { |
| 1106 return this._errors; |
| 1107 }, |
| 1108 set errors(value) |
| 1109 { |
| 1110 if (value != this._errors) |
| 1111 { |
| 1112 var oldValue = this._errors; |
| 1113 this._errors = value; |
| 1114 FilterNotifier.triggerListeners("subscription.errors", this, value, oldV
alue); |
| 1115 } |
| 1116 return this._errors; |
| 1117 }, |
| 1118 requiredVersion: null, |
| 1119 upgradeRequired: false, |
| 1120 alternativeLocations: null, |
| 1121 serialize: function(buffer) |
| 1122 { |
| 1123 RegularSubscription.prototype.serialize.call(this, buffer); |
| 1124 if (this.nextURL) |
| 1125 { |
| 1126 buffer.push("nextURL=" + this.nextURL); |
| 1127 } |
| 1128 if (this.downloadStatus) |
| 1129 { |
| 1130 buffer.push("downloadStatus=" + this.downloadStatus); |
| 1131 } |
| 1132 if (this.lastModified) |
| 1133 { |
| 1134 buffer.push("lastModified=" + this.lastModified); |
| 1135 } |
| 1136 if (this.lastSuccess) |
| 1137 { |
| 1138 buffer.push("lastSuccess=" + this.lastSuccess); |
| 1139 } |
| 1140 if (this.lastCheck) |
| 1141 { |
| 1142 buffer.push("lastCheck=" + this.lastCheck); |
| 1143 } |
| 1144 if (this.expires) |
| 1145 { |
| 1146 buffer.push("expires=" + this.expires); |
| 1147 } |
| 1148 if (this.softExpiration) |
| 1149 { |
| 1150 buffer.push("softExpiration=" + this.softExpiration); |
| 1151 } |
| 1152 if (this.errors) |
| 1153 { |
| 1154 buffer.push("errors=" + this.errors); |
| 1155 } |
| 1156 if (this.requiredVersion) |
| 1157 { |
| 1158 buffer.push("requiredVersion=" + this.requiredVersion); |
| 1159 } |
| 1160 if (this.alternativeLocations) |
| 1161 { |
| 1162 buffer.push("alternativeLocations=" + this.alternativeLocations); |
| 1163 } |
| 1164 } |
| 1165 }; |
| 1166 return exports; |
| 1167 })(); |
| 1168 require.scopes["filterStorage"] = (function() |
| 1169 { |
| 1170 var exports = {}; |
| 1171 var IO = require("io").IO; |
| 1172 var Prefs = require("prefs").Prefs; |
| 1173 var _tempVar7 = require("filterClasses"); |
| 1174 var Filter = _tempVar7.Filter; |
| 1175 var ActiveFilter = _tempVar7.ActiveFilter; |
| 1176 var _tempVar8 = require("subscriptionClasses"); |
| 1177 var Subscription = _tempVar8.Subscription; |
| 1178 var SpecialSubscription = _tempVar8.SpecialSubscription; |
| 1179 var ExternalSubscription = _tempVar8.ExternalSubscription; |
| 1180 var FilterNotifier = require("filterNotifier").FilterNotifier; |
| 1181 var formatVersion = 4; |
| 1182 var FilterStorage = exports.FilterStorage = |
| 1183 { |
| 1184 get formatVersion() |
| 1185 { |
| 1186 return formatVersion; |
| 1187 }, |
| 1188 get sourceFile() |
| 1189 { |
| 1190 var file = null; |
| 1191 if (Prefs.patternsfile) |
| 1192 { |
| 1193 file = IO.resolveFilePath(Prefs.patternsfile); |
| 1194 } |
| 1195 if (!file) |
| 1196 { |
| 1197 file = IO.resolveFilePath(Prefs.data_directory); |
| 1198 if (file) |
| 1199 { |
| 1200 file.append("patterns.ini"); |
| 1201 } |
| 1202 } |
| 1203 if (!file) |
| 1204 { |
| 1205 try |
| 1206 { |
| 1207 file = IO.resolveFilePath(Services.prefs.getDefaultBranch("extensions.
adblockplus.").getCharPref("data_directory")); |
| 1208 if (file) |
| 1209 { |
| 1210 file.append("patterns.ini"); |
| 1211 } |
| 1212 } |
| 1213 catch (e){} |
| 1214 } |
| 1215 if (!file) |
| 1216 { |
| 1217 Cu.reportError("Adblock Plus: Failed to resolve filter file location fro
m extensions.adblockplus.patternsfile preference"); |
| 1218 } |
| 1219 this.__defineGetter__("sourceFile", function() |
| 1220 { |
| 1221 return file; |
| 1222 }); |
| 1223 return this.sourceFile; |
| 1224 }, |
| 1225 fileProperties: |
| 1226 { |
| 1227 __proto__: null |
| 1228 }, |
| 1229 subscriptions: [], |
| 1230 knownSubscriptions: |
| 1231 { |
| 1232 __proto__: null |
| 1233 }, |
| 1234 getGroupForFilter: function(filter) |
| 1235 { |
| 1236 var generalSubscription = null; |
| 1237 for (var _loopIndex9 = 0; _loopIndex9 < FilterStorage.subscriptions.length
; ++_loopIndex9) |
| 1238 { |
| 1239 var subscription = FilterStorage.subscriptions[_loopIndex9]; |
| 1240 if (subscription instanceof SpecialSubscription && !subscription.disable
d) |
| 1241 { |
| 1242 if (subscription.isDefaultFor(filter)) |
| 1243 { |
| 1244 return subscription; |
| 1245 } |
| 1246 if (!generalSubscription && (!subscription.defaults || !subscription.d
efaults.length)) |
| 1247 { |
| 1248 generalSubscription = subscription; |
| 1249 } |
| 1250 } |
| 1251 } |
| 1252 return generalSubscription; |
| 1253 }, |
| 1254 addSubscription: function(subscription, silent) |
| 1255 { |
| 1256 if (subscription.url in FilterStorage.knownSubscriptions) |
| 1257 { |
| 1258 return; |
| 1259 } |
| 1260 FilterStorage.subscriptions.push(subscription); |
| 1261 FilterStorage.knownSubscriptions[subscription.url] = subscription; |
| 1262 addSubscriptionFilters(subscription); |
| 1263 if (!silent) |
| 1264 { |
| 1265 FilterNotifier.triggerListeners("subscription.added", subscription); |
| 1266 } |
| 1267 }, |
| 1268 removeSubscription: function(subscription, silent) |
| 1269 { |
| 1270 for (var i = 0; i < FilterStorage.subscriptions.length; i++) |
| 1271 { |
| 1272 if (FilterStorage.subscriptions[i].url == subscription.url) |
| 1273 { |
| 1274 removeSubscriptionFilters(subscription); |
| 1275 FilterStorage.subscriptions.splice(i--, 1); |
| 1276 delete FilterStorage.knownSubscriptions[subscription.url]; |
| 1277 if (!silent) |
| 1278 { |
| 1279 FilterNotifier.triggerListeners("subscription.removed", subscription
); |
| 1280 } |
| 1281 return; |
| 1282 } |
| 1283 } |
| 1284 }, |
| 1285 moveSubscription: function(subscription, insertBefore) |
| 1286 { |
| 1287 var currentPos = FilterStorage.subscriptions.indexOf(subscription); |
| 1288 if (currentPos < 0) |
| 1289 { |
| 1290 return; |
| 1291 } |
| 1292 var newPos = insertBefore ? FilterStorage.subscriptions.indexOf(insertBefo
re) : -1; |
| 1293 if (newPos < 0) |
| 1294 { |
| 1295 newPos = FilterStorage.subscriptions.length; |
| 1296 } |
| 1297 if (currentPos < newPos) |
| 1298 { |
| 1299 newPos--; |
| 1300 } |
| 1301 if (currentPos == newPos) |
| 1302 { |
| 1303 return; |
| 1304 } |
| 1305 FilterStorage.subscriptions.splice(currentPos, 1); |
| 1306 FilterStorage.subscriptions.splice(newPos, 0, subscription); |
| 1307 FilterNotifier.triggerListeners("subscription.moved", subscription); |
| 1308 }, |
| 1309 updateSubscriptionFilters: function(subscription, filters) |
| 1310 { |
| 1311 removeSubscriptionFilters(subscription); |
| 1312 subscription.oldFilters = subscription.filters; |
| 1313 subscription.filters = filters; |
| 1314 addSubscriptionFilters(subscription); |
| 1315 FilterNotifier.triggerListeners("subscription.updated", subscription); |
| 1316 delete subscription.oldFilters; |
| 1317 }, |
| 1318 addFilter: function(filter, subscription, position, silent) |
| 1319 { |
| 1320 if (!subscription) |
| 1321 { |
| 1322 if (filter.subscriptions.some(function(s) |
| 1323 { |
| 1324 return s instanceof SpecialSubscription && !s.disabled; |
| 1325 })) |
| 1326 { |
| 1327 return; |
| 1328 } |
| 1329 subscription = FilterStorage.getGroupForFilter(filter); |
| 1330 } |
| 1331 if (!subscription) |
| 1332 { |
| 1333 subscription = SpecialSubscription.createForFilter(filter); |
| 1334 this.addSubscription(subscription); |
| 1335 return; |
| 1336 } |
| 1337 if (typeof position == "undefined") |
| 1338 { |
| 1339 position = subscription.filters.length; |
| 1340 } |
| 1341 if (filter.subscriptions.indexOf(subscription) < 0) |
| 1342 { |
| 1343 filter.subscriptions.push(subscription); |
| 1344 } |
| 1345 subscription.filters.splice(position, 0, filter); |
| 1346 if (!silent) |
| 1347 { |
| 1348 FilterNotifier.triggerListeners("filter.added", filter, subscription, po
sition); |
| 1349 } |
| 1350 }, |
| 1351 removeFilter: function(filter, subscription, position) |
| 1352 { |
| 1353 var subscriptions = subscription ? [subscription] : filter.subscriptions.s
lice(); |
| 1354 for (var i = 0; i < subscriptions.length; i++) |
| 1355 { |
| 1356 var subscription = subscriptions[i]; |
| 1357 if (subscription instanceof SpecialSubscription) |
| 1358 { |
| 1359 var positions = []; |
| 1360 if (typeof position == "undefined") |
| 1361 { |
| 1362 var index = -1; |
| 1363 do |
| 1364 { |
| 1365 index = subscription.filters.indexOf(filter, index + 1); |
| 1366 if (index >= 0) |
| 1367 { |
| 1368 positions.push(index); |
| 1369 } |
| 1370 } |
| 1371 while (index >= 0); |
| 1372 } |
| 1373 else |
| 1374 { |
| 1375 positions.push(position); |
| 1376 } |
| 1377 for (var j = positions.length - 1; j >= 0; j--) |
| 1378 { |
| 1379 var position = positions[j]; |
| 1380 if (subscription.filters[position] == filter) |
| 1381 { |
| 1382 subscription.filters.splice(position, 1); |
| 1383 if (subscription.filters.indexOf(filter) < 0) |
| 1384 { |
| 1385 var index = filter.subscriptions.indexOf(subscription); |
| 1386 if (index >= 0) |
| 1387 { |
| 1388 filter.subscriptions.splice(index, 1); |
| 1389 } |
| 1390 } |
| 1391 FilterNotifier.triggerListeners("filter.removed", filter, subscrip
tion, position); |
| 1392 } |
| 1393 } |
| 1394 } |
| 1395 } |
| 1396 }, |
| 1397 moveFilter: function(filter, subscription, oldPosition, newPosition) |
| 1398 { |
| 1399 if (!(subscription instanceof SpecialSubscription) || subscription.filters
[oldPosition] != filter) |
| 1400 { |
| 1401 return; |
| 1402 } |
| 1403 newPosition = Math.min(Math.max(newPosition, 0), subscription.filters.leng
th - 1); |
| 1404 if (oldPosition == newPosition) |
| 1405 { |
| 1406 return; |
| 1407 } |
| 1408 subscription.filters.splice(oldPosition, 1); |
| 1409 subscription.filters.splice(newPosition, 0, filter); |
| 1410 FilterNotifier.triggerListeners("filter.moved", filter, subscription, oldP
osition, newPosition); |
| 1411 }, |
| 1412 increaseHitCount: function(filter) |
| 1413 { |
| 1414 if (!Prefs.savestats || PrivateBrowsing.enabled || !(filter instanceof Act
iveFilter)) |
| 1415 { |
| 1416 return; |
| 1417 } |
| 1418 filter.hitCount++; |
| 1419 filter.lastHit = Date.now(); |
| 1420 }, |
| 1421 resetHitCounts: function(filters) |
| 1422 { |
| 1423 if (!filters) |
| 1424 { |
| 1425 filters = []; |
| 1426 for (var text in Filter.knownFilters) |
| 1427 { |
| 1428 filters.push(Filter.knownFilters[text]); |
| 1429 } |
| 1430 } |
| 1431 for (var _loopIndex10 = 0; _loopIndex10 < filters.length; ++_loopIndex10) |
| 1432 { |
| 1433 var filter = filters[_loopIndex10]; |
| 1434 filter.hitCount = 0; |
| 1435 filter.lastHit = 0; |
| 1436 } |
| 1437 }, |
| 1438 _loading: false, |
| 1439 loadFromDisk: function(sourceFile) |
| 1440 { |
| 1441 if (this._loading) |
| 1442 { |
| 1443 return; |
| 1444 } |
| 1445 var readFile = function(sourceFile, backupIndex) |
| 1446 { |
| 1447 var parser = new INIParser(); |
| 1448 IO.readFromFile(sourceFile, true, parser, function(e) |
| 1449 { |
| 1450 if (!e && parser.subscriptions.length == 0) |
| 1451 { |
| 1452 e = new Error("No data in the file"); |
| 1453 } |
| 1454 if (e) |
| 1455 { |
| 1456 Cu.reportError(e); |
| 1457 } |
| 1458 if (e && !explicitFile) |
| 1459 { |
| 1460 sourceFile = this.sourceFile; |
| 1461 if (sourceFile) |
| 1462 { |
| 1463 var _tempVar11 = /^(.*)(\.\w+)$/.exec(sourceFile.leafName) || [nul
l, sourceFile.leafName, ""]; |
| 1464 var part1 = _tempVar11[1]; |
| 1465 var part2 = _tempVar11[2]; |
| 1466 sourceFile = sourceFile.clone(); |
| 1467 sourceFile.leafName = part1 + "-backup" + ++backupIndex + part2; |
| 1468 IO.statFile(sourceFile, function(e, statData) |
| 1469 { |
| 1470 if (!e && statData.exists) |
| 1471 { |
| 1472 readFile(sourceFile, backupIndex); |
| 1473 } |
| 1474 }); |
| 1475 return; |
| 1476 } |
| 1477 } |
| 1478 var specialMap = |
| 1479 { |
| 1480 "~il~": true, |
| 1481 "~wl~": true, |
| 1482 "~fl~": true, |
| 1483 "~eh~": true |
| 1484 }; |
| 1485 var knownSubscriptions = |
| 1486 { |
| 1487 __proto__: null |
| 1488 }; |
| 1489 for (var i = 0; i < parser.subscriptions.length; i++) |
| 1490 { |
| 1491 var subscription = parser.subscriptions[i]; |
| 1492 if (subscription instanceof SpecialSubscription && subscription.filt
ers.length == 0 && subscription.url in specialMap) |
| 1493 { |
| 1494 parser.subscriptions.splice(i--, 1); |
| 1495 } |
| 1496 else |
| 1497 { |
| 1498 knownSubscriptions[subscription.url] = subscription; |
| 1499 } |
| 1500 } |
| 1501 this.fileProperties = parser.fileProperties; |
| 1502 this.subscriptions = parser.subscriptions; |
| 1503 this.knownSubscriptions = knownSubscriptions; |
| 1504 Filter.knownFilters = parser.knownFilters; |
| 1505 Subscription.knownSubscriptions = parser.knownSubscriptions; |
| 1506 if (parser.userFilters) |
| 1507 { |
| 1508 for (var i = 0; i < parser.userFilters.length; i++) |
| 1509 { |
| 1510 var filter = Filter.fromText(parser.userFilters[i]); |
| 1511 this.addFilter(filter, null, undefined, true); |
| 1512 } |
| 1513 } |
| 1514 this._loading = false; |
| 1515 FilterNotifier.triggerListeners("load"); |
| 1516 if (sourceFile != this.sourceFile) |
| 1517 { |
| 1518 this.saveToDisk(); |
| 1519 } |
| 1520 }.bind(this), "FilterStorageRead"); |
| 1521 }.bind(this); |
| 1522 var startRead = function(file) |
| 1523 { |
| 1524 this._loading = true; |
| 1525 readFile(file, 0); |
| 1526 }.bind(this); |
| 1527 var explicitFile; |
| 1528 if (sourceFile) |
| 1529 { |
| 1530 explicitFile = true; |
| 1531 startRead(sourceFile); |
| 1532 } |
| 1533 else |
| 1534 { |
| 1535 explicitFile = false; |
| 1536 sourceFile = FilterStorage.sourceFile; |
| 1537 var callback = function(e, statData) |
| 1538 { |
| 1539 if (e || !statData.exists) |
| 1540 { |
| 1541 var addonRoot = require("info").addonRoot; |
| 1542 sourceFile = Services.io.newURI(addonRoot + "defaults/patterns.ini",
null, null); |
| 1543 } |
| 1544 startRead(sourceFile); |
| 1545 }; |
| 1546 if (sourceFile) |
| 1547 { |
| 1548 IO.statFile(sourceFile, callback); |
| 1549 } |
| 1550 else |
| 1551 { |
| 1552 callback(true); |
| 1553 } |
| 1554 } |
| 1555 }, |
| 1556 _generateFilterData: function(subscriptions) |
| 1557 { |
| 1558 var _generatorResult12 = []; |
| 1559 _generatorResult12.push("# Adblock Plus preferences"); |
| 1560 _generatorResult12.push("version=" + formatVersion); |
| 1561 var saved = |
| 1562 { |
| 1563 __proto__: null |
| 1564 }; |
| 1565 var buf = []; |
| 1566 for (var i = 0; i < subscriptions.length; i++) |
| 1567 { |
| 1568 var subscription = subscriptions[i]; |
| 1569 for (var j = 0; j < subscription.filters.length; j++) |
| 1570 { |
| 1571 var filter = subscription.filters[j]; |
| 1572 if (!(filter.text in saved)) |
| 1573 { |
| 1574 filter.serialize(buf); |
| 1575 saved[filter.text] = filter; |
| 1576 for (var k = 0; k < buf.length; k++) |
| 1577 { |
| 1578 _generatorResult12.push(buf[k]); |
| 1579 } |
| 1580 buf.splice(0); |
| 1581 } |
| 1582 } |
| 1583 } |
| 1584 for (var i = 0; i < subscriptions.length; i++) |
| 1585 { |
| 1586 var subscription = subscriptions[i]; |
| 1587 _generatorResult12.push(""); |
| 1588 subscription.serialize(buf); |
| 1589 if (subscription.filters.length) |
| 1590 { |
| 1591 buf.push("", "[Subscription filters]"); |
| 1592 subscription.serializeFilters(buf); |
| 1593 } |
| 1594 for (var k = 0; k < buf.length; k++) |
| 1595 { |
| 1596 _generatorResult12.push(buf[k]); |
| 1597 } |
| 1598 buf.splice(0); |
| 1599 } |
| 1600 return _generatorResult12; |
| 1601 }, |
| 1602 _saving: false, |
| 1603 _needsSave: false, |
| 1604 saveToDisk: function(targetFile) |
| 1605 { |
| 1606 var explicitFile = true; |
| 1607 if (!targetFile) |
| 1608 { |
| 1609 targetFile = FilterStorage.sourceFile; |
| 1610 explicitFile = false; |
| 1611 } |
| 1612 if (!targetFile) |
| 1613 { |
| 1614 return; |
| 1615 } |
| 1616 if (!explicitFile && this._saving) |
| 1617 { |
| 1618 this._needsSave = true; |
| 1619 return; |
| 1620 } |
| 1621 try |
| 1622 { |
| 1623 targetFile.parent.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRE
CTORY); |
| 1624 } |
| 1625 catch (e){} |
| 1626 var writeFilters = function() |
| 1627 { |
| 1628 IO.writeToFile(targetFile, true, this._generateFilterData(subscriptions)
, function(e) |
| 1629 { |
| 1630 if (!explicitFile) |
| 1631 { |
| 1632 this._saving = false; |
| 1633 } |
| 1634 if (e) |
| 1635 { |
| 1636 Cu.reportError(e); |
| 1637 } |
| 1638 if (!explicitFile && this._needsSave) |
| 1639 { |
| 1640 this._needsSave = false; |
| 1641 this.saveToDisk(); |
| 1642 } |
| 1643 else |
| 1644 { |
| 1645 FilterNotifier.triggerListeners("save"); |
| 1646 } |
| 1647 }.bind(this), "FilterStorageWrite"); |
| 1648 }.bind(this); |
| 1649 var checkBackupRequired = function(callbackNotRequired, callbackRequired) |
| 1650 { |
| 1651 if (explicitFile || Prefs.patternsbackups <= 0) |
| 1652 { |
| 1653 callbackNotRequired(); |
| 1654 } |
| 1655 else |
| 1656 { |
| 1657 IO.statFile(targetFile, function(e, statData) |
| 1658 { |
| 1659 if (e || !statData.exists) |
| 1660 { |
| 1661 callbackNotRequired(); |
| 1662 } |
| 1663 else |
| 1664 { |
| 1665 var _tempVar13 = /^(.*)(\.\w+)$/.exec(targetFile.leafName) || [nul
l, targetFile.leafName, ""]; |
| 1666 var part1 = _tempVar13[1]; |
| 1667 var part2 = _tempVar13[2]; |
| 1668 var newestBackup = targetFile.clone(); |
| 1669 newestBackup.leafName = part1 + "-backup1" + part2; |
| 1670 IO.statFile(newestBackup, function(e, statData) |
| 1671 { |
| 1672 if (!e && (!statData.exists || (Date.now() - statData.lastModifi
ed) / 3600000 >= Prefs.patternsbackupinterval)) |
| 1673 { |
| 1674 callbackRequired(part1, part2); |
| 1675 } |
| 1676 else |
| 1677 { |
| 1678 callbackNotRequired(); |
| 1679 } |
| 1680 }); |
| 1681 } |
| 1682 }); |
| 1683 } |
| 1684 }.bind(this); |
| 1685 var removeLastBackup = function(part1, part2) |
| 1686 { |
| 1687 var file = targetFile.clone(); |
| 1688 file.leafName = part1 + "-backup" + Prefs.patternsbackups + part2; |
| 1689 IO.removeFile(file, function(e) |
| 1690 { |
| 1691 return renameBackup(part1, part2, Prefs.patternsbackups - 1); |
| 1692 }); |
| 1693 }.bind(this); |
| 1694 var renameBackup = function(part1, part2, index) |
| 1695 { |
| 1696 if (index > 0) |
| 1697 { |
| 1698 var fromFile = targetFile.clone(); |
| 1699 fromFile.leafName = part1 + "-backup" + index + part2; |
| 1700 var toName = part1 + "-backup" + (index + 1) + part2; |
| 1701 IO.renameFile(fromFile, toName, function(e) |
| 1702 { |
| 1703 return renameBackup(part1, part2, index - 1); |
| 1704 }); |
| 1705 } |
| 1706 else |
| 1707 { |
| 1708 var toFile = targetFile.clone(); |
| 1709 toFile.leafName = part1 + "-backup" + (index + 1) + part2; |
| 1710 IO.copyFile(targetFile, toFile, writeFilters); |
| 1711 } |
| 1712 }.bind(this); |
| 1713 var subscriptions = this.subscriptions.filter(function(s) |
| 1714 { |
| 1715 return !(s instanceof ExternalSubscription); |
| 1716 }); |
| 1717 if (!explicitFile) |
| 1718 { |
| 1719 this._saving = true; |
| 1720 } |
| 1721 checkBackupRequired(writeFilters, removeLastBackup); |
| 1722 }, |
| 1723 getBackupFiles: function() |
| 1724 { |
| 1725 var result = []; |
| 1726 var _tempVar14 = /^(.*)(\.\w+)$/.exec(FilterStorage.sourceFile.leafName) |
| [null, FilterStorage.sourceFile.leafName, ""]; |
| 1727 var part1 = _tempVar14[1]; |
| 1728 var part2 = _tempVar14[2]; |
| 1729 for (var i = 1;; i++) |
| 1730 { |
| 1731 var file = FilterStorage.sourceFile.clone(); |
| 1732 file.leafName = part1 + "-backup" + i + part2; |
| 1733 if (file.exists()) |
| 1734 { |
| 1735 result.push(file); |
| 1736 } |
| 1737 else |
| 1738 { |
| 1739 break; |
| 1740 } |
| 1741 } |
| 1742 return result; |
| 1743 } |
| 1744 }; |
| 1745 |
| 1746 function addSubscriptionFilters(subscription) |
| 1747 { |
| 1748 if (!(subscription.url in FilterStorage.knownSubscriptions)) |
| 1749 { |
| 1750 return; |
| 1751 } |
| 1752 for (var _loopIndex15 = 0; _loopIndex15 < subscription.filters.length; ++_lo
opIndex15) |
| 1753 { |
| 1754 var filter = subscription.filters[_loopIndex15]; |
| 1755 filter.subscriptions.push(subscription); |
| 1756 } |
| 1757 } |
| 1758 |
| 1759 function removeSubscriptionFilters(subscription) |
| 1760 { |
| 1761 if (!(subscription.url in FilterStorage.knownSubscriptions)) |
| 1762 { |
| 1763 return; |
| 1764 } |
| 1765 for (var _loopIndex16 = 0; _loopIndex16 < subscription.filters.length; ++_lo
opIndex16) |
| 1766 { |
| 1767 var filter = subscription.filters[_loopIndex16]; |
| 1768 var i = filter.subscriptions.indexOf(subscription); |
| 1769 if (i >= 0) |
| 1770 { |
| 1771 filter.subscriptions.splice(i, 1); |
| 1772 } |
| 1773 } |
| 1774 } |
| 1775 var PrivateBrowsing = exports.PrivateBrowsing = |
| 1776 { |
| 1777 enabled: false, |
| 1778 init: function() |
| 1779 { |
| 1780 if ("@mozilla.org/privatebrowsing;1" in Cc) |
| 1781 { |
| 1782 try |
| 1783 { |
| 1784 this.enabled = Cc["@mozilla.org/privatebrowsing;1"].getService(Ci.nsIP
rivateBrowsingService).privateBrowsingEnabled; |
| 1785 Services.obs.addObserver(this, "private-browsing", true); |
| 1786 onShutdown.add(function() |
| 1787 { |
| 1788 Services.obs.removeObserver(this, "private-browsing"); |
| 1789 }.bind(this)); |
| 1790 } |
| 1791 catch (e) |
| 1792 { |
| 1793 Cu.reportError(e); |
| 1794 } |
| 1795 } |
| 1796 }, |
| 1797 observe: function(subject, topic, data) |
| 1798 { |
| 1799 if (topic == "private-browsing") |
| 1800 { |
| 1801 if (data == "enter") |
| 1802 { |
| 1803 this.enabled = true; |
| 1804 } |
| 1805 else if (data == "exit") |
| 1806 { |
| 1807 this.enabled = false; |
| 1808 } |
| 1809 } |
| 1810 }, |
| 1811 QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIOb
server]) |
| 1812 }; |
| 1813 PrivateBrowsing.init(); |
| 1814 |
| 1815 function INIParser() |
| 1816 { |
| 1817 this.fileProperties = this.curObj = {}; |
| 1818 this.subscriptions = []; |
| 1819 this.knownFilters = |
| 1820 { |
| 1821 __proto__: null |
| 1822 }; |
| 1823 this.knownSubscriptions = |
| 1824 { |
| 1825 __proto__: null |
| 1826 }; |
| 1827 } |
| 1828 INIParser.prototype = |
| 1829 { |
| 1830 subscriptions: null, |
| 1831 knownFilters: null, |
| 1832 knownSubscrptions: null, |
| 1833 wantObj: true, |
| 1834 fileProperties: null, |
| 1835 curObj: null, |
| 1836 curSection: null, |
| 1837 userFilters: null, |
| 1838 process: function(val) |
| 1839 { |
| 1840 var origKnownFilters = Filter.knownFilters; |
| 1841 Filter.knownFilters = this.knownFilters; |
| 1842 var origKnownSubscriptions = Subscription.knownSubscriptions; |
| 1843 Subscription.knownSubscriptions = this.knownSubscriptions; |
| 1844 var match; |
| 1845 try |
| 1846 { |
| 1847 if (this.wantObj === true && (match = /^(\w+)=(.*)$/.exec(val))) |
| 1848 { |
| 1849 this.curObj[match[1]] = match[2]; |
| 1850 } |
| 1851 else if (val === null || (match = /^\s*\[(.+)\]\s*$/.exec(val))) |
| 1852 { |
| 1853 if (this.curObj) |
| 1854 { |
| 1855 switch (this.curSection) |
| 1856 { |
| 1857 case "filter": |
| 1858 case "pattern": |
| 1859 if ("text" in this.curObj) |
| 1860 { |
| 1861 Filter.fromObject(this.curObj); |
| 1862 } |
| 1863 break; |
| 1864 case "subscription": |
| 1865 var subscription = Subscription.fromObject(this.curObj); |
| 1866 if (subscription) |
| 1867 { |
| 1868 this.subscriptions.push(subscription); |
| 1869 } |
| 1870 break; |
| 1871 case "subscription filters": |
| 1872 case "subscription patterns": |
| 1873 if (this.subscriptions.length) |
| 1874 { |
| 1875 var subscription = this.subscriptions[this.subscriptions.length
- 1]; |
| 1876 for (var _loopIndex17 = 0; _loopIndex17 < this.curObj.length; ++
_loopIndex17) |
| 1877 { |
| 1878 var text = this.curObj[_loopIndex17]; |
| 1879 var filter = Filter.fromText(text); |
| 1880 subscription.filters.push(filter); |
| 1881 filter.subscriptions.push(subscription); |
| 1882 } |
| 1883 } |
| 1884 break; |
| 1885 case "user patterns": |
| 1886 this.userFilters = this.curObj; |
| 1887 break; |
| 1888 } |
| 1889 } |
| 1890 if (val === null) |
| 1891 { |
| 1892 return; |
| 1893 } |
| 1894 this.curSection = match[1].toLowerCase(); |
| 1895 switch (this.curSection) |
| 1896 { |
| 1897 case "filter": |
| 1898 case "pattern": |
| 1899 case "subscription": |
| 1900 this.wantObj = true; |
| 1901 this.curObj = {}; |
| 1902 break; |
| 1903 case "subscription filters": |
| 1904 case "subscription patterns": |
| 1905 case "user patterns": |
| 1906 this.wantObj = false; |
| 1907 this.curObj = []; |
| 1908 break; |
| 1909 default: |
| 1910 this.wantObj = undefined; |
| 1911 this.curObj = null; |
| 1912 } |
| 1913 } |
| 1914 else if (this.wantObj === false && val) |
| 1915 { |
| 1916 this.curObj.push(val.replace(/\\\[/g, "[")); |
| 1917 } |
| 1918 } |
| 1919 finally |
| 1920 { |
| 1921 Filter.knownFilters = origKnownFilters; |
| 1922 Subscription.knownSubscriptions = origKnownSubscriptions; |
| 1923 } |
| 1924 } |
| 1925 }; |
| 1926 return exports; |
| 1927 })(); |
| 1928 require.scopes["elemHide"] = (function() |
| 1929 { |
| 1930 var exports = {}; |
| 1931 var Utils = require("utils").Utils; |
| 1932 var IO = require("io").IO; |
| 1933 var Prefs = require("prefs").Prefs; |
| 1934 var ElemHideException = require("filterClasses").ElemHideException; |
| 1935 var FilterNotifier = require("filterNotifier").FilterNotifier; |
| 1936 var AboutHandler = require("elemHideHitRegistration").AboutHandler; |
| 1937 var filterByKey = |
| 1938 { |
| 1939 __proto__: null |
| 1940 }; |
| 1941 var keyByFilter = |
| 1942 { |
| 1943 __proto__: null |
| 1944 }; |
| 1945 var knownExceptions = |
| 1946 { |
| 1947 __proto__: null |
| 1948 }; |
| 1949 var exceptions = |
| 1950 { |
| 1951 __proto__: null |
| 1952 }; |
| 1953 var styleURL = null; |
| 1954 var ElemHide = exports.ElemHide = |
| 1955 { |
| 1956 isDirty: false, |
| 1957 applied: false, |
| 1958 init: function() |
| 1959 { |
| 1960 Prefs.addListener(function(name) |
| 1961 { |
| 1962 if (name == "enabled") |
| 1963 { |
| 1964 ElemHide.apply(); |
| 1965 } |
| 1966 }); |
| 1967 onShutdown.add(function() |
| 1968 { |
| 1969 ElemHide.unapply(); |
| 1970 }); |
| 1971 var styleFile = IO.resolveFilePath(Prefs.data_directory); |
| 1972 styleFile.append("elemhide.css"); |
| 1973 styleURL = Services.io.newFileURI(styleFile).QueryInterface(Ci.nsIFileURL)
; |
| 1974 }, |
| 1975 clear: function() |
| 1976 { |
| 1977 filterByKey = |
| 1978 { |
| 1979 __proto__: null |
| 1980 }; |
| 1981 keyByFilter = |
| 1982 { |
| 1983 __proto__: null |
| 1984 }; |
| 1985 knownExceptions = |
| 1986 { |
| 1987 __proto__: null |
| 1988 }; |
| 1989 exceptions = |
| 1990 { |
| 1991 __proto__: null |
| 1992 }; |
| 1993 ElemHide.isDirty = false; |
| 1994 ElemHide.unapply(); |
| 1995 }, |
| 1996 add: function(filter) |
| 1997 { |
| 1998 if (filter instanceof ElemHideException) |
| 1999 { |
| 2000 if (filter.text in knownExceptions) |
| 2001 { |
| 2002 return; |
| 2003 } |
| 2004 var selector = filter.selector; |
| 2005 if (!(selector in exceptions)) |
| 2006 { |
| 2007 exceptions[selector] = []; |
| 2008 } |
| 2009 exceptions[selector].push(filter); |
| 2010 knownExceptions[filter.text] = true; |
| 2011 } |
| 2012 else |
| 2013 { |
| 2014 if (filter.text in keyByFilter) |
| 2015 { |
| 2016 return; |
| 2017 } |
| 2018 var key; |
| 2019 do |
| 2020 { |
| 2021 key = Math.random().toFixed(15).substr(5); |
| 2022 } |
| 2023 while (key in filterByKey); |
| 2024 filterByKey[key] = filter; |
| 2025 keyByFilter[filter.text] = key; |
| 2026 ElemHide.isDirty = true; |
| 2027 } |
| 2028 }, |
| 2029 remove: function(filter) |
| 2030 { |
| 2031 if (filter instanceof ElemHideException) |
| 2032 { |
| 2033 if (!(filter.text in knownExceptions)) |
| 2034 { |
| 2035 return; |
| 2036 } |
| 2037 var list = exceptions[filter.selector]; |
| 2038 var index = list.indexOf(filter); |
| 2039 if (index >= 0) |
| 2040 { |
| 2041 list.splice(index, 1); |
| 2042 } |
| 2043 delete knownExceptions[filter.text]; |
| 2044 } |
| 2045 else |
| 2046 { |
| 2047 if (!(filter.text in keyByFilter)) |
| 2048 { |
| 2049 return; |
| 2050 } |
| 2051 var key = keyByFilter[filter.text]; |
| 2052 delete filterByKey[key]; |
| 2053 delete keyByFilter[filter.text]; |
| 2054 ElemHide.isDirty = true; |
| 2055 } |
| 2056 }, |
| 2057 getException: function(filter, docDomain) |
| 2058 { |
| 2059 var selector = filter.selector; |
| 2060 if (!(filter.selector in exceptions)) |
| 2061 { |
| 2062 return null; |
| 2063 } |
| 2064 var list = exceptions[filter.selector]; |
| 2065 for (var i = list.length - 1; i >= 0; i--) |
| 2066 { |
| 2067 if (list[i].isActiveOnDomain(docDomain)) |
| 2068 { |
| 2069 return list[i]; |
| 2070 } |
| 2071 } |
| 2072 return null; |
| 2073 }, |
| 2074 _applying: false, |
| 2075 _needsApply: false, |
| 2076 apply: function() |
| 2077 { |
| 2078 if (this._applying) |
| 2079 { |
| 2080 this._needsApply = true; |
| 2081 return; |
| 2082 } |
| 2083 if (!ElemHide.isDirty || !Prefs.enabled) |
| 2084 { |
| 2085 if (Prefs.enabled && !ElemHide.applied) |
| 2086 { |
| 2087 try |
| 2088 { |
| 2089 Utils.styleService.loadAndRegisterSheet(styleURL, Ci.nsIStyleSheetSe
rvice.USER_SHEET); |
| 2090 ElemHide.applied = true; |
| 2091 } |
| 2092 catch (e) |
| 2093 { |
| 2094 Cu.reportError(e); |
| 2095 } |
| 2096 } |
| 2097 else if (!Prefs.enabled && ElemHide.applied) |
| 2098 { |
| 2099 ElemHide.unapply(); |
| 2100 } |
| 2101 return; |
| 2102 } |
| 2103 IO.writeToFile(styleURL.file, false, this._generateCSSContent(), function(
e) |
| 2104 { |
| 2105 this._applying = false; |
| 2106 if (e && e.result == Cr.NS_ERROR_NOT_AVAILABLE) |
| 2107 { |
| 2108 IO.removeFile(styleURL.file, function(e2){}); |
| 2109 } |
| 2110 else if (e) |
| 2111 { |
| 2112 Cu.reportError(e); |
| 2113 } |
| 2114 if (this._needsApply) |
| 2115 { |
| 2116 this._needsApply = false; |
| 2117 this.apply(); |
| 2118 } |
| 2119 else if (!e || e.result == Cr.NS_ERROR_NOT_AVAILABLE) |
| 2120 { |
| 2121 ElemHide.isDirty = false; |
| 2122 ElemHide.unapply(); |
| 2123 if (!e) |
| 2124 { |
| 2125 try |
| 2126 { |
| 2127 Utils.styleService.loadAndRegisterSheet(styleURL, Ci.nsIStyleSheet
Service.USER_SHEET); |
| 2128 ElemHide.applied = true; |
| 2129 } |
| 2130 catch (e) |
| 2131 { |
| 2132 Cu.reportError(e); |
| 2133 } |
| 2134 } |
| 2135 FilterNotifier.triggerListeners("elemhideupdate"); |
| 2136 } |
| 2137 }.bind(this), "ElemHideWrite"); |
| 2138 this._applying = true; |
| 2139 }, |
| 2140 _generateCSSContent: function() |
| 2141 { |
| 2142 var _generatorResult12 = []; |
| 2143 var domains = |
| 2144 { |
| 2145 __proto__: null |
| 2146 }; |
| 2147 var hasFilters = false; |
| 2148 for (var key in filterByKey) |
| 2149 { |
| 2150 var filter = filterByKey[key]; |
| 2151 var domain = filter.selectorDomain || ""; |
| 2152 var list; |
| 2153 if (domain in domains) |
| 2154 { |
| 2155 list = domains[domain]; |
| 2156 } |
| 2157 else |
| 2158 { |
| 2159 list = |
| 2160 { |
| 2161 __proto__: null |
| 2162 }; |
| 2163 domains[domain] = list; |
| 2164 } |
| 2165 list[filter.selector] = key; |
| 2166 hasFilters = true; |
| 2167 } |
| 2168 if (!hasFilters) |
| 2169 { |
| 2170 throw Cr.NS_ERROR_NOT_AVAILABLE; |
| 2171 } |
| 2172 |
| 2173 function escapeChar(match) |
| 2174 { |
| 2175 return "\\" + match.charCodeAt(0).toString(16) + " "; |
| 2176 } |
| 2177 var cssTemplate = "-moz-binding: url(about:" + AboutHandler.aboutPrefix +
"?%ID%#dummy) !important;"; |
| 2178 for (var domain in domains) |
| 2179 { |
| 2180 var rules = []; |
| 2181 var list = domains[domain]; |
| 2182 if (domain) |
| 2183 { |
| 2184 _generatorResult12.push(("@-moz-document domain(\"" + domain.split(","
).join("\"),domain(\"") + "\"){").replace(/[^\x01-\x7F]/g, escapeChar)); |
| 2185 } |
| 2186 else |
| 2187 { |
| 2188 _generatorResult12.push("@-moz-document url-prefix(\"http://\"),url-pr
efix(\"https://\"),url-prefix(\"mailbox://\"),url-prefix(\"imap://\"),url-prefix
(\"news://\"),url-prefix(\"snews://\"){"); |
| 2189 } |
| 2190 for (var selector in list) |
| 2191 { |
| 2192 _generatorResult12.push(selector.replace(/[^\x01-\x7F]/g, escapeChar)
+ "{" + cssTemplate.replace("%ID%", list[selector]) + "}"); |
| 2193 } |
| 2194 _generatorResult12.push("}"); |
| 2195 } |
| 2196 return _generatorResult12; |
| 2197 }, |
| 2198 unapply: function() |
| 2199 { |
| 2200 if (ElemHide.applied) |
| 2201 { |
| 2202 try |
| 2203 { |
| 2204 Utils.styleService.unregisterSheet(styleURL, Ci.nsIStyleSheetService.U
SER_SHEET); |
| 2205 } |
| 2206 catch (e) |
| 2207 { |
| 2208 Cu.reportError(e); |
| 2209 } |
| 2210 ElemHide.applied = false; |
| 2211 } |
| 2212 }, |
| 2213 get styleURL() |
| 2214 { |
| 2215 return ElemHide.applied ? styleURL.spec : null; |
| 2216 }, |
| 2217 getFilterByKey: function(key) |
| 2218 { |
| 2219 return key in filterByKey ? filterByKey[key] : null; |
| 2220 }, |
| 2221 getSelectorsForDomain: function(domain, specificOnly) |
| 2222 { |
| 2223 var result = []; |
| 2224 for (var key in filterByKey) |
| 2225 { |
| 2226 var filter = filterByKey[key]; |
| 2227 if (specificOnly && (!filter.domains || filter.domains[""])) |
| 2228 { |
| 2229 continue; |
| 2230 } |
| 2231 if (filter.isActiveOnDomain(domain) && !this.getException(filter, domain
)) |
| 2232 { |
| 2233 result.push(filter.selector); |
| 2234 } |
| 2235 } |
| 2236 return result; |
| 2237 } |
| 2238 }; |
| 2239 return exports; |
| 2240 })(); |
| 2241 require.scopes["filterListener"] = (function() |
| 2242 { |
| 2243 var exports = {}; |
| 2244 var FilterStorage = require("filterStorage").FilterStorage; |
| 2245 var FilterNotifier = require("filterNotifier").FilterNotifier; |
| 2246 var ElemHide = require("elemHide").ElemHide; |
| 2247 var defaultMatcher = require("matcher").defaultMatcher; |
| 2248 var _tempVar18 = require("filterClasses"); |
| 2249 var ActiveFilter = _tempVar18.ActiveFilter; |
| 2250 var RegExpFilter = _tempVar18.RegExpFilter; |
| 2251 var ElemHideBase = _tempVar18.ElemHideBase; |
| 2252 var Prefs = require("prefs").Prefs; |
| 2253 var batchMode = false; |
| 2254 var isDirty = 0; |
| 2255 var FilterListener = exports.FilterListener = |
| 2256 { |
| 2257 get batchMode() |
| 2258 { |
| 2259 return batchMode; |
| 2260 }, |
| 2261 set batchMode(value) |
| 2262 { |
| 2263 batchMode = value; |
| 2264 flushElemHide(); |
| 2265 }, |
| 2266 setDirty: function(factor) |
| 2267 { |
| 2268 if (factor == 0 && isDirty > 0) |
| 2269 { |
| 2270 isDirty = 1; |
| 2271 } |
| 2272 else |
| 2273 { |
| 2274 isDirty += factor; |
| 2275 } |
| 2276 if (isDirty >= 1) |
| 2277 { |
| 2278 FilterStorage.saveToDisk(); |
| 2279 } |
| 2280 } |
| 2281 }; |
| 2282 var HistoryPurgeObserver = |
| 2283 { |
| 2284 observe: function(subject, topic, data) |
| 2285 { |
| 2286 if (topic == "browser:purge-session-history" && Prefs.clearStatsOnHistoryP
urge) |
| 2287 { |
| 2288 FilterStorage.resetHitCounts(); |
| 2289 FilterListener.setDirty(0); |
| 2290 Prefs.recentReports = []; |
| 2291 } |
| 2292 }, |
| 2293 QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIOb
server]) |
| 2294 }; |
| 2295 |
| 2296 function init() |
| 2297 { |
| 2298 FilterNotifier.addListener(function(action, item, newValue, oldValue) |
| 2299 { |
| 2300 var match = /^(\w+)\.(.*)/.exec(action); |
| 2301 if (match && match[1] == "filter") |
| 2302 { |
| 2303 onFilterChange(match[2], item, newValue, oldValue); |
| 2304 } |
| 2305 else if (match && match[1] == "subscription") |
| 2306 { |
| 2307 onSubscriptionChange(match[2], item, newValue, oldValue); |
| 2308 } |
| 2309 else |
| 2310 { |
| 2311 onGenericChange(action, item); |
| 2312 } |
| 2313 }); |
| 2314 var application = require("info").application; |
| 2315 if (application == "chrome" || application == "opera") |
| 2316 { |
| 2317 flushElemHide = function(){}; |
| 2318 } |
| 2319 else |
| 2320 { |
| 2321 ElemHide.init(); |
| 2322 } |
| 2323 FilterStorage.loadFromDisk(); |
| 2324 Services.obs.addObserver(HistoryPurgeObserver, "browser:purge-session-histor
y", true); |
| 2325 onShutdown.add(function() |
| 2326 { |
| 2327 Services.obs.removeObserver(HistoryPurgeObserver, "browser:purge-session-h
istory"); |
| 2328 }); |
| 2329 } |
| 2330 init(); |
| 2331 |
| 2332 function flushElemHide() |
| 2333 { |
| 2334 if (!batchMode && ElemHide.isDirty) |
| 2335 { |
| 2336 ElemHide.apply(); |
| 2337 } |
| 2338 } |
| 2339 |
| 2340 function addFilter(filter) |
| 2341 { |
| 2342 if (!(filter instanceof ActiveFilter) || filter.disabled) |
| 2343 { |
| 2344 return; |
| 2345 } |
| 2346 var hasEnabled = false; |
| 2347 for (var i = 0; i < filter.subscriptions.length; i++) |
| 2348 { |
| 2349 if (!filter.subscriptions[i].disabled) |
| 2350 { |
| 2351 hasEnabled = true; |
| 2352 } |
| 2353 } |
| 2354 if (!hasEnabled) |
| 2355 { |
| 2356 return; |
| 2357 } |
| 2358 if (filter instanceof RegExpFilter) |
| 2359 { |
| 2360 defaultMatcher.add(filter); |
| 2361 } |
| 2362 else if (filter instanceof ElemHideBase) |
| 2363 { |
| 2364 ElemHide.add(filter); |
| 2365 } |
| 2366 } |
| 2367 |
| 2368 function removeFilter(filter) |
| 2369 { |
| 2370 if (!(filter instanceof ActiveFilter)) |
| 2371 { |
| 2372 return; |
| 2373 } |
| 2374 if (!filter.disabled) |
| 2375 { |
| 2376 var hasEnabled = false; |
| 2377 for (var i = 0; i < filter.subscriptions.length; i++) |
| 2378 { |
| 2379 if (!filter.subscriptions[i].disabled) |
| 2380 { |
| 2381 hasEnabled = true; |
| 2382 } |
| 2383 } |
| 2384 if (hasEnabled) |
| 2385 { |
| 2386 return; |
| 2387 } |
| 2388 } |
| 2389 if (filter instanceof RegExpFilter) |
| 2390 { |
| 2391 defaultMatcher.remove(filter); |
| 2392 } |
| 2393 else if (filter instanceof ElemHideBase) |
| 2394 { |
| 2395 ElemHide.remove(filter); |
| 2396 } |
| 2397 } |
| 2398 |
| 2399 function onSubscriptionChange(action, subscription, newValue, oldValue) |
| 2400 { |
| 2401 FilterListener.setDirty(1); |
| 2402 if (action != "added" && action != "removed" && action != "disabled" && acti
on != "updated") |
| 2403 { |
| 2404 return; |
| 2405 } |
| 2406 if (action != "removed" && !(subscription.url in FilterStorage.knownSubscrip
tions)) |
| 2407 { |
| 2408 return; |
| 2409 } |
| 2410 if ((action == "added" || action == "removed" || action == "updated") && sub
scription.disabled) |
| 2411 { |
| 2412 return; |
| 2413 } |
| 2414 if (action == "added" || action == "removed" || action == "disabled") |
| 2415 { |
| 2416 var method = action == "added" || action == "disabled" && newValue == fals
e ? addFilter : removeFilter; |
| 2417 if (subscription.filters) |
| 2418 { |
| 2419 subscription.filters.forEach(method); |
| 2420 } |
| 2421 } |
| 2422 else if (action == "updated") |
| 2423 { |
| 2424 subscription.oldFilters.forEach(removeFilter); |
| 2425 subscription.filters.forEach(addFilter); |
| 2426 } |
| 2427 flushElemHide(); |
| 2428 } |
| 2429 |
| 2430 function onFilterChange(action, filter, newValue, oldValue) |
| 2431 { |
| 2432 if (action == "hitCount" || action == "lastHit") |
| 2433 { |
| 2434 FilterListener.setDirty(0.002); |
| 2435 } |
| 2436 else |
| 2437 { |
| 2438 FilterListener.setDirty(1); |
| 2439 } |
| 2440 if (action != "added" && action != "removed" && action != "disabled") |
| 2441 { |
| 2442 return; |
| 2443 } |
| 2444 if ((action == "added" || action == "removed") && filter.disabled) |
| 2445 { |
| 2446 return; |
| 2447 } |
| 2448 if (action == "added" || action == "disabled" && newValue == false) |
| 2449 { |
| 2450 addFilter(filter); |
| 2451 } |
| 2452 else |
| 2453 { |
| 2454 removeFilter(filter); |
| 2455 } |
| 2456 flushElemHide(); |
| 2457 } |
| 2458 |
| 2459 function onGenericChange(action) |
| 2460 { |
| 2461 if (action == "load") |
| 2462 { |
| 2463 isDirty = 0; |
| 2464 defaultMatcher.clear(); |
| 2465 ElemHide.clear(); |
| 2466 for (var _loopIndex19 = 0; _loopIndex19 < FilterStorage.subscriptions.leng
th; ++_loopIndex19) |
| 2467 { |
| 2468 var subscription = FilterStorage.subscriptions[_loopIndex19]; |
| 2469 if (!subscription.disabled) |
| 2470 { |
| 2471 subscription.filters.forEach(addFilter); |
| 2472 } |
| 2473 } |
| 2474 flushElemHide(); |
| 2475 } |
| 2476 else if (action == "save") |
| 2477 { |
| 2478 isDirty = 0; |
| 2479 } |
| 2480 } |
| 2481 return exports; |
| 2482 })(); |
| 2483 require.scopes["synchronizer"] = (function() |
| 2484 { |
| 2485 var exports = {}; |
| 2486 var Utils = require("utils").Utils; |
| 2487 var FilterStorage = require("filterStorage").FilterStorage; |
| 2488 var FilterNotifier = require("filterNotifier").FilterNotifier; |
| 2489 var Prefs = require("prefs").Prefs; |
| 2490 var _tempVar20 = require("filterClasses"); |
| 2491 var Filter = _tempVar20.Filter; |
| 2492 var CommentFilter = _tempVar20.CommentFilter; |
| 2493 var _tempVar21 = require("subscriptionClasses"); |
| 2494 var Subscription = _tempVar21.Subscription; |
| 2495 var DownloadableSubscription = _tempVar21.DownloadableSubscription; |
| 2496 var MILLISECONDS_IN_SECOND = 1000; |
| 2497 var SECONDS_IN_MINUTE = 60; |
| 2498 var SECONDS_IN_HOUR = 60 * SECONDS_IN_MINUTE; |
| 2499 var SECONDS_IN_DAY = 24 * SECONDS_IN_HOUR; |
| 2500 var INITIAL_DELAY = 6 * SECONDS_IN_MINUTE; |
| 2501 var CHECK_INTERVAL = SECONDS_IN_HOUR; |
| 2502 var MIN_EXPIRATION_INTERVAL = 1 * SECONDS_IN_DAY; |
| 2503 var MAX_EXPIRATION_INTERVAL = 14 * SECONDS_IN_DAY; |
| 2504 var MAX_ABSENSE_INTERVAL = 1 * SECONDS_IN_DAY; |
| 2505 var timer = null; |
| 2506 var executing = |
| 2507 { |
| 2508 __proto__: null |
| 2509 }; |
| 2510 var Synchronizer = exports.Synchronizer = |
| 2511 { |
| 2512 init: function() |
| 2513 { |
| 2514 var callback = function() |
| 2515 { |
| 2516 timer.delay = CHECK_INTERVAL * MILLISECONDS_IN_SECOND; |
| 2517 checkSubscriptions(); |
| 2518 }; |
| 2519 timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); |
| 2520 timer.initWithCallback(callback, INITIAL_DELAY * MILLISECONDS_IN_SECOND, C
i.nsITimer.TYPE_REPEATING_SLACK); |
| 2521 onShutdown.add(function() |
| 2522 { |
| 2523 timer.cancel(); |
| 2524 }); |
| 2525 }, |
| 2526 isExecuting: function(url) |
| 2527 { |
| 2528 return url in executing; |
| 2529 }, |
| 2530 execute: function(subscription, manual, forceDownload) |
| 2531 { |
| 2532 Utils.runAsync(this.executeInternal, this, subscription, manual, forceDown
load); |
| 2533 }, |
| 2534 executeInternal: function(subscription, manual, forceDownload) |
| 2535 { |
| 2536 var url = subscription.url; |
| 2537 if (url in executing) |
| 2538 { |
| 2539 return; |
| 2540 } |
| 2541 var newURL = subscription.nextURL; |
| 2542 var hadTemporaryRedirect = false; |
| 2543 subscription.nextURL = null; |
| 2544 var loadFrom = newURL; |
| 2545 var isBaseLocation = true; |
| 2546 if (!loadFrom) |
| 2547 { |
| 2548 loadFrom = url; |
| 2549 } |
| 2550 if (loadFrom == url) |
| 2551 { |
| 2552 if (subscription.alternativeLocations) |
| 2553 { |
| 2554 var options = [ |
| 2555 [1, url] |
| 2556 ]; |
| 2557 var totalWeight = 1; |
| 2558 for (var _loopIndex22 = 0; _loopIndex22 < subscription.alternativeLoca
tions.split(",").length; ++_loopIndex22) |
| 2559 { |
| 2560 var alternative = subscription.alternativeLocations.split(",")[_loop
Index22]; |
| 2561 if (!/^https?:\/\//.test(alternative)) |
| 2562 { |
| 2563 continue; |
| 2564 } |
| 2565 var weight = 1; |
| 2566 var match = /;q=([\d\.]+)$/.exec(alternative); |
| 2567 if (match) |
| 2568 { |
| 2569 weight = parseFloat(match[1]); |
| 2570 if (isNaN(weight) || !isFinite(weight) || weight < 0) |
| 2571 { |
| 2572 weight = 1; |
| 2573 } |
| 2574 if (weight > 10) |
| 2575 { |
| 2576 weight = 10; |
| 2577 } |
| 2578 alternative = alternative.substr(0, match.index); |
| 2579 } |
| 2580 options.push([weight, alternative]); |
| 2581 totalWeight += weight; |
| 2582 } |
| 2583 var choice = Math.random() * totalWeight; |
| 2584 for (var _loopIndex23 = 0; _loopIndex23 < options.length; ++_loopIndex
23) |
| 2585 { |
| 2586 var _tempVar24 = options[_loopIndex23]; |
| 2587 var weight = _tempVar24[0]; |
| 2588 var alternative = _tempVar24[1]; |
| 2589 choice -= weight; |
| 2590 if (choice < 0) |
| 2591 { |
| 2592 loadFrom = alternative; |
| 2593 break; |
| 2594 } |
| 2595 } |
| 2596 isBaseLocation = loadFrom == url; |
| 2597 } |
| 2598 } |
| 2599 else |
| 2600 { |
| 2601 forceDownload = true; |
| 2602 } |
| 2603 var addonVersion = require("info").addonVersion; |
| 2604 loadFrom = loadFrom.replace(/%VERSION%/, "ABP" + addonVersion); |
| 2605 var request = null; |
| 2606 |
| 2607 function errorCallback(error) |
| 2608 { |
| 2609 var channelStatus = -1; |
| 2610 try |
| 2611 { |
| 2612 channelStatus = request.channel.status; |
| 2613 } |
| 2614 catch (e){} |
| 2615 var responseStatus = ""; |
| 2616 try |
| 2617 { |
| 2618 responseStatus = request.channel.QueryInterface(Ci.nsIHttpChannel).res
ponseStatus; |
| 2619 } |
| 2620 catch (e){} |
| 2621 setError(subscription, error, channelStatus, responseStatus, loadFrom, i
sBaseLocation, manual); |
| 2622 } |
| 2623 try |
| 2624 { |
| 2625 request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(C
i.nsIXMLHttpRequest); |
| 2626 request.mozBackgroundRequest = true; |
| 2627 request.open("GET", loadFrom); |
| 2628 } |
| 2629 catch (e) |
| 2630 { |
| 2631 errorCallback("synchronize_invalid_url"); |
| 2632 return; |
| 2633 } |
| 2634 try |
| 2635 { |
| 2636 request.overrideMimeType("text/plain"); |
| 2637 request.channel.loadFlags = request.channel.loadFlags | request.channel.
INHIBIT_CACHING | request.channel.VALIDATE_ALWAYS; |
| 2638 if (request.channel instanceof Ci.nsIHttpChannel) |
| 2639 { |
| 2640 request.channel.redirectionLimit = 5; |
| 2641 } |
| 2642 var oldNotifications = request.channel.notificationCallbacks; |
| 2643 var oldEventSink = null; |
| 2644 request.channel.notificationCallbacks = |
| 2645 { |
| 2646 QueryInterface: XPCOMUtils.generateQI([Ci.nsIInterfaceRequestor, Ci.ns
IChannelEventSink]), |
| 2647 getInterface: function(iid) |
| 2648 { |
| 2649 if (iid.equals(Ci.nsIChannelEventSink)) |
| 2650 { |
| 2651 try |
| 2652 { |
| 2653 oldEventSink = oldNotifications.QueryInterface(iid); |
| 2654 } |
| 2655 catch (e){} |
| 2656 return this; |
| 2657 } |
| 2658 if (oldNotifications) |
| 2659 { |
| 2660 return oldNotifications.QueryInterface(iid); |
| 2661 } |
| 2662 else |
| 2663 { |
| 2664 throw Cr.NS_ERROR_NO_INTERFACE; |
| 2665 } |
| 2666 }, |
| 2667 asyncOnChannelRedirect: function(oldChannel, newChannel, flags, callba
ck) |
| 2668 { |
| 2669 if (isBaseLocation && !hadTemporaryRedirect && oldChannel instanceof
Ci.nsIHttpChannel) |
| 2670 { |
| 2671 try |
| 2672 { |
| 2673 subscription.alternativeLocations = oldChannel.getResponseHeader
("X-Alternative-Locations"); |
| 2674 } |
| 2675 catch (e) |
| 2676 { |
| 2677 subscription.alternativeLocations = null; |
| 2678 } |
| 2679 } |
| 2680 if (flags & Ci.nsIChannelEventSink.REDIRECT_TEMPORARY) |
| 2681 { |
| 2682 hadTemporaryRedirect = true; |
| 2683 } |
| 2684 else if (!hadTemporaryRedirect) |
| 2685 { |
| 2686 newURL = newChannel.URI.spec; |
| 2687 } |
| 2688 if (oldEventSink) |
| 2689 { |
| 2690 oldEventSink.asyncOnChannelRedirect(oldChannel, newChannel, flags,
callback); |
| 2691 } |
| 2692 else |
| 2693 { |
| 2694 callback.onRedirectVerifyCallback(Cr.NS_OK); |
| 2695 } |
| 2696 } |
| 2697 }; |
| 2698 } |
| 2699 catch (e) |
| 2700 { |
| 2701 Cu.reportError(e); |
| 2702 } |
| 2703 if (subscription.lastModified && !forceDownload) |
| 2704 { |
| 2705 request.setRequestHeader("If-Modified-Since", subscription.lastModified)
; |
| 2706 } |
| 2707 request.addEventListener("error", function(ev) |
| 2708 { |
| 2709 if (onShutdown.done) |
| 2710 { |
| 2711 return; |
| 2712 } |
| 2713 delete executing[url]; |
| 2714 try |
| 2715 { |
| 2716 request.channel.notificationCallbacks = null; |
| 2717 } |
| 2718 catch (e){} |
| 2719 errorCallback("synchronize_connection_error"); |
| 2720 }, false); |
| 2721 request.addEventListener("load", function(ev) |
| 2722 { |
| 2723 if (onShutdown.done) |
| 2724 { |
| 2725 return; |
| 2726 } |
| 2727 delete executing[url]; |
| 2728 try |
| 2729 { |
| 2730 request.channel.notificationCallbacks = null; |
| 2731 } |
| 2732 catch (e){} |
| 2733 if (request.status && request.status != 200 && request.status != 304) |
| 2734 { |
| 2735 errorCallback("synchronize_connection_error"); |
| 2736 return; |
| 2737 } |
| 2738 var newFilters = null; |
| 2739 if (request.status != 304) |
| 2740 { |
| 2741 newFilters = readFilters(subscription, request.responseText, errorCall
back); |
| 2742 if (!newFilters) |
| 2743 { |
| 2744 return; |
| 2745 } |
| 2746 subscription.lastModified = request.getResponseHeader("Last-Modified")
; |
| 2747 } |
| 2748 if (isBaseLocation && !hadTemporaryRedirect) |
| 2749 { |
| 2750 subscription.alternativeLocations = request.getResponseHeader("X-Alter
native-Locations"); |
| 2751 } |
| 2752 subscription.lastSuccess = subscription.lastDownload = Math.round(Date.n
ow() / MILLISECONDS_IN_SECOND); |
| 2753 subscription.downloadStatus = "synchronize_ok"; |
| 2754 subscription.errors = 0; |
| 2755 var now = Math.round(((new Date(request.getResponseHeader("Date"))).getT
ime() || Date.now()) / MILLISECONDS_IN_SECOND); |
| 2756 var expires = Math.round((new Date(request.getResponseHeader("Expires"))
).getTime() / MILLISECONDS_IN_SECOND) || 0; |
| 2757 var expirationInterval = expires ? expires - now : 0; |
| 2758 for (var _loopIndex25 = 0; _loopIndex25 < (newFilters || subscription.fi
lters).length; ++_loopIndex25) |
| 2759 { |
| 2760 var filter = (newFilters || subscription.filters)[_loopIndex25]; |
| 2761 if (!(filter instanceof CommentFilter)) |
| 2762 { |
| 2763 continue; |
| 2764 } |
| 2765 var match = /\bExpires\s*(?::|after)\s*(\d+)\s*(h)?/i.exec(filter.text
); |
| 2766 if (match) |
| 2767 { |
| 2768 var interval = parseInt(match[1], 10); |
| 2769 if (match[2]) |
| 2770 { |
| 2771 interval *= SECONDS_IN_HOUR; |
| 2772 } |
| 2773 else |
| 2774 { |
| 2775 interval *= SECONDS_IN_DAY; |
| 2776 } |
| 2777 if (interval > expirationInterval) |
| 2778 { |
| 2779 expirationInterval = interval; |
| 2780 } |
| 2781 } |
| 2782 } |
| 2783 expirationInterval = Math.min(Math.max(expirationInterval, MIN_EXPIRATIO
N_INTERVAL), MAX_EXPIRATION_INTERVAL); |
| 2784 subscription.expires = subscription.lastDownload + expirationInterval *
2; |
| 2785 subscription.softExpiration = subscription.lastDownload + Math.round(exp
irationInterval * (Math.random() * 0.4 + 0.8)); |
| 2786 if (newFilters) |
| 2787 { |
| 2788 var fixedTitle = false; |
| 2789 for (var i = 0; i < newFilters.length; i++) |
| 2790 { |
| 2791 var filter = newFilters[i]; |
| 2792 if (!(filter instanceof CommentFilter)) |
| 2793 { |
| 2794 continue; |
| 2795 } |
| 2796 var match = /^!\s*(\w+)\s*:\s*(.*)/.exec(filter.text); |
| 2797 if (match) |
| 2798 { |
| 2799 var keyword = match[1].toLowerCase(); |
| 2800 var value = match[2]; |
| 2801 var known = true; |
| 2802 if (keyword == "redirect") |
| 2803 { |
| 2804 if (isBaseLocation && value != url) |
| 2805 { |
| 2806 subscription.nextURL = value; |
| 2807 } |
| 2808 } |
| 2809 else if (keyword == "homepage") |
| 2810 { |
| 2811 var uri = Utils.makeURI(value); |
| 2812 if (uri && (uri.scheme == "http" || uri.scheme == "https")) |
| 2813 { |
| 2814 subscription.homepage = uri.spec; |
| 2815 } |
| 2816 } |
| 2817 else if (keyword == "title") |
| 2818 { |
| 2819 if (value) |
| 2820 { |
| 2821 subscription.title = value; |
| 2822 fixedTitle = true; |
| 2823 } |
| 2824 } |
| 2825 else |
| 2826 { |
| 2827 known = false; |
| 2828 } |
| 2829 if (known) |
| 2830 { |
| 2831 newFilters.splice(i--, 1); |
| 2832 } |
| 2833 } |
| 2834 } |
| 2835 subscription.fixedTitle = fixedTitle; |
| 2836 } |
| 2837 if (isBaseLocation && newURL && newURL != url) |
| 2838 { |
| 2839 var listed = subscription.url in FilterStorage.knownSubscriptions; |
| 2840 if (listed) |
| 2841 { |
| 2842 FilterStorage.removeSubscription(subscription); |
| 2843 } |
| 2844 url = newURL; |
| 2845 var newSubscription = Subscription.fromURL(url); |
| 2846 for (var key in newSubscription) |
| 2847 { |
| 2848 delete newSubscription[key]; |
| 2849 } |
| 2850 for (var key in subscription) |
| 2851 { |
| 2852 newSubscription[key] = subscription[key]; |
| 2853 } |
| 2854 delete Subscription.knownSubscriptions[subscription.url]; |
| 2855 newSubscription.oldSubscription = subscription; |
| 2856 subscription = newSubscription; |
| 2857 subscription.url = url; |
| 2858 if (!(subscription.url in FilterStorage.knownSubscriptions) && listed) |
| 2859 { |
| 2860 FilterStorage.addSubscription(subscription); |
| 2861 } |
| 2862 } |
| 2863 if (newFilters) |
| 2864 { |
| 2865 FilterStorage.updateSubscriptionFilters(subscription, newFilters); |
| 2866 } |
| 2867 delete subscription.oldSubscription; |
| 2868 }, false); |
| 2869 executing[url] = true; |
| 2870 FilterNotifier.triggerListeners("subscription.downloadStatus", subscriptio
n); |
| 2871 try |
| 2872 { |
| 2873 request.send(null); |
| 2874 } |
| 2875 catch (e) |
| 2876 { |
| 2877 delete executing[url]; |
| 2878 errorCallback("synchronize_connection_error"); |
| 2879 return; |
| 2880 } |
| 2881 } |
| 2882 }; |
| 2883 Synchronizer.init(); |
| 2884 |
| 2885 function checkSubscriptions() |
| 2886 { |
| 2887 if (!Prefs.subscriptions_autoupdate) |
| 2888 { |
| 2889 return; |
| 2890 } |
| 2891 var time = Math.round(Date.now() / MILLISECONDS_IN_SECOND); |
| 2892 for (var _loopIndex26 = 0; _loopIndex26 < FilterStorage.subscriptions.length
; ++_loopIndex26) |
| 2893 { |
| 2894 var subscription = FilterStorage.subscriptions[_loopIndex26]; |
| 2895 if (!(subscription instanceof DownloadableSubscription)) |
| 2896 { |
| 2897 continue; |
| 2898 } |
| 2899 if (subscription.lastCheck && time - subscription.lastCheck > MAX_ABSENSE_
INTERVAL) |
| 2900 { |
| 2901 subscription.softExpiration += time - subscription.lastCheck; |
| 2902 } |
| 2903 subscription.lastCheck = time; |
| 2904 if (subscription.expires - time > MAX_EXPIRATION_INTERVAL) |
| 2905 { |
| 2906 subscription.expires = time + MAX_EXPIRATION_INTERVAL; |
| 2907 } |
| 2908 if (subscription.softExpiration - time > MAX_EXPIRATION_INTERVAL) |
| 2909 { |
| 2910 subscription.softExpiration = time + MAX_EXPIRATION_INTERVAL; |
| 2911 } |
| 2912 if (subscription.softExpiration > time && subscription.expires > time) |
| 2913 { |
| 2914 continue; |
| 2915 } |
| 2916 if (time - subscription.lastDownload >= MIN_EXPIRATION_INTERVAL) |
| 2917 { |
| 2918 Synchronizer.execute(subscription, false); |
| 2919 } |
| 2920 } |
| 2921 } |
| 2922 |
| 2923 function readFilters(subscription, text, errorCallback) |
| 2924 { |
| 2925 var lines = text.split(/[\r\n]+/); |
| 2926 var match = /\[Adblock(?:\s*Plus\s*([\d\.]+)?)?\]/i.exec(lines[0]); |
| 2927 if (!match) |
| 2928 { |
| 2929 errorCallback("synchronize_invalid_data"); |
| 2930 return null; |
| 2931 } |
| 2932 var minVersion = match[1]; |
| 2933 for (var i = 0; i < lines.length; i++) |
| 2934 { |
| 2935 var match = /!\s*checksum[\s\-:]+([\w\+\/]+)/i.exec(lines[i]); |
| 2936 if (match) |
| 2937 { |
| 2938 lines.splice(i, 1); |
| 2939 var checksum = Utils.generateChecksum(lines); |
| 2940 if (checksum && checksum != match[1]) |
| 2941 { |
| 2942 errorCallback("synchronize_checksum_mismatch"); |
| 2943 return null; |
| 2944 } |
| 2945 break; |
| 2946 } |
| 2947 } |
| 2948 delete subscription.requiredVersion; |
| 2949 delete subscription.upgradeRequired; |
| 2950 if (minVersion) |
| 2951 { |
| 2952 var addonVersion = require("info").addonVersion; |
| 2953 subscription.requiredVersion = minVersion; |
| 2954 if (Services.vc.compare(minVersion, addonVersion) > 0) |
| 2955 { |
| 2956 subscription.upgradeRequired = true; |
| 2957 } |
| 2958 } |
| 2959 lines.shift(); |
| 2960 var result = []; |
| 2961 for (var _loopIndex27 = 0; _loopIndex27 < lines.length; ++_loopIndex27) |
| 2962 { |
| 2963 var line = lines[_loopIndex27]; |
| 2964 line = Filter.normalize(line); |
| 2965 if (line) |
| 2966 { |
| 2967 result.push(Filter.fromText(line)); |
| 2968 } |
| 2969 } |
| 2970 return result; |
| 2971 } |
| 2972 |
| 2973 function setError(subscription, error, channelStatus, responseStatus, download
URL, isBaseLocation, manual) |
| 2974 { |
| 2975 if (!isBaseLocation) |
| 2976 { |
| 2977 subscription.alternativeLocations = null; |
| 2978 } |
| 2979 try |
| 2980 { |
| 2981 Cu.reportError("Adblock Plus: Downloading filter subscription " + subscrip
tion.title + " failed (" + Utils.getString(error) + ")\n" + "Download address: "
+ downloadURL + "\n" + "Channel status: " + channelStatus + "\n" + "Server resp
onse: " + responseStatus); |
| 2982 } |
| 2983 catch (e){} |
| 2984 subscription.lastDownload = Math.round(Date.now() / MILLISECONDS_IN_SECOND); |
| 2985 subscription.downloadStatus = error; |
| 2986 if (!manual) |
| 2987 { |
| 2988 if (error == "synchronize_checksum_mismatch") |
| 2989 { |
| 2990 subscription.errors = 0; |
| 2991 } |
| 2992 else |
| 2993 { |
| 2994 subscription.errors++; |
| 2995 } |
| 2996 if (subscription.errors >= Prefs.subscriptions_fallbackerrors && /^https?:
\/\//i.test(subscription.url)) |
| 2997 { |
| 2998 subscription.errors = 0; |
| 2999 var fallbackURL = Prefs.subscriptions_fallbackurl; |
| 3000 var addonVersion = require("info").addonVersion; |
| 3001 fallbackURL = fallbackURL.replace(/%VERSION%/g, encodeURIComponent(addon
Version)); |
| 3002 fallbackURL = fallbackURL.replace(/%SUBSCRIPTION%/g, encodeURIComponent(
subscription.url)); |
| 3003 fallbackURL = fallbackURL.replace(/%URL%/g, encodeURIComponent(downloadU
RL)); |
| 3004 fallbackURL = fallbackURL.replace(/%ERROR%/g, encodeURIComponent(error))
; |
| 3005 fallbackURL = fallbackURL.replace(/%CHANNELSTATUS%/g, encodeURIComponent
(channelStatus)); |
| 3006 fallbackURL = fallbackURL.replace(/%RESPONSESTATUS%/g, encodeURIComponen
t(responseStatus)); |
| 3007 var request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstan
ce(Ci.nsIXMLHttpRequest); |
| 3008 request.mozBackgroundRequest = true; |
| 3009 request.open("GET", fallbackURL); |
| 3010 request.overrideMimeType("text/plain"); |
| 3011 request.channel.loadFlags = request.channel.loadFlags | request.channel.
INHIBIT_CACHING | request.channel.VALIDATE_ALWAYS; |
| 3012 request.addEventListener("load", function(ev) |
| 3013 { |
| 3014 if (onShutdown.done) |
| 3015 { |
| 3016 return; |
| 3017 } |
| 3018 if (!(subscription.url in FilterStorage.knownSubscriptions)) |
| 3019 { |
| 3020 return; |
| 3021 } |
| 3022 var match = /^(\d+)(?:\s+(\S+))?$/.exec(request.responseText); |
| 3023 if (match && match[1] == "301" && match[2]) |
| 3024 { |
| 3025 subscription.nextURL = match[2]; |
| 3026 } |
| 3027 else if (match && match[1] == "410") |
| 3028 { |
| 3029 var data = "[Adblock]\n" + subscription.filters.map(function(f) |
| 3030 { |
| 3031 return f.text; |
| 3032 }).join("\n"); |
| 3033 var url = "data:text/plain," + encodeURIComponent(data); |
| 3034 var newSubscription = Subscription.fromURL(url); |
| 3035 newSubscription.title = subscription.title; |
| 3036 newSubscription.disabled = subscription.disabled; |
| 3037 FilterStorage.removeSubscription(subscription); |
| 3038 FilterStorage.addSubscription(newSubscription); |
| 3039 Synchronizer.execute(newSubscription); |
| 3040 } |
| 3041 }, false); |
| 3042 request.send(null); |
| 3043 } |
| 3044 } |
| 3045 } |
| 3046 return exports; |
| 3047 })(); |
OLD | NEW |