diff options
author | Martyn Russell <martyn@lanedo.com> | 2011-07-29 14:18:30 +0100 |
---|---|---|
committer | Martyn Russell <martyn@lanedo.com> | 2011-07-29 14:18:30 +0100 |
commit | 37563f88e254ce8b804660e87b64986edaf61316 (patch) | |
tree | 53784e3f33aef491b620be76ed9f84536294b316 | |
parent | 76535bc895c6ce2a164f7957e2297ddcba7b5930 (diff) | |
parent | c71b741a17c6a0ca4872a5a8feb87954a6376bc9 (diff) | |
download | tracker-37563f88e254ce8b804660e87b64986edaf61316.tar.gz |
Merge branch 'firefox'
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; |