1 function NSGetModule(compMgr
, fileSpec
)
4 const settings
= Components
.classes
['@mozilla.org/preferences-service;1'].getService(Components
.interfaces
.nsIPrefBranch
)
5 const urlParser
= Components
.classes
['@mozilla.org/network/standard-url;1'].getService(Components
.interfaces
.nsIURI
)
6 const whiteList
= {'chrome': true, 'resource': true}
7 const hostRE
= /^(?:\d{1,3}\.){3}\d{1,3}|[\w\-]{3,}(?=(?:\.[a-z]{2})*\.\w{2,}$)/
8 const contentRE
= /^(?:text\/html|application\/xhtml\+xml)/
9 const cacheRE
= /^(?:text|image|multipart)\/|^application\/(?:x-)?(?:javascript|json)/
10 const ACCEPT
= Components
.interfaces
.nsIContentPolicy
.ACCEPT
11 const REJECT
= Components
.interfaces
.nsIContentPolicy
.REJECT_SERVER
15 // Implementation: content-policy //
16 function getDomainName(URL
)
18 hostName
= hostRE
.exec(URL
.host
)
19 return hostName
? hostName
[0].toLowerCase() : URL
.host
22 function isImageLink(node
)
24 return node
instanceof Components
.interfaces
.nsIDOMHTMLImageElement
&&
25 node
.parentNode
instanceof Components
.interfaces
.nsIDOMHTMLAnchorElement
28 function lastMeasure(node
, targetURL
)
30 if (filterLevel
> 2 && isImageLink(node
)) {
36 function shouldLoad(contentType
, contentLocation
, requestOrigin
, context
, mimeTypeGuess
, extra
)
38 if (filterLevel
< 1 || context
instanceof Components
.interfaces
.nsIDOMXULElement
|| requestOrigin
== null ||
39 requestOrigin
.scheme
in whiteList
|| contentLocation
.scheme
in whiteList
)
42 sourceHost
= getDomainName(requestOrigin
)
43 destHost
= getDomainName(contentLocation
)
45 if (filterLevel
> 1 && isImageLink(context
)) {
46 urlParser
.spec
= context
.parentNode
.href
47 if (getDomainName(urlParser
) != sourceHost
)
51 if (sourceHost
== destHost
)
52 return lastMeasure(context
, contentLocation
)
54 exceptHosts
= exceptions
[sourceHost
]
55 if (exceptHosts
&& destHost
in exceptHosts
)
56 return lastMeasure(context
, contentLocation
)
61 // Implementation: http-on-modify-request //
62 function getRequestHeader(channel
, tag
)
64 try { return channel
.getRequestHeader(tag
) }
65 catch (e
) { return false }
68 function getResponseHeader(channel
, tag
)
70 try { return channel
.getResponseHeader(tag
) }
71 catch (e
) { return false }
74 function observe(subject
, topic
, data
)
78 case 'http-on-modify-request':
80 httpChannel
= subject
.QueryInterface(Components
.interfaces
.nsIHttpChannel
)
81 httpChannel
.setRequestHeader('If-Modified-Since', '', false)
82 httpChannel
.setRequestHeader('User-Agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.6) '
83 + 'Gecko/2009011913 Firefox/3.0.6 ', false)
85 if (httpReferer
= getRequestHeader(httpChannel
, 'Referer')) {
86 urlParser
.spec
= httpReferer
87 httpReferer
= getDomainName(urlParser
)
88 urlParser
.spec
= 'http://' + getRequestHeader(httpChannel
, 'Host')
90 if (httpReferer
!= getDomainName(urlParser
))
91 httpChannel
.setRequestHeader('Referer', urlParser
.spec
, false)
96 case 'http-on-examine-response':
98 httpChannel
= subject
.QueryInterface(Components
.interfaces
.nsIHttpChannel
)
99 httpChannel
.setResponseHeader('Age', '', false)
100 httpChannel
.setResponseHeader('Cache-Control', '', false)
101 httpChannel
.setResponseHeader('Date', '', false)
102 httpChannel
.setResponseHeader('ETag', '', false)
103 httpChannel
.setResponseHeader('Last-Modified', '', false)
104 httpChannel
.setResponseHeader('Pragma', '', false)
105 httpChannel
.setResponseHeader('Vary', '', false)
107 if (contentType
= getResponseHeader(httpChannel
, 'Content-Type')) {
108 if (contentType
.match(contentRE
))
109 httpChannel
.setResponseHeader('Expires', new Date( Date
.now() + 120000 ).toGMTString(), false)
111 contentLength
= getResponseHeader(httpChannel
, 'Content-Length')
112 if (!contentLength
|| parseInt(contentLength
) > 2097152 || !contentType
.match(cacheRE
))
113 httpChannel
.setResponseHeader('Expires', 'Thu, 01 Jan 1970 00:00:00 GMT', false)
115 httpChannel
.setResponseHeader('Expires', 'Sun, 07 Feb 2106 06:28:15 GMT', false)
121 case 'nsPref:changed':
122 path
= data
.split('.')
127 dstHost
= settings
.getCharPref(data
).split(',')
129 if (dstHost
.length
> 0) {
130 exceptions
[srcHost
] = { }
132 exceptions
[srcHost
][dstHost
[i
]] = true
134 delete exceptions
[srcHost
]
138 filterLevel
= settings
.getIntPref(data
)
145 // XPCOM registration //
146 Components
.utils
.import('resource://gre/modules/XPCOMUtils.jsm')
148 function Minimalist() {
149 this.wrappedJSObject
= this
150 observer
= Components
.classes
['@mozilla.org/observer-service;1'].getService(Components
.interfaces
.nsIObserverService
)
151 observer
.addObserver(this, 'http-on-modify-request', false)
152 observer
.addObserver(this, 'http-on-examine-response', false)
153 settings
.QueryInterface(Components
.interfaces
.nsIPrefBranch2
)
154 settings
.addObserver('extensions.minimalist.', this, false)
156 entries
= settings
.getChildList('extensions.minimalist.whitelist', {})
158 entry
= entries
[i
].split('.')[3]
159 exceptions
[entry
] = {}
161 values
= settings
.getCharPref(entries
[i
]).split(',')
163 exceptions
[entry
][values
[j
]] = true
166 Minimalist
.prototype = {
167 classDescription
: 'Minimalist',
168 classID
: Components
.ID('{124b1de7-bd8a-4a41-a04a-9d40070a0b3a}'),
169 contractID
: '@zelgadis.jp/minimalist;1',
170 _xpcom_categories
: [{category
: 'content-policy'}],
171 QueryInterface
: XPCOMUtils
.generateQI([Components
.interfaces
.nsIContentPolicy
, Components
.interfaces
.nsIObserver
]),
172 shouldLoad
: shouldLoad
,
173 shouldProcess: function() { return ACCEPT
},
177 return XPCOMUtils
.generateModule([Minimalist
])