Skip to content

Commit 26e163c

Browse files
GijsKruitboschGijsKruitbosch
GijsKruitbosch
authored and
GijsKruitbosch
committedMay 3, 2007
Initial Code Import
git-svn-id: https://chromelist.googlecode.com/svn/trunk@2 652e530c-8f2f-0410-a032-d38e632a91c5
1 parent 59c63e8 commit 26e163c

23 files changed

+2317
-0
lines changed
 

‎build.bat

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
del chromelist.xpi
2+
rem this is fugly, but who cares.
3+
ls | sed s/build\.bat// | sed s/preview.png// | sed s/preview-small.png// | xargs 7z a -tzip "chromelist.xpi" -r -mx=9 -x!*CVS*

‎chrome.manifest

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
content chromelist content/
2+
skin chromelist modern/1.0 skin/
3+
locale chromelist en-US locale/
4+
overlay chrome://browser/content/browser.xul chrome://chromelist/content/ChromeListOverlay.xul

‎content/ChromeListOverlay.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
function startChromeList()
2+
{
3+
window.openDialog("chrome://chromelist/content/chromelist.xul", "chrome-browser", "resizable,dialog=no,status", {url: "chrome://"});
4+
}

‎content/ChromeListOverlay.xul

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0"?>
2+
3+
<overlay id="chromeListToolsOverlay"
4+
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
5+
6+
<script type="application/x-javascript" src="chrome://chromelist/content/ChromeListOverlay.js" />
7+
8+
<menupopup id="menu_ToolsPopup">
9+
<menuitem insertafter="devToolsSeparator" label="Explore Chrome"
10+
accesskey="x" oncommand="startChromeList();" />
11+
</menupopup>
12+
13+
</overlay>
14+

‎content/chromeDirTree.js

