/*
* Copyright © 2000, 2001, 2002, 2003, 2004 Marco Pesenti Gritti
* Copyright © 2003, 2004, 2005 Christian Persch
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $Id$
*/
#include "config.h"
#include "ephy-lockdown.h"
#include "ephy-extension.h"
#include "ephy-action-helper.h"
#include "ephy-toolbar.h"
#include "ephy-prefs.h"
#include "eel-gconf-extensions.h"
#include "ephy-debug.h"
#include <gtk/gtkactiongroup.h>
#include <gtk/gtkuimanager.h>
#include <string.h>
/* Make sure these don't overlap with those in ephy-window.c and ephy-toolbar.c */
enum
{
LOCKDOWN_FLAG = 1 << 31
};
static const char * const keys [] =
{
CONF_LOCKDOWN_DISABLE_ARBITRARY_URL,
CONF_LOCKDOWN_DISABLE_BOOKMARK_EDITING,
CONF_LOCKDOWN_DISABLE_COMMAND_LINE,
CONF_LOCKDOWN_DISABLE_HISTORY,
CONF_LOCKDOWN_DISABLE_PRINTING,
CONF_LOCKDOWN_DISABLE_PRINT_SETUP,
CONF_LOCKDOWN_DISABLE_SAVE_TO_DISK,
CONF_LOCKDOWN_DISABLE_TOOLBAR_EDITING,
CONF_LOCKDOWN_FULLSCREEN
};
#define EPHY_LOCKDOWN_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_LOCKDOWN, EphyLockdownPrivate))
struct _EphyLockdownPrivate
{
guint notifier_id[G_N_ELEMENTS (keys)];
GList *windows;
};
static GObjectClass *parent_class = NULL;
static int
find_name (GtkActionGroup *action_group,
const char *name)
{
return strcmp (gtk_action_group_get_name (action_group), name);
}
static GtkActionGroup *
find_action_group (GtkUIManager *manager,
const char *name)
{
GList *list, *element;
list = gtk_ui_manager_get_action_groups (manager);
element = g_list_find_custom (list, name, (GCompareFunc) find_name);
g_return_val_if_fail (element != NULL, NULL);
return GTK_ACTION_GROUP (element->data);
}
static void
update_location_editable (EphyWindow *window,
GtkAction *action,
gboolean editable)
{
EphyTab *tab;
EphyEmbed *embed;
GtkWidget *toolbar;
char *address;
g_object_set (action, "editable", editable, NULL);
/* Restore the real web page address when disabling entry */
if (editable == FALSE)
{
toolbar = ephy_window_get_toolbar (window);
tab = ephy_window_get_active_tab (window);
/* embed is NULL on startup */
if (tab != NULL)
{
embed = ephy_tab_get_embed (tab);
g_return_if_fail (embed != NULL);
address = ephy_embed_get_location (embed, TRUE);
ephy_toolbar_set_location (EPHY_TOOLBAR (toolbar), address, NULL);
ephy_tab_set_typed_address (tab, NULL,
EPHY_TAB_ADDRESS_EXPIRE_CURRENT);
g_free (address);
}
}
}
/* NOTE: If you bring more actions under lockdown control, make sure
* that all sensitivity updates on them are done using the helpers!
*/
static void
update_window (EphyWindow *window,
EphyLockdown *lockdown)
{
GtkUIManager *manager;
GtkActionGroup *action_group, *popups_action_group, *toolbar_action_group;
GtkAction *action;
gboolean disabled, fullscreen, print_setup_disabled, writable;
LOG ("Updating window %p", window);
manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (window));
action_group = find_action_group (manager, "WindowActions");
popups_action_group = find_action_group (manager, "PopupsActions");
toolbar_action_group = find_action_group (manager, "SpecialToolbarActions");
g_return_if_fail (action_group != NULL && popups_action_group != NULL && toolbar_action_group != NULL);
disabled = eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_PRINTING);
print_setup_disabled = eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_PRINT_SETUP) ||
eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_COMMAND_LINE);
action = gtk_action_group_get_action (action_group, "FilePrintSetup");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled || print_setup_disabled);
action = gtk_action_group_get_action (action_group, "FilePrintPreview");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
action = gtk_action_group_get_action (action_group, "FilePrint");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
writable = eel_gconf_key_is_writable (CONF_WINDOWS_SHOW_TOOLBARS);
action = gtk_action_group_get_action (action_group, "ViewToolbar");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, !writable);
writable = eel_gconf_key_is_writable (CONF_WINDOWS_SHOW_STATUSBAR);
action = gtk_action_group_get_action (action_group, "ViewStatusbar");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, !writable);
disabled = eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_ARBITRARY_URL);
action = gtk_action_group_get_action (action_group, "GoLocation");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
action = gtk_action_group_get_action (toolbar_action_group, "Location");
update_location_editable (window, action, !disabled);
action = gtk_action_group_get_action (toolbar_action_group, "NavigationUp");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
disabled = eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_HISTORY);
action = gtk_action_group_get_action (action_group, "GoHistory");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
action = gtk_action_group_get_action (toolbar_action_group, "NavigationBack");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
action = gtk_action_group_get_action (toolbar_action_group, "NavigationForward");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
disabled = eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_BOOKMARK_EDITING);
action = gtk_action_group_get_action (action_group, "GoBookmarks");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
action = gtk_action_group_get_action (action_group, "FileBookmarkPage");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
action = gtk_action_group_get_action (popups_action_group, "ContextBookmarkPage");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
action = gtk_action_group_get_action (popups_action_group, "BookmarkLink");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
disabled = eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_SAVE_TO_DISK);
action = gtk_action_group_get_action (action_group, "FileSaveAs");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
action = gtk_action_group_get_action (popups_action_group, "DownloadLink");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
action = gtk_action_group_get_action (popups_action_group, "DownloadLinkAs");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
action = gtk_action_group_get_action (popups_action_group, "SaveImageAs");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
action = gtk_action_group_get_action (popups_action_group, "OpenImage");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
writable = eel_gconf_key_is_writable (CONF_DESKTOP_BG_PICTURE);
action = gtk_action_group_get_action (popups_action_group, "SetImageAsBackground");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled || !writable);
disabled = eel_gconf_get_boolean (CONF_LOCKDOWN_DISABLE_TOOLBAR_EDITING);
action = gtk_action_group_get_action (action_group, "ViewToolbarEditor");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, disabled);
fullscreen = eel_gconf_get_boolean (CONF_LOCKDOWN_FULLSCREEN);
action = gtk_action_group_get_action (toolbar_action_group, "FileNewWindow");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, fullscreen);
action = gtk_action_group_get_action (action_group, "ViewFullscreen");
ephy_action_change_sensitivity_flags (action, LOCKDOWN_FLAG, fullscreen);
if (fullscreen)
{
gtk_window_fullscreen (GTK_WINDOW (window));
}
}
static void
notifier (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
EphyLockdown *lockdown)
{
EphyLockdownPrivate *priv = lockdown->priv;
LOG ("Key %s changed", entry->key);
g_list_foreach (priv->windows, (GFunc) update_window, lockdown);
}
static void
ephy_lockdown_init (EphyLockdown *lockdown)
{
EphyLockdownPrivate *priv;
guint i;
lockdown->priv = priv = EPHY_LOCKDOWN_GET_PRIVATE (lockdown);
LOG ("EphyLockdown initialising");
for (i = 0; i < G_N_ELEMENTS (keys); i++)
{
priv->notifier_id[i] =eel_gconf_notification_add
(keys[i], (GConfClientNotifyFunc) notifier, lockdown);
}
/* We know that no windows are open yet,
* so we don't need to do notify here.
*/
eel_gconf_monitor_add ("/apps/epiphany/lockdown");
eel_gconf_monitor_add ("/desktop/gnome/lockdown");
}
static void
ephy_lockdown_finalize (GObject *object)
{
EphyLockdown *lockdown = EPHY_LOCKDOWN (object);
EphyLockdownPrivate *priv = lockdown->priv;
guint i;
LOG ("EphyLockdown finalising");
eel_gconf_monitor_remove ("/apps/epiphany/lockdown");
eel_gconf_monitor_remove ("/desktop/gnome/lockdown");
for (i = 0; i < G_N_ELEMENTS (keys); i++)
{
eel_gconf_notification_remove (priv->notifier_id[i]);
}
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
impl_attach_window (EphyExtension *extension,
EphyWindow *window)
{
EphyLockdown *lockdown = EPHY_LOCKDOWN (extension);
EphyLockdownPrivate *priv = lockdown->priv;
priv->windows = g_list_prepend (priv->windows, window);
update_window (window, lockdown);
}
static void
impl_detach_window (EphyExtension *extension,
EphyWindow *window)
{
EphyLockdown *lockdown = EPHY_LOCKDOWN (extension);
EphyLockdownPrivate *priv = lockdown->priv;
priv->windows = g_list_remove (priv->windows, window);
/* Since we know that the window closes now, we don't have to
* undo anything.
*/
}
static void
ephy_lockdown_iface_init (EphyExtensionIface *iface)
{
iface->attach_window = impl_attach_window;
iface->detach_window = impl_detach_window;
}
static void
ephy_lockdown_class_init (EphyLockdownClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
parent_class = (GObjectClass *) g_type_class_peek_parent (klass);
object_class->finalize = ephy_lockdown_finalize;
g_type_class_add_private (object_class, sizeof (EphyLockdownPrivate));
}
GType
ephy_lockdown_get_type (void)
{
static GType type = 0;
if (G_UNLIKELY (type == 0))
{
const GTypeInfo our_info =
{
sizeof (EphyLockdownClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) ephy_lockdown_class_init,
NULL,
NULL, /* class_data */
sizeof (EphyLockdown),
0, /* n_preallocs */
(GInstanceInitFunc) ephy_lockdown_init
};
const GInterfaceInfo extension_info =
{
(GInterfaceInitFunc) ephy_lockdown_iface_init,
NULL,
NULL
};
type = g_type_register_static (G_TYPE_OBJECT,
"EphyLockdown",
&our_info, 0);
g_type_add_interface_static (type,
EPHY_TYPE_EXTENSION,
&extension_info);
}
return type;
}