Oops, fix a scale problem with the RSS size calculation
[beagle.git] / mozilla-extension / content / beagleOverlay.js
blob2a3971fc4fbfe26a79e02de592fe738642e1cf79
1 /* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3 * Beagle Extension: Index webpages you visit using the Beagle Indexing Engine.
4 * An Extension for the Firefox (and Mozilla?) Browser.
5 */
7 // Initiate a new preference instance.
8 var gPref = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces.nsIPrefBranch);
9 var gEnv = Components.classes["@mozilla.org/process/environment;1"].getService(Components.interfaces.nsIEnvironment);
11 // Load jslib parts used in file execution
12 var gFile = new FileUtils();
14 // Create the global variables
15 var gBeagleRunStatus = 0;
16 var gBeagleDataPath = gEnv.get("HOME") + "/.beagle/ToIndex";
17 var gBeagleDataDir = new Dir(gBeagleDataPath);
18 var gBeagleBestPath;
20 function beagleFindFileInPath(filename)
22 var path = gEnv.get("PATH");
23 if (path) {
24 var split = path.split(':');
25 var idx = 0;
26 while (idx < split.length) {
27 var trypath = split[idx++] + '/' + filename;
28 if (gFile.exists(trypath))
29 return trypath;
32 return undefined;
35 function beagleInit()
37 dump ("beagleInit started!\n");
39 gBeagleBestPath = beagleFindFileInPath("beagle-search");
41 dump ("beagleInit: Found beagle-search: " + gBeagleBestPath + "\n");
43 // Create eventlistener to trigger when context menu is invoked.
44 if (gBeagleBestPath) {
45 try {
46 document.getElementById('contentAreaContextMenu').addEventListener('popupshowing',
47 beagleContext,
48 false);
49 } catch(e) {
50 alert(e);
54 // Get the global enable/disable pref
55 try { bPref = gPref.getBoolPref('beagle.enabled'); }
56 catch(e) { bPref = true }
58 if (bPref)
59 gBeagleRunStatus = 0;
60 else
61 gBeagleRunStatus = -1;
63 // Add listener for page loads
64 if (document.getElementById("appcontent"))
65 document.getElementById("appcontent").addEventListener("load",
66 beaglePageLoad,
67 true);
68 dump ("beagleInit : Listening to document['appcontent'].load\n");
70 beagleUpdateStatus ();
74 // Copied from nsIWebBrowserPersist.idl
77 // Only use cached data (could fail)
78 var PERSIST_FLAGS_FROM_CACHE = 1;
79 // Replace existing files on the disk
80 var PERSIST_FLAGS_REPLACE_EXISTING_FILES = 32;
81 // Don't modify or add base tags
82 var PERSIST_FLAGS_NO_BASE_TAG_MODIFICATIONS = 64;
83 // Don't make any adjustments to links
84 var PERSIST_FLAGS_DONT_FIXUP_LINKS = 512;
85 // Don't make any adjustments to filenames
86 var PERSIST_FLAGS_DONT_CHANGE_FILENAMES = 2048;
87 // Cleanup on failure
88 var PERSIST_FLAGS_CLEANUP_ON_FAILURE = 8192;
90 var PERSIST_MASK = (PERSIST_FLAGS_FROM_CACHE |
91 PERSIST_FLAGS_REPLACE_EXISTING_FILES |
92 PERSIST_FLAGS_NO_BASE_TAG_MODIFICATIONS |
93 PERSIST_FLAGS_DONT_FIXUP_LINKS |
94 PERSIST_FLAGS_DONT_CHANGE_FILENAMES |
95 PERSIST_FLAGS_CLEANUP_ON_FAILURE);
97 // Write raw source
98 var ENCODE_FLAGS_RAW = 4;
99 // Convert links to absolute links where possible.
100 var ENCODE_FLAGS_ABSOLUTE_LINKS = 128;
102 var ENCODE_MASK = (ENCODE_FLAGS_RAW | ENCODE_FLAGS_ABSOLUTE_LINKS);
104 function beagleWriteContent(page, tmpfilepath)
106 var tmpfile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
107 tmpfile.initWithPath(tmpfilepath);
109 var persist = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(Components.interfaces.nsIWebBrowserPersist);
110 persist.persistFlags = PERSIST_MASK;
112 persist.saveDocument(page, tmpfile, null, null, ENCODE_MASK, 0);
115 function beagleWriteMetadata(page, tmpfilepath)
117 var tmpfile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
118 tmpfile.initWithPath(tmpfilepath);
120 var stream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
121 stream.QueryInterface(Components.interfaces.nsIOutputStream);
122 stream.init(tmpfile, 0x04 | 0x08 | 0x20, 0600, 0);
124 var line;
126 // First line: URI
127 line = page.location.href + "\n";
128 stream.write(line, line.length);
130 // Second line: Hit Type
131 line = "WebHistory\n";
132 stream.write(line, line.length);
134 // Third line: Mime type
135 line = "text/html\n";
136 stream.write(line, line.length);
138 // Additional lines: Properties
139 line = "k:_unindexed:encoding=" + page.characterSet + "\n";
140 stream.write(line, line.length);
142 stream.flush();
143 stream.close();
146 function beagleShouldIndex(page)
148 // user disabled, or can't find beagle-index-url.
149 if (gBeagleRunStatus == -1)
150 return false;
152 if (!page ||
153 !page.location ||
154 page.location == 'about:blank' ||
155 !page.location.href) {
156 dump("beagleShouldIndex: strange page: " + page + "\n");
157 return false;
160 try {
161 fPref = gPref.getCharPref('beagle.security.filters');
162 var filtered = fPref.split(';');
163 for (j = 0; j < filtered.length; j++){
164 if (page.location.host.search("/"+filtered[j]+"/i") != -1){
165 dump("beagleShouldIndex: filtered host: " + page.location.host + '\n');
166 gBeagleRunStatus = -2;
167 beagleUpdateStatus ();
168 return false;
171 } catch (e) {
172 // Do nothing..
175 if (page.location.protocol == "https:") {
176 var bPref;
178 // secure content, check if user wants it indexed
179 try { bPref = gPref.getBoolPref('beagle.security.active'); }
180 catch(e) { bPref = false }
182 if (!bPref) {
183 // don't index. disable and return.
184 gBeagleRunStatus = -2;
185 beagleUpdateStatus ();
186 return false;
188 } else if (gBeagleRunStatus == -2) {
189 // no longer secure content, re-enable
190 gBeagleRunStatus = 0;
191 beagleUpdateStatus ();
194 return true;
197 function beaglePageLoad(event)
199 var page = event.originalTarget;
201 if (!beagleShouldIndex (page))
202 return;
204 if (!gFile.exists (gEnv.get("HOME") + "/.beagle")) {
205 dump("beaglePageLoad: ~/.beagle doesn't exist, not indexing");
206 return;
209 dump("beaglePageLoad: storing page: " + page.location.href + "\n");
211 if (!gFile.exists(gBeagleDataPath)) {
212 try {
213 gBeagleDataDir.create ();
214 dump ("beaglePageLoad: Created .beagle/firefox\n");
215 } catch(e) {
216 dump ("beaglePageLoad: Unable to create .beagle/firefox: " + e + "\n");
220 var hash = hex_md5(page.location.href);
221 var tmpdatapath = gBeagleDataPath + "/firefox-beagle-" + hash + ".html";
222 var tmpmetapath = gBeagleDataPath + "/.firefox-beagle-" + hash + ".html";
224 try {
225 beagleWriteContent(page, tmpdatapath);
226 dump ("beaglePageLoad: beagleWriteContent sucessful!\n");
227 beagleWriteMetadata(page, tmpmetapath);
228 dump ("beaglePageLoad: beagleWriteMetadata sucessful!\n");
229 } catch (ex) {
230 alert ("beaglePageLoad: beagleWriteContent/Metadata failed: " + ex);
234 function beagleRunBest(query)
236 try {
237 dump("Running best with query: "+ query + "\n");
238 var retval = gFile.spawn(gBeagleBestPath, ["", query]);
239 if (retval)
240 alert("Error running best: " + retval);
241 } catch(e) {
242 alert("Caught error from best: " + e);
246 function beagleShowPrefs()
248 window.openDialog('chrome://beagle/content/beaglePrefs.xul',
249 'PrefWindow',
250 'chrome,modal=yes,resizable=no',
251 'browser');
254 function beagleProcessClick(event)
256 // Right-click event.
257 if (event.button == 2) {
258 beagleShowPrefs();
259 return;
262 // Left-click event (also single click, like Mac).
263 if (event.button == 0) {
264 if (event.ctrlKey) {
265 // Ctrl-click for Mac properties. Works on PC too.
266 beagleShowPrefs();
267 } else {
268 switch(gBeagleRunStatus) {
269 case 0:
270 // currently enabled. disable by user.
271 gBeagleRunStatus = -1;
272 gPref.setBoolPref('beagle.enabled', false);
273 break;
274 case -1:
275 case -2:
276 // currently disabled (by user or by secure content). enable.
277 gBeagleRunStatus = 0;
278 gPref.setBoolPref('beagle.enabled', true);
279 break;
280 default:
281 // last run was an error, show the error
282 alert("Error running Beagle Indexer: " + gBeagleRunStatus);
283 return;
286 beagleUpdateStatus();
291 function beagleUpdateStatus()
293 var icon = document.getElementById('beagle-notifier-status');
295 switch(gBeagleRunStatus) {
296 case 0: // active
297 icon.setAttribute("status","000");
298 icon.setAttribute("tooltiptext","Beagle indexing active. Click to disable.");
299 break;
300 case -1: // disabled by user
301 case -2: // disabled for secure protocol
302 icon.setAttribute("status","00f");
303 icon.setAttribute("tooltiptext","Beagle indexing disabled. Click to enable.");
304 break;
305 default: // anything else is an error
306 icon.setAttribute("status","f00");
307 icon.setAttribute("tooltiptext",
308 "Error while indexing: " + gBeagleRunStatus);
309 break;
313 // Create event listener.
314 window.addEventListener('load', beagleInit, false);
316 // Right-click context menu
317 function beagleContext()
319 var bPref;
321 // Find context menu display preference.
322 try { bPref = gPref.getBoolPref('beagle.context.active'); }
323 catch(e) { }
325 // Set hidden property of context menu and separators.
326 document.getElementById('beagle-context-menu').hidden = !(bPref);
327 document.getElementById('beagle-context-sep-a').hidden = !(bPref);
328 document.getElementById('beagle-context-sep-b').hidden = !(bPref);
330 // If not displaying context menu, return.
331 if (!bPref) return;
333 // Separator A (top) display preference.
334 try { bPref = gPref.getBoolPref('beagle.context.sep.a'); }
335 catch(e) { bPref = false }
336 document.getElementById('beagle-context-sep-a').hidden = !(bPref);
338 // Separator B (bottom) display preference.
339 try { bPref = gPref.getBoolPref('beagle.context.sep.b'); }
340 catch(e) { bPref = false }
341 document.getElementById('beagle-context-sep-b').hidden = !(bPref);
343 // Should search link item be hidden or shown?
344 document.getElementById('beagle-context-search-link').hidden = !(gContextMenu.onLink);
346 // Should text search item be hidden or shown?
347 document.getElementById('beagle-context-search-text').hidden = !(gContextMenu.isTextSelected);
348 document.getElementById('beagle-context-search-text').setAttribute("label","Search for \"" + gContextMenu.searchSelected() + "\"");