+317
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2+
*
3+
* The contents of this file are subject to the Mozilla Public License
4+
* Version 1.1 (the "License"); you may not use this file except in
5+
* compliance with the License. You may obtain a copy of the License at
6+
* http://www.mozilla.org/MPL/
7+
*
8+
* Software distributed under the License is distributed on an "AS IS" basis,
9+
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10+
* for the specific language governing rights and limitations under the
11+
* License.
12+
*
13+
* The Original Code is FireFTP
14+
*
15+
* The Initial Developer of the Original Code is
16+
* Mime Cuvalo
17+
* Portions created by Mime Cuvalo are Copyright (C) 2004 Mime Cuvalo.
18+
*
19+
* Alternatively, the contents of this file may be used under the
20+
* terms of the GNU Public License (the "GPL"), in which case the
21+
* provisions of the GPL are applicable instead of those above.
22+
* If you wish to allow use of your version of this file only
23+
* under the terms of the GPL and not to allow others to use your
24+
* version of this file under the MPL, indicate your decision by
25+
* deleting the provisions above and replace them with the notice
26+
* and other provisions required by the GPL. If you do not delete
27+
* the provisions above, a recipient may use your version of this
28+
* file under either the MPL or the GPL.
29+
*
30+
* Contributor(s):
31+
* Gijs Kruitbosch, <gijskruitbosch@gmail`com>
32+
*/
33+
/*
34+
* Large portions of this code are taken literally or partially from code for
35+
* the FireFTP extension by Mime Cuvalo. Many thanks to him for writing the
36+
* original code.
37+
*/
38+
39+
var chromeDirTree = {
40+
data: new Array,
41+
getCellText: cdt_getCellText,
42+
getLevel: cdt_getLevel,
43+
getParentIndex: cdt_getParentIndex,
44+
getImageSrc: function(row,col) {},
45+
getCellProperties: function(row,col,props) {},
46+
getColumnProperties: function(colid,col,props) {},
47+
getRowProperties: function(row,props) {},
48+
hasNextSibling: function(row,nextrow) { return this.data[row].hasNext; },
49+
isContainer: function(row) { return true; },
50+
isContainerEmpty: cdt_isContainerEmpty,
51+
isContainerOpen: function(row) { return this.data[row].open; },
52+
isSeparator: function(row) { return false; },
53+
isSorted: function(row) { return false; },
54+
setTree: function(treebox) { this.treebox = treebox; },
55+
toggleOpenState: cdt_toggleOpenState,
56+
updateParentIndices: cdt_updateParentIndices,
57+
cdup: cdt_cdup,
58+
reselectCurrentDirectory: cdt_reselectCurrentDirectory,
59+
changeDir: cdt_changeDir,
60+
indexOfURL: cdt_indexOfURL,
61+
canDrop: function (aIndex, aOrientation) { return false; },
62+
click: cdt_click
63+
}
64+
65+
66+
function cdt_getCellText(row,column)
67+
{
68+
return row == -1 ? "" : this.data[row].leafName;
69+
}
70+
71+
function cdt_getLevel(row)
72+
{
73+
if ((row < 0) || (row >= this.data.length))
74+
return 0; // Don't feed bogus, please.
75+
76+
return this.data[row].level - 1; // Woo! Decrement because <tree> assumes lowest level is 0.
77+
}
78+
79+
function cdt_isContainerEmpty(row)
80+
{
81+
if ((row < 0) || (row >= this.data.length)) // rows we don't know are empty.
82+
return true;
83+
return this.data[row].empty;
84+
}
85+
86+
function cdt_getParentIndex(row)
87+
{
88+
if (row <= 0)
89+
return -1;
90+
return this.data[row].parentIndex;
91+
}
92+
93+
function cdt_toggleOpenState(row)
94+
{
95+
// Don't feed us nonsense.
96+
if (row < 0 || row > this.data.length)
97+
return;
98+
99+
if (this.isContainerOpen(row))
100+
{
101+
// The container is open, find all children and remove them.
102+
var currentLevel = this.getLevel(row);
103+
// last child to remove:
104+
var lastChild = row;
105+
// Find the last child's index (within the limits of the data and with a higher level):
106+
while ((lastChild + 1 < this.rowCount) && (this.getLevel(lastChild + 1) > currentLevel))
107+
++lastChild;
108+
// Remove the subdirectories and clean up:
109+
this.data[row].children = this.data.splice(row + 1, lastChild - row);
110+
this.updateParentIndices();
111+
this.rowCount = this.data.length;
112+
this.treebox.rowCountChanged(row, -(lastChild - row));
113+
114+
// Alright, it's no longer open:
115+
this.data[row].open = false;
116+
// Update the row:
117+
this.treebox.invalidateRow(row);
118+
119+
// Technically, we can be asked to collapse a node above the node we're
120+
// viewing. We need to cope with that:
121+
if (chromeTree.currentURL.indexOf(this.data[row].href) == 0
122+
&& chromeTree.currentURL != this.data[row].href
123+
&& chromeTree.currentLevel > this.getLevel(row))
124+
{
125+
chromeTree.currentURL = this.data[row].href;
126+
chromeTree.updateView();
127+
this.selection.select(row);
128+
this.treebox.ensureRowIsVisible(row);
129+
}
130+
else if (chromeTree.currentURL == this.data[row].href)
131+
{
132+
this.selection.select(row);
133+
this.treebox.ensureRowIsVisible(row);
134+
}
135+
}
136+
else // Okay, this node was closed, we open it, we need to add the children.
137+
{
138+
// Do we have stored data on the children from before? Pretty please? :-D
139+
if (this.data[row].children)
140+
{
141+
for (var x = this.data[row].children.length - 1; x >= 0; --x)
142+
this.data.splice(row + 1, 0, this.data[row].children[x]);
143+
144+
// Clean up
145+
this.updateParentIndices();
146+
this.rowCount = this.data.length;
147+
this.treebox.rowCountChanged(row + 1, this.data[row].children.length);
148+
this.data[row].children = null;
149+
this.data[row].open = true;
150+
this.treebox.invalidateRow(row);
151+
}
152+
else // Awwwww. :-(. Well, let's do it the hard way then.
153+
{
154+
var dirNode = chromeStructure.findURL(this.data[row].href);
155+
var subDirs = [];
156+
for (var k in dirNode.directories)
157+
{
158+
subDirs.push( {leafName: k, parent: dirNode.href, href: dirNode.directories[k].href,
159+
level: dirNode.directories[k].level,
160+
open: false, empty: false, children: null, hasNext: true, parentIndex: -1 });
161+
}
162+
if (subDirs.length == 0)
163+
{
164+
this.data[row].empty = true;
165+
this.data[row].open = false;
166+
this.treebox.invalidateRow(row);
167+
return;
168+
}
169+
subDirs.sort(dirSort);
170+
subDirs[subDirs.length - 1].hasNext = false; // Last element doesn't have a next item.
171+
172+
for (var x = subDirs.length - 1; x >= 0; --x)
173+
this.data.splice(row + 1, 0, subDirs[x]);
174+
this.rowCount = this.data.length;
175+
this.treebox.rowCountChanged(row + 1, subDirs.length);
176+
this.data[row].open = true;
177+
this.treebox.invalidateRow(row);
178+
}
179+
}
180+
}
181+
182+
function cdt_updateParentIndices()
183+
{
184+
for (var x = 0; x < this.data.length; ++x)
185+
{
186+
var pIndex = this.data[x].parent ? this.indexOfURL(this.data[x].parent) : -1;
187+
this.data[x].parentIndex = pIndex;
188+
}
189+
}
190+
191+
function cdt_cdup()
192+
{
193+
var parentIndex = this.getParentIndex(this.selection.currentIndex);
194+
if (parentIndex != -1)
195+
{
196+
this.changeDir(this.data[parentIndex].href);
197+
this.selection.select(parentIndex);
198+
}
199+
}
200+
201+
function cdt_reselectCurrentDirectory()
202+
{
203+
var index = this.indexOfURL(chromeTree.currentURL);
204+
this.selection.select(index);
205+
this.treebox.ensureRowIsVisible(index);
206+
}
207+
208+
function cdt_changeDir(href)
209+
{
210+
// Hrmmm....
211+
if (!(/\/$/).test(href)) // No slash at the end? tsk.
212+
href = href + "/";
213+
214+
var oldDir = chromeTree.currentURL;
215+
chromeTree.currentURL = href;
216+
if (this.data.length == 0) // We need to create the full data array first.
217+
{
218+
var elemsAdded = 0;
219+
for (var dir in chromeStructure.directories)
220+
{
221+
var dirObj = chromeStructure.directories[dir];
222+
this.data.push( {leafName: dir, parent: "", href: dirObj.href, open: false, level: dirObj.level,
223+
empty: false, children: null, hasNext:false, parentIndex: -1} );
224+
elemsAdded++;
225+
}
226+
this.data.sort(dirSort);
227+
this.rowCount = elemsAdded;
228+
this.treebox.rowCountChanged(0, elemsAdded);
229+
this.selection.select(0);
230+
}
231+
232+
// Now we're sure we have a tree. Do something useful with it.
233+
var currentLevel = chromeTree.currentLevel;
234+
// open parent directories til we find the directory
235+
for (var x = 0; x < this.data.length; ++x)
236+
{
237+
for (var y = this.data.length - 1; y >= x; --y)
238+
{
239+
// Does the current row have a matching href?
240+
if (chromeTree.currentURL.indexOf(this.data[y].href) == 0
241+
// Is the level smaller (parent dir), or do we have an exactly matching URL?
242+
&& (this.getLevel(y) < currentLevel || chromeTree.currentURL == this.data[y].href))
243+
{
244+
x = y;
245+
break;
246+
}
247+
}
248+
249+
if (chromeTree.currentURL.indexOf(this.data[x].href) == 0)
250+
{
251+
// If the directory is not open, open it.
252+
if (!this.data[x].open)
253+
this.toggleOpenState(x);
254+
255+
if (chromeTree.currentURL == this.data[x].href) // Woo, we're done!
256+
{
257+
chromeTree.updateView();
258+
return;
259+
}
260+
}
261+
}
262+
// If we get here, we never found the damn thing, and that's bad.
263+
// We should go back to where we were previously.
264+
// XXX: maybe fix this to refresh the entire dir structure (bad, lots of work!)
265+
chromeTree.currentURL = oldDir;
266+
}
267+
268+
function cdt_indexOfURL(href)
269+
{ // binary search to find an url in the chromeDirTree
270+
var left = 0;
271+
var right = this.data.length - 1;
272+
href = href.replace(/\x2f/g, "\x01").toLowerCase(); // make '/' less than everything (except null)
273+
274+
while (left <= right) {
275+
var mid = Math.floor((left + right) / 2);
276+
var dataHref = this.data[mid].href.replace(/\x2f/g, "\x01").toLowerCase();
277+
if (dataHref == href || dataHref + "\x01" == href || dataHref == href + "\x01")
278+
return mid;
279+
else if (href < dataHref)
280+
right = mid - 1;
281+
else if (href > dataHref)
282+
left = mid + 1;
283+
}
284+
return -1;
285+
}
286+
287+
function dirSort(a, b)
288+
{
289+
// make '/' less than everything (except null)
290+
var tempA = a.href.replace(/\x2f/g, "\x01").toLowerCase();
291+
var tempB = b.href.replace(/\x2f/g, "\x01").toLowerCase();
292+
293+
if (tempA < tempB)
294+
return -1;
295+
if (tempA > tempB)
296+
return 1;
297+
return 0;
298+
}
299+
300+
301+
//////////////////////////////
302+
// Handlers
303+
//////////////////////////////
304+
305+
function cdt_click(event)
306+
{
307+
if (event.button == 0 || event.button == 2)
308+
{
309+
var row = {}; var col = {}; var child = {};
310+
this.treebox.getCellAt(event.pageX, event.pageY, row, col, child);
311+
var index = this.selection.currentIndex;
312+
313+
// index == row.value in case were collapsing the folder
314+
if ((index == row.value) && (this.data[index].href != chromeTree.currentURL))
315+
this.changeDir(this.data[index].href);
316+
}
317+
}

‎content/chromeStruct.js

+469
Large diffs are not rendered by default.

‎content/chromeTree.js

+344
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2+
*
3+
* The contents of this file are subject to the Mozilla Public License
4+
* Version 1.1 (the "License"); you may not use this file except in
5+
* compliance with the License. You may obtain a copy of the License at
6+
* http://www.mozilla.org/MPL/
7+
*
8+
* Software distributed under the License is distributed on an "AS IS" basis,
9+
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10+
* for the specific language governing rights and limitations under the
11+
* License.
12+
*
13+
* The Original Code is FireFTP
14+
*
15+
* The Initial Developer of the Original Code is
16+
* Mime Cuvalo
17+
* Portions created by Mime Cuvalo are Copyright (C) 2004 Mime Cuvalo.
18+
*
19+
* Alternatively, the contents of this file may be used under the
20+
* terms of the GNU Public License (the "GPL"), in which case the
21+
* provisions of the GPL are applicable instead of those above.
22+
* If you wish to allow use of your version of this file only
23+
* under the terms of the GPL and not to allow others to use your
24+
* version of this file under the MPL, indicate your decision by
25+
* deleting the provisions above and replace them with the notice
26+
* and other provisions required by the GPL. If you do not delete
27+
* the provisions above, a recipient may use your version of this
28+
* file under either the MPL or the GPL.
29+
*
30+
* Contributor(s):
31+
* Gijs Kruitbosch, <gijskruitbosch@gmail`com>
32+
*/
33+
/*
34+
* Large portions of this code are taken literally or partially from code for
35+
* the FireFTP extension by Mime Cuvalo. Many thanks to him for writing the
36+
* original code.
37+
*/
38+
39+
var bytesMode = false;
40+
41+
var chromeTree = {
42+
data: new Array(),
43+
displayData: new Array(),
44+
rowCount: 0,
45+
getCellText: ct_getCellText,
46+
getCellProperties: ct_getCellProperties,
47+
getExtension: ct_getExtension,
48+
getImageSrc: ct_getImageSrc,
49+
getFileIcon: ct_getFileIcon,
50+
cycleHeader: ct_cycleHeader,
51+
updateView: ct_updateView,
52+
getParentIndex: function(row) { return -1; },
53+
getColumnProperties: function(colid, col, props) {},
54+
getLevel: function(row) { return 0; },
55+
getRowProperties: function(row, props) {},
56+
isContainer: function(row) { return false; },
57+
isSeparator: function(row) { return false; },
58+
isSorted: function(row) { return false; },
59+
setTree: function(treebox) { this.treebox = treebox; },
60+
sort: ct_sort,
61+
getFormattedFileSize: ct_getFormattedFileSize,
62+
click: function() {},
63+
dblClick: ct_dblClick,
64+
popupShowing: ct_popupShowing,
65+
getCurrentHref: ct_getCurrentHref,
66+
getCurrentItem: ct_getCurrentItem,
67+
mouseOver: function() {},
68+
cut: function() {},
69+
copy: function() {},
70+
paste: function() {},
71+
canDrop: function (aIndex, aOrientation) { return false; },
72+
drop: function (aIndex, aOrientation) { },
73+
_url: ""
74+
}
75+
76+
chromeTree.__defineSetter__("currentURL", setChromeTreeURL);
77+
chromeTree.__defineGetter__("currentURL", getChromeTreeURL);
78+
79+
function setChromeTreeURL(newURL)
80+
{
81+
this._url = newURL;
82+
}
83+
84+
function getChromeTreeURL()
85+
{
86+
return this._url;
87+
}
88+
89+
90+
// Functions used by chromeTree
91+
// Get the text to display in any given cell.
92+
function ct_getCellText(row, column)
93+
{
94+
if (row == -1)
95+
return " ";
96+
switch(column.id)
97+
{
98+
case "chromefilename":
99+
return this.displayData[row].leafName;
100+
case "chromefilesize":
101+
return this.displayData[row].size;
102+
case "chromefiletype":
103+
return this.displayData[row].extension;
104+
default:
105+
return " "; // shouldn't get here
106+
}
107+
}
108+
109+
function ct_getCellProperties(row, col, props)
110+
{
111+
if (row == -1)
112+
return;
113+
if (col.id == "chromefilename" && this.data[row].isDirectory)
114+
{
115+
var atomsvc = getService("@mozilla.org/atom-service;1", "nsIAtomService");
116+
props.AppendElement(atomsvc.getAtom("isFolder"));
117+
}
118+
}
119+
120+
// Get the extension on a (f)ile path.
121+
function ct_getExtension(f)
122+
{
123+
if (f.lastIndexOf(".") != -1)
124+
return f.substring(f.lastIndexOf(".") + 1, f.length).toLowerCase();
125+
else
126+
return "";
127+
}
128+
129+
// Get the icons for the files
130+
function ct_getImageSrc(row, column)
131+
{
132+
if (row == -1)
133+
return "";
134+
if (column.id == "chromefilename" && this.displayData[row].icon)
135+
return this.displayData[row].icon;
136+
return "";
137+
}
138+
139+
function ct_cycleHeader(column)
140+
{
141+
var sortDir = column.element.getAttribute("sortDirection");
142+
var sortDirection = (sortDir == "ascending" || sortDir == "natural") ? "descending" : "ascending";
143+
document.getElementById('chromefilename').setAttribute("sortDirection", "natural");
144+
document.getElementById('chromefilesize').setAttribute("sortDirection", "natural");
145+
document.getElementById('chromefiletype').setAttribute("sortDirection", "natural");
146+
column.element.setAttribute("sortDirection", sortDirection);
147+
this.sort();
148+
}
149+
150+
function ct_sort()
151+
{
152+
if (document.getElementById('chromefilename').getAttribute("sortDirection") &&
153+
document.getElementById('chromefilename').getAttribute("sortDirection") != "natural")
154+
{
155+
this.data.sort(compareName);
156+
if (document.getElementById('chromefilename').getAttribute("sortDirection") == "ascending")
157+
this.data.reverse();
158+
}
159+
if (document.getElementById('chromefilesize').getAttribute("sortDirection") &&
160+
document.getElementById('chromefilesize').getAttribute("sortDirection") != "natural")
161+
{
162+
this.data.sort(compareSize);
163+
if (document.getElementById('chromefilesize').getAttribute("sortDirection") == "ascending")
164+
this.data.reverse();
165+
}
166+
if (document.getElementById('chromefiletype').getAttribute("sortDirection") &&
167+
document.getElementById('chromefiletype').getAttribute("sortDirection") != "natural")
168+
{
169+
this.data.sort(compareType);
170+
if (document.getElementById('chromefiletype').getAttribute("sortDirection") == "ascending")
171+
this.data.reverse();
172+
}
173+
174+
delete this.displayData;
175+
this.displayData = new Array;
176+
for (var row = 0; row < this.data.length; ++row)
177+
{
178+
var fName = this.data[row].leafName;
179+
var fSize = this.getFormattedFileSize(row);
180+
var fExt = this.getExtension(this.data[row].leafName);
181+
var fIcon = this.getFileIcon(row);
182+
var formattedData = { leafName : fName, size: fSize, extension: fExt, icon: fIcon };
183+
this.displayData.push(formattedData);
184+
}
185+
186+
this.treebox.rowCountChanged(0, -this.rowCount);
187+
this.rowCount = this.data.length;
188+
this.treebox.rowCountChanged(0, this.rowCount);
189+
}
190+
191+
function ct_updateView(column, direction)
192+
{
193+
var localTreeItems = new Array;
194+
var url = this.currentURL;
195+
var position = chromeStructure.findURL(url);
196+
if (position)
197+
{
198+
var dirs = position.directories;
199+
for (var key in dirs)
200+
localTreeItems.push(dirs[key]);
201+
var files = position.files;
202+
for (var key in files)
203+
localTreeItems.push(files[key]);
204+
}
205+
this.currentLevel = position.level;
206+
207+
this.data = localTreeItems;
208+
this.sort();
209+
210+
chromeDirTree.reselectCurrentDirectory(); // select directory in chromeDirTree
211+
if (this.data.length)
212+
this.selection.select(0); // Select the first item.
213+
}
214+
215+
function ct_getFormattedFileSize(row)
216+
{
217+
if (this.data[row].isDirectory)
218+
return "";
219+
if (this.data[row].size == 0)
220+
return "0" + (bytesMode ? " " : " KB ");
221+
if (bytesMode)
222+
return this.data[row].size + " ";
223+
else
224+
return (Math.floor(this.data[row].size / 1024) + 1) + " KB ";
225+
}
226+
227+
function ct_getFileIcon(row)
228+
{
229+
if (this.data[row].isDirectory)
230+
return "";
231+
// Thanks to Alex Sirota!
232+
var url = "moz-icon://" + this.data[row].leafName + "?size=16";
233+
dump(url);
234+
return url;
235+
}
236+
237+
function ct_popupShowing(event)
238+
{
239+
// return early for submenus, don't need to do anything.
240+
if (event.target != document.getElementById("chromemenu"))
241+
return true;
242+
243+
if (this.selection.count != 1)
244+
return false; // cancel, we can't do anything? :S
245+
246+
var selectedItem = this.data[this.selection.currentIndex];
247+
// Can't open or save a dir, nor copy contents:
248+
var isDir = selectedItem.isDirectory;
249+
document.getElementById("cx-open").setAttribute("disabled", isDir);
250+
document.getElementById("cx-saveas").setAttribute("disabled", isDir);
251+
if (selectedItem.scheme == "file")
252+
{
253+
document.getElementById("cx-copyjarurl").hidden = true;
254+
document.getElementById("cx-copyjarpath").hidden = true;
255+
document.getElementById("cx-copyfilepath").hidden = false;
256+
document.getElementById("cx-copyfileurl").hidden = false;
257+
}
258+
else if (selectedItem.scheme == "jar")
259+
{
260+
document.getElementById("cx-copyjarurl").hidden = false;
261+
document.getElementById("cx-copyjarpath").hidden = false;
262+
document.getElementById("cx-copyfilepath").hidden = true;
263+
document.getElementById("cx-copyfileurl").hidden = true;
264+
}
265+
//document.getElementById("cx-copycontent").setAttribute("disabled", isDir);
266+
//document.getElementById("cx-copycontentdata").setAttribute("disabled", isDir);
267+
return true;
268+
}
269+
270+
function ct_getCurrentHref()
271+
{
272+
if (this.selection.count != 1)
273+
return "";
274+
var selectedItem = this.data[this.selection.currentIndex];
275+
return selectedItem.href;
276+
}
277+
278+
function ct_getCurrentItem()
279+
{
280+
if (this.selection.count != 1)
281+
return null;
282+
return this.data[this.selection.currentIndex];
283+
}
284+
285+
function compareName(a, b) {
286+
if (!a.isDirectory && b.isDirectory)
287+
return 1;
288+
if (a.isDirectory && !b.isDirectory)
289+
return -1;
290+
if (a.leafName.toLowerCase() < b.leafName.toLowerCase())
291+
return -1;
292+
if (a.leafName.toLowerCase() > b.leafName.toLowerCase())
293+
return 1;
294+
return 0;
295+
}
296+
297+
function compareSize(a, b) {
298+
if (!a.isDirectory && b.isDirectory)
299+
return 1;
300+
if (a.isDirectory && !b.isDirectory)
301+
return -1;
302+
if (a.isDirectory && b.isDirectory)
303+
return 0;
304+
return a.size - b.size;
305+
}
306+
307+
function compareType(a, b) {
308+
if (!a.isDirectory && b.isDirectory)
309+
return 1;
310+
if (a.isDirectory && !b.isDirectory)
311+
return -1;
312+
if (chromeTree.getExtension(a.leafName.toLowerCase()) < chromeTree.getExtension(b.leafName.toLowerCase()))
313+
return -1;
314+
if (chromeTree.getExtension(a.leafName.toLowerCase()) > chromeTree.getExtension(b.leafName.toLowerCase()))
315+
return 1;
316+
return 0;
317+
}
318+
319+
////////////////////////////////////////////////////
320+
321+
function ct_dblClick(event)
322+
{
323+
// Nothing to do for weird buttons, no selection or no valid target.
324+
if (event.button != 0 || event.originalTarget.localName != "treechildren" || this.selection.count == 0)
325+
return;
326+
327+
// Select a *useful* element if necessary.
328+
if (this.selection.currentIndex < 0 || this.selection.currentIndex >= this.rowCount)
329+
this.selection.currentIndex = this.rowCount - 1;
330+
331+
var i = this.selection.currentIndex;
332+
if (this.data[i].isDirectory) // Open directories
333+
{
334+
chromeDirTree.changeDir(this.data[i].href);
335+
}
336+
else // View file sources.
337+
{
338+
// View the source of rdf, dtd, xul or js files by default.
339+
if ((/xul|js|rdf|dtd/).test(this.getExtension(this.data[i].leafName)))
340+
chromeBrowser.viewSourceOf(this.data[i].href);
341+
else
342+
chromeBrowser.view(this.data[i].href);
343+
}
344+
}

