Commit 28a84367 authored by Carlos Garcia Campos's avatar Carlos Garcia Campos Committed by Carlos Garcia Campos

Add automation mode

parent d8767ea1
Pipeline #49039 passed with stage
in 8 minutes and 21 seconds
...@@ -37,6 +37,9 @@ Start a private instance (temporary profile directory, not private browsing mode ...@@ -37,6 +37,9 @@ Start a private instance (temporary profile directory, not private browsing mode
\fB\-\-incognito\-mode\fR \fB\-\-incognito\-mode\fR
Start a private instance in incognito mode Start a private instance in incognito mode
.TP .TP
\fB\-\-automation\-mode\fR
Start the browser in automation mode, for WebDriver control
.TP
\fB\-\-profile\fR=\fIFILE\fR \fB\-\-profile\fR=\fIFILE\fR
Profile directory to use in the private instance Profile directory to use in the private instance
.TP .TP
......
...@@ -165,3 +165,22 @@ ephy_embed_container_get_is_popup (EphyEmbedContainer *container) ...@@ -165,3 +165,22 @@ ephy_embed_container_get_is_popup (EphyEmbedContainer *container)
iface = EPHY_EMBED_CONTAINER_GET_IFACE (container); iface = EPHY_EMBED_CONTAINER_GET_IFACE (container);
return iface->get_is_popup (container); return iface->get_is_popup (container);
} }
/**
* ephy_embed_container_get_n_children:
* @container: a #EphyEmbedContainer
*
* Returns the number of #EphyEmbed:s in the container.
*
* Returns: the number of children
*/
guint
ephy_embed_container_get_n_children (EphyEmbedContainer *container)
{
EphyEmbedContainerInterface *iface;
g_assert (EPHY_IS_EMBED_CONTAINER (container));
iface = EPHY_EMBED_CONTAINER_GET_IFACE (container);
return iface->get_n_children (container);
}
...@@ -52,6 +52,8 @@ struct _EphyEmbedContainerInterface ...@@ -52,6 +52,8 @@ struct _EphyEmbedContainerInterface
GList * (* get_children) (EphyEmbedContainer *container); GList * (* get_children) (EphyEmbedContainer *container);
gboolean (* get_is_popup) (EphyEmbedContainer *container); gboolean (* get_is_popup) (EphyEmbedContainer *container);
guint (* get_n_children) (EphyEmbedContainer *container);
}; };
gint ephy_embed_container_add_child (EphyEmbedContainer *container, gint ephy_embed_container_add_child (EphyEmbedContainer *container,
...@@ -65,5 +67,6 @@ void ephy_embed_container_remove_child (EphyEmbedContainer *con ...@@ -65,5 +67,6 @@ void ephy_embed_container_remove_child (EphyEmbedContainer *con
EphyEmbed * ephy_embed_container_get_active_child (EphyEmbedContainer *container); EphyEmbed * ephy_embed_container_get_active_child (EphyEmbedContainer *container);
GList * ephy_embed_container_get_children (EphyEmbedContainer *container); GList * ephy_embed_container_get_children (EphyEmbedContainer *container);
gboolean ephy_embed_container_get_is_popup (EphyEmbedContainer *container); gboolean ephy_embed_container_get_is_popup (EphyEmbedContainer *container);
guint ephy_embed_container_get_n_children (EphyEmbedContainer *container);
G_END_DECLS G_END_DECLS
...@@ -756,6 +756,7 @@ ephy_embed_shell_get_global_history_service (EphyEmbedShell *shell) ...@@ -756,6 +756,7 @@ ephy_embed_shell_get_global_history_service (EphyEmbedShell *shell)
EphySQLiteConnectionMode mode; EphySQLiteConnectionMode mode;
if (priv->mode == EPHY_EMBED_SHELL_MODE_INCOGNITO || if (priv->mode == EPHY_EMBED_SHELL_MODE_INCOGNITO ||
priv->mode == EPHY_EMBED_SHELL_MODE_AUTOMATION ||
priv->mode == EPHY_EMBED_SHELL_MODE_SEARCH_PROVIDER) priv->mode == EPHY_EMBED_SHELL_MODE_SEARCH_PROVIDER)
mode = EPHY_SQLITE_CONNECTION_MODE_READ_ONLY; mode = EPHY_SQLITE_CONNECTION_MODE_READ_ONLY;
else else
...@@ -958,7 +959,7 @@ initialize_web_extensions (WebKitWebContext *web_context, ...@@ -958,7 +959,7 @@ initialize_web_extensions (WebKitWebContext *web_context,
address = priv->dbus_server ? g_dbus_server_get_client_address (priv->dbus_server) : NULL; address = priv->dbus_server ? g_dbus_server_get_client_address (priv->dbus_server) : NULL;
private_profile = priv->mode == EPHY_EMBED_SHELL_MODE_PRIVATE || priv->mode == EPHY_EMBED_SHELL_MODE_INCOGNITO; private_profile = priv->mode == EPHY_EMBED_SHELL_MODE_PRIVATE || priv->mode == EPHY_EMBED_SHELL_MODE_INCOGNITO || priv->mode == EPHY_EMBED_SHELL_MODE_AUTOMATION;
browser_mode = priv->mode == EPHY_EMBED_SHELL_MODE_BROWSER; browser_mode = priv->mode == EPHY_EMBED_SHELL_MODE_BROWSER;
user_data = g_variant_new ("(smsssbb)", user_data = g_variant_new ("(smsssbb)",
priv->guid, priv->guid,
...@@ -1101,6 +1102,12 @@ ephy_embed_shell_create_web_context (EphyEmbedShell *shell) ...@@ -1101,6 +1102,12 @@ ephy_embed_shell_create_web_context (EphyEmbedShell *shell)
return; return;
} }
if (priv->mode == EPHY_EMBED_SHELL_MODE_AUTOMATION) {
priv->web_context = webkit_web_context_new_ephemeral ();
webkit_web_context_set_automation_allowed (priv->web_context, TRUE);
return;
}
data_dir = g_build_filename (priv->mode == EPHY_EMBED_SHELL_MODE_PRIVATE ? data_dir = g_build_filename (priv->mode == EPHY_EMBED_SHELL_MODE_PRIVATE ?
ephy_dot_dir () : g_get_user_data_dir (), ephy_dot_dir () : g_get_user_data_dir (),
g_get_prgname (), NULL); g_get_prgname (), NULL);
...@@ -1258,17 +1265,21 @@ ephy_embed_shell_startup (GApplication *application) ...@@ -1258,17 +1265,21 @@ ephy_embed_shell_startup (GApplication *application)
priv->password_manager = ephy_password_manager_new (); priv->password_manager = ephy_password_manager_new ();
/* Favicon Database */ /* Do not cache favicons in automation mode. Don't change the TLS policy either, since that's
if (priv->mode == EPHY_EMBED_SHELL_MODE_PRIVATE) * handled by session capabilities in automation mode.
favicon_db_path = g_build_filename (ephy_dot_dir (), "icondatabase", NULL); */
else if (priv->mode != EPHY_EMBED_SHELL_MODE_AUTOMATION) {
favicon_db_path = g_build_filename (g_get_user_cache_dir (), "epiphany", "icondatabase", NULL); /* Favicon Database */
webkit_web_context_set_favicon_database_directory (priv->web_context, favicon_db_path); if (priv->mode == EPHY_EMBED_SHELL_MODE_PRIVATE)
g_free (favicon_db_path); favicon_db_path = g_build_filename (ephy_dot_dir (), "icondatabase", NULL);
else
/* Do not ignore TLS errors. */ favicon_db_path = g_build_filename (g_get_user_cache_dir (), "epiphany", "icondatabase", NULL);
webkit_web_context_set_tls_errors_policy (priv->web_context, WEBKIT_TLS_ERRORS_POLICY_FAIL); 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 */ /* about: URIs handler */
priv->about_handler = ephy_about_handler_new (); priv->about_handler = ephy_about_handler_new ();
...@@ -1299,7 +1310,7 @@ ephy_embed_shell_startup (GApplication *application) ...@@ -1299,7 +1310,7 @@ ephy_embed_shell_startup (GApplication *application)
/* Store cookies in moz-compatible SQLite format */ /* Store cookies in moz-compatible SQLite format */
cookie_manager = webkit_web_context_get_cookie_manager (priv->web_context); cookie_manager = webkit_web_context_get_cookie_manager (priv->web_context);
if (priv->mode != EPHY_EMBED_SHELL_MODE_INCOGNITO) { if (!webkit_web_context_is_ephemeral (priv->web_context)) {
filename = g_build_filename (ephy_dot_dir (), "cookies.sqlite", NULL); filename = g_build_filename (ephy_dot_dir (), "cookies.sqlite", NULL);
webkit_cookie_manager_set_persistent_storage (cookie_manager, filename, webkit_cookie_manager_set_persistent_storage (cookie_manager, filename,
WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE); WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE);
......
...@@ -46,7 +46,8 @@ typedef enum ...@@ -46,7 +46,8 @@ typedef enum
EPHY_EMBED_SHELL_MODE_INCOGNITO, EPHY_EMBED_SHELL_MODE_INCOGNITO,
EPHY_EMBED_SHELL_MODE_APPLICATION, EPHY_EMBED_SHELL_MODE_APPLICATION,
EPHY_EMBED_SHELL_MODE_TEST, EPHY_EMBED_SHELL_MODE_TEST,
EPHY_EMBED_SHELL_MODE_SEARCH_PROVIDER EPHY_EMBED_SHELL_MODE_SEARCH_PROVIDER,
EPHY_EMBED_SHELL_MODE_AUTOMATION
} EphyEmbedShellMode; } EphyEmbedShellMode;
struct _EphyEmbedShellClass struct _EphyEmbedShellClass
......
...@@ -808,6 +808,20 @@ ephy_embed_constructed (GObject *object) ...@@ -808,6 +808,20 @@ ephy_embed_constructed (GObject *object)
g_signal_connect (inspector, "closed", g_signal_connect (inspector, "closed",
G_CALLBACK (ephy_embed_close_inspector_cb), G_CALLBACK (ephy_embed_close_inspector_cb),
embed); embed);
if (webkit_web_view_is_controlled_by_automation (embed->web_view)) {
GtkWidget *info_bar;
GtkWidget *label;
info_bar = gtk_info_bar_new ();
gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_INFO);
label = gtk_label_new (_("Web is being controlled by automation"));
  • This string could use a translator comment explaining that it’s the browser that is controlled by robots, not the Web as a whole (as much as it’s actually true in reality 😃).

    @mcatanzaro

    Edited by Piotr Drąg
  • Added!

Please register or sign in to reply
gtk_box_pack_start (GTK_BOX (gtk_info_bar_get_content_area (GTK_INFO_BAR (info_bar))), label, FALSE, FALSE, 0);
gtk_widget_show (label);
ephy_embed_add_top_widget (embed, info_bar, EPHY_EMBED_TOP_WIDGET_POLICY_RETAIN_ON_TRANSITION);
gtk_widget_show (info_bar);
}
} }
static void static void
......
...@@ -2900,6 +2900,7 @@ ephy_web_view_new (void) ...@@ -2900,6 +2900,7 @@ ephy_web_view_new (void)
"web-context", ephy_embed_shell_get_web_context (shell), "web-context", ephy_embed_shell_get_web_context (shell),
"user-content-manager", ephy_embed_shell_get_user_content_manager (shell), "user-content-manager", ephy_embed_shell_get_user_content_manager (shell),
"settings", ephy_embed_prefs_get_settings (), "settings", ephy_embed_prefs_get_settings (),
"is-controlled-by-automation", ephy_embed_shell_get_mode (shell) == EPHY_EMBED_SHELL_MODE_AUTOMATION,
NULL); NULL);
} }
...@@ -3687,7 +3688,8 @@ ephy_web_view_load_homepage (EphyWebView *view) ...@@ -3687,7 +3688,8 @@ ephy_web_view_load_homepage (EphyWebView *view)
shell = ephy_embed_shell_get_default (); shell = ephy_embed_shell_get_default ();
mode = ephy_embed_shell_get_mode (shell); mode = ephy_embed_shell_get_mode (shell);
if (mode == EPHY_EMBED_SHELL_MODE_INCOGNITO) { if (mode == EPHY_EMBED_SHELL_MODE_INCOGNITO ||
mode == EPHY_EMBED_SHELL_MODE_AUTOMATION) {
ephy_web_view_load_new_tab_page (view); ephy_web_view_load_new_tab_page (view);
return; return;
} }
...@@ -3718,6 +3720,8 @@ ephy_web_view_load_new_tab_page (EphyWebView *view) ...@@ -3718,6 +3720,8 @@ ephy_web_view_load_new_tab_page (EphyWebView *view)
ephy_web_view_set_visit_type (view, EPHY_PAGE_VISIT_HOMEPAGE); ephy_web_view_set_visit_type (view, EPHY_PAGE_VISIT_HOMEPAGE);
if (mode == EPHY_EMBED_SHELL_MODE_INCOGNITO) if (mode == EPHY_EMBED_SHELL_MODE_INCOGNITO)
ephy_web_view_load_url (view, "about:incognito"); ephy_web_view_load_url (view, "about:incognito");
else if (mode == EPHY_EMBED_SHELL_MODE_AUTOMATION)
ephy_web_view_load_url (view, "about:blank");
else else
ephy_web_view_load_url (view, "about:overview"); ephy_web_view_load_url (view, "about:overview");
} }
......
...@@ -49,6 +49,11 @@ conf.set10('TECH_PREVIEW', tech_preview) ...@@ -49,6 +49,11 @@ conf.set10('TECH_PREVIEW', tech_preview)
conf.set_quoted('VERSION', meson.project_version()) conf.set_quoted('VERSION', meson.project_version())
version_array = meson.project_version().split('.')
conf.set('EPHY_MAJOR_VERSION', version_array[0].to_int())
conf.set('EPHY_MINOR_VERSION', version_array[1].to_int())
conf.set('EPHY_MICRO_VERSION', version_array[2].to_int())
configure_file( configure_file(
output: 'config.h', output: 'config.h',
configuration: conf configuration: conf
......
...@@ -252,7 +252,8 @@ window_added_cb (GtkApplication *application, ...@@ -252,7 +252,8 @@ window_added_cb (GtkApplication *application,
g_settings_bind_writable (settings, "picture-filename", g_settings_bind_writable (settings, "picture-filename",
action, "enabled", FALSE); action, "enabled", FALSE);
if (mode != EPHY_EMBED_SHELL_MODE_APPLICATION) { if (mode != EPHY_EMBED_SHELL_MODE_APPLICATION &&
mode != EPHY_EMBED_SHELL_MODE_AUTOMATION) {
location_controller = ephy_window_get_location_controller (EPHY_WINDOW (window)); location_controller = ephy_window_get_location_controller (EPHY_WINDOW (window));
bind_location_controller (EPHY_SETTINGS_LOCKDOWN, location_controller); bind_location_controller (EPHY_SETTINGS_LOCKDOWN, location_controller);
} }
......
...@@ -57,6 +57,7 @@ static char *application_to_delete = NULL; ...@@ -57,6 +57,7 @@ static char *application_to_delete = NULL;
static gboolean private_instance = FALSE; static gboolean private_instance = FALSE;
static gboolean incognito_mode = FALSE; static gboolean incognito_mode = FALSE;
static gboolean application_mode = FALSE; static gboolean application_mode = FALSE;
static gboolean automation_mode = FALSE;
static char *desktop_file_basename = NULL; static char *desktop_file_basename = NULL;
static char *profile_directory = NULL; static char *profile_directory = NULL;
...@@ -128,6 +129,8 @@ static const GOptionEntry option_entries[] = ...@@ -128,6 +129,8 @@ static const GOptionEntry option_entries[] =
{ "application-mode", 'a', G_OPTION_FLAG_FILENAME | G_OPTION_FLAG_OPTIONAL_ARG, { "application-mode", 'a', G_OPTION_FLAG_FILENAME | G_OPTION_FLAG_OPTIONAL_ARG,
G_OPTION_ARG_CALLBACK, application_mode_cb, G_OPTION_ARG_CALLBACK, application_mode_cb,
N_("Start the browser in application mode"), NULL }, N_("Start the browser in application mode"), NULL },
{ "automation-mode", 0, 0, G_OPTION_ARG_NONE, &automation_mode,
N_("Start an instance in automation mode"), NULL },
{ "profile", 0, 0, G_OPTION_ARG_STRING, &profile_directory, { "profile", 0, 0, G_OPTION_ARG_STRING, &profile_directory,
N_("Profile directory to use in the private instance"), N_("DIR") }, N_("Profile directory to use in the private instance"), N_("DIR") },
{ G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &arguments, { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &arguments,
...@@ -306,6 +309,11 @@ main (int argc, ...@@ -306,6 +309,11 @@ main (int argc,
exit (1); exit (1);
} }
if (automation_mode && (private_instance || incognito_mode || application_mode || profile_directory)) {
g_print ("Cannot use --automation-mode and --private-instance, --incognito-mode, --application-mode, or --profile at the same time\n");
exit (1);
}
if (application_mode && profile_directory && !g_file_test (profile_directory, G_FILE_TEST_IS_DIR)) { if (application_mode && profile_directory && !g_file_test (profile_directory, G_FILE_TEST_IS_DIR)) {
g_print ("--profile must be an existing directory when --application-mode is requested\n"); g_print ("--profile must be an existing directory when --application-mode is requested\n");
exit (1); exit (1);
...@@ -336,7 +344,7 @@ main (int argc, ...@@ -336,7 +344,7 @@ main (int argc,
/* Start our services */ /* Start our services */
flags = !application_mode ? EPHY_FILE_HELPERS_ENSURE_EXISTS : 0; flags = !application_mode ? EPHY_FILE_HELPERS_ENSURE_EXISTS : 0;
if (incognito_mode || private_instance || application_mode) if (incognito_mode || private_instance || application_mode || automation_mode)
flags |= EPHY_FILE_HELPERS_PRIVATE_PROFILE; flags |= EPHY_FILE_HELPERS_PRIVATE_PROFILE;
if (incognito_mode) if (incognito_mode)
flags |= EPHY_FILE_HELPERS_STEAL_DATA; flags |= EPHY_FILE_HELPERS_STEAL_DATA;
...@@ -349,8 +357,8 @@ main (int argc, ...@@ -349,8 +357,8 @@ main (int argc,
/* Run the migration in all cases, except when running a private /* Run the migration in all cases, except when running a private
instance without a given profile directory or running in instance without a given profile directory or running in
incognito mode. */ incognito or automation mode. */
if (!(private_instance && profile_directory == NULL) && incognito_mode == FALSE) { if (!(private_instance && profile_directory == NULL) && !incognito_mode && !automation_mode) {
/* If the migration fails we don't really want to continue. */ /* If the migration fails we don't really want to continue. */
if (!ephy_profile_utils_do_migration ((const char *)profile_directory, -1, FALSE)) { if (!ephy_profile_utils_do_migration ((const char *)profile_directory, -1, FALSE)) {
g_print ("Failed to run the migrator process, Web will now abort.\n"); g_print ("Failed to run the migrator process, Web will now abort.\n");
...@@ -358,6 +366,10 @@ main (int argc, ...@@ -358,6 +366,10 @@ main (int argc,
} }
} }
/* Ignore arguments in automation mode */
if (automation_mode)
g_clear_pointer (&arguments, g_strfreev);
arbitrary_url = g_settings_get_boolean (EPHY_SETTINGS_LOCKDOWN, arbitrary_url = g_settings_get_boolean (EPHY_SETTINGS_LOCKDOWN,
EPHY_PREFS_LOCKDOWN_ARBITRARY_URL); EPHY_PREFS_LOCKDOWN_ARBITRARY_URL);
...@@ -397,6 +409,8 @@ main (int argc, ...@@ -397,6 +409,8 @@ main (int argc,
startup_flags |= EPHY_STARTUP_NEW_TAB; startup_flags |= EPHY_STARTUP_NEW_TAB;
} else if (incognito_mode) { } else if (incognito_mode) {
mode = EPHY_EMBED_SHELL_MODE_INCOGNITO; mode = EPHY_EMBED_SHELL_MODE_INCOGNITO;
} else if (automation_mode) {
mode = EPHY_EMBED_SHELL_MODE_AUTOMATION;
} else if (application_mode) { } else if (application_mode) {
mode = EPHY_EMBED_SHELL_MODE_APPLICATION; mode = EPHY_EMBED_SHELL_MODE_APPLICATION;
......
...@@ -372,7 +372,8 @@ ephy_shell_startup (GApplication *application) ...@@ -372,7 +372,8 @@ ephy_shell_startup (GApplication *application)
app_entries, G_N_ELEMENTS (app_entries), app_entries, G_N_ELEMENTS (app_entries),
application); application);
if (mode != EPHY_EMBED_SHELL_MODE_INCOGNITO) { if (mode != EPHY_EMBED_SHELL_MODE_INCOGNITO &&
mode != EPHY_EMBED_SHELL_MODE_AUTOMATION) {
g_action_map_add_action_entries (G_ACTION_MAP (application), g_action_map_add_action_entries (G_ACTION_MAP (application),
non_incognito_extra_app_entries, G_N_ELEMENTS (non_incognito_extra_app_entries), non_incognito_extra_app_entries, G_N_ELEMENTS (non_incognito_extra_app_entries),
application); application);
...@@ -409,6 +410,41 @@ ephy_shell_startup (GApplication *application) ...@@ -409,6 +410,41 @@ ephy_shell_startup (GApplication *application)
set_accel_for_action (shell, "app.quit", "<Primary>q"); set_accel_for_action (shell, "app.quit", "<Primary>q");
} }
static GtkWidget *
create_web_view_for_automation_cb (WebKitAutomationSession *session,
EphyShell *shell)
{
EphyEmbed *embed;
EphyWindow *window;
EphyWebView *web_view;
guint n_embeds;
window = EPHY_WINDOW (gtk_application_get_active_window (GTK_APPLICATION (shell)));
embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
n_embeds = ephy_embed_container_get_n_children (EPHY_EMBED_CONTAINER (window));
web_view = ephy_embed_get_web_view (embed);
if (n_embeds == 1 && ephy_web_view_get_visit_type (web_view) == EPHY_PAGE_VISIT_HOMEPAGE)
return GTK_WIDGET (web_view);
embed = ephy_shell_new_tab (shell, window, NULL, EPHY_NEW_TAB_JUMP);
return GTK_WIDGET (ephy_embed_get_web_view (embed));
}
static void
automation_started_cb (WebKitWebContext *web_context,
WebKitAutomationSession *session,
EphyShell *shell)
{
WebKitApplicationInfo *info = webkit_application_info_new ();
webkit_application_info_set_name (info, "Epiphany");
webkit_application_info_set_version (info, EPHY_MAJOR_VERSION, EPHY_MINOR_VERSION, EPHY_MICRO_VERSION);
webkit_automation_session_set_application_info (session, info);
webkit_application_info_unref (info);
g_signal_connect (session, "create-web-view", G_CALLBACK (create_web_view_for_automation_cb), shell);
}
static void static void
session_load_cb (GObject *object, session_load_cb (GObject *object,
GAsyncResult *result, GAsyncResult *result,
...@@ -425,6 +461,12 @@ static void ...@@ -425,6 +461,12 @@ static void
ephy_shell_activate (GApplication *application) ephy_shell_activate (GApplication *application)
{ {
EphyShell *shell = EPHY_SHELL (application); EphyShell *shell = EPHY_SHELL (application);
EphyEmbedShell *embed_shell = EPHY_EMBED_SHELL (shell);
if (ephy_embed_shell_get_mode (embed_shell) == EPHY_EMBED_SHELL_MODE_AUTOMATION) {
WebKitWebContext *web_context = ephy_embed_shell_get_web_context (embed_shell);
g_signal_connect (web_context, "automation-started", G_CALLBACK (automation_started_cb), shell);
}
if (shell->remote_startup_context == NULL) { if (shell->remote_startup_context == NULL) {
EphySession *session = ephy_shell_get_session (shell); EphySession *session = ephy_shell_get_session (shell);
...@@ -819,7 +861,7 @@ ephy_shell_get_session (EphyShell *shell) ...@@ -819,7 +861,7 @@ ephy_shell_get_session (EphyShell *shell)
g_assert (EPHY_IS_SHELL (shell)); g_assert (EPHY_IS_SHELL (shell));
mode = ephy_embed_shell_get_mode (EPHY_EMBED_SHELL (shell)); mode = ephy_embed_shell_get_mode (EPHY_EMBED_SHELL (shell));
if (mode == EPHY_EMBED_SHELL_MODE_APPLICATION || mode == EPHY_EMBED_SHELL_MODE_INCOGNITO) if (mode == EPHY_EMBED_SHELL_MODE_APPLICATION || mode == EPHY_EMBED_SHELL_MODE_INCOGNITO || mode == EPHY_EMBED_SHELL_MODE_AUTOMATION)
return NULL; return NULL;
if (shell->session == NULL) if (shell->session == NULL)
......
...@@ -312,6 +312,14 @@ impl_get_is_popup (EphyEmbedContainer *container) ...@@ -312,6 +312,14 @@ impl_get_is_popup (EphyEmbedContainer *container)
return EPHY_WINDOW (container)->is_popup; return EPHY_WINDOW (container)->is_popup;
} }
static guint
impl_get_n_children (EphyEmbedContainer *container)
{
EphyWindow *window = EPHY_WINDOW (container);
return gtk_notebook_get_n_pages (window->notebook);
}
static void static void
ephy_window_embed_container_iface_init (EphyEmbedContainerInterface *iface) ephy_window_embed_container_iface_init (EphyEmbedContainerInterface *iface)
{ {
...@@ -321,6 +329,7 @@ ephy_window_embed_container_iface_init (EphyEmbedContainerInterface *iface) ...@@ -321,6 +329,7 @@ ephy_window_embed_container_iface_init (EphyEmbedContainerInterface *iface)
iface->get_active_child = impl_get_active_child; iface->get_active_child = impl_get_active_child;
iface->get_children = impl_get_children; iface->get_children = impl_get_children;
iface->get_is_popup = impl_get_is_popup; iface->get_is_popup = impl_get_is_popup;
iface->get_n_children = impl_get_n_children;
} }
static EphyEmbed * static EphyEmbed *
...@@ -1159,6 +1168,7 @@ sync_tab_bookmarked_status (EphyWebView *view, ...@@ -1159,6 +1168,7 @@ sync_tab_bookmarked_status (EphyWebView *view,
{ {
EphyBookmarksManager *manager = ephy_shell_get_bookmarks_manager (ephy_shell_get_default ()); EphyBookmarksManager *manager = ephy_shell_get_bookmarks_manager (ephy_shell_get_default ());
EphyEmbedShell *shell = ephy_embed_shell_get_default (); EphyEmbedShell *shell = ephy_embed_shell_get_default ();
EphyEmbedShellMode mode;
EphyLocationEntryBookmarkIconState state; EphyLocationEntryBookmarkIconState state;
GtkWidget *widget; GtkWidget *widget;
EphyBookmark *bookmark; EphyBookmark *bookmark;
...@@ -1170,10 +1180,12 @@ sync_tab_bookmarked_status (EphyWebView *view, ...@@ -1170,10 +1180,12 @@ sync_tab_bookmarked_status (EphyWebView *view,
return; return;
address = ephy_web_view_get_address (view); address = ephy_web_view_get_address (view);
mode = ephy_embed_shell_get_mode (shell);
if (!address || if (!address ||
ephy_embed_utils_is_no_show_address (address) || ephy_embed_utils_is_no_show_address (address) ||
ephy_embed_shell_get_mode (shell) == EPHY_EMBED_SHELL_MODE_INCOGNITO) { mode == EPHY_EMBED_SHELL_MODE_INCOGNITO ||
mode == EPHY_EMBED_SHELL_MODE_AUTOMATION) {
state = EPHY_LOCATION_ENTRY_BOOKMARK_ICON_HIDDEN; state = EPHY_LOCATION_ENTRY_BOOKMARK_ICON_HIDDEN;
} else { } else {
bookmark = ephy_bookmarks_manager_get_bookmark_by_url (manager, address); bookmark = ephy_bookmarks_manager_get_bookmark_by_url (manager, address);
...@@ -2771,6 +2783,11 @@ notebook_page_close_request_cb (EphyNotebook *notebook, ...@@ -2771,6 +2783,11 @@ notebook_page_close_request_cb (EphyNotebook *notebook,
return; return;
} }
if (ephy_embed_shell_get_mode (ephy_embed_shell_get_default ()) == EPHY_EMBED_SHELL_MODE_AUTOMATION) {
/* Never prompt the user before closing in automation mode */
ephy_window_close_tab (window, embed);
}
/* Last window, check ongoing downloads before closing the tab */ /* Last window, check ongoing downloads before closing the tab */
if (ephy_shell_get_n_windows (ephy_shell_get_default ()) == 1) { if (ephy_shell_get_n_windows (ephy_shell_get_default ()) == 1) {
EphyDownloadsManager *manager = ephy_embed_shell_get_downloads_manager (EPHY_EMBED_SHELL (ephy_shell_get_default ())); EphyDownloadsManager *manager = ephy_embed_shell_get_downloads_manager (EPHY_EMBED_SHELL (ephy_shell_get_default ()));
...@@ -3377,6 +3394,8 @@ ephy_window_constructed (GObject *object) ...@@ -3377,6 +3394,8 @@ ephy_window_constructed (GObject *object)
mode = ephy_embed_shell_get_mode (ephy_embed_shell_get_default ()); mode = ephy_embed_shell_get_mode (ephy_embed_shell_get_default ());
if (mode == EPHY_EMBED_SHELL_MODE_INCOGNITO) if (mode == EPHY_EMBED_SHELL_MODE_INCOGNITO)
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (window)), "incognito-mode"); gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (window)), "incognito-mode");
else if (mode == EPHY_EMBED_SHELL_MODE_AUTOMATION)
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (window)), "automation-mode");
/* Setup the toolbar. */ /* Setup the toolbar. */
window->header_bar = setup_header_bar (window); window->header_bar = setup_header_bar (window);
...@@ -3448,6 +3467,8 @@ ephy_window_constructed (GObject *object) ...@@ -3448,6 +3467,8 @@ ephy_window_constructed (GObject *object)
action = g_action_map_lookup_action (G_ACTION_MAP (action_group), "context-bookmark-page"); action = g_action_map_lookup_action (G_ACTION_MAP (action_group), "context-bookmark-page");
ephy_action_change_sensitivity_flags (G_SIMPLE_ACTION (action), ephy_action_change_sensitivity_flags (G_SIMPLE_ACTION (action),
SENS_FLAG_CHROME, TRUE); SENS_FLAG_CHROME, TRUE);
} else if (mode == EPHY_EMBED_SHELL_MODE_AUTOMATION) {
g_object_set (window->location_controller, "editable", FALSE, NULL);
} }
window->mouse_gesture_controller = ephy_mouse_gesture_controller_new (window); window->mouse_gesture_controller = ephy_mouse_gesture_controller_new (window);
......
...@@ -41,6 +41,48 @@ ...@@ -41,6 +41,48 @@
.incognito-mode headerbar entry:backdrop { box-shadow: none; } .incognito-mode headerbar entry:backdrop { box-shadow: none; }
.automation-mode headerbar { background: #ff9600 linear-gradient(to top, #bd6f00, #f59000 2px, #ff9600 3px); box-shadow: inset 0 1px #ffb142; border-color: #995a00; color: rgba(46, 52, 54, 0.2); }
.automation-mode headerbar > * { color: #2e3436; }
.automation-mode headerbar > *:backdrop { color: #929595; }
.automation-mode headerbar:backdrop { box-shadow: inset 0 1px #ffb142; color: rgba(146, 149, 149, 0.1); }
.automation-mode headerbar button { color: #2e3436; outline-color: rgba(46, 52, 54, 0.3); border-color: #995a00; border-bottom-color: #663c00; background-image: linear-gradient(to bottom, #ff9600, #eb8a00 95%, #db8100 1px); text-shadow: 0 1px rgba(255, 255, 255, 0.769231); -gtk-icon-shadow: 0 1px rgba(255, 255, 255, 0.769231); box-shadow: inset 0 1px rgba(255, 255, 255, 0.2); }
.automation-mode headerbar button.flat, .automation-mode headerbar button.titlebutton { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; }
.automation-mode headerbar button.titlebutton { text-shadow: 0 1px rgba(255, 255, 255, 0.769231); -gtk-icon-shadow: 0 1px rgba(255, 255, 255, 0.769231); }
.automation-mode headerbar button:hover { color: #2e3436; outline-color: rgba(46, 52, 54, 0.3); border-color: #995a00; border-bottom-color: #663c00; text-shadow: 0 1px rgba(255, 255, 255, 0.769231); -gtk-icon-shadow: 0 1px rgba(255, 255, 255, 0.769231); box-shadow: inset 0 1px rgba(255, 255, 255, 0.4); background-image: linear-gradient(to bottom, #ffa31f, #ff9600 95%, #db8100 1px); }
.automation-mode headerbar button:active, .automation-mode headerbar button:checked { color: #2e3436; outline-color: rgba(46, 52, 54, 0.3); border-color: #995a00; background-image: image(#e08400); box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; }
.automation-mode headerbar button:disabled { border-color: #995a00; background-image: image(#ffa626); text-shadow: none; -gtk-icon-shadow: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); }
.automation-mode headerbar button:disabled label, .automation-mode headerbar button:disabled { color: #929595; }
.automation-mode headerbar button:backdrop { border-color: #ff9600; background-image: image(#ff9600); text-shadow: none; -gtk-icon-shadow: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); border-color: #995a00; }
.automation-mode headerbar button:backdrop label, .automation-mode headerbar button:backdrop { color: #929595; }
.automation-mode headerbar button:backdrop:active { border-color: #fc9500; background-image: image(#fc9500); box-shadow: inset 0 1px rgba(255, 255, 255, 0); border-color: #995a00; }
.automation-mode headerbar button:backdrop:active label, .automation-mode headerbar button:backdrop:active { color: #929595; }
.automation-mode headerbar button:backdrop:disabled { border-color: #ffa626; background-image: image(#ffa626); text-shadow: none; -gtk-icon-shadow: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); border-color: #995a00; }
.automation-mode headerbar button:backdrop:disabled label, .automation-mode headerbar button:backdrop:disabled { color: #b67e2c; }
.automation-mode headerbar button.flat:backdrop, .automation-mode headerbar button.titlebutton:backdrop { border-color: transparent; background-color: transparent; background-image: none; box-shadow: inset 0 1px rgba(255, 255, 255, 0); text-shadow: none; -gtk-icon-shadow: none; }
.automation-mode headerbar entry { border-color: #995a00; }
.automation-mode headerbar entry:focus { border-color: #3584e4; box-shadow: inset 0 0 0 1px #3584e4; }
.automation-mode headerbar entry:backdrop { box-shadow: none; }
.bookmark-tag-widget { background-color: #cfcfcd; } .bookmark-tag-widget { background-color: #cfcfcd; }
.bookmark-tag-widget image, .bookmark-tag-widget label { color: #2e3436; } .bookmark-tag-widget image, .bookmark-tag-widget label { color: #2e3436; }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
.incognito-mode { .incognito-mode {
headerbar { headerbar {
@include headerbar_fill($incognito_color, $edge_color, -gtk-icontheme($incognito_icon) 160px 0 / 64px 64px no-repeat); @include headerbar_fill($incognito_color, $incognito_edge_color, -gtk-icontheme($incognito_icon) 160px 0 / 64px 64px no-repeat);
border-color: _border_color($incognito_color); border-color: _border_color($incognito_color);
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
&:backdrop { &:backdrop {
background-image: -gtk-icontheme($incognito_icon), image($incognito_color); background-image: -gtk-icontheme($incognito_icon), image($incognito_color);
box-shadow: inset 0 1px $edge_color; box-shadow: inset 0 1px $incognito_edge_color;
color: transparentize($backdrop_fg_color, 0.9); // color of the overlayed icon in backdrop color: transparentize($backdrop_fg_color, 0.9); // color of the overlayed icon in backdrop
} }
...@@ -68,6 +68,68 @@ ...@@ -68,6 +68,68 @@
} }
} }
.automation-mode {
headerbar {
@include headerbar_fill($automation_color, $automation_edge_color);
border-color: _border_color($automation_color);
color: transparentize($fg_color, 0.8); // this is the color of the overlayed icon
> * {
color: $fg_color;
&:backdrop { color: $backdrop_fg_color }
}
&:backdrop {
box-shadow: inset 0 1px $automation_edge_color;
color: transparentize($backdrop_fg_color, 0.9); // color of the overlayed icon in backdrop
}
button { // changing the headerbar background color requires changing widget borders accordingly
@include button(normal, $automation_color);
&.flat, &.titlebutton { @include button(undecorated); }
&.titlebutton { @include _button_text_shadow($fg_color, $automation_color); }
&:hover { @include button(hover, $automation_color); }
&:active, &:checked { @include button(active, $automation_color); }
&:disabled { @include button(insensitive, $automation_color); }
&:backdrop {
@include button(backdrop, $automation_color);
border-color: _border_color($automation_color);
&:active {
@include button(backdrop-active, $automation_color);
border-color: _border_color($automation_color);
}
&:disabled {
@include button(backdrop-insensitive, $automation_color);
border-color: _border_color($automation_color);
}
}
&.flat:backdrop, &.titlebutton:backdrop { @include button(undecorated); }
}
entry {
border-color: _border_color($automation_color);