Ejemplo n.º 1
0
static void
migrate_cookies ()
{
  const char *cookies_file_sqlite = "cookies.sqlite";
  const char *cookies_file_txt = "cookies.txt";
  char *src_sqlite = NULL, *src_txt = NULL, *dest = NULL;

  dest = g_build_filename (ephy_dot_dir (), cookies_file_sqlite, NULL);
  /* If we already have a cookies.sqlite file, do nothing */
  if (g_file_test (dest, G_FILE_TEST_EXISTS))
    goto out;

  src_sqlite = g_build_filename (ephy_dot_dir (), "mozilla",
                                 "epiphany", cookies_file_sqlite, NULL);
  src_txt = g_build_filename (ephy_dot_dir (), "mozilla",
                              "epiphany", cookies_file_txt, NULL);

  /* First check if we have a cookies.sqlite file in Mozilla */
  if (g_file_test (src_sqlite, G_FILE_TEST_EXISTS)) {
    GFile *gsrc, *gdest;

    /* Copy the file */
    gsrc = g_file_new_for_path (src_sqlite);
    gdest = g_file_new_for_path (dest);

    if (!g_file_copy (gsrc, gdest, 0, NULL, NULL, NULL, NULL))
      g_warning (_("Failed to copy cookies file from Mozilla."));

    g_object_unref (gsrc);
    g_object_unref (gdest);
  } else if (g_file_test (src_txt, G_FILE_TEST_EXISTS)) {
    /* Create a SoupCookieJarSQLite with the contents of the txt file */
    GSList *cookies, *p;
    SoupCookieJar *txt, *sqlite;

    txt = soup_cookie_jar_text_new (src_txt, TRUE);
    sqlite = soup_cookie_jar_sqlite_new (dest, FALSE);
    cookies = soup_cookie_jar_all_cookies (txt);

    for (p = cookies; p; p = p->next) {
      SoupCookie *cookie = (SoupCookie*)p->data;
      /* Cookie is stolen, so we won't free it */
      soup_cookie_jar_add_cookie (sqlite, cookie);
    }

    g_slist_free (cookies);
    g_object_unref (txt);
    g_object_unref (sqlite);
  }

 out:
  g_free (src_sqlite);
  g_free (src_txt);
  g_free (dest);
}
Ejemplo n.º 2
0
static void
migrate_passwords2 ()
{
#ifdef ENABLE_NSS
  char *dest, *contents;
  gsize length;
  GError *error = NULL;

  dest = g_build_filename (ephy_dot_dir (),
                           "gecko-passwords.txt",
                           NULL);
  if (!g_file_test (dest, G_FILE_TEST_EXISTS)) {
    g_free (dest);
    return;
  }

  if (!ephy_nss_glue_init ())
    return;

  if (!g_file_get_contents (dest, &contents, &length, &error)) {
    g_free (dest);
  }

  parse_and_decrypt_signons (contents, TRUE);
  g_free (contents);

  ephy_nss_glue_close ();
#endif
}
Ejemplo n.º 3
0
/**
 * ephy_embed_shell_get_print_settings:
 * @shell: the #EphyEmbedShell
 *
 * Gets the global #GtkPrintSettings object.
 *
 * Returns: (transfer none): a #GtkPrintSettings object
 **/
GtkPrintSettings *
ephy_embed_shell_get_print_settings (EphyEmbedShell *shell)
{
  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);

  g_return_val_if_fail (EPHY_IS_EMBED_SHELL (shell), NULL);

  if (priv->print_settings == NULL) {
    GError *error = NULL;
    char *path;

    path = g_build_filename (ephy_dot_dir (), PRINT_SETTINGS_FILENAME, NULL);
    priv->print_settings = gtk_print_settings_new_from_file (path, &error);
    g_free (path);

    /* Note: the gtk print settings file format is the same as our
     * legacy one, so no need to migrate here.
     */

    if (priv->print_settings == NULL)
      priv->print_settings = gtk_print_settings_new ();
  }

  return priv->print_settings;
}
Ejemplo n.º 4
0
/**
 * ephy_embed_shell_get_page_setup:
 *
 * Return value: (transfer none):
 **/