‎content/chromelist.js

+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
var chrometree, chromedirtree;
2+
3+
function onLoad()
4+
{
5+
chrometree = document.getElementById("chrometree");
6+
chromedirtree = document.getElementById("chromedirtree");
7+
iosvc = getService("@mozilla.org/network/io-service;1", "nsIIOService");
8+
chromeReg = getService("@mozilla.org/chrome/chrome-registry;1",
9+
"nsIToolkitChromeRegistry");
10+
11+
chrometree.view = chromeTree;
12+
chromedirtree.view = chromeDirTree;
13+
setStatusText(getStr("info.status.reading.manifests"));
14+
setTimeout(refreshChromeList, 0, onLoadDone);
15+
}
16+
17+
function onLoadDone()
18+
{
19+
setStatusText(getStr("info.status.done"));
20+
setStatusProgress(-1);
21+
chromeTree.currentURL = "chrome://";
22+
chromeDirTree.changeDir("chrome://");
23+
chromeBrowser.init();
24+
}
25+
26+
function onUnload()
27+
{
28+
chrometree.view = null;
29+
chromedirtree.view = null;
30+
}
31+
32+
var chromeBrowser = {}; // Global object.
33+
34+
chromeBrowser.init =
35+
function cb_init()
36+
{
37+
const PREF_CTRID = "@mozilla.org/preferences-service;1";
38+
const nsIPrefService = Components.interfaces.nsIPrefService;
39+
const nsIPrefBranch = Components.interfaces.nsIPrefBranch;
40+
const nsIPrefBranchInternal = Components.interfaces.nsIPrefBranchInternal;
41+
42+
this.prefService =
43+
Components.classes[PREF_CTRID].getService(nsIPrefService);
44+
this.prefBranch = this.prefService.getBranch("extensions.chromelist.");
45+
this.prefBranchInternal =
46+
this.prefBranch.QueryInterface(nsIPrefBranchInternal);
47+
48+
}
49+
50+
chromeBrowser.getPref =
51+
function cb_getPref(prefName)
52+
{
53+
var type = this.prefBranch.getPrefType(prefName);
54+
try
55+
{
56+
switch (type)
57+
{
58+
case Components.interfaces.nsIPrefBranch.PREF_INT:
59+
return this.prefBranch.getIntPref(prefName);
60+
case Components.interfaces.nsIPrefBranch.PREF_BOOL:
61+
return this.prefBranch.getBoolPref(prefName);
62+
case Components.interfaces.nsIPrefBranch.PREF_STRING:
63+
return this.prefBranch.getCharPref(prefName);
64+
}
65+
}
66+
catch (ex)
67+
{
68+
logException(ex);
69+
return null;
70+
}
71+
return null; // Keep js happy (strict warning otherwise)
72+
}
73+
74+
////////////////////////////////////////////////////////////////
75+
// View stuff.
76+
77+
chromeBrowser.viewSourceOf =
78+
function cb_viewSourceOf(href)
79+
{
80+
const vsURL = "chrome://global/content/viewSource.xul";
81+
// Create a window.
82+
openDialog(vsURL, "_blank", "chrome,all,dialog=no", href);
83+
}
84+
85+
chromeBrowser.view =
86+
function cb_view(href)
87+
{
88+
if (!href)
89+
{
90+
alert("Couldn't get the URL for this file... sorry!");
91+
return;
92+
}
93+
94+
var openInTab = this.getPref("open-files-in-tab");
95+
if (!openInTab)
96+
{
97+
openUILinkIn(href, "window");
98+
return;
99+
}
100+
openUILinkIn(href, "tab");
101+
}
102+
103+
chromeBrowser.viewInCurrent =
104+
function cb_viewInCurrent(href)
105+
{
106+
if (!href)
107+
{
108+
alert("Couldn't get the URL for this file... sorry!");
109+
return;
110+
}
111+
openUILinkIn(href, "current");
112+
}
113+
114+
chromeBrowser.viewInWindow =
115+
function cb_viewInWindow(href)
116+
{
117+
if (!href)
118+
{
119+
alert("Couldn't get the URL for this file... sorry!");
120+
return;
121+
}
122+
openUILinkIn(href, "window");
123+
}
124+
125+
chromeBrowser.viewInTab =
126+
function cb_viewInTab(href)
127+
{
128+
if (!href)
129+
{
130+
alert("Couldn't get the URL for this file... sorry!");
131+
return;
132+
}
133+
openUILinkIn(href, "tab");
134+
}
135+
136+
////////////////////////////////////////////////////////////////
137+
// Copy stuff.
138+
139+
chromeBrowser.copy =
140+
function cb_copy(item, prop)
141+
{
142+
try {
143+
var clipboardhelper = getService("@mozilla.org/widget/clipboardhelper;1",
144+
"nsIClipboardHelper");
145+
}
146+
catch (ex) {};
147+
if (!item || !clipboardhelper || !(prop in item))
148+
return;
149+
150+
clipboardhelper.copyString(item[prop]);
151+
}
152+
153+
// Save stuff.
154+
chromeBrowser.saveAs =
155+
function cb_saveAs(href)
156+
{
157+
if (!href)
158+
{
159+
alert("Couldn't get the URL for this file... sorry!");
160+
return;
161+
}
162+
saveURL(href, null, null, false, false, null);
163+
}
164+
165+
// LXR stuff.
166+
chromeBrowser.lxr =
167+
function cb_lxr(item)
168+
{
169+
var openWhere = this.getPref("open-files-in-tab") ? "tab" : "window";
170+
if (item)
171+
{
172+
var searchString = encodeURIComponent(glimpseEscape(item.leafName));
173+
openUILinkIn(this.getPref("lxr-url").replace("%s", searchString), openWhere);
174+
}
175+
176+
}
177+
178+
// Properties stuff.
179+
chromeBrowser.showProperties =
180+
function cb_properties(item)
181+
{
182+
var windowArgs = "dialog,resizable";
183+
window.openDialog("chrome://chromelist/content/properties.xul", "_blank", windowArgs, item);
184+
}
185+

