├── LICENSE ├── README.md ├── chrome.manifest ├── content ├── kabl-config.js ├── kabl-config.xul ├── kabl-frame.js ├── kabl-inserter.js ├── kabl-lib.js ├── kabl-monitor.js ├── kabl-monitor.xul ├── kabl-overlay.js ├── kabl-overlay.xul ├── kabl-parse.js ├── kabl-policy.js ├── kabl-pref.js └── kabl-sync.js ├── defaults └── preferences │ └── kabl.js ├── install.rdf └── skin ├── blocked.png ├── icon.png ├── kabl-config.css ├── kabl-monitor.css ├── kabl-overlay.css ├── spinner16.gif ├── toolbar-large.png └── toolbar.png /LICENSE: -------------------------------------------------------------------------------- 1 | GNU General Public License 2 | ************************** 3 | 4 | GNU GENERAL PUBLIC LICENSE 5 | Version 2, June 1991 6 | 7 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 8 | 675 Mass Ave, Cambridge, MA 02139, USA 9 | Everyone is permitted to copy and distribute verbatim copies 10 | of this license document, but changing it is not allowed. 11 | 12 | Preamble 13 | 14 | The licenses for most software are designed to take away your 15 | freedom to share and change it. By contrast, the GNU General Public 16 | License is intended to guarantee your freedom to share and change free 17 | software--to make sure the software is free for all its users. This 18 | General Public License applies to most of the Free Software 19 | Foundation's software and to any other program whose authors commit to 20 | using it. (Some other Free Software Foundation software is covered by 21 | the GNU Library General Public License instead.) You can apply it to 22 | your programs, too. 23 | 24 | When we speak of free software, we are referring to freedom, not 25 | price. Our General Public Licenses are designed to make sure that you 26 | have the freedom to distribute copies of free software (and charge for 27 | this service if you wish), that you receive source code or can get it 28 | if you want it, that you can change the software or use pieces of it 29 | in new free programs; and that you know you can do these things. 30 | 31 | To protect your rights, we need to make restrictions that forbid 32 | anyone to deny you these rights or to ask you to surrender the rights. 33 | These restrictions translate to certain responsibilities for you if you 34 | distribute copies of the software, or if you modify it. 35 | 36 | For example, if you distribute copies of such a program, whether 37 | gratis or for a fee, you must give the recipients all the rights that 38 | you have. You must make sure that they, too, receive or can get the 39 | source code. And you must show them these terms so they know their 40 | rights. 41 | 42 | We protect your rights with two steps: (1) copyright the software, and 43 | (2) offer you this license which gives you legal permission to copy, 44 | distribute and/or modify the software. 45 | 46 | Also, for each author's protection and ours, we want to make certain 47 | that everyone understands that there is no warranty for this free 48 | software. If the software is modified by someone else and passed on, we 49 | want its recipients to know that what they have is not the original, so 50 | that any problems introduced by others will not reflect on the original 51 | authors' reputations. 52 | 53 | Finally, any free program is threatened constantly by software 54 | patents. We wish to avoid the danger that redistributors of a free 55 | program will individually obtain patent licenses, in effect making the 56 | program proprietary. To prevent this, we have made it clear that any 57 | patent must be licensed for everyone's free use or not licensed at all. 58 | 59 | The precise terms and conditions for copying, distribution and 60 | modification follow. 61 | 62 | GNU GENERAL PUBLIC LICENSE 63 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 64 | 65 | 0. This License applies to any program or other work which contains 66 | a notice placed by the copyright holder saying it may be distributed 67 | under the terms of this General Public License. The "Program", below, 68 | refers to any such program or work, and a "work based on the Program" 69 | means either the Program or any derivative work under copyright law: 70 | that is to say, a work containing the Program or a portion of it, 71 | either verbatim or with modifications and/or translated into another 72 | language. (Hereinafter, translation is included without limitation in 73 | the term "modification".) Each licensee is addressed as "you". 74 | 75 | Activities other than copying, distribution and modification are not 76 | covered by this License; they are outside its scope. The act of 77 | running the Program is not restricted, and the output from the Program 78 | is covered only if its contents constitute a work based on the 79 | Program (independent of having been made by running the Program). 80 | Whether that is true depends on what the Program does. 81 | 82 | 1. You may copy and distribute verbatim copies of the Program's 83 | source code as you receive it, in any medium, provided that you 84 | conspicuously and appropriately publish on each copy an appropriate 85 | copyright notice and disclaimer of warranty; keep intact all the 86 | notices that refer to this License and to the absence of any warranty; 87 | and give any other recipients of the Program a copy of this License 88 | along with the Program. 89 | 90 | You may charge a fee for the physical act of transferring a copy, and 91 | you may at your option offer warranty protection in exchange for a fee. 92 | 93 | 2. You may modify your copy or copies of the Program or any portion 94 | of it, thus forming a work based on the Program, and copy and 95 | distribute such modifications or work under the terms of Section 1 96 | above, provided that you also meet all of these conditions: 97 | 98 | a) You must cause the modified files to carry prominent notices 99 | stating that you changed the files and the date of any change. 100 | 101 | b) You must cause any work that you distribute or publish, that in 102 | whole or in part contains or is derived from the Program or any 103 | part thereof, to be licensed as a whole at no charge to all third 104 | parties under the terms of this License. 105 | 106 | c) If the modified program normally reads commands interactively 107 | when run, you must cause it, when started running for such 108 | interactive use in the most ordinary way, to print or display an 109 | announcement including an appropriate copyright notice and a 110 | notice that there is no warranty (or else, saying that you provide 111 | a warranty) and that users may redistribute the program under 112 | these conditions, and telling the user how to view a copy of this 113 | License. (Exception: if the Program itself is interactive but 114 | does not normally print such an announcement, your work based on 115 | the Program is not required to print an announcement.) 116 | 117 | These requirements apply to the modified work as a whole. If 118 | identifiable sections of that work are not derived from the Program, 119 | and can be reasonably considered independent and separate works in 120 | themselves, then this License, and its terms, do not apply to those 121 | sections when you distribute them as separate works. But when you 122 | distribute the same sections as part of a whole which is a work based 123 | on the Program, the distribution of the whole must be on the terms of 124 | this License, whose permissions for other licensees extend to the 125 | entire whole, and thus to each and every part regardless of who wrote it. 126 | 127 | Thus, it is not the intent of this section to claim rights or contest 128 | your rights to work written entirely by you; rather, the intent is to 129 | exercise the right to control the distribution of derivative or 130 | collective works based on the Program. 131 | 132 | In addition, mere aggregation of another work not based on the Program 133 | with the Program (or with a work based on the Program) on a volume of 134 | a storage or distribution medium does not bring the other work under 135 | the scope of this License. 136 | 137 | 3. You may copy and distribute the Program (or a work based on it, 138 | under Section 2) in object code or executable form under the terms of 139 | Sections 1 and 2 above provided that you also do one of the following: 140 | 141 | a) Accompany it with the complete corresponding machine-readable 142 | source code, which must be distributed under the terms of Sections 143 | 1 and 2 above on a medium customarily used for software interchange; or, 144 | 145 | b) Accompany it with a written offer, valid for at least three 146 | years, to give any third party, for a charge no more than your 147 | cost of physically performing source distribution, a complete 148 | machine-readable copy of the corresponding source code, to be 149 | distributed under the terms of Sections 1 and 2 above on a medium 150 | customarily used for software interchange; or, 151 | 152 | c) Accompany it with the information you received as to the offer 153 | to distribute corresponding source code. (This alternative is 154 | allowed only for noncommercial distribution and only if you 155 | received the program in object code or executable form with such 156 | an offer, in accord with Subsection b above.) 157 | 158 | The source code for a work means the preferred form of the work for 159 | making modifications to it. For an executable work, complete source 160 | code means all the source code for all modules it contains, plus any 161 | associated interface definition files, plus the scripts used to 162 | control compilation and installation of the executable. However, as a 163 | special exception, the source code distributed need not include 164 | anything that is normally distributed (in either source or binary 165 | form) with the major components (compiler, kernel, and so on) of the 166 | operating system on which the executable runs, unless that component 167 | itself accompanies the executable. 168 | 169 | If distribution of executable or object code is made by offering 170 | access to copy from a designated place, then offering equivalent 171 | access to copy the source code from the same place counts as 172 | distribution of the source code, even though third parties are not 173 | compelled to copy the source along with the object code. 174 | 175 | 4. You may not copy, modify, sublicense, or distribute the Program 176 | except as expressly provided under this License. Any attempt 177 | otherwise to copy, modify, sublicense or distribute the Program is 178 | void, and will automatically terminate your rights under this License. 179 | However, parties who have received copies, or rights, from you under 180 | this License will not have their licenses terminated so long as such 181 | parties remain in full compliance. 182 | 183 | 5. You are not required to accept this License, since you have not 184 | signed it. However, nothing else grants you permission to modify or 185 | distribute the Program or its derivative works. These actions are 186 | prohibited by law if you do not accept this License. Therefore, by 187 | modifying or distributing the Program (or any work based on the 188 | Program), you indicate your acceptance of this License to do so, and 189 | all its terms and conditions for copying, distributing or modifying 190 | the Program or works based on it. 191 | 192 | 6. Each time you redistribute the Program (or any work based on the 193 | Program), the recipient automatically receives a license from the 194 | original licensor to copy, distribute or modify the Program subject to 195 | these terms and conditions. You may not impose any further 196 | restrictions on the recipients' exercise of the rights granted herein. 197 | You are not responsible for enforcing compliance by third parties to 198 | this License. 199 | 200 | 7. If, as a consequence of a court judgment or allegation of patent 201 | infringement or for any other reason (not limited to patent issues), 202 | conditions are imposed on you (whether by court order, agreement or 203 | otherwise) that contradict the conditions of this License, they do not 204 | excuse you from the conditions of this License. If you cannot 205 | distribute so as to satisfy simultaneously your obligations under this 206 | License and any other pertinent obligations, then as a consequence you 207 | may not distribute the Program at all. For example, if a patent 208 | license would not permit royalty-free redistribution of the Program by 209 | all those who receive copies directly or indirectly through you, then 210 | the only way you could satisfy both it and this License would be to 211 | refrain entirely from distribution of the Program. 212 | 213 | If any portion of this section is held invalid or unenforceable under 214 | any particular circumstance, the balance of the section is intended to 215 | apply and the section as a whole is intended to apply in other 216 | circumstances. 217 | 218 | It is not the purpose of this section to induce you to infringe any 219 | patents or other property right claims or to contest validity of any 220 | such claims; this section has the sole purpose of protecting the 221 | integrity of the free software distribution system, which is 222 | implemented by public license practices. Many people have made 223 | generous contributions to the wide range of software distributed 224 | through that system in reliance on consistent application of that 225 | system; it is up to the author/donor to decide if he or she is willing 226 | to distribute software through any other system and a licensee cannot 227 | impose that choice. 228 | 229 | This section is intended to make thoroughly clear what is believed to 230 | be a consequence of the rest of this License. 231 | 232 | 8. If the distribution and/or use of the Program is restricted in 233 | certain countries either by patents or by copyrighted interfaces, the 234 | original copyright holder who places the Program under this License 235 | may add an explicit geographical distribution limitation excluding 236 | those countries, so that distribution is permitted only in or among 237 | countries not thus excluded. In such case, this License incorporates 238 | the limitation as if written in the body of this License. 239 | 240 | 9. The Free Software Foundation may publish revised and/or new versions 241 | of the General Public License from time to time. Such new versions will 242 | be similar in spirit to the present version, but may differ in detail to 243 | address new problems or concerns. 244 | 245 | Each version is given a distinguishing version number. If the Program 246 | specifies a version number of this License which applies to it and "any 247 | later version", you have the option of following the terms and conditions 248 | either of that version or of any later version published by the Free 249 | Software Foundation. If the Program does not specify a version number of 250 | this License, you may choose any version ever published by the Free Software 251 | Foundation. 252 | 253 | 10. If you wish to incorporate parts of the Program into other free 254 | programs whose distribution conditions are different, write to the author 255 | to ask for permission. For software which is copyrighted by the Free 256 | Software Foundation, write to the Free Software Foundation; we sometimes 257 | make exceptions for this. Our decision will be guided by the two goals 258 | of preserving the free status of all derivatives of our free software and 259 | of promoting the sharing and reuse of software generally. 260 | 261 | NO WARRANTY 262 | 263 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 264 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 265 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 266 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 267 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 268 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 269 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 270 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 271 | REPAIR OR CORRECTION. 272 | 273 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 274 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 275 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 276 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 277 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 278 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 279 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 280 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 281 | POSSIBILITY OF SUCH DAMAGES. 282 | 283 | END OF TERMS AND CONDITIONS 284 | 285 | Appendix: How to Apply These Terms to Your New Programs 286 | 287 | If you develop a new program, and you want it to be of the greatest 288 | possible use to the public, the best way to achieve this is to make it 289 | free software which everyone can redistribute and change under these terms. 290 | 291 | To do so, attach the following notices to the program. It is safest 292 | to attach them to the start of each source file to most effectively 293 | convey the exclusion of warranty; and each file should have at least 294 | the "copyright" line and a pointer to where the full notice is found. 295 | 296 | 297 | Copyright (C) 19yy 298 | 299 | This program is free software; you can redistribute it and/or modify 300 | it under the terms of the GNU General Public License as published by 301 | the Free Software Foundation; either version 2 of the License, or 302 | (at your option) any later version. 303 | 304 | This program is distributed in the hope that it will be useful, 305 | but WITHOUT ANY WARRANTY; without even the implied warranty of 306 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 307 | GNU General Public License for more details. 308 | 309 | You should have received a copy of the GNU General Public License 310 | along with this program; if not, write to the Free Software 311 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 312 | 313 | Also add information on how to contact you by electronic and paper mail. 314 | 315 | If the program is interactive, make it output a short notice like this 316 | when it starts in an interactive mode: 317 | 318 | Gnomovision version 69, Copyright (C) 19yy name of author 319 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 320 | This is free software, and you are welcome to redistribute it 321 | under certain conditions; type `show c' for details. 322 | 323 | The hypothetical commands `show w' and `show c' should show the appropriate 324 | parts of the General Public License. Of course, the commands you use may 325 | be called something other than `show w' and `show c'; they could even be 326 | mouse-clicks or menu items--whatever suits your program. 327 | 328 | You should also get your employer (if you work as a programmer) or your 329 | school, if any, to sign a "copyright disclaimer" for the program, if 330 | necessary. Here is a sample; alter the names: 331 | 332 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 333 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 334 | 335 | , 1 April 1989 336 | Ty Coon, President of Vice 337 | 338 | This General Public License does not permit incorporating your program into 339 | proprietary programs. If your program is a subroutine library, you may 340 | consider it more useful to permit linking proprietary applications with the 341 | library. If this is what you want to do, use the GNU Library General 342 | Public License instead of this License. 343 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | Karma Blocker is an ad/nuisance blocker and privacy enhancer for technical people. 4 | It uses a simplistic definition language to assign "karma" points to every resource that Firefox loads when rendering pages. If any resource gathers enough points, it is blocked. It sports the following features: 5 | 6 | * Request-time blocking of any resource. 7 | (Blocked objects never load, never use bandwidth, never set cookies.) 8 | * Karma (or score) based weighting of objects, similar to popular spam filtering solutions like [SpamAssasin](http://spamassassin.apache.org/). 9 | * A flexible expression language for powerful filtering, on a richer set of data than simply "the URL". 10 | * Global function injection; if a script is blocked, yet functions in it are still called, injecting a blank function of the same name will eliminate any errors. 11 | 12 | ## Operation 13 | 14 | Every time Firefox begins to load any resource (page, image, style sheet, javascript file, etc.) Karma Blocker will first check it against the rules it is configured to use. 15 | If the rules match that request, it will be denied and never load. 16 | There are certain exceptions: 17 | 18 | * When Karma Blocker is disabled (and the status bar icon is greyed out), all requests will be allowed. 19 | * When the resource is not from one of the schemes `http`, `https`, `ftp`, `chrome`, all requests will be allowed. 20 | * Three different checks are made to ensure that resources that form part of the browser itself (i.e. the back/forward buttons, icons, etc.) are never blocked. 21 | 22 | Click the icon in the status bar to globally enable/disable Karma Blocker. 23 | 24 | ## Configuration 25 | 26 | See [Configuration wiki page](https://github.com/arantius/karma-blocker/wiki/Configuration). 27 | 28 | # Changelog 29 | 30 | * Version 0.6.2 (Pending) 31 | * Inject functions which do not break the page when called. 32 | * Version 0.6.1 (September 8, 2015) 33 | * Minor bug fix to new monitor window. 34 | * Version 0.6 (September 3, 2015) 35 | * Bug fix: Allow literal 'false' values. 36 | * Toolbar button's default click action is to disable only while reloading the page. 37 | * Add request type 'xmlhttprequest'. 38 | * Allow semicolon for comments. 39 | * Richer options in the monitor window. 40 | * Version 0.5 (March 27, 2015) 41 | * Compatibility with multi-process Firefox. 42 | * Version 0.4.8 (October 17, 2013) 43 | * Performance Enhancements 44 | * Version 0.4.7 (September 1, 2013) 45 | * Small bug fixes for compatibility with modern Firefox versions. 46 | * Version 0.4.6 (August 16, 2011) 47 | * Do not warn when local and to-sync rules match. (#529) 48 | * Fix warning about internal Firefox API change. (#530) 49 | * Support up to Firefox 7. (#532) 50 | * Version 0.4.5 (June 27, 2011) 51 | * Fix changing the rules w/out requiring a browser restart. (#499) 52 | * Tweaks to default rule set. (#513, #518) 53 | * Display a spinner in the config dialog's sync button while loading the remote resource. 54 | * Compatibility with Firefox 5.0. 55 | * Version 0.4.4 (March 15, 2011) 56 | * Detect invalid regular expressions. (#487) 57 | * Fix early DOM access bug (forced visibility of tab scroll buttons). (#488) 58 | * New icons. 59 | * Version 0.4.3 (March 7, 2011) 60 | * Firefox 4 compatibility. (#482) 61 | * Properly handle resources loaded from pretty-printed feeds. (#372) 62 | * Check for undefined property accesses. (#412) 63 | * Fix syntax in default rules. (#415) 64 | * Indicate in the monitor dialog when the cutoff score halts processing. (#416) 65 | * When a rule was not checked, display 'Skipped' for match rather than 'No'. (#417) 66 | * Do not reset the 'Scores' box of the monitor window when resources are added. (#419) 67 | * Add less than and greater than operators. (#421) 68 | * Version 0.4.2 (Jan 11, 2010) 69 | * Fix typo in default preferences, causing the rules to be just "undefined". (#392) 70 | * New button in configuration dialog, to reset to default rules. (#389) 71 | * Version 0.4.1 (Dec 31, 2009) 72 | * Firefox 3.6 compatibility flag. 73 | * Avoid spurious "function anonymous() { }" text in page. (#306) 74 | * Add an optional toolbar button. (#285) 75 | * Monitor dialog displays types correctly. (#370) 76 | * Add `origin.size` property, for compact size rules. (#371) 77 | * New default rules to demonstrate new features, cause less false positives. (#265) 78 | * Version 0.4 (Jun 26, 2009) 79 | * Mark Firefox compatibility with 3.0 through 3.5. 80 | * Add option for the monitor window to gather only blocked resources. (#221) 81 | * Add configuration setting to enable/disable the element collapsing feature (now ''off'' by default), and make it less aggressive when it is enabled. (#209) 82 | * Allow functions with properties to be injected, i.e. `inject='_gat._getTracker'` will eat undefined function errors from blocked Google Analytics scripts. (#253) 83 | * Disable wrapping when editing rules, so long lines display on one line (with a horizontal scroll bar). 84 | * Never block core parts of the browser itself. (#222) 85 | * In the monitor window, you can copy data, remove items, open URLs, and expand/collapse rows via a context menu. (#266) 86 | * New default rules which are highly functional. (#265) 87 | * Version 0.3.2 (Sep 27, 2008) 88 | * Bug fix, certain rule sets can cause Firefox to freeze. (#182) 89 | * Version 0.3.1 (Jul 15, 2008) 90 | * Enhanced element collapsing. (When an ad is blocked, if it is inside an otherwise empty, fixed size container, that container will be removed from the page.) 91 | * Version 0.3 (Feb 9, 2008) 92 | * Bug fix: allow rules to block chrome (#93). 93 | * Compatibility with Firefox 3.0. 94 | * Feature: Monitor window, which displays the score, and blocked status of all resources, plus the match status and score contribution of each group, for each resource. 95 | * Add the "name" field for "Group" sections, to allow meaningful group display in the monitor window. 96 | * Version 0.2.1 (Jun 28, 2007) 97 | * Add debugging output detailing where functions are being injected to. 98 | * Fix home page address. 99 | * Remove stability/security disclaimer, a few months of testing have gone well. 100 | * Version 0.2 (Feb 17, 2007) 101 | * Initial release of Karma Blocker with full feature set: 102 | * Karma based scoring system. 103 | * Flexible rules language for matching. 104 | * Function injection. 105 | * Version 0.1 (Jan 3, 2007) 106 | * Initial release of grandfather project, Third Party Script Stopper. 107 | 108 | # Credits 109 | 110 | * [Using the RegExp Object for Lexical Analysis in Javascript](http://cc.usu.edu/~amcinnes/js-regexp-lexing.html) - Lexical analysis algorithm 111 | * [FireBug](http://www.getfirebug.com/) - Content page function injection 112 | * [Fast Icon](http://www.fasticon.com/) iSimple System set - Main Icon 113 | * [famfamfam.com](http://www.famfamfam.com/lab/icons/silk/) Silk icons set - Blocked Icon 114 | * Previously: [Everaldo Coelho](http://everaldo.com/) Crystal Clear Actions icons set - Main Icon 115 | * [AdBlock](http://adblock.mozdev.org/) and [AdBlock Plus](http://adblockplus.org/) - Ideas, some code sections 116 | 117 | # License 118 | 119 | Karma Blocker is released under the GPLv2 license. 120 | -------------------------------------------------------------------------------- /chrome.manifest: -------------------------------------------------------------------------------- 1 | content kabl content/ 2 | skin kabl classic/1.0 skin/ 3 | 4 | overlay chrome://browser/content/browser.xul chrome://kabl/content/kabl-overlay.xul 5 | style chrome://browser/content/browser.xul chrome://kabl/skin/kabl-overlay.css 6 | style chrome://global/content/customizeToolbar.xul chrome://kabl/skin/kabl-overlay.css 7 | -------------------------------------------------------------------------------- /content/kabl-config.js: -------------------------------------------------------------------------------- 1 | // ***** BEGIN LICENSE BLOCK ***** 2 | // Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | // 4 | // The contents of this file are subject to the Mozilla Public License Version 5 | // 1.1 (the 'License'); you may not use this file except in compliance with 6 | // the License. You may obtain a copy of the License at 7 | // http://www.mozilla.org/MPL/ 8 | // 9 | // Software distributed under the License is distributed on an 'AS IS' basis, 10 | // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | // for the specific language governing rights and limitations under the 12 | // License. 13 | // 14 | // The Initial Developer of the Original Code is Anthony Lieuallen. 15 | // 16 | // Portions created by the Initial Developer are Copyright (C) 2007 17 | // the Initial Developer. All Rights Reserved. 18 | // 19 | // 20 | // Alternatively, the contents of this file may be used under the terms of 21 | // either the GNU General Public License Version 2 or later (the 'GPL'), or 22 | // the GNU Lesser General Public License Version 2.1 or later (the 'LGPL'), 23 | // in which case the provisions of the GPL or the LGPL are applicable instead 24 | // of those above. If you wish to allow use of your version of this file only 25 | // under the terms of either the GPL or the LGPL, and not to allow others to 26 | // use your version of this file under the terms of the MPL, indicate your 27 | // decision by deleting the provisions above and replace them with the notice 28 | // and other provisions required by the GPL or the LGPL. If you do not delete 29 | // the provisions above, a recipient may use your version of this file under 30 | // the terms of any one of the MPL, the GPL or the LGPL. 31 | // 32 | // ***** END LICENSE BLOCK ***** 33 | 34 | Components.utils.import('chrome://kabl/content/kabl-lib.js'); 35 | Components.utils.import('chrome://kabl/content/kabl-parse.js'); 36 | Components.utils.import('chrome://kabl/content/kabl-pref.js'); 37 | Components.utils.import('chrome://kabl/content/kabl-sync.js'); 38 | 39 | // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // 40 | 41 | function gKablConfigOpen() { 42 | document.getElementById('enabled') 43 | .setAttribute('checked', gKablPrefs.enabled); 44 | document.getElementById('sync_enabled') 45 | .setAttribute('checked', gKablPrefs.sync_enabled); 46 | document.getElementById('sync_url') 47 | .setAttribute('value', gKablPrefs.sync_url); 48 | 49 | var rules=document.getElementById('rules'); 50 | rules.value=gKablPrefs.rules; 51 | rules.selectionStart=0; 52 | rules.selectionEnd=0; 53 | rules.focus(); 54 | 55 | gKablSetSyncTime(); 56 | 57 | document.getElementById('sync_enabled').addEventListener( 58 | 'click', gKablSyncEnabledChange, true); 59 | document.getElementById('sync_enabled').addEventListener( 60 | 'keypress', gKablSyncEnabledChange, true); 61 | gKablSyncEnabledChange(); 62 | } 63 | 64 | function gKablConfigAccept() { 65 | var parseOk=gKablCheckConfig(); 66 | if (!parseOk) { 67 | if (!confirm('Parse error.\nReally save rules?')) return; 68 | } 69 | 70 | // extract pref vals 71 | gKablPrefs.enabled=document.getElementById('enabled').checked; 72 | gKablPrefs.rules=document.getElementById('rules').value; 73 | gKablPrefs.sync_enabled=document.getElementById('sync_enabled').checked; 74 | gKablPrefs.sync_url=document.getElementById('sync_url').value; 75 | 76 | gKablSave(); 77 | 78 | return true; 79 | } 80 | 81 | function gKablCheckConfig() { 82 | var textbox=document.getElementById('rules'); 83 | 84 | try { 85 | gKablRulesObj.parse(textbox.value); 86 | } catch (e) { 87 | if (e instanceof KablParseException) { 88 | gKablSetStatusLabel('err', e.message); 89 | textbox.selectionStart=parseInt(e.start); 90 | textbox.selectionEnd=parseInt(e.end); 91 | textbox.focus(); 92 | return false; 93 | } 94 | dump("ERROR in gKablCheckConfig():\n"); 95 | for (var i in e) dump(i+' '+e[i]+'\n'); 96 | return false; 97 | } 98 | 99 | gKablSetStatusLabel('ok'); 100 | 101 | textbox.focus(); 102 | return true; 103 | } 104 | 105 | function gKablSetStatusLabel(type, msg) { 106 | for (label in {'unk':1, 'ok':1, 'err':1}) { 107 | document.getElementById('status_'+label).setAttribute( 108 | 'hidden', (label!=type) 109 | ); 110 | } 111 | 112 | var errmsg=document.getElementById('status_errmsg'); 113 | if ('err'==type) { 114 | errmsg.setAttribute('value', msg); 115 | errmsg.setAttribute('hidden', false); 116 | } else { 117 | errmsg.setAttribute('hidden', true); 118 | } 119 | } 120 | 121 | // This function originates from AdBlock Plus, reused under MPL. 122 | function gKablLoadInBrowser(url) { 123 | var currentWindow=gKablBrowserWin(); 124 | if (currentWindow) { 125 | try { 126 | currentWindow.delayedOpenTab(url); 127 | } 128 | catch(e) { 129 | currentWindow.loadURI(url); 130 | } 131 | } else { 132 | var protocolService=Components 133 | .classes['@mozilla.org/uriloader/external-protocol-service;1'] 134 | .getService(Components.interfaces.nsIExternalProtocolService); 135 | protocolService.loadUrl(url); 136 | } 137 | } 138 | 139 | function gKablResetConfig() { 140 | if (!confirm('Really throw away current rules and reset to defaults?')) { 141 | return; 142 | } 143 | 144 | var defaultPref=Components.classes['@mozilla.org/preferences-service;1'] 145 | .getService(Components.interfaces.nsIPrefService) 146 | .getDefaultBranch('extensions.kabl.'); 147 | 148 | document.getElementById('enabled').checked=defaultPref.getBoolPref('enabled');; 149 | document.getElementById('rules').value=defaultPref.getCharPref('rules'); 150 | document.getElementById('sync_enabled').value=defaultPref.getBoolPref('sync_enabled'); 151 | document.getElementById('sync_url').value=defaultPref.getCharPref('sync_url'); 152 | } 153 | 154 | function gKablSyncEnabledChange(aEvent) { 155 | var syncEnabled=document.getElementById('sync_enabled').checked; 156 | document.getElementById('sync_now').disabled=!syncEnabled; 157 | document.getElementById('sync_url').disabled=!syncEnabled; 158 | } 159 | 160 | function gKablSyncNow() { 161 | var btn = document.getElementById('sync_now'); 162 | btn.className += ' loading'; 163 | btn.disabled = true; 164 | 165 | gKablRuleSync(gKablSyncNowCallback, 166 | document.getElementById('sync_enabled').checked, 167 | document.getElementById('sync_url').value); 168 | } 169 | 170 | function gKablSyncNowCallback() { 171 | var btn = document.getElementById('sync_now'); 172 | btn.className = btn.className.replace(' loading', ''); 173 | btn.disabled = false; 174 | 175 | var rules=document.getElementById('rules'); 176 | rules.value=gKablPrefs.rules; 177 | gKablSetSyncTime(); 178 | } 179 | 180 | function gKablSetSyncTime() { 181 | var lastSync='Never'; 182 | if (gKablPrefs.sync_last_time) { 183 | lastSync=new Date(gKablPrefs.sync_last_time).toLocaleString(); 184 | } 185 | document.getElementById('sync_time').value='Last sync: '+lastSync; 186 | } 187 | -------------------------------------------------------------------------------- /content/kabl-config.xul: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 59 | -------------------------------------------------------------------------------- /content/kabl-frame.js: -------------------------------------------------------------------------------- 1 | // ***** BEGIN LICENSE BLOCK ***** 2 | // Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | // 4 | // The contents of this file are subject to the Mozilla Public License Version 5 | // 1.1 (the 'License'); you may not use this file except in compliance with 6 | // the License. You may obtain a copy of the License at 7 | // http://www.mozilla.org/MPL/ 8 | // 9 | // Software distributed under the License is distributed on an 'AS IS' basis, 10 | // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | // for the specific language governing rights and limitations under the 12 | // License. 13 | // 14 | // The Initial Developer of the Original Code is Anthony Lieuallen. 15 | // 16 | // Portions created by the Initial Developer are Copyright (C) 2007 17 | // the Initial Developer. All Rights Reserved. 18 | // 19 | // Alternatively, the contents of this file may be used under the terms of 20 | // either the GNU General Public License Version 2 or later (the 'GPL'), or 21 | // the GNU Lesser General Public License Version 2.1 or later (the 'LGPL'), 22 | // in which case the provisions of the GPL or the LGPL are applicable instead 23 | // of those above. If you wish to allow use of your version of this file only 24 | // under the terms of either the GPL or the LGPL, and not to allow others to 25 | // use your version of this file under the terms of the MPL, indicate your 26 | // decision by deleting the provisions above and replace them with the notice 27 | // and other provisions required by the GPL or the LGPL. If you do not delete 28 | // the provisions above, a recipient may use your version of this file under 29 | // the terms of any one of the MPL, the GPL or the LGPL. 30 | // 31 | // ***** END LICENSE BLOCK ***** 32 | 33 | Components.utils.import('chrome://kabl/content/kabl-inserter.js'); 34 | Components.utils.import('chrome://kabl/content/kabl-policy.js'); 35 | Components.utils.import('chrome://kabl/content/kabl-pref.js'); 36 | Components.utils.import('chrome://kabl/content/kabl-sync.js'); 37 | 38 | //\\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // 39 | 40 | gKablPolicy.startup(); 41 | addEventListener('DOMContentLoaded', gKablPolicy.collapse, false); 42 | 43 | gKablInserter.addObserver(); 44 | addEventListener('unload', gKablInserter.removeObserver, false); 45 | -------------------------------------------------------------------------------- /content/kabl-inserter.js: -------------------------------------------------------------------------------- 1 | // ***** BEGIN LICENSE BLOCK ***** 2 | // Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | // 4 | // The contents of this file are subject to the Mozilla Public License Version 5 | // 1.1 (the 'License'); you may not use this file except in compliance with 6 | // the License. You may obtain a copy of the License at 7 | // http://www.mozilla.org/MPL/ 8 | // 9 | // Software distributed under the License is distributed on an 'AS IS' basis, 10 | // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | // for the specific language governing rights and limitations under the 12 | // License. 13 | // 14 | // The Initial Developer of the Original Code is Joe Hewitt. 15 | // 16 | // Portions created by the Initial Developer are Copyright (C) 2005 17 | // the Initial Developer. All Rights Reserved. 18 | // 19 | // Contributor(s): 20 | // Anthony Lieuallen, Copyright (C) 2007 21 | // 22 | // Alternatively, the contents of this file may be used under the terms of 23 | // either the GNU General Public License Version 2 or later (the 'GPL'), or 24 | // the GNU Lesser General Public License Version 2.1 or later (the 'LGPL'), 25 | // in which case the provisions of the GPL or the LGPL are applicable instead 26 | // of those above. If you wish to allow use of your version of this file only 27 | // under the terms of either the GPL or the LGPL, and not to allow others to 28 | // use your version of this file under the terms of the MPL, indicate your 29 | // decision by deleting the provisions above and replace them with the notice 30 | // and other provisions required by the GPL or the LGPL. If you do not delete 31 | // the provisions above, a recipient may use your version of this file under 32 | // the terms of any one of the MPL, the GPL or the LGPL. 33 | // 34 | // ***** END LICENSE BLOCK ***** 35 | 36 | var EXPORTED_SYMBOLS=['gKablInserter']; 37 | 38 | Components.utils.import('resource://gre/modules/Services.jsm'); 39 | 40 | Components.utils.import('chrome://kabl/content/kabl-parse.js'); 41 | Components.utils.import('chrome://kabl/content/kabl-pref.js'); 42 | 43 | var gKablInserter={}; 44 | 45 | gKablInserter.addObserver=function() { 46 | Services.obs.addObserver( 47 | gKablInserter, 'content-document-global-created', false); 48 | }; 49 | 50 | gKablInserter.removeObserver=function() { 51 | Services.obs.removeObserver( 52 | gKablInserter, 'content-document-global-created', false); 53 | }; 54 | 55 | gKablInserter.observe=function(aSubject, aTopic, aData) { 56 | if ('content-document-global-created' != aTopic) return; 57 | if (!gKablPrefs.enabled) return; 58 | if (0 == gKablRulesObj.injectFunctions.length) return; 59 | 60 | var sandbox = Components.utils.Sandbox(aSubject, { 61 | 'sameZoneAs': aSubject, 62 | 'sandboxPrototype': aSubject, 63 | 'wantXrays': false, 64 | }); 65 | Components.utils.evalInSandbox( 66 | gKablInserter.insertStr 67 | + ';insert('+gKablRulesObj.injectFunctionsStr+');', 68 | sandbox); 69 | }; 70 | 71 | (function() { 72 | function insert(aFuncs) { 73 | var obj=function(){return arguments.callee;}; 74 | obj.__noSuchMethod__=obj; 75 | obj.toString=function(){return '';}; 76 | 77 | for (var i=0, func=null; func=aFuncs[i]; i++) { 78 | var subObj=obj; 79 | var name=func.split('.'); 80 | var baseName=name.shift(), subName; 81 | 82 | // Don't overwrite, if the page already has this object. 83 | if ('undefined'!=typeof window[baseName]) continue; 84 | 85 | // Create properties, as necessary. 86 | while (subName=name.shift()) { 87 | subObj[subName]=obj; 88 | subObj=subObj[subName]; 89 | } 90 | 91 | window[baseName]=obj; 92 | } 93 | }; 94 | gKablInserter.insertStr=uneval(insert); 95 | })(); 96 | -------------------------------------------------------------------------------- /content/kabl-lib.js: -------------------------------------------------------------------------------- 1 | // ***** BEGIN LICENSE BLOCK ***** 2 | // Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | // 4 | // The contents of this file are subject to the Mozilla Public License Version 5 | // 1.1 (the 'License'); you may not use this file except in compliance with 6 | // the License. You may obtain a copy of the License at 7 | // http://www.mozilla.org/MPL/ 8 | // 9 | // Software distributed under the License is distributed on an 'AS IS' basis, 10 | // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | // for the specific language governing rights and limitations under the 12 | // License. 13 | // 14 | // The Initial Developer of the Original Code is Anthony Lieuallen. 15 | // 16 | // Portions created by the Initial Developer are Copyright (C) 2007 17 | // the Initial Developer. All Rights Reserved. 18 | // 19 | // Alternatively, the contents of this file may be used under the terms of 20 | // either the GNU General Public License Version 2 or later (the 'GPL'), or 21 | // the GNU Lesser General Public License Version 2.1 or later (the 'LGPL'), 22 | // in which case the provisions of the GPL or the LGPL are applicable instead 23 | // of those above. If you wish to allow use of your version of this file only 24 | // under the terms of either the GPL or the LGPL, and not to allow others to 25 | // use your version of this file under the terms of the MPL, indicate your 26 | // decision by deleting the provisions above and replace them with the notice 27 | // and other provisions required by the GPL or the LGPL. If you do not delete 28 | // the provisions above, a recipient may use your version of this file under 29 | // the terms of any one of the MPL, the GPL or the LGPL. 30 | // 31 | // ***** END LICENSE BLOCK ***** 32 | 33 | var EXPORTED_SYMBOLS=['gKablActiveWin', 'gKablBrowserWin']; 34 | 35 | function gKablActiveWin() { 36 | var ww=Components.classes["@mozilla.org/embedcomp/window-watcher;1"] 37 | .getService(Components.interfaces.nsIWindowWatcher); 38 | return ww.activeWindow; 39 | } 40 | 41 | function gKablBrowserWin() { 42 | var windowMediator=Components 43 | .classes["@mozilla.org/appshell/window-mediator;1"] 44 | .getService(Components.interfaces.nsIWindowMediator); 45 | return windowMediator.getMostRecentWindow("navigator:browser"); 46 | } 47 | -------------------------------------------------------------------------------- /content/kabl-monitor.js: -------------------------------------------------------------------------------- 1 | // ***** BEGIN LICENSE BLOCK ***** 2 | // Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | // 4 | // The contents of this file are subject to the Mozilla Public License Version 5 | // 1.1 (the 'License'); you may not use this file except in compliance with 6 | // the License. You may obtain a copy of the License at 7 | // http://www.mozilla.org/MPL/ 8 | // 9 | // Software distributed under the License is distributed on an 'AS IS' basis, 10 | // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | // for the specific language governing rights and limitations under the 12 | // License. 13 | // 14 | // The Initial Developer of the Original Code is Anthony Lieuallen. 15 | // 16 | // Portions created by the Initial Developer are Copyright (C) 2007 17 | // the Initial Developer. All Rights Reserved. 18 | // 19 | // Alternatively, the contents of this file may be used under the terms of 20 | // either the GNU General Public License Version 2 or later (the 'GPL'), or 21 | // the GNU Lesser General Public License Version 2.1 or later (the 'LGPL'), 22 | // in which case the provisions of the GPL or the LGPL are applicable instead 23 | // of those above. If you wish to allow use of your version of this file only 24 | // under the terms of either the GPL or the LGPL, and not to allow others to 25 | // use your version of this file under the terms of the MPL, indicate your 26 | // decision by deleting the provisions above and replace them with the notice 27 | // and other provisions required by the GPL or the LGPL. If you do not delete 28 | // the provisions above, a recipient may use your version of this file under 29 | // the terms of any one of the MPL, the GPL or the LGPL. 30 | // 31 | // ***** END LICENSE BLOCK ***** 32 | 33 | Components.utils.import('chrome://kabl/content/kabl-policy.js'); 34 | 35 | //\\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // 36 | 37 | var Cc = Components.classes; 38 | var Ci = Components.interfaces; 39 | var Cu = Components.utils; 40 | 41 | var LENGTH_LIMIT = 4000; 42 | 43 | var gPreviousSelectedItem=null; 44 | var $=function(x){ return document.getElementById(x); } 45 | 46 | var gKablMonitor={ 47 | typeMap:{ 48 | '1':'other', 49 | '2':'script', 50 | '3':'image', 51 | '4':'stylesheet', 52 | '5':'object', 53 | '6':'document', 54 | '7':'subdocument', 55 | '8':'refresh', 56 | '9':'xbl', 57 | '10':'ping', 58 | '11':'xmlhttprequest', 59 | '12':'object_subrequest' 60 | }, 61 | 62 | treeRes:null, 63 | treeScore:null, 64 | changing:false, 65 | 66 | onLoad:function() { 67 | window.removeEventListener('DOMContentLoaded', gKablMonitor.onLoad, false); 68 | gKablMonitor.treeRes=$('treeRes'); 69 | gKablMonitor.treeScore=$('treeScore'); 70 | 71 | Cc['@mozilla.org/parentprocessmessagemanager;1'] 72 | .getService(Ci.nsIMessageBroadcaster) 73 | .broadcastAsyncMessage('kabl:monitor-opened'); 74 | Cc['@mozilla.org/parentprocessmessagemanager;1'] 75 | .getService(Ci.nsIMessageListenerManager) 76 | .addMessageListener('kabl:monitor', gKablMonitor.add); 77 | 78 | $('filterForm').addEventListener('click', function(event) { 79 | // After timeout so that .checked/.selected matches new state. 80 | setTimeout(gKablMonitor.changeShowing, 0, event); 81 | }, true); 82 | }, 83 | 84 | onUnload:function() { 85 | Cc['@mozilla.org/parentprocessmessagemanager;1'] 86 | .getService(Ci.nsIMessageBroadcaster) 87 | .broadcastAsyncMessage('kabl:monitor-closed'); 88 | Cc['@mozilla.org/parentprocessmessagemanager;1'] 89 | .getService(Ci.nsIMessageListenerManager) 90 | .removeMessageListener('kabl:monitor', gKablMonitor.add); 91 | }, 92 | 93 | changeShowing:function(event) { 94 | var checkedShowAll = $('showTypeAll').checked; 95 | var checkedAllOther = 96 | $('showTypeXhr').checked && 97 | $('showTypeCss').checked && 98 | $('showTypeImg').checked && 99 | $('showTypeScr').checked && 100 | $('showTypeOth').checked; 101 | 102 | if ('showTypeAll' == event.target.id) { 103 | $('showTypeXhr').checked = 104 | $('showTypeCss').checked = 105 | $('showTypeImg').checked = 106 | $('showTypeScr').checked = 107 | $('showTypeOth').checked = 108 | $('showTypeAll').checked; 109 | } else if (checkedAllOther) { 110 | $('showTypeAll').checked = true; 111 | } else { 112 | $('showTypeAll').checked = false; 113 | } 114 | 115 | gKablMonitor.changing = true; 116 | for (var i = 0, row = null; row = gKablMonitor.treeRes.childNodes[i]; i++) { 117 | row.hidden = !gKablMonitor.showRow(row); 118 | } 119 | gKablMonitor.changing = false; 120 | }, 121 | 122 | clear:function() { 123 | gKablMonitor.changing=true; 124 | while (gKablMonitor.treeScore.firstChild) { 125 | gKablMonitor.treeScore.removeChild(gKablMonitor.treeScore.firstChild); 126 | } 127 | while (gKablMonitor.treeRes.firstChild) { 128 | gKablMonitor.treeRes.removeChild(gKablMonitor.treeRes.firstChild); 129 | } 130 | gKablMonitor.changing=false; 131 | }, 132 | 133 | resSelect:function(event) { 134 | if (gKablMonitor.changing) return; 135 | 136 | while (gKablMonitor.treeScore.firstChild) { 137 | gKablMonitor.treeScore.removeChild(gKablMonitor.treeScore.firstChild); 138 | } 139 | 140 | var tree = event.target; 141 | var item = tree.contentView.getItemAtIndex(tree.currentIndex); 142 | if (!item) return; 143 | if (item && item==gPreviousSelectedItem) return; 144 | gPreviousSelectedItem=item; 145 | 146 | for (i in item.groups) { 147 | gKablMonitor.treeScore.appendChild( 148 | gKablMonitor.groupItem(item.groups[i])); 149 | } 150 | }, 151 | 152 | showRow:function(row) { 153 | if ($('showBlockedNo').selected && row.blocked) return false; 154 | if ($('showBlockedYes').selected && !row.blocked) return false; 155 | 156 | if ($('showTypeAll').checked) return true; 157 | 158 | if (row.fields.$type == 2) return $('showTypeScr').checked; 159 | else if (row.fields.$type == 3) return $('showTypeImg').checked; 160 | else if (row.fields.$type == 4) return $('showTypeCss').checked; 161 | else if (row.fields.$type == 11) return $('showTypeXhr').checked; 162 | else return $('showTypeOth').checked; 163 | }, 164 | 165 | add:function(message) { 166 | fields = message.data.fields; 167 | groups = message.data.groups; 168 | score = message.data.score; 169 | blocked = message.data.blocked; 170 | 171 | var item=gKablMonitor.fieldItem('$url', fields.$url, score, blocked); 172 | item.blocked=blocked; 173 | item.fields=fields; 174 | item.groups=groups; 175 | 176 | item.hidden = !gKablMonitor.showRow(item); 177 | 178 | var children=document.createElement('treechildren'); 179 | item.appendChild(children); 180 | 181 | var subItem; 182 | for (i in fields) { 183 | if ('$url'==i) continue; 184 | if ('node'==i) continue; 185 | if ('undefined'==typeof fields[i]) continue; 186 | 187 | subItem=gKablMonitor.fieldItem(i, fields[i]); 188 | children.appendChild(subItem); 189 | } 190 | 191 | gKablMonitor.treeRes.insertBefore(item, gKablMonitor.treeRes.firstChild); 192 | while (gKablMonitor.treeRes.childNodes.length > LENGTH_LIMIT) { 193 | gKablMonitor.treeRes.removeChild(gKablMonitor.treeRes.lastChild); 194 | } 195 | }, 196 | 197 | fieldItem:function(name, value, score, blocked) { 198 | if ('$type'==name) { 199 | value=gKablMonitor.typeMap[value]; 200 | } 201 | 202 | var cell, row, item=document.createElement('treeitem'); 203 | 204 | row=document.createElement('treerow'); 205 | item.appendChild(row); 206 | 207 | cell=document.createElement('treecell'); 208 | cell.setAttribute('label', name+': '+value); 209 | row.appendChild(cell); 210 | 211 | if ('undefined'!=typeof score) { 212 | item.setAttribute('container', 'true'); 213 | 214 | cell=document.createElement('treecell'); 215 | cell.setAttribute('label', score); 216 | row.appendChild(cell); 217 | 218 | cell=document.createElement('treecell'); 219 | if (blocked) cell.setAttribute('properties', 'blocked'); 220 | row.appendChild(cell); 221 | } 222 | 223 | return item; 224 | }, 225 | 226 | groupItem:function(group) { 227 | var cell, row, item=document.createElement('treeitem'); 228 | if (group.rules) item.setAttribute('container', 'true'); 229 | 230 | row=document.createElement('treerow'); 231 | item.appendChild(row); 232 | 233 | cell=document.createElement('treecell'); 234 | cell.setAttribute('label', group.name); 235 | row.appendChild(cell); 236 | 237 | cell=document.createElement('treecell'); 238 | cell.setAttribute('label', group.score); 239 | row.appendChild(cell); 240 | 241 | if (!group.rules) return item; 242 | 243 | var children=document.createElement('treechildren'); 244 | item.appendChild(children); 245 | 246 | var rule; 247 | for (i in group.rules) { 248 | rule=group.rules[i]; 249 | 250 | var subItem=document.createElement('treeitem'); 251 | 252 | row=document.createElement('treerow'); 253 | subItem.appendChild(row); 254 | children.appendChild(subItem); 255 | 256 | cell=document.createElement('treecell'); 257 | var val=rule.val; 258 | if ('$type'==rule.field) val=this.typeMap[val]; 259 | cell.setAttribute('label', rule.field+' '+rule.op+' '+val); 260 | row.appendChild(cell); 261 | 262 | cell=document.createElement('treecell'); 263 | var match=''; 264 | if (null===rule.match) { 265 | match='Skipped'; 266 | } else { 267 | match=rule.match?'Yes':'No'; 268 | } 269 | cell.setAttribute('label', match); 270 | row.appendChild(cell); 271 | } 272 | 273 | return item; 274 | }, 275 | 276 | labelForResourceItem:function(item) { 277 | // row cell 278 | return item.firstChild.firstChild.getAttribute('label'); 279 | }, 280 | 281 | withSelectedResources:function(callbackRow, callbackDetail) { 282 | var treeView=gKablMonitor.treeRes.parentNode.view; 283 | var start=new Object(), end=new Object(); 284 | for (var i=0; i 2 | 3 | 4 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /content/kabl-overlay.js: -------------------------------------------------------------------------------- 1 | // ***** BEGIN LICENSE BLOCK ***** 2 | // Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | // 4 | // The contents of this file are subject to the Mozilla Public License Version 5 | // 1.1 (the 'License'); you may not use this file except in compliance with 6 | // the License. You may obtain a copy of the License at 7 | // http://www.mozilla.org/MPL/ 8 | // 9 | // Software distributed under the License is distributed on an 'AS IS' basis, 10 | // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | // for the specific language governing rights and limitations under the 12 | // License. 13 | // 14 | // The Initial Developer of the Original Code is Anthony Lieuallen. 15 | // 16 | // Portions created by the Initial Developer are Copyright (C) 2007 17 | // the Initial Developer. All Rights Reserved. 18 | // 19 | // Alternatively, the contents of this file may be used under the terms of 20 | // either the GNU General Public License Version 2 or later (the 'GPL'), or 21 | // the GNU Lesser General Public License Version 2.1 or later (the 'LGPL'), 22 | // in which case the provisions of the GPL or the LGPL are applicable instead 23 | // of those above. If you wish to allow use of your version of this file only 24 | // under the terms of either the GPL or the LGPL, and not to allow others to 25 | // use your version of this file under the terms of the MPL, indicate your 26 | // decision by deleting the provisions above and replace them with the notice 27 | // and other provisions required by the GPL or the LGPL. If you do not delete 28 | // the provisions above, a recipient may use your version of this file under 29 | // the terms of any one of the MPL, the GPL or the LGPL. 30 | // 31 | // ***** END LICENSE BLOCK ***** 32 | 33 | Components.utils.import('chrome://kabl/content/kabl-pref.js'); 34 | 35 | var gKabl={ 36 | menuitemToggle: null, 37 | menuitemReload: null, 38 | 39 | isReloading: false, 40 | reloadTimer: null, 41 | 42 | finishReload:function() { 43 | if (!gKabl.isReloading) return; 44 | dump("Finishing disabled reload ...\n"); 45 | gKabl.isReloading = false; 46 | if (gKabl.reloadTimer) { 47 | clearTimeout(gKabl.reloadTimer); 48 | gKabl.reloadTimer = null; 49 | } 50 | gKablSet('enabled', true); 51 | }, 52 | 53 | openConfig:function() { 54 | var windowWatcher=Components 55 | .classes['@mozilla.org/embedcomp/window-watcher;1'] 56 | .getService(Components.interfaces.nsIWindowWatcher); 57 | windowWatcher.openWindow( 58 | window, 'chrome://kabl/content/kabl-config.xul', null, 59 | 'chrome,dependent,centerscreen,resizable,dialog', null); 60 | }, 61 | 62 | openMonitorWindow:function(parentWin) { 63 | if (gKabl.monitorWin && false===gKabl.monitorWin.closed) { 64 | return gKabl.monitorWin; 65 | } 66 | 67 | return gKabl.monitorWin=parentWin.open( 68 | 'chrome://kabl/content/kabl-monitor.xul', null, 69 | 'chrome,close=no,dependent,dialog,resizable' 70 | ); 71 | }, 72 | 73 | popupshowing:function() { 74 | gKabl.menuitemToggle.style.fontWeight 75 | = gKablPrefs.enabled ? 'normal' : 'bold'; 76 | gKabl.menuitemReload.style.fontWeight 77 | = gKablPrefs.enabled ? 'bold' : 'normal'; 78 | }, 79 | 80 | toggle:function() { 81 | gKablSet('enabled', !gKablPrefs.enabled); 82 | }, 83 | 84 | toolbarButtonDefault:function() { 85 | dump('>>> toolbarButtonDefault ...\n'); 86 | if (gKablPrefs.enabled) { 87 | dump("Reloading, disabled ...\n"); 88 | gKabl.isReloading = true; 89 | gKablSet('enabled', false); 90 | gKabl.reloadTimer = setTimeout(gKabl.finishReload, 30000); 91 | try { 92 | gBrowser.reloadTab(gBrowser.mCurrentTab); 93 | } catch (e) { 94 | dump('could not reload tab!\n'+e+'\n'); 95 | } 96 | } else { 97 | gKablSet('enabled', true); 98 | } 99 | }, 100 | 101 | setToolbarButtonState:function() { 102 | var tb=document.getElementById('tb-kabl'); 103 | if (tb) { 104 | // Standard is disabled=true -- but that disables the button, so 105 | // clicking it fires no command and won't re-enable us. Use our 106 | // own yes/no styled to be similar. 107 | tb.setAttribute('kabl_disabled', gKablPrefs.enabled ? 'no' : 'yes'); 108 | } 109 | }, 110 | 111 | onContentLoad:function(event) { 112 | gKabl.finishReload(); 113 | }, 114 | 115 | onChromeLoad:function() { 116 | gKabl.setToolbarButtonState(); 117 | 118 | gKabl.menuitemToggle 119 | = document.querySelector('#tb-kabl menuitem[label=Toggle]'); 120 | gKabl.menuitemReload 121 | = document.querySelector('#tb-kabl menuitem[label=Reload]'); 122 | 123 | window.removeEventListener('load', gKabl.onLoad, false); 124 | gBrowser.addEventListener('load', gKabl.onContentLoad, true); 125 | 126 | Components 127 | .classes['@mozilla.org/globalmessagemanager;1'] 128 | .getService(Ci.nsIMessageListenerManager) 129 | .loadFrameScript('chrome://kabl/content/kabl-frame.js', true); 130 | } 131 | }; 132 | 133 | window.addEventListener('load', gKabl.onChromeLoad, false); 134 | -------------------------------------------------------------------------------- /content/kabl-overlay.xul: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 13 | 14 | 17 | 20 | 23 | 26 | 27 | 28 | 29 | 30 | 31 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /content/kabl-parse.js: -------------------------------------------------------------------------------- 1 | // ***** BEGIN LICENSE BLOCK ***** 2 | // Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | // 4 | // The contents of this file are subject to the Mozilla Public License Version 5 | // 1.1 (the 'License'); you may not use this file except in compliance with 6 | // the License. You may obtain a copy of the License at 7 | // http://www.mozilla.org/MPL/ 8 | // 9 | // Software distributed under the License is distributed on an 'AS IS' basis, 10 | // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | // for the specific language governing rights and limitations under the 12 | // License. 13 | // 14 | // The Initial Developer of the Original Code is Anthony Lieuallen. 15 | // 16 | // Portions created by the Initial Developer are Copyright (C) 2007 17 | // the Initial Developer. All Rights Reserved. 18 | // 19 | // Alternatively, the contents of this file may be used under the terms of 20 | // either the GNU General Public License Version 2 or later (the 'GPL'), or 21 | // the GNU Lesser General Public License Version 2.1 or later (the 'LGPL'), 22 | // in which case the provisions of the GPL or the LGPL are applicable instead 23 | // of those above. If you wish to allow use of your version of this file only 24 | // under the terms of either the GPL or the LGPL, and not to allow others to 25 | // use your version of this file under the terms of the MPL, indicate your 26 | // decision by deleting the provisions above and replace them with the notice 27 | // and other provisions required by the GPL or the LGPL. If you do not delete 28 | // the provisions above, a recipient may use your version of this file under 29 | // the terms of any one of the MPL, the GPL or the LGPL. 30 | // 31 | // ***** END LICENSE BLOCK ***** 32 | 33 | var EXPORTED_SYMBOLS = ['gKablRulesObj', 'KablParseException']; 34 | 35 | // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // 36 | 37 | var gKablTokens=[]; 38 | // settings section 39 | gKablTokens['settings']='\\[Settings\\]'; 40 | gKablTokens['settings_cmd']='(?:threshold|cutoff|collapse)'; 41 | 42 | // inject section 43 | gKablTokens['inject']='\\[Inject\\]'; 44 | gKablTokens['inject_cmd']='(?:function)'; 45 | 46 | // group section 47 | gKablTokens['group']='\\[Group\\]'; 48 | gKablTokens['group_cmd']='(?:match|score|rule|name)'; 49 | gKablTokens['group_match_val']='(?:all|any)'; 50 | 51 | // fields 52 | gKablTokens['field']='(?:'+ 53 | '\\$thirdParty|\\$type'+ 54 | '|\\$url\\.?(?:host|path|scheme)?'+ 55 | '|\\$origin\\.tag\\.[a-zA-Z][a-zA-Z0-9]*'+ 56 | '|\\$origin\\.?(?:host|path|scheme|tag)?'+ 57 | ')'; 58 | gKablTokens['field_type_val']= 59 | '(?:script|image|stylesheet|object_subrequest|object|subdocument|ping|font|media|xmlhttprequest)'; 60 | 61 | // types 62 | gKablTokens['bool']='(?:true|false)'; 63 | gKablTokens['number']='-?\\d+(?:\\.\\d+)?'; 64 | gKablTokens['string']='(?:\'.*\'|".*")'; 65 | 66 | // operators 67 | gKablTokens['field_op']='(?:==|!=|=~|!~|\\^=|\\$=|<|>)'; 68 | gKablTokens['inieq']='='; 69 | 70 | // etc 71 | gKablTokens['comment']='^[;#].*'; 72 | gKablTokens['whitespace']='[ \t\\n\\r]'; 73 | 74 | var gKablIdxTokMap=[]; 75 | for (key in gKablTokens) { 76 | gKablIdxTokMap[gKablIdxTokMap.length]=key; 77 | } 78 | 79 | // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // 80 | 81 | function KablToken(type, val, cstart, cend) { 82 | this.type=type; 83 | this.val=val; 84 | this.cstart=cstart; 85 | this.cend=cend; 86 | } 87 | KablToken.prototype.toString = function() { 88 | return "{ " + this.type + ", \"" + this.val + "\" }"; 89 | }; 90 | 91 | function KablParseException(start, end, errMsg, token) { 92 | if (token) { 93 | errMsg=errMsg.replace('%%', token.val); 94 | } 95 | 96 | this.start=start; 97 | this.end=end; 98 | this.message=errMsg; 99 | 100 | this.toString=function() { 101 | return '[KablParseException '+start+';'+end+' '+errMsg+']'; 102 | }; 103 | } 104 | 105 | var untitledGroupNum=0; 106 | function defaultGroup() { 107 | this.score=1; 108 | this.match='any'; 109 | this.rules=[]; 110 | this.name='Untitled Group '+(++untitledGroupNum); 111 | }; 112 | 113 | // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // 114 | 115 | var gKablRulesObj={ 116 | ///////////////////////////////// DATA ///////////////////////////////////// 117 | 118 | // string rules turn into tokens, stored here 119 | rulesTok:[], 120 | 121 | // the actual rules data 122 | threshold:null, 123 | cutoff:null, 124 | collapse:null, 125 | groups:null, 126 | injectFunctions:null, 127 | injectFunctionsStr:'[]', 128 | 129 | /////////////////////////////// METHODS //////////////////////////////////// 130 | 131 | expect:function(expectTok, errMsg) { 132 | var tok=this.rulesTok.shift(); 133 | 134 | if (!tok) { 135 | throw new KablParseException(0, 0, 'Unexpected end of file'); 136 | } else if (expectTok!=tok.type) { 137 | throw new KablParseException(tok.cstart, tok.cend, errMsg, tok); 138 | } 139 | 140 | return tok; 141 | }, 142 | 143 | lex:function(rules) { 144 | // special case 145 | if (rules.match(/^\s*$/)) return true; 146 | 147 | // collapse defined tokens into a giant regex 148 | var tokRegex='', i=0, parens=''; 149 | for (key in gKablTokens) { 150 | tokRegex+=gKablTokens[key]+parens+'|'; 151 | parens+='()'; 152 | i++; 153 | } 154 | tokRegex=tokRegex.substring(0, tokRegex.length-1); 155 | tokRegex=new RegExp(tokRegex, 'gim'); 156 | 157 | // init empty, in case this isn't the first run 158 | this.rulesTok=[]; 159 | 160 | // use the giant regex to tokenize the string 161 | var prev_lastIndex=0; 162 | while (true) { 163 | var match=tokRegex.exec(rules); 164 | 165 | if (null==match) { 166 | throw new KablParseException( 167 | prev_lastIndex, tokRegex.lastIndex, 'Syntax error'); 168 | } else if (match.index!=prev_lastIndex) { 169 | // start of this isn't end of last 170 | throw new KablParseException( 171 | prev_lastIndex, match.index, 'Syntax error: illegal character(s)'); 172 | } else { 173 | var tokIdx=0; 174 | for (var i=0; i=rules.length) { 193 | // lexed the whole string, no errors thrown, we're done! 194 | break; 195 | } else { 196 | prev_lastIndex=tokRegex.lastIndex; 197 | } 198 | } 199 | }, 200 | 201 | parse:function(rules) { 202 | // this giant try lets us more cleanly terminate parsing at any point 203 | // by throwing a custom exception, even from subroutines 204 | try { 205 | // init default values 206 | this.threshold=10; 207 | this.cutoff=Number.MAX_VALUE; 208 | this.collapse=false; 209 | this.groups=[]; 210 | this.injectFunctions=[]; 211 | 212 | this.lex(rules); 213 | 214 | untitledGroupNum=0; 215 | 216 | // State: 217 | // 00 - started 218 | // 10 - in settings section 219 | // 20 - in group section 220 | // 30 - in inject section 221 | var tok=null, tok2=null, state=0, group=null; 222 | 223 | // parse the rules, by examining the tokens in order 224 | while (this.rulesTok.length>0) { 225 | tok=this.rulesTok.shift(); 226 | 227 | switch (tok.type) { 228 | //////////////////////////////////////////////////////////////// 229 | case 'settings': 230 | state=10; 231 | break; 232 | case 'settings_cmd': 233 | if (10!=state) { 234 | throw new KablParseException( 235 | tok.cstart, tok.cend, 236 | 'Unexpected '+tok.type+' outside of [Settings] section'); 237 | } 238 | 239 | switch (tok.val) { 240 | case 'threshold': 241 | case 'cutoff': 242 | this.expect('inieq', 'Unexpected "%%" expected: "="'); 243 | tok2=this.expect('number', 'Unexpected "%%" expected: number'); 244 | this[tok.val]=parseFloat(tok2.val); 245 | break; 246 | case 'collapse': 247 | this.expect('inieq', 'Unexpected "%%" expected: "="'); 248 | tok2=this.expect('bool', 'Unexpected "%%" expected: bool'); 249 | this.collapse='true'==tok2.val; 250 | break; 251 | } 252 | break; 253 | //////////////////////////////////////////////////////////////// 254 | case 'inject': 255 | state=30; 256 | break; 257 | case 'inject_cmd': 258 | if (30!=state) { 259 | throw new KablParseException( 260 | tok.cstart, tok.cend, 261 | 'Unexpected '+tok.type+' outside of [Inject] section'); 262 | } 263 | 264 | switch (tok.val) { 265 | case 'function': 266 | this.expect('inieq', 'Unexpected "%%" expected: "="'); 267 | tok2=this.expect('string', 'Unexpected "%%" expected: string'); 268 | this.injectFunctions.push( 269 | // strip off the quote marks 270 | tok2.val.substr(0, tok2.val.length-1).substr(1)); 271 | this.injectFunctionsStr=JSON.stringify(this.injectFunctions); 272 | break; 273 | } 274 | break; 275 | //////////////////////////////////////////////////////////////// 276 | case 'group': 277 | state=20; 278 | if (group) this.groups.push(group); 279 | group=new defaultGroup; 280 | break; 281 | case 'group_cmd': 282 | if (20!=state) { 283 | throw new KablParseException( 284 | tok.cstart, tok.cend, 285 | 'Unexpected "%%" outside of [Group] section', tok); 286 | } 287 | 288 | switch (tok.val) { 289 | case 'match': 290 | this.expect('inieq', 'Unexpected "%%" expected: "="'); 291 | tok2=this.expect('group_match_val', 'Unexpected "%%" expected: "any", "all"'); 292 | group.match=tok2.val; 293 | break; 294 | case 'score': 295 | this.expect('inieq', 'Unexpected "%%" expected: "="'); 296 | tok2=this.expect('number', 'Unexpected "%%" expected: number'); 297 | group.score=parseFloat(tok2.val); 298 | break; 299 | case 'rule': 300 | this.expect('inieq', 'Unexpected "%%" expected: "="'); 301 | group.rules.push(this.parseRule()); 302 | break; 303 | case 'name': 304 | this.expect('inieq', 'Unexpected "%%" expected: "="'); 305 | tok2=this.expect('string', 'Unexpected "%%" expected: string'); 306 | group.name=tok2.val.substring(1, tok2.val.length-1); 307 | untitledGroupNum--; 308 | break; 309 | } 310 | break; 311 | //////////////////////////////////////////////////////////////// 312 | default: 313 | throw new KablParseException( 314 | tok.cstart, tok.cend, 'Unexpected "%%"', tok); 315 | } 316 | } 317 | } catch (e) { 318 | // Used to do special handling here. Now just re-raise, so as to not 319 | // cause a whitespace diff for the whole body of the try. 320 | throw e; 321 | } 322 | 323 | // if the last parsed section was a group with rules, add it 324 | if (group && group.rules.length) this.groups.push(group); 325 | }, 326 | 327 | parseRule:function() { 328 | var fieldTok=this.expect('field', 'Unexpected "%%" expected: field'); 329 | var opTok=this.expect('field_op', 'Unexpected "%%" expected: field operator'); 330 | 331 | var valTok=null, val=null; 332 | 333 | switch (true) { 334 | case '$thirdParty'==fieldTok.val: 335 | valTok=this.expect('bool', 'Unexpected "%%" expected: true, false'); 336 | val='true'===valTok.val?true:false; 337 | break; 338 | case '$type'==fieldTok.val: 339 | valTok=this.expect('field_type_val', 'Unexpected "%%" expected: type'); 340 | // ensure type 341 | val=Components.interfaces.nsIContentPolicy[ 342 | 'TYPE_'+valTok.val.toUpperCase() 343 | ]; 344 | break; 345 | case '$origin'==fieldTok.val.substring(0, 7): 346 | case '$url'==fieldTok.val.substring(0, 4): 347 | if ('<'==opTok.val || '>'==opTok.val) { 348 | valTok=this.expect('number', 'Unexpected "%%" expected: number'); 349 | val=parseFloat(valTok.val); // ensure type 350 | } else { 351 | valTok=this.expect('string', 'Unexpected "%%" expected: string'); 352 | val=valTok.val.toLowerCase(); // ensure type, case insensitivity 353 | val=val.substr(0, val.length-1).substr(1); // strip off the quote marks 354 | } 355 | break; 356 | default: 357 | throw new KablParseException( 358 | fieldTok.cstart, fieldTok.cend, 359 | 'Unexpected "%%", expected: field', field 360 | ); 361 | } 362 | 363 | var regexVal = null; 364 | if ('=~' == opTok.val || '!~' == opTok.val) { 365 | try { 366 | regexVal=new RegExp(val); 367 | } catch (e) { 368 | throw new KablParseException( 369 | valTok.cstart, valTok.cend, 370 | 'Invalid regular expression: %%', {val: e} 371 | ); 372 | } 373 | } 374 | 375 | if (typeof val != 'null') { 376 | return { 377 | field:fieldTok.val, 378 | op:opTok.val, 379 | val:val, 380 | regexVal:regexVal, 381 | match:null 382 | }; 383 | } else { 384 | return null; 385 | } 386 | } 387 | }; 388 | -------------------------------------------------------------------------------- /content/kabl-policy.js: -------------------------------------------------------------------------------- 1 | // ***** BEGIN LICENSE BLOCK ***** 2 | // Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | // 4 | // The contents of this file are subject to the Mozilla Public License Version 5 | // 1.1 (the 'License'); you may not use this file except in compliance with 6 | // the License. You may obtain a copy of the License at 7 | // http://www.mozilla.org/MPL/ 8 | // 9 | // Software distributed under the License is distributed on an 'AS IS' basis, 10 | // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | // for the specific language governing rights and limitations under the 12 | // License. 13 | // 14 | // The Initial Developer of the Original Code is Anthony Lieuallen. 15 | // 16 | // Portions created by the Initial Developer are Copyright (C) 2007 17 | // the Initial Developer. All Rights Reserved. 18 | // 19 | // Alternatively, the contents of this file may be used under the terms of 20 | // either the GNU General Public License Version 2 or later (the 'GPL'), or 21 | // the GNU Lesser General Public License Version 2.1 or later (the 'LGPL'), 22 | // in which case the provisions of the GPL or the LGPL are applicable instead 23 | // of those above. If you wish to allow use of your version of this file only 24 | // under the terms of either the GPL or the LGPL, and not to allow others to 25 | // use your version of this file under the terms of the MPL, indicate your 26 | // decision by deleting the provisions above and replace them with the notice 27 | // and other provisions required by the GPL or the LGPL. If you do not delete 28 | // the provisions above, a recipient may use your version of this file under 29 | // the terms of any one of the MPL, the GPL or the LGPL. 30 | // 31 | // ***** END LICENSE BLOCK ***** 32 | 33 | var EXPORTED_SYMBOLS = ['gKablPolicy']; 34 | 35 | var Cc = Components.classes; 36 | var Ci = Components.interfaces; 37 | var Cu = Components.utils; 38 | 39 | Cu.import('chrome://kabl/content/kabl-parse.js'); 40 | Cu.import('chrome://kabl/content/kabl-pref.js'); 41 | Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 42 | 43 | var gKablCollapseMarker=String(Math.floor(Math.random()*100000)); 44 | var UNORDERED_NODE_SNAPSHOT_TYPE=6; 45 | var COLLAPSE_TEXT_LENGTH=25; 46 | 47 | var gMessageSender = Cc['@mozilla.org/childprocessmessagemanager;1'] 48 | .getService(Ci.nsIMessageSender); 49 | 50 | //\\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // 51 | 52 | // constructor for details of the request 53 | function Fields(type, loc, org, node) { 54 | this['$type']=type; 55 | 56 | this['$url']=loc.spec; 57 | this['$url.host']=loc.host; 58 | this['$url.path']=loc.path; 59 | this['$url.scheme']=loc.scheme; 60 | 61 | // Set base values. 62 | this['$thirdParty']=false; 63 | this['$origin']=undefined; 64 | this['$origin.host']=undefined; 65 | this['$origin.path']=undefined; 66 | this['$origin.scheme']=undefined; 67 | this['$origin.tag']=undefined; 68 | 69 | if ('about:feeds' == org.spec) { 70 | var ioService = Cc["@mozilla.org/network/io-service;1"] 71 | .getService(Ci.nsIIOService); 72 | org = ioService.newURI(node.ownerDocument.location.href, null, null); 73 | } 74 | 75 | // Conditionally override them based on scheme. 76 | switch (org.scheme) { 77 | case 'about': 78 | this['$origin']=org.spec; 79 | setOriginTag(this, node); 80 | 81 | break; 82 | case 'file': 83 | case 'chrome': 84 | this['$origin']=org.spec; 85 | this['$origin.path']=org.path; 86 | this['$origin.scheme']=org.scheme; 87 | 88 | setOriginTag(this, node); 89 | 90 | break; 91 | case 'ftp': 92 | case 'http': 93 | case 'https': 94 | var lHost=loc.host; 95 | var oHost=org.host; 96 | if (!lHost.match(/^[0-9.]+$/)) { 97 | lHost=hostToTld(lHost); 98 | oHost=hostToTld(oHost); 99 | } 100 | this['$thirdParty']=(lHost!=oHost); 101 | 102 | this['$origin']=org.spec; 103 | this['$origin.host']=org.host; 104 | this['$origin.path']=org.path; 105 | this['$origin.scheme']=org.scheme; 106 | 107 | setOriginTag(this, node); 108 | 109 | break; 110 | default: 111 | if (gKablPrefs.debug) { 112 | dump('kabl error condition, unknown origin scheme for\n\t'+org.spec+'\n'); 113 | } 114 | break; 115 | } 116 | 117 | for (var i=0, key=null; key=fieldNames[i]; i++) { 118 | if ('string'==typeof this[key]) this[key]=this[key].toLowerCase(); 119 | } 120 | 121 | this.node=node; 122 | } 123 | 124 | function cloneObject(obj) { 125 | if (null==obj || 'object'!=typeof obj) { 126 | return obj; 127 | } 128 | 129 | var out=new obj.constructor(); 130 | for (var key in obj) { 131 | if (key=="regexVal") { 132 | // would have preferred to check "instanceof RegExp", but it fails when called from extensions 133 | //special case to avoid destroying the cached regex 134 | out[key]=obj[key]; 135 | } else { 136 | out[key]=cloneObject(obj[key]); 137 | } 138 | } 139 | 140 | return out; 141 | } 142 | 143 | // true if group matches 144 | function evalGroup(group, fields) { 145 | var flag=null; 146 | 147 | for (var j=0, rule=null; rule=group.rules[j]; j++) { 148 | flag=false; 149 | 150 | if (!(rule.field in fields)) continue; 151 | var fieldVal=fields[rule.field]; 152 | switch (rule.op) { 153 | case '==': 154 | flag=fieldVal==rule.val; 155 | break; 156 | case '!=': 157 | flag=fieldVal!=rule.val; 158 | break; 159 | case '=~': 160 | flag=rule.regexVal.test(fieldVal); 161 | break; 162 | case '!~': 163 | flag=!rule.regexVal.test(fieldVal); 164 | break; 165 | case '^=': 166 | flag=fieldVal.substr(0, rule.val.length)==rule.val; 167 | break; 168 | case '$=': 169 | flag=fieldVal.substr(fieldVal.length-rule.val.length)==rule.val; 170 | break; 171 | case '<': 172 | fieldVal=parseFloat(fieldVal); 173 | flag=(!isNaN(fieldVal)) && fieldVal': 176 | fieldVal=parseFloat(fieldVal); 177 | flag=(!isNaN(fieldVal)) && fieldVal>rule.val; 178 | break; 179 | } 180 | 181 | if (monitoring) rule.match=flag; 182 | 183 | if (flag && 'any'==group.match) { 184 | return true; 185 | } else if (!flag && 'all'==group.match) { 186 | return false; 187 | } 188 | } 189 | 190 | if (flag && 'all'==group.match) { 191 | return true; 192 | } 193 | } 194 | 195 | function hostToTld(host) { 196 | // this terribly simple method seems to work well enough 197 | return host.replace(/.*\.(.*......)/, '$1'); 198 | } 199 | 200 | // evaluate if/how we should handle this type of score 201 | function evalScore(type, score, fields) { 202 | if (('threshold'==type && score>=gKablRulesObj.threshold) || 203 | ('cutoff'==type && score>=gKablRulesObj.cutoff) 204 | ) { 205 | try { 206 | var el=fields.node 207 | .QueryInterface(Components.interfaces.nsIDOMNode); 208 | } catch (e) { 209 | if (gKablPrefs.debug) dump('Error in evalScore: '+e+'\n'); 210 | return; 211 | } 212 | 213 | // Attempt to hide the node, i.e. if a non-loaded image will 214 | // result in an alt tag showing. 215 | try { 216 | el.setAttribute('style', 'display: none !important'); 217 | } catch (e) { 218 | if (gKablPrefs.debug) dump('Error in evalScore: '+e+'\n'); 219 | } 220 | 221 | // Mark the node for collapsing. 222 | try { 223 | if ('STYLE'!=el.tagName) { 224 | el.setAttribute('kabl', gKablCollapseMarker); 225 | } 226 | } catch (e) { 227 | if (gKablPrefs.debug) dump('Error in evalScore: '+e+'\n'); 228 | } 229 | 230 | return REJECT; 231 | } else if ('threshold'==type || 232 | ('cutoff'==type && Math.abs(score)>=gKablRulesObj.cutoff) 233 | ) { 234 | return ACCEPT; 235 | } else { 236 | return undefined; 237 | } 238 | } 239 | 240 | function monitorAdd(fields, groups, score, flag) { 241 | if (!monitoring) return; 242 | 243 | var blocked=REJECT==flag; 244 | 245 | try { 246 | var filteredFields = {}; 247 | for (i in fields) { 248 | var t = typeof fields[i]; 249 | if (t == 'string' || t == 'number') filteredFields[i] = fields[i] 250 | } 251 | gMessageSender.sendAsyncMessage('kabl:monitor', { 252 | 'fields': filteredFields, 253 | 'groups': groups, 254 | 'score': score, 255 | 'blocked': blocked, 256 | }); 257 | } catch (e) { 258 | dump('ERROR in monitorAdd: ' + e + '\n\n'); 259 | } 260 | } 261 | 262 | function setOriginTag(obj, node) { 263 | obj['$origin.tag']=node.tagName; 264 | 265 | if (!node.attributes) return; 266 | for (var i=0, attr=null; attr=node.attributes.item(i); i++) { 267 | obj['$origin.tag.'+attr.nodeName]=attr.value.toLowerCase(); 268 | } 269 | 270 | if (obj['$origin.tag.width'] && obj['$origin.tag.height']) { 271 | obj['$origin.tag.size']=obj['$origin.tag.width'] 272 | +'x'+obj['$origin.tag.height']; 273 | } 274 | } 275 | 276 | function strippedTextContent(el) { 277 | var text=el.innerHTML || el.textContent; 278 | if (!text) return ''; 279 | 280 | text=text.replace(/[\s]+/g, ' '); //collapse whitespace 281 | text=text.replace(/^\s+|\s+$/g, ''); //strip leading/trailing whitespace 282 | text=text.replace(//gi, ''); //strip js 283 | text=text.replace(//gi, ''); //strip no-js 284 | text=text.replace(//gi, ''); // iframe, alternate content 285 | text=text.replace(//gi, ''); //strip comments 286 | text=text.replace(/<\/?[^>]+>/gi, ''); //strip tags 287 | 288 | return text; 289 | } 290 | 291 | //Inherited from AdBlock Plus, utils.js 292 | function windowForNode(node) { 293 | if (node && node.nodeType!=Components.interfaces.nsIDOMNode.DOCUMENT_NODE) { 294 | node = node.ownerDocument; 295 | } 296 | 297 | if (!node || node.nodeType!=Components.interfaces.nsIDOMNode.DOCUMENT_NODE) { 298 | return null; 299 | } 300 | 301 | return node.defaultView; 302 | } 303 | 304 | //\\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // 305 | 306 | var ACCEPT=Components.interfaces.nsIContentPolicy.ACCEPT; 307 | var REJECT=Components.interfaces.nsIContentPolicy.REJECT_REQUEST; 308 | 309 | var fieldNames=['$type', '$thirdParty', 310 | '$url', '$url.host', '$url.path', '$url.scheme', 311 | '$origin', '$origin.host', '$origin.path', '$origin.scheme', '$origin.tag']; 312 | 313 | var monitoring=false; 314 | 315 | //\\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // 316 | 317 | var startupDone=false; 318 | 319 | var gKablPolicy={ 320 | classDescription: 'Karma Blocker content policy', 321 | classID: Components.ID('cabe6b3f-578c-480f-a2f0-68bc4b7a1142'), 322 | contractID: '@arantius.com/kabl-policy;1', 323 | 324 | QueryInterface: XPCOMUtils.generateQI( 325 | [Ci.nsIContentPolicy, Ci.nsIFactory, Ci.nsISupportsWeakReference]), 326 | 327 | // nsIFactory 328 | createInstance:function(outer, iid) { 329 | if (outer) throw Cr.NS_ERROR_NO_AGGREGATION; 330 | return this.QueryInterface(iid); 331 | }, 332 | 333 | // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // 334 | 335 | startup:function(outer, iid) { 336 | if (startupDone) return; 337 | startupDone=true; 338 | 339 | // set up initial parsed rules object 340 | gKablRulesObj.parse(gKablPrefs.rules); 341 | 342 | try { 343 | var registrar = Components.manager.QueryInterface( 344 | Ci.nsIComponentRegistrar); 345 | registrar.registerFactory( 346 | gKablPolicy.classID, gKablPolicy.classDescription, 347 | gKablPolicy.contractID, gKablPolicy); 348 | } catch (e) { 349 | dump('KABL registration error: '+e+'\n'); 350 | } 351 | 352 | var categoryManager = Cc['@mozilla.org/categorymanager;1'] 353 | .getService(Ci.nsICategoryManager); 354 | categoryManager.addCategoryEntry( 355 | 'content-policy', gKablPolicy.classDescription, 356 | gKablPolicy.contractID, false, true); 357 | 358 | var cpmm = Cc['@mozilla.org/childprocessmessagemanager;1'] 359 | .getService(Ci.nsIMessageListenerManager); 360 | cpmm.addMessageListener('kabl:monitor-opened', function() { 361 | monitoring=true; 362 | }); 363 | cpmm.addMessageListener('kabl:monitor-closed', function() { 364 | monitoring=false; 365 | }); 366 | }, 367 | 368 | collapse:function(event) { 369 | // Don't continue if we're configured not to do collapsing. 370 | if (!gKablRulesObj.collapse) return; 371 | 372 | // called when a content page loads, this looks for elements that were 373 | // marked as blocked, and looks for a parent node that should be 374 | // collapsed down (because it's probably just a wrapper around the ad) 375 | 376 | var doc=event.target; 377 | var xpr=doc.evaluate( 378 | '//*[@kabl="'+gKablCollapseMarker+'"]', 379 | doc, null, UNORDERED_NODE_SNAPSHOT_TYPE, null); 380 | for (var i=0, item=null; item=xpr.snapshotItem(i); i++) { 381 | // Climb the DOM, from this item, to find a container to collapse. 382 | var el=null; 383 | while (item=item.parentNode) { 384 | // Before we pick this as a collapsing candidate, check for 385 | // stop conditions. 386 | if ('BODY'==item.tagName) break; 387 | if ('HTML'==item.tagName) break; 388 | if (0!=item.getElementsByTagName('form').length) break; 389 | if (strippedTextContent(item).length>COLLAPSE_TEXT_LENGTH) break; 390 | 391 | el=item; 392 | } 393 | 394 | // If we selected an item, collapse it. 395 | // try block just in case, attempt to hide the node, i.e. 396 | // if a non-loaded image will result in an alt tag showing 397 | try { 398 | if (el) { 399 | el=el.QueryInterface(Components.interfaces.nsIDOMNode); 400 | el.setAttribute('style', 'display: none !important'); 401 | el.setAttribute('kablcollapse', '1'); 402 | } 403 | } catch (e) { 404 | if (gKablPrefs.debug) dump('Error in collapse: '+e+'\n'); 405 | } 406 | } 407 | }, 408 | 409 | // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // 410 | 411 | // nsIContentPolicy 412 | shouldLoad:function(contentType, contentLocation, requestOrigin, 413 | requestingNode, mimeTypeGuess, extra) { 414 | try { 415 | 416 | // when not enabled, let it through 417 | if (!gKablPrefs.enabled) { 418 | return ACCEPT; 419 | } 420 | 421 | // it's not a remote scheme, definitely let it through 422 | if (!contentLocation.schemeIs('http') && 423 | !contentLocation.schemeIs('https') && 424 | !contentLocation.schemeIs('chrome') && 425 | !contentLocation.schemeIs('ftp') 426 | ) { 427 | return ACCEPT; 428 | } 429 | 430 | // never block core parts of the browser 431 | if ('chrome://global/'==contentLocation.spec.substr(0, 16) 432 | || 'chrome://browser/'==contentLocation.spec.substr(0, 17) 433 | ) { 434 | return ACCEPT; 435 | } 436 | 437 | // if it is chrome, and so is the origin, let it through 438 | if (contentLocation.schemeIs('chrome') && 439 | requestOrigin && requestOrigin.schemeIs('chrome') 440 | ) { 441 | return ACCEPT; 442 | } 443 | 444 | // Only block in content windows (this from AdBlock Plus) 445 | var win=windowForNode(requestingNode); 446 | if (!win) return ACCEPT; 447 | var winType=win 448 | .QueryInterface(Components.interfaces.nsIInterfaceRequestor) 449 | .getInterface(Components.interfaces.nsIWebNavigation) 450 | .QueryInterface(Components.interfaces.nsIDocShellTreeItem) 451 | .itemType; 452 | if (winType!=Components.interfaces.nsIDocShellTreeItem.typeContent) { 453 | return ACCEPT; 454 | } 455 | 456 | // Start checking for whether we should block! 457 | var fields=new Fields( 458 | contentType, contentLocation, requestOrigin, requestingNode); 459 | var monitorGroups=[]; 460 | 461 | var score=0, flag=false; 462 | for (var i=0, group=null; group=gKablRulesObj.groups[i]; i++) { 463 | if (monitoring) { 464 | group=cloneObject(group); 465 | monitorGroups.push(group); 466 | } 467 | 468 | if (evalGroup(group, fields, monitoring)) { 469 | score+=group.score; 470 | flag=evalScore('cutoff', score, fields); 471 | if (flag) { 472 | if (monitoring) { 473 | monitorGroups.push({ 474 | 'name': 'Cutoff score reached, processing halted.', 475 | 'score': null, 'match': null, 'rules': null}); 476 | } 477 | break; 478 | } 479 | } else { 480 | if (monitoring) group.score=0; 481 | } 482 | } 483 | 484 | if (!flag) { 485 | flag=evalScore('threshold', score, fields); 486 | } 487 | 488 | if (!flag) flag=ACCEPT; 489 | 490 | if (monitoring) monitorAdd(fields, monitorGroups, score, flag); 491 | return flag; 492 | 493 | } catch (e) { 494 | dump('ERROR IN kabl policy: ' + e + '\n'); 495 | for (var i in e) dump(i+' '+e[i]+'\n'); 496 | return ACCEPT; 497 | } 498 | }, 499 | 500 | shouldProcess:function(contentType, contentLocation, requestOrigin, 501 | requestingNode, mimeType, extra) { 502 | return ACCEPT; 503 | } 504 | }; 505 | -------------------------------------------------------------------------------- /content/kabl-pref.js: -------------------------------------------------------------------------------- 1 | // ***** BEGIN LICENSE BLOCK ***** 2 | // Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | // 4 | // The contents of this file are subject to the Mozilla Public License Version 5 | // 1.1 (the 'License'); you may not use this file except in compliance with 6 | // the License. You may obtain a copy of the License at 7 | // http://www.mozilla.org/MPL/ 8 | // 9 | // Software distributed under the License is distributed on an 'AS IS' basis, 10 | // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | // for the specific language governing rights and limitations under the 12 | // License. 13 | // 14 | // The Initial Developer of the Original Code is Anthony Lieuallen. 15 | // 16 | // Portions created by the Initial Developer are Copyright (C) 2007 17 | // the Initial Developer. All Rights Reserved. 18 | // 19 | // Alternatively, the contents of this file may be used under the terms of 20 | // either the GNU General Public License Version 2 or later (the 'GPL'), or 21 | // the GNU Lesser General Public License Version 2.1 or later (the 'LGPL'), 22 | // in which case the provisions of the GPL or the LGPL are applicable instead 23 | // of those above. If you wish to allow use of your version of this file only 24 | // under the terms of either the GPL or the LGPL, and not to allow others to 25 | // use your version of this file under the terms of the MPL, indicate your 26 | // decision by deleting the provisions above and replace them with the notice 27 | // and other provisions required by the GPL or the LGPL. If you do not delete 28 | // the provisions above, a recipient may use your version of this file under 29 | // the terms of any one of the MPL, the GPL or the LGPL. 30 | // 31 | // ***** END LICENSE BLOCK ***** 32 | 33 | var EXPORTED_SYMBOLS=[ 34 | 'gKablLoad', 'gKablPrefs', 'gKablSet', 'gKablSave']; 35 | 36 | Components.utils.import('chrome://kabl/content/kabl-parse.js'); 37 | 38 | // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // 39 | 40 | var prefBranch=Components.classes['@mozilla.org/preferences-service;1'] 41 | .getService(Components.interfaces.nsIPrefService) 42 | .getBranch('extensions.kabl.'); 43 | 44 | // globals that hold the settings 45 | var gKablPrefs={ 46 | 'debug':null, 47 | 'enabled':null, 48 | 'rules':null, 49 | 'sync_enabled':null, 50 | 'sync_check_interval':null, 51 | 'sync_last_rules':null, 52 | 'sync_last_time':null, 53 | 'sync_update_interval':null, 54 | 'sync_url':null}; 55 | 56 | function gKablLoad() { 57 | gKablPrefs.debug=prefBranch.getIntPref('debug'); 58 | gKablPrefs.enabled=prefBranch.getBoolPref('enabled'); 59 | gKablPrefs.rules=prefBranch.getCharPref('rules'); 60 | gKablPrefs.sync_enabled=prefBranch.getBoolPref('sync_enabled'); 61 | gKablPrefs.sync_check_interval=prefBranch.getIntPref('sync_check_interval'); 62 | gKablPrefs.sync_last_rules=prefBranch.getCharPref('sync_last_rules'); 63 | gKablPrefs.sync_last_time=parseFloat(prefBranch.getCharPref('sync_last_time')); 64 | gKablPrefs.sync_update_interval=prefBranch.getIntPref('sync_update_interval'); 65 | gKablPrefs.sync_url=prefBranch.getCharPref('sync_url'); 66 | } 67 | 68 | function gKablSave() { 69 | prefBranch.setIntPref('debug', gKablPrefs.debug); 70 | prefBranch.setBoolPref('enabled', gKablPrefs.enabled); 71 | prefBranch.setCharPref('rules', gKablPrefs.rules); 72 | prefBranch.setBoolPref('sync_enabled', gKablPrefs.sync_enabled); 73 | prefBranch.setIntPref('sync_check_interval', gKablPrefs.sync_check_interval); 74 | prefBranch.setCharPref('sync_last_rules', gKablPrefs.sync_last_rules); 75 | prefBranch.setCharPref('sync_last_time', String(gKablPrefs.sync_last_time)); 76 | prefBranch.setIntPref('sync_update_interval', gKablPrefs.sync_update_interval); 77 | prefBranch.setCharPref('sync_url', gKablPrefs.sync_url); 78 | } 79 | 80 | function gKablSet(name, value) { 81 | gKablPrefs[name]=value; 82 | gKablSave(); 83 | } 84 | 85 | // run the passed function on all navigator windows 86 | function withAllChrome(func) { 87 | var mediator=Components.classes['@mozilla.org/appshell/window-mediator;1'] 88 | .getService(Components.interfaces.nsIWindowMediator); 89 | var winEnum=mediator.getEnumerator('navigator:browser'); 90 | while (winEnum.hasMoreElements()){ 91 | func(winEnum.getNext()); 92 | } 93 | } 94 | 95 | var gKablPrefObserver={ 96 | _branch:null, 97 | 98 | register:function() { 99 | prefBranch.QueryInterface(Components.interfaces.nsIPrefBranch2); 100 | prefBranch.addObserver('', this, false); 101 | }, 102 | 103 | observe:function(aSubject, aTopic, aData) { 104 | if('nsPref:changed'!=aTopic) return; 105 | // aSubject is the nsIPrefBranch we're observing (after appropriate QI) 106 | // aData is the name of the pref that's been changed (relative to aSubject) 107 | gKablLoad(); 108 | switch (aData) { 109 | case 'enabled': 110 | withAllChrome(function(win) { win.gKabl.setToolbarButtonState(); }); 111 | break; 112 | case 'rules': 113 | gKablRulesObj.parse(prefBranch.getCharPref('rules')); 114 | break; 115 | } 116 | } 117 | }; 118 | 119 | gKablPrefObserver.register(); 120 | gKablLoad(); 121 | -------------------------------------------------------------------------------- /content/kabl-sync.js: -------------------------------------------------------------------------------- 1 | // ***** BEGIN LICENSE BLOCK ***** 2 | // Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | // 4 | // The contents of this file are subject to the Mozilla Public License Version 5 | // 1.1 (the 'License'); you may not use this file except in compliance with 6 | // the License. You may obtain a copy of the License at 7 | // http://www.mozilla.org/MPL/ 8 | // 9 | // Software distributed under the License is distributed on an 'AS IS' basis, 10 | // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | // for the specific language governing rights and limitations under the 12 | // License. 13 | // 14 | // The Initial Developer of the Original Code is Anthony Lieuallen. 15 | // 16 | // Portions created by the Initial Developer are Copyright (C) 2007 17 | // the Initial Developer. All Rights Reserved. 18 | // 19 | // Alternatively, the contents of this file may be used under the terms of 20 | // either the GNU General Public License Version 2 or later (the 'GPL'), or 21 | // the GNU Lesser General Public License Version 2.1 or later (the 'LGPL'), 22 | // in which case the provisions of the GPL or the LGPL are applicable instead 23 | // of those above. If you wish to allow use of your version of this file only 24 | // under the terms of either the GPL or the LGPL, and not to allow others to 25 | // use your version of this file under the terms of the MPL, indicate your 26 | // decision by deleting the provisions above and replace them with the notice 27 | // and other provisions required by the GPL or the LGPL. If you do not delete 28 | // the provisions above, a recipient may use your version of this file under 29 | // the terms of any one of the MPL, the GPL or the LGPL. 30 | // 31 | // ***** END LICENSE BLOCK ***** 32 | 33 | var EXPORTED_SYMBOLS=['gKablRuleSync']; 34 | 35 | var Cc = Components.classes; 36 | var Ci = Components.interfaces; 37 | var Cu = Components.utils; 38 | 39 | Cu.import('chrome://kabl/content/kabl-lib.js'); 40 | Cu.import('chrome://kabl/content/kabl-pref.js'); 41 | Cu.import("resource://gre/modules/Services.jsm"); 42 | Cu.import("resource://gre/modules/PopupNotifications.jsm"); 43 | 44 | // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // 45 | 46 | function gKablRuleSync(callback, force, url) { 47 | if (!force && !gKablPrefs.sync_enabled) return; 48 | 49 | gKablSet('sync_last_time', new Date().valueOf()); 50 | 51 | var xhr=Cc["@mozilla.org/xmlextras/xmlhttprequest;1"] 52 | .createInstance(Ci.nsIXMLHttpRequest); 53 | xhr.open('GET', url || gKablPrefs.sync_url, true); 54 | xhr.onreadystatechange = function() { 55 | if (4!=xhr.readyState) return; 56 | if (200!=xhr.status) return; 57 | gKablRuleSyncApply(force, callback, xhr.responseText); 58 | }; 59 | xhr.send(null); 60 | } 61 | 62 | function gKablRuleSyncApply(force, callback, newRules) { 63 | if (!force 64 | && gKablPrefs.rules!=gKablPrefs.sync_last_rules 65 | && gKablPrefs.rules!=newRules) { 66 | var line1='Karma Blocker Sync Confirmation'; 67 | var line2='The local ruleset has changed since the last sync.\n' 68 | +'Destroy changes and apply update?'; 69 | var win=gKablActiveWin(); 70 | if (win && win == gKablBrowserWin()) { 71 | win.PopupNotifications.show( 72 | win.gBrowser.selectedBrowser, 73 | 'kabl-update-conflict', 74 | line1+'. '+line2, 75 | 'tb-kabl', 76 | { 77 | label: 'Apply update', 78 | accessKey: 'a', 79 | callback: function() { 80 | gKablRuleSyncApply(true, callback, newRules); 81 | } 82 | }, 83 | null); 84 | } else { 85 | var doSync=Services.prompt.confirm(null, line1, line2); 86 | if (doSync) gKablRuleSyncApply(true, callback, newRules); 87 | } 88 | return; 89 | } 90 | 91 | gKablSet('sync_last_rules', newRules); 92 | gKablSet('rules', newRules); 93 | callback && callback(); 94 | } 95 | 96 | var timerCallback={ 97 | notify:function(timer) { 98 | var now=new Date().valueOf(); 99 | if (now < gKablPrefs.sync_last_time+gKablPrefs.sync_update_interval) { 100 | return; 101 | } 102 | gKablRuleSync(); 103 | } 104 | }; 105 | 106 | var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); 107 | // Once in a few seconds (after load), and .. 108 | timer.initWithCallback(timerCallback, 10000, Ci.nsITimer.TYPE_ONE_shot); 109 | // .. once every hour (check_interval). 110 | timer.initWithCallback(timerCallback, gKablPrefs.sync_check_interval, 111 | Ci.nsITimer.TYPE_REPEATING_SLACK); 112 | -------------------------------------------------------------------------------- /defaults/preferences/kabl.js: -------------------------------------------------------------------------------- 1 | pref('extensions.kabl.enabled', true); 2 | pref('extensions.kabl.debug', 0); 3 | pref("extensions.kabl.rules", "# This is a ruleset configuration for Karma Blocker. For more information, see:\n# http://trac.arantius.com/wiki/Extensions/KarmaBlocker\n\n# This default ruleset is intended to be demonstrative: making productive\n# use of all the features that the Karma Blocker rule syntax provides. It\n# should generally work, but it has intentionally not been tweaked to deal\n# with the particulars of any given site. All rules here are intended to\n# explain what can be done, and how it can be done, while remaining as\n# generic as possible, with limited exceptions. You the user are expected\n# to tweak and customize these rules.\n[Settings]\nthreshold=12\ncutoff=12\ncollapse=false\n\n[Inject]\nfunction='DM_tag'\nfunction='OA_show'\nfunction='_gat._getTracker'\nfunction='quantserve'\nfunction='s.t'\nfunction='setOmniturePageName'\nfunction='urchinTracker'\n\n# If any request that a Flash movie makes is blocked, the entire Flash\n# movie will remove itself from the page. So if we let the movie\n# through, we let all requests it makes go through, with this rule.\n[Group]\nname=\"Whitelist: flash sub-request\"\nscore=-13\nrule=$type==object_subrequest\n\n# eBay uses third-party iframes for auction descriptions now, to\n# prevent the XSS hole they left open for a long time.\n[Group]\nname=\"Whitelist: eBay\"\nmatch=any\nscore=-13\nrule=$url.host=='cgi.ebay.com'\nrule=$url.host=='vi.ebaydesc.com'\nrule=$url.host=='srx.main.ebayrtm.com'\n\n[Group]\nname=\"Whitelist: HTTPS\"\nscore=-4\nrule=$url.scheme=='https'\n\n[Group]\nname=\"Whitelist: CDNs\"\nscore=-4\nmatch=any\nrule=$url.host$='.akamai.com'\nrule=$url.host$='.asset-cache.com'\nrule=$url.host$='.cachefly.com'\nrule=$url.host$='.fsdn.com'\nrule=$url.host$='.ggpht.com'\nrule=$url.host$='.gstatic.com'\nrule=$url.host=~'cdn'\n\n[Group]\nname=\"Whitelist: Keywords\"\nscore=-4\nmatch=any\nrule=$url=~'(\\b|_)(downlo|uplo)ads?\\d*(\\b|_)'\n\n[Group]\nname=\"(I)FRAMEs and Scripts\"\nscore=6\nmatch=any\nrule=$type==script\nrule=$type==subdocument\n\n[Group]\nname=\"Feed Trackers\"\nscore=4\nmatch=any\nrule=$url.path=~'^/~.{1,2}/'\nrule=$url^='http://feeds.wordpress.com/1.0/'\n\n[Group]\nname=\"Size: 0x0 & 1x1\"\nscore=4\nmatch=any\nrule=$origin.tag.size=='0x0'\nrule=$origin.tag.size=='1x1'\n\n# See: http://www.iab.net/iab_products_and_industry_services/1421/1443/1452\n[Group]\nname=\"Size: Standard Banner\"\nscore=4\nmatch=any\nrule=$origin.tag.size=='300x250'\nrule=$origin.tag.size=='468x60'\nrule=$origin.tag.size=='234x60'\nrule=$origin.tag.size=='88x31'\nrule=$origin.tag.size=='120x90'\nrule=$origin.tag.size=='120x60'\nrule=$origin.tag.size=='120x240'\nrule=$origin.tag.size=='125x125'\nrule=$origin.tag.size=='728x90'\nrule=$origin.tag.size=='160x600'\nrule=$origin.tag.size=='120x600'\nrule=$origin.tag.size=='300x600'\n\n[Group]\nname=\"Third-party\"\nscore=4\nrule=$thirdParty==true\n\n[Group]\nname=\"Unsavory hosts\"\nscore=4\nmatch=any\nrule=$url.host$='.addtoany.com'\nrule=$url.host$='.blogads.com'\nrule=$url.host$='.imrworldwide.com'\nrule=$url.host$='.kontera.com'\nrule=$url.host$='.scorecardresearch.com'\nrule=$url.host$='.statcounter.com'\n\n[Group]\nname=\"Images\"\nscore=3\nrule=$type==image\n\n[Group]\nname=\"Extra-long URLs\"\nscore=2\nrule=$url.path=~'.{175}'\n\n[Group]\nname=\"Keywords (Full)\"\nscore=2\nrule=$url=~'(\\b|_)ad(frame|sense|server?|sonar)?s?\\d*(\\b|_)'\nrule=$url=~'(\\b|_)banners?\\d*(\\b|_)'\nrule=$url=~'(\\b|_)(analytic|quant|s_code|track|urchin|webtrend)(s|er|ing)?\\d*(\\b|_)'\nrule=$url.host=~'metrics'\n\n[Group]\nname=\"Keywords (Partial)\"\nscore=2\nrule=$url=~'(\\b|_)ads?\\d*|ads?\\d*(\\b|_)'\nrule=$url=~'(\\b|_)track(s|er|ing)?\\d*|track(s|er|ing)?\\d*(\\b|_)'\n\n[Group]\nname=\"Long Querystring\"\nscore=2\nmatch=all\nrule=$url.path=~'\\?(.*&){6,}'\n\n[Group]\nname=\"Objects (Flash)\"\nscore=2\nrule=$type==object\n\n[Group]\nname=\"Querystring\"\nscore=1\nrule=$url.path=~'\\?'"); 4 | pref('extensions.kabl.sync_enabled', false); 5 | pref('extensions.kabl.sync_check_interval', 3600000); // ms = 1 hour 6 | pref('extensions.kabl.sync_last_rules', ''); 7 | pref('extensions.kabl.sync_last_time', '0'); 8 | pref('extensions.kabl.sync_update_interval', 432000000); // ms = 5 days 9 | pref('extensions.kabl.sync_url', 'https://gist.github.com/raw/857951/Karma_Blocker_Default_Rules.ini'); 10 | -------------------------------------------------------------------------------- /install.rdf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | kabl@trac.arantius.com 5 | Karma Blocker 6 | 0.6.2beta2 7 | Block resources based on their karma. 8 | 2 9 | 10 | Anthony Lieuallen 11 | 12 | chrome://kabl/skin/icon.png 13 | http://trac.arantius.com/wiki/Extensions/KarmaBlocker 14 | chrome://kabl/content/kabl-config.xul 15 | 16 | 17 | 18 | {ec8030f7-c20a-464f-9b0e-13a3a9e97384} 19 | 40.0 20 | 45.* 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /skin/blocked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arantius/karma-blocker/de8da6e634081908879d5fedb4b8172aafed467a/skin/blocked.png -------------------------------------------------------------------------------- /skin/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arantius/karma-blocker/de8da6e634081908879d5fedb4b8172aafed467a/skin/icon.png -------------------------------------------------------------------------------- /skin/kabl-config.css: -------------------------------------------------------------------------------- 1 | #status_box { 2 | padding-top: 7px; 3 | } 4 | 5 | textbox#rules { 6 | margin: 0px 5px; 7 | font-family: monospace; 8 | } 9 | 10 | textbox#status_line { 11 | margin-right: 5px; 12 | padding-left: 8px; 13 | cursor: default; 14 | } 15 | textbox#status_line input { 16 | display: none; 17 | } 18 | textbox#status_line label { 19 | margin-left: 0; 20 | } 21 | 22 | button[dlgtype='extra1'] { 23 | float: left; 24 | } 25 | 26 | button#sync_now image { display: none; } 27 | button#sync_now.loading image { display: block; } /* why not -moz-box ? */ 28 | -------------------------------------------------------------------------------- /skin/kabl-monitor.css: -------------------------------------------------------------------------------- 1 | dialog { 2 | min-height: 40em; 3 | min-width: 50em; 4 | } 5 | 6 | treechildren:-moz-tree-cell(blocked) { 7 | background: url('chrome://kabl/skin/blocked.png') 50% 50% no-repeat; 8 | } 9 | -------------------------------------------------------------------------------- /skin/kabl-overlay.css: -------------------------------------------------------------------------------- 1 | #tb-kabl { 2 | list-style-image: url("chrome://kabl/skin/toolbar-large.png"); 3 | } 4 | toolbar[iconsize="small"] #tb-kabl { 5 | list-style-image: url("chrome://kabl/skin/toolbar.png"); 6 | } 7 | 8 | #tb-kabl[kabl_disabled="yes"] { 9 | opacity: 0.8; 10 | } 11 | #tb-kabl[kabl_disabled="yes"] .toolbarbutton-icon { 12 | opacity: 0.5; 13 | } 14 | 15 | .popup-notification-icon[popupid="kabl-update-conflict"] { 16 | list-style-image: url("chrome://kabl/skin/icon.png"); 17 | } 18 | -------------------------------------------------------------------------------- /skin/spinner16.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arantius/karma-blocker/de8da6e634081908879d5fedb4b8172aafed467a/skin/spinner16.gif -------------------------------------------------------------------------------- /skin/toolbar-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arantius/karma-blocker/de8da6e634081908879d5fedb4b8172aafed467a/skin/toolbar-large.png -------------------------------------------------------------------------------- /skin/toolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arantius/karma-blocker/de8da6e634081908879d5fedb4b8172aafed467a/skin/toolbar.png --------------------------------------------------------------------------------