diff -Nru url-dispatcher-0.1+14.04.20140217.1/cmake/ConstantBuilderTemplates.cmake url-dispatcher-0.1+14.04.20140331.1/cmake/ConstantBuilderTemplates.cmake --- url-dispatcher-0.1+14.04.20140217.1/cmake/ConstantBuilderTemplates.cmake 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/cmake/ConstantBuilderTemplates.cmake 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,12 @@ + file(READ "${input}" input_contents) + string(REGEX REPLACE "\n" " " input_on_one_line "${input_contents}") + set(new_contents + "\#include \"${name}.h\"\nconst char * ${const_name} = \"${input_on_one_line}\";\n") + if (EXISTS "${file_target}") + file(READ "${file_target}" old_contents) + if(NOT new_contents EQUAL old_contents) + file(WRITE "${file_target}" "${new_contents}") + endif() + else() + file(WRITE "${file_target}" "${new_contents}") + endif() diff -Nru url-dispatcher-0.1+14.04.20140217.1/cmake/Coverage.cmake url-dispatcher-0.1+14.04.20140331.1/cmake/Coverage.cmake --- url-dispatcher-0.1+14.04.20140217.1/cmake/Coverage.cmake 2014-02-17 17:58:24.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/cmake/Coverage.cmake 2014-03-31 17:18:15.000000000 +0000 @@ -27,6 +27,9 @@ add_custom_target (coverage-html WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMAND "${LCOV_EXECUTABLE}" --directory ${CMAKE_BINARY_DIR} --capture --output-file coverage.info --no-checksum + COMMAND "${LCOV_EXECUTABLE}" --remove "${CMAKE_BINARY_DIR}/coverage.info" '${CMAKE_SOURCE_DIR}/tests/*' --output-file "${CMAKE_BINARY_DIR}/coverage.info" + COMMAND "${LCOV_EXECUTABLE}" --remove "${CMAKE_BINARY_DIR}/coverage.info" '/usr/*' --output-file "${CMAKE_BINARY_DIR}/coverage.info" + COMMAND "${LCOV_EXECUTABLE}" --remove "${CMAKE_BINARY_DIR}/coverage.info" '${CMAKE_BINARY_DIR}/*' --output-file "${CMAKE_BINARY_DIR}/coverage.info" COMMAND "${GENHTML_EXECUTABLE}" --prefix ${CMAKE_BINARY_DIR} --output-directory coveragereport --title "Code Coverage" --legend --show-details coverage.info ) endif() diff -Nru url-dispatcher-0.1+14.04.20140217.1/CMakeLists.txt url-dispatcher-0.1+14.04.20140331.1/CMakeLists.txt --- url-dispatcher-0.1+14.04.20140217.1/CMakeLists.txt 2014-02-17 17:58:24.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/CMakeLists.txt 2014-03-31 17:18:15.000000000 +0000 @@ -50,6 +50,9 @@ pkg_check_modules(DBUSTEST REQUIRED dbustest-1>=14.04.0) include_directories(${DBUSTEST_INCLUDE_DIRS}) +pkg_check_modules(SQLITE REQUIRED sqlite3) +include_directories(${SQLITE_INCLUDE_DIRS}) + if(${LOCAL_INSTALL}) set(DBUSSERVICEDIR "${CMAKE_INSTALL_DATADIR}/dbus-1/services/") else() diff -Nru url-dispatcher-0.1+14.04.20140217.1/data/CMakeLists.txt url-dispatcher-0.1+14.04.20140331.1/data/CMakeLists.txt --- url-dispatcher-0.1+14.04.20140217.1/data/CMakeLists.txt 2014-02-17 17:58:24.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/data/CMakeLists.txt 2014-03-31 17:18:15.000000000 +0000 @@ -10,6 +10,13 @@ ) ########################### +# Set stuff +########################### + +set(pkglibexecdir "${CMAKE_INSTALL_FULL_LIBEXECDIR}/url-dispatcher") +set(datadir "${CMAKE_INSTALL_FULL_DATADIR}") + +########################### # Upstart Job ########################### @@ -17,7 +24,6 @@ "${CMAKE_CURRENT_BINARY_DIR}/url-dispatcher.conf" ) -set(pkglibexecdir "${CMAKE_INSTALL_FULL_LIBEXECDIR}/url-dispatcher") configure_file("url-dispatcher.conf.in" "${DISPATCHER_UPSTART}" @ONLY @@ -29,3 +35,50 @@ DESTINATION "/usr/share/upstart/sessions" ) +########################### +# Upstart Update Job +########################### + +set(DISPATCHER_UPDATE_UPSTART +"${CMAKE_CURRENT_BINARY_DIR}/url-dispatcher-update.conf" +) + +configure_file("url-dispatcher-update.conf.in" + "${DISPATCHER_UPDATE_UPSTART}" + @ONLY +) + +install( +FILES +"${DISPATCHER_UPDATE_UPSTART}" +DESTINATION "/usr/share/upstart/sessions" +) + +########################### +# Upstart Refresh Job +########################### + +set(DISPATCHER_REFRESH_UPSTART +"${CMAKE_CURRENT_BINARY_DIR}/url-dispatcher-refresh.conf" +) + +configure_file("url-dispatcher-refresh.conf.in" + "${DISPATCHER_REFRESH_UPSTART}" + @ONLY +) + +install( +FILES +"${DISPATCHER_REFRESH_UPSTART}" +DESTINATION "/usr/share/upstart/sessions" +) + +########################### +# Click Hook +########################### + +configure_file("url-dispatcher.click-hook.in" + "${CMAKE_SOURCE_DIR}/debian/url-dispatcher.click-hook" + @ONLY +) + diff -Nru url-dispatcher-0.1+14.04.20140217.1/data/url-dispatcher.click-hook.in url-dispatcher-0.1+14.04.20140331.1/data/url-dispatcher.click-hook.in --- url-dispatcher-0.1+14.04.20140217.1/data/url-dispatcher.click-hook.in 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/data/url-dispatcher.click-hook.in 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,4 @@ +Pattern: ${home}/.cache/url-dispatcher/click-urls/${id}.url-dispatcher +Exec: @pkglibexecdir@/update-directory $HOME/.cache/url-dispatcher/click-urls/ +User-Level: yes +Hook-Name: urls diff -Nru url-dispatcher-0.1+14.04.20140217.1/data/url-dispatcher-refresh.conf.in url-dispatcher-0.1+14.04.20140331.1/data/url-dispatcher-refresh.conf.in --- url-dispatcher-0.1+14.04.20140217.1/data/url-dispatcher-refresh.conf.in 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/data/url-dispatcher-refresh.conf.in 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,18 @@ +description "Ensure the URL dispatcher database is up-to-date, likely at session init" + +start on started url-dispatcher + +emits url-dispatcher-update + +pre-start script +# If we're starting with url-dispatcher let's let the rest of the +# system have a chance to settle. + if [ "$UPSTART_EVENTS" = "started" ] ; then + sleep 60 + fi +end script + +script + initctl emit --no-wait url-dispatcher-update "MATCH=$HOME/.config/url-dispatcher/urls/" + initctl emit --no-wait url-dispatcher-update "MATCH=@datadir@/url-dispatcher/urls/" +end script diff -Nru url-dispatcher-0.1+14.04.20140217.1/data/url-dispatcher-update.conf.in url-dispatcher-0.1+14.04.20140331.1/data/url-dispatcher-update.conf.in --- url-dispatcher-0.1+14.04.20140217.1/data/url-dispatcher-update.conf.in 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/data/url-dispatcher-update.conf.in 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,7 @@ +description "URL Dispatcher Directory Watch" + +start on (file FILE=~/.config/url-dispatcher/urls/*.url-dispatcher) or (file FILE=@datadir@/url-dispatcher/urls/*.url-dispatcher) or url-dispatcher-update + +instance $MATCH + +exec @pkglibexecdir@/update-directory "$MATCH" diff -Nru url-dispatcher-0.1+14.04.20140217.1/debian/changelog url-dispatcher-0.1+14.04.20140331.1/debian/changelog --- url-dispatcher-0.1+14.04.20140217.1/debian/changelog 2014-04-01 13:36:14.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/debian/changelog 2014-04-01 13:36:14.000000000 +0000 @@ -1,3 +1,12 @@ +url-dispatcher (0.1+14.04.20140331.1-0ubuntu1) trusty; urgency=low + + [ Ted Gould ] + * Make it so that URLs can be installed with configuration files. + * Switch to using libupstart-app-launch for discovering AppIDs + * Migrate test suite to use libclick based libual + + -- Ubuntu daily release Mon, 31 Mar 2014 17:18:43 +0000 + url-dispatcher (0.1+14.04.20140217.1-0ubuntu1) trusty; urgency=low [ Ted Gould ] diff -Nru url-dispatcher-0.1+14.04.20140217.1/debian/control url-dispatcher-0.1+14.04.20140331.1/debian/control --- url-dispatcher-0.1+14.04.20140217.1/debian/control 2014-04-01 13:36:14.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/debian/control 2014-04-01 13:36:14.000000000 +0000 @@ -2,7 +2,8 @@ Section: gnome Priority: optional Maintainer: Ubuntu Developers -Build-Depends: cmake, +Build-Depends: click-dev, + cmake, dbus-test-runner, debhelper (>= 9), dh-autoreconf, @@ -13,9 +14,11 @@ libglib2.0-dev, libjson-glib-dev, libgtest-dev, + libsqlite3-dev, libupstart-app-launch2-dev (>= 0.3), python, python3-dbusmock, + sqlite3, Standards-Version: 3.9.4 Homepage: http://launchpad.net/url-dispatcher # If you aren't a member of ~indicator-applet-developers but need to upload @@ -29,7 +32,6 @@ Multi-Arch: same Pre-Depends: ${misc:Pre-Depends}, Depends: upstart-app-launch, - click (>= 0.4.9), ${misc:Depends}, ${shlibs:Depends}, Description: service to allow sending of URLs and get handlers started diff -Nru url-dispatcher-0.1+14.04.20140217.1/debian/rules url-dispatcher-0.1+14.04.20140331.1/debian/rules --- url-dispatcher-0.1+14.04.20140217.1/debian/rules 2014-04-01 13:36:14.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/debian/rules 2014-04-01 13:36:14.000000000 +0000 @@ -4,4 +4,4 @@ export G_MESSAGES_DEBUG=all %: - dh $@ --fail-missing + dh $@ --fail-missing --with click diff -Nru url-dispatcher-0.1+14.04.20140217.1/docs/URL Dispatcher Architecture.svg url-dispatcher-0.1+14.04.20140331.1/docs/URL Dispatcher Architecture.svg --- url-dispatcher-0.1+14.04.20140217.1/docs/URL Dispatcher Architecture.svg 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/docs/URL Dispatcher Architecture.svg 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,437 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + URL DispatcherUser Service + + + + DBus + + + + URL DispatcherUpdate Tool + + + + + SQLiteURLCache + + + + Upstart + + + Click + + + + + + Click PackageInstall orRemoval + Session InitRefresh + Configurationfile change + Readonly + Readwrite + + + Upstart AppLaunch + + + + diff -Nru url-dispatcher-0.1+14.04.20140217.1/service/CMakeLists.txt url-dispatcher-0.1+14.04.20140331.1/service/CMakeLists.txt --- url-dispatcher-0.1+14.04.20140217.1/service/CMakeLists.txt 2014-02-17 17:58:24.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/service/CMakeLists.txt 2014-03-31 17:18:15.000000000 +0000 @@ -1,8 +1,12 @@ +include(UseConstantBuilder) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + ########################### # Generated Lib ########################### + set(SERVICE_GENERATED_HEADERS service-iface.h ) @@ -37,10 +41,37 @@ dispatcher.c) target_link_libraries(dispatcher-lib + url-db-lib service-generated ${GLIB2_LIBRARIES} ${GOBJECT2_LIBRARIES} ${GIO2_LIBRARIES} + ${SQLITE_LIBRARIES} +) + +########################### +# URL DB Lib +########################### + +set(URL_DB_SOURCES + url-db.c + url-db.h + create-db-sql.h +) + +add_constant_template(URL_DB_SOURCES + create-db-sql + create_db_sql + "${CMAKE_CURRENT_SOURCE_DIR}/create-db.sql" +) + +add_library(url-db-lib STATIC + ${URL_DB_SOURCES} +) + +target_link_libraries(url-db-lib + ${GLIB2_LIBRARIES} + ${SQLITE_LIBRARIES} ) ########################### @@ -56,10 +87,19 @@ target_link_libraries(service-exec dispatcher-lib ${UPSTART_APP_LAUNCH_LIBRARIES}) ########################### +# Update Directory +########################### + +add_executable(update-directory update-directory.c recoverable-problem.c) +set_target_properties(update-directory PROPERTIES OUTPUT_NAME "update-directory") +target_link_libraries(update-directory ${GIO2_LIBRARIES} ${JSONGLIB_LIBRARIES} url-db-lib) + +########################### # Installation ########################### install( - TARGETS service-exec + TARGETS service-exec update-directory RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_LIBEXECDIR}/url-dispatcher" ) + diff -Nru url-dispatcher-0.1+14.04.20140217.1/service/create-db.sql url-dispatcher-0.1+14.04.20140331.1/service/create-db.sql --- url-dispatcher-0.1+14.04.20140217.1/service/create-db.sql 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/service/create-db.sql 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,3 @@ +create table if not exists configfiles (name text unique, timestamp bigint); +create table if not exists urls (sourcefile integer, protocol text, domainsuffix text); +create unique index if not exists urls_index on urls (sourcefile, protocol, domainsuffix); diff -Nru url-dispatcher-0.1+14.04.20140217.1/service/create-db-sql.h url-dispatcher-0.1+14.04.20140331.1/service/create-db-sql.h --- url-dispatcher-0.1+14.04.20140217.1/service/create-db-sql.h 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/service/create-db-sql.h 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,3 @@ + +extern const char * create_db_sql; + diff -Nru url-dispatcher-0.1+14.04.20140217.1/service/dispatcher.c url-dispatcher-0.1+14.04.20140331.1/service/dispatcher.c --- url-dispatcher-0.1+14.04.20140217.1/service/dispatcher.c 2014-02-17 17:58:24.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/service/dispatcher.c 2014-03-31 17:18:25.000000000 +0000 @@ -13,6 +13,8 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * + * Author: Ted Gould + * */ #include @@ -21,15 +23,17 @@ #include "dispatcher.h" #include "service-iface.h" #include "recoverable-problem.h" +#include "url-db.h" /* Globals */ static GCancellable * cancellable = NULL; static ServiceIfaceComCanonicalURLDispatcher * skel = NULL; static GRegex * applicationre = NULL; static GRegex * appidre = NULL; -static gchar * click_exec = NULL; - -#define CURRENT "current-user-version" +static GRegex * genericre = NULL; +static GRegex * musicfilere = NULL; /* FIXME */ +static GRegex * videofilere = NULL; /* FIXME */ +static sqlite3 * urldb = NULL; /* Errors */ enum { @@ -134,327 +138,6 @@ return; } -typedef enum _app_name_t app_name_t; -enum _app_name_t { - APP_NAME_PRECISE, - APP_NAME_ONLY, - APP_NAME_FIRST, - APP_NAME_LAST -}; - -typedef enum _version_search_t version_search_t; -enum _version_search_t { - VERSION_SEARCH_PRECISE, - VERSION_SEARCH_CURRENT -}; - -/* Check to see if the app name is one of our keywords */ -static app_name_t -app_name_type (const gchar * appname) -{ - if (g_strcmp0(appname, "only-listed-app") == 0) { - return APP_NAME_ONLY; - } - - if (g_strcmp0(appname, "first-listed-app") == 0) { - return APP_NAME_FIRST; - } - - if (g_strcmp0(appname, "last-listed-app") == 0) { - return APP_NAME_LAST; - } - - return APP_NAME_PRECISE; -} - -/* Check to see if the version is special */ -static version_search_t -version_search_type (const gchar * version) -{ - if (g_strcmp0(version, CURRENT) == 0) { - return VERSION_SEARCH_CURRENT; - } - - return VERSION_SEARCH_PRECISE; -} - -/* Try and get a manifest file and do a couple sanity checks on it */ -JsonParser * -get_manifest_file (const gchar * pkg) -{ - /* Get the directory from click */ - GError * error = NULL; - gchar * cmdline = g_strdup_printf("%s info \"%s\"", - click_exec == NULL ? "click" : click_exec, - pkg); - - gchar * output = NULL; - g_spawn_command_line_sync(cmdline, &output, NULL, NULL, &error); - g_free(cmdline); - - if (error != NULL) { - g_warning("Unable to get manifest for '%s' package: %s", pkg, error->message); - g_error_free(error); - g_free(output); - return NULL; - } - - /* Let's look at that manifest file */ - JsonParser * parser = json_parser_new(); - json_parser_load_from_data(parser, output, -1, &error); - g_free(output); - - if (error != NULL) { - g_warning("Unable to load manifest for '%s': %s", pkg, error->message); - g_error_free(error); - g_object_unref(parser); - return NULL; - } - - JsonNode * root = json_parser_get_root(parser); - if (json_node_get_node_type(root) != JSON_NODE_OBJECT) { - g_warning("Manifest file for package '%s' does not have an object as its root node", pkg); - g_object_unref(parser); - return NULL; - } - - JsonObject * rootobj = json_node_get_object(root); - - if (!json_object_has_member(rootobj, "version")) { - g_warning("Manifest file for package '%s' does not have a version", pkg); - g_object_unref(parser); - return NULL; - } - - if (!json_object_has_member(rootobj, "hooks")) { - g_warning("Manifest file for package '%s' does not have a hooks section", pkg); - g_object_unref(parser); - return NULL; - } - - return parser; -} - -/* Figure out the app name using the manifest */ -const gchar * -manifest_app_name (JsonParser * manifest, app_name_t app_type, const gchar * original_app) -{ - if (app_type == APP_NAME_PRECISE) { - return original_app; - } - - JsonNode * root_node = json_parser_get_root(manifest); - JsonObject * root_obj = json_node_get_object(root_node); - JsonObject * hooks = json_object_get_object_member(root_obj, "hooks"); - - if (hooks == NULL) { - return NULL; - } - - GList * apps = json_object_get_members(hooks); - if (apps == NULL) { - return NULL; - } - - const gchar * retapp = NULL; - - switch (app_type) { - case APP_NAME_ONLY: - if (g_list_length(apps) == 1) { - retapp = (const gchar *)apps->data; - } - break; - case APP_NAME_FIRST: - retapp = (const gchar *)apps->data; - break; - case APP_NAME_LAST: - retapp = (const gchar *)(g_list_last(apps)->data); - break; - default: - break; - } - - g_list_free(apps); - - return retapp; -} - -/* Figure out the app name using the manifest */ -const gchar * -manifest_version (JsonParser * manifest, version_search_t version_type, const gchar * original_ver) -{ - if (version_type == VERSION_SEARCH_PRECISE) { - return original_ver; - } - - if (version_type == VERSION_SEARCH_CURRENT) { - JsonNode * node = json_parser_get_root(manifest); - JsonObject * obj = json_node_get_object(node); - return json_object_get_string_member(obj, "version"); - } - - return NULL; -} - -/* Works with a fuzzy set of parameters to determine the right app to - call and then calls pass_url_to_app() with the full AppID */ -static gboolean -app_id_discover (const gchar * pkg, const gchar * app, const gchar * version, const gchar * url) -{ - version_search_t version_search = version_search_type(version); - app_name_t app_name = app_name_type(app); - - if (version_search == VERSION_SEARCH_PRECISE && app_name == APP_NAME_PRECISE) { - /* This the non-search case, just put it together and pass along */ - gchar * appid = g_strdup_printf("%s_%s_%s", pkg, app, version); - - pass_url_to_app(appid, url); - - g_free(appid); - return TRUE; - } - - /* Get the manifest and turn that into our needed values */ - JsonParser * parser = get_manifest_file(pkg); - if (parser == NULL) { - return FALSE; - } - - const gchar * final_app = manifest_app_name(parser, app_name, app); - const gchar * final_ver = manifest_version(parser, version_search, version); - - if (final_app == NULL || final_ver == NULL) { - g_object_unref(parser); - return FALSE; - } - - gchar * appid = g_strdup_printf("%s_%s_%s", pkg, final_app, final_ver); - g_object_unref(parser); - - pass_url_to_app(appid, url); - - g_free(appid); - return TRUE; -} - -/* URL handlers need to be identified */ -typedef struct _url_type_t url_type_t; -struct _url_type_t { - gchar * regex_patern; - GRegex * regex_object; - gchar * app_id; - gchar * package; - gchar * application; - gchar * version; -}; - -#define USERNAME_REGEX "[a-zA-Z0-9_\\-]*" - -/* TODO: Make these come from registrations, but this works for now */ -url_type_t url_types[] = { -#ifdef APP_ID_TEST_URI - { - .regex_patern = "^appidtest:///", - .regex_object = NULL, - .package = "com.test.good", - .application = "first-listed-app", - .version = CURRENT, - .app_id = NULL - }, -#endif - /* Alarms */ - { - .regex_patern = "^alarm:///", - .regex_object = NULL, - .app_id = NULL, - .package = "com.ubuntu.clock", - .application = "clock", - .version = CURRENT - }, - /* Address Book */ - { - .regex_patern = "^addressbook:///", - .regex_object = NULL, - .package = NULL, .application = NULL, .version = NULL, - .app_id = "address-book-app" - }, - /* Calendar */ - { - .regex_patern = "^calendar:///", - .regex_object = NULL, - .app_id = NULL, - .package = "com.ubuntu.calendar", - .application = "calendar", - .version = CURRENT - }, - /* Messages */ - { - .regex_patern = "^message:///", - .regex_object = NULL, - .package = NULL, .application = NULL, .version = NULL, - .app_id = "messaging-app" - }, - /* Music */ - { - .regex_patern = "^music:///", - .regex_object = NULL, - .app_id = NULL, - .package = "com.ubuntu.music", - .application = "music", - .version = CURRENT - }, - { - /* TODO: This is temporary for 13.10, we expect to be smarter in the future */ - .regex_patern = "^file:///home/" USERNAME_REGEX "/Music/", - .regex_object = NULL, - .app_id = NULL, - .package = "com.ubuntu.music", - .application = "music", - .version = CURRENT - }, - /* Phone Numbers */ - { - .regex_patern = "^tel:///[\\d\\.+x,\\(\\)-]*$", - .regex_object = NULL, - .package = NULL, .application = NULL, .version = NULL, - .app_id = "dialer-app" - }, - /* Settings */ - { - .regex_patern = "^settings:///system/", - .regex_object = NULL, - .package = NULL, .application = NULL, .version = NULL, - .app_id = "ubuntu-system-settings" - }, - /* Video */ - { - .regex_patern = "^video:///", - .regex_object = NULL, - .package = NULL, .application = NULL, .version = NULL, - .app_id = "mediaplayer-app" - }, - { - /* TODO: This is temporary for 13.10, we expect to be smarter in the future */ - .regex_patern = "^file:///home/" USERNAME_REGEX "/Videos/", - .regex_object = NULL, - .package = NULL, .application = NULL, .version = NULL, - .app_id = "mediaplayer-app" - }, - /* Web Stuff */ - { - .regex_patern = "^http://", - .regex_object = NULL, - .package = NULL, .application = NULL, .version = NULL, - .app_id = "webbrowser-app" - }, - { - .regex_patern = "^https://", - .regex_object = NULL, - .package = NULL, .application = NULL, .version = NULL, - .app_id = "webbrowser-app" - } -}; - /* Get a URL off of the bus */ static gboolean dispatch_url_cb (GObject * skel, GDBusMethodInvocation * invocation, const gchar * url, gpointer user_data) @@ -484,10 +167,16 @@ gchar * package = g_match_info_fetch(appidmatch, 1); gchar * app = g_match_info_fetch(appidmatch, 2); gchar * version = g_match_info_fetch(appidmatch, 3); - gboolean retval = TRUE; + gchar * appid = NULL; + gboolean retval = FALSE; - retval = app_id_discover(package, app, version, NULL); + appid = upstart_app_launch_triplet_to_app_id(package, app, version); + if (appid != NULL) { + pass_url_to_app(appid, NULL); + retval = TRUE; + } + g_free(appid); g_free(package); g_free(app); g_free(version); @@ -509,22 +198,58 @@ } g_match_info_free(appmatch); - int i; - for (i = 0; i < G_N_ELEMENTS(url_types); i++) { - if (url_types[i].regex_object == NULL) { - url_types[i].regex_object = g_regex_new(url_types[i].regex_patern, 0, 0, NULL); + /* start FIXME: These are needed work arounds until everything migrates away + from them. Ewww */ + GMatchInfo * musicmatch = NULL; + if (g_regex_match(musicfilere, url, 0, &musicmatch)) { + gboolean retval = FALSE; + gchar * appid = NULL; + + appid = upstart_app_launch_triplet_to_app_id("com.ubuntu.music", "music", NULL); + if (appid != NULL) { + pass_url_to_app(appid, url); + retval = TRUE; } - if (g_regex_match(url_types[i].regex_object, url, 0, NULL)) { - if (url_types[i].app_id != NULL) { - pass_url_to_app(url_types[i].app_id, url); - } else { - app_id_discover(url_types[i].package, url_types[i].application, url_types[i].version, url); - } + g_free(appid); + g_match_info_free(musicmatch); + return retval; + } + g_match_info_free(musicmatch); + + GMatchInfo * videomatch = NULL; + if (g_regex_match(videofilere, url, 0, &videomatch)) { + pass_url_to_app("mediaplayer-app", url); + + g_match_info_free(videomatch); + return TRUE; + } + g_match_info_free(videomatch); + /* end FIXME: Making the ugly stop */ - return TRUE; + /* Check the URL db */ + GMatchInfo * genericmatch = NULL; + if (g_regex_match(genericre, url, 0, &genericmatch)) { + gboolean found = FALSE; + gchar * protocol = g_match_info_fetch(genericmatch, 1); + gchar * domain = g_match_info_fetch(genericmatch, 2); + + gchar * appid = url_db_find_url(urldb, protocol, domain); + + if (appid != NULL) { + found = TRUE; + pass_url_to_app(appid, url); + g_free(appid); } + + g_free(protocol); + g_free(domain); + + g_match_info_free(genericmatch); + + return found; } + g_match_info_free(genericmatch); return FALSE; } @@ -579,18 +304,23 @@ return; } +#define USERNAME_REGEX "[a-zA-Z0-9_\\-]*" + /* Initialize all the globals */ gboolean dispatcher_init (GMainLoop * mainloop) { cancellable = g_cancellable_new(); + urldb = url_db_create_database(); + applicationre = g_regex_new("^application:///([a-zA-Z0-9_\\.-]*)\\.desktop$", 0, 0, NULL); appidre = g_regex_new("^appid://([a-z0-9\\.-]*)/([a-zA-Z0-9-]*)/([a-zA-Z0-9\\.-]*)$", 0, 0, NULL); + genericre = g_regex_new("^(.*)://([a-z0-9\\.-]*)?/?(.*)?$", 0, 0, NULL); - if (g_getenv("URL_DISPATCHER_CLICK_EXEC") != NULL) { - click_exec = g_strdup(g_getenv("URL_DISPATCHER_CLICK_EXEC")); - } + /* FIXME: Legacy */ + musicfilere = g_regex_new("^file:///home/" USERNAME_REGEX "/Music/", 0, 0, NULL); + videofilere = g_regex_new("^file:///home/" USERNAME_REGEX "/Videos/", 0, 0, NULL); g_bus_get(G_BUS_TYPE_SESSION, cancellable, bus_got, mainloop); @@ -610,12 +340,10 @@ g_object_unref(skel); g_regex_unref(applicationre); g_regex_unref(appidre); - g_free(click_exec); - - int i; - for (i = 0; i < G_N_ELEMENTS(url_types); i++) { - g_clear_pointer(&url_types[i].regex_object, g_regex_unref); - } + g_regex_unref(genericre); + g_regex_unref(musicfilere); /* FIXME */ + g_regex_unref(videofilere); /* FIXME */ + sqlite3_close(urldb); return TRUE; } diff -Nru url-dispatcher-0.1+14.04.20140217.1/service/dispatcher.h url-dispatcher-0.1+14.04.20140331.1/service/dispatcher.h --- url-dispatcher-0.1+14.04.20140217.1/service/dispatcher.h 2014-02-17 17:58:24.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/service/dispatcher.h 2014-03-31 17:18:15.000000000 +0000 @@ -13,6 +13,8 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * + * Author: Ted Gould + * */ #include diff -Nru url-dispatcher-0.1+14.04.20140217.1/service/service.c url-dispatcher-0.1+14.04.20140331.1/service/service.c --- url-dispatcher-0.1+14.04.20140217.1/service/service.c 2014-02-17 17:58:36.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/service/service.c 2014-03-31 17:18:15.000000000 +0000 @@ -13,6 +13,8 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * + * Author: Ted Gould + * */ #include diff -Nru url-dispatcher-0.1+14.04.20140217.1/service/update-directory.c url-dispatcher-0.1+14.04.20140331.1/service/update-directory.c --- url-dispatcher-0.1+14.04.20140217.1/service/update-directory.c 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/service/update-directory.c 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,217 @@ +/** + * Copyright © 2014 Canonical, Ltd. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3, as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Author: Ted Gould + * + */ + +#include +#include +#include "url-db.h" +#include "recoverable-problem.h" + +typedef struct { + const gchar * filename; + sqlite3 * db; +} urldata_t; + +static void +each_url (JsonArray * array, guint index, JsonNode * value, gpointer user_data) +{ + urldata_t * urldata = (urldata_t *)user_data; + + if (!JSON_NODE_HOLDS_OBJECT(value)) { + g_warning("File %s: Array entry %d not an object", urldata->filename, index); + return; + } + + JsonObject * obj = json_node_get_object(value); + + const gchar * protocol = NULL; + const gchar * suffix = NULL; + + if (json_object_has_member(obj, "protocol")) { + protocol = json_object_get_string_member(obj, "protocol"); + } + + if (json_object_has_member(obj, "domain-suffix")) { + suffix = json_object_get_string_member(obj, "domain-suffix"); + } + + if (protocol == NULL) { + g_warning("File %s: Array entry %d doesn't contain a 'protocol'", urldata->filename, index); + return; + } + + url_db_insert_url(urldata->db, urldata->filename, protocol, suffix); +} + +static void +insert_urls_from_file (const gchar * filename, sqlite3 * db) +{ + GError * error = NULL; + JsonParser * parser = json_parser_new(); + json_parser_load_from_file(parser, filename, &error); + + if (error != NULL) { + g_warning("Unable to parse JSON in '%s': %s", filename, error->message); + g_object_unref(parser); + g_error_free(error); + return; + } + + JsonNode * rootnode = json_parser_get_root(parser); + if (!JSON_NODE_HOLDS_ARRAY(rootnode)) { + g_warning("File '%s' does not have an array as its root node", filename); + g_object_unref(parser); + return; + } + + JsonArray * rootarray = json_node_get_array(rootnode); + + urldata_t urldata = { + .filename = filename, + .db = db + }; + + json_array_foreach_element(rootarray, each_url, &urldata); + + g_object_unref(parser); +} + +static gboolean +check_file_outofdate (const gchar * filename, sqlite3 * db) +{ + g_debug("Processing file: %s", filename); + + GTimeVal dbtime = {0}; + GTimeVal filetime = {0}; + + GFile * file = g_file_new_for_path(filename); + g_return_if_fail(file != NULL); + + GFileInfo * info = g_file_query_info(file, G_FILE_ATTRIBUTE_TIME_MODIFIED, G_FILE_QUERY_INFO_NONE, NULL, NULL); + g_file_info_get_modification_time(info, &filetime); + + g_object_unref(info); + g_object_unref(file); + + if (url_db_get_file_motification_time(db, filename, &dbtime)) { + if (filetime.tv_sec <= dbtime.tv_sec) { + g_debug("\tup-to-date: %s", filename); + return FALSE; + } + } + + url_db_set_file_motification_time(db, filename, &filetime); + + return TRUE; +} + +/* Remove a file from the database */ +static void +remove_file (gpointer key, gpointer value, gpointer user_data) +{ + const gchar * filename = (const gchar *)key; + g_debug(" Removing file: %s", filename); + if (!url_db_remove_file((sqlite3*)user_data, filename)) { + g_warning("Unable to remove file: %s", filename); + } +} + +/* In the beginning, there was main, and that was good */ +int +main (int argc, char * argv[]) +{ + if (argc != 2) { + g_printerr("Usage: %s \n", argv[0]); + return 1; + } + + sqlite3 * db = url_db_create_database(); + g_return_val_if_fail(db != NULL, -1); + + /* Check out what we got and recover */ + gchar * dirname = g_strdup(argv[1]); + if (!g_file_test(dirname, G_FILE_TEST_IS_DIR) && !g_str_has_suffix(dirname, "/")) { + gchar * upone = g_path_get_dirname(dirname); + /* Upstart will give us filenames a bit, let's handle them */ + if (g_file_test(upone, G_FILE_TEST_IS_DIR)) { + g_free(dirname); + dirname = upone; + } else { + /* If the dirname function doesn't help, stick with what + we were given, the whole thing coulda been deleted */ + g_free(upone); + } + } + + /* Get the current files in the directory in the DB so we + know if any got dropped */ + GHashTable * startingdb = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + GList * files = url_db_files_for_dir(db, dirname); + GList * cur; + for (cur = files; cur != NULL; cur = g_list_next(cur)) { + g_hash_table_add(startingdb, cur->data); + } + g_list_free(files); + + + /* Open the directory on the file system and start going + through it */ + if (g_file_test(dirname, G_FILE_TEST_IS_DIR)) { + GDir * dir = g_dir_open(dirname, 0, NULL); + g_return_val_if_fail(dir != NULL, -1); + + const gchar * name = NULL; + while ((name = g_dir_read_name(dir)) != NULL) { + if (g_str_has_suffix(name, ".url-dispatcher")) { + gchar * fullname = g_build_filename(dirname, name, NULL); + + if (check_file_outofdate(fullname, db)) { + insert_urls_from_file(fullname, db); + } + + g_hash_table_remove(startingdb, fullname); + g_free(fullname); + } + } + + g_dir_close(dir); + } + + /* Remove deleted files */ + g_hash_table_foreach(startingdb, remove_file, db); + g_hash_table_destroy(startingdb); + + int close_status = sqlite3_close(db); + if (close_status != SQLITE_OK) { + gchar * additional[3] = { + "SQLiteStatus", + NULL, + NULL + }; + gchar * status = g_strdup_printf("%d", close_status); + additional[1] = status; + + report_recoverable_problem("url-dispatcher-sqlite-close-error", 0, TRUE, additional); + g_free(status); + } + + g_debug("Directory '%s' is up-to-date", dirname); + g_free(dirname); + + return 0; +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/service/url-db.c url-dispatcher-0.1+14.04.20140331.1/service/url-db.c --- url-dispatcher-0.1+14.04.20140217.1/service/url-db.c 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/service/url-db.c 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,362 @@ +/** + * Copyright © 2014 Canonical, Ltd. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3, as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Author: Ted Gould + * + */ + +#include +#include "url-db.h" +#include "create-db-sql.h" + +#define DB_SCHEMA_VERSION "1" + +sqlite3 * +url_db_create_database (void) +{ + const gchar * cachedir = g_getenv("URL_DISPATCHER_CACHE_DIR"); /* Mostly for testing */ + + if (G_LIKELY(cachedir == NULL)) { + cachedir = g_get_user_cache_dir(); + } + + gchar * urldispatchercachedir = g_build_filename(cachedir, "url-dispatcher", NULL); + if (!g_file_test(urldispatchercachedir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { + gint cachedirokay = g_mkdir_with_parents(urldispatchercachedir, 1 << 6 | 1 << 7 | 1 << 8); // 700 + + if (cachedirokay != 0) { + g_warning("Unable to make or find cache directory '%s'", urldispatchercachedir); + g_free(urldispatchercachedir); + return NULL; + } + } + + gchar * dbfilename = g_build_filename(urldispatchercachedir, "urls-" DB_SCHEMA_VERSION ".db", NULL); + g_free(urldispatchercachedir); + + gboolean dbexists = g_file_test(dbfilename, G_FILE_TEST_EXISTS); + int open_status = SQLITE_ERROR; + sqlite3 * db = NULL; + + open_status = sqlite3_open(dbfilename, &db); + if (open_status != SQLITE_OK) { + g_warning("Unable to open URL database"); + g_free(dbfilename); + if (db != NULL) { + sqlite3_close(db); + } + return NULL; + } + + g_free(dbfilename); + + if (!dbexists) { /* First usage */ + int exec_status = SQLITE_ERROR; + char * failstring = NULL; + + exec_status = sqlite3_exec(db, create_db_sql, NULL, NULL, &failstring); + + if (exec_status != SQLITE_OK) { + g_warning("Unable to create tables: %s", failstring); + sqlite3_free(failstring); + sqlite3_close(db); + return NULL; + } + + } + + return db; +} + +gboolean +url_db_get_file_motification_time (sqlite3 * db, const gchar * filename, GTimeVal * timeval) +{ + g_return_val_if_fail(db != NULL, FALSE); + g_return_val_if_fail(filename != NULL, FALSE); + g_return_val_if_fail(timeval != NULL, FALSE); + + timeval->tv_sec = 0; + timeval->tv_usec = 0; + + sqlite3_stmt * stmt; + if (sqlite3_prepare_v2(db, + "select timestamp from configfiles where name = ?1", + -1, /* length */ + &stmt, + NULL) != SQLITE_OK) { + g_warning("Unable to parse SQL to get file times"); + return FALSE; + } + + sqlite3_bind_text(stmt, 1, filename, -1, SQLITE_TRANSIENT); + + gboolean valueset = FALSE; + int exec_status = SQLITE_ROW; + while ((exec_status = sqlite3_step(stmt)) == SQLITE_ROW) { + if (timeval->tv_sec != 0) { + g_warning("Seemingly two timestamps for the same file"); + } + + timeval->tv_sec = sqlite3_column_int(stmt, 0); + valueset = TRUE; + } + + sqlite3_finalize(stmt); + + if (exec_status != SQLITE_DONE) { + g_warning("Unable to execute insert"); + return FALSE; + } + + return valueset; +} + +gboolean +url_db_set_file_motification_time (sqlite3 * db, const gchar * filename, GTimeVal * timeval) +{ + g_return_val_if_fail(db != NULL, FALSE); + g_return_val_if_fail(filename != NULL, FALSE); + g_return_val_if_fail(timeval != NULL, FALSE); + + sqlite3_stmt * stmt; + if (sqlite3_prepare_v2(db, + "insert or replace into configfiles values (?1, ?2)", + -1, /* length */ + &stmt, + NULL) != SQLITE_OK) { + g_warning("Unable to parse SQL to set file times"); + return FALSE; + } + + sqlite3_bind_text(stmt, 1, filename, -1, SQLITE_TRANSIENT); + sqlite3_bind_int(stmt, 2, timeval->tv_sec); + + int exec_status = SQLITE_ROW; + while ((exec_status = sqlite3_step(stmt)) == SQLITE_ROW) {} + + sqlite3_finalize(stmt); + + if (exec_status != SQLITE_DONE) { + g_warning("Unable to execute insert"); + return FALSE; + } + + return TRUE; +} + +gboolean +url_db_insert_url (sqlite3 * db, const gchar * filename, const gchar * protocol, const gchar * domainsuffix) +{ + g_return_val_if_fail(db != NULL, FALSE); + g_return_val_if_fail(filename != NULL, FALSE); + g_return_val_if_fail(protocol != NULL, FALSE); + + if (domainsuffix == NULL) { + domainsuffix = ""; + } + + sqlite3_stmt * stmt; + if (sqlite3_prepare_v2(db, + "insert or replace into urls select rowid, ?2, ?3 from configfiles where name = ?1", + -1, /* length */ + &stmt, + NULL) != SQLITE_OK) { + g_warning("Unable to parse SQL to insert"); + return FALSE; + } + + sqlite3_bind_text(stmt, 1, filename, -1, SQLITE_TRANSIENT); + sqlite3_bind_text(stmt, 2, protocol, -1, SQLITE_TRANSIENT); + sqlite3_bind_text(stmt, 3, domainsuffix, -1, SQLITE_TRANSIENT); + + int exec_status = SQLITE_ROW; + while ((exec_status = sqlite3_step(stmt)) == SQLITE_ROW) {} + + sqlite3_finalize(stmt); + + if (exec_status != SQLITE_DONE) { + g_warning("Unable to execute insert"); + return FALSE; + } + + return TRUE; +} + +gchar * +url_db_find_url (sqlite3 * db, const gchar * protocol, const gchar * domainsuffix) +{ + g_return_val_if_fail(db != NULL, NULL); + g_return_val_if_fail(protocol != NULL, NULL); + + if (domainsuffix == NULL) { + domainsuffix = ""; + } + + sqlite3_stmt * stmt; + if (sqlite3_prepare_v2(db, + "select configfiles.name from configfiles, urls where urls.sourcefile = configfiles.rowid and urls.protocol = ?1 and ?2 like '%' || urls.domainsuffix order by length(urls.domainsuffix) desc limit 1", + -1, /* length */ + &stmt, + NULL) != SQLITE_OK) { + g_warning("Unable to parse SQL to find url"); + return NULL; + } + + sqlite3_bind_text(stmt, 1, protocol, -1, SQLITE_TRANSIENT); + sqlite3_bind_text(stmt, 2, domainsuffix, -1, SQLITE_TRANSIENT); + + gchar * filename = NULL; + int exec_status = SQLITE_ROW; + while ((exec_status = sqlite3_step(stmt)) == SQLITE_ROW && filename == NULL) { + filename = g_strdup((const gchar *)sqlite3_column_text(stmt, 0)); + } + + gchar * output = NULL; + if (filename != NULL) { + g_debug("Found file: '%s'", filename); + gchar * basename = g_path_get_basename(filename); + gchar * suffix = g_strrstr(basename, ".url-dispatcher"); + if (suffix != NULL) /* This should never not happen, but it's too scary not to throw this 'if' in */ + suffix[0] = '\0'; + output = g_strdup(basename); + g_free(basename); + g_free(filename); + } + + sqlite3_finalize(stmt); + + if (exec_status != SQLITE_DONE) { + g_warning("Unable to execute insert"); + g_free(output); + return NULL; + } + + return output; +} + +GList * +url_db_files_for_dir (sqlite3 * db, const gchar * dir) +{ + g_return_val_if_fail(db != NULL, NULL); + + if (dir == NULL) { + dir = ""; + } + + gchar * dir_search = g_strdup_printf("%s%%", dir); + + sqlite3_stmt * stmt; + if (sqlite3_prepare_v2(db, + "select name from configfiles where name like ?1", + -1, /* length */ + &stmt, + NULL) != SQLITE_OK) { + g_warning("Unable to parse SQL to find files"); + return NULL; + } + + sqlite3_bind_text(stmt, 1, dir_search, -1, SQLITE_TRANSIENT); + + GList * filelist = NULL; + int exec_status = SQLITE_ROW; + while ((exec_status = sqlite3_step(stmt)) == SQLITE_ROW) { + gchar * name = g_strdup((const gchar *)sqlite3_column_text(stmt, 0)); + filelist = g_list_prepend(filelist, name); + } + + sqlite3_finalize(stmt); + g_free(dir_search); + + if (exec_status != SQLITE_DONE) { + g_warning("Unable to execute insert"); + g_list_free_full(filelist, g_free); + return NULL; + } + + return filelist; +} + +/* Remove a file from the database along with all URLs that were + built because of it. */ +gboolean +url_db_remove_file (sqlite3 * db, const gchar * path) +{ + g_return_val_if_fail(db != NULL, FALSE); + g_return_val_if_fail(path != NULL, FALSE); + + /* Start a transaction so the database doesn't end up + in an inconsistent state */ + if (sqlite3_exec(db, "begin", NULL, NULL, NULL) != SQLITE_OK) { + g_warning("Unable to start transaction to delete"); + return FALSE; + } + + /* Remove all URLs for file */ + sqlite3_stmt * stmt; + if (sqlite3_prepare_v2(db, + "delete from urls where sourcefile in (select rowid from configfiles where name = ?1);", + -1, /* length */ + &stmt, + NULL) != SQLITE_OK) { + g_warning("Unable to parse SQL to remove urls"); + return FALSE; + } + + sqlite3_bind_text(stmt, 1, path, -1, SQLITE_TRANSIENT); + + int exec_status = SQLITE_ROW; + while ((exec_status = sqlite3_step(stmt)) == SQLITE_ROW) { + } + + sqlite3_finalize(stmt); + + if (exec_status != SQLITE_DONE) { + g_warning("Unable to execute removal of URLs"); + return FALSE; + } + + /* Remove references to the file */ + stmt = NULL; + + if (sqlite3_prepare_v2(db, + "delete from configfiles where name = ?1;", + -1, /* length */ + &stmt, + NULL) != SQLITE_OK) { + g_warning("Unable to parse SQL to remove urls"); + return FALSE; + } + + sqlite3_bind_text(stmt, 1, path, -1, SQLITE_TRANSIENT); + + exec_status = SQLITE_ROW; + while ((exec_status = sqlite3_step(stmt)) == SQLITE_ROW) { + } + + sqlite3_finalize(stmt); + + if (exec_status != SQLITE_DONE) { + g_warning("Unable to execute removal of file"); + return FALSE; + } + + /* Commit the full transaction */ + if (sqlite3_exec(db, "commit", NULL, NULL, NULL) != SQLITE_OK) { + g_warning("Unable to commit transaction to delete"); + return FALSE; + } + + return TRUE; +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/service/url-db.h url-dispatcher-0.1+14.04.20140331.1/service/url-db.h --- url-dispatcher-0.1+14.04.20140217.1/service/url-db.h 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/service/url-db.h 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,49 @@ +/** + * Copyright © 2014 Canonical, Ltd. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3, as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Author: Ted Gould + * + */ + +#include +#include + +#ifndef __URL_DB_H__ +#define __URL_DB_H__ 1 + +G_BEGIN_DECLS + +sqlite3 * url_db_create_database (void); +gboolean url_db_get_file_motification_time (sqlite3 * db, + const gchar * filename, + GTimeVal * timeval); +gboolean url_db_set_file_motification_time (sqlite3 * db, + const gchar * filename, + GTimeVal * timeval); +gboolean url_db_insert_url (sqlite3 * db, + const gchar * filename, + const gchar * protocol, + const gchar * domainsuffix); +gchar * url_db_find_url (sqlite3 * db, + const gchar * protocol, + const gchar * domainsuffix); +GList * url_db_files_for_dir (sqlite3 * db, + const gchar * dir); +gboolean url_db_remove_file (sqlite3 * db, + const gchar * path); + +G_END_DECLS + +#endif /* __URL_DB_H__ */ diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/app-id-test.cc url-dispatcher-0.1+14.04.20140331.1/tests/app-id-test.cc --- url-dispatcher-0.1+14.04.20140217.1/tests/app-id-test.cc 2014-02-17 17:58:24.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/app-id-test.cc 2014-03-31 17:18:35.000000000 +0000 @@ -26,11 +26,15 @@ private: GTestDBus * testbus = NULL; GMainLoop * mainloop = NULL; + gchar * cachedir = NULL; protected: virtual void SetUp() { - g_setenv("URL_DISPATCHER_CLICK_EXEC", CMAKE_SOURCE_DIR "/click-test.sh", TRUE); - g_setenv("URL_DISPATCHER_TEST_CLICK_DIR", CMAKE_SOURCE_DIR "/click-data/", TRUE); + g_setenv("TEST_CLICK_DB", "click-db", TRUE); + g_setenv("TEST_CLICK_USER", "test-user", TRUE); + + cachedir = g_build_filename(CMAKE_BINARY_DIR, "app-id-test-cache", NULL); + g_setenv("URL_DISPATCHER_CACHE_DIR", cachedir, TRUE); testbus = g_test_dbus_new(G_TEST_DBUS_NONE); g_test_dbus_up(testbus); @@ -55,6 +59,11 @@ g_test_dbus_down(testbus); g_object_unref(testbus); + + gchar * cmdline = g_strdup_printf("rm -rf \"%s\"", cachedir); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + g_free(cachedir); return; } }; @@ -119,17 +128,9 @@ return; } -TEST_F(AppIdTest, CustomUri) -{ - /* Good sanity check */ - ASSERT_TRUE(dispatch_url("appidtest:///foo")); - ASSERT_STREQ("com.test.good_app1_1.2.3", upstart_app_launch_mock_get_last_app_id()); - upstart_app_launch_mock_clear_last_app_id(); -} - TEST_F(AppIdTest, BadDirectory) { - g_setenv("URL_DISPATCHER_TEST_CLICK_DIR", CMAKE_SOURCE_DIR "/not-a-real-directory/", TRUE); + g_setenv("TEST_CLICK_DB", "not-click-db", TRUE); dispatch_url("appid://com.test.good/app1/current-user-version"); ASSERT_TRUE(NULL == upstart_app_launch_mock_get_last_app_id()); @@ -138,9 +139,9 @@ return; } -TEST_F(AppIdTest, BadClick) +TEST_F(AppIdTest, BadUser) { - g_unsetenv("URL_DISPATCHER_TEST_CLICK_DIR"); + g_setenv("TEST_CLICK_USER", "not-test-user", TRUE); dispatch_url("appid://com.test.good/app1/current-user-version"); ASSERT_TRUE(NULL == upstart_app_launch_mock_get_last_app_id()); diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/info/com.test.good.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/info/com.test.good.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/info/com.test.good.manifest 2014-02-17 17:58:24.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/info/com.test.good.manifest 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -{ - "version": "1.2.3", - "name": "com.test.good", - "hooks": { - "app1": { - "test": "test" - } - } -} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/info/com.test.multiple.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/info/com.test.multiple.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/info/com.test.multiple.manifest 2014-02-17 17:58:24.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/info/com.test.multiple.manifest 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -{ - "version": "1.2.3", - "name": "com.test.good", - "hooks": { - "app-first": { - "test": "test" - }, - "app-middle": { - "test": "test" - }, - "app-last": { - "test": "test" - } - } -} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/info/com.ubuntu.calendar.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/info/com.ubuntu.calendar.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/info/com.ubuntu.calendar.manifest 2014-02-17 17:58:24.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/info/com.ubuntu.calendar.manifest 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -{ - "version": "9.8.2343", - "name": "com.ubuntu.calendar", - "hooks": { - "calendar": { - "test": "test" - } - } -} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/info/com.ubuntu.clock.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/info/com.ubuntu.clock.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/info/com.ubuntu.clock.manifest 2014-02-17 17:58:24.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/info/com.ubuntu.clock.manifest 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -{ - "version": "3.23455.1", - "name": "com.ubuntu.clock", - "hooks": { - "clock": { - "test": "test" - } - } -} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/info/com.ubuntu.music.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/info/com.ubuntu.music.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/info/com.ubuntu.music.manifest 2014-02-17 17:58:24.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/info/com.ubuntu.music.manifest 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -{ - "version": "1.5.4", - "name": "com.ubuntu.music", - "hooks": { - "music": { - "test": "test" - } - } -} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.test.good.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.test.good.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.test.good.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.test.good.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app1": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.test.multiple.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.test.multiple.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.test.multiple.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.test.multiple.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,15 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app-first": { + "test": "test" + }, + "app-middle": { + "test": "test" + }, + "app-last": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.ubuntu.calendar.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.ubuntu.calendar.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.ubuntu.calendar.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.ubuntu.calendar.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "9.8.2343", + "name": "com.ubuntu.calendar", + "hooks": { + "calendar": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.ubuntu.clock.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.ubuntu.clock.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.ubuntu.clock.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.ubuntu.clock.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "3.23455.1", + "name": "com.ubuntu.clock", + "hooks": { + "clock": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.ubuntu.music.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.ubuntu.music.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.ubuntu.music.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.good/.click/info/com.ubuntu.music.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.5.4", + "name": "com.ubuntu.music", + "hooks": { + "music": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.test.good.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.test.good.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.test.good.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.test.good.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app1": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.test.multiple.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.test.multiple.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.test.multiple.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.test.multiple.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,15 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app-first": { + "test": "test" + }, + "app-middle": { + "test": "test" + }, + "app-last": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.ubuntu.calendar.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.ubuntu.calendar.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.ubuntu.calendar.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.ubuntu.calendar.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "9.8.2343", + "name": "com.ubuntu.calendar", + "hooks": { + "calendar": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.ubuntu.clock.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.ubuntu.clock.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.ubuntu.clock.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.ubuntu.clock.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "3.23455.1", + "name": "com.ubuntu.clock", + "hooks": { + "clock": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.ubuntu.music.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.ubuntu.music.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.ubuntu.music.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.test.multiple/.click/info/com.ubuntu.music.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.5.4", + "name": "com.ubuntu.music", + "hooks": { + "music": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.test.good.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.test.good.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.test.good.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.test.good.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app1": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.test.multiple.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.test.multiple.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.test.multiple.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.test.multiple.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,15 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app-first": { + "test": "test" + }, + "app-middle": { + "test": "test" + }, + "app-last": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.ubuntu.calendar.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.ubuntu.calendar.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.ubuntu.calendar.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.ubuntu.calendar.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "9.8.2343", + "name": "com.ubuntu.calendar", + "hooks": { + "calendar": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.ubuntu.clock.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.ubuntu.clock.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.ubuntu.clock.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.ubuntu.clock.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "3.23455.1", + "name": "com.ubuntu.clock", + "hooks": { + "clock": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.ubuntu.music.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.ubuntu.music.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.ubuntu.music.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.calendar/.click/info/com.ubuntu.music.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.5.4", + "name": "com.ubuntu.music", + "hooks": { + "music": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.test.good.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.test.good.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.test.good.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.test.good.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app1": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.test.multiple.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.test.multiple.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.test.multiple.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.test.multiple.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,15 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app-first": { + "test": "test" + }, + "app-middle": { + "test": "test" + }, + "app-last": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.ubuntu.calendar.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.ubuntu.calendar.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.ubuntu.calendar.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.ubuntu.calendar.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "9.8.2343", + "name": "com.ubuntu.calendar", + "hooks": { + "calendar": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.ubuntu.clock.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.ubuntu.clock.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.ubuntu.clock.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.ubuntu.clock.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "3.23455.1", + "name": "com.ubuntu.clock", + "hooks": { + "clock": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.ubuntu.music.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.ubuntu.music.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.ubuntu.music.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.clock/.click/info/com.ubuntu.music.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.5.4", + "name": "com.ubuntu.music", + "hooks": { + "music": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.test.good.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.test.good.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.test.good.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.test.good.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app1": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.test.multiple.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.test.multiple.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.test.multiple.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.test.multiple.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,15 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app-first": { + "test": "test" + }, + "app-middle": { + "test": "test" + }, + "app-last": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.ubuntu.calendar.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.ubuntu.calendar.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.ubuntu.calendar.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.ubuntu.calendar.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "9.8.2343", + "name": "com.ubuntu.calendar", + "hooks": { + "calendar": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.ubuntu.clock.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.ubuntu.clock.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.ubuntu.clock.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.ubuntu.clock.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "3.23455.1", + "name": "com.ubuntu.clock", + "hooks": { + "clock": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.ubuntu.music.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.ubuntu.music.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.ubuntu.music.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/.click/users/test-user/com.ubuntu.music/.click/info/com.ubuntu.music.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.5.4", + "name": "com.ubuntu.music", + "hooks": { + "music": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.good/1.2.3/.click/info/com.test.good.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.good/1.2.3/.click/info/com.test.good.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.good/1.2.3/.click/info/com.test.good.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.good/1.2.3/.click/info/com.test.good.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app1": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.good/1.2.3/.click/info/com.test.multiple.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.good/1.2.3/.click/info/com.test.multiple.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.good/1.2.3/.click/info/com.test.multiple.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.good/1.2.3/.click/info/com.test.multiple.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,15 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app-first": { + "test": "test" + }, + "app-middle": { + "test": "test" + }, + "app-last": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.good/1.2.3/.click/info/com.ubuntu.calendar.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.good/1.2.3/.click/info/com.ubuntu.calendar.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.good/1.2.3/.click/info/com.ubuntu.calendar.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.good/1.2.3/.click/info/com.ubuntu.calendar.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "9.8.2343", + "name": "com.ubuntu.calendar", + "hooks": { + "calendar": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.good/1.2.3/.click/info/com.ubuntu.clock.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.good/1.2.3/.click/info/com.ubuntu.clock.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.good/1.2.3/.click/info/com.ubuntu.clock.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.good/1.2.3/.click/info/com.ubuntu.clock.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "3.23455.1", + "name": "com.ubuntu.clock", + "hooks": { + "clock": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.good/1.2.3/.click/info/com.ubuntu.music.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.good/1.2.3/.click/info/com.ubuntu.music.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.good/1.2.3/.click/info/com.ubuntu.music.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.good/1.2.3/.click/info/com.ubuntu.music.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.5.4", + "name": "com.ubuntu.music", + "hooks": { + "music": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.test.good.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.test.good.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.test.good.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.test.good.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app1": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.test.multiple.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.test.multiple.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.test.multiple.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.test.multiple.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,15 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app-first": { + "test": "test" + }, + "app-middle": { + "test": "test" + }, + "app-last": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.ubuntu.calendar.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.ubuntu.calendar.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.ubuntu.calendar.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.ubuntu.calendar.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "9.8.2343", + "name": "com.ubuntu.calendar", + "hooks": { + "calendar": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.ubuntu.clock.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.ubuntu.clock.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.ubuntu.clock.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.ubuntu.clock.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "3.23455.1", + "name": "com.ubuntu.clock", + "hooks": { + "clock": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.ubuntu.music.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.ubuntu.music.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.ubuntu.music.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.test.multiple/1.2.3/.click/info/com.ubuntu.music.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.5.4", + "name": "com.ubuntu.music", + "hooks": { + "music": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.test.good.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.test.good.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.test.good.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.test.good.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app1": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.test.multiple.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.test.multiple.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.test.multiple.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.test.multiple.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,15 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app-first": { + "test": "test" + }, + "app-middle": { + "test": "test" + }, + "app-last": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.ubuntu.calendar.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.ubuntu.calendar.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.ubuntu.calendar.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.ubuntu.calendar.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "9.8.2343", + "name": "com.ubuntu.calendar", + "hooks": { + "calendar": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.ubuntu.clock.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.ubuntu.clock.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.ubuntu.clock.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.ubuntu.clock.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "3.23455.1", + "name": "com.ubuntu.clock", + "hooks": { + "clock": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.ubuntu.music.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.ubuntu.music.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.ubuntu.music.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info/com.ubuntu.music.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.5.4", + "name": "com.ubuntu.music", + "hooks": { + "music": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.test.good.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.test.good.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.test.good.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.test.good.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app1": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.test.multiple.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.test.multiple.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.test.multiple.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.test.multiple.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,15 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app-first": { + "test": "test" + }, + "app-middle": { + "test": "test" + }, + "app-last": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.ubuntu.calendar.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.ubuntu.calendar.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.ubuntu.calendar.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.ubuntu.calendar.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "9.8.2343", + "name": "com.ubuntu.calendar", + "hooks": { + "calendar": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.ubuntu.clock.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.ubuntu.clock.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.ubuntu.clock.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.ubuntu.clock.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "3.23455.1", + "name": "com.ubuntu.clock", + "hooks": { + "clock": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.ubuntu.music.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.ubuntu.music.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.ubuntu.music.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info/com.ubuntu.music.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.5.4", + "name": "com.ubuntu.music", + "hooks": { + "music": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.test.good.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.test.good.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.test.good.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.test.good.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app1": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.test.multiple.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.test.multiple.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.test.multiple.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.test.multiple.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,15 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app-first": { + "test": "test" + }, + "app-middle": { + "test": "test" + }, + "app-last": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.ubuntu.calendar.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.ubuntu.calendar.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.ubuntu.calendar.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.ubuntu.calendar.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "9.8.2343", + "name": "com.ubuntu.calendar", + "hooks": { + "calendar": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.ubuntu.clock.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.ubuntu.clock.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.ubuntu.clock.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.ubuntu.clock.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "3.23455.1", + "name": "com.ubuntu.clock", + "hooks": { + "clock": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.ubuntu.music.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.ubuntu.music.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.ubuntu.music.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/com.ubuntu.music/1.5.4/.click/info/com.ubuntu.music.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.5.4", + "name": "com.ubuntu.music", + "hooks": { + "music": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/manifests/com.test.good.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/manifests/com.test.good.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/manifests/com.test.good.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/manifests/com.test.good.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app1": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/manifests/com.test.multiple.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/manifests/com.test.multiple.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/manifests/com.test.multiple.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/manifests/com.test.multiple.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,15 @@ +{ + "version": "1.2.3", + "name": "com.test.good", + "hooks": { + "app-first": { + "test": "test" + }, + "app-middle": { + "test": "test" + }, + "app-last": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/manifests/com.ubuntu.calendar.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/manifests/com.ubuntu.calendar.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/manifests/com.ubuntu.calendar.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/manifests/com.ubuntu.calendar.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "9.8.2343", + "name": "com.ubuntu.calendar", + "hooks": { + "calendar": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/manifests/com.ubuntu.clock.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/manifests/com.ubuntu.clock.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/manifests/com.ubuntu.clock.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/manifests/com.ubuntu.clock.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "3.23455.1", + "name": "com.ubuntu.clock", + "hooks": { + "clock": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-data/manifests/com.ubuntu.music.manifest url-dispatcher-0.1+14.04.20140331.1/tests/click-data/manifests/com.ubuntu.music.manifest --- url-dispatcher-0.1+14.04.20140217.1/tests/click-data/manifests/com.ubuntu.music.manifest 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-data/manifests/com.ubuntu.music.manifest 2014-03-31 17:17:59.000000000 +0000 @@ -0,0 +1,9 @@ +{ + "version": "1.5.4", + "name": "com.ubuntu.music", + "hooks": { + "music": { + "test": "test" + } + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-db/test.conf.in url-dispatcher-0.1+14.04.20140331.1/tests/click-db/test.conf.in --- url-dispatcher-0.1+14.04.20140217.1/tests/click-db/test.conf.in 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-db/test.conf.in 2014-03-31 17:18:35.000000000 +0000 @@ -0,0 +1,2 @@ +[Click Database] +root = @CMAKE_CURRENT_SOURCE_DIR@/click-data diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/click-test.sh url-dispatcher-0.1+14.04.20140331.1/tests/click-test.sh --- url-dispatcher-0.1+14.04.20140217.1/tests/click-test.sh 2014-02-17 17:58:24.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/click-test.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -#!/bin/bash - -if [ "x${URL_DISPATCHER_TEST_CLICK_DIR}" == "x" ]; then - exit 1 -fi - -cat "${URL_DISPATCHER_TEST_CLICK_DIR}/.click/info/${2}.manifest" diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/CMakeLists.txt url-dispatcher-0.1+14.04.20140331.1/tests/CMakeLists.txt --- url-dispatcher-0.1+14.04.20140217.1/tests/CMakeLists.txt 2014-02-17 17:58:24.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/CMakeLists.txt 2014-03-31 17:18:35.000000000 +0000 @@ -1,4 +1,13 @@ +add_definitions ( -DCMAKE_BINARY_DIR="${CMAKE_CURRENT_BINARY_DIR}" ) + +########################### +# Click Database +########################### + +configure_file ("click-db/test.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/click-db/test.conf" @ONLY) +set_directory_properties (PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_CURRENT_BINARY_DIR}/click-db/test.conf") + ########################### # Google Test ########################### @@ -34,6 +43,7 @@ dispatcher-lib mock-lib gtest + ${UPSTART_APP_LAUNCH_LIBRARIES} ${GTEST_LIBS}) add_test (dispatcher-test dispatcher-test) @@ -52,6 +62,7 @@ dispatcher-lib mock-lib gtest + ${UPSTART_APP_LAUNCH_LIBRARIES} ${GTEST_LIBS}) add_test (app-id-test app-id-test) @@ -70,7 +81,7 @@ add_test (lib-test lib-test) ########################### -# lib test +# service test ########################### add_definitions ( -DURL_DISPATCHER_SERVICE="${CMAKE_BINARY_DIR}/service/url-dispatcher" ) @@ -80,7 +91,44 @@ dispatcher gtest ${DBUSTEST_LIBRARIES} + ${UPSTART_APP_LAUNCH_LIBRARIES} ${GTEST_LIBS}) add_test (service-test service-test) + +########################### +# create db test +########################### + +add_test (NAME create-db-test + COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/test-sql.sh" "${CMAKE_SOURCE_DIR}/service/create-db.sql") + +########################### +# update directory test +########################### + +add_definitions ( -DUPDATE_DIRECTORY_TOOL="${CMAKE_BINARY_DIR}/service/update-directory" ) +add_definitions ( -DUPDATE_DIRECTORY_URLS="${CMAKE_CURRENT_SOURCE_DIR}/test-urls-simple" ) +add_definitions ( -DUPDATE_DIRECTORY_VARIED="${CMAKE_CURRENT_SOURCE_DIR}/test-urls-varied" ) + +add_executable (directory-update-test directory-update-test.cc) +target_link_libraries (directory-update-test + url-db-lib + gtest + ${GTEST_LIBS}) + +add_test (directory-update-test directory-update-test) + +########################### +# url db test +########################### + +add_executable (url-db-test url-db-test.cc) +target_link_libraries (url-db-test + url-db-lib + gtest + ${GTEST_LIBS}) + +add_test (url-db-test url-db-test) + diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/directory-update-test.cc url-dispatcher-0.1+14.04.20140331.1/tests/directory-update-test.cc --- url-dispatcher-0.1+14.04.20140217.1/tests/directory-update-test.cc 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/directory-update-test.cc 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,353 @@ +/** + * Copyright © 2014 Canonical, Ltd. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3, as published by + * the Free Software Foundation. + * * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + */ + +#include +#include "url-db.h" +#include + +class DirectoryUpdateTest : public ::testing::Test +{ + protected: + gchar * cachedir = NULL; + + virtual void SetUp() { + cachedir = g_build_filename(CMAKE_BINARY_DIR, "url-db-test-cache", NULL); + g_setenv("URL_DISPATCHER_CACHE_DIR", cachedir, TRUE); + } + + virtual void TearDown() { + gchar * cmdline = g_strdup_printf("rm -rf \"%s\"", cachedir); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + g_free(cachedir); + } + + int get_file_count (sqlite3 * db) { + sqlite3_stmt * stmt; + if (sqlite3_prepare_v2(db, + "select count(*) from configfiles", + -1, /* length */ + &stmt, + NULL) != SQLITE_OK) { + g_warning("Unable to parse SQL to get file times"); + return 0; + } + + int retval = 0; + int exec_status = SQLITE_ROW; + while ((exec_status = sqlite3_step(stmt)) == SQLITE_ROW) { + retval = sqlite3_column_int(stmt, 0); + } + + sqlite3_finalize(stmt); + + if (exec_status != SQLITE_DONE) { + g_warning("Unable to execute insert"); + return 0; + } + + return retval; + } + + int get_url_count (sqlite3 * db) { + sqlite3_stmt * stmt; + if (sqlite3_prepare_v2(db, + "select count(*) from urls", + -1, /* length */ + &stmt, + NULL) != SQLITE_OK) { + g_warning("Unable to parse SQL to get file times"); + return 0; + } + + int retval = 0; + int exec_status = SQLITE_ROW; + while ((exec_status = sqlite3_step(stmt)) == SQLITE_ROW) { + retval = sqlite3_column_int(stmt, 0); + } + + sqlite3_finalize(stmt); + + if (exec_status != SQLITE_DONE) { + g_warning("Unable to execute insert"); + return 0; + } + + return retval; + } + + bool has_file (sqlite3 * db, const char * filename) { + sqlite3_stmt * stmt; + if (sqlite3_prepare_v2(db, + "select count(*) from configfiles where name = ?1", + -1, /* length */ + &stmt, + NULL) != SQLITE_OK) { + g_warning("Unable to parse SQL to get file times"); + return false; + } + + sqlite3_bind_text(stmt, 1, filename, -1, SQLITE_TRANSIENT); + + int retval = 0; + int exec_status = SQLITE_ROW; + while ((exec_status = sqlite3_step(stmt)) == SQLITE_ROW) { + retval = sqlite3_column_int(stmt, 0); + } + + sqlite3_finalize(stmt); + + if (exec_status != SQLITE_DONE) { + g_warning("Unable to execute insert"); + return false; + } + + if (retval > 1) { + g_warning("Database contains more than one instance of '%s'", filename); + return false; + } + + return retval == 1; + } + + bool has_url (sqlite3 * db, const char * protocol, const char * domainsuffix) { + sqlite3_stmt * stmt; + if (sqlite3_prepare_v2(db, + "select count(*) from urls where protocol = ?1 and domainsuffix = ?2", + -1, /* length */ + &stmt, + NULL) != SQLITE_OK) { + g_warning("Unable to parse SQL to get file times"); + return false; + } + + sqlite3_bind_text(stmt, 1, protocol, -1, SQLITE_TRANSIENT); + sqlite3_bind_text(stmt, 2, domainsuffix, -1, SQLITE_TRANSIENT); + + int retval = 0; + int exec_status = SQLITE_ROW; + while ((exec_status = sqlite3_step(stmt)) == SQLITE_ROW) { + retval = sqlite3_column_int(stmt, 0); + } + + sqlite3_finalize(stmt); + + if (exec_status != SQLITE_DONE) { + g_warning("Unable to execute insert"); + return false; + } + + if (retval > 1) { + g_warning("Database contains more than one instance of prtocol '%s'", protocol); + return false; + } + + return retval == 1; + } +}; + +TEST_F(DirectoryUpdateTest, DirDoesntExist) +{ + sqlite3 * db = url_db_create_database(); + + gchar * cmdline = g_strdup_printf("%s \"%s\"", UPDATE_DIRECTORY_TOOL, CMAKE_SOURCE_DIR "/this-does-not-exist"); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + + EXPECT_EQ(0, get_file_count(db)); + EXPECT_EQ(0, get_url_count(db)); + + sqlite3_close(db); +}; + +TEST_F(DirectoryUpdateTest, SingleGoodItem) +{ + sqlite3 * db = url_db_create_database(); + + gchar * cmdline = g_strdup_printf("%s \"%s\"", UPDATE_DIRECTORY_TOOL, UPDATE_DIRECTORY_URLS); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + + EXPECT_EQ(1, get_file_count(db)); + EXPECT_EQ(1, get_url_count(db)); + + EXPECT_TRUE(has_file(db, UPDATE_DIRECTORY_URLS "/single-good.url-dispatcher")); + EXPECT_TRUE(has_url(db, "http", "ubuntu.com")); + + sqlite3_close(db); +}; + +TEST_F(DirectoryUpdateTest, RerunAgain) +{ + gchar * cmdline = NULL; + sqlite3 * db = url_db_create_database(); + + cmdline = g_strdup_printf("%s \"%s\"", UPDATE_DIRECTORY_TOOL, UPDATE_DIRECTORY_URLS); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + + EXPECT_EQ(1, get_file_count(db)); + EXPECT_EQ(1, get_url_count(db)); + + cmdline = g_strdup_printf("%s \"%s\"", UPDATE_DIRECTORY_TOOL, UPDATE_DIRECTORY_URLS); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + + EXPECT_EQ(1, get_file_count(db)); + EXPECT_EQ(1, get_url_count(db)); + + cmdline = g_strdup_printf("%s \"%s\"", UPDATE_DIRECTORY_TOOL, UPDATE_DIRECTORY_URLS); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + + EXPECT_EQ(1, get_file_count(db)); + EXPECT_EQ(1, get_url_count(db)); + + sqlite3_close(db); +}; + +TEST_F(DirectoryUpdateTest, VariedItems) +{ + sqlite3 * db = url_db_create_database(); + + gchar * cmdline = g_strdup_printf("%s \"%s\"", UPDATE_DIRECTORY_TOOL, UPDATE_DIRECTORY_VARIED); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + + EXPECT_EQ(6, get_file_count(db)); + EXPECT_EQ(13, get_url_count(db)); + + /* object-base.url-dispatcher */ + EXPECT_TRUE(has_file(db, UPDATE_DIRECTORY_VARIED "/object-base.url-dispatcher")); + EXPECT_FALSE(has_url(db, "object", "object-base.com")); + + /* bad-filename-suffix.url-launcher */ + EXPECT_FALSE(has_file(db, UPDATE_DIRECTORY_VARIED "/bad-filename-suffix.url-launcher")); + EXPECT_FALSE(has_url(db, "badsuffix", "bad.suffix.com")); + + /* not-json.url-dispatcher */ + EXPECT_TRUE(has_file(db, UPDATE_DIRECTORY_VARIED "/not-json.url-dispatcher")); + EXPECT_FALSE(has_url(db, "notjson", "not.json.com")); + + /* lots-o-entries.url-dispatcher */ + EXPECT_TRUE(has_file(db, UPDATE_DIRECTORY_VARIED "/lots-o-entries.url-dispatcher")); + EXPECT_TRUE(has_url(db, "lots0", "lots.com")); + EXPECT_TRUE(has_url(db, "lots1", "lots.com")); + EXPECT_TRUE(has_url(db, "lots2", "lots.com")); + EXPECT_TRUE(has_url(db, "lots3", "lots.com")); + EXPECT_TRUE(has_url(db, "lots4", "lots.com")); + EXPECT_TRUE(has_url(db, "lots5", "lots.com")); + EXPECT_TRUE(has_url(db, "lots6", "lots.com")); + EXPECT_TRUE(has_url(db, "lots7", "lots.com")); + EXPECT_TRUE(has_url(db, "lots8", "lots.com")); + EXPECT_TRUE(has_url(db, "lots9", "lots.com")); + + /* duplicate.url-dispatcher */ + EXPECT_TRUE(has_file(db, UPDATE_DIRECTORY_VARIED "/duplicate.url-dispatcher")); + EXPECT_TRUE(has_url(db, "duplicate", "dup.licate.com")); + + /* dup-file-1.url-dispatcher */ + /* dup-file-2.url-dispatcher */ + EXPECT_TRUE(has_file(db, UPDATE_DIRECTORY_VARIED "/dup-file-1.url-dispatcher")); + EXPECT_TRUE(has_file(db, UPDATE_DIRECTORY_VARIED "/dup-file-2.url-dispatcher")); + EXPECT_FALSE(has_url(db, "dupfile", "this.is.in.two.file.org")); + + sqlite3_close(db); +}; + +TEST_F(DirectoryUpdateTest, RemoveFile) +{ + gchar * cmdline; + sqlite3 * db = url_db_create_database(); + + /* A temporary directory to put files in */ + gchar * datadir = g_build_filename(CMAKE_BINARY_DIR, "remove-file-data", NULL); + g_mkdir_with_parents(datadir, 1 << 6 | 1 << 7 | 1 << 8); // 700 + ASSERT_TRUE(g_file_test(datadir, (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))); + + /* Copy the files */ + cmdline = g_strdup_printf("cp \"%s/%s\" \"%s\"", UPDATE_DIRECTORY_URLS, "single-good.url-dispatcher", datadir); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + + /* Run the tool */ + cmdline = g_strdup_printf("%s \"%s\"", UPDATE_DIRECTORY_TOOL, datadir); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + + EXPECT_EQ(1, get_file_count(db)); + EXPECT_EQ(1, get_url_count(db)); + + /* Kill the files */ + cmdline = g_strdup_printf("rm \"%s/%s\"", datadir, "single-good.url-dispatcher"); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + + /* Run the tool */ + cmdline = g_strdup_printf("%s \"%s\"", UPDATE_DIRECTORY_TOOL, datadir); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + + EXPECT_EQ(0, get_file_count(db)); + EXPECT_EQ(0, get_url_count(db)); + + /* Cleanup */ + cmdline = g_strdup_printf("rm -rf \"%s\"", datadir); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + + sqlite3_close(db); +} + +TEST_F(DirectoryUpdateTest, RemoveDirectory) +{ + gchar * cmdline; + sqlite3 * db = url_db_create_database(); + + /* A temporary directory to put files in */ + gchar * datadir = g_build_filename(CMAKE_BINARY_DIR, "remove-directory-data", NULL); + g_mkdir_with_parents(datadir, 1 << 6 | 1 << 7 | 1 << 8); // 700 + ASSERT_TRUE(g_file_test(datadir, (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))); + + /* Copy the files */ + cmdline = g_strdup_printf("cp \"%s/%s\" \"%s\"", UPDATE_DIRECTORY_URLS, "single-good.url-dispatcher", datadir); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + + /* Run the tool */ + cmdline = g_strdup_printf("%s \"%s/\"", UPDATE_DIRECTORY_TOOL, datadir); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + + EXPECT_EQ(1, get_file_count(db)); + EXPECT_EQ(1, get_url_count(db)); + + /* Kill the dir */ + cmdline = g_strdup_printf("rm -rf \"%s\"", datadir); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + + /* Run the tool */ + cmdline = g_strdup_printf("%s \"%s/\"", UPDATE_DIRECTORY_TOOL, datadir); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + + EXPECT_EQ(0, get_file_count(db)); + EXPECT_EQ(0, get_url_count(db)); + + /* Cleanup */ + sqlite3_close(db); +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/dispatcher-test.cc url-dispatcher-0.1+14.04.20140331.1/tests/dispatcher-test.cc --- url-dispatcher-0.1+14.04.20140217.1/tests/dispatcher-test.cc 2014-02-17 17:58:24.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/dispatcher-test.cc 2014-03-31 17:18:35.000000000 +0000 @@ -20,17 +20,30 @@ #include #include "dispatcher.h" #include "upstart-app-launch-mock.h" +#include "url-db.h" class DispatcherTest : public ::testing::Test { private: GTestDBus * testbus = NULL; GMainLoop * mainloop = NULL; + gchar * cachedir = NULL; protected: virtual void SetUp() { - g_setenv("URL_DISPATCHER_CLICK_EXEC", CMAKE_SOURCE_DIR "/click-test.sh", TRUE); - g_setenv("URL_DISPATCHER_TEST_CLICK_DIR", CMAKE_SOURCE_DIR "/click-data/", TRUE); + g_setenv("TEST_CLICK_DB", "click-db", TRUE); + g_setenv("TEST_CLICK_USER", "test-user", TRUE); + + cachedir = g_build_filename(CMAKE_BINARY_DIR, "dispatcher-test-cache", NULL); + g_setenv("URL_DISPATCHER_CACHE_DIR", cachedir, TRUE); + + sqlite3 * db = url_db_create_database(); + GTimeVal timestamp = { .tv_sec = 12345 }; + + url_db_set_file_motification_time(db, "/testdir/com.ubuntu.calendar_calendar_9.8.2343.url-dispatcher", ×tamp); + url_db_insert_url(db, "/testdir/com.ubuntu.calendar_calendar_9.8.2343.url-dispatcher", "calendar", NULL); + + sqlite3_close(db); testbus = g_test_dbus_new(G_TEST_DBUS_NONE); g_test_dbus_up(testbus); @@ -53,8 +66,16 @@ upstart_app_launch_mock_clear_last_app_id(); + /* let other threads settle */ + g_usleep(500000); + g_test_dbus_down(testbus); g_object_unref(testbus); + + gchar * cmdline = g_strdup_printf("rm -rf \"%s\"", cachedir); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + g_free(cachedir); return; } }; @@ -96,51 +117,27 @@ ASSERT_STREQ("com.ubuntu.calendar_calendar_9.8.2343", upstart_app_launch_mock_get_last_app_id()); upstart_app_launch_mock_clear_last_app_id(); - /* Two Slash Calendar */ - dispatch_url("calendar://?starttime=196311221830Z"); - ASSERT_TRUE(NULL == upstart_app_launch_mock_get_last_app_id()); + /* Two Slash, nothing else */ + dispatch_url("calendar://"); + ASSERT_STREQ("com.ubuntu.calendar_calendar_9.8.2343", upstart_app_launch_mock_get_last_app_id()); upstart_app_launch_mock_clear_last_app_id(); return; } -TEST_F(DispatcherTest, VideoTest) +/* FIXME: These should go away */ +TEST_F(DispatcherTest, FixmeTest) { - /* Base Video */ - dispatch_url("video:///foo.mp4"); - ASSERT_STREQ("mediaplayer-app", upstart_app_launch_mock_get_last_app_id()); - upstart_app_launch_mock_clear_last_app_id(); - /* File Video */ dispatch_url("file:///home/bar/Videos/foo.mp4"); ASSERT_STREQ("mediaplayer-app", upstart_app_launch_mock_get_last_app_id()); upstart_app_launch_mock_clear_last_app_id(); - return; -} - -TEST_F(DispatcherTest, MusicTest) -{ - /* Base Video */ - dispatch_url("music:///The_Bars_Live.mp3"); - ASSERT_STREQ("com.ubuntu.music_music_1.5.4", upstart_app_launch_mock_get_last_app_id()); - upstart_app_launch_mock_clear_last_app_id(); - /* File Video */ dispatch_url("file:///home/bar/Music/The_Bars_Live.mp3"); ASSERT_STREQ("com.ubuntu.music_music_1.5.4", upstart_app_launch_mock_get_last_app_id()); upstart_app_launch_mock_clear_last_app_id(); return; -} - -TEST_F(DispatcherTest, AlarmTest) -{ - /* Base Alarm */ - dispatch_url("alarm:///?starttime=196311221830Z"); - ASSERT_STREQ("com.ubuntu.clock_clock_3.23455.1", upstart_app_launch_mock_get_last_app_id()); - upstart_app_launch_mock_clear_last_app_id(); - - return; } diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/test-sql.sh url-dispatcher-0.1+14.04.20140331.1/tests/test-sql.sh --- url-dispatcher-0.1+14.04.20140217.1/tests/test-sql.sh 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/test-sql.sh 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,14 @@ +#!/bin/bash + +TEMPFILE=`mktemp` +SQLSTATUS=`sqlite3 -bail -echo -init $1 $TEMPFILE .quit 3>&1 1>&2- 2>&3- | grep ^Error` + +rm $TEMPFILE + +if [ "x$SQLSTATUS" == "x" ] ; then + exit 0 +else + echo "SQL Parsing Error: $1" + echo $SQLSTATUS + exit 1 +fi diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/test-urls-simple/single-good.url-dispatcher url-dispatcher-0.1+14.04.20140331.1/tests/test-urls-simple/single-good.url-dispatcher --- url-dispatcher-0.1+14.04.20140217.1/tests/test-urls-simple/single-good.url-dispatcher 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/test-urls-simple/single-good.url-dispatcher 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,6 @@ +[ + { + "protocol": "http", + "domain-suffix": "ubuntu.com" + } +] diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/test-urls-varied/bad-filename-suffix.url-launcher url-dispatcher-0.1+14.04.20140331.1/tests/test-urls-varied/bad-filename-suffix.url-launcher --- url-dispatcher-0.1+14.04.20140217.1/tests/test-urls-varied/bad-filename-suffix.url-launcher 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/test-urls-varied/bad-filename-suffix.url-launcher 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,6 @@ +[ + { + "protocol": "badsuffix", + "domain-suffix": "bad.suffix.com" + } +] diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/test-urls-varied/dup-file-1.url-dispatcher url-dispatcher-0.1+14.04.20140331.1/tests/test-urls-varied/dup-file-1.url-dispatcher --- url-dispatcher-0.1+14.04.20140217.1/tests/test-urls-varied/dup-file-1.url-dispatcher 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/test-urls-varied/dup-file-1.url-dispatcher 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,6 @@ +[ + { + "protocol": "dupfile", + "domain-suffix": "this.is.in.two.file.org" + } +] diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/test-urls-varied/dup-file-2.url-dispatcher url-dispatcher-0.1+14.04.20140331.1/tests/test-urls-varied/dup-file-2.url-dispatcher --- url-dispatcher-0.1+14.04.20140217.1/tests/test-urls-varied/dup-file-2.url-dispatcher 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/test-urls-varied/dup-file-2.url-dispatcher 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,6 @@ +[ + { + "protocol": "dupfile", + "domain-suffix": "this.is.in.two.file.org" + } +] diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/test-urls-varied/duplicate.url-dispatcher url-dispatcher-0.1+14.04.20140331.1/tests/test-urls-varied/duplicate.url-dispatcher --- url-dispatcher-0.1+14.04.20140217.1/tests/test-urls-varied/duplicate.url-dispatcher 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/test-urls-varied/duplicate.url-dispatcher 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,10 @@ +[ + { + "protocol": "duplicate", + "domain-suffix": "dup.licate.com" + }, + { + "protocol": "duplicate", + "domain-suffix": "dup.licate.com" + } +] diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/test-urls-varied/lots-o-entries.url-dispatcher url-dispatcher-0.1+14.04.20140331.1/tests/test-urls-varied/lots-o-entries.url-dispatcher --- url-dispatcher-0.1+14.04.20140217.1/tests/test-urls-varied/lots-o-entries.url-dispatcher 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/test-urls-varied/lots-o-entries.url-dispatcher 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,42 @@ +[ + { + "protocol": "lots0", + "domain-suffix": "lots.com" + }, + { + "protocol": "lots1", + "domain-suffix": "lots.com" + }, + { + "protocol": "lots2", + "domain-suffix": "lots.com" + }, + { + "protocol": "lots3", + "domain-suffix": "lots.com" + }, + { + "protocol": "lots4", + "domain-suffix": "lots.com" + }, + { + "protocol": "lots5", + "domain-suffix": "lots.com" + }, + { + "protocol": "lots6", + "domain-suffix": "lots.com" + }, + { + "protocol": "lots7", + "domain-suffix": "lots.com" + }, + { + "protocol": "lots8", + "domain-suffix": "lots.com" + }, + { + "protocol": "lots9", + "domain-suffix": "lots.com" + } +] diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/test-urls-varied/not-json.url-dispatcher url-dispatcher-0.1+14.04.20140331.1/tests/test-urls-varied/not-json.url-dispatcher --- url-dispatcher-0.1+14.04.20140217.1/tests/test-urls-varied/not-json.url-dispatcher 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/test-urls-varied/not-json.url-dispatcher 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,4 @@ + + notjson + not.json.com + diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/test-urls-varied/object-base.url-dispatcher url-dispatcher-0.1+14.04.20140331.1/tests/test-urls-varied/object-base.url-dispatcher --- url-dispatcher-0.1+14.04.20140217.1/tests/test-urls-varied/object-base.url-dispatcher 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/test-urls-varied/object-base.url-dispatcher 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "first": { + "protocol": "object", + "domain-suffix": "object-base.com" + } +} diff -Nru url-dispatcher-0.1+14.04.20140217.1/tests/url-db-test.cc url-dispatcher-0.1+14.04.20140331.1/tests/url-db-test.cc --- url-dispatcher-0.1+14.04.20140217.1/tests/url-db-test.cc 1970-01-01 00:00:00.000000000 +0000 +++ url-dispatcher-0.1+14.04.20140331.1/tests/url-db-test.cc 2014-03-31 17:18:15.000000000 +0000 @@ -0,0 +1,185 @@ +/** + * Copyright © 2014 Canonical, Ltd. + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License version 3, as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + */ + +#include +#include "url-db.h" + +class UrlDBTest : public ::testing::Test +{ + protected: + gchar * cachedir = NULL; + + virtual void SetUp() { + cachedir = g_build_filename(CMAKE_BINARY_DIR, "url-db-test-cache", NULL); + g_setenv("URL_DISPATCHER_CACHE_DIR", cachedir, TRUE); + } + + virtual void TearDown() { + gchar * cmdline = g_strdup_printf("rm -rf \"%s\"", cachedir); + g_spawn_command_line_sync(cmdline, NULL, NULL, NULL, NULL); + g_free(cmdline); + g_free(cachedir); + } + + bool file_list_has (GList * list, const gchar * filename) { + GList * cur; + + for (cur = list; cur != NULL; cur = g_list_next(cur)) { + const gchar * path = (const gchar *)cur->data; + gchar * basename = g_path_get_basename(path); + gint same = g_strcmp0(basename, filename); + g_free(basename); + + if (same == 0) { + return true; + } + } + + return false; + } +}; + +TEST_F(UrlDBTest, CreateTest) { + sqlite3 * db = url_db_create_database(); + + ASSERT_TRUE(db != NULL); + + gchar * dbfile = g_build_filename(cachedir, "url-dispatcher", "urls-1.db", NULL); + EXPECT_TRUE(g_file_test(dbfile, G_FILE_TEST_EXISTS)); + g_free(dbfile); + + const char * type = NULL; + + EXPECT_EQ(SQLITE_OK, sqlite3_table_column_metadata(db, NULL, "configfiles", "name", &type, NULL, NULL, NULL, NULL)); + EXPECT_STREQ("text", type); + EXPECT_EQ(SQLITE_OK, sqlite3_table_column_metadata(db, NULL, "configfiles", "timestamp", &type, NULL, NULL, NULL, NULL)); + EXPECT_STREQ("bigint", type); + + EXPECT_EQ(SQLITE_OK, sqlite3_table_column_metadata(db, NULL, "urls", "sourcefile", &type, NULL, NULL, NULL, NULL)); + EXPECT_STREQ("integer", type); + EXPECT_EQ(SQLITE_OK, sqlite3_table_column_metadata(db, NULL, "urls", "protocol", &type, NULL, NULL, NULL, NULL)); + EXPECT_STREQ("text", type); + EXPECT_EQ(SQLITE_OK, sqlite3_table_column_metadata(db, NULL, "urls", "domainsuffix", &type, NULL, NULL, NULL, NULL)); + EXPECT_STREQ("text", type); + + sqlite3_close(db); +} + +TEST_F(UrlDBTest, TimestampTest) { + sqlite3 * db = url_db_create_database(); + + ASSERT_TRUE(db != NULL); + + GTimeVal timeval = {0}; + EXPECT_FALSE(url_db_get_file_motification_time(db, "/foo", &timeval)); + + timeval.tv_sec = 12345; + EXPECT_TRUE(url_db_set_file_motification_time(db, "/foo", &timeval)); + + timeval.tv_sec = 0; + EXPECT_TRUE(url_db_get_file_motification_time(db, "/foo", &timeval)); + EXPECT_EQ(12345, timeval.tv_sec); + + sqlite3_close(db); +} + +TEST_F(UrlDBTest, UrlTest) { + sqlite3 * db = url_db_create_database(); + + ASSERT_TRUE(db != NULL); + + GTimeVal timeval = {0}; + timeval.tv_sec = 12345; + EXPECT_TRUE(url_db_set_file_motification_time(db, "/foo.url-dispatcher", &timeval)); + + /* Insert and find */ + EXPECT_TRUE(url_db_insert_url(db, "/foo.url-dispatcher", "bar", "foo.com")); + EXPECT_STREQ("foo", url_db_find_url(db, "bar", "foo.com")); + EXPECT_STREQ("foo", url_db_find_url(db, "bar", "www.foo.com")); + + /* Two to compete */ + timeval.tv_sec = 67890; + EXPECT_TRUE(url_db_set_file_motification_time(db, "/bar.url-dispatcher", &timeval)); + EXPECT_TRUE(url_db_insert_url(db, "/bar.url-dispatcher", "bar", "more.foo.com")); + EXPECT_STREQ("foo", url_db_find_url(db, "bar", "www.foo.com")); + EXPECT_STREQ("bar", url_db_find_url(db, "bar", "more.foo.com")); + EXPECT_STREQ("bar", url_db_find_url(db, "bar", "www.more.foo.com")); + + sqlite3_close(db); +} + +TEST_F(UrlDBTest, FileListTest) { + sqlite3 * db = url_db_create_database(); + + ASSERT_TRUE(db != NULL); + + GTimeVal timeval = {0}; + timeval.tv_sec = 12345; + + /* One Dir */ + EXPECT_TRUE(url_db_set_file_motification_time(db, "/base/directory/for/us/one.url-dispatcher", &timeval)); + EXPECT_TRUE(url_db_set_file_motification_time(db, "/base/directory/for/us/two.url-dispatcher", &timeval)); + /* No three! */ + EXPECT_TRUE(url_db_set_file_motification_time(db, "/base/directory/for/us/four.url-dispatcher", &timeval)); + EXPECT_TRUE(url_db_set_file_motification_time(db, "/base/directory/for/us/five.url-dispatcher", &timeval)); + + /* Another Dir */ + EXPECT_TRUE(url_db_set_file_motification_time(db, "/base/directory/for/them/six.url-dispatcher", &timeval)); + + GList * files = url_db_files_for_dir(db, "/base/directory/for/us"); + EXPECT_TRUE(file_list_has(files, "one.url-dispatcher")); + EXPECT_TRUE(file_list_has(files, "two.url-dispatcher")); + EXPECT_FALSE(file_list_has(files, "three.url-dispatcher")); + EXPECT_TRUE(file_list_has(files, "four.url-dispatcher")); + EXPECT_TRUE(file_list_has(files, "five.url-dispatcher")); + EXPECT_FALSE(file_list_has(files, "six.url-dispatcher")); + + g_list_free_full(files, g_free); + + files = url_db_files_for_dir(db, "/base/directory/for/them"); + EXPECT_FALSE(file_list_has(files, "five.url-dispatcher")); + EXPECT_TRUE(file_list_has(files, "six.url-dispatcher")); + + g_list_free_full(files, g_free); + + files = url_db_files_for_dir(db, "/dir/not/there"); + EXPECT_EQ(0, g_list_length(files)); + + sqlite3_close(db); +} + +TEST_F(UrlDBTest, RemoveFile) { + sqlite3 * db = url_db_create_database(); + + ASSERT_TRUE(db != NULL); + + GTimeVal timeval = {0}; + timeval.tv_sec = 12345; + EXPECT_TRUE(url_db_set_file_motification_time(db, "/foo.url-dispatcher", &timeval)); + + /* Insert and find */ + EXPECT_TRUE(url_db_insert_url(db, "/foo.url-dispatcher", "bar", "foo.com")); + EXPECT_STREQ("foo", url_db_find_url(db, "bar", "foo.com")); + + /* Remove and not find */ + EXPECT_TRUE(url_db_remove_file(db, "/foo.url-dispatcher")); + EXPECT_FALSE(url_db_get_file_motification_time(db, "/foo.url-dispatcher", &timeval)); + EXPECT_STREQ(NULL, url_db_find_url(db, "bar", "foo.com")); + + sqlite3_close(db); +} +