‎content/chromelist.xul

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
3+
<?xml-stylesheet href="chrome://chromelist/skin/tree.css" type="text/css"?>
4+
<!DOCTYPE window SYSTEM "chrome://chromelist/locale/chromelist.dtd">
5+
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
6+
title="&window.title;"
7+
id="chrome-browser-window"
8+
orient="vertical"
9+
onload="setTimeout('onLoad()', 10)"
10+
onunload="onUnload()"
11+
width="640"
12+
height="480"
13+
persist="width height screenX screenY sizemode">
14+
<script type="application/x-javascript" src="chrome://chromelist/content/file-utils.js"></script>
15+
<script type="application/x-javascript" src="chrome://chromelist/content/utils.js"></script>
16+
<script type="application/x-javascript" src="chrome://browser/content/utilityOverlay.js"></script>
17+
<script type="application/x-javascript" src="chrome://global/content/contentAreaUtils.js"></script>
18+
<script type="application/x-javascript" src="chrome://chromelist/content/chromelist.js"></script>
19+
<script type="application/x-javascript" src="chrome://chromelist/content/chromeStruct.js"></script>
20+
<script type="application/x-javascript" src="chrome://chromelist/content/chromeDirTree.js"></script>
21+
<script type="application/x-javascript" src="chrome://chromelist/content/chromeTree.js"></script>
22+
<stringbundleset>
23+
<stringbundle id="locale-strings" src="chrome://chromelist/locale/chromelist.properties"/>
24+
</stringbundleset>
25+
26+
<hbox width="1" flex="1">
27+
<tree id="chromedirtree" class="plain" flex="1" hidecolumnpicker="true"
28+
persist="collapsed">
29+
<treecols>
30+
<treecol id="chromedirname" hideheader="true" flex="1"
31+
primary="true" persist="width ordinal hidden"/>
32+
</treecols>
33+
<treechildren id="chromedirtreechildren"
34+
class="dirTree"
35+
onclick="chromeDirTree.click(event)"/>
36+
</tree>
37+
<splitter id="chromesplitter" style="width: 4px; max-width: 4px;"
38+
persist="state" collapse="before">
39+
<grippy/>
40+
</splitter>
41+
<tree id="chrometree" class="plain" flex="2" seltype="single"
42+
enableColumnDrag="true" context="chromemenu">
43+
<treecols>
44+
<treecol id="chromefilename" sortDirection="descending"
45+
label="&tree.filetree.filename;" flex="3"
46+
persist="width ordinal hidden sortDirection"/>
47+
<splitter class="tree-splitter"/>
48+
<treecol id="chromefilesize" style="text-align:right"
49+
label="&tree.filetree.filesize;" flex="1"
50+
persist="width ordinal hidden sortDirection"/>
51+
<splitter class="tree-splitter"/>
52+
<treecol id="chromefiletype" label="&tree.filetree.filetype;"
53+
persist="width ordinal hidden sortDirection" flex="1"/>
54+
</treecols>
55+
<treechildren id="chromefiletreechildren" class="fileTree"
56+
ondblclick="chromeTree.dblClick(event);" />
57+
</tree>
58+
</hbox>
59+
<statusbar id="status-bar" class="chromeclass-status">
60+
<statusbarpanel id="status-text" crop="right" flex="1"/>
61+
<statusbarpanel class="statusbarpanel-progress" id="status-progress-panel">
62+
<progressmeter class="progressmeter-statusbar" id="status-progress-bar"
63+
mode="determined" value="0"/>
64+
</statusbarpanel>
65+
</statusbar>
66+
67+
<popup id="chromemenu" onpopupshowing="return chromeTree.popupShowing(event);">
68+
<menu id="cx-open" label="&cx.open;">
69+
<menupopup>
70+
<menuitem id="cx-opencurrent" label="&cx.open.current;" accesskey="&cx.open.current.accesskey;"
71+
oncommand="chromeBrowser.viewInCurrent(chromeTree.getCurrentHref());"/>
72+
<menuitem id="cx-opentab" label="&cx.open.tab;" accesskey="&cx.open.tab.accesskey;"
73+
oncommand="chromeBrowser.viewInTab(chromeTree.getCurrentHref());"/>
74+
<menuitem id="cx-openwindow" label="&cx.open.window;" accesskey="&cx.open.window.accesskey;"
75+
oncommand="chromeBrowser.viewInWindow(chromeTree.getCurrentHref());"/>
76+
<menuseparator/>
77+
<menuitem id="cx-view-source" label="&cx.view-source;" accesskey="&cx.view-source.accesskey;"
78+
oncommand="chromeBrowser.viewSourceOf(chromeTree.getCurrentHref());"/>
79+
</menupopup>
80+
</menu>
81+
<menu id="cx-copy" label="&cx.copy;">
82+
<menupopup>
83+
<menuitem id="cx-copychromeurl" label="&cx.copy.chrome;" accesskey="&cx.copy.chrome.accesskey;"
84+
oncommand="chromeBrowser.copy(chromeTree.getCurrentItem(), 'href')"/>
85+
<menuitem id="cx-copyjarurl" label="&cx.copy.jarurl;" accesskey="&cx.copy.jarurl.accesskey;"
86+
oncommand="chromeBrowser.copy(chromeTree.getCurrentItem(), 'resolvedURI')"/>
87+
<menuitem id="cx-copyjarpath" label="&cx.copy.jarpath;" accesskey="&cx.copy.jarpath.accesskey;"
88+
oncommand="chromeBrowser.copy(chromeTree.getCurrentItem(), 'path')"/>
89+
<menuitem id="cx-copyfileurl" label="&cx.copy.fileurl;" accesskey="&cx.copy.fileurl.accesskey;"
90+
oncommand="chromeBrowser.copy(chromeTree.getCurrentItem(), 'resolvedURI')"/>
91+
<menuitem id="cx-copyfilepath" label="&cx.copy.filepath;" accesskey="&cx.copy.filepath.accesskey;"
92+
oncommand="chromeBrowser.copy(chromeTree.getCurrentItem(), 'path')"/>
93+
<!-- <menuseparator/>
94+
<menuitem id="cx-copycontent" label="&cx.copy.content;" accesskey="&cx.copy.content.accesskey;"/>
95+
<menuitem id="cx-copycontentdata" label="&cx.copy.contentdata;" accesskey="&cx.copy.contentdata.accesskey;"/> -->
96+
</menupopup>
97+
</menu>
98+
<menuitem id="cx-lxr" label="&cx.lxr;" accesskey="&cx.lxr.accesskey;"
99+
oncommand="chromeBrowser.lxr(chromeTree.getCurrentItem());"/>
100+
<menuseparator/>
101+
<menuitem id="cx-saveas" label="&cx.save-as;" accesskey="&cx.save-as.accesskey;"
102+
oncommand="chromeBrowser.saveAs(chromeTree.getCurrentHref());"/>
103+
<menuitem id="cx-properties" label="&cx.properties;" accesskey="&cx.properties.accesskey;"
104+
oncommand="chromeBrowser.showProperties(chromeTree.getCurrentItem());"/>
105+
106+
</popup>
107+
</window>