GtkPageSetup *
ephy_embed_shell_get_page_setup (EphyEmbedShell *shell)
{
  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);

  g_return_val_if_fail (EPHY_IS_EMBED_SHELL (shell), NULL);

  if (priv->page_setup == NULL) {
    GError *error = NULL;
    char *path;

    path = g_build_filename (ephy_dot_dir (), PAGE_SETUP_FILENAME, NULL);
    priv->page_setup = gtk_page_setup_new_from_file (path, &error);
    g_free (path);

    if (error)
      g_error_free (error);

    /* If that still didn't work, create a new, empty one */
    if (priv->page_setup == NULL)
      priv->page_setup = gtk_page_setup_new ();
  }

  return priv->page_setup;
}
Ejemplo n.º 5
0
static GFile *
get_session_file (const char *filename)
{
	GFile *file;
	char *path;

	if (filename == NULL)
	{
		return NULL;
	}

	if (strcmp (filename, SESSION_STATE) == 0)
	{
		path = g_build_filename (ephy_dot_dir (),
					 "session_state.xml",
					 NULL);
	}
	else
	{
		path = g_strdup (filename);
	}

	file = g_file_new_for_path (path);
	g_free (path);

	return file;
}
Ejemplo n.º 6
0
/**
 * ephy_embed_shell_get_global_history_service:
 * @shell: the #EphyEmbedShell
 *
 * Return value: (transfer none): the global #EphyHistoryService
 **/
