summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartyn Russell <martyn@lanedo.com>2011-07-29 14:18:30 +0100
committerMartyn Russell <martyn@lanedo.com>2011-07-29 14:18:30 +0100
commit37563f88e254ce8b804660e87b64986edaf61316 (patch)
tree53784e3f33aef491b620be76ed9f84536294b316
parent76535bc895c6ce2a164f7957e2297ddcba7b5930 (diff)
parentc71b741a17c6a0ca4872a5a8feb87954a6376bc9 (diff)
downloadtracker-37563f88e254ce8b804660e87b64986edaf61316.tar.gz
Merge branch 'firefox'
-rw-r--r--.gitignore1
-rw-r--r--configure.ac71
-rw-r--r--docs/manpages/tracker-search.116
-rw-r--r--src/plugins/Makefile.am4
-rw-r--r--src/plugins/firefox/COPYRIGHT15
-rw-r--r--src/plugins/firefox/Makefile.am17
-rw-r--r--src/plugins/firefox/README8
-rw-r--r--src/plugins/firefox/chrome.manifest8
-rw-r--r--src/plugins/firefox/chrome/Makefile.am3
-rw-r--r--src/plugins/firefox/chrome/content/Makefile.am10
-rw-r--r--src/plugins/firefox/chrome/content/about.xul18
-rw-r--r--src/plugins/firefox/chrome/content/bindings.js127
-rw-r--r--src/plugins/firefox/chrome/content/bookmarks.js366
-rw-r--r--src/plugins/firefox/chrome/content/ff-overlay.xul17
-rw-r--r--src/plugins/firefox/chrome/content/namespace.js5
-rw-r--r--src/plugins/firefox/chrome/content/plugin.js64
-rw-r--r--src/plugins/firefox/chrome/locale/Makefile.am3
-rw-r--r--src/plugins/firefox/chrome/locale/en-US/Makefile.am7
-rw-r--r--src/plugins/firefox/chrome/locale/en-US/about.dtd4
-rw-r--r--src/plugins/firefox/chrome/locale/en-US/overlay.dtd0
-rw-r--r--src/plugins/firefox/chrome/locale/en-US/overlay.properties1
-rw-r--r--src/plugins/firefox/chrome/locale/es-ES/Makefile.am7
-rw-r--r--src/plugins/firefox/chrome/locale/es-ES/about.dtd4
-rw-r--r--src/plugins/firefox/chrome/locale/es-ES/overlay.dtd0
-rw-r--r--src/plugins/firefox/chrome/locale/es-ES/overlay.properties1
-rw-r--r--src/plugins/firefox/chrome/locale/fr-FR/Makefile.am7
-rw-r--r--src/plugins/firefox/chrome/locale/fr-FR/about.dtd4
-rw-r--r--src/plugins/firefox/chrome/locale/fr-FR/overlay.dtd0
-rw-r--r--src/plugins/firefox/chrome/locale/fr-FR/overlay.properties1
-rw-r--r--src/plugins/firefox/chrome/skin/Makefile.am5
-rw-r--r--src/plugins/firefox/chrome/skin/overlay.css22
-rw-r--r--src/plugins/firefox/defaults/Makefile.am3
-rw-r--r--src/plugins/firefox/defaults/preferences/Makefile.am5
-rw-r--r--src/plugins/firefox/defaults/preferences/prefs.js2
-rw-r--r--src/plugins/firefox/install.rdf.in20
-rw-r--r--src/tracker-utils/tracker-search.c97
36 files changed, 943 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index 5343f40b9..5f76aa0a7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,6 +27,7 @@ coverage
depcomp
gtk-doc.make
install-sh
+install.rdf
intltool-extract.in
intltool-merge.in
intltool-update.in
diff --git a/configure.ac b/configure.ac
index 5d1e910fb..a1a9673ef 100644
--- a/configure.ac
+++ b/configure.ac
@@ -407,6 +407,20 @@ if test -n $THUNDERBIRD; then
AC_SUBST(THUNDERBIRD)
fi
+# Check requirements for tracker-miner-firefox
+TRACKER_MINER_FIREFOX_REQUIRED=4.0
+have_tracker_miner_firefox="no "
+
+AC_PATH_PROG(FIREFOX, firefox, firefox)
+if test -n $FIREFOX; then
+ firefox_version=`$FIREFOX --version | cut -d" " -f3`
+
+ AX_COMPARE_VERSION([$firefox_version], ge, [$TRACKER_MINER_FIREFOX_REQUIRED],
+ have_tracker_miner_firefox="yes",
+ have_tracker_miner_firefox="no ")
+ AC_SUBST(FIREFOX)
+fi
+
# Check requirements for tracker-miner-rss
TRACKER_MINER_RSS_REQUIRED="glib-2.0 >= $GLIB_REQUIRED
libgrss-0 >= $LIBGRSS_REQUIRED"
@@ -1238,6 +1252,51 @@ AC_SUBST(TRACKER_MINER_THUNDERBIRD_INSTALL_DIR)
AM_CONDITIONAL(HAVE_TRACKER_MINER_THUNDERBIRD, test "x$have_tracker_miner_thunderbird" = "xyes")
####################################################################
+# Check for tracker-miner-firefox
+####################################################################
+
+tracker_miner_firefox_install_dir="/dev/null"
+
+AC_ARG_ENABLE([miner_firefox],
+ AS_HELP_STRING([--enable-miner-firefox],
+ [enable Firefox email data miner [[default=auto]]]),,
+ [enable_miner_firefox=auto])
+
+enable_tracker_miner_firefox=$enable_miner_firefox
+
+if test "x$enable_tracker_miner_firefox" = "xyes"; then
+ if test "x$have_tracker_miner_firefox" != "xyes"; then
+ AC_MSG_ERROR([Couldn't find Firefox ($TRACKER_MINER_FIREFOX_REQUIRED).])
+ fi
+else
+ if test "x$enable_tracker_miner_firefox" = "xno"; then
+ have_tracker_miner_firefox="no (disabled)"
+ fi
+fi
+
+if test "x$have_tracker_miner_firefox" = "xyes"; then
+
+ AC_ARG_WITH([firefox_plugin_dir],
+ AS_HELP_STRING([--with-firefox-plugin-dir],
+ [path to Firefox plugin directory]))
+ if test "x$with_firefox_plugin_dir" = "x" ; then
+ # This is a symlinked to $prefix/share/xul-ext
+ tracker_miner_firefox_install_dir="${prefix}/lib/firefox-5.0/extensions"
+ else
+ tracker_miner_firefox_install_dir="$with_firefox_plugin_dir"
+ fi
+
+ if test -z $tracker_miner_firefox_install_dir; then
+ AC_MSG_ERROR([Couldn't find firefox plugin dir, consider using --with-firefox-plugin-dir.])
+ fi
+fi
+
+TRACKER_MINER_FIREFOX_INSTALL_DIR=$tracker_miner_firefox_install_dir
+AC_SUBST(TRACKER_MINER_FIREFOX_INSTALL_DIR)
+
+AM_CONDITIONAL(HAVE_TRACKER_MINER_FIREFOX, test "x$have_tracker_miner_firefox" = "xyes")
+
+####################################################################
# Check for nautilus extension
####################################################################
@@ -2140,6 +2199,17 @@ AC_CONFIG_FILES([
src/plugins/thunderbird/chrome/skin/Makefile
src/plugins/thunderbird/defaults/Makefile
src/plugins/thunderbird/defaults/preferences/Makefile
+ src/plugins/firefox/Makefile
+ src/plugins/firefox/install.rdf
+ src/plugins/firefox/chrome/Makefile
+ src/plugins/firefox/chrome/content/Makefile
+ src/plugins/firefox/chrome/locale/Makefile
+ src/plugins/firefox/chrome/locale/en-US/Makefile
+ src/plugins/firefox/chrome/locale/es-ES/Makefile
+ src/plugins/firefox/chrome/locale/fr-FR/Makefile
+ src/plugins/firefox/chrome/skin/Makefile
+ src/plugins/firefox/defaults/Makefile
+ src/plugins/firefox/defaults/preferences/Makefile
src/plugins/nautilus/Makefile
src/vapi/Makefile
tests/common/Makefile
@@ -2277,6 +2347,7 @@ Data Miners:
RSS: $have_tracker_miner_rss
Evolution: $have_tracker_miner_evolution ($tracker_miner_evolution_install_dir)
Thunderbird: $have_tracker_miner_thunderbird ($tracker_miner_thunderbird_install_dir)
+ FireFox: $have_tracker_miner_firefox ($tracker_miner_firefox_install_dir)
Flickr: $have_tracker_miner_flickr
Plugins:
diff --git a/docs/manpages/tracker-search.1 b/docs/manpages/tracker-search.1
index 2c2987186..72f0bbbe8 100644
--- a/docs/manpages/tracker-search.1
+++ b/docs/manpages/tracker-search.1
@@ -79,6 +79,22 @@ of subjects for emails found.
Search for contacts matching \fIEXPRESSION\fR (optional). Returns a list
of names and email addresses found.
.TP
+.B \-\-software=EXPRESSION
+Search for software installed matching \fIEXPRESSION\fR (optional). Returns a list
+of desktop files and application titles found.
+.TP
+.B \-\-software-categories=EXPRESSION
+Search for software categories matching \fIEXPRESSION\fR (optional). Returns a list
+of urns and their categories (e.g. Settings, Video, Utility, etc).
+.TP
+.B \-\-feeds=EXPRESSION
+Search through RSS feed information matching \fIEXPRESSION\fR (optional). Returns a list
+of those found.
+.TP
+.B \-b, \-\-bookmarks=EXPRESSION
+Search through bookmarks matching \fIEXPRESSION\fR (optional). Returns a list
+titles and links for each bookmark found.
+.TP
.B \-V, \-\-version
Print version.
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 37406a4f6..e525adb49 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -10,6 +10,10 @@ if HAVE_TRACKER_MINER_THUNDERBIRD
SUBDIRS += thunderbird
endif
+if HAVE_TRACKER_MINER_FIREFOX
+SUBDIRS += firefox
+endif
+
if HAVE_TRACKER_NAUTILUS_EXTENSION
SUBDIRS += nautilus
endif
diff --git a/src/plugins/firefox/COPYRIGHT b/src/plugins/firefox/COPYRIGHT
new file mode 100644
index 000000000..716e99751
--- /dev/null
+++ b/src/plugins/firefox/COPYRIGHT
@@ -0,0 +1,15 @@
+Tracker-Firefox - Tracker addon that exports data to Firefox
+Copyright (C) 2011 Adrien Bustany <abustany@gnome.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
diff --git a/src/plugins/firefox/Makefile.am b/src/plugins/firefox/Makefile.am
new file mode 100644
index 000000000..b62743078
--- /dev/null
+++ b/src/plugins/firefox/Makefile.am
@@ -0,0 +1,17 @@
+include $(top_srcdir)/Makefile.decl
+
+SUBDIRS = chrome defaults
+
+extensiondir = $(datadir)/xul-ext/trackerfox
+extension_DATA = \
+ install.rdf \
+ chrome.manifest \
+ README \
+ COPYRIGHT
+
+install-data-hook:
+ mkdir -p "$(TRACKER_MINER_FIREFOX_INSTALL_DIR)"
+ $(LN_S) "$(extensiondir)" "$(TRACKER_MINER_FIREFOX_INSTALL_DIR)/trackerfox@bustany.org"
+
+uninstall-hook:
+ $(RM) "$(TRACKER_MINER_FIREFOX_INSTALL_DIR)/trackerfox@bustany.org" \ No newline at end of file
diff --git a/src/plugins/firefox/README b/src/plugins/firefox/README
new file mode 100644
index 000000000..4c7658bbe
--- /dev/null
+++ b/src/plugins/firefox/README
@@ -0,0 +1,8 @@
+A simple bookmark exporter for Tracker
+
+This Firefox addon exports your bookmarks to Tracker, so that you can search
+for them for example using tracker-needle.
+
+To generate the XPI from the git repository, use the following command:
+
+git archive --format=zip HEAD > tracker-firefox.xpi
diff --git a/src/plugins/firefox/chrome.manifest b/src/plugins/firefox/chrome.manifest
new file mode 100644
index 000000000..7c69b5b59
--- /dev/null
+++ b/src/plugins/firefox/chrome.manifest
@@ -0,0 +1,8 @@
+content trackerfox chrome/content/
+skin trackerfox classic/1.0 chrome/skin/
+locale trackerfox en-US chrome/locale/en-US/
+locale trackerfox fr-FR chrome/locale/fr-FR/
+locale trackerfox es-ES chrome/locale/es-ES/
+
+
+overlay chrome://browser/content/browser.xul chrome://trackerfox/content/ff-overlay.xul
diff --git a/src/plugins/firefox/chrome/Makefile.am b/src/plugins/firefox/chrome/Makefile.am
new file mode 100644
index 000000000..8e1b19dbf
--- /dev/null
+++ b/src/plugins/firefox/chrome/Makefile.am
@@ -0,0 +1,3 @@
+include $(top_srcdir)/Makefile.decl
+
+SUBDIRS = skin locale content
diff --git a/src/plugins/firefox/chrome/content/Makefile.am b/src/plugins/firefox/chrome/content/Makefile.am
new file mode 100644
index 000000000..c51e8749f
--- /dev/null
+++ b/src/plugins/firefox/chrome/content/Makefile.am
@@ -0,0 +1,10 @@
+include $(top_srcdir)/Makefile.decl
+
+extensiondir = $(datadir)/xul-ext/trackerfox/chrome/content
+extension_DATA = \
+ about.xul \
+ bindings.js \
+ bookmarks.js \
+ ff-overlay.xul \
+ namespace.js \
+ plugin.js
diff --git a/src/plugins/firefox/chrome/content/about.xul b/src/plugins/firefox/chrome/content/about.xul
new file mode 100644
index 000000000..fc923a50d
--- /dev/null
+++ b/src/plugins/firefox/chrome/content/about.xul
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<!DOCTYPE dialog SYSTEM "chrome://trackerfox/locale/about.dtd">
+
+<dialog title="&about; TrackerFox" orient="vertical" autostretch="always" onload="sizeToContent()" buttons="accept" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <groupbox align="center" orient="horizontal">
+ <vbox>
+ <text value="TrackerFox" style="font-weight: bold; font-size: x-large;"/>
+ <text value="&version; 1.0"/>
+ <separator class="thin"/>
+ <text value="&createdBy;" style="font-weight: bold;"/>
+ <text value="Adrien Bustany"/>
+ <separator class="thin"/>
+ </vbox>
+ </groupbox>
+</dialog>
diff --git a/src/plugins/firefox/chrome/content/bindings.js b/src/plugins/firefox/chrome/content/bindings.js
new file mode 100644
index 000000000..a5374a56d
--- /dev/null
+++ b/src/plugins/firefox/chrome/content/bindings.js
@@ -0,0 +1,127 @@
+if (!org.bustany.TrackerFox.TrackerSparql || !org.bustany.TrackerFox.TrackerSparql.__initialized)
+org.bustany.TrackerFox.TrackerSparql = {
+ __initialized: true,
+
+ _trackerSparqlPath: "libtracker-sparql-0.10.so.0",
+ _lib: null,
+
+ init: function () {
+ var tracker = org.bustany.TrackerFox.TrackerSparql;
+
+ // Safeguard just in case a fool would call that twice
+ if (tracker._lib) {
+ return true;
+ }
+
+ Components.utils.import ("resource://gre/modules/ctypes.jsm");
+
+ try {
+ tracker._lib = ctypes.open (tracker._trackerSparqlPath);
+ } catch (e) {
+ tracker._trackerSparqlPath = "libtracker-sparql-0.11.so.0";
+
+ try {
+ tracker._lib = ctypes.open (tracker._trackerSparqlPath);
+ } catch (e) {
+ dump("Could not load libtracker-sparql 0.10 or 0.11\n");
+ return false;
+ }
+ }
+
+ // GLib types
+ tracker.Cancellable = new ctypes.StructType ("GCancellable");
+ tracker.Error = new ctypes.StructType ("GError", [
+ {domain : ctypes.uint32_t},
+ {code : ctypes.int32_t},
+ {message : ctypes.char.ptr}
+ ]);
+
+ // TrackerSparql types
+ tracker.Connection = ctypes.StructType ("TrackerSparqlConnection");
+ tracker.Cursor = ctypes.StructType ("TrackerSparqlCursor");
+
+ // GLib methods
+ tracker.object_unref = tracker._lib.declare (
+ "g_object_unref",
+ ctypes.default_abi,
+ ctypes.void_t,
+ ctypes.void_t.ptr // Binding GObject* as a void* since we don't have GObject binding...
+ );
+
+ tracker.error_free = tracker._lib.declare (
+ "g_error_free",
+ ctypes.default_abi,
+ ctypes.void_t,
+ tracker.Error.ptr
+ );
+
+ // TrackerSparql methods (name, ABI, args with first arg = return type)
+ tracker.connection_open = tracker._lib.declare (
+ "tracker_sparql_connection_get",
+ ctypes.default_abi,
+ tracker.Connection.ptr,
+ tracker.Cancellable.ptr,
+ tracker.Error.ptr.ptr
+ );
+
+ tracker.connection_query = tracker._lib.declare (
+ "tracker_sparql_connection_query",
+ ctypes.default_abi,
+ tracker.Cursor.ptr,
+ tracker.Connection.ptr,
+ ctypes.char.ptr,
+ tracker.Cancellable.ptr,
+ tracker.Error.ptr.ptr
+ );
+
+ tracker.connection_update = tracker._lib.declare (
+ "tracker_sparql_connection_update",
+ ctypes.default_abi,
+ ctypes.void_t,
+ tracker.Connection.ptr,
+ ctypes.char.ptr,
+ ctypes.int32_t,
+ tracker.Cancellable.ptr,
+ tracker.Error.ptr.ptr
+ );
+
+ tracker.cursor_next = tracker._lib.declare (
+ "tracker_sparql_cursor_next",
+ ctypes.default_abi,
+ ctypes.bool,
+ tracker.Cursor.ptr,
+ tracker.Cancellable.ptr,
+ tracker.Error.ptr.ptr
+ );
+
+ tracker.cursor_get_string = tracker._lib.declare (
+ "tracker_sparql_cursor_get_string",
+ ctypes.default_abi,
+ ctypes.char.ptr,
+ tracker.Cursor.ptr,
+ ctypes.int,
+ ctypes.long.ptr
+ );
+
+ tracker.escape_string = tracker._lib.declare (
+ "tracker_sparql_escape_string",
+ ctypes.default_abi,
+ ctypes.char.ptr,
+ ctypes.char.ptr
+ );
+
+ return true;
+ },
+
+ shutdown: function () {
+ var tracker = org.bustany.TrackerFox.TrackerSparql;
+
+ if (this._connection) {
+ tracker.object_unref(this._connection);
+ }
+
+ if (this._lib) {
+ this._lib.close ();
+ }
+ }
+}
diff --git a/src/plugins/firefox/chrome/content/bookmarks.js b/src/plugins/firefox/chrome/content/bookmarks.js
new file mode 100644
index 000000000..eebf26a3f
--- /dev/null
+++ b/src/plugins/firefox/chrome/content/bookmarks.js
@@ -0,0 +1,366 @@
+if (!org.bustany.TrackerFox.Bookmarks || !org.bustany.TrackerFox.Bookmarks.__initialized)
+org.bustany.TrackerFox.Bookmarks = {
+ __initialized: true,
+
+ _tracker: org.bustany.TrackerFox.TrackerSparql,
+ _connection: null,
+ _dataSourceUrn: "urn:nepomuk:datasource:4754847fa79e41c6badc0bfc69e324d2",
+
+ _bmService: null,
+ _histService: null,
+
+ _observer: null,
+
+ init: function (connection) {
+ this._connection = connection;
+
+ this._bmService = Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"]
+ .getService (Components.interfaces.nsINavBookmarksService);
+ this._histService = Components.classes["@mozilla.org/browser/nav-history-service;1"]
+ .getService (Components.interfaces.nsINavHistoryService);
+
+ if (!this.insertDataSource ()) {
+ return false;
+ }
+
+ Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+ this.setupObserver ();
+
+ return true;
+ },
+
+ shutdown: function () {
+ if (this._observer) {
+ this._bmService.removeObserver (this._observer);
+ }
+ },
+
+ setupObserver: function () {
+ if (this._observer) {
+ return;
+ }
+
+ this._observer = {
+ _attached: false,
+
+ service: org.bustany.TrackerFox.Bookmarks,
+
+ onItemAdded: function (itemId, parentId, index, itemType, uri) {
+ var bookmark = this.getBookmark (itemId, parentId, itemType, uri);
+
+ if (!bookmark) {
+ dump ("Could not load new bookmark\n");
+ return;
+ }
+
+ this.service.insertBookmarks ([bookmark]);
+ },
+
+ onItemChanged: function (itemId, property, isAnnotation, newValue, lastModified, itemType) {
+ if (property == "") {
+ return;
+ }
+
+ dump ("Bookmark changed " + property + "!\n");
+ },
+
+ onItemRemoved: function (id, parentId, index, itemType) {
+ var bookmark = { itemId: id };
+
+ this.service.deleteBookmarks ([bookmark]);
+ },
+
+ getBookmark: function (itemId, parentId, itemType, uri) {
+ var bookmarks = this.service._bmService;
+ var history = this.service._histService;
+
+ if (itemType != bookmarks.TYPE_BOOKMARK) {
+ return;
+ }
+
+ // No idea how you get a full bookmark directly from its id
+ var query = history.getNewQuery ();
+ query.setFolders ([parentId], 1);
+ query.onlyBookmarked = true;
+
+ if (uri) {
+ query.uri = uri;
+ }
+
+ var options = history.getNewQueryOptions ();
+ options.queryType = options.QUERY_TYPE_BOOKMARKS;
+ var result = history.executeQuery (query, options);
+ var root = result.root;
+ root.containerOpen = true;
+
+ var bookmark = null;
+
+ for (var i = 0; i < root.childCount; ++i) {
+ var b = root.getChild (i);
+
+ if (b.itemId == itemId) {
+ bookmark = b;
+ }
+ }
+
+ if (!bookmark) {
+ dump ("Couldn't find the bookmark with id " + itemId + "!\n");
+ }
+
+ return bookmark;
+ },
+
+ QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsINavBookmarkObserver])
+ };
+
+ this._bmService.addObserver (this._observer, false);
+ },
+
+ insertDataSource: function () {
+ var tracker = this._tracker;
+
+ var error = new tracker.Error.ptr;
+ tracker.connection_update (this._connection,
+ "INSERT { <" + this._dataSourceUrn + "> " +
+ "a nie:DataSource; " +
+ "rdfs:label \"TrackerFox\"}",
+ 0,
+ null,
+ error.address ());
+
+ if (!error.isNull ()) {
+ this.handleError (error, "Can't insert DataSource");
+ return false;
+ }
+
+ return true;
+ },
+
+ syncBookmarks: function () {
+ var localBookmarks = this.getLocalBookmarks();
+ var trackerBookmarks = this.getTrackerBookmarks ();
+
+ // Quirky way of detecting an error
+ if (trackerBookmarks.length == 1 && trackerBookmarks[0] == null) {
+ return false;
+ }
+
+ var trackerDict = {};
+ var newBookmarks = new Array ();
+ var updatedBookmarks = new Array();
+ var deletedBookmarks = new Array();
+
+ for (var i in trackerBookmarks) {
+ var bookmark = trackerBookmarks[i]
+ trackerDict[bookmark.itemId] = bookmark;
+ }
+
+ for (var i = localBookmarks.length - 1; i >= 0; --i) {
+ var local = localBookmarks[i];
+ var id = local.itemId.toString();
+
+ if (!trackerDict[id]) {
+ newBookmarks.push (local);
+ continue;
+ }
+
+ var remote = trackerDict[id];
+
+ // We divide by 1000000 here since Tracker's resolution is second
+ if (Math.round(local.lastModified / 1000000) > (this.dateToPRTime(remote.lastModified) / 1000000)) {
+ updatedBookmarks.push (local);
+ }
+
+ trackerDict[id] = null;
+ }
+
+ for (var id in trackerDict) {
+ if (trackerDict[id]) {
+ deletedBookmarks.push (trackerDict[id]);
+ }
+ }
+
+ this.insertBookmarks (newBookmarks);
+ this.updateBookmarks (updatedBookmarks);
+ this.deleteBookmarks (deletedBookmarks);
+ },
+
+ getLocalBookmarks: function (folder) {
+ var bookmarks = this._bmService;
+ var history = this._histService;
+
+ const foldersToList = [bookmarks.toolbarFolder,
+ bookmarks.bookmarksMenuFolder,
+ bookmarks.unfiledBookmarksFolder];
+
+ var query = history.getNewQuery ();
+ query.setFolders (foldersToList, foldersToList.length);
+ var options = history.getNewQueryOptions ();
+ options.queryType = options.QUERY_TYPE_BOOKMARKS;
+ var result = history.executeQuery (query, options);
+ var root = result.root;
+ root.containerOpen = true;
+
+ var bookmarks = new Array ();
+
+ for (var i = 0; i < root.childCount; ++i) {
+ bookmarks.push (root.getChild (i));
+ }
+
+ return bookmarks;
+ },
+
+ // Returns a list of
+ // {
+ // urn: xxx
+ // itemId: xxx
+ // lastModified: xxx
+ // }
+ //
+ // or [ null ] in case of error
+ getTrackerBookmarks: function () {
+ var tracker = this._tracker;
+
+ var error = new tracker.Error.ptr;
+
+ var cursor = tracker.connection_query (this._connection,
+ "SELECT ?b nao:identifier(?b) nie:contentLastModified(?b) " +
+ "{ ?b a nfo:Bookmark ; " +
+ "nie:dataSource <" + this._dataSourceUrn + ">}",
+ null,
+ error.address ());
+
+ if (!error.isNull ()) {
+ this.handleError (error, "Can't get bookmarks from Tracker");
+ return [null];
+ }
+
+ var bookmarks = new Array ();
+
+ while (tracker.cursor_next (cursor, null, error.address())) {
+ if (!error.isNull ()) {
+ this.handleError (error, "Can't get bookmarks from Tracker")
+ return [null];
+ }
+
+ var bookmark = {
+ urn: tracker.cursor_get_string (cursor, 0, null).readString (),
+ itemId: tracker.cursor_get_string (cursor, 1, null).readString (),
+ lastModified: tracker.cursor_get_string (cursor, 2, null).readString ()
+ };
+
+ bookmarks.push (bookmark);
+ }
+
+ tracker.object_unref (cursor);
+
+ return bookmarks;
+ },
+
+ insertBookmarks: function (bookmarks) {
+ if (bookmarks.length == 0) {
+ return;
+ }
+
+ var tracker = this._tracker;
+
+ var globalQuery = "";
+
+ for (var i in bookmarks) {
+ var bookmark = bookmarks[i];
+
+ var iri = "<urn:trackerfox:bookmark:" + bookmark.itemId + ">";
+
+ var query = "INSERT { _:rdo a nfo:RemoteDataObject; " +
+ "nie:url \"" + bookmark.uri + "\" }" +
+ "WHERE {FILTER(!EXISTS {?r nie:url \"" + bookmark.uri + "\"})}" +
+ "\n" +
+ "INSERT { " + iri + " a nfo:Bookmark, nie:DataObject; " +
+ "nie:dataSource <" + this._dataSourceUrn + ">; " +
+ "nie:usageCounter " + bookmark.accessCount + "; " +
+ "nie:contentCreated \"" + this.PRTimeToDate (bookmark.dateAdded).toISOString () + "\"; " +
+ "nao:identifier \"" + bookmark.itemId + "\"; " +
+ "nie:contentLastModified \"" + this.PRTimeToDate (bookmark.lastModified).toISOString () + "\"; " +
+ "nfo:bookmarks ?rdo";
+ if (bookmark.time != 0) {
+ query += "; nie:contentAccessed \"" + this.PRTimeToDate (bookmark.time).toISOString () + "\"";
+ }
+
+ if (bookmark.title != "") {
+ query += "; nie:title \"" + tracker.escape_string (bookmark.title).readString () + "\"";
+ }
+
+ query += "} WHERE {?rdo nie:url \"" + bookmark.uri + "\"}\n\n";
+
+ globalQuery += query;
+ }
+
+ var error = new tracker.Error.ptr;
+ tracker.connection_update (this._connection,
+ globalQuery,
+ 0,
+ null,
+ error.address ());
+
+ if (!error.isNull ()) {
+ this.handleError (error, "Can't save bookmarks");
+ return;
+ }
+ },
+
+ updateBookmarks: function (bookmarks) {
+ if (bookmarks.length == 0) {
+ return;
+ }
+
+ // FIXME: Not optimal
+ this.deleteBookmarks (bookmarks);
+ this.insertBookmarks (bookmarks);
+ },
+
+ deleteBookmarks: function (bookmarks) {
+ if (bookmarks.length == 0) {
+ return;
+ }
+
+ var tracker = this._tracker;
+
+ var globalQuery = "";
+
+ for (var i in bookmarks) {
+ var bookmark = bookmarks[i];
+
+ var iri = "<urn:trackerfox:bookmark:" + bookmark.itemId + ">";
+
+ globalQuery += "DELETE {" + iri + " a rdfs:Resource}\n\n";
+ }
+
+ var error = new tracker.Error.ptr;
+ tracker.connection_update (this._connection,
+ globalQuery,
+ 0,
+ null,
+ error.address ());
+
+ if (!error.isNull ()) {
+ this.handleError (error, "Can't save bookmarks");
+ return;
+ }
+ },
+
+ handleError: function (error, message) {
+ var tracker = this._tracker;
+
+ dump (message + ": " + error.contents.message.readString () + "\n");
+ tracker.error_free(error);
+ },
+
+ dateToPRTime: function (date) {
+ return Date.parse (date) * 1000;
+ },
+
+ PRTimeToDate: function (date) {
+ return new Date (date / 1000);
+ }
+}
diff --git a/src/plugins/firefox/chrome/content/ff-overlay.xul b/src/plugins/firefox/chrome/content/ff-overlay.xul
new file mode 100644
index 000000000..d30759923
--- /dev/null
+++ b/src/plugins/firefox/chrome/content/ff-overlay.xul
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="chrome://trackerfox/skin/overlay.css" type="text/css"?>
+<!DOCTYPE overlay SYSTEM "chrome://trackerfox/locale/overlay.dtd">
+<overlay id="trackerfox-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script src="namespace.js"/>
+ <script src="bindings.js"/>
+ <script src="bookmarks.js"/>
+ <script src="plugin.js"/>
+
+ <stringbundleset id="stringbundleset">
+ <stringbundle id="trackerfox-strings" src="chrome://trackerfox/locale/overlay.properties"/>
+ </stringbundleset>
+
+
+
+
+</overlay>
diff --git a/src/plugins/firefox/chrome/content/namespace.js b/src/plugins/firefox/chrome/content/namespace.js
new file mode 100644
index 000000000..6e6dd1907
--- /dev/null
+++ b/src/plugins/firefox/chrome/content/namespace.js
@@ -0,0 +1,5 @@
+// Avoid polluting main namespace
+if (!org) var org = {};
+if (!org.bustany) org.bustany = {};
+if (!org.bustany.TrackerFox) org.bustany.TrackerFox = {};
+
diff --git a/src/plugins/firefox/chrome/content/plugin.js b/src/plugins/firefox/chrome/content/plugin.js
new file mode 100644
index 000000000..7e40e0064
--- /dev/null
+++ b/src/plugins/firefox/chrome/content/plugin.js
@@ -0,0 +1,64 @@
+if (!org.bustany.TrackerFox.Plugin || !org.bustany.TrackerFox.Plugin.__initialized)
+org.bustany.TrackerFox.Plugin={
+ // Init barrier
+ __initialized: true,
+
+ // Private members
+ _connection: null,
+ _tracker: org.bustany.TrackerFox.TrackerSparql,
+ _bookmarks: null,
+
+ // Methods
+ onLoad: function () {
+ // initialization code
+ this.initialized = true;
+ this.strings = document.getElementById ("trackerfox-strings");
+
+ dump ("Initializing TrackerFox...\n");
+
+ if (!this.initTracker ()) {
+ dump ("Couldn't initialize Tracker!\n");
+ return;
+ }
+
+ this._bookmarks = org.bustany.TrackerFox.Bookmarks;
+
+ if (!this._bookmarks.init (this._connection)) {
+ dump ("Couldn't initialize bookmarks service!\n");
+ return;
+ }
+
+ this._bookmarks.syncBookmarks();
+ },
+
+ onUnload: function () {
+ dump ("Closing TrackerFox...\n");
+
+ var tracker = org.bustany.TrackerFox.TrackerSparql;
+ this._bookmarks.shutdown ();
+ tracker.shutdown ();
+ },
+
+ initTracker: function () {
+ var tracker = this._tracker;
+
+ if (!tracker.init ()) {
+ dump ("Couldn't initialize tracker bindings, and I don't even know why :'(\n");
+ return false;
+ }
+
+ var error = new tracker.Error.ptr;
+ this._connection = tracker.connection_open (null, error.address());
+
+ if (!error.isNull ()) {
+ dump ("Could not initialize Tracker: " + error.contents.message.readString() + "\n");
+ tracker.error_free(error);
+ return false;
+ }
+
+ return true;
+ }
+};
+
+window.addEventListener ("load", function () { org.bustany.TrackerFox.Plugin.onLoad (); }, false);
+window.addEventListener ("unload", function () { org.bustany.TrackerFox.Plugin.onUnload (); }, false);
diff --git a/src/plugins/firefox/chrome/locale/Makefile.am b/src/plugins/firefox/chrome/locale/Makefile.am
new file mode 100644
index 000000000..f7390e286
--- /dev/null
+++ b/src/plugins/firefox/chrome/locale/Makefile.am
@@ -0,0 +1,3 @@
+include $(top_srcdir)/Makefile.decl
+
+SUBDIRS = en-US es-ES fr-FR
diff --git a/src/plugins/firefox/chrome/locale/en-US/Makefile.am b/src/plugins/firefox/chrome/locale/en-US/Makefile.am
new file mode 100644
index 000000000..d7ff79143
--- /dev/null
+++ b/src/plugins/firefox/chrome/locale/en-US/Makefile.am
@@ -0,0 +1,7 @@
+include $(top_srcdir)/Makefile.decl
+
+extensiondir = $(datadir)/xul-ext/trackerfox/chrome/locale/en-US/
+extension_DATA = \
+ about.dtd \
+ overlay.dtd \
+ overlay.properties
diff --git a/src/plugins/firefox/chrome/locale/en-US/about.dtd b/src/plugins/firefox/chrome/locale/en-US/about.dtd
new file mode 100644
index 000000000..ddd4023af
--- /dev/null
+++ b/src/plugins/firefox/chrome/locale/en-US/about.dtd
@@ -0,0 +1,4 @@
+<!ENTITY about "About">
+<!ENTITY version "Version:">
+<!ENTITY createdBy "Created By:">
+<!ENTITY homepage "Home Page:">
diff --git a/src/plugins/firefox/chrome/locale/en-US/overlay.dtd b/src/plugins/firefox/chrome/locale/en-US/overlay.dtd
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/plugins/firefox/chrome/locale/en-US/overlay.dtd
diff --git a/src/plugins/firefox/chrome/locale/en-US/overlay.properties b/src/plugins/firefox/chrome/locale/en-US/overlay.properties
new file mode 100644
index 000000000..1f8be1ee7
--- /dev/null
+++ b/src/plugins/firefox/chrome/locale/en-US/overlay.properties
@@ -0,0 +1 @@
+extensions.trackerfox@bustany.org.description=Search your bookmarks from Tracker
diff --git a/src/plugins/firefox/chrome/locale/es-ES/Makefile.am b/src/plugins/firefox/chrome/locale/es-ES/Makefile.am
new file mode 100644
index 000000000..ac243e99a
--- /dev/null
+++ b/src/plugins/firefox/chrome/locale/es-ES/Makefile.am
@@ -0,0 +1,7 @@
+include $(top_srcdir)/Makefile.decl
+
+extensiondir = $(datadir)/xul-ext/trackerfox/chrome/locale/es-ES/
+extension_DATA = \
+ about.dtd \
+ overlay.dtd \
+ overlay.properties
diff --git a/src/plugins/firefox/chrome/locale/es-ES/about.dtd b/src/plugins/firefox/chrome/locale/es-ES/about.dtd
new file mode 100644
index 000000000..3c813dcd4
--- /dev/null
+++ b/src/plugins/firefox/chrome/locale/es-ES/about.dtd
@@ -0,0 +1,4 @@
+<!ENTITY about "Acerca de">
+<!ENTITY version "Versión:">
+<!ENTITY createdBy "Creado por:">
+<!ENTITY homepage "Pagina internet:">
diff --git a/src/plugins/firefox/chrome/locale/es-ES/overlay.dtd b/src/plugins/firefox/chrome/locale/es-ES/overlay.dtd
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/plugins/firefox/chrome/locale/es-ES/overlay.dtd
diff --git a/src/plugins/firefox/chrome/locale/es-ES/overlay.properties b/src/plugins/firefox/chrome/locale/es-ES/overlay.properties
new file mode 100644
index 000000000..bbc33ac31
--- /dev/null
+++ b/src/plugins/firefox/chrome/locale/es-ES/overlay.properties
@@ -0,0 +1 @@
+extensions.trackerfox@bustany.org.description=Recherchez dans vos favoris depuis Tracker
diff --git a/src/plugins/firefox/chrome/locale/fr-FR/Makefile.am b/src/plugins/firefox/chrome/locale/fr-FR/Makefile.am
new file mode 100644
index 000000000..7d3f910db
--- /dev/null
+++ b/src/plugins/firefox/chrome/locale/fr-FR/Makefile.am
@@ -0,0 +1,7 @@
+include $(top_srcdir)/Makefile.decl
+
+extensiondir = $(datadir)/xul-ext/trackerfox/chrome/locale/fr-FR/
+extension_DATA = \
+ about.dtd \
+ overlay.dtd \
+ overlay.properties
diff --git a/src/plugins/firefox/chrome/locale/fr-FR/about.dtd b/src/plugins/firefox/chrome/locale/fr-FR/about.dtd
new file mode 100644
index 000000000..e558c6c42
--- /dev/null
+++ b/src/plugins/firefox/chrome/locale/fr-FR/about.dtd
@@ -0,0 +1,4 @@
+<!ENTITY about "À propos">
+<!ENTITY version "Version:">
+<!ENTITY createdBy "Créé par:">
+<!ENTITY homepage "Page internet:">
diff --git a/src/plugins/firefox/chrome/locale/fr-FR/overlay.dtd b/src/plugins/firefox/chrome/locale/fr-FR/overlay.dtd
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/plugins/firefox/chrome/locale/fr-FR/overlay.dtd
diff --git a/src/plugins/firefox/chrome/locale/fr-FR/overlay.properties b/src/plugins/firefox/chrome/locale/fr-FR/overlay.properties
new file mode 100644
index 000000000..bbc33ac31
--- /dev/null
+++ b/src/plugins/firefox/chrome/locale/fr-FR/overlay.properties
@@ -0,0 +1 @@
+extensions.trackerfox@bustany.org.description=Recherchez dans vos favoris depuis Tracker
diff --git a/src/plugins/firefox/chrome/skin/Makefile.am b/src/plugins/firefox/chrome/skin/Makefile.am
new file mode 100644
index 000000000..80abb1779
--- /dev/null
+++ b/src/plugins/firefox/chrome/skin/Makefile.am
@@ -0,0 +1,5 @@
+include $(top_srcdir)/Makefile.decl
+
+extensiondir = $(datadir)/xul-ext/trackerfox/chrome/skin
+extension_DATA = \
+ overlay.css
diff --git a/src/plugins/firefox/chrome/skin/overlay.css b/src/plugins/firefox/chrome/skin/overlay.css
new file mode 100644
index 000000000..399111f7d
--- /dev/null
+++ b/src/plugins/firefox/chrome/skin/overlay.css
@@ -0,0 +1,22 @@
+/* This is just an example. You shouldn't do this. */
+#trackerfox-hello
+{
+ color: red ! important;
+}
+#trackerfox-toolbar-button
+{
+ list-style-image: url("chrome://trackerfox/skin/toolbar-button.png");
+ -moz-image-region: rect(0px 24px 24px 0px);
+}
+#trackerfox-toolbar-button:hover
+{
+ -moz-image-region: rect(24px 24px 48px 0px);
+}
+[iconsize="small"] #trackerfox-toolbar-button
+{
+ -moz-image-region: rect( 0px 40px 16px 24px);
+}
+[iconsize="small"] #trackerfox-toolbar-button:hover
+{
+ -moz-image-region: rect(24px 40px 40px 24px);
+}
diff --git a/src/plugins/firefox/defaults/Makefile.am b/src/plugins/firefox/defaults/Makefile.am
new file mode 100644
index 000000000..4c3d6b4b3
--- /dev/null
+++ b/src/plugins/firefox/defaults/Makefile.am
@@ -0,0 +1,3 @@
+include $(top_srcdir)/Makefile.decl
+
+SUBDIRS = preferences
diff --git a/src/plugins/firefox/defaults/preferences/Makefile.am b/src/plugins/firefox/defaults/preferences/Makefile.am
new file mode 100644
index 000000000..0876a3a90
--- /dev/null
+++ b/src/plugins/firefox/defaults/preferences/Makefile.am
@@ -0,0 +1,5 @@
+include $(top_srcdir)/Makefile.decl
+
+extensiondir = $(datadir)/xul-ext/trackerfox/defaults/preferences
+extension_DATA = \
+ prefs.js
diff --git a/src/plugins/firefox/defaults/preferences/prefs.js b/src/plugins/firefox/defaults/preferences/prefs.js
new file mode 100644
index 000000000..86fedf3d6
--- /dev/null
+++ b/src/plugins/firefox/defaults/preferences/prefs.js
@@ -0,0 +1,2 @@
+// https://developer.mozilla.org/en/Localizing_extension_descriptions
+pref("extensions.trackerfox@bustany.org.description", "chrome://trackerfox/locale/overlay.properties");
diff --git a/src/plugins/firefox/install.rdf.in b/src/plugins/firefox/install.rdf.in
new file mode 100644
index 000000000..e4accc745
--- /dev/null
+++ b/src/plugins/firefox/install.rdf.in
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+ <Description about="urn:mozilla:install-manifest">
+ <em:id>trackerfox@bustany.org</em:id>
+ <em:type>2</em:type>
+ <em:name>TrackerFox</em:name>
+ <em:version>@VERSION@</em:version>
+ <em:creator>Adrien Bustany</em:creator>
+ <em:contributor></em:contributor>
+ <em:description>Makes your bookmarks searchable from Tracker</em:description>
+ <em:aboutURL>chrome://trackerfox/content/about.xul</em:aboutURL>
+ <em:targetApplication>
+ <Description>
+ <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- Firefox -->
+ <em:minVersion>4.0</em:minVersion>
+ <em:maxVersion>4.0.*</em:maxVersion>
+ </Description>
+ </em:targetApplication>
+ </Description>
+</RDF>
diff --git a/src/tracker-utils/tracker-search.c b/src/tracker-utils/tracker-search.c
index 8434f4d11..25b5e5875 100644
--- a/src/tracker-utils/tracker-search.c
+++ b/src/tracker-utils/tracker-search.c
@@ -60,6 +60,7 @@ static gboolean contacts;
static gboolean feeds;
static gboolean software;
static gboolean software_categories;
+static gboolean bookmarks;
static gboolean print_version;
static GOptionEntry entries[] = {
@@ -135,6 +136,10 @@ static GOptionEntry entries[] = {
N_("Search for feeds (--all has no effect on this)"),
NULL
},
+ { "bookmarks", 'b', 0, G_OPTION_ARG_NONE, &bookmarks,
+ N_("Search for bookmarks (--all has no effect on this)"),
+ NULL
+ },
{ "version", 'V', 0, G_OPTION_ARG_NONE, &print_version,
N_("Print version"),
NULL
@@ -845,6 +850,88 @@ get_music_albums (TrackerSparqlConnection *connection,
}
static gboolean
+get_bookmarks (TrackerSparqlConnection *connection,
+ GStrv search_terms,
+ gint search_offset,
+ gint search_limit,
+ gboolean use_or_operator)
+{
+ GError *error = NULL;
+ TrackerSparqlCursor *cursor;
+ gchar *fts;
+ gchar *query;
+
+ fts = get_fts_string (search_terms, use_or_operator);
+
+ if (fts) {
+ query = g_strdup_printf ("SELECT nie:title(?urn) nie:url(?bookmark) "
+ "WHERE {"
+ " ?urn a nfo:Bookmark ;"
+ " nfo:bookmarks ?bookmark ."
+ " ?urn fts:match \"%s\" . "
+ "} "
+ "ORDER BY ASC(nie:title(?urn)) "
+ "OFFSET %d "
+ "LIMIT %d",
+ fts,
+ search_offset,
+ search_limit);
+ } else {
+ query = g_strdup_printf ("SELECT nie:title(?urn) nie:url(?bookmark) "
+ "WHERE {"
+ " ?urn a nfo:Bookmark ;"
+ " nfo:bookmarks ?bookmark ."
+ "} "
+ "ORDER BY ASC(nie:title(?urn)) "
+ "OFFSET %d "
+ "LIMIT %d",
+ search_offset,
+ search_limit);
+ }
+
+ g_free (fts);
+
+ cursor = tracker_sparql_connection_query (connection, query, NULL, &error);
+ g_free (query);
+
+ if (error) {
+ g_printerr ("%s, %s\n",
+ _("Could not get search results"),
+ error->message);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ if (!cursor) {
+ g_print ("%s\n",
+ _("No bookmarks were found"));
+ } else {
+ gint count = 0;
+
+ g_print ("%s:\n", _("Bookmarks"));
+
+ while (tracker_sparql_cursor_next (cursor, NULL, NULL)) {
+ g_print (" %s (%s)\n",
+ tracker_sparql_cursor_get_string (cursor, 0, NULL),
+ tracker_sparql_cursor_get_string (cursor, 1, NULL));
+
+ count++;
+ }
+
+ g_print ("\n");
+
+ if (count >= search_limit) {
+ show_limit_warning ();
+ }
+
+ g_object_unref (cursor);
+ }
+
+ return TRUE;
+}
+
+static gboolean
get_feeds (TrackerSparqlConnection *connection,
GStrv search_terms,
gint search_offset,
@@ -1352,6 +1439,7 @@ main (int argc, char **argv)
}
if (!music_albums && !music_artists && !music_files &&
+ !bookmarks &&
!feeds &&
!software &&
!software_categories &&
@@ -1565,6 +1653,15 @@ main (int argc, char **argv)
return success ? EXIT_SUCCESS : EXIT_FAILURE;
}
+ if (bookmarks) {
+ gboolean success;
+
+ success = get_bookmarks (connection, terms, offset, limit, or_operator);
+ g_object_unref (connection);
+
+ return success ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+
if (terms) {
gboolean success;