‎content/file-utils.js

+377
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,377 @@
1+
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2+
*
3+
* ***** BEGIN LICENSE BLOCK *****
4+
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
5+
*
6+
* The contents of this file are subject to the Mozilla Public License Version
7+
* 1.1 (the "License"); you may not use this file except in compliance with
8+
* the License. You may obtain a copy of the License at
9+
* http://www.mozilla.org/MPL/
10+
*
11+
* Software distributed under the License is distributed on an "AS IS" basis,
12+
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13+
* for the specific language governing rights and limitations under the
14+
* License.
15+
*
16+
* The Original Code is The JavaScript Debugger.
17+
*
18+
* The Initial Developer of the Original Code is
19+
* Netscape Communications Corporation.
20+
* Portions created by the Initial Developer are Copyright (C) 1998
21+
* the Initial Developer. All Rights Reserved.
22+
*
23+
* Contributor(s):
24+
* Robert Ginda, <rginda@netscape.com>, original author
25+
*
26+
* Alternatively, the contents of this file may be used under the terms of
27+
* either the GNU General Public License Version 2 or later (the "GPL"), or
28+
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29+
* in which case the provisions of the GPL or the LGPL are applicable instead
30+
* of those above. If you wish to allow use of your version of this file only
31+
* under the terms of either the GPL or the LGPL, and not to allow others to
32+
* use your version of this file under the terms of the MPL, indicate your
33+
* decision by deleting the provisions above and replace them with the notice
34+
* and other provisions required by the GPL or the LGPL. If you do not delete
35+
* the provisions above, a recipient may use your version of this file under
36+
* the terms of any one of the MPL, the GPL or the LGPL.
37+
*
38+
* ***** END LICENSE BLOCK ***** */
39+
40+
/* notice that these valuse are octal. */
41+
const PERM_IRWXU = 00700; /* read, write, execute/search by owner */
42+
const PERM_IRUSR = 00400; /* read permission, owner */
43+
const PERM_IWUSR = 00200; /* write permission, owner */
44+
const PERM_IXUSR = 00100; /* execute/search permission, owner */
45+
const PERM_IRWXG = 00070; /* read, write, execute/search by group */
46+
const PERM_IRGRP = 00040; /* read permission, group */
47+
const PERM_IWGRP = 00020; /* write permission, group */
48+
const PERM_IXGRP = 00010; /* execute/search permission, group */
49+
const PERM_IRWXO = 00007; /* read, write, execute/search by others */
50+
const PERM_IROTH = 00004; /* read permission, others */
51+
const PERM_IWOTH = 00002; /* write permission, others */
52+
const PERM_IXOTH = 00001; /* execute/search permission, others */
53+
54+
const MODE_RDONLY = 0x01;
55+
const MODE_WRONLY = 0x02;
56+
const MODE_RDWR = 0x04;
57+
const MODE_CREATE = 0x08;
58+
const MODE_APPEND = 0x10;
59+
const MODE_TRUNCATE = 0x20;
60+
const MODE_SYNC = 0x40;
61+
const MODE_EXCL = 0x80;
62+
63+
const PICK_OK = Components.interfaces.nsIFilePicker.returnOK;
64+
const PICK_CANCEL = Components.interfaces.nsIFilePicker.returnCancel;
65+
const PICK_REPLACE = Components.interfaces.nsIFilePicker.returnReplace;
66+
67+
const FILTER_ALL = Components.interfaces.nsIFilePicker.filterAll;
68+
const FILTER_HTML = Components.interfaces.nsIFilePicker.filterHTML;
69+
const FILTER_TEXT = Components.interfaces.nsIFilePicker.filterText;
70+
const FILTER_IMAGES = Components.interfaces.nsIFilePicker.filterImages;
71+
const FILTER_XML = Components.interfaces.nsIFilePicker.filterXML;
72+
const FILTER_XUL = Components.interfaces.nsIFilePicker.filterXUL;
73+
74+
const FTYPE_DIR = Components.interfaces.nsIFile.DIRECTORY_TYPE;
75+
const FTYPE_FILE = Components.interfaces.nsIFile.NORMAL_FILE_TYPE;
76+
77+
// evald f = fopen("/home/rginda/foo.txt", MODE_WRONLY | MODE_CREATE)
78+
// evald f = fopen("/home/rginda/vnk.txt", MODE_RDONLY)
79+
80+
var futils = new Object();
81+
82+
futils.umask = PERM_IWOTH | PERM_IWGRP;
83+
futils.MSG_SAVE_AS = "Save As";
84+
futils.MSG_OPEN = "Open";
85+
86+
futils.getPicker =
87+
function futils_nosepicker(initialPath, typeList, attribs)
88+
{
89+
const classes = Components.classes;
90+
const interfaces = Components.interfaces;
91+
92+
const PICKER_CTRID = "@mozilla.org/filepicker;1";
93+
const LOCALFILE_CTRID = "@mozilla.org/file/local;1";
94+
95+
const nsIFilePicker = interfaces.nsIFilePicker;
96+
const nsILocalFile = interfaces.nsILocalFile;
97+
98+
var picker = classes[PICKER_CTRID].createInstance(nsIFilePicker);
99+
if (typeof attribs == "object")
100+
{
101+
for (var a in attribs)
102+
picker[a] = attribs[a];
103+
}
104+
else
105+
throw "bad type for param |attribs|";
106+
107+
if (initialPath)
108+
{
109+
var localFile;
110+
111+
if (typeof initialPath == "string")
112+
{
113+
localFile =
114+
classes[LOCALFILE_CTRID].createInstance(nsILocalFile);
115+
localFile.initWithPath(initialPath);
116+
}
117+
else
118+
{
119+
if (!(initialPath instanceof nsILocalFile))
120+
throw "bad type for argument |initialPath|";
121+
122+
localFile = initialPath;
123+
}
124+
125+
picker.displayDirectory = localFile
126+
}
127+
128+
var allIncluded = false;
129+
130+
if (typeof typeList == "string")
131+
typeList = typeList.split(" ");
132+
133+
if (typeList instanceof Array)
134+
{
135+
for (var i in typeList)
136+
{
137+
switch (typeList[i])
138+
{
139+
case "$all":
140+
allIncluded = true;
141+
picker.appendFilters(FILTER_ALL);
142+
break;
143+
144+
case "$html":
145+
picker.appendFilters(FILTER_HTML);
146+
break;
147+
148+
case "$text":
149+
picker.appendFilters(FILTER_TEXT);
150+
break;
151+
152+
case "$images":
153+
picker.appendFilters(FILTER_IMAGES);
154+
break;
155+
156+
case "$xml":
157+
picker.appendFilters(FILTER_XML);
158+
break;
159+
160+
case "$xul":
161+
picker.appendFilters(FILTER_XUL);
162+
break;
163+
164+
case "$noAll":
165+
// This prevents the automatic addition of "All Files"
166+
// as a file type option by pretending it is already there.
167+
allIncluded = true;
168+
break;
169+
170+
default:
171+
if ((typeof typeList[i] == "object") && isinstance(typeList[i], Array))
172+
picker.appendFilter(typeList[i][0], typeList[i][1]);
173+
else
174+
picker.appendFilter(typeList[i], typeList[i]);
175+
break;
176+
}
177+
}
178+
}
179+
180+
if (!allIncluded)
181+
picker.appendFilters(FILTER_ALL);
182+
183+
return picker;
184+
}
185+
186+
function pickSaveAs (title, typeList, defaultFile, defaultDir, defaultExt)
187+
{
188+
if (!defaultDir && "lastSaveAsDir" in futils)
189+
defaultDir = futils.lastSaveAsDir;
190+
191+
var picker = futils.getPicker (defaultDir, typeList,
192+
{defaultString: defaultFile,
193+
defaultExtension: defaultExt});
194+
picker.init (window, title ? title : futils.MSG_SAVE_AS,
195+
Components.interfaces.nsIFilePicker.modeSave);
196+
197+
var reason;
198+
199+
try
200+
{
201+
reason = picker.show();
202+
}
203+
catch (ex)
204+
{
205+
dd ("caught exception from file picker: " + ex);
206+
}
207+
208+
var obj = new Object();
209+
210+
obj.reason = reason;
211+
obj.picker = picker;
212+
213+
if (reason != PICK_CANCEL)
214+
{
215+
obj.file = picker.file;
216+
futils.lastSaveAsDir = picker.file.parent;
217+
}
218+
else
219+
{
220+
obj.file = null;
221+
}
222+
223+
return obj;
224+
}
225+
226+
function pickOpen (title, typeList, defaultFile, defaultDir)
227+
{
228+
if (!defaultDir && "lastOpenDir" in futils)
229+
defaultDir = futils.lastOpenDir;
230+
231+
var picker = futils.getPicker (defaultDir, typeList,
232+
{defaultString: defaultFile});
233+
picker.init (window, title ? title : futils.MSG_OPEN,
234+
Components.interfaces.nsIFilePicker.modeOpen);
235+
236+
var rv = picker.show();
237+
238+
if (rv != PICK_CANCEL)
239+
futils.lastOpenDir = picker.file.parent;
240+
241+
return {reason: rv, file: picker.file, picker: picker};
242+
}
243+
244+
function mkdir (localFile, perms)
245+
{
246+
if (typeof perms == "undefined")
247+
perms = 0766 & ~futils.umask;
248+
249+
localFile.create(FTYPE_DIR, perms);
250+
}
251+
252+
function nsLocalFile(path)
253+
{
254+
const LOCALFILE_CTRID = "@mozilla.org/file/local;1";
255+
const nsILocalFile = Components.interfaces.nsILocalFile;
256+
257+
var localFile =
258+
Components.classes[LOCALFILE_CTRID].createInstance(nsILocalFile);
259+
localFile.initWithPath(path);
260+
return localFile;
261+
}
262+
263+
function fopen (path, mode, perms, tmp)
264+
{
265+
return new LocalFile(path, mode, perms, tmp);
266+
}
267+
268+
function LocalFile(file, mode, perms, tmp)
269+
{
270+
const classes = Components.classes;
271+
const interfaces = Components.interfaces;
272+
273+
const LOCALFILE_CTRID = "@mozilla.org/file/local;1";
274+
const FILEIN_CTRID = "@mozilla.org/network/file-input-stream;1";
275+
const FILEOUT_CTRID = "@mozilla.org/network/file-output-stream;1";
276+
const SCRIPTSTREAM_CTRID = "@mozilla.org/scriptableinputstream;1";
277+
278+
const nsIFile = interfaces.nsIFile;
279+
const nsILocalFile = interfaces.nsILocalFile;
280+
const nsIFileOutputStream = interfaces.nsIFileOutputStream;
281+
const nsIFileInputStream = interfaces.nsIFileInputStream;
282+
const nsIScriptableInputStream = interfaces.nsIScriptableInputStream;
283+
284+
if (typeof perms == "undefined")
285+
perms = 0666 & ~futils.umask;
286+
287+
if (typeof mode == "string")
288+
{
289+
switch (mode)
290+
{
291+
case ">":
292+
mode = MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE;
293+
break;
294+
case ">>":
295+
mode = MODE_WRONLY | MODE_CREATE | MODE_APPEND;
296+
break;
297+
case "<":
298+
mode = MODE_RDONLY;
299+
break;
300+
default:
301+
throw "Invalid mode ``" + mode + "''";
302+
}
303+
}
304+
305+
if (typeof file == "string")
306+
{
307+
this.localFile = new nsLocalFile(file);
308+
}
309+
else if (file instanceof nsILocalFile)
310+
{
311+
this.localFile = file;
312+
}
313+
else
314+
{
315+
throw "bad type for argument |file|.";
316+
}
317+
318+
this.path = this.localFile.path;
319+
320+
if (mode & (MODE_WRONLY | MODE_RDWR))
321+
{
322+
this.outputStream =
323+
classes[FILEOUT_CTRID].createInstance(nsIFileOutputStream);
324+
this.outputStream.init(this.localFile, mode, perms, 0);
325+
}
326+
327+
if (mode & (MODE_RDONLY | MODE_RDWR))
328+
{
329+
this.baseInputStream =
330+
classes[FILEIN_CTRID].createInstance(nsIFileInputStream);
331+
this.baseInputStream.init(this.localFile, mode, perms, tmp);
332+
this.inputStream =
333+
classes[SCRIPTSTREAM_CTRID].createInstance(nsIScriptableInputStream);
334+
this.inputStream.init(this.baseInputStream);
335+
}
336+
}
337+
338+
LocalFile.prototype.write =
339+
function fo_write(buf)
340+
{
341+
if (!("outputStream" in this))
342+
throw "file not open for writing.";
343+
344+
return this.outputStream.write(buf, buf.length);
345+
}
346+
347+
LocalFile.prototype.read =
348+
function fo_read(max)
349+
{
350+
if (!("inputStream" in this))
351+
throw "file not open for reading.";
352+
353+
var av = this.inputStream.available();
354+
if (typeof max == "undefined")
355+
max = av;
356+
357+
if (!av)
358+
return null;
359+
360+
var rv = this.inputStream.read(max);
361+
return rv;
362+
}
363+
364+
LocalFile.prototype.close =
365+
function fo_close()
366+
{
367+
if ("outputStream" in this)
368+
this.outputStream.close();
369+
if ("inputStream" in this)
370+
this.inputStream.close();
371+
}
372+
373+
LocalFile.prototype.flush =
374+
function fo_close()
375+
{
376+
return this.outputStream.flush();
377+
}