GObject *
ephy_embed_shell_get_global_history_service (EphyEmbedShell *shell)
{
  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);

  g_return_val_if_fail (EPHY_IS_EMBED_SHELL (shell), NULL);

  if (priv->global_history_service == NULL) {
    char *filename;

    filename = g_build_filename (ephy_dot_dir (), EPHY_HISTORY_FILE, NULL);
    priv->global_history_service = ephy_history_service_new (filename,
                                                             priv->mode == EPHY_EMBED_SHELL_MODE_INCOGNITO);
    g_free (filename);
    g_return_val_if_fail (priv->global_history_service, NULL);
    g_signal_connect (priv->global_history_service, "urls-visited",
                      G_CALLBACK (history_service_urls_visited_cb),
                      shell);
    g_signal_connect (priv->global_history_service, "url-title-changed",
                      G_CALLBACK (history_service_url_title_changed_cb),
                      shell);
    g_signal_connect (priv->global_history_service, "url-deleted",
                      G_CALLBACK (history_service_url_deleted_cb),
                      shell);
    g_signal_connect (priv->global_history_service, "host-deleted",
                      G_CALLBACK (history_service_host_deleted_cb),
                      shell);
    g_signal_connect (priv->global_history_service, "cleared",
                      G_CALLBACK (history_service_cleared_cb),
                      shell);
  }

  return G_OBJECT (priv->global_history_service);
}
Ejemplo n.º 7
0
static void
migrate_passwords ()
{
#ifdef ENABLE_NSS
  char *dest, *contents, *gecko_passwords_backup;
  gsize length;
  GError *error = NULL;

  dest = g_build_filename (ephy_dot_dir (),
                           "mozilla", "epiphany", "signons3.txt",
                           NULL);
  if (!g_file_test (dest, G_FILE_TEST_EXISTS)) {
    g_free (dest);
    dest = g_build_filename (ephy_dot_dir (),
                             "mozilla", "epiphany", "signons2.txt",
                             NULL);
    if (!g_file_test (dest, G_FILE_TEST_EXISTS)) {
      g_free (dest);
      return;
    }
  }

  if (!ephy_nss_glue_init ())
    return;

  if (!g_file_get_contents (dest, &contents, &length, &error)) {
    g_free (dest);
  }

  parse_and_decrypt_signons (contents, FALSE);

  /* Save the contents in a backup directory for future data
     extraction when we support more features */
  gecko_passwords_backup = g_build_filename (ephy_dot_dir (),
                                             "gecko-passwords.txt", NULL);

  if (!g_file_set_contents (gecko_passwords_backup, contents,
                            -1, &error)) {
    g_error_free (error);
  }

  g_free (gecko_passwords_backup);
  g_free (contents);

  ephy_nss_glue_close ();
#endif
}
Ejemplo n.º 8
0
gboolean
ephy_profile_utils_set_migration_version (int version)
{
    char *migrated_file, *contents;
    gboolean result = FALSE;

    migrated_file = g_build_filename (ephy_dot_dir (),
                                      PROFILE_MIGRATION_FILE,
                                      NULL);
    contents = g_strdup_printf ("%d", version);
    result = g_file_set_contents (migrated_file, contents, -1, NULL);

    if (result == FALSE)
        LOG ("Couldn't store migration version %d in %s (%s, %s)",
             version, migrated_file, ephy_dot_dir (), PROFILE_MIGRATION_FILE);

    g_free (contents);
    g_free (migrated_file);

    return result;
}
Ejemplo n.º 9
0
static void
ephy_embed_shell_create_web_context (EphyEmbedShell *embed_shell)
{
  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (embed_shell);
  WebKitWebsiteDataManager *manager;
  char *data_dir;
  char *cache_dir;

  data_dir = g_build_filename (EPHY_EMBED_SHELL_MODE_HAS_PRIVATE_PROFILE (priv->mode) ?
                               ephy_dot_dir () : g_get_user_data_dir (),
                               g_get_prgname (), NULL);
  cache_dir = g_build_filename (EPHY_EMBED_SHELL_MODE_HAS_PRIVATE_PROFILE (priv->mode) ?
                                ephy_dot_dir () : g_get_user_cache_dir (),
                                g_get_prgname (), NULL);

  manager = webkit_website_data_manager_new ("base-data-directory", data_dir,
                                             "base-cache-directory", cache_dir,
                                             NULL);
  g_free (data_dir);
  g_free (cache_dir);

  priv->web_context = webkit_web_context_new_with_website_data_manager (manager);
  g_object_unref (manager);
}
Ejemplo n.º 10
0
static SoupCookieJar *get_current_cookie_jar ()
{
  char *filename;
  SoupCookieJar *jar;

  /* FIXME: There's no API in WebKit2 to get all cookies, so we create a
   * temp read-only jar for the current cookies to read from it.
   * It would be better to have an API in WebKit to get the cookies instead.
   */
  filename = g_build_filename (ephy_dot_dir (), "cookies.sqlite", NULL);
  jar = (SoupCookieJar*)soup_cookie_jar_sqlite_new (filename, TRUE);
  g_free (filename);

  return jar;
}
Ejemplo n.º 11
0
static void
clear_bookmark_files (void)
{
  GFile *file;
  char *path;
  guint i;

  for (i = 0; i < G_N_ELEMENTS (bookmarks_paths); i++) {
    path = g_build_filename (ephy_dot_dir (),
                             bookmarks_paths[i],
                             NULL);
    file = g_file_new_for_path (path);
    g_file_delete (file, NULL, NULL);
    g_object_unref (file);
    g_free (path);
  }
}
Ejemplo n.º 12
0
static void
initialize_web_extensions (WebKitWebContext* web_context,
                           EphyEmbedShell *shell)
{
  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
  GVariant *user_data;
  gboolean private_profile;
  char *web_extension_id;
  static guint web_extension_count = 0;

  webkit_web_context_set_web_extensions_directory (web_context, EPHY_WEB_EXTENSIONS_DIR);

  web_extension_id = g_strdup_printf ("%u-%u", getpid (), ++web_extension_count);
  ephy_embed_shell_watch_web_extension (shell, web_extension_id);

  private_profile = EPHY_EMBED_SHELL_MODE_HAS_PRIVATE_PROFILE (priv->mode);
  user_data = g_variant_new ("(ssb)", web_extension_id, ephy_dot_dir (), private_profile);
  webkit_web_context_set_web_extensions_initialization_user_data (web_context, user_data);
}
Ejemplo n.º 13
0
/**
 * ephy_embed_shell_set_print_settings:
 * @shell: the #EphyEmbedShell
 * @settings: the new #GtkPrintSettings object
 *
 * Sets the global #GtkPrintSettings object.
 *
 **/
void
ephy_embed_shell_set_print_settings (EphyEmbedShell *shell,
                                     GtkPrintSettings *settings)
{
  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
  char *path;

  g_return_if_fail (EPHY_IS_EMBED_SHELL (shell));

  if (settings != NULL)
    g_object_ref (settings);

  if (priv->print_settings != NULL)
    g_object_unref (priv->print_settings);

  priv->print_settings = settings ? settings : gtk_print_settings_new ();

  path = g_build_filename (ephy_dot_dir (), PRINT_SETTINGS_FILENAME, NULL);
  gtk_print_settings_to_file (settings, path, NULL);
  g_free (path);
}
Ejemplo n.º 14
0
void
ephy_embed_shell_set_page_setup (EphyEmbedShell *shell,
                                 GtkPageSetup *page_setup)
{
  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
  char *path;

  g_return_if_fail (EPHY_IS_EMBED_SHELL (shell));

  if (page_setup != NULL)
    g_object_ref (page_setup);
  else
    page_setup = gtk_page_setup_new ();

  if (priv->page_setup != NULL)
    g_object_unref (priv->page_setup);

  priv->page_setup = page_setup;

  path = g_build_filename (ephy_dot_dir (), PAGE_SETUP_FILENAME, NULL);
  gtk_page_setup_to_file (page_setup, path, NULL);
  g_free (path);
}
Ejemplo n.º 15
0
/**
 * ephy_web_application_get_profile_directory:
 * @name: the application name
 *
 * Gets the directory where the profile for @name is meant to be stored.
 *
 * Returns: (transfer full): A newly allocated string.
 **/
