url-dispatcher-0.1+14.04.20140403/ 0000755 0000153 0177776 00000000000 12317350137 016675 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tools/ 0000755 0000153 0177776 00000000000 12317350137 020035 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tools/CMakeLists.txt 0000644 0000153 0177776 00000000513 12317347671 022605 0 ustar pbuser nogroup 0000000 0000000
###########################
# URL Dispatcher
###########################
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../liburl-dispatcher)
add_executable(url-dispatcher url-dispatcher.c)
target_link_libraries(url-dispatcher
dispatcher
)
install(
TARGETS url-dispatcher
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
)
url-dispatcher-0.1+14.04.20140403/tools/url-dispatcher.c 0000644 0000153 0177776 00000002311 12317347671 023135 0 ustar pbuser nogroup 0000000 0000000 /**
* Copyright (C) 2013 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 "url-dispatcher.h"
static gboolean global_success = FALSE;
static void
callback (const gchar * url, gboolean success, gpointer user_data)
{
global_success = success;
g_main_loop_quit((GMainLoop *)user_data);
return;
}
int
main (int argc, char * argv[])
{
if (argc != 2) {
g_printerr("Usage: %s \n", argv[0]);
return 1;
}
GMainLoop * mainloop = g_main_loop_new(NULL, FALSE);
url_dispatch_send(argv[1], callback, mainloop);
g_main_loop_run(mainloop);
if (global_success) {
return 0;
} else {
return 1;
}
}
url-dispatcher-0.1+14.04.20140403/cmake/ 0000755 0000153 0177776 00000000000 12317350137 017755 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/cmake/Coverage.cmake 0000644 0000153 0177776 00000004170 12317347671 022525 0 ustar pbuser nogroup 0000000 0000000 if (CMAKE_BUILD_TYPE MATCHES coverage)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} --coverage")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --coverage")
find_program(GCOVR_EXECUTABLE gcovr HINTS ${GCOVR_ROOT} "${GCOVR_ROOT}/bin")
if (NOT GCOVR_EXECUTABLE)
message(STATUS "Gcovr binary was not found, can not generate XML coverage info.")
else ()
message(STATUS "Gcovr found, can generate XML coverage info.")
add_custom_target (coverage-xml
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMAND "${GCOVR_EXECUTABLE}" --exclude="test.*" --exclude="obj.*" -x -r "${CMAKE_SOURCE_DIR}"
--object-directory=${CMAKE_BINARY_DIR} -o coverage.xml)
endif()
find_program(LCOV_EXECUTABLE lcov HINTS ${LCOV_ROOT} "${GCOVR_ROOT}/bin")
find_program(GENHTML_EXECUTABLE genhtml HINTS ${GENHTML_ROOT})
if (NOT LCOV_EXECUTABLE)
message(STATUS "Lcov binary was not found, can not generate HTML coverage info.")
else ()
if(NOT GENHTML_EXECUTABLE)
message(STATUS "Genthml binary not found, can not generate HTML coverage info.")
else()
message(STATUS "Lcov and genhtml found, can generate HTML coverage info.")
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()
endif()
endif()
url-dispatcher-0.1+14.04.20140403/cmake/UseGdbusCodegen.cmake 0000644 0000153 0177776 00000002146 12317347671 024001 0 ustar pbuser nogroup 0000000 0000000 cmake_minimum_required(VERSION 2.6)
if(POLICY CMP0011)
cmake_policy(SET CMP0011 NEW)
endif(POLICY CMP0011)
find_program(GDBUS_CODEGEN NAMES gdbus-codegen DOC "gdbus-codegen executable")
if(NOT GDBUS_CODEGEN)
message(FATAL_ERROR "Excutable gdbus-codegen not found")
endif()
function(add_gdbus_codegen)
set(_one_value OUTFILES NAME PREFIX NAMESPACE SERVICE_XML)
set(_multi_value DEPENDS)
cmake_parse_arguments (arg "" "${_one_value}" "${_multi_value}" ${ARGN})
if(arg_PREFIX)
set(PREFIX --interface-prefix ${arg_PREFIX})
endif()
if(arg_NAMESPACE)
set(NAMESPACE --c-namespace ${arg_NAMESPACE})
endif()
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${arg_NAME}.h" "${CMAKE_CURRENT_BINARY_DIR}/${arg_NAME}.c"
COMMAND "${GDBUS_CODEGEN}"
--generate-c-code "${arg_NAME}"
${PREFIX}
${NAMESPACE}
"${arg_SERVICE_XML}"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS ${arg_DEPENDS} "${arg_SERVICE_XML}"
)
set(${arg_OUTFILES} ${${arg_OUTFILES}} "${CMAKE_CURRENT_BINARY_DIR}/${arg_NAME}.c" PARENT_SCOPE)
endfunction(add_gdbus_codegen)
url-dispatcher-0.1+14.04.20140403/cmake/UseConstantBuilder.cmake 0000644 0000153 0177776 00000001232 12317347671 024543 0 ustar pbuser nogroup 0000000 0000000 cmake_minimum_required(VERSION 2.6)
if(POLICY CMP0011)
cmake_policy(SET CMP0011 NEW)
endif(POLICY CMP0011)
macro(add_constant_template outfiles name const_name input)
set(file_target "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
add_custom_command(
OUTPUT ${file_target}
COMMAND ${CMAKE_COMMAND}
"-Dname=${name}"
"-Dfile_target=${file_target}"
"-Dconst_name=${const_name}"
"-Dinput=${input}"
-P "${CMAKE_SOURCE_DIR}/cmake/ConstantBuilderTemplates.cmake"
DEPENDS "${CMAKE_SOURCE_DIR}/cmake/ConstantBuilderTemplates.cmake" "${input}"
)
list(APPEND ${outfiles} "${file_target}")
endmacro(add_constant_template)
url-dispatcher-0.1+14.04.20140403/cmake/ConstantBuilderTemplates.cmake 0000644 0000153 0177776 00000000732 12317347671 025751 0 ustar pbuser nogroup 0000000 0000000 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()
url-dispatcher-0.1+14.04.20140403/cmake/UseGSettings.cmake 0000644 0000153 0177776 00000003715 12317347671 023362 0 ustar pbuser nogroup 0000000 0000000 # GSettings.cmake, CMake macros written for Marlin, feel free to re-use them.
option (GSETTINGS_LOCALINSTALL "Install GSettings Schemas locally instead of to the GLib prefix" ${LOCAL_INSTALL})
option (GSETTINGS_COMPILE "Compile GSettings Schemas after installation" ${GSETTINGS_LOCALINSTALL})
if(GSETTINGS_LOCALINSTALL)
message(STATUS "GSettings schemas will be installed locally.")
endif()
if(GSETTINGS_COMPILE)
message(STATUS "GSettings shemas will be compiled.")
endif()
macro(add_schema SCHEMA_NAME)
set(PKG_CONFIG_EXECUTABLE pkg-config)
# Have an option to not install the schema into where GLib is
if (GSETTINGS_LOCALINSTALL)
SET (GSETTINGS_DIR "${CMAKE_INSTALL_PREFIX}/share/glib-2.0/schemas/")
else (GSETTINGS_LOCALINSTALL)
execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} glib-2.0 --variable prefix OUTPUT_VARIABLE _glib_prefix OUTPUT_STRIP_TRAILING_WHITESPACE)
SET (GSETTINGS_DIR "${_glib_prefix}/share/glib-2.0/schemas/")
endif (GSETTINGS_LOCALINSTALL)
# Run the validator and error if it fails
execute_process (COMMAND ${PKG_CONFIG_EXECUTABLE} gio-2.0 --variable glib_compile_schemas OUTPUT_VARIABLE _glib_comple_schemas OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process (COMMAND ${_glib_comple_schemas} --dry-run --schema-file=${CMAKE_CURRENT_SOURCE_DIR}/${SCHEMA_NAME} ERROR_VARIABLE _schemas_invalid OUTPUT_STRIP_TRAILING_WHITESPACE)
if (_schemas_invalid)
message (SEND_ERROR "Schema validation error: ${_schemas_invalid}")
endif (_schemas_invalid)
# Actually install and recomple schemas
message (STATUS "GSettings schemas will be installed into ${GSETTINGS_DIR}")
install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/${SCHEMA_NAME} DESTINATION ${GSETTINGS_DIR} OPTIONAL)
if (GSETTINGS_COMPILE)
install (CODE "message (STATUS \"Compiling GSettings schemas\")")
install (CODE "execute_process (COMMAND ${_glib_comple_schemas} ${GSETTINGS_DIR})")
endif ()
endmacro()
url-dispatcher-0.1+14.04.20140403/cmake/UseGlibGeneration.cmake 0000644 0000153 0177776 00000005445 12317347671 024346 0 ustar pbuser nogroup 0000000 0000000 cmake_minimum_required(VERSION 2.6)
if(POLICY CMP0011)
cmake_policy(SET CMP0011 NEW)
endif(POLICY CMP0011)
find_program(GLIB_MKENUMS glib-mkenums)
find_program(GLIB_GENMARSHAL glib-genmarshal)
macro(add_glib_marshal outfiles name prefix otherinclude)
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.h"
COMMAND ${GLIB_GENMARSHAL} --header "--prefix=${prefix}"
"${CMAKE_CURRENT_SOURCE_DIR}/${name}.list"
> "${CMAKE_CURRENT_BINARY_DIR}/${name}.h"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${name}.list"
)
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.c"
COMMAND echo "\\#include \\\"${otherinclude}\\\"" > "${CMAKE_CURRENT_BINARY_DIR}/${name}.c"
COMMAND echo "\\#include \\\"glib-object.h\\\"" >> "${CMAKE_CURRENT_BINARY_DIR}/${name}.c"
COMMAND echo "\\#include \\\"${name}.h\\\"" >> "${CMAKE_CURRENT_BINARY_DIR}/${name}.c"
COMMAND ${GLIB_GENMARSHAL} --body "--prefix=${prefix}"
"${CMAKE_CURRENT_SOURCE_DIR}/${name}.list"
>> "${CMAKE_CURRENT_BINARY_DIR}/${name}.c"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${name}.list"
"${CMAKE_CURRENT_BINARY_DIR}/${name}.h"
)
list(APPEND ${outfiles} "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
endmacro(add_glib_marshal)
macro(add_glib_enumtypes_t outfiles name htemplate ctemplate)
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.h"
COMMAND ${GLIB_MKENUMS}
--template "${htemplate}"
${ARGN} > "${CMAKE_CURRENT_BINARY_DIR}/${name}.h"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${ARGN} "${htemplate}"
)
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.c"
COMMAND ${GLIB_MKENUMS}
--template "${ctemplate}"
${ARGN} > "${CMAKE_CURRENT_BINARY_DIR}/${name}.c"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${ARGN} ${ctemplate}
"${CMAKE_CURRENT_BINARY_DIR}/${name}.h"
)
list(APPEND ${outfiles} "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
endmacro(add_glib_enumtypes_t)
macro(add_glib_enumtypes outfiles name namespace includeguard)
set(htemplate "${CMAKE_CURRENT_BINARY_DIR}/${name}.h.template")
set(ctemplate "${CMAKE_CURRENT_BINARY_DIR}/${name}.c.template")
# Write the .h template
add_custom_command(
OUTPUT ${htemplate} ${ctemplate}
COMMAND ${CMAKE_COMMAND}
"-Dctemplate=${ctemplate}"
"-Dhtemplate=${htemplate}"
"-Dname=${name}"
"-Dnamespace=${namespace}"
"-Dincludeguard=${includeguard}"
"\"-Dheaders=${ARGN}\""
-P "${CMAKE_SOURCE_DIR}/cmake/GlibGenerationTemplates.cmake"
DEPENDS "${CMAKE_SOURCE_DIR}/cmake/GlibGenerationTemplates.cmake" ${headers}
)
add_glib_enumtypes_t(${outfiles} ${name} ${htemplate} ${ctemplate} ${ARGN})
endmacro(add_glib_enumtypes)
url-dispatcher-0.1+14.04.20140403/liburl-dispatcher/ 0000755 0000153 0177776 00000000000 12317350137 022312 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/liburl-dispatcher/url-dispatcher.h 0000644 0000153 0177776 00000002202 12317347671 025416 0 ustar pbuser nogroup 0000000 0000000 /**
* Copyright (C) 2013 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
#ifndef __URL_DISPATCH_H__
#define __URL_DISPATCH_H__ 1
#pragma GCC visibility push(default)
G_BEGIN_DECLS
typedef void (*URLDispatchCallback) (const gchar * url, gboolean success, gpointer user_data);
void url_dispatch_send (const gchar * url,
URLDispatchCallback cb,
gpointer user_data);
G_END_DECLS
#pragma GCC visibility pop
#endif /* __URL_DISPATCH_H__ */
url-dispatcher-0.1+14.04.20140403/liburl-dispatcher/url-dispatcher.pc.in 0000644 0000153 0177776 00000000400 12317347671 026174 0 ustar pbuser nogroup 0000000 0000000 libdir=@libdir@
includedir=@includedir@
Cflags: -I${includedir}/liburl-dispatcher-@apiversion@
Requires: glib-2.0 gio-2.0
Libs: -L${libdir} -lurl-dispatcher
Name: liburl-dispatcher
Description: A library to request a URL to be opened
Version: @VERSION@
url-dispatcher-0.1+14.04.20140403/liburl-dispatcher/CMakeLists.txt 0000644 0000153 0177776 00000003623 12317347671 025067 0 ustar pbuser nogroup 0000000 0000000
###########################
# Version Information
###########################
set(API_VERSION 1)
set(ABI_VERSION 1)
###########################
# Generated Lib
###########################
set(GENERATED_HEADERS
service-iface.h
)
set(GENERATED_SOURCES
service-iface.c
)
add_gdbus_codegen(
OUTFILES GENERATED_SOURCES
NAME service-iface
PREFIX com.canonical.URLDispatcher.
NAMESPACE ServiceIface
SERVICE_XML ${CMAKE_CURRENT_SOURCE_DIR}/../data/com.canonical.URLDispatcher.xml
)
add_library(generated STATIC ${GENERATED_SOURCES})
target_link_libraries(generated
${GLIB2_LIBRARIES}
${GOBJECT2_LIBRARIES}
${GIO2_LIBRARIES}
)
###########################
# Lib
###########################
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
include_directories(${CMAKE_CURRENT_BINARY_DIR})
set(DISPATCHER_HEADERS
url-dispatcher.h
)
set(DISPATCHER_SOURCES
url-dispatcher.c
)
add_library(dispatcher SHARED ${DISPATCHER_SOURCES})
set_target_properties(dispatcher PROPERTIES
VERSION ${API_VERSION}.0.0
SOVERSION ${ABI_VERSION}
OUTPUT_NAME "url-dispatcher"
)
target_link_libraries(dispatcher
generated
${GLIB2_LIBRARIES}
${GOBJECT2_LIBRARIES}
-Wl,--no-undefined
)
###########################
# Pkg Config
###########################
set(DISPATCHER_PC "url-dispatcher-${API_VERSION}.pc")
set(apiversion "${API_VERSION}")
set(libdir "${CMAKE_INSTALL_FULL_LIBDIR}")
set(includedir "${CMAKE_INSTALL_FULL_INCLUDEDIR}")
set(VERSION "${ABI_VERSION}")
configure_file("url-dispatcher.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/${DISPATCHER_PC}" @ONLY)
###########################
# Installation
###########################
install(
FILES ${DISPATCHER_HEADERS}
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/liburl-dispatcher-${API_VERSION}"
)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/${DISPATCHER_PC}"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
)
install(
TARGETS dispatcher
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
url-dispatcher-0.1+14.04.20140403/liburl-dispatcher/url-dispatcher.c 0000644 0000153 0177776 00000005742 12317347671 025425 0 ustar pbuser nogroup 0000000 0000000 /**
* Copyright (C) 2013 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 "url-dispatcher.h"
#include "service-iface.h"
typedef struct _dispatch_data_t dispatch_data_t;
struct _dispatch_data_t {
ServiceIfaceComCanonicalURLDispatcher * proxy;
URLDispatchCallback cb;
gpointer user_data;
gchar * url;
};
static void
url_dispatched (GObject * obj, GAsyncResult * res, gpointer user_data)
{
GError * error = NULL;
dispatch_data_t * dispatch_data = (dispatch_data_t *)user_data;
service_iface_com_canonical_urldispatcher_call_dispatch_url_finish(
SERVICE_IFACE_COM_CANONICAL_URLDISPATCHER(obj),
res,
&error);
if (error != NULL) {
g_warning("Unable to dispatch url '%s':%s", dispatch_data->url, error->message);
g_error_free(error);
if (dispatch_data->cb != NULL) {
dispatch_data->cb(dispatch_data->url, FALSE, dispatch_data->user_data);
}
} else {
if (dispatch_data->cb != NULL) {
dispatch_data->cb(dispatch_data->url, TRUE, dispatch_data->user_data);
}
}
g_clear_object(&dispatch_data->proxy);
g_free(dispatch_data->url);
g_free(dispatch_data);
return;
}
static void
got_proxy (GObject * obj, GAsyncResult * res, gpointer user_data)
{
GError * error = NULL;
dispatch_data_t * dispatch_data = (dispatch_data_t *)user_data;
dispatch_data->proxy = service_iface_com_canonical_urldispatcher_proxy_new_for_bus_finish(res, &error);
if (error != NULL) {
g_warning("Unable to get proxy for URL Dispatcher: %s", error->message);
g_error_free(error);
if (dispatch_data->cb != NULL) {
dispatch_data->cb(dispatch_data->url, FALSE, dispatch_data->user_data);
}
g_free(dispatch_data->url);
g_free(dispatch_data);
return;
}
service_iface_com_canonical_urldispatcher_call_dispatch_url(
dispatch_data->proxy,
dispatch_data->url,
NULL, /* cancelable */
url_dispatched,
dispatch_data);
return;
}
void
url_dispatch_send (const gchar * url, URLDispatchCallback cb, gpointer user_data)
{
dispatch_data_t * dispatch_data = g_new0(dispatch_data_t, 1);
dispatch_data->cb = cb;
dispatch_data->user_data = user_data;
dispatch_data->url = g_strdup(url);
service_iface_com_canonical_urldispatcher_proxy_new_for_bus(
G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
"com.canonical.URLDispatcher",
"/com/canonical/URLDispatcher",
NULL, /* cancellable */
got_proxy,
dispatch_data
);
return;
}
url-dispatcher-0.1+14.04.20140403/tests/ 0000755 0000153 0177776 00000000000 12317350137 020037 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/dispatcher-test.cc 0000644 0000153 0177776 00000010251 12317347671 023461 0 ustar pbuser nogroup 0000000 0000000 /**
* Copyright (C) 2013 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
#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("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);
mainloop = g_main_loop_new(NULL, FALSE);
dispatcher_init(mainloop);
return;
}
virtual void TearDown() {
dispatcher_shutdown();
/* Clean up queued events */
while (g_main_pending()) {
g_main_iteration(TRUE);
}
g_main_loop_unref(mainloop);
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;
}
};
TEST_F(DispatcherTest, ApplicationTest)
{
/* Good sanity check */
dispatch_url("application:///foo.desktop");
ASSERT_STREQ("foo", upstart_app_launch_mock_get_last_app_id());
upstart_app_launch_mock_clear_last_app_id();
/* No .desktop */
dispatch_url("application:///foo");
ASSERT_TRUE(NULL == upstart_app_launch_mock_get_last_app_id());
upstart_app_launch_mock_clear_last_app_id();
/* Missing a / */
dispatch_url("application://foo.desktop");
ASSERT_TRUE(NULL == upstart_app_launch_mock_get_last_app_id());
upstart_app_launch_mock_clear_last_app_id();
/* Good with hyphens */
dispatch_url("application:///my-really-cool-app.desktop");
ASSERT_STREQ("my-really-cool-app", upstart_app_launch_mock_get_last_app_id());
upstart_app_launch_mock_clear_last_app_id();
/* Good Click Style */
dispatch_url("application:///com.test.foo_bar-app_0.3.4.desktop");
ASSERT_STREQ("com.test.foo_bar-app_0.3.4", upstart_app_launch_mock_get_last_app_id());
upstart_app_launch_mock_clear_last_app_id();
return;
}
TEST_F(DispatcherTest, CalendarTest)
{
/* Base Calendar */
dispatch_url("calendar:///?starttime=196311221830Z");
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, 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;
}
/* FIXME: These should go away */
TEST_F(DispatcherTest, FixmeTest)
{
/* 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();
/* 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;
}
url-dispatcher-0.1+14.04.20140403/tests/test-urls-simple/ 0000755 0000153 0177776 00000000000 12317350137 023270 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/test-urls-simple/single-good.url-dispatcher 0000644 0000153 0177776 00000000100 12317347671 030347 0 ustar pbuser nogroup 0000000 0000000 [
{
"protocol": "http",
"domain-suffix": "ubuntu.com"
}
]
url-dispatcher-0.1+14.04.20140403/tests/test-urls-varied/ 0000755 0000153 0177776 00000000000 12317350137 023251 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/test-urls-varied/lots-o-entries.url-dispatcher 0000644 0000153 0177776 00000001133 12317347671 031014 0 ustar pbuser nogroup 0000000 0000000 [
{
"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"
}
]
url-dispatcher-0.1+14.04.20140403/tests/test-urls-varied/bad-filename-suffix.url-launcher 0000644 0000153 0177776 00000000111 12317347671 031404 0 ustar pbuser nogroup 0000000 0000000 [
{
"protocol": "badsuffix",
"domain-suffix": "bad.suffix.com"
}
]
url-dispatcher-0.1+14.04.20140403/tests/test-urls-varied/duplicate.url-dispatcher 0000644 0000153 0177776 00000000217 12317347671 030104 0 ustar pbuser nogroup 0000000 0000000 [
{
"protocol": "duplicate",
"domain-suffix": "dup.licate.com"
},
{
"protocol": "duplicate",
"domain-suffix": "dup.licate.com"
}
]
url-dispatcher-0.1+14.04.20140403/tests/test-urls-varied/object-base.url-dispatcher 0000644 0000153 0177776 00000000120 12317347671 030301 0 ustar pbuser nogroup 0000000 0000000 {
"first": {
"protocol": "object",
"domain-suffix": "object-base.com"
}
}
url-dispatcher-0.1+14.04.20140403/tests/test-urls-varied/not-json.url-dispatcher 0000644 0000153 0177776 00000000136 12317347671 027701 0 ustar pbuser nogroup 0000000 0000000
notjson
not.json.com
url-dispatcher-0.1+14.04.20140403/tests/test-urls-varied/dup-file-2.url-dispatcher 0000644 0000153 0177776 00000000120 12317347671 027767 0 ustar pbuser nogroup 0000000 0000000 [
{
"protocol": "dupfile",
"domain-suffix": "this.is.in.two.file.org"
}
]
url-dispatcher-0.1+14.04.20140403/tests/test-urls-varied/dup-file-1.url-dispatcher 0000644 0000153 0177776 00000000120 12317347671 027766 0 ustar pbuser nogroup 0000000 0000000 [
{
"protocol": "dupfile",
"domain-suffix": "this.is.in.two.file.org"
}
]
url-dispatcher-0.1+14.04.20140403/tests/click-data/ 0000755 0000153 0177776 00000000000 12317350137 022033 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.test.multiple/ 0000755 0000153 0177776 00000000000 12317350137 025421 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.test.multiple/1.2.3/ 0000755 0000153 0177776 00000000000 12317350137 026062 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.test.multiple/1.2.3/.click/ 0000755 0000153 0177776 00000000000 12317350137 027225 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.test.multiple/1.2.3/.click/info 0000777 0000153 0177776 00000000000 12317350137 032655 2../../../manifests ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.ubuntu.clock/ 0000755 0000153 0177776 00000000000 12317350137 025224 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.ubuntu.clock/3.23455.1/ 0000755 0000153 0177776 00000000000 12317350137 026206 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.ubuntu.clock/3.23455.1/.click/ 0000755 0000153 0177776 00000000000 12317350137 027351 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.ubuntu.clock/3.23455.1/.click/info 0000777 0000153 0177776 00000000000 12317350137 033001 2../../../manifests ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.test.good/ 0000755 0000153 0177776 00000000000 12317350137 024516 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.test.good/1.2.3/ 0000755 0000153 0177776 00000000000 12317350137 025157 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.test.good/1.2.3/.click/ 0000755 0000153 0177776 00000000000 12317350137 026322 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.test.good/1.2.3/.click/info 0000777 0000153 0177776 00000000000 12317350137 031752 2../../../manifests ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/.click/ 0000755 0000153 0177776 00000000000 12317350137 023176 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/.click/users/ 0000755 0000153 0177776 00000000000 12317350137 024337 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/.click/users/test-user/ 0000755 0000153 0177776 00000000000 12317350137 026272 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/.click/users/test-user/com.test.multiple 0000777 0000153 0177776 00000000000 12317350137 036472 2../../../com.test.multiple/1.2.3/ ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/.click/users/test-user/com.ubuntu.clock 0000777 0000153 0177776 00000000000 12317350137 036421 2../../../com.ubuntu.clock/3.23455.1/ ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/.click/users/test-user/com.test.good 0000777 0000153 0177776 00000000000 12317350137 034664 2../../../com.test.good/1.2.3/ ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/.click/users/test-user/com.ubuntu.calendar 0000777 0000153 0177776 00000000000 12317350137 037503 2../../../com.ubuntu.calendar/9.8.2343/ ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/.click/users/test-user/com.ubuntu.music 0000777 0000153 0177776 00000000000 12317350137 036156 2../../../com.ubuntu.music/1.5.4/ ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.ubuntu.calendar/ 0000755 0000153 0177776 00000000000 12317350137 025702 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.ubuntu.calendar/9.8.2343/ 0000755 0000153 0177776 00000000000 12317350137 026612 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/ 0000755 0000153 0177776 00000000000 12317350137 027755 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.ubuntu.calendar/9.8.2343/.click/info 0000777 0000153 0177776 00000000000 12317350137 033405 2../../../manifests ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.ubuntu.music/ 0000755 0000153 0177776 00000000000 12317350137 025251 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.ubuntu.music/1.5.4/ 0000755 0000153 0177776 00000000000 12317350137 025716 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.ubuntu.music/1.5.4/.click/ 0000755 0000153 0177776 00000000000 12317350137 027061 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/com.ubuntu.music/1.5.4/.click/info 0000777 0000153 0177776 00000000000 12317350137 032511 2../../../manifests ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/manifests/ 0000755 0000153 0177776 00000000000 12317350137 024024 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-data/manifests/com.test.multiple.manifest 0000644 0000153 0177776 00000000271 12317347671 031153 0 ustar pbuser nogroup 0000000 0000000 {
"version": "1.2.3",
"name": "com.test.good",
"hooks": {
"app-first": {
"test": "test"
},
"app-middle": {
"test": "test"
},
"app-last": {
"test": "test"
}
}
}
url-dispatcher-0.1+14.04.20140403/tests/click-data/manifests/com.ubuntu.calendar.manifest 0000644 0000153 0177776 00000000161 12317347671 031432 0 ustar pbuser nogroup 0000000 0000000 {
"version": "9.8.2343",
"name": "com.ubuntu.calendar",
"hooks": {
"calendar": {
"test": "test"
}
}
}
url-dispatcher-0.1+14.04.20140403/tests/click-data/manifests/com.test.good.manifest 0000644 0000153 0177776 00000000144 12317347671 030247 0 ustar pbuser nogroup 0000000 0000000 {
"version": "1.2.3",
"name": "com.test.good",
"hooks": {
"app1": {
"test": "test"
}
}
}
url-dispatcher-0.1+14.04.20140403/tests/click-data/manifests/com.ubuntu.music.manifest 0000644 0000153 0177776 00000000150 12317347671 030777 0 ustar pbuser nogroup 0000000 0000000 {
"version": "1.5.4",
"name": "com.ubuntu.music",
"hooks": {
"music": {
"test": "test"
}
}
}
url-dispatcher-0.1+14.04.20140403/tests/click-data/manifests/com.ubuntu.clock.manifest 0000644 0000153 0177776 00000000154 12317347671 030756 0 ustar pbuser nogroup 0000000 0000000 {
"version": "3.23455.1",
"name": "com.ubuntu.clock",
"hooks": {
"clock": {
"test": "test"
}
}
}
url-dispatcher-0.1+14.04.20140403/tests/service-test.cc 0000644 0000153 0177776 00000010645 12317347671 023002 0 ustar pbuser nogroup 0000000 0000000 /**
* Copyright (C) 2013 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
#include
#include
class ServiceTest : public ::testing::Test
{
protected:
DbusTestService * service = NULL;
DbusTestDbusMock * mock = NULL;
DbusTestDbusMockObject * obj = NULL;
DbusTestDbusMockObject * jobobj = NULL;
DbusTestProcess * dispatcher = NULL;
GDBusConnection * bus = NULL;
virtual void SetUp() {
g_setenv("UPSTART_APP_LAUNCH_USE_SESSION", "1", TRUE);
g_setenv("URL_DISPATCHER_DISABLE_RECOVERABLE_ERROR", "1", TRUE);
service = dbus_test_service_new(NULL);
dispatcher = dbus_test_process_new(URL_DISPATCHER_SERVICE);
dbus_test_task_set_name(DBUS_TEST_TASK(dispatcher), "Dispatcher");
dbus_test_service_add_task(service, DBUS_TEST_TASK(dispatcher));
mock = dbus_test_dbus_mock_new("com.ubuntu.Upstart");
obj = dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", NULL);
dbus_test_dbus_mock_object_add_method(mock, obj,
"GetJobByName",
G_VARIANT_TYPE_STRING,
G_VARIANT_TYPE_OBJECT_PATH, /* out */
"ret = dbus.ObjectPath('/job')", /* python */
NULL); /* error */
jobobj = dbus_test_dbus_mock_get_object(mock, "/job", "com.ubuntu.Upstart0_6.Job", NULL);
dbus_test_dbus_mock_object_add_method(mock, jobobj,
"Start",
G_VARIANT_TYPE("(asb)"),
G_VARIANT_TYPE_OBJECT_PATH, /* out */
"ret = dbus.ObjectPath('/instance')", /* python */
NULL); /* error */
dbus_test_service_add_task(service, DBUS_TEST_TASK(mock));
dbus_test_service_start_tasks(service);
bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
g_dbus_connection_set_exit_on_close(bus, FALSE);
g_object_add_weak_pointer(G_OBJECT(bus), (gpointer *)&bus);
return;
}
virtual void TearDown() {
/* dbustest should probably do this, not sure */
kill(dbus_test_process_get_pid(dispatcher), SIGTERM);
g_usleep(50000);
g_clear_object(&dispatcher);
g_clear_object(&mock);
g_clear_object(&service);
g_object_unref(bus);
unsigned int cleartry = 0;
while (bus != NULL && cleartry < 100) {
g_usleep(100000);
while (g_main_pending())
g_main_iteration(TRUE);
cleartry++;
}
return;
}
};
static void
simple_cb (const gchar * url, gboolean success, gpointer user_data)
{
g_main_loop_quit(static_cast(user_data));
}
TEST_F(ServiceTest, InvalidTest) {
GMainLoop * main = g_main_loop_new(NULL, FALSE);
/* Send an invalid URL */
url_dispatch_send("foo://bar/barish", simple_cb, main);
/* Give it some time to send and reply */
g_main_loop_run(main);
g_main_loop_unref(main);
guint callslen = 0;
const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, jobobj, "Start", &callslen, NULL);
ASSERT_EQ(callslen, 0);
}
TEST_F(ServiceTest, ApplicationTest) {
GMainLoop * main = g_main_loop_new(NULL, FALSE);
/* Send an invalid URL */
url_dispatch_send("application:///foo-bar.desktop", simple_cb, main);
/* Give it some time to send and reply */
g_main_loop_run(main);
g_main_loop_unref(main);
guint callslen = 0;
const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, jobobj, "Start", &callslen, NULL);
ASSERT_EQ(callslen, 1);
/* Making sure the APP_ID is here. We're not testing more to
make it so the tests break less, that should be tested in
Upstart App Launch, we don't need to retest */
GVariant * env = g_variant_get_child_value(calls->params, 0);
GVariantIter iter;
bool found_appid = false;
g_variant_iter_init(&iter, env);
gchar * var = NULL;
while (g_variant_iter_loop(&iter, "s", &var)) {
if (g_strcmp0(var, "APP_ID=foo-bar") == 0) {
ASSERT_FALSE(found_appid);
found_appid = true;
}
}
g_variant_unref(env);
ASSERT_TRUE(found_appid);
}
url-dispatcher-0.1+14.04.20140403/tests/test-sql.sh 0000755 0000153 0177776 00000000360 12317347671 022162 0 ustar pbuser nogroup 0000000 0000000 #!/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
url-dispatcher-0.1+14.04.20140403/tests/upstart-app-launch-mock.c 0000644 0000153 0177776 00000002216 12317347671 024674 0 ustar pbuser nogroup 0000000 0000000 /**
* Copyright (C) 2013 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 "upstart-app-launch-mock.h"
static gchar * last_appid = NULL;
gboolean
upstart_app_launch_start_application (const gchar * appid, const gchar * const * uris)
{
upstart_app_launch_mock_clear_last_app_id();
last_appid = g_strdup(appid);
return TRUE;
}
void
upstart_app_launch_mock_clear_last_app_id (void)
{
g_free(last_appid);
last_appid = NULL;
return;
}
gchar *
upstart_app_launch_mock_get_last_app_id (void)
{
return last_appid;
}
url-dispatcher-0.1+14.04.20140403/tests/recoverable-problem-mock.c 0000644 0000153 0177776 00000001605 12317347671 025074 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright 2013 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Authors:
* Ted Gould
*/
#include
#include "recoverable-problem.h"
void
report_recoverable_problem (const gchar * signature, GPid report_pid, gboolean wait, gchar * additional_properties[])
{
return;
}
url-dispatcher-0.1+14.04.20140403/tests/CMakeLists.txt 0000644 0000153 0177776 00000006254 12317347671 022617 0 ustar pbuser nogroup 0000000 0000000
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
###########################
include_directories(${GTEST_INCLUDE_DIR})
add_library (gtest STATIC
${GTEST_SOURCE_DIR}/gtest-all.cc
${GTEST_SOURCE_DIR}/gtest_main.cc)
###########################
# Mock Lib
###########################
add_library(mock-lib STATIC
recoverable-problem-mock.c
upstart-app-launch-mock.h
upstart-app-launch-mock.c)
target_link_libraries(mock-lib
${GLIB2_LIBRARIES}
)
###########################
# Dispatcher test
###########################
include_directories("${CMAKE_SOURCE_DIR}/service")
add_executable (dispatcher-test dispatcher-test.cc)
target_link_libraries (dispatcher-test
dispatcher-lib
mock-lib
gtest
${UPSTART_APP_LAUNCH_LIBRARIES}
${GTEST_LIBS})
add_test (dispatcher-test dispatcher-test)
###########################
# App ID URL test
###########################
include_directories("${CMAKE_BINARY_DIR}/service")
add_definitions ( -DCMAKE_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}" )
add_definitions ( -DAPP_ID_TEST_URI=1 )
add_executable (app-id-test app-id-test.cc "${CMAKE_SOURCE_DIR}/service/dispatcher.c")
target_link_libraries (app-id-test
dispatcher-lib
mock-lib
gtest
${UPSTART_APP_LAUNCH_LIBRARIES}
${GTEST_LIBS})
add_test (app-id-test app-id-test)
###########################
# lib test
###########################
add_executable (lib-test lib-test.cc)
target_link_libraries (lib-test
dispatcher
gtest
${DBUSTEST_LIBRARIES}
${GTEST_LIBS})
add_test (lib-test lib-test)
###########################
# service test
###########################
add_definitions ( -DURL_DISPATCHER_SERVICE="${CMAKE_BINARY_DIR}/service/url-dispatcher" )
add_executable (service-test service-test.cc)
target_link_libraries (service-test
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)
url-dispatcher-0.1+14.04.20140403/tests/url-db-test.cc 0000644 0000153 0177776 00000014034 12317347671 022523 0 ustar pbuser nogroup 0000000 0000000 /**
* 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);
}
url-dispatcher-0.1+14.04.20140403/tests/directory-update-test.cc 0000644 0000153 0177776 00000024432 12317347671 024625 0 ustar pbuser nogroup 0000000 0000000 /**
* 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);
}
url-dispatcher-0.1+14.04.20140403/tests/lib-test.cc 0000644 0000153 0177776 00000005317 12317347671 022110 0 ustar pbuser nogroup 0000000 0000000 /**
* Copyright (C) 2013 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
#include
#include
class LibTest : public ::testing::Test
{
protected:
DbusTestService * service = NULL;
DbusTestDbusMock * mock = NULL;
DbusTestDbusMockObject * obj = NULL;
GDBusConnection * bus = NULL;
virtual void SetUp() {
service = dbus_test_service_new(NULL);
mock = dbus_test_dbus_mock_new("com.canonical.URLDispatcher");
obj = dbus_test_dbus_mock_get_object(mock, "/com/canonical/URLDispatcher", "com.canonical.URLDispatcher", NULL);
dbus_test_dbus_mock_object_add_method(mock, obj,
"DispatchURL",
G_VARIANT_TYPE_STRING,
NULL, /* out */
"", /* python */
NULL); /* error */
dbus_test_service_add_task(service, DBUS_TEST_TASK(mock));
dbus_test_service_start_tasks(service);
bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
g_dbus_connection_set_exit_on_close(bus, FALSE);
g_object_add_weak_pointer(G_OBJECT(bus), (gpointer *)&bus);
return;
}
virtual void TearDown() {
g_clear_object(&mock);
g_clear_object(&service);
g_object_unref(bus);
unsigned int cleartry = 0;
while (bus != NULL && cleartry < 100) {
g_usleep(100000);
while (g_main_pending())
g_main_iteration(TRUE);
cleartry++;
}
return;
}
};
static void
simple_cb (const gchar * url, gboolean success, gpointer user_data)
{
g_main_loop_quit(static_cast(user_data));
}
TEST_F(LibTest, BaseTest) {
GMainLoop * main = g_main_loop_new(NULL, FALSE);
url_dispatch_send("foo://bar/barish", simple_cb, main);
/* Give it some time to send and reply */
g_main_loop_run(main);
g_main_loop_unref(main);
guint callslen = 0;
const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "DispatchURL", &callslen, NULL);
// ASSERT_NE(calls, nullptr);
ASSERT_EQ(callslen, 1);
GVariant * check = g_variant_new_parsed("('foo://bar/barish',)");
g_variant_ref_sink(check);
ASSERT_TRUE(g_variant_equal(calls->params, check));
g_variant_unref(check);
}
url-dispatcher-0.1+14.04.20140403/tests/app-id-test.cc 0000644 0000153 0177776 00000011074 12317347671 022511 0 ustar pbuser nogroup 0000000 0000000 /**
* Copyright (C) 2013 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
#include "dispatcher.h"
#include "upstart-app-launch-mock.h"
class AppIdTest : public ::testing::Test
{
private:
GTestDBus * testbus = NULL;
GMainLoop * mainloop = NULL;
gchar * cachedir = NULL;
protected:
virtual void SetUp() {
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);
mainloop = g_main_loop_new(NULL, FALSE);
dispatcher_init(mainloop);
return;
}
virtual void TearDown() {
dispatcher_shutdown();
/* Clean up queued events */
while (g_main_pending()) {
g_main_iteration(TRUE);
}
g_main_loop_unref(mainloop);
upstart_app_launch_mock_clear_last_app_id();
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;
}
};
TEST_F(AppIdTest, BaseUrl)
{
/* Good sanity check */
dispatch_url("appid://com.test.good/app1/1.2.3");
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();
/* No version at all */
dispatch_url("appid://com.test.good/app1");
ASSERT_TRUE(NULL == upstart_app_launch_mock_get_last_app_id());
upstart_app_launch_mock_clear_last_app_id();
}
TEST_F(AppIdTest, WildcardUrl)
{
/* Version wildcard */
dispatch_url("appid://com.test.good/app1/current-user-version");
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();
/* First app */
dispatch_url("appid://com.test.good/first-listed-app/current-user-version");
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();
/* Last app */
dispatch_url("appid://com.test.good/last-listed-app/current-user-version");
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();
/* Only app */
dispatch_url("appid://com.test.good/only-listed-app/current-user-version");
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();
/* Wild app fixed version */
dispatch_url("appid://com.test.good/only-listed-app/1.2.3");
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();
return;
}
TEST_F(AppIdTest, OrderingUrl)
{
dispatch_url("appid://com.test.multiple/first-listed-app/current-user-version");
ASSERT_STREQ("com.test.multiple_app-first_1.2.3", upstart_app_launch_mock_get_last_app_id());
upstart_app_launch_mock_clear_last_app_id();
dispatch_url("appid://com.test.multiple/last-listed-app/current-user-version");
ASSERT_STREQ("com.test.multiple_app-last_1.2.3", upstart_app_launch_mock_get_last_app_id());
upstart_app_launch_mock_clear_last_app_id();
dispatch_url("appid://com.test.multiple/only-listed-app/current-user-version");
ASSERT_TRUE(NULL == upstart_app_launch_mock_get_last_app_id());
upstart_app_launch_mock_clear_last_app_id();
return;
}
TEST_F(AppIdTest, BadDirectory)
{
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());
upstart_app_launch_mock_clear_last_app_id();
return;
}
TEST_F(AppIdTest, BadUser)
{
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());
upstart_app_launch_mock_clear_last_app_id();
}
url-dispatcher-0.1+14.04.20140403/tests/click-db/ 0000755 0000153 0177776 00000000000 12317350137 021507 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/tests/click-db/test.conf.in 0000644 0000153 0177776 00000000076 12317347671 023756 0 ustar pbuser nogroup 0000000 0000000 [Click Database]
root = @CMAKE_CURRENT_SOURCE_DIR@/click-data
url-dispatcher-0.1+14.04.20140403/tests/upstart-app-launch-mock.h 0000644 0000153 0177776 00000001674 12317347671 024710 0 ustar pbuser nogroup 0000000 0000000 /**
* Copyright (C) 2013 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
#ifndef __UPSTART_APP_LAUNCH_MOCK__
#define __UPSTART_APP_LAUNCH_MOCK__ 1
G_BEGIN_DECLS
void upstart_app_launch_mock_clear_last_app_id (void);
gchar * upstart_app_launch_mock_get_last_app_id (void);
G_END_DECLS
#endif /* __UPSTART_APP_LAUNCH_MOCK__ */
url-dispatcher-0.1+14.04.20140403/service/ 0000755 0000153 0177776 00000000000 12317350137 020335 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/service/dispatcher.h 0000644 0000153 0177776 00000001731 12317347671 022647 0 ustar pbuser nogroup 0000000 0000000 /**
* Copyright (C) 2013 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
#ifndef __DISPATCHER_H__
#define __DISPATCHER_H__ 1
G_BEGIN_DECLS
gboolean dispatcher_init (GMainLoop * mainloop);
gboolean dispatcher_shutdown (void);
gboolean dispatch_url (const gchar * url);
G_END_DECLS
#endif /* __DISPATCHER_H__ */
url-dispatcher-0.1+14.04.20140403/service/url-db.c 0000644 0000153 0177776 00000022204 12317347671 021677 0 ustar pbuser nogroup 0000000 0000000 /**
* 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;
}
url-dispatcher-0.1+14.04.20140403/service/dispatcher.c 0000644 0000153 0177776 00000021537 12317347671 022650 0 ustar pbuser nogroup 0000000 0000000 /**
* Copyright (C) 2013 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
#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 GRegex * genericre = NULL;
static GRegex * musicfilere = NULL; /* FIXME */
static GRegex * videofilere = NULL; /* FIXME */
static sqlite3 * urldb = NULL;
/* Errors */
enum {
ERROR_BAD_URL
};
G_DEFINE_QUARK(url_dispatcher, url_dispatcher_error);
/* Register our errors */
static void
register_dbus_errors (void)
{
g_dbus_error_register_error(url_dispatcher_error_quark(), ERROR_BAD_URL, "com.canonical.URLDispatcher.BadURL");
return;
}
/* We should have the PID now so we can make sure to file the
problem on the right package. */
static void
recoverable_problem_file (GObject * obj, GAsyncResult * res, gpointer user_data)
{
gchar * badurl = (gchar *)user_data;
GVariant * pid_tuple = NULL;
GError * error = NULL;
pid_tuple = g_dbus_connection_call_finish(G_DBUS_CONNECTION(obj), res, &error);
if (error != NULL) {
g_warning("Unable to get PID for calling program with URL '%s': %s", badurl, error->message);
g_free(badurl);
g_error_free(error);
return;
}
guint32 pid = 0;
g_variant_get(pid_tuple, "(u)", &pid);
g_variant_unref(pid_tuple);
gchar * signature = g_strdup_printf("url-dispatcher;bad-url;%s", badurl);
gchar * additional[3] = {
"BadURL",
badurl,
NULL
};
/* Allow disabling for testing, we don't want to report bugs on
our tests ;-) */
if (g_getenv("URL_DISPATCHER_DISABLE_RECOVERABLE_ERROR") == NULL) {
report_recoverable_problem(signature, pid, FALSE, additional);
}
g_free(signature);
g_free(badurl);
return;
}
/* Say that we have a bad URL and report a recoverable error on the process that
sent it to us. */
static gboolean
bad_url (GDBusMethodInvocation * invocation, const gchar * url)
{
const gchar * sender = g_dbus_method_invocation_get_sender(invocation);
GDBusConnection * conn = g_dbus_method_invocation_get_connection(invocation);
g_dbus_connection_call(conn,
"org.freedesktop.DBus",
"/",
"org.freedesktop.DBus",
"GetConnectionUnixProcessID",
g_variant_new("(s)", sender),
G_VARIANT_TYPE("(u)"),
G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */
NULL, /* cancellable */
recoverable_problem_file,
g_strdup(url));
g_dbus_method_invocation_return_error(invocation,
url_dispatcher_error_quark(),
ERROR_BAD_URL,
"URL '%s' is not handleable by the URL Dispatcher",
url);
return TRUE;
}
/* Handles taking an application and an URL and sending them to Upstart */
static void
pass_url_to_app (const gchar * app_id, const gchar * url)
{
g_debug("Emitting 'application-start' for APP_ID='%s' and URLS='%s'", app_id, url);
const gchar * urls[2] = {
url,
NULL
};
if (!upstart_app_launch_start_application(app_id, urls)) {
g_warning("Unable to start application '%s' with URL '%s'", app_id, url);
}
return;
}
/* Get a URL off of the bus */
static gboolean
dispatch_url_cb (GObject * skel, GDBusMethodInvocation * invocation, const gchar * url, gpointer user_data)
{
g_debug("Dispatching URL: %s", url);
if (url == NULL || url[0] == '\0') {
return bad_url(invocation, url);
}
if (dispatch_url(url)) {
g_dbus_method_invocation_return_value(invocation, NULL);
} else {
bad_url(invocation, url);
}
return TRUE;
}
/* The core of the URL handling */
gboolean
dispatch_url (const gchar * url)
{
/* Special case the app id */
GMatchInfo * appidmatch = NULL;
if (g_regex_match(appidre, url, 0, &appidmatch)) {
gchar * package = g_match_info_fetch(appidmatch, 1);
gchar * app = g_match_info_fetch(appidmatch, 2);
gchar * version = g_match_info_fetch(appidmatch, 3);
gchar * appid = NULL;
gboolean retval = FALSE;
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);
g_match_info_free(appidmatch);
return retval;
}
/* Special case the application URL */
GMatchInfo * appmatch = NULL;
if (g_regex_match(applicationre, url, 0, &appmatch)) {
gchar * appid = g_match_info_fetch(appmatch, 1);
pass_url_to_app(appid, NULL);
g_free(appid);
g_match_info_free(appmatch);
return TRUE;
}
g_match_info_free(appmatch);
/* 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;
}
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 */
/* 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;
}
/* We're goin' down cap'n */
static void
name_lost (GDBusConnection * con, const gchar * name, gpointer user_data)
{
GMainLoop * mainloop = (GMainLoop *)user_data;
g_warning("Unable to get name '%s'", name);
g_main_loop_quit(mainloop);
return;
}
/* Callback when we're connected to dbus */
static void
bus_got (GObject * obj, GAsyncResult * res, gpointer user_data)
{
GMainLoop * mainloop = (GMainLoop *)user_data;
GDBusConnection * bus = NULL;
GError * error = NULL;
bus = g_bus_get_finish(res, &error);
if (error != NULL) {
if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
g_error("Unable to connect to D-Bus: %s", error->message);
g_main_loop_quit(mainloop);
}
g_error_free(error);
return;
}
register_dbus_errors();
g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(skel), bus, "/com/canonical/URLDispatcher", &error);
if (error != NULL) {
g_error("Unable to export interface skeleton: %s", error->message);
g_main_loop_quit(mainloop);
return;
}
g_bus_own_name_on_connection(bus,
"com.canonical.URLDispatcher",
G_BUS_NAME_OWNER_FLAGS_NONE, /* flags */
NULL, /* name acquired */
name_lost,
user_data, NULL); /* user data */
g_object_unref(bus);
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);
/* 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);
skel = service_iface_com_canonical_urldispatcher_skeleton_new();
g_signal_connect(skel, "handle-dispatch-url", G_CALLBACK(dispatch_url_cb), NULL);
return TRUE;
}
/* Clean up all the globals */
gboolean
dispatcher_shutdown (void)
{
g_cancellable_cancel(cancellable);
g_object_unref(cancellable);
g_object_unref(skel);
g_regex_unref(applicationre);
g_regex_unref(appidre);
g_regex_unref(genericre);
g_regex_unref(musicfilere); /* FIXME */
g_regex_unref(videofilere); /* FIXME */
sqlite3_close(urldb);
return TRUE;
}
url-dispatcher-0.1+14.04.20140403/service/url-db.h 0000644 0000153 0177776 00000004251 12317347671 021706 0 ustar pbuser nogroup 0000000 0000000 /**
* 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__ */
url-dispatcher-0.1+14.04.20140403/service/service.c 0000644 0000153 0177776 00000002470 12317347671 022155 0 ustar pbuser nogroup 0000000 0000000 /**
* Copyright (C) 2013 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 "dispatcher.h"
GMainLoop * mainloop = NULL;
static gboolean
sig_term (gpointer user_data)
{
g_debug("SIGTERM");
g_main_loop_quit((GMainLoop *)user_data);
return G_SOURCE_CONTINUE;
}
/* Where it all begins */
int
main (int argc, char * argv[])
{
mainloop = g_main_loop_new(NULL, FALSE);
guint term_source = g_unix_signal_add(SIGTERM, sig_term, mainloop);
dispatcher_init(mainloop);
/* Run Main */
g_main_loop_run(mainloop);
/* Clean up globals */
dispatcher_shutdown();
g_source_remove(term_source);
g_main_loop_unref(mainloop);
return 0;
}
url-dispatcher-0.1+14.04.20140403/service/update-directory.c 0000644 0000153 0177776 00000013321 12317347671 023776 0 ustar pbuser nogroup 0000000 0000000 /**
* 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;
}
url-dispatcher-0.1+14.04.20140403/service/CMakeLists.txt 0000644 0000153 0177776 00000004250 12317347671 023107 0 ustar pbuser nogroup 0000000 0000000
include(UseConstantBuilder)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
###########################
# Generated Lib
###########################
set(SERVICE_GENERATED_HEADERS
service-iface.h
)
set(SERVICE_GENERATED_SOURCES
service-iface.c
)
add_gdbus_codegen(
OUTFILES SERVICE_GENERATED_SOURCES
NAME service-iface
PREFIX com.canonical.URLDispatcher.
NAMESPACE ServiceIface
SERVICE_XML ${CMAKE_CURRENT_SOURCE_DIR}/../data/com.canonical.URLDispatcher.xml
)
add_library(service-generated STATIC ${SERVICE_GENERATED_SOURCES})
target_link_libraries(service-generated
${GLIB2_LIBRARIES}
${GOBJECT2_LIBRARIES}
${GIO2_LIBRARIES}
${JSONGLIB_LIBRARIES}
)
###########################
# Dispatcher Lib
###########################
add_library(dispatcher-lib STATIC
dispatcher.h
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}
)
###########################
# Service Executable
###########################
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_executable(service-exec service.c recoverable-problem.h recoverable-problem.c)
set_target_properties(service-exec PROPERTIES OUTPUT_NAME "url-dispatcher")
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 update-directory
RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_LIBEXECDIR}/url-dispatcher"
)
url-dispatcher-0.1+14.04.20140403/service/create-db-sql.h 0000644 0000153 0177776 00000000045 12317347671 023141 0 ustar pbuser nogroup 0000000 0000000
extern const char * create_db_sql;
url-dispatcher-0.1+14.04.20140403/service/recoverable-problem.h 0000644 0000153 0177776 00000001757 12317347671 024460 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright 2013 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Authors:
* Ted Gould
*/
#include
void report_recoverable_problem (const gchar * signature,
GPid report_pid,
gboolean wait,
gchar * additional_properties[]);
url-dispatcher-0.1+14.04.20140403/service/recoverable-problem.c 0000644 0000153 0177776 00000007466 12317347671 024456 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright 2013 Canonical Ltd.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*
* Authors:
* Ted Gould
*/
#include "recoverable-problem.h"
#include
#include
#include
/* Helpers to ensure we write nicely */
static void
write_string (int fd,
const gchar *string)
{
int res;
do
res = write (fd, string, strlen (string));
while (G_UNLIKELY (res == -1 && errno == EINTR));
}
/* Make NULLs fast and fun! */
static void
write_null (int fd)
{
int res;
do
res = write (fd, "", 1);
while (G_UNLIKELY (res == -1 && errno == EINTR));
}
/* Child watcher */
static gboolean
apport_child_watch (GPid pid, gint status, gpointer user_data)
{
g_main_loop_quit((GMainLoop *)user_data);
return FALSE;
}
static gboolean
apport_child_timeout (gpointer user_data)
{
g_warning("Recoverable Error Reporter Timeout");
g_main_loop_quit((GMainLoop *)user_data);
return FALSE;
}
/* Code to report an error */
void
report_recoverable_problem (const gchar * signature, GPid report_pid, gboolean wait, gchar * additional_properties[])
{
GError * error = NULL;
gint error_stdin = 0;
GPid pid = 0;
gchar * pid_str = NULL;
gchar ** argv = NULL;
gchar * argv_nopid[2] = {
"/usr/share/apport/recoverable_problem",
NULL
};
gchar * argv_pid[4] = {
"/usr/share/apport/recoverable_problem",
"-p",
NULL, /* put pid_str when allocated here */
NULL
};
argv = (gchar **)argv_nopid;
if (report_pid != 0) {
pid_str = g_strdup_printf("%d", report_pid);
argv_pid[2] = pid_str;
argv = (gchar**)argv_pid;
}
GSpawnFlags flags = G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL;
if (wait) {
flags |= G_SPAWN_DO_NOT_REAP_CHILD;
}
g_spawn_async_with_pipes(NULL, /* cwd */
argv,
NULL, /* envp */
flags,
NULL, NULL, /* child setup func */
&pid,
&error_stdin,
NULL, /* stdout */
NULL, /* stderr */
&error);
if (error != NULL) {
g_warning("Unable to report a recoverable error: %s", error->message);
g_error_free(error);
}
gboolean first = TRUE;
if (error_stdin != 0 && signature != NULL) {
write_string(error_stdin, "DuplicateSignature");
write_null(error_stdin);
write_string(error_stdin, signature);
first = FALSE;
}
if (error_stdin != 0 && additional_properties != NULL) {
gint i;
for (i = 0; additional_properties[i] != NULL; i++) {
if (!first) {
write_null(error_stdin);
} else {
first = FALSE;
}
write_string(error_stdin, additional_properties[i]);
}
}
if (error_stdin != 0) {
close(error_stdin);
}
if (wait && pid != 0) {
GSource * child_source, * timeout_source;
GMainContext * context = g_main_context_new();
GMainLoop * loop = g_main_loop_new(context, FALSE);
child_source = g_child_watch_source_new(pid);
g_source_attach(child_source, context);
g_source_set_callback(child_source, (GSourceFunc)apport_child_watch, loop, NULL);
timeout_source = g_timeout_source_new_seconds(5);
g_source_attach(timeout_source, context);
g_source_set_callback(timeout_source, apport_child_timeout, loop, NULL);
g_main_loop_run(loop);
g_source_destroy(timeout_source);
g_source_destroy(child_source);
g_main_loop_unref(loop);
g_main_context_unref(context);
g_spawn_close_pid(pid);
}
g_free(pid_str);
return;
}
url-dispatcher-0.1+14.04.20140403/service/create-db.sql 0000644 0000153 0177776 00000000400 12317347671 022707 0 ustar pbuser nogroup 0000000 0000000 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);
url-dispatcher-0.1+14.04.20140403/data/ 0000755 0000153 0177776 00000000000 12317350137 017606 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/data/url-dispatcher-refresh.conf.in 0000644 0000153 0177776 00000001166 12317347702 025454 0 ustar pbuser nogroup 0000000 0000000 description "Ensure the URL dispatcher database is up-to-date, likely at session init"
start on started url-dispatcher
emits url-dispatcher-update
# Work around for: https://bugs.launchpad.net/upstart/+bug/1302117
umask 0022
# end work around
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
url-dispatcher-0.1+14.04.20140403/data/com.canonical.URLDispatcher.xml 0000644 0000153 0177776 00000000314 12317347671 025513 0 ustar pbuser nogroup 0000000 0000000
url-dispatcher-0.1+14.04.20140403/data/CMakeLists.txt 0000644 0000153 0177776 00000002776 12317347671 022373 0 ustar pbuser nogroup 0000000 0000000
###########################
# Dbus Interfaces
###########################
install(
FILES
com.canonical.URLDispatcher.xml
DESTINATION ${DBUSIFACEDIR}
)
###########################
# Set stuff
###########################
set(pkglibexecdir "${CMAKE_INSTALL_FULL_LIBEXECDIR}/url-dispatcher")
set(datadir "${CMAKE_INSTALL_FULL_DATADIR}")
###########################
# Upstart Job
###########################
set(DISPATCHER_UPSTART
"${CMAKE_CURRENT_BINARY_DIR}/url-dispatcher.conf"
)
configure_file("url-dispatcher.conf.in"
"${DISPATCHER_UPSTART}"
@ONLY
)
install(
FILES
"${DISPATCHER_UPSTART}"
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
)
url-dispatcher-0.1+14.04.20140403/data/url-dispatcher-update.conf.in 0000644 0000153 0177776 00000000555 12317347702 025301 0 ustar pbuser nogroup 0000000 0000000 description "URL Dispatcher Directory Watch"
# Work around for: https://bugs.launchpad.net/upstart/+bug/1302117
umask 0022
# end work around
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"
url-dispatcher-0.1+14.04.20140403/data/url-dispatcher.click-hook.in 0000644 0000153 0177776 00000000266 12317347671 025123 0 ustar pbuser nogroup 0000000 0000000 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
url-dispatcher-0.1+14.04.20140403/data/url-dispatcher.conf.in 0000644 0000153 0177776 00000000751 12317347702 024017 0 ustar pbuser nogroup 0000000 0000000 description "URL Dispatcher"
author "Ted Gould "
start on started dbus
stop on stopping dbus
respawn
# Work around for: https://bugs.launchpad.net/upstart/+bug/1302117
umask 0022
pre-start script
if [ -d "$HOME/.cache/url-dispatcher" ] && [ ! -x "$HOME/.cache/url-dispatcher" ] ; then
echo "Fixing cache directory permissions"
chmod 700 "$HOME/.cache/url-dispatcher"
fi
end script
# end work around
emits application-start
exec @pkglibexecdir@/url-dispatcher
url-dispatcher-0.1+14.04.20140403/CMakeLists.txt 0000644 0000153 0177776 00000005351 12317347671 021452 0 ustar pbuser nogroup 0000000 0000000 project(url-dispatcher C CXX)
cmake_minimum_required(VERSION 2.8.9)
option (enable_tests "Build tests" ON)
option (enable_lcov "Generate Coverage Reports" ON)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" "${CMAKE_MODULE_PATH}")
set(PACKAGE ${CMAKE_PROJECT_NAME})
set(GETTEXT_PACKAGE ${CMAKE_PROJECT_NAME})
# Trick the H10enable_coverage script into enabling coverage by including the text below:
# CMAKE_BUILD_TYPE coverage
find_package(PkgConfig REQUIRED)
include(GNUInstallDirs)
include(CheckIncludeFile)
include(CheckFunctionExists)
include(Coverage)
include(UseGlibGeneration)
include(UseGdbusCodegen)
include(UseConstantBuilder)
# Workaround for libexecdir on debian
if (EXISTS "/etc/debian_version")
set(CMAKE_INSTALL_LIBEXECDIR ${CMAKE_INSTALL_LIBDIR})
set(CMAKE_INSTALL_FULL_LIBEXECDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBEXECDIR}")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror")
pkg_check_modules(UPSTART_APP_LAUNCH REQUIRED upstart-app-launch-2)
include_directories(${UPSTART_APP_LAUNCH_INCLUDE_DIRS})
pkg_check_modules(GLIB2 REQUIRED glib-2.0)
include_directories(${GLIB2_INCLUDE_DIRS})
pkg_check_modules(GOBJECT2 REQUIRED gobject-2.0)
include_directories(${GOBJECT2_INCLUDE_DIRS})
pkg_check_modules(GIO2 REQUIRED gio-2.0)
include_directories(${GIO2_INCLUDE_DIRS})
pkg_check_modules(GIO_UNIX2 REQUIRED gio-unix-2.0)
include_directories(${GIO_UNIX2_INCLUDE_DIRS})
pkg_check_modules(JSONGLIB REQUIRED json-glib-1.0)
include_directories(${JSONGLIB_INCLUDE_DIRS})
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()
EXEC_PROGRAM(${PKG_CONFIG_EXECUTABLE} ARGS dbus-1 --variable session_bus_services_dir OUTPUT_VARIABLE DBUSSERVICEDIR )
endif()
message("Installing DBus services to ${DBUSSERVICEDIR}")
if(${LOCAL_INSTALL})
set(DBUSIFACEDIR "${CMAKE_INSTALL_DATADIR}/dbus-1/interfaces/")
else()
EXEC_PROGRAM(${PKG_CONFIG_EXECUTABLE} ARGS dbus-1 --variable interfaces_dir OUTPUT_VARIABLE DBUSIFACEDIR )
endif()
message("Installing DBus interfaces to ${DBUSIFACEDIR}")
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -fPIC")
add_subdirectory(data)
add_subdirectory(service)
add_subdirectory(liburl-dispatcher)
add_subdirectory(tools)
# testing & coverage
if (${enable_tests})
set (GTEST_SOURCE_DIR /usr/src/gtest/src)
set (GTEST_INCLUDE_DIR ${GTEST_SOURCE_DIR}/..)
set (GTEST_LIBS -lpthread)
enable_testing ()
if (${enable_lcov})
# include(GCov)
endif ()
add_subdirectory(tests)
endif ()
url-dispatcher-0.1+14.04.20140403/COPYING 0000644 0000153 0177776 00000016743 12317347671 017754 0 ustar pbuser nogroup 0000000 0000000 GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
url-dispatcher-0.1+14.04.20140403/docs/ 0000755 0000153 0177776 00000000000 12317350137 017625 5 ustar pbuser nogroup 0000000 0000000 url-dispatcher-0.1+14.04.20140403/docs/URL Dispatcher Architecture.svg 0000644 0000153 0177776 00000045110 12317347671 025474 0 ustar pbuser nogroup 0000000 0000000
url-dispatcher-0.1+14.04.20140403/README 0000644 0000153 0177776 00000000646 12317347671 017574 0 ustar pbuser nogroup 0000000 0000000 Introduction
------------
This is a small handler to take URLs and do what is appropriate with them.
That could be anything from launching a web browser to just starting an
application. This is done over DBus because application confinement doesn't
allow for doing it from a confined application otherwise. It's important
the that applications can't know about each other, so this is a fire and forget
type operation.