‎content/properties.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
var file = null;
2+
function onLoad()
3+
{
4+
file = window.arguments[0];
5+
document.title = document.title + file.leafName;
6+
document.getElementById("chrome-url-text").value = file.href;
7+
document.getElementById("resolved-url-text").value = file.resolvedURI;
8+
document.getElementById("resolved-file-text").value = file.path;
9+
document.getElementById("resolved-jarfile-text").value = file.path;
10+
if (file.scheme == "jar")
11+
document.getElementById("resolved-file").hidden = true;
12+
else if (file.scheme == "file")
13+
document.getElementById("resolved-jarfile").hidden = true;
14+
15+
if (file.TYPE == "ChromeDirectory")
16+
document.getElementById("file-size").hidden = true;
17+
else
18+
document.getElementById("file-size-text").value = file.size/1000 + " KB";
19+
document.getElementById("manifest-text").value = file.getManifest();
20+
}

‎content/properties.xul

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<?xml-stylesheet href="chrome://chromelist/skin/properties.css" type="text/css"?>
3+
<?xul-overlay href="chrome://global/content/dialogOverlay.xul"?>
4+
5+
<!DOCTYPE window SYSTEM "chrome://chromelist/locale/chromelist.dtd" >
6+
7+
<window id="metadata"
8+
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
9+
title="&props.caption;"
10+
onload="onLoad()"
11+
class="dialog"
12+
style="width: 60em; height: 10em;"
13+
persist="screenX screenY width height"
14+
orient="vertical"
15+
screenX="24" screenY="24">
16+
17+
<script type="application/x-javascript" src="chrome://chromelist/content/properties.js"></script>
18+
19+
<keyset id="dialogKeys"/>
20+
21+
<label value="&props.header.label;"/>
22+
<separator class="groove"/>
23+
<grid>
24+
<columns>
25+
<column/>
26+
<column/>
27+
<column flex="1"/>
28+
</columns>
29+
<rows>
30+
<row id="chrome-url">
31+
<separator orient="vertical"/>
32+
<label value="&props.chrome-url.label; "/>
33+
<textbox readonly="true" id="chrome-url-text"/>
34+
</row>
35+
<row id="resolved-url">
36+
<separator orient="vertical"/>
37+
<label value="&props.resolved-url.label; "/>
38+
<textbox readonly="true" id="resolved-url-text"/>
39+
</row>
40+
<row id="resolved-file">
41+
<separator orient="vertical"/>
42+
<label value="&props.resolved-file.label; "/>
43+
<textbox readonly="true" id="resolved-file-text"/>
44+
</row>
45+
<row id="resolved-jarfile">
46+
<separator orient="vertical"/>
47+
<label value="&props.resolved-jarfile.label; "/>
48+
<textbox readonly="true" id="resolved-jarfile-text"/>
49+
</row>
50+
<row id="file-size">
51+
<separator orient="vertical"/>
52+
<label value="&props.file-size.label; "/>
53+
<textbox readonly="true" id="file-size-text"/>
54+
</row>
55+
<row id="manifest">
56+
<separator orient="vertical"/>
57+
<label value="&props.manifest.label; "/>
58+
<textbox readonly="true" id="manifest-text"/>
59+
</row>
60+
</rows>
61+
</grid>
62+
<separator/>
63+
</window>
64+

