...
 
Commits (184)
build/
subprojects/libdazzle/
subprojects/libhandy/
stages:
- test
- review
include: 'https://gitlab.gnome.org/GNOME/citemplates/raw/master/flatpak/flatpak_ci_initiative.yml'
variables:
# Replace with your preferred file name of the resulting Flatpak bundle
BUNDLE: "epiphany-git.flatpak"
BUNDLE: 'epiphany-git.flatpak'
flatpak:
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
stage: test
variables:
# Replace with your manifest path
MANIFEST_PATH: "org.gnome.Epiphany.json"
RUNTIME_REPO: "https://sdk.gnome.org/gnome-nightly.flatpakrepo"
# Replace with your application name, as written in the manifest
FLATPAK_MODULE: "epiphany"
# Make sure to keep this in sync with the Flatpak manifest, all arguments
# are passed except the config-args because we build it ourselves
MESON_ARGS: "-Dunit_tests=true"
DBUS_ID: "org.gnome.Epiphany"
script:
- flatpak-builder --stop-at=${FLATPAK_MODULE} app ${MANIFEST_PATH}
# Make sure to keep this in sync with the Flatpak manifest, all arguments
# are passed except the config-args because we build it ourselves
- flatpak build app meson --prefix=/app ${MESON_ARGS} _build
- flatpak build app ninja -C _build install
- flatpak-builder --finish-only --repo=repo app ${MANIFEST_PATH}
# Generate a Flatpak bundle
- flatpak build-bundle repo ${BUNDLE} --runtime-repo=${RUNTIME_REPO} ${DBUS_ID}
# Run automatic tests inside the Flatpak env
- xvfb-run -a -s "-screen 0 1024x768x24" flatpak build app ninja -C _build test
artifacts:
paths:
- ${BUNDLE}
- _build/meson-logs/meson-log.txt
- _build/meson-logs/testlog.txt
expire_in: 30 days
cache:
paths:
- .flatpak-builder/cache
extends: '.flatpak'
variables:
MANIFEST_PATH: 'flatpak/org.gnome.Epiphany.json'
RUNTIME_REPO: 'https://sdk.gnome.org/gnome-nightly.flatpakrepo'
FLATPAK_MODULE: 'epiphany'
# Make sure to keep this in sync with the Flatpak manifest, all arguments
# are passed except the config-args because we build it ourselves
MESON_ARGS: '-Dunit_tests=true'
APP_ID: 'org.gnome.Epiphany'
review:
stage: review
dependencies:
- flatpak
script:
- echo "Generating flatpak deployment"
artifacts:
paths:
- ${BUNDLE}
expire_in: 30 days
environment:
name: review/$CI_COMMIT_REF_NAME
url: https://gitlab.gnome.org/$CI_PROJECT_PATH/-/jobs/$CI_JOB_ID/artifacts/raw/${BUNDLE}
on_stop: stop_review
except:
- master@GNOME/epiphany
- tags
dependencies:
- 'flatpak'
extends: '.review'
stop_review:
stage: review
script:
- echo "Stopping flatpak deployment"
when: manual
environment:
name: review/$CI_COMMIT_REF_NAME
action: stop
except:
- master@GNOME/epiphany
- tags
\ No newline at end of file
extends: '.stop_review'
\ No newline at end of file
......@@ -3,13 +3,9 @@ very short, so please read it before reporting your issue.
For tips for hacking on Epiphany, see the HACKING.md file.
# Submitting an Issue Report?
# Software versions
Thanks for reporting your problem with Epiphany.
## Software versions
Please include the following in your report:
Please include the following in your issue report:
* Epiphany version
* WebKitGTK+ version
......@@ -18,7 +14,7 @@ Please include the following in your report:
Check the About dialog if you're not sure what Epiphany or WebKitGTK+ versions
you have.
## Web Content Bugs
# Web Content Bugs
This is the **wrong place** to report bugs with web content (e.g. incorrect page
rendering, broken JavaScript, problems with video playback, font issues, network
......@@ -41,7 +37,7 @@ or WebKit is responsible for a bug. If we suspect an issue reported on the
Epiphany issue tracker is actually a WebKit bug, we will close it and ask you to
report the issue on WebKit Bugzilla instead.
## Crashes
# Crashes
If Epiphany crashed, then we really need a backtrace taken in gdb with `bt full`
in order to solve the problem. Be sure to install the necessary debuginfo
......
......@@ -16,7 +16,8 @@ need to stick to in order to get your patch accepted:
* Use K&R style for the braces.
* No braces for one line control clauses.
* No braces for one line control clauses except when another clause in the
chain contains more than one line.
* Callback functions have a suffix _cb.
......@@ -40,6 +41,10 @@ need to stick to in order to get your patch accepted:
* There's no space between a type cast and the variable name: Right:
`(int *)foo`. Wrong: `(int*) foo`.
* Avoid explicit comparisons against TRUE, FALSE, and NULL. Right:
`if (!condition)`, `if (!pointer)`, `if (integer == 0)`. Wrong:
`if (condition == FALSE)`, `if (pointer == NULL)`, `if (!integer)`.
# Code Structure
## Layering
......
3.31.4 - January 7, 2019
========================
- Add default zoom level option to preferences dialog (#8)
- Double click on reader mode icon should not maximize window (#44)
- Move new tab button to start of the header bar, always (#69, #447)
- Hide Help and About when running in Pantheon (#71, #72)
- Reenable address bar DNS prefetch (#79)
- Add hidden setting to keep window open on Ctrl+W (#80)
- Fix file extension when saving a View Source page (#98)
- Add reload all tabs to tab context menu (#118)
- Remember last upload/download directory (#133)
- Highlight matching text in address bar dropdown (#164)
- History dialog should respect desktop 12/24 hour clock setting (#197)
- Add reload tab and reopen closed tab to tab context menu (#199, #226)
- Convert all hostnames to lowercase (#230)
- Add support for viewing PDFs using libevince (#264)
- Add application manager to window menu (#267)
- Fix passwords dialog expanding after deleting password (#285)
- Hide various menu items from app mode (#309)
- Remove MIME type restrictions (#310)
- Remove broken bookmarks command line options (#338)
- Reenable some tests that were broken (#341, #419, #494)
- Open in new tab when middle clicking homepage button (#368)
- Monitor for changes to user CSS file (#370)
- Fix Ctrl+Shift+Page[Up,Down] (#399)
- Remove obsolete shortcuts documentation (#407)
- 127.0.0.1 and ::1 are now always considered secure (#410)
- Floating status bar no longer blocks clicks (#428)
- Add experimental support for mouse gestures (#430)
- Allow search the web context menu item in text fields (#438)
- Improve documentation of command line options (#440)
- Allow more zoom levels (#492)
- Adopt standard behavior for clicks with modifier keys pressed (#493)
- Add preference to disable smooth scrolling (#577, Sharaz Ali)
- Use /etc/os-release to set distributor name (#586)
- Fix remote inspector (#600, Loïc Yhuel)
- Alt-number tab switching can no longer be intercepted (#606)
- Fix crash after bookmark sync (#612)
- Add --automation-mode, for control by WebKitWebDriver
- Use libhandy for improved narrow mode (Adrien Plazas)
- Make history and encoding dialogs responsive
- Don't show new fullscreen header bar for fullscreen videos
- Move copy/search items to the top of the context menu (Jonathan Kang)
3.31.3 - December 10, 2018
==========================
- Improve padding in bookmarks view (#496, Apostol Bakalov)
- Do not show progress bar on empty new tabs (#574)
- Fix crash storing password on paypal.com (#575)
- Add column spacing to encoding dialog grid (#576)
- Fix suggestion entry not closing after Paste & Go (#581)
- Fix suggestion entry reopening after closed with Escape (#582)
- Tags with empty labels are no longer allowed in bookmarks (#585, Aral Balkan)
- Fix freeze when closing window or tabs when secondary process is hung (#587)
- Fix crash when web view has not loaded anything yet (#590)
- Temporarily disable hardware accelerated page rendering (#595)
- Stop lowercasing spellcheck and Accept-Langs locales
- Locales on language selection dialog are now displayed translated
- Locales on language selection dialog are no longer limited
- Several miscellaneous code improvements (Thomas An)
3.31.2 - November 11, 2018
==========================
......
Some TODO items, in no particular order:
- Remove all use of slice allocator
- Rename all classes that lack the Ephy namespace
- Use g_signal_emit instead of g_signal_emit_by_name
- Use GDK_EVENT_PROPAGATE/GDK_EVENT_STOP.
- Use G_SOURCE_CONTINUE/G_SOURCE_REMOVE.
- Name all timeout and idle sources
- Replace constructor functions with constructed functions
- Use g_clear_object/g_clear_pointer in dispose/finalize
- Use g_clear_object/g_clear_pointer in dispose (and finalize?)
- Use g_clear_weak_pointer and g_clear_handle_id
- Replace dispose with finalize wherever possible
- Use GtkBuilder instead of declaring the UIs with C
- Use g_autofree/g_autoptr where possible
- Write out foo == NULL instead of !foo where possible
- We practically don't test any part of Epiphany, change that (how do
you test UI code? There's like 3 or 4 frameworks for this, pick one?
What does Chrome do?)
.\" Epiphany manpage.
.\" Copyright © 2006 GNOME Foundation, Inc.
.\" Copyright © 2006-2019 GNOME Foundation, Inc.
.\"
.TH EPIPHANY "1" "2018-01-23" "GNOME" ""
.TH EPIPHANY "1" "January 2019"
.SH NAME
epiphany \- simple to use web browser for GNOME
epiphany \- a simple, clean, beautiful view of the web
.SH SYNOPSIS
.B epiphany
[\fIOPTION\fR...] [url]
.SH DESCRIPTION
Help options
.TP
-?, \fB\-\-help\fR
Show help options
.PP
Application options
.TP
\fB\-n\fR, \fB\-\-new\-tab\fR
Open a new tab in an existing
browser window
\fBepiphany\fR is the codename of GNOME Web, the web browser designed for the
GNOME desktop and elementary OS. It offers a simple, clean, beautiful view of
the web featuring first-class GNOME and Pantheon desktop integration, using
WebKitGTK+ for web rendering.
.SH OPTIONS
.TP
\fB\-\-new\-window\fR
Open a new browser window
.TP
\fB\-\-import\-bookmarks\fR=\fIFILE\fR
Import bookmarks from the given file
Open a new browser window instead of a new tab
.TP
\fB\-l\fR, \fB\-\-load\-session\fR=\fIFILE\fR
Load the given session file
Load the given session state file
.TP
\fB\-t\fR, \fB\-\-add\-bookmark\fR=\fIURL\fR
Add a bookmark
\fB\-i\fR, \fB\-\-incognito\-mode\fR
Start an instance with user data read-only
.TP
\fB\-p\fR, \fB\-\-private\-instance\fR
Start a private instance (temporary profile directory, not private browsing mode)
Start a private instance with separate user data
.TP
\fB\-a\fR, \fB\-\-application\-mode\fR[=\fIBASENAME\fR]
Start a private instance in web application mode (requires passing either desktop file basename or
.B \-\-profile)
.TP
\fB\-\-incognito\-mode\fR
Start a private instance in incognito mode
\fB\-\-automation\-mode\fR
Start a private instance for WebDriver control
.TP
\fB\-\-profile\fR=\fIFILE\fR
Profile directory to use in the private instance
Custom profile directory for private instance (optional)
.TP
-?, \fB\-\-help\fR
Show help options
.TP
\fB\-\-version\fR
Show version
......@@ -46,4 +45,6 @@ Show version
Epiphany has a comprehensive help system. Run the browser
and select \fBHelp\fR from the menu.
.SH AUTHOR
Written by Marco Pesenti Gritti, Christian Persch and others.
Written by Marco Pesenti Gritti (in memoriam), Christian Persch, Xan Lopez,
Carlos Garcia Campos, Claudio Saavedra, Michael Catanzaro, Jan-Michael Brummer,
and many others.
......@@ -2,7 +2,7 @@ install_subdir('icons/hicolor',
install_dir: join_paths(datadir, 'icons')
)
i18n.merge_file('desktop-file',
desktop_file = i18n.merge_file('desktop-file',
input: 'org.gnome.Epiphany.desktop.in',
output: 'org.gnome.Epiphany.desktop',
install: true,
......@@ -10,14 +10,33 @@ i18n.merge_file('desktop-file',
po_dir: '../po',
type: 'desktop'
)
desktop_file_validate = find_program ('desktop-file-validate', required: false)
if desktop_file_validate.found()
test(
'validate-desktop',
desktop_file_validate,
args: [
desktop_file.full_path()
]
)
endif
i18n.merge_file('appdata-file',
appdata_file = i18n.merge_file('appdata-file',
input: 'org.gnome.Epiphany.appdata.xml.in',
output: 'org.gnome.Epiphany.appdata.xml',
install: true,
install_dir: join_paths(datadir, 'metainfo'),
po_dir: '../po'
)
appstream_util = find_program('appstream-util', required: false)
if appstream_util.found()
test(
'validate-appdata', appstream_util,
args: [
'validate-relax', '--nonet', appdata_file.full_path()
]
)
endif
# We need three custom_target() calls because Meson doesn't have very
# good support for GSettings yet. First, generate our GSettings enums
......
......@@ -118,6 +118,11 @@
<summary>The visibility policy for the tabs bar.</summary>
<description>Controls when the tabs bar is shown. Possible values are “always” (the tabs bar is always shown), “more-than-one” (the tabs bar is only shown if there’s two or more tabs) and “never” (the tabs bar is never shown).</description>
</key>
<key type="b" name="keep-window-open">
<default>false</default>
<summary>Keep window open when closing last tab</summary>
<description>If enabled application window is kept open when closing the last tab.</description>
</key>
</schema>
<schema path="/org/gnome/epiphany/reader/" id="org.gnome.Epiphany.reader">
<key name="font-style" enum="org.gnome.Epiphany.EphyPrefsReaderFontStyle">
......@@ -249,6 +254,21 @@
<summary>Enable autosearch</summary>
<description>Whether to automatically search the web when something that does not look like a URL is entered in the address bar. If this setting is disabled, everything will be loaded as a URL unless a search engine is explicitly selected from the dropdown menu.</description>
</key>
<key type="b" name="enable-mouse-gestures">
<default>false</default>
<summary>Enable mouse gesture</summary>
<description>Whether to enable mouse gestures. Mouse gestures are based on Opera’s behaviour and are activated using the middle mouse button + gesture.</description>
</key>
<key type="s" name="last-upload-directory">
<default>''</default>
<summary>Last upload directory</summary>
<description>Keep track of last upload directory</description>
</key>
<key type="s" name="last-download-directory">
<default>''</default>
<summary>Last download directory</summary>
<description>Keep track of last download directory</description>
</key>
</schema>
<schema id="org.gnome.Epiphany.webapp">
<key type="as" name="additional-urls">
......
......@@ -25,7 +25,9 @@
#include "ephy-embed.h"
#include "ephy-embed-shell.h"
#include "ephy-embed-type-builtins.h"
#include "ephy-evince-document-view.h"
#include "ephy-file-helpers.h"
#include "ephy-flatpak-utils.h"
#include "ephy-prefs.h"
#include "ephy-settings.h"
......@@ -42,6 +44,7 @@ struct _EphyDownload {
char *content_type;
gboolean show_notification;
gboolean in_document_mode;
EphyDownloadActionType action;
guint32 start_time;
......@@ -438,14 +441,16 @@ ephy_download_do_download_action (EphyDownload *download,
switch ((action ? action : download->action)) {
case EPHY_DOWNLOAD_ACTION_BROWSE_TO:
LOG ("ephy_download_do_download_action: browse_to");
ret = ephy_file_browse_to (destination, user_time);
/* Must not use this action type under flatpak! */
ret = ephy_file_browse_to (destination, user_time,
EPHY_FILE_HELPERS_I_UNDERSTAND_I_MUST_NOT_USE_THIS_FUNCTION_UNDER_FLATPAK);
break;
case EPHY_DOWNLOAD_ACTION_OPEN:
LOG ("ephy_download_do_download_action: open");
ret = ephy_embed_shell_launch_handler (ephy_embed_shell_get_default (),
destination, NULL, user_time);
if (!ret)
ret = ephy_file_browse_to (destination, user_time);
ret = ephy_file_launch_handler (destination, user_time);
if (!ret && !ephy_is_running_inside_flatpak ())
ret = ephy_file_browse_to (destination, user_time,
EPHY_FILE_HELPERS_I_UNDERSTAND_I_MUST_NOT_USE_THIS_FUNCTION_UNDER_FLATPAK);
break;
case EPHY_DOWNLOAD_ACTION_NONE:
LOG ("ephy_download_do_download_action: none");
......@@ -630,6 +635,16 @@ download_decide_destination_cb (WebKitDownload *wk_download,
const gchar *suggested_filename,
EphyDownload *download)
{
if (download->in_document_mode) {
g_autofree gchar *tmp_file = g_strdup_printf ("%s/%s", g_get_user_cache_dir (), suggested_filename);
g_autofree gchar *file_uri = g_filename_to_uri (tmp_file, NULL, NULL);
webkit_download_set_allow_overwrite (wk_download, TRUE);
webkit_download_set_destination (wk_download, file_uri);
return TRUE;
}
if (webkit_download_get_destination (wk_download))
return TRUE;
......@@ -812,3 +827,9 @@ ephy_download_disable_desktop_notification (EphyDownload *download)
download->show_notification = FALSE;
}
void
ephy_download_enable_evince_document_mode (EphyDownload *download)
{
download->in_document_mode = TRUE;
}
......@@ -36,32 +36,33 @@ typedef enum
EPHY_DOWNLOAD_ACTION_OPEN
} EphyDownloadActionType;
EphyDownload *ephy_download_new (WebKitDownload *download);
EphyDownload *ephy_download_new_for_uri (const char *uri);
EphyDownload *ephy_download_new (WebKitDownload *download);
EphyDownload *ephy_download_new_for_uri (const char *uri);
void ephy_download_cancel (EphyDownload *download);
gboolean ephy_download_is_active (EphyDownload *download);
gboolean ephy_download_succeeded (EphyDownload *download);
gboolean ephy_download_failed (EphyDownload *download,
GError **error);
void ephy_download_cancel (EphyDownload *download);
gboolean ephy_download_is_active (EphyDownload *download);
gboolean ephy_download_succeeded (EphyDownload *download);
gboolean ephy_download_failed (EphyDownload *download,
GError **error);
void ephy_download_set_destination_uri (EphyDownload *download,
const char *destination);
void ephy_download_set_destination_uri (EphyDownload *download,
const char *destination);
WebKitDownload *ephy_download_get_webkit_download (EphyDownload *download);
WebKitDownload *ephy_download_get_webkit_download (EphyDownload *download);
const char *ephy_download_get_destination_uri (EphyDownload *download);
const char *ephy_download_get_content_type (EphyDownload *download);
const char *ephy_download_get_destination_uri (EphyDownload *download);
const char *ephy_download_get_content_type (EphyDownload *download);
guint32 ephy_download_get_start_time (EphyDownload *download);
guint32 ephy_download_get_start_time (EphyDownload *download);
EphyDownloadActionType ephy_download_get_action (EphyDownload *download);
void ephy_download_set_action (EphyDownload *download,
EphyDownloadActionType action);
gboolean ephy_download_do_download_action (EphyDownload *download,
EphyDownloadActionType action,
guint32 user_time);
EphyDownloadActionType ephy_download_get_action (EphyDownload *download);
void ephy_download_set_action (EphyDownload *download,
EphyDownloadActionType action);
gboolean ephy_download_do_download_action (EphyDownload *download,
EphyDownloadActionType action,
guint32 user_time);
void ephy_download_disable_desktop_notification
(EphyDownload *download);
(EphyDownload *download);
void ephy_download_enable_evince_document_mode (EphyDownload *download);
G_END_DECLS
......@@ -165,3 +165,22 @@ ephy_embed_container_get_is_popup (EphyEmbedContainer *container)
iface = EPHY_EMBED_CONTAINER_GET_IFACE (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
GList * (* get_children) (EphyEmbedContainer *container);
gboolean (* get_is_popup) (EphyEmbedContainer *container);
guint (* get_n_children) (EphyEmbedContainer *container);
};
gint ephy_embed_container_add_child (EphyEmbedContainer *container,
......@@ -65,5 +67,6 @@ void ephy_embed_container_remove_child (EphyEmbedContainer *con
EphyEmbed * ephy_embed_container_get_active_child (EphyEmbedContainer *container);
GList * ephy_embed_container_get_children (EphyEmbedContainer *container);
gboolean ephy_embed_container_get_is_popup (EphyEmbedContainer *container);
guint ephy_embed_container_get_n_children (EphyEmbedContainer *container);
G_END_DECLS
......@@ -37,7 +37,9 @@ typedef struct {
} PrefData;
#define DEFAULT_ENCODING_SETTING "default-charset"
// FIXME: Refactor this code to remove the need of those globals
static WebKitSettings *webkit_settings = NULL;
static GFileMonitor *user_style_sheet_monitor = NULL;
static void
user_style_sheet_output_stream_splice_cb (GOutputStream *output_stream,
......@@ -60,9 +62,9 @@ user_style_sheet_output_stream_splice_cb (GOutputStream *output_stream,
}
static void
user_style_seet_read_cb (GFile *file,
GAsyncResult *result,
gpointer user_data)
user_style_sheet_read_cb (GFile *file,
GAsyncResult *result,
gpointer user_data)
{
GFileInputStream *input_stream;
GOutputStream *output_stream;
......@@ -83,6 +85,21 @@ user_style_seet_read_cb (GFile *file,
g_object_unref (output_stream);
}
static void
user_style_sheet_file_changed (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer user_data)
{
if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT) {
webkit_user_content_manager_remove_all_style_sheets (WEBKIT_USER_CONTENT_MANAGER (ephy_embed_shell_get_user_content_manager (ephy_embed_shell_get_default ())));
g_file_read_async (file, G_PRIORITY_DEFAULT, NULL,
(GAsyncReadyCallback)user_style_sheet_read_cb, NULL);
}
}
static void
webkit_pref_callback_user_stylesheet (GSettings *settings,
const char *key,
......@@ -92,10 +109,12 @@ webkit_pref_callback_user_stylesheet (GSettings *settings,
value = g_settings_get_boolean (settings, key);
if (!value)
if (!value) {
g_clear_object (&user_style_sheet_monitor);
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 {
} else {
GFile *file;
GError *error = NULL;
char *filename;
filename = g_build_filename (ephy_dot_dir (), USER_STYLESHEET_FILENAME, NULL);
......@@ -103,7 +122,17 @@ webkit_pref_callback_user_stylesheet (GSettings *settings,
g_free (filename);
g_file_read_async (file, G_PRIORITY_DEFAULT, NULL,
(GAsyncReadyCallback)user_style_seet_read_cb, NULL);
(GAsyncReadyCallback)user_style_sheet_read_cb, NULL);
g_assert (user_style_sheet_monitor == NULL);
user_style_sheet_monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, &error);
if (user_style_sheet_monitor == NULL) {
g_warning ("Could not create a file monitor for %s: %s\n", g_file_get_uri (file), error->message);
g_error_free (error);
} else {
g_signal_connect (user_style_sheet_monitor, "changed", G_CALLBACK (user_style_sheet_file_changed), NULL);
}
g_object_unref (file);
}
}
......@@ -435,6 +464,17 @@ ephy_embed_prefs_init (gpointer user_data)
"javascript-can-open-windows-automatically", TRUE,
NULL);
/* Accelerated compositing mode is pretty broken right now.
* Disable it entirely as a workaround for these bugs:
*
* https://bugs.webkit.org/show_bug.cgi?id=192230
* https://bugs.webkit.org/show_bug.cgi?id=192276
* https://gitlab.gnome.org/GNOME/gtk/issues/1401
*
* Of course this should be reverted when the bugs are fixed.
*/
webkit_settings_set_hardware_acceleration_policy (webkit_settings, WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER);
for (i = 0; i < G_N_ELEMENTS (webkit_pref_entries); i++) {
GSettings *settings;
char *key;
......
......@@ -25,6 +25,7 @@
#include "ephy-about-handler.h"
#include "ephy-dbus-util.h"
#include "ephy-debug.h"
#include "ephy-downloads-manager.h"
#include "ephy-embed-container.h"
#include "ephy-embed-prefs.h"
#include "ephy-embed-type-builtins.h"
......@@ -348,7 +349,7 @@ typedef struct {
EphyEmbedShell *shell;
char *origin;
gint32 promise_id;
gint32 page_id;
guint64 page_id;
} PasswordManagerData;
static void
......@@ -369,7 +370,7 @@ password_manager_query_finished_cb (GList *records,
data->page_id,
data->origin);
if (proxy)
ephy_web_extension_proxy_password_query_response (proxy, username, password, data->promise_id);
ephy_web_extension_proxy_password_query_response (proxy, username, password, data->promise_id, data->page_id);
g_object_unref (data->shell);
g_free (data->origin);
......@@ -394,6 +395,14 @@ property_to_int32 (JSCValue *value,
return jsc_value_to_int32 (prop);
}
static int
property_to_uint64 (JSCValue *value,
const char *name)
{
g_autoptr(JSCValue) prop = jsc_value_object_get_property (value, name);
return (guint64)jsc_value_to_double (prop);
}
static void
web_extension_password_manager_query_received_cb (WebKitUserContentManager *manager,
WebKitJavascriptResult *message,
......@@ -407,7 +416,7 @@ web_extension_password_manager_query_received_cb (WebKitUserContentManager *mana
g_autofree char *username_field = property_to_string_or_null (value, "usernameField");
g_autofree char *password_field = property_to_string_or_null (value, "passwordField");
gint32 promise_id = property_to_int32 (value, "promiseID");
gint32 page_id = property_to_int32 (value, "pageID");
guint64 page_id = property_to_uint64 (value, "pageID");
PasswordManagerData *data = g_new (PasswordManagerData, 1);
data->shell = g_object_ref (shell);
......@@ -482,7 +491,7 @@ web_extension_password_manager_save_real (EphyEmbedShell *shell,
g_autofree char *password_field = property_to_string_or_null (value, "passwordField");
g_autoptr(JSCValue) is_new_prop = jsc_value_object_get_property (value, "isNew");
gboolean is_new = jsc_value_to_boolean (is_new_prop);
gint32 page_id = property_to_int32 (value, "pageID");
guint64 page_id = property_to_uint64 (value, "pageID");
EphyWebView *view;
/* Both password and password field are required. */
......@@ -552,9 +561,9 @@ web_extension_password_manager_cached_users_received_cb (WebKitUserContentManage
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
JSCValue *value = webkit_javascript_result_get_js_value (message);
g_autofree char *origin = jsc_value_to_string (jsc_value_object_get_property (value, "origin"));
gint32 promise_id = jsc_value_to_int32 (jsc_value_object_get_property (value, "promiseID"));
gint32 page_id = jsc_value_to_int32 (jsc_value_object_get_property (value, "pageID"));
g_autofree char *origin = property_to_string_or_null (value, "origin");
gint32 promise_id = property_to_int32 (value, "promiseID");
guint64 page_id = property_to_uint64 (value, "pageID");
GList *cached_users;
cached_users = ephy_password_manager_get_cached_users (priv->password_manager, origin);
......@@ -562,7 +571,7 @@ web_extension_password_manager_cached_users_received_cb (WebKitUserContentManage
EphyWebExtensionProxy *proxy = ephy_embed_shell_get_extension_proxy_for_page_id (
shell, page_id, origin);
if (proxy)
ephy_web_extension_proxy_password_cached_users_response (proxy, cached_users, promise_id);
ephy_web_extension_proxy_password_cached_users_response (proxy, cached_users, promise_id, page_id);
}
static void
......@@ -755,6 +764,7 @@ ephy_embed_shell_get_global_history_service (EphyEmbedShell *shell)
EphySQLiteConnectionMode mode;
if (priv->mode == EPHY_EMBED_SHELL_MODE_INCOGNITO ||
priv->mode == EPHY_EMBED_SHELL_MODE_AUTOMATION ||
priv->mode == EPHY_EMBED_SHELL_MODE_SEARCH_PROVIDER)
mode = EPHY_SQLITE_CONNECTION_MODE_READ_ONLY;
else
......@@ -957,7 +967,7 @@ initialize_web_extensions (WebKitWebContext *web_context,
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;
user_data = g_variant_new ("(smsssbb)",
priv->guid,
......@@ -1100,6 +1110,12 @@ ephy_embed_shell_create_web_context (EphyEmbedShell *shell)
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 ?
ephy_dot_dir () : g_get_user_data_dir (),
g_get_prgname (), NULL);
......@@ -1134,6 +1150,44 @@ adblock_filters_dir (EphyEmbedShell *shell)
return result;
}
static void
download_started_cb (WebKitWebContext *web_context,
WebKitDownload *download,
EphyEmbedShell *shell)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
EphyDownload *ephy_download;
EphyEmbed *embed;
GtkWindow *window;
gboolean ephy_download_set;
/* Is download locked down? */
if (g_settings_get_boolean (EPHY_SETTINGS_LOCKDOWN,
EPHY_PREFS_LOCKDOWN_SAVE_TO_DISK)) {
webkit_download_cancel (download);
return;
}
/* Only create an EphyDownload for the WebKitDownload if it doesn't exist yet.
* This can happen when the download has been started automatically by WebKit,
* due to a context menu action or policy checker decision. Downloads started
* explicitly by Epiphany are marked with ephy-download-set GObject data.
*/
ephy_download_set = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (download), "ephy-download-set"));
if (ephy_download_set)
return;
ephy_download = ephy_download_new (download);
window = gtk_application_get_active_window (GTK_APPLICATION (shell));
embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
if (embed != NULL)
ephy_embed_download_started (embed, ephy_download);
ephy_downloads_manager_add_download (priv->downloads_manager, ephy_download);
g_object_unref (ephy_download);
}
static void
ephy_embed_shell_startup (GApplication *application)
{
......@@ -1215,8 +1269,6 @@ ephy_embed_shell_startup (GApplication *application)
G_CALLBACK (web_extension_password_manager_request_save_received_cb),
shell);
webkit_web_context_set_sandbox_enabled (priv->web_context, TRUE);
ephy_embed_shell_setup_process_model (shell);
g_signal_connect_object (priv->web_context, "initialize-web-extensions",
G_CALLBACK (initialize_web_extensions),
......@@ -1229,17 +1281,21 @@ ephy_embed_shell_startup (GApplication *application)
priv->password_manager = ephy_password_manager_new ();
/* Favicon Database */
if (priv->mode == EPHY_EMBED_SHELL_MODE_PRIVATE)
favicon_db_path = g_build_filename (ephy_dot_dir (), "icondatabase", NULL);
else
favicon_db_path = g_build_filename (g_get_user_cache_dir (), "epiphany", "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);
/* Do not cache favicons in automation mode. Don't change the TLS policy either, since that's
* handled by session capabilities in automation mode.
*/
if (priv->mode != EPHY_EMBED_SHELL_MODE_AUTOMATION) {
/* Favicon Database */
if (priv->mode == EPHY_EMBED_SHELL_MODE_PRIVATE)
favicon_db_path = g_build_filename (ephy_dot_dir (), "icondatabase", NULL);
else
favicon_db_path = g_build_filename (g_get_user_cache_dir (), "epiphany", "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 ();
......@@ -1270,7 +1326,7 @@ ephy_embed_shell_startup (GApplication *application)
/* Store cookies in moz-compatible SQLite format */
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);
webkit_cookie_manager_set_persistent_storage (cookie_manager, filename,
WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE);
......@@ -1285,6 +1341,9 @@ ephy_embed_shell_startup (GApplication *application)
filters_dir = adblock_filters_dir (shell);
priv->filters_manager = ephy_filters_manager_new (filters_dir);
g_free (filters_dir);
g_signal_connect (priv->web_context, "download-started",
G_CALLBACK (download_started_cb), shell);
}
static void
......@@ -1666,50 +1725,6 @@ ephy_embed_shell_get_mode (EphyEmbedShell *shell)
return priv->mode;
}
/**
* ephy_embed_shell_launch_handler:
* @shell: an #EphyEmbedShell
* @file: a #GFile to open
* @mime_type: the mime type of @file or %NULL
* @user_time: user time to prevent focus stealing
*
* Tries to open @file with the right application, making sure we will
* not call ourselves in the process. This is needed to avoid
* potential infinite loops when opening unknown file types.
*
* Returns: %TRUE on success
**/
gboolean
ephy_embed_shell_launch_handler (EphyEmbedShell *shell,
GFile *file,
const char *mime_type,
guint32 user_time)
{
GAppInfo *app;
GList *list = NULL;
gboolean ret = FALSE;
g_assert (EPHY_IS_EMBED_SHELL (shell));
g_assert (file || mime_type);
if (ephy_is_running_inside_flatpak ()) {
return ephy_file_launch_file_via_uri_handler (file);
}
app = ephy_file_launcher_get_app_info_for_file (file, mime_type);
/* Do not allow recursive calls into the browser, they can lead to
* infinite loops and they should never happen anyway. */
if (!app || g_strcmp0 (g_app_info_get_id (app), "org.gnome.Epiphany.desktop") == 0)
return ret;
list = g_list_append (list, file);
ret = ephy_file_launch_application (app, list, user_time, NULL);
g_list_free (list);
return ret;
}
/**
* ephy_embed_shell_clear_cache:
* @shell: an #EphyEmbedShell
......
......@@ -46,7 +46,8 @@ typedef enum
EPHY_EMBED_SHELL_MODE_INCOGNITO,
EPHY_EMBED_SHELL_MODE_APPLICATION,
EPHY_EMBED_SHELL_MODE_TEST,
EPHY_EMBED_SHELL_MODE_SEARCH_PROVIDER
EPHY_EMBED_SHELL_MODE_SEARCH_PROVIDER,
EPHY_EMBED_SHELL_MODE_AUTOMATION
} EphyEmbedShellMode;
struct _EphyEmbedShellClass
......@@ -71,10 +72,6 @@ void ephy_embed_shell_set_print_settings (EphyEmbedShell
GtkPrintSettings *settings);
GtkPrintSettings *ephy_embed_shell_get_print_settings (EphyEmbedShell *shell);
EphyEmbedShellMode ephy_embed_shell_get_mode (EphyEmbedShell *shell);
gboolean ephy_embed_shell_launch_handler (EphyEmbedShell *shell,
GFile *file,
const char *mime_type,
guint32 user_time);
void ephy_embed_shell_clear_cache (EphyEmbedShell *shell);
void ephy_embed_shell_set_thumbnail_path (EphyEmbedShell *shell,
const char *url,
......
......@@ -30,6 +30,7 @@
#include "ephy-string.h"
#include "ephy-view-source-handler.h"
#include <evince-document.h>
#include <glib/gi18n.h>
#include <jsc/jsc.h>
#include <libsoup/soup.h>
......@@ -304,11 +305,35 @@ ephy_embed_utils_autosearch_address (const char *search_key)
return effective_address;
}
static char *
ensure_host_name_is_lowercase (const char *address)
{
g_autofree gchar *host = ephy_string_get_host_name (address);
g_autofree gchar *lowercase_host = NULL;
char *ret = NULL;
if (host == NULL) {
return g_strdup (address);
}
lowercase_host = g_utf8_strdown (host, -1);
if (strcmp (host, lowercase_host) != 0) {
ret = ephy_string_find_and_replace (address, host, lowercase_host);
} else {
ret = g_strdup (address);
}
return ret;
}
char *
ephy_embed_utils_normalize_or_autosearch_address (const char *address)
{
if (ephy_embed_utils_address_is_valid (address))
return ephy_embed_utils_normalize_address (address);
g_autofree gchar *lower_case_address = ensure_host_name_is_lowercase (address);
if (ephy_embed_utils_address_is_valid (lower_case_address))
return ephy_embed_utils_normalize_address (lower_case_address);
else
return ephy_embed_utils_autosearch_address (address);
}
......@@ -391,3 +416,27 @@ ephy_embed_utils_shutdown (void)
g_clear_pointer (&non_search_regex, g_regex_unref);
g_clear_pointer (&domain_regex, g_regex_unref);
}
gboolean
ephy_embed_utils_mime_type_is_supported_evince_document (const char *mime_type)
{
GList *doc_types = ev_backends_manager_get_all_types_info ();
GList *l;
gboolean found = FALSE;
for (l = doc_types; l != NULL && !found; l = l->next) {
EvTypeInfo *info = (EvTypeInfo *)l->data;
guint i;
for (i = 0; info->mime_types[i] != NULL; ++i) {
if (g_ascii_strcasecmp (mime_type, info->mime_types[i]) == 0) {
found = TRUE;
break;
}
}
}
g_list_free (doc_types);
return found;
}
......@@ -36,18 +36,19 @@ G_BEGIN_DECLS
#define EPHY_WEBKIT_BACK_FORWARD_LIMIT 100
char* ephy_embed_utils_link_message_parse (const char *message);
gboolean ephy_embed_utils_address_has_web_scheme (const char *address);
gboolean ephy_embed_utils_address_is_existing_absolute_filename (const char *address);
gboolean ephy_embed_utils_address_is_valid (const char *address);
char* ephy_embed_utils_normalize_address (const char *address);
char * ephy_embed_utils_autosearch_address (const char *search_key);
char * ephy_embed_utils_normalize_or_autosearch_address (const char *address);
gboolean ephy_embed_utils_url_is_empty (const char *location);
gboolean ephy_embed_utils_is_no_show_address (const char *address);
char *ephy_embed_utils_get_title_from_address (const char *address);
gboolean ephy_embed_utils_urls_have_same_origin (const char *a_url,
const char *b_url);
void ephy_embed_utils_shutdown (void);
char* ephy_embed_utils_link_message_parse (const char *message);
gboolean ephy_embed_utils_address_has_web_scheme (const char *address);
gboolean ephy_embed_utils_address_is_existing_absolute_filename (const char *address);
gboolean ephy_embed_utils_address_is_valid (const char *address);
char* ephy_embed_utils_normalize_address (const char *address);
char * ephy_embed_utils_autosearch_address (const char *search_key);
char * ephy_embed_utils_normalize_or_autosearch_address (const char *address);
gboolean ephy_embed_utils_url_is_empty (const char *location);
gboolean ephy_embed_utils_is_no_show_address (const char *address);
char *ephy_embed_utils_get_title_from_address (const char *address);
gboolean ephy_embed_utils_urls_have_same_origin (const char *a_url,
const char *b_url);
void ephy_embed_utils_shutdown (void);
gboolean ephy_embed_utils_mime_type_is_supported_evince_document (const char *mime_type);
G_END_DECLS
......@@ -29,6 +29,7 @@
#include "ephy-embed-prefs.h"
#include "ephy-embed-shell.h"
#include "ephy-embed-utils.h"
#include "ephy-evince-document-view.h"
#include "ephy-find-toolbar.h"
#include "ephy-notification-container.h"
#include "ephy-prefs.h"
......@@ -65,6 +66,7 @@ struct _EphyEmbed {
GtkWidget *floating_bar;
GtkWidget *progress;
GtkWidget *fullscreen_message_label;
GtkWidget *document_view;
char *title;
WebKitURIRequest *delayed_request;
......@@ -74,6 +76,8 @@ struct _EphyEmbed {
GSList *messages;
GSList *keys;
EphyEmbedMode mode;
guint seq_context_id;
guint seq_message_id;
......@@ -183,7 +187,7 @@ ephy_embed_statusbar_push (EphyEmbed *embed, guint context_id, const char *text)
g_assert (context_id != 0);
g_assert (text != NULL);
msg = g_slice_new (EphyEmbedStatusbarMsg);
msg = g_new (EphyEmbedStatusbarMsg, 1);
msg->text = g_strdup (text);
msg->context_id = context_id;
msg->message_id = embed->seq_message_id++;
......@@ -212,7 +216,7 @@ ephy_embed_statusbar_pop (EphyEmbed *embed, guint context_id)
if (msg->context_id == context_id) {
embed->messages = g_slist_remove_link (embed->messages, list);
g_free (msg->text);
g_slice_free (EphyEmbedStatusbarMsg, msg);
g_free (msg);
g_slist_free_1 (list);
break;
}
......@@ -414,7 +418,7 @@ ephy_embed_finalize (GObject *object)
msg = list->data;
g_free (msg->text);
g_slice_free (EphyEmbedStatusbarMsg, msg);
g_free (msg);
}
g_slist_free (embed->messages);
......@@ -750,6 +754,7 @@ ephy_embed_constructed (GObject *object)
gtk_widget_set_no_show_all (embed->floating_bar, TRUE);
gtk_overlay_add_overlay (GTK_OVERLAY (embed->overlay), embed->floating_bar);
gtk_overlay_set_overlay_pass_through (GTK_OVERLAY (embed->overlay), embed->floating_bar, TRUE);
if (embed->progress_bar_enabled) {
embed->progress = gtk_progress_bar_new ();
......@@ -807,6 +812,21 @@ ephy_embed_constructed (GObject *object)
g_signal_connect (inspector, "closed",
G_CALLBACK (ephy_embed_close_inspector_cb),
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);
/* Translators: this means WebDriver control. */
label = gtk_label_new (_("Web is being controlled by automation."));
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
......@@ -1002,3 +1022,61 @@ ephy_embed_detach_notification_container (EphyEmbed *embed)
gtk_container_remove (GTK_CONTAINER (embed->overlay), g_object_ref (GTK_WIDGET (container)));
}
}
void
ephy_embed_set_mode (EphyEmbed *embed, EphyEmbedMode mode)
{
g_assert (EPHY_IS_EMBED (embed));
if (embed->mode == mode)
return;
switch (mode) {
case EPHY_EMBED_MODE_WEB_VIEW:
if (embed->document_view != NULL) {
gtk_widget_destroy (embed->document_view);
embed->document_view = NULL;
}
gtk_widget_set_visible (GTK_WIDGET (embed->paned), TRUE);
break;
case EPHY_EMBED_MODE_EVINCE_DOCUMENT:
gtk_widget_set_visible (GTK_WIDGET (embed->paned), FALSE);
embed->document_view = ephy_evince_document_view_new ();
ephy_evince_document_set_embed (EPHY_EVINCE_DOCUMENT_VIEW (embed->document_view), embed);
gtk_box_pack_start (GTK_BOX (embed),
embed->document_view,
TRUE, TRUE, 0);
gtk_widget_show_all (embed->document_view);
break;
}
embed->mode = mode;
}
EphyEmbedMode
ephy_embed_get_mode (EphyEmbed *embed)
{
return embed->mode;
}
static void
document_download_finished_cb (WebKitDownload *download,
EphyEmbed *embed)
{
const char *document_uri = webkit_download_get_destination (download);
ephy_evince_document_view_load_uri (EPHY_EVINCE_DOCUMENT_VIEW (embed->document_view),
document_uri);
}
void
ephy_embed_download_started (EphyEmbed *embed,
EphyDownload *ephy_download)
{
WebKitDownload *download = ephy_download_get_webkit_download (ephy_download);
if (embed->mode == EPHY_EMBED_MODE_EVINCE_DOCUMENT) {
ephy_download_enable_evince_document_mode (ephy_download);
g_signal_connect (download, "finished", G_CALLBACK (document_download_finished_cb), embed);
}
}
......@@ -37,6 +37,11 @@ typedef enum {
EPHY_EMBED_TOP_WIDGET_POLICY_DESTROY_ON_TRANSITION
} EphyEmbedTopWidgetPolicy;
typedef enum {
EPHY_EMBED_MODE_WEB_VIEW,
EPHY_EMBED_MODE_EVINCE_DOCUMENT
} EphyEmbedMode;
EphyWebView* ephy_embed_get_web_view (EphyEmbed *embed);
EphyFindToolbar* ephy_embed_get_find_toolbar (EphyEmbed *embed);
void ephy_embed_add_top_widget (EphyEmbed *embed,
......@@ -54,5 +59,10 @@ gboolean ephy_embed_inspector_is_loaded (EphyEmbed *embed);
const char *ephy_embed_get_title (EphyEmbed *embed);
void ephy_embed_attach_notification_container (EphyEmbed *embed);
void ephy_embed_detach_notification_container (EphyEmbed *embed);
void ephy_embed_set_mode (EphyEmbed *embed,
EphyEmbedMode mode);
EphyEmbedMode ephy_embed_get_mode (EphyEmbed *embed);
void ephy_embed_download_started (EphyEmbed *embed,
EphyDownload *ephy_download);
G_END_DECLS
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
/* vim: set sw=2 ts=2 sts=2 et: */
/*
* Copyright © 2012 Igalia S.L.
* Copyright © 2018 Jan-Michael Brummer
*
* 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.
*
*/
#include "config.h"
#include "ephy-evince-document-view.h"
#include "ephy-embed-shell.h"
#include <evince-view.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <libsoup/soup.h>
struct _EphyEvinceDocumentView {
GtkBox parent_instance;
GtkWidget *view;
GtkWidget *current_page;
GtkWidget *total_page;
GtkWidget *sizing_mode;
GtkWidget *popup;
EphyEmbed *embed;
EvJob *job;
EvDocumentModel *model;
SoupURI *uri;
};
G_DEFINE_TYPE (EphyEvinceDocumentView, ephy_evince_document_view, GTK_TYPE_BOX)
static void
ephy_evince_document_view_finalize (GObject *object)
{
EphyEvinceDocumentView *self = EPHY_EVINCE_DOCUMENT_VIEW (object);
if (self->uri != NULL) {
g_unlink (self->uri->path);
g_clear_pointer (&self->uri, soup_uri_free);
}
if (self->job != NULL) {
ev_job_cancel (self->job);
g_clear_object (&self->job);
}
g_clear_object (&self->model);
G_OBJECT_CLASS (ephy_evince_document_view_parent_class)->finalize (object);
}
static void
on_save_button_clicked (GtkButton *button,
EphyEvinceDocumentView *self)
{
g_autoptr (GtkFileChooserNative) native = NULL;
GtkFileChooser *chooser;
GError *error = NULL;
gint res;
g_autofree gchar *basename = g_path_get_basename (self->uri->path);
native = gtk_file_chooser_native_new (_("Save File"),
NULL,
GTK_FILE_CHOOSER_ACTION_SAVE,
NULL,
NULL);
chooser = GTK_FILE_CHOOSER (native);
gtk_file_chooser_set_do_overwrite_confirmation (chooser, TRUE);
gtk_file_chooser_set_current_name (chooser, basename);
res = gtk_native_dialog_run (GTK_NATIVE_DIALOG (native));
if (res == GTK_RESPONSE_ACCEPT) {
g_autofree gchar *filename;
GFile *source = g_file_new_for_uri (self->uri->path);
GFile *dest;
filename = gtk_file_chooser_get_filename (chooser);
dest = g_file_new_for_path (filename);
if (!g_file_copy (source, dest, G_FILE_COPY_NONE, NULL, NULL, NULL, &error)) {
g_warning ("%s(): Could not copy file: %s\n", __FUNCTION__, error->message);
g_error_free (error);
}
}
}
static void
view_external_link_cb (EvView *view,
EvLinkAction *action,
EphyEvinceDocumentView *self)
{
EvLinkActionType type = ev_link_action_get_action_type (action);
EphyWebView *webview;
const gchar *url;
if (type != EV_LINK_ACTION_TYPE_EXTERNAL_URI)
return;
url = ev_link_action_get_uri (action);
webview = ephy_embed_get_web_view (self->embed);
ephy_web_view_load_url (webview, url);
}
static void
ephy_evince_document_view_constructed (GObject *object)
{
EphyEvinceDocumentView *self = EPHY_EVINCE_DOCUMENT_VIEW (object);
GtkWidget *box;
GtkWidget *entry_box;
GtkWidget *save_button;
GtkWidget *scrolled_window;
GtkWidget *separator;
G_OBJECT_CLASS (ephy_evince_document_view_parent_class)->constructed (object);
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
self->view = ev_view_new ();
g_signal_connect (self->view, "external-link", G_CALLBACK (view_external_link_cb), self);
gtk_container_add (GTK_CONTAINER (scrolled_window), self->view);
gtk_box_pack_start (GTK_BOX (self), scrolled_window, TRUE, TRUE, 0);
self->model = ev_document_model_new ();
ev_view_set_model (EV_VIEW (self->view), self->model);
separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
gtk_box_pack_start (GTK_BOX (self), separator, FALSE, TRUE, 0);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_widget_set_margin_start (box, 6);
gtk_widget_set_margin_end (box, 6);
gtk_widget_set_margin_top (box, 6);
gtk_widget_set_margin_bottom (box, 6);
gtk_box_pack_start (GTK_BOX (self), box, FALSE, TRUE, 0);
entry_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_style_context_add_class (gtk_widget_get_style_context (entry_box), GTK_STYLE_CLASS_LINKED);
gtk_style_context_add_class (gtk_widget_get_style_context (entry_box), GTK_STYLE_CLASS_RAISED);
gtk_box_pack_start (GTK_BOX (box), entry_box, FALSE, TRUE, 0);
self->current_page = gtk_entry_new ();
gtk_entry_set_width_chars (GTK_ENTRY (self->current_page), 2);
gtk_box_pack_start (GTK_BOX (entry_box), self->current_page, FALSE, TRUE, 0);
self->total_page = gtk_entry_new ();
gtk_entry_set_width_chars (GTK_ENTRY (self->total_page), 5);
gtk_widget_set_sensitive (self->total_page, FALSE);
gtk_box_pack_start (GTK_BOX (entry_box), self->total_page, FALSE, TRUE, 0);
save_button = gtk_button_new_from_icon_name ("document-save-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR);
g_signal_connect (save_button, "clicked", G_CALLBACK (on_save_butt