1 // Providing shortcuts for many otherwise lengthy XPCOM interfaces and constants
2 const PREF_STRING
= Components
.interfaces
.nsIPrefBranch
.PREF_STRING
3 const nsIPrefBranch
= Components
.interfaces
.nsIPrefBranch
4 const nsIPromptService
= Components
.interfaces
.nsIPromptService
5 const nsIURI
= Components
.interfaces
.nsIURI
8 const settings
= Components
.classes
['@zelgadis.jp/minimalist;1'].getService().wrappedJSObject
9 const preferenceManager
= Components
.classes
['@mozilla.org/preferences-service;1'].getService(nsIPrefBranch
)
10 const promptService
= Components
.classes
['@mozilla.org/embedcomp/prompt-service;1'].getService(nsIPromptService
)
11 const sourceURL
= Components
.classes
['@mozilla.org/network/standard-url;1'].getService(nsIURI
)
12 const destinationURL
= sourceURL
.clone()
14 // Various regular expressions. They are automatically compiled once on startup due to the literal notation
15 const extractRefreshURL
= /url=(.+)/i
18 /* Purpose: Gets called for every new document and does everything we can't do within the XPCOM code
20 const onDocumentLoaded = function(event
) {
21 // This sub-function scans for meta refresh tags and immediately follows their target
22 if (settings
.skipRefresh
) {
23 var metaTags
= event
.target
.getElementsByTagName('meta')
25 for each (var metaTag
in metaTags
) {
26 if (metaTag
.httpEquiv
.toLowerCase() == 'refresh') {
27 if (match
= extractRefreshURL
.exec(metaTag
.content
)) {
28 sourceURL
.spec
= event
.target
.location
.href
29 destinationURL
.spec
= srcURL
.resolve(match
[1])
31 // Make sure we're not loading this document again, else we'd end up in an infinite loop
32 if (!sourceURL
.equals(destinationURL
)) {
33 event
.target
.location
.replace(dstURL
.spec
) } } } } } }
35 getBrowser().addEventListener('DOMContentLoaded', onDocumentLoaded
, false)
38 /* Purpose: Gets called every time the user clicks on the statusbar panel and once on startup.
39 * It acts differently depending on which mouse button was clicked
41 const onButtonClicked = function(self
, button
, behavior
) {
43 // Filter level button
48 // This is used once at startup. It doesn't change the filter level, but sets the icon
52 // Left mouse button was clicked. Cycle to the next filter level
53 preferenceManager
.setIntPref('extensions.minimalist.level', (settings
.level
+ cycleAmount
) & 3)
54 self
.src
= 'chrome://minimalist/content/L' + settings
.level
+ '.png'
58 // Right mouse button was clicked. Show a list of blocked sites for this tab
59 var popupMenu
= document
.getElementById('minimalist-filter-popup')
61 // Remove all previous entries
62 while (popupMenu
.lastChild
) {
63 popupMenu
.removeChild(popupMenu
.lastChild
) }
65 // <\Skip redirection delays>: Insert into menu list
66 var settingsItem1
= document
.createElement('menuitem')
67 settingsItem1
.onclick
= onChangeSetting
68 settingsItem1
.setAttribute('label', 'Skip redirection delays')
69 settingsItem1
.setAttribute('closemenu', 'none')
70 settingsItem1
.setAttribute('type', 'checkbox')
71 settingsItem1
.setAttribute('checked', settings
.skipRefresh
)
73 // <\Global embed whitelist>: Insert into menu list
74 var settingsMenu1
= document
.createElement('menu')
75 var settingsPopup1
= document
.createElement('menupopup')
76 settingsMenu1
.setAttribute('label', 'Global embed whitelist')
78 // <\Whitelisted domains>: Insert into menu list
79 var settingsMenu2
= document
.createElement('menu')
80 var settingsPopup2
= document
.createElement('menupopup')
81 settingsMenu2
.setAttribute('label', 'Whitelisted domains')
83 // <\Blocked resources>: Insert into menu list
84 var settingsMenu3
= document
.createElement('menu')
85 var settingsPopup3
= document
.createElement('menupopup')
86 settingsMenu3
.setAttribute('label', 'Blocked resources')
88 // <\Blocked resources>: Prepare deeper menu level
89 var currentWindow
= gBrowser
.selectedBrowser
.contentWindow
.location
.href
90 if (currentWindow
in settings
.blockedSites
) {
91 var destinationHosts
= settings
.blockedSites
[currentWindow
]
92 for (var destinationHost
in destinationHosts
) {
93 // <\Blocked resources\[hosts]>: Build contents
94 var menuForHost
= document
.createElement('menu')
95 menuForHost
.setAttribute('label', destinationHost
)
97 // <\Blocked resources\[hosts]>: Prepare deeper menu level
98 var menuForPaths
= document
.createElement('menupopup')
99 var destinationPaths
= destinationHosts
[destinationHost
]
100 for (var destinationPath
in destinationPaths
) {
101 var blockedResource
= destinationPaths
[destinationPath
]
103 // <\Blocked resources\[hosts]\[paths]>: Build contents
104 var pathMenuItem
= document
.createElement('menuitem')
105 pathMenuItem
.onclick
= onChangeWhitelistEntry
106 pathMenuItem
.setUserData( 'responsibleTag', blockedResource
.responsibleTag
, null)
107 pathMenuItem
.setUserData( 'sourceDomain', blockedResource
.sourceDomain
, null)
108 pathMenuItem
.setUserData('destinationDomain', blockedResource
.destinationDomain
, null)
109 pathMenuItem
.setAttribute('label',
110 '[L' + blockedResource
.filterLevel
+ ':' + blockedResource
.responsibleTag
+ '] ' +
113 menuForPaths
.appendChild(pathMenuItem
) }
114 menuForHost
.appendChild(menuForPaths
)
115 settingsPopup3
.appendChild(menuForHost
) } }
117 // <\Blocked resources\Empty>: Insert into menu list (if necessary)
118 if (!settingsPopup3
.firstChild
) {
119 var emptyMenuItem
= document
.createElement('menuitem')
120 emptyMenuItem
.setAttribute('label', 'Empty')
121 emptyMenuItem
.setAttribute('disabled', true)
122 settingsPopup3
.appendChild(emptyMenuItem
) }
124 // <\Global embed whitelist>: Prepare deeper menu level
125 var settingPath
='extensions.minimalist.embed'
126 var whiteList
= preferenceManager
.getCharPref(settingPath
).split(',')
127 if (whiteList
.length
> 1 || whiteList
[0] != '') {
128 // <\Global embed whitelist\[domains]>: Build contents
129 for each (destinationDomain
in whiteList
) {
130 var listMenuItem
= document
.createElement('menuitem')
131 listMenuItem
.onclick
= onChangeWhitelistEntry
132 listMenuItem
.setUserData('domainList', whiteList
, null)
133 listMenuItem
.setUserData('settingPath', settingPath
, null)
134 listMenuItem
.setAttribute('label', destinationDomain
)
135 listMenuItem
.setAttribute('value', '<embeds>')
136 settingsPopup1
.appendChild(listMenuItem
) } }
138 // <\Global embed whitelist\Empty>: Insert into menu list
139 var listMenuItem
= document
.createElement('menuitem')
140 listMenuItem
.setAttribute('label', 'Empty')
141 listMenuItem
.setAttribute('disabled', true)
142 settingsPopup1
.appendChild(listMenuItem
) }
144 // <\Whitelisted domains>: Prepare deeper menu level
145 var currentDomain
= settings
.getDomainName(currentWindow
)
146 settingPath
= 'extensions.minimalist.whitelist.' + currentDomain
147 if (preferenceManager
.getPrefType(settingPath
) == PREF_STRING
) {
148 whiteList
= preferenceManager
.getCharPref(settingPath
).split(',')
150 // <\Whitelisted domains\[domains]>: Build contents
151 if (whiteList
.length
> 1 || whiteList
[0] != '') {
152 for each (destinationDomain
in whiteList
) {
153 var listMenuItem
= document
.createElement('menuitem')
154 listMenuItem
.onclick
= onChangeWhitelistEntry
155 listMenuItem
.setUserData('domainList', whiteList
, null)
156 listMenuItem
.setUserData('settingPath', settingPath
, null)
157 listMenuItem
.setAttribute('label', destinationDomain
)
158 listMenuItem
.setAttribute('value', currentDomain
)
159 settingsPopup2
.appendChild(listMenuItem
) } } }
161 // <\Whitelisted domains\Empty>: Insert into menu list (if necessary)
162 if (!settingsPopup2
.firstChild
) {
163 var listMenuItem
= document
.createElement('menuitem')
164 listMenuItem
.setAttribute('label', 'Empty')
165 listMenuItem
.setAttribute('disabled', true)
166 settingsPopup2
.appendChild(listMenuItem
) }
168 // Put everything together and attach it to the XUL document popup node
169 settingsMenu1
.appendChild(settingsPopup1
)
170 settingsMenu2
.appendChild(settingsPopup2
)
171 settingsMenu3
.appendChild(settingsPopup3
)
172 popupMenu
.appendChild(settingsItem1
)
173 popupMenu
.appendChild(settingsMenu1
)
174 popupMenu
.appendChild(settingsMenu2
)
175 popupMenu
.appendChild(settingsMenu3
)
176 self
.parentNode
.appendChild(popupMenu
)
179 popupMenu
.openPopup(self
, 'before_end', 0, 0, true, false)
188 /* Purpose: Gets called when a menu entry in the blocked sites or whitelisted domains popup list is clicked.
189 * Asks the user whether she wants to add/remove it to/from the whitelist and acts accordingly
191 const onChangeWhitelistEntry = function(event
) {
192 if (event
.target
.value
) {
193 // This mode removes a domain from the whitelist. Only left button mouse clicks are processed here
194 if (event
.button
== 0) {
195 var domainList
= event
.target
.getUserData('domainList')
196 var settingPath
= event
.target
.getUserData('settingPath')
198 // Find and remove the clicked domain name from the whitelist
199 for (var index
in domainList
) {
200 if (domainList
[index
] == event
.target
.label
) {
201 domainList
.splice(index
, 1)
205 var queryText
= 'Remove domain <' + event
.target
.label
+ '> from '
206 if (event
.target
.value
== '<embeds>') {
207 queryText
= queryText
+ 'the global embed whitelist?' }
209 queryText
= queryText
+ '<' + event
.target
.value
+ '>\'s whitelist?' }
211 // For convenience, automatically reloads the tab's content after rewriting the whitelist
212 if (promptService
.confirm(null, 'Confirm your choice', queryText
)) {
213 if (domainList
.length
== 0 || domainList
[0] == '') {
214 preferenceManager
.clearUserPref(settingPath
)
215 if (preferenceManager
.getPrefType(settingPath
) == PREF_STRING
) {
216 preferenceManager
.setCharPref(settingPath
, '') } }
218 preferenceManager
.setCharPref(settingPath
, domainList
.join(',')) }
219 gBrowser
.selectedBrowser
.contentWindow
.location
.reload() } } }
221 // This mode adds a domain to the whitelist
222 var currentDomain
= event
.target
.getUserData('sourceDomain')
223 var domainToAdd
= event
.target
.getUserData('destinationDomain')
226 var settingPath
, queryText
= 'Add domain <' + domainToAdd
+ '> to '
227 if (event
.button
== 2) {
228 var responsibleTag
= event
.target
.getUserData('responsibleTag')
229 if (responsibleTag
in settings
.embedTagClass
) {
230 settingPath
= 'extensions.minimalist.embed'
231 queryText
= queryText
+ 'the global embed whitelist?' }
235 settingPath
= 'extensions.minimalist.whitelist.' + currentDomain
236 queryText
= queryText
+ '<' + currentDomain
+ '>\'s whitelist?' }
238 // Append the new domain to the existing list of domains - or create a new list if it doesn't exist
240 if (preferenceManager
.getPrefType(settingPath
) == PREF_STRING
) {
241 currentList
= currentList
+ preferenceManager
.getCharPref(settingPath
)
242 if (currentList
!= '') {
243 currentList
= currentList
+ ',' } }
244 currentList
= currentList
+ domainToAdd
246 // For convenience, automatically reloads the tab's content after adding the whitelist entry
247 if (promptService
.confirm(null, 'Confirm your choice', queryText
)) {
248 preferenceManager
.setCharPref(settingPath
, currentList
)
249 gBrowser
.selectedBrowser
.contentWindow
.location
.reload() } } }
252 /* Purpose: Gets called when the user clicks a menu item for changing a setting
254 const onChangeSetting = function(event
) {
255 if (event
.target
.getAttribute('type')) {
256 // This mode simply toggles skipRefresh. The menu item is toggled automatically
257 var settingPath
= 'extensions.minimalist.skipRefresh'
258 var newValue
= !preferenceManager
.getBoolPref(settingPath
)
260 preferenceManager
.setBoolPref(settingPath
, newValue
) } }
263 /* Purpose: These two functions delete all blocked sites entries for a tab when they become invalid
265 const onLocationChange = function(browser
) {
266 delete settings
.blockedSites
[browser
.contentWindow
.location
.href
] }
268 const onTabClosed = function(event
) {
269 delete settings
.blockedSites
[event
.target
.linkedBrowser
.contentWindow
.location
.href
] }
272 /* Purpose: Gets called once the XUL overlay is loaded. It sets up everything we need for our statusbar panel
274 const onOverlayLoaded = function() {
275 // Track every location change in a tab so we can clear its current blocked sites list
276 gBrowser
.addTabsProgressListener({
277 onLocationChange
: onLocationChange
,
278 onStateChange: function() {},
279 onProgressChange: function() {},
280 onStatusChange: function() {},
281 onSecurityChange: function() {}})
283 // Closing the tab also makes its blocked sites list invalid
284 gBrowser
.tabContainer
.addEventListener('TabClose', onTabClosed
, false)
286 // Set initial values for statusbar panel
287 onButtonClicked(document
.getElementById('minimalist-filterLevel'), 0, 4) }
289 window
.addEventListener('load', onOverlayLoaded
, false)