‎content/utils.js

+241
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2+
*
3+
* ***** BEGIN LICENSE BLOCK *****
4+
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
5+
*
6+
* The contents of this file are subject to the Mozilla Public License Version
7+
* 1.1 (the "License"); you may not use this file except in compliance with
8+
* the License. You may obtain a copy of the License at
9+
* http://www.mozilla.org/MPL/
10+
*
11+
* Software distributed under the License is distributed on an "AS IS" basis,
12+
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13+
* for the specific language governing rights and limitations under the
14+
* License.
15+
*
16+
* The Original Code is JSIRC Library.
17+
*
18+
* The Initial Developer of the Original Code is
19+
* New Dimensions Consulting, Inc.
20+
* Portions created by the Initial Developer are Copyright (C) 1999
21+
* the Initial Developer. All Rights Reserved.
22+
*
23+
* Contributor(s):
24+
* Robert Ginda, rginda@ndcico.com, original author
25+
*
26+
* Alternatively, the contents of this file may be used under the terms of
27+
* either the GNU General Public License Version 2 or later (the "GPL"), or
28+
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29+
* in which case the provisions of the GPL or the LGPL are applicable instead
30+
* of those above. If you wish to allow use of your version of this file only
31+
* under the terms of either the GPL or the LGPL, and not to allow others to
32+
* use your version of this file under the terms of the MPL, indicate your
33+
* decision by deleting the provisions above and replace them with the notice
34+
* and other provisions required by the GPL or the LGPL. If you do not delete
35+
* the provisions above, a recipient may use your version of this file under
36+
* the terms of any one of the MPL, the GPL or the LGPL.
37+
*
38+
* ***** END LICENSE BLOCK ***** */
39+
40+
// A large portion of the original code has been snipped.
41+
// A large portion of this code wasn't in the original code. The license header
42+
// is here for legal reasons, I think. If you want to look at the original,
43+
// refer to http://lxr.mozilla.org/seamonkey/source/extensions/irc/js/lib/utils.js
44+
// and its cvs history there.
45+
46+
47+
function getWindowByType(windowType)
48+
{
49+
const MEDIATOR_CONTRACTID = "@mozilla.org/appshell/window-mediator;1";
50+
const nsIWindowMediator = Components.interfaces.nsIWindowMediator;
51+
52+
var windowManager =
53+
Components.classes[MEDIATOR_CONTRACTID].getService(nsIWindowMediator);
54+
55+
return windowManager.getMostRecentWindow(windowType);
56+
}
57+
58+
function stringTrim(s)
59+
{
60+
if (!s)
61+
return "";
62+
s = s.replace(/^\s+/, "");
63+
return s.replace(/\s+$/, "");
64+
}
65+
66+
function getService(contractID, iface)
67+
{
68+
var rv;
69+
var cls = Components.classes[contractID];
70+
71+
if (!cls)
72+
return null;
73+
74+
switch (typeof iface)
75+
{
76+
case "undefined":
77+
rv = cls.getService();
78+
break;
79+
80+
case "string":
81+
rv = cls.getService(Components.interfaces[iface]);
82+
break;
83+
84+
case "object":
85+
rv = cls.getService(iface);
86+
break;
87+
88+
default:
89+
rv = null;
90+
break;
91+
}
92+
93+
return rv;
94+
}
95+
96+
function newObject(contractID, iface)
97+
{
98+
var rv;
99+
var cls = Components.classes[contractID];
100+
101+
if (!cls)
102+
return null;
103+
104+
switch (typeof iface)
105+
{
106+
case "undefined":
107+
rv = cls.createInstance();
108+
break;
109+
110+
case "string":
111+
rv = cls.createInstance(Components.interfaces[iface]);
112+
break;
113+
114+
case "object":
115+
rv = cls.createInstance(iface);
116+
break;
117+
118+
default:
119+
rv = null;
120+
break;
121+
}
122+
123+
return rv;
124+
}
125+
126+
function dumpObjectTree (o, recurse, compress, level)
127+
{
128+
var s = "";
129+
var pfx = "";
130+
131+
if (typeof recurse == "undefined")
132+
recurse = 0;
133+
if (typeof level == "undefined")
134+
level = 0;
135+
if (typeof compress == "undefined")
136+
compress = true;
137+
138+
for (var i = 0; i < level; i++)
139+
pfx += (compress) ? "| " : "| ";
140+
141+
var tee = (compress) ? "+ " : "+- ";
142+
143+
for (i in o)
144+
{
145+
var t, ex;
146+
147+
try
148+
{
149+
t = typeof o[i];
150+
}
151+
catch (ex)
152+
{
153+
t = "ERROR";
154+
}
155+
156+
switch (t)
157+
{
158+
case "function":
159+
var sfunc = String(o[i]).split("\n");
160+
if (sfunc[2] == " [native code]")
161+
sfunc = "[native code]";
162+
else
163+
if (sfunc.length == 1)
164+
sfunc = String(sfunc);
165+
else
166+
sfunc = sfunc.length + " lines";
167+
s += pfx + tee + i + " (function) " + sfunc + "\n";
168+
break;
169+
170+
case "object":
171+
s += pfx + tee + i + " (object)\n";
172+
if (!compress)
173+
s += pfx + "|\n";
174+
if ((i != "parent") && (recurse))
175+
s += dumpObjectTree (o[i], recurse - 1,
176+
compress, level + 1);
177+
break;
178+
179+
case "string":
180+
if (o[i].length > 200)
181+
s += pfx + tee + i + " (" + t + ") " +
182+
o[i].length + " chars\n";
183+
else
184+
s += pfx + tee + i + " (" + t + ") '" + o[i] + "'\n";
185+
break;
186+
187+
case "ERROR":
188+
s += pfx + tee + i + " (" + t + ") ?\n";
189+
break;
190+
191+
default:
192+
s += pfx + tee + i + " (" + t + ") " + o[i] + "\n";
193+
194+
}
195+
if (!compress)
196+
s += pfx + "|\n";
197+
}
198+
s += pfx + "*\n";
199+
return s;
200+
}
201+
202+
function getFileFromURLSpec(url)
203+
{
204+
const nsIFileProtocolHandler = Components.interfaces.nsIFileProtocolHandler;
205+
var handler = iosvc.getProtocolHandler("file");
206+
handler = handler.QueryInterface(nsIFileProtocolHandler);
207+
return handler.getFileFromURLSpec(url);
208+
}
209+
210+
211+
// This would be my own cruft:
212+
213+
function glimpseEscape(str)
214+
{
215+
return str.replace(/([\$\^\*\[\|\(\)\!\\;,#><\-.])/g, "\\$1");
216+
}
217+
218+
function getStr(id)
219+
{
220+
return document.getElementById("locale-strings").getString(id);
221+
}
222+
223+
function setStatusText(str)
224+
{
225+
document.getElementById("status-text").setAttribute("label", str);
226+
}
227+
228+
function setStatusProgress(n)
229+
{
230+
var progressMeter = document.getElementById("status-progress-bar");
231+
if (n == -1)
232+
{
233+
progressMeter.parentNode.parentNode.setAttribute("hidden", "true");
234+
}
235+
else
236+
{
237+
progressMeter.setAttribute("value", String(n));
238+
progressMeter.parentNode.parentNode.setAttribute("hidden", "false");
239+
}
240+
}
241+

‎defaults/preferences/prefs.js

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pref("extensions.chromelist.open-files-in-tab", true);
2+
pref("extensions.chromelist.lxr-url", "http://lxr.mozilla.org/seamonkey/find?string=%s");

‎install.rdf

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0"?>
2+
<RDF:RDF xmlns:em="http://www.mozilla.org/2004/em-rdf#"
3+
xmlns:NC="http://home.netscape.com/NC-rdf#"
4+
xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
5+
<RDF:Description RDF:about="urn:mozilla:install-manifest"
6+
em:id="chromelist@extensions.gijsk.com"
7+
em:name="Chrome List"
8+
em:version="0.1"
9+
em:description="Lets you take a peek at the files under the hood of your Firefox installation and profile"
10+
em:creator="Gijs Kruitbosch"
11+
em:homepageURL="http://www.gijsk.com/">
12+
<em:file RDF:resource="urn:mozilla:extension:file:chrome"/>
13+
<em:targetApplication RDF:resource="rdf:#$w+QUG3"/>
14+
</RDF:Description>
15+
<RDF:Description RDF:about="urn:mozilla:extension:file:chrome"
16+
em:package="content"
17+
em:skin="skin"
18+
em:locale="locale" />
19+
<RDF:Description RDF:about="rdf:#$w+QUG3"
20+
em:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"
21+
em:minVersion="2.0"
22+
em:maxVersion="3.0a3" />
23+
</RDF:RDF>

‎license.txt

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
With un-compiled languages, comments affect the size of the shipped product, so
2+
to save space, this comment block applies to any file in the ChromeList XPI without
3+
its own licensing information.
4+
5+
--------------------------------------------------------------------------------
6+
7+
The contents of this file are subject to the Mozilla Public License
8+
Version 1.1 (the "License"); you may not use this file except in
9+
compliance with the License. You may obtain a copy of the License at
10+
http://www.mozilla.org/MPL/
11+
12+
Software distributed under the License is distributed on an "AS IS" basis,
13+
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14+
for the specific language governing rights and limitations under the
15+
License.
16+
17+
The Original Code is Chrome List
18+
19+
The Initial Developer of the Original Code is Gijs Kruitbosch
20+
Portions created by the Initial Developer are Copyright (C) 2007
21+
the Initial Developer. All Rights Reserved.
22+
23+
Contributor(s):
24+
Gijs Kruitbosch <gijskruitbosch@gmail.com> (Original Author)
25+
26+
Alternatively, the contents of this file may be used under the
27+
terms of the GNU Public License (the "GPL"), in which case the
28+
provisions of the GPL are applicable instead of those above.
29+
If you wish to allow use of your version of this file only
30+
under the terms of the GPL and not to allow others to use your
31+
version of this file under the MPL, indicate your decision by
32+
deleting the provisions above and replace them with the notice
33+
and other provisions required by the GPL. If you do not delete
34+
the provisions above, a recipient may use your version of this
35+
file under either the MPL or the GPL.

‎locale/chromelist.dtd

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<!-- window stuff -->
2+
<!ENTITY window.title "Chrome Browser">
3+
4+
<!-- tree stuff -->
5+
<!ENTITY tree.filetree.filesize "File Size">
6+
<!ENTITY tree.filetree.filetype "File Type">
7+
<!ENTITY tree.filetree.filename "File Name">
8+
9+
<!-- Context menu stuff -->
10+
<!ENTITY cx.open "Open">
11+
<!ENTITY cx.open.tab "In a New Tab">
12+
<!ENTITY cx.open.tab.accesskey "T">
13+
<!ENTITY cx.open.window "in a New Window">
14+
<!ENTITY cx.open.window.accesskey "W">
15+
<!ENTITY cx.open.current "Open in Current Window/Tab">
16+
<!ENTITY cx.open.current.accesskey "C">
17+
<!ENTITY cx.view-source "View Source">
18+
<!ENTITY cx.view-source.accesskey "S">
19+
20+
<!ENTITY cx.copy "Copy">
21+
<!ENTITY cx.copy.chrome "Chrome URL">
22+
<!ENTITY cx.copy.chrome.accesskey "C">
23+
<!ENTITY cx.copy.jarurl "JAR URL">
24+
<!ENTITY cx.copy.jarurl.accesskey "J">
25+
<!ENTITY cx.copy.jarpath "JARFile Path">
26+
<!ENTITY cx.copy.jarpath.accesskey "P">
27+
<!ENTITY cx.copy.fileurl "File URL">
28+
<!ENTITY cx.copy.fileurl.accesskey "F">
29+
<!ENTITY cx.copy.filepath "File Path">
30+
<!ENTITY cx.copy.filepath.accesskey "P">
31+
<!-- <!ENTITY cx.copy.content "File Contents">
32+
<!ENTITY cx.copy.contentdata "File Contents as Data URI"> -->
33+
34+
35+
<!ENTITY cx.properties "Properties...">
36+
<!ENTITY cx.properties.accesskey "P">
37+
<!ENTITY cx.save-as "Save As...">
38+
<!ENTITY cx.save-as.accesskey "A">
39+
<!ENTITY cx.lxr "Find file in LXR">
40+
<!ENTITY cx.lxr.accesskey "L">
41+
42+
43+
<!-- Properties dialog stuff -->
44+
<!ENTITY props.caption "Properties of ">
45+
<!ENTITY props.header.label "File Properties">
46+
<!ENTITY props.chrome-url.label "Chrome URL">
47+
<!ENTITY props.resolved-url.label "Resolved URL">
48+
<!ENTITY props.resolved-file.label "File Path">
49+
<!ENTITY props.resolved-jarfile.label "JARFile Path">
50+
<!ENTITY props.manifest.label "Package Manifest">
51+
<!ENTITY props.file-size.label "File Size">
52+

‎locale/chromelist.properties

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
info.status.reading.manifests = Reading Manifests...
2+
info.status.mapping.chrome = Mapping Chrome URLs...
3+
info.status.done = Done.

‎preview-small.png

11.1 KB
Loading

‎preview.png

21.1 KB
Loading

‎skin/icons/folders.png

1006 Bytes
Loading

‎skin/properties.css

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
@import "chrome://global/skin/";
2+
3+
tree {
4+
margin: .5em;
5+
}
6+
7+
textbox,
8+
textbox > .textbox-internal-box,
9+
textbox > .textarea-internal-box {
10+
background: transparent !important;
11+
border: none;
12+
padding: 0px;
13+
-moz-appearance: none;
14+
}
15+
16+
textbox.header {
17+
-moz-margin-start: 0;
18+
}
19+
20+
#thepreviewimage {
21+
margin: 1em;
22+
}
23+
24+
.fixedsize {
25+
height: 8.5em;
26+
}
27+
28+
textbox[disabled] {
29+
font-style: italic;
30+
}
31+

‎skin/tree.css

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
.dirTree::-moz-tree-image(closed) {
2+
list-style-image: url("chrome://chromelist/skin/icons/folders.png");
3+
margin-right: 2px;
4+
-moz-image-region: rect(0px 16px 16px 0px);
5+
}
6+
7+
.fileTree::-moz-tree-image(isFolder) {
8+
list-style-image: url("chrome://chromelist/skin/icons/folders.png");
9+
margin-right: 2px;
10+
-moz-image-region: rect(0px 16px 16px 0px);
11+
}
12+
13+
.dirTree::-moz-tree-image(open) {
14+
list-style-image: url("chrome://chromelist/skin/icons/folders.png");
15+
-moz-image-region: rect(0px 32px 16px 16px);
16+
margin-right: 2px;
17+
}
18+
19+
.fileTree::-moz-tree-image
20+
{
21+
margin-right: 2px;
22+
}

0 commit comments

Comments
 (0)
Please sign in to comment.