char *
ephy_web_application_get_profile_directory (const char *name)
{
  char *app_dir, *wm_class, *profile_dir, *encoded;
  GError *error = NULL;

  wm_class = get_wm_class_from_app_title (name);
  encoded = g_filename_from_utf8 (wm_class, -1, NULL, NULL, &error);
  g_free (wm_class);

  if (error) {
    g_warning ("%s", error->message);
    g_error_free (error);
    return NULL;
  }

  app_dir = g_strconcat (EPHY_WEB_APP_PREFIX, encoded, NULL);
  profile_dir = g_build_filename (ephy_dot_dir (), app_dir, NULL);
  g_free (encoded);
  g_free (app_dir);

  return profile_dir;
}
Ejemplo n.º 16
0
static void
webkit_pref_callback_user_stylesheet (GSettings  *settings,
                                      const char *key,
                                      gpointer    data)
{
  gboolean value;

  value = g_settings_get_boolean (settings, key);

  if (!value)
    webkit_user_content_manager_remove_all_style_sheets (WEBKIT_USER_CONTENT_MANAGER (ephy_embed_shell_get_user_content_manager (ephy_embed_shell_get_default ())));
  else {
    GFile *file;
    char *filename;

    filename = g_build_filename (ephy_dot_dir (), USER_STYLESHEET_FILENAME, NULL);
    file = g_file_new_for_path (filename);
    g_free (filename);

    g_file_read_async (file, G_PRIORITY_DEFAULT, NULL,
                       (GAsyncReadyCallback)user_style_seet_read_cb, NULL);
    g_object_unref (file);
  }
}
Ejemplo n.º 17
0
int
ephy_profile_utils_get_migration_version (void)
{
    char *migrated_file, *contents = NULL;
    gsize size;
    int result = 0;
    int latest = 0;

    migrated_file = g_build_filename (ephy_dot_dir (),
                                      PROFILE_MIGRATION_FILE,
                                      NULL);

    if (g_file_test (migrated_file, G_FILE_TEST_EXISTS)) {
        g_file_get_contents (migrated_file, &contents, &size, NULL);

        if (contents != NULL)
            result = sscanf (contents, "%d", &latest);

        g_free (contents);

        if (result != 1)
            latest = 0;
    } else if (ephy_dot_dir_is_default () == FALSE) {
        /* Since version 8, we need to migrate also profile directories
           other than the default one. Profiles in such directories work
           perfectly fine without going through the first 7 migration
           steps, so it is safe to assume that any non-default profile
           directory without a migration file can be migrated starting
           from the step 8. */
        latest = 7;
    }

    g_free (migrated_file);

    return latest;
}
Ejemplo n.º 18
0
static void
migrate_history ()
{
  GFileInputStream *input;
  GMarkupParseContext *context;
  GError *error = NULL;
  GFile *file;
  char *filename;
  char buffer[1024];
  HistoryParseData parse_data;

  gchar *temporary_file = g_build_filename (ephy_dot_dir (), "ephy-history.db", NULL);
  /* Do nothing if the history file already exists. Safer than wiping
   * it out. */
  if (g_file_test (temporary_file, G_FILE_TEST_EXISTS)) {
    g_warning ("Did not migrate Epiphany's history, the ephy-history.db file already exists");
    g_free (temporary_file);
    return;
  }

  history_service = ephy_history_service_new (temporary_file);
  g_free (temporary_file);

  memset (&parse_data, 0, sizeof (HistoryParseData));
  parse_data.location = NULL;
  parse_data.title = NULL;
  parse_data.visits = NULL;

  filename = g_build_filename (ephy_dot_dir (),
                               "ephy-history.xml",
                               NULL);

  file = g_file_new_for_path (filename);
  g_free (filename);

  input = g_file_read (file, NULL, &error);
  g_object_unref (file);

  if (error) {
    if (error->code != G_IO_ERROR_NOT_FOUND)
      g_warning ("Could not load Epiphany history data, migration aborted: %s", error->message);

    g_error_free (error);
    return;
  }

  context = g_markup_parse_context_new (&history_parse_funcs, 0, &parse_data, NULL);
  while (TRUE) {
    gssize count = g_input_stream_read (G_INPUT_STREAM (input), buffer, sizeof (buffer), NULL, &error);
    if (count <= 0)
      break;

    if (!g_markup_parse_context_parse (context, buffer, count, &error))
      break;
  }

  g_markup_parse_context_free (context);
  g_input_stream_close (G_INPUT_STREAM (input), NULL, NULL);
  g_object_unref (input);

  if (parse_data.visits) {
    ephy_history_service_add_visits (history_service, parse_data.visits, NULL, (EphyHistoryJobCallback)visit_cb, NULL);
    ephy_history_page_visit_list_free (parse_data.visits);

    while (!all_done)
      g_main_context_iteration (NULL, FALSE);
  }

  g_object_unref (history_service);
}
Ejemplo n.º 19
0
static void
ephy_embed_shell_startup (GApplication* application)
{
  EphyEmbedShell *shell = EPHY_EMBED_SHELL (application);
  EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
  char *favicon_db_path;
  WebKitCookieManager *cookie_manager;
  char *filename;
  char *cookie_policy;

  G_APPLICATION_CLASS (ephy_embed_shell_parent_class)->startup (application);

  /* We're not remoting, setup the Web Context if we are not running in a test.
     Tests already do this after construction. */
  if (priv->mode != EPHY_EMBED_SHELL_MODE_TEST)
    ephy_embed_shell_create_web_context (embed_shell);

  ephy_embed_shell_setup_web_extensions_connection (shell);

  /* User content manager */
  if (priv->mode != EPHY_EMBED_SHELL_MODE_TEST)
    priv->user_content = webkit_user_content_manager_new ();

  webkit_user_content_manager_register_script_message_handler (priv->user_content,
                                                               "overview");
  g_signal_connect (priv->user_content, "script-message-received::overview",
                    G_CALLBACK (web_extension_overview_message_received_cb),
                    shell);

  webkit_user_content_manager_register_script_message_handler (priv->user_content,
                                                               "tlsErrorPage");
  g_signal_connect (priv->user_content, "script-message-received::tlsErrorPage",
                    G_CALLBACK (web_extension_tls_error_page_message_received_cb),
                    shell);

  webkit_user_content_manager_register_script_message_handler (priv->user_content,
                                                               "formAuthData");
  g_signal_connect (priv->user_content, "script-message-received::formAuthData",
                    G_CALLBACK (web_extension_form_auth_data_message_received_cb),
                    shell);

  webkit_user_content_manager_register_script_message_handler (priv->user_content,
                                                               "aboutApps");
  g_signal_connect (priv->user_content, "script-message-received::aboutApps",
                    G_CALLBACK (web_extension_about_apps_message_received_cb),
                    shell);

  ephy_embed_shell_setup_process_model (shell);
  g_signal_connect (priv->web_context, "initialize-web-extensions",
                    G_CALLBACK (initialize_web_extensions),
                    shell);

  /* Favicon Database */
  favicon_db_path = g_build_filename (EPHY_EMBED_SHELL_MODE_HAS_PRIVATE_PROFILE (priv->mode) ?
                                      ephy_dot_dir () : g_get_user_cache_dir (),
                                      "icondatabase", NULL);
  webkit_web_context_set_favicon_database_directory (priv->web_context, favicon_db_path);
  g_free (favicon_db_path);

  /* Do not ignore TLS errors. */
  webkit_web_context_set_tls_errors_policy (priv->web_context, WEBKIT_TLS_ERRORS_POLICY_FAIL);


  /* about: URIs handler */
  priv->about_handler = ephy_about_handler_new ();
  webkit_web_context_register_uri_scheme (priv->web_context,
                                          EPHY_ABOUT_SCHEME,
                                          (WebKitURISchemeRequestCallback)about_request_cb,
                                          shell, NULL);

  /* Register about scheme as local so that it can contain file resources */
  webkit_security_manager_register_uri_scheme_as_local (webkit_web_context_get_security_manager (priv->web_context),
                                                        EPHY_ABOUT_SCHEME);

  /* ephy-resource handler */
  webkit_web_context_register_uri_scheme (priv->web_context, "ephy-resource",
                                          (WebKitURISchemeRequestCallback)ephy_resource_request_cb,
                                          NULL, NULL);

  /* Store cookies in moz-compatible SQLite format */
  cookie_manager = webkit_web_context_get_cookie_manager (priv->web_context);
  filename = g_build_filename (ephy_dot_dir (), "cookies.sqlite", NULL);
  webkit_cookie_manager_set_persistent_storage (cookie_manager, filename,
                                                WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE);
  g_free (filename);

  cookie_policy = g_settings_get_string (EPHY_SETTINGS_WEB,
                                         EPHY_PREFS_WEB_COOKIES_POLICY);
  ephy_embed_prefs_set_cookie_accept_policy (cookie_manager, cookie_policy);
  g_free (cookie_policy);
}
Ejemplo n.º 20
0
/**
 * ephy_web_application_get_application_list:
 *
 * Gets a list of the currently installed web applications.
 * Free the returned GList with
 * ephy_web_application_free_application_list.
 *
 * Returns: (transfer-full): a #GList of #EphyWebApplication objects
 **/
GList *
ephy_web_application_get_application_list ()
{
  GFileEnumerator *children = NULL;
  GFileInfo *info;
  GList *applications = NULL;
  GFile *dot_dir;

  dot_dir = g_file_new_for_path (ephy_dot_dir ());
  children = g_file_enumerate_children (dot_dir,
                                        "standard::name",
                                        0, NULL, NULL);
  g_object_unref (dot_dir);

  info = g_file_enumerator_next_file (children, NULL, NULL);
  while (info) {
    EphyWebApplication *app;
    const char *name;
    glong prefix_length = g_utf8_strlen (EPHY_WEB_APP_PREFIX, -1);

    name = g_file_info_get_name (info);
    if (g_str_has_prefix (name, EPHY_WEB_APP_PREFIX)) {
      char *profile_dir;
      guint64 created;
      GDate *date;
      char *desktop_file, *desktop_file_path;
      char *contents;
      GFileInfo *desktop_info;

      app = g_slice_new0 (EphyWebApplication);

      profile_dir = g_build_filename (ephy_dot_dir (), name, NULL);
      app->icon_url = g_build_filename (profile_dir, EPHY_WEB_APP_ICON_NAME, NULL);

      desktop_file = g_strconcat (name + prefix_length, ".desktop", NULL);
      desktop_file_path = g_build_filename (profile_dir, desktop_file, NULL);
      app->desktop_file = g_strdup (desktop_file);

      if (g_file_get_contents (desktop_file_path, &contents, NULL, NULL)) {
        char *exec;
        char **strings;
        GKeyFile *key;
        int i;
        GFile *file;

        key = g_key_file_new ();
        g_key_file_load_from_data (key, contents, -1, 0, NULL);
        app->name = g_key_file_get_string (key, "Desktop Entry", "Name", NULL);
        exec = g_key_file_get_string (key, "Desktop Entry", "Exec", NULL);
        strings = g_strsplit (exec, " ", -1);

        for (i = 0; strings[i]; i++);
        app->url = g_strdup (strings[i - 1]);

        g_strfreev (strings);
        g_free (exec);
        g_key_file_free (key);

        file = g_file_new_for_path (desktop_file_path);

        /* FIXME: this should use TIME_CREATED but it does not seem to be working. */
        desktop_info = g_file_query_info (file, G_FILE_ATTRIBUTE_TIME_MODIFIED, 0, NULL, NULL);
        created = g_file_info_get_attribute_uint64 (desktop_info, G_FILE_ATTRIBUTE_TIME_MODIFIED);

        date = g_date_new ();
        g_date_set_time_t (date, (time_t)created);
        g_date_strftime (app->install_date, 127, "%x", date);

        g_date_free (date);
        g_object_unref (file);
        g_object_unref (desktop_info);

        applications = g_list_append (applications, app);
      }

      g_free (contents);
      g_free (desktop_file);
      g_free (profile_dir);
      g_free (desktop_file_path);
    }

    g_object_unref (info);

    info = g_file_enumerator_next_file (children, NULL, NULL);
  }

  g_object_unref (children);

  return applications;
}
static char *
get_script_dir (void)
{
	return g_build_filename (ephy_dot_dir (), "extensions", "data",
				 "greasemonkey", NULL);
}