Revert "Merge branch 'mjog/558-webkit-shared-process' into 'mainline'"
Revert merge request GNOME/geary!374 for now since the shared process model breaks old-style WebProcess message handler IPC. This can be un-reverted when out JS is ported to the new Messages API that is landing in WebKitGTK 2.28. This reverts commite4a5b85698, reversing changes made to66f6525480.
This commit is contained in:
parent
d9c10b5f20
commit
cbe6e0ba9b
28 changed files with 240 additions and 406 deletions
|
|
@ -101,7 +101,6 @@
|
||||||
<li>Extend undo for email actions such as archiving, marking</li>
|
<li>Extend undo for email actions such as archiving, marking</li>
|
||||||
<li>Undo sending, saving and discarding composed email</li>
|
<li>Undo sending, saving and discarding composed email</li>
|
||||||
<li>Undo editing in text fields, including in the composer</li>
|
<li>Undo editing in text fields, including in the composer</li>
|
||||||
<li>Conversation loading performance improvements</li>
|
|
||||||
<li>App-wide notification preferences now handled by desktop</li>
|
<li>App-wide notification preferences now handled by desktop</li>
|
||||||
<li>Improved missing attachment detection in composer</li>
|
<li>Improved missing attachment detection in composer</li>
|
||||||
<li>Initial plugin system</li>
|
<li>Initial plugin system</li>
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ src/client/application/goa-mediator.vala
|
||||||
src/client/application/main.vala
|
src/client/application/main.vala
|
||||||
src/client/application/secret-mediator.vala
|
src/client/application/secret-mediator.vala
|
||||||
src/client/client-action.vala
|
src/client/client-action.vala
|
||||||
|
src/client/components/client-web-view.vala
|
||||||
src/client/components/components-attachment-pane.vala
|
src/client/components/components-attachment-pane.vala
|
||||||
src/client/components/components-entry-undo.vala
|
src/client/components/components-entry-undo.vala
|
||||||
src/client/components/components-in-app-notification.vala
|
src/client/components/components-in-app-notification.vala
|
||||||
|
|
@ -39,7 +40,6 @@ src/client/components/components-placeholder-pane.vala
|
||||||
src/client/components/components-preferences-window.vala
|
src/client/components/components-preferences-window.vala
|
||||||
src/client/components/components-search-bar.vala
|
src/client/components/components-search-bar.vala
|
||||||
src/client/components/components-validator.vala
|
src/client/components/components-validator.vala
|
||||||
src/client/components/components-web-view.vala
|
|
||||||
src/client/components/count-badge.vala
|
src/client/components/count-badge.vala
|
||||||
src/client/components/folder-popover.vala
|
src/client/components/folder-popover.vala
|
||||||
src/client/components/icon-factory.vala
|
src/client/components/icon-factory.vala
|
||||||
|
|
|
||||||
|
|
@ -718,7 +718,7 @@ internal class Accounts.RemoveMailboxCommand : Application.Command {
|
||||||
internal class Accounts.SignatureChangedCommand : Application.Command {
|
internal class Accounts.SignatureChangedCommand : Application.Command {
|
||||||
|
|
||||||
|
|
||||||
private Components.WebView signature_view;
|
private ClientWebView signature_view;
|
||||||
private Geary.AccountInformation account;
|
private Geary.AccountInformation account;
|
||||||
|
|
||||||
private string old_value;
|
private string old_value;
|
||||||
|
|
@ -728,7 +728,7 @@ internal class Accounts.SignatureChangedCommand : Application.Command {
|
||||||
private bool new_enabled = false;
|
private bool new_enabled = false;
|
||||||
|
|
||||||
|
|
||||||
public SignatureChangedCommand(Components.WebView signature_view,
|
public SignatureChangedCommand(ClientWebView signature_view,
|
||||||
Geary.AccountInformation account) {
|
Geary.AccountInformation account) {
|
||||||
this.signature_view = signature_view;
|
this.signature_view = signature_view;
|
||||||
this.account = account;
|
this.account = account;
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,14 @@
|
||||||
/**
|
/**
|
||||||
* A class for editing signatures in the accounts editor.
|
* A class for editing signatures in the accounts editor.
|
||||||
*/
|
*/
|
||||||
public class Accounts.SignatureWebView : Components.WebView {
|
public class Accounts.SignatureWebView : ClientWebView {
|
||||||
|
|
||||||
|
|
||||||
private static WebKit.UserScript? app_script = null;
|
private static WebKit.UserScript? app_script = null;
|
||||||
|
|
||||||
public static new void load_resources()
|
public static new void load_resources()
|
||||||
throws GLib.Error {
|
throws GLib.Error {
|
||||||
SignatureWebView.app_script = Components.WebView.load_app_script(
|
SignatureWebView.app_script = ClientWebView.load_app_script(
|
||||||
"signature-web-view.js"
|
"signature-web-view.js"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -135,12 +135,13 @@ internal class Application.Controller : Geary.BaseObject {
|
||||||
this.upgrade_dialog = new UpgradeDialog(application);
|
this.upgrade_dialog = new UpgradeDialog(application);
|
||||||
|
|
||||||
// Initialise WebKit and WebViews
|
// Initialise WebKit and WebViews
|
||||||
Components.WebView.init_web_context(
|
ClientWebView.init_web_context(
|
||||||
this.application.config,
|
this.application.config,
|
||||||
this.application.get_web_extensions_dir(),
|
this.application.get_web_extensions_dir(),
|
||||||
this.application.get_user_cache_directory().get_child("web-resources")
|
this.application.get_user_cache_directory().get_child("web-resources")
|
||||||
);
|
);
|
||||||
Components.WebView.load_resources(
|
|
||||||
|
ClientWebView.load_resources(
|
||||||
this.application.get_user_config_directory()
|
this.application.get_user_config_directory()
|
||||||
);
|
);
|
||||||
Composer.WebView.load_resources();
|
Composer.WebView.load_resources();
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,12 @@ int main(string[] args) {
|
||||||
Environment.set_variable("G_TLS_GNUTLS_PRIORITY", "NORMAL:%COMPAT:!VERS-SSL3.0", false);
|
Environment.set_variable("G_TLS_GNUTLS_PRIORITY", "NORMAL:%COMPAT:!VERS-SSL3.0", false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Temporary workaround for WebKitGTK deprecation of the
|
||||||
|
// shared-secondary process model. Pull this out in 3.36 when the
|
||||||
|
// proper fix lands. See GNOME/geary#558.
|
||||||
|
Environment.set_variable("WEBKIT_USE_SINGLE_WEB_PROCESS", "1", true);
|
||||||
|
|
||||||
|
|
||||||
// Init logging right up front so as to capture as many log
|
// Init logging right up front so as to capture as many log
|
||||||
// messages as possible
|
// messages as possible
|
||||||
Geary.Logging.init();
|
Geary.Logging.init();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2016 Software Freedom Conservancy Inc.
|
* Copyright 2016 Software Freedom Conservancy Inc.
|
||||||
* Copyright 2016-2019 Michael Gratton <mike@vee.net>
|
* Copyright 2016 Michael Gratton <mike@vee.net>
|
||||||
*
|
*
|
||||||
* This software is licensed under the GNU Lesser General Public License
|
* This software is licensed under the GNU Lesser General Public License
|
||||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* integration, Inspector support, and remote and inline image
|
* integration, Inspector support, and remote and inline image
|
||||||
* handling.
|
* handling.
|
||||||
*/
|
*/
|
||||||
public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
public abstract class ClientWebView : WebKit.WebView, Geary.BaseInterface {
|
||||||
|
|
||||||
|
|
||||||
/** URI Scheme and delimiter for internal resource loads. */
|
/** URI Scheme and delimiter for internal resource loads. */
|
||||||
|
|
@ -65,6 +65,7 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||||
private static WebKit.UserStyleSheet? user_stylesheet = null;
|
private static WebKit.UserStyleSheet? user_stylesheet = null;
|
||||||
|
|
||||||
private static WebKit.UserScript? script = null;
|
private static WebKit.UserScript? script = null;
|
||||||
|
private static WebKit.UserScript? allow_remote_images = null;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -75,18 +76,23 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||||
File cache_dir) {
|
File cache_dir) {
|
||||||
WebsiteDataManager data_manager = new WebsiteDataManager(cache_dir.get_path());
|
WebsiteDataManager data_manager = new WebsiteDataManager(cache_dir.get_path());
|
||||||
WebKit.WebContext context = new WebKit.WebContext.with_website_data_manager(data_manager);
|
WebKit.WebContext context = new WebKit.WebContext.with_website_data_manager(data_manager);
|
||||||
|
#if HAS_WEBKIT_SHARED_PROC
|
||||||
|
// Use a shared process so we don't spawn N WebProcess instances
|
||||||
|
// when showing N messages in a conversation.
|
||||||
|
context.set_process_model(WebKit.ProcessModel.SHARED_SECONDARY_PROCESS);
|
||||||
|
#endif
|
||||||
// Use the doc viewer model since each web view instance only
|
// Use the doc viewer model since each web view instance only
|
||||||
// ever shows a single HTML document.
|
// ever shows a single HTML document.
|
||||||
context.set_cache_model(WebKit.CacheModel.DOCUMENT_VIEWER);
|
context.set_cache_model(WebKit.CacheModel.DOCUMENT_VIEWER);
|
||||||
|
|
||||||
context.register_uri_scheme("cid", (req) => {
|
context.register_uri_scheme("cid", (req) => {
|
||||||
WebView? view = req.get_web_view() as WebView;
|
ClientWebView? view = req.get_web_view() as ClientWebView;
|
||||||
if (view != null) {
|
if (view != null) {
|
||||||
view.handle_cid_request(req);
|
view.handle_cid_request(req);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
context.register_uri_scheme("geary", (req) => {
|
context.register_uri_scheme("geary", (req) => {
|
||||||
WebView? view = req.get_web_view() as WebView;
|
ClientWebView? view = req.get_web_view() as ClientWebView;
|
||||||
if (view != null) {
|
if (view != null) {
|
||||||
view.handle_internal_request(req);
|
view.handle_internal_request(req);
|
||||||
}
|
}
|
||||||
|
|
@ -107,22 +113,25 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||||
update_spellcheck(context, config);
|
update_spellcheck(context, config);
|
||||||
});
|
});
|
||||||
|
|
||||||
WebView.default_context = context;
|
ClientWebView.default_context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads static resources used by WebView.
|
* Loads static resources used by ClientWebView.
|
||||||
*/
|
*/
|
||||||
public static void load_resources(GLib.File user_dir)
|
public static void load_resources(GLib.File user_dir)
|
||||||
throws GLib.Error {
|
throws GLib.Error {
|
||||||
WebView.script = load_app_script(
|
ClientWebView.script = load_app_script(
|
||||||
"components-web-view.js"
|
"client-web-view.js"
|
||||||
|
);
|
||||||
|
ClientWebView.allow_remote_images = load_app_script(
|
||||||
|
"client-web-view-allow-remote-images.js"
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach (string name in new string[] { USER_CSS, USER_CSS_LEGACY }) {
|
foreach (string name in new string[] { USER_CSS, USER_CSS_LEGACY }) {
|
||||||
GLib.File stylesheet = user_dir.get_child(name);
|
GLib.File stylesheet = user_dir.get_child(name);
|
||||||
try {
|
try {
|
||||||
WebView.user_stylesheet = load_user_stylesheet(stylesheet);
|
ClientWebView.user_stylesheet = load_user_stylesheet(stylesheet);
|
||||||
break;
|
break;
|
||||||
} catch (GLib.IOError.NOT_FOUND err) {
|
} catch (GLib.IOError.NOT_FOUND err) {
|
||||||
// All good, try the next one or just exit
|
// All good, try the next one or just exit
|
||||||
|
|
@ -290,9 +299,8 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||||
public signal void remote_image_load_blocked();
|
public signal void remote_image_load_blocked();
|
||||||
|
|
||||||
|
|
||||||
protected WebView(Application.Configuration config,
|
protected ClientWebView(Application.Configuration config,
|
||||||
WebKit.UserContentManager? custom_manager = null,
|
WebKit.UserContentManager? custom_manager = null) {
|
||||||
WebView? related = null) {
|
|
||||||
WebKit.Settings setts = new WebKit.Settings();
|
WebKit.Settings setts = new WebKit.Settings();
|
||||||
setts.allow_modal_dialogs = false;
|
setts.allow_modal_dialogs = false;
|
||||||
setts.default_charset = "UTF-8";
|
setts.default_charset = "UTF-8";
|
||||||
|
|
@ -313,40 +321,62 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||||
|
|
||||||
WebKit.UserContentManager content_manager =
|
WebKit.UserContentManager content_manager =
|
||||||
custom_manager ?? new WebKit.UserContentManager();
|
custom_manager ?? new WebKit.UserContentManager();
|
||||||
content_manager.add_script(WebView.script);
|
content_manager.add_script(ClientWebView.script);
|
||||||
if (WebView.user_stylesheet != null) {
|
if (ClientWebView.user_stylesheet != null) {
|
||||||
content_manager.add_style_sheet(WebView.user_stylesheet);
|
content_manager.add_style_sheet(ClientWebView.user_stylesheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object(
|
Object(
|
||||||
settings: setts,
|
web_context: ClientWebView.default_context,
|
||||||
user_content_manager: content_manager,
|
user_content_manager: content_manager,
|
||||||
web_context: WebView.default_context
|
settings: setts
|
||||||
);
|
);
|
||||||
base_ref();
|
base_ref();
|
||||||
init(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// XXX get the allow prefix from the extension somehow
|
||||||
* Constructs a new web view with a new shared WebProcess.
|
|
||||||
*
|
this.decide_policy.connect(on_decide_policy);
|
||||||
* The new view will use the same WebProcess, settings and content
|
this.web_process_terminated.connect((reason) => {
|
||||||
* manager as the given related view's.
|
warning("Web process crashed: %s", reason.to_string());
|
||||||
*
|
});
|
||||||
* @see WebKit.WebView.with_related_view
|
|
||||||
*/
|
register_message_handler(
|
||||||
protected WebView.with_related_view(Application.Configuration config,
|
COMMAND_STACK_CHANGED, on_command_stack_changed
|
||||||
WebView related) {
|
|
||||||
Object(
|
|
||||||
related_view: related,
|
|
||||||
settings: related.get_settings(),
|
|
||||||
user_content_manager: related.user_content_manager
|
|
||||||
);
|
);
|
||||||
base_ref();
|
register_message_handler(
|
||||||
init(config);
|
CONTENT_LOADED, on_content_loaded
|
||||||
|
);
|
||||||
|
register_message_handler(
|
||||||
|
DOCUMENT_MODIFIED, on_document_modified
|
||||||
|
);
|
||||||
|
register_message_handler(
|
||||||
|
PREFERRED_HEIGHT_CHANGED, on_preferred_height_changed
|
||||||
|
);
|
||||||
|
register_message_handler(
|
||||||
|
REMOTE_IMAGE_LOAD_BLOCKED, on_remote_image_load_blocked
|
||||||
|
);
|
||||||
|
register_message_handler(
|
||||||
|
SELECTION_CHANGED, on_selection_changed
|
||||||
|
);
|
||||||
|
|
||||||
|
// Manage zoom level, ensure it's sane
|
||||||
|
config.bind(Application.Configuration.CONVERSATION_VIEWER_ZOOM_KEY, this, "zoom_level");
|
||||||
|
if (this.zoom_level < ZOOM_MIN) {
|
||||||
|
this.zoom_level = ZOOM_MIN;
|
||||||
|
} else if (this.zoom_level > ZOOM_MAX) {
|
||||||
|
this.zoom_level = ZOOM_MAX;
|
||||||
|
}
|
||||||
|
this.scroll_event.connect(on_scroll_event);
|
||||||
|
|
||||||
|
// Watch desktop font settings
|
||||||
|
Settings system_settings = config.gnome_interface;
|
||||||
|
system_settings.bind("document-font-name", this,
|
||||||
|
"document-font", SettingsBindFlags.DEFAULT);
|
||||||
|
system_settings.bind("monospace-font-name", this,
|
||||||
|
"monospace-font", SettingsBindFlags.DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
~WebView() {
|
~ClientWebView() {
|
||||||
base_unref();
|
base_unref();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -403,7 +433,13 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||||
* effect.
|
* effect.
|
||||||
*/
|
*/
|
||||||
public void allow_remote_image_loading() {
|
public void allow_remote_image_loading() {
|
||||||
this.run_javascript.begin("_gearyAllowRemoteResourceLoads = true", null);
|
// Use a separate script here since we need to update the
|
||||||
|
// value of window.geary.allow_remote_image_loading after it
|
||||||
|
// was first created by client-web-view.js (which is loaded at
|
||||||
|
// the start of page load), but before the page load is
|
||||||
|
// started (so that any remote images present are actually
|
||||||
|
// loaded).
|
||||||
|
this.user_content_manager.add_script(ClientWebView.allow_remote_images);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -479,7 +515,7 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||||
JavaScriptMessageHandler handler) {
|
JavaScriptMessageHandler handler) {
|
||||||
// XXX can't use the delegate directly, see b.g.o Bug
|
// XXX can't use the delegate directly, see b.g.o Bug
|
||||||
// 604781. However the workaround below creates a circular
|
// 604781. However the workaround below creates a circular
|
||||||
// reference, causing WebView instances to leak. So to
|
// reference, causing ClientWebView instances to leak. So to
|
||||||
// work around that we need to record handler ids and
|
// work around that we need to record handler ids and
|
||||||
// disconnect them when being destroyed.
|
// disconnect them when being destroyed.
|
||||||
ulong id = this.user_content_manager.script_message_received[name].connect(
|
ulong id = this.user_content_manager.script_message_received[name].connect(
|
||||||
|
|
@ -491,50 +527,6 @@ public abstract class Components.WebView : WebKit.WebView, Geary.BaseInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init(Application.Configuration config) {
|
|
||||||
// XXX get the allow prefix from the extension somehow
|
|
||||||
|
|
||||||
this.decide_policy.connect(on_decide_policy);
|
|
||||||
this.web_process_terminated.connect((reason) => {
|
|
||||||
warning("Web process crashed: %s", reason.to_string());
|
|
||||||
});
|
|
||||||
|
|
||||||
register_message_handler(
|
|
||||||
COMMAND_STACK_CHANGED, on_command_stack_changed
|
|
||||||
);
|
|
||||||
register_message_handler(
|
|
||||||
CONTENT_LOADED, on_content_loaded
|
|
||||||
);
|
|
||||||
register_message_handler(
|
|
||||||
DOCUMENT_MODIFIED, on_document_modified
|
|
||||||
);
|
|
||||||
register_message_handler(
|
|
||||||
PREFERRED_HEIGHT_CHANGED, on_preferred_height_changed
|
|
||||||
);
|
|
||||||
register_message_handler(
|
|
||||||
REMOTE_IMAGE_LOAD_BLOCKED, on_remote_image_load_blocked
|
|
||||||
);
|
|
||||||
register_message_handler(
|
|
||||||
SELECTION_CHANGED, on_selection_changed
|
|
||||||
);
|
|
||||||
|
|
||||||
// Manage zoom level, ensure it's sane
|
|
||||||
config.bind(Application.Configuration.CONVERSATION_VIEWER_ZOOM_KEY, this, "zoom_level");
|
|
||||||
if (this.zoom_level < ZOOM_MIN) {
|
|
||||||
this.zoom_level = ZOOM_MIN;
|
|
||||||
} else if (this.zoom_level > ZOOM_MAX) {
|
|
||||||
this.zoom_level = ZOOM_MAX;
|
|
||||||
}
|
|
||||||
this.scroll_event.connect(on_scroll_event);
|
|
||||||
|
|
||||||
// Watch desktop font settings
|
|
||||||
Settings system_settings = config.gnome_interface;
|
|
||||||
system_settings.bind("document-font-name", this,
|
|
||||||
"document-font", SettingsBindFlags.DEFAULT);
|
|
||||||
system_settings.bind("monospace-font-name", this,
|
|
||||||
"monospace-font", SettingsBindFlags.DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handle_cid_request(WebKit.URISchemeRequest request) {
|
private void handle_cid_request(WebKit.URISchemeRequest request) {
|
||||||
if (!handle_internal_response(request)) {
|
if (!handle_internal_response(request)) {
|
||||||
request.finish_error(new FileError.NOENT("Unknown CID"));
|
request.finish_error(new FileError.NOENT("Unknown CID"));
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
/**
|
/**
|
||||||
* A WebView for editing messages in the composer.
|
* A WebView for editing messages in the composer.
|
||||||
*/
|
*/
|
||||||
public class Composer.WebView : Components.WebView {
|
public class Composer.WebView : ClientWebView {
|
||||||
|
|
||||||
|
|
||||||
// WebKit message handler names
|
// WebKit message handler names
|
||||||
|
|
@ -92,10 +92,10 @@ public class Composer.WebView : Components.WebView {
|
||||||
|
|
||||||
public static new void load_resources()
|
public static new void load_resources()
|
||||||
throws Error {
|
throws Error {
|
||||||
WebView.app_style = Components.WebView.load_app_stylesheet(
|
WebView.app_style = ClientWebView.load_app_stylesheet(
|
||||||
"composer-web-view.css"
|
"composer-web-view.css"
|
||||||
);
|
);
|
||||||
WebView.app_script = Components.WebView.load_app_script(
|
WebView.app_script = ClientWebView.load_app_script(
|
||||||
"composer-web-view.js"
|
"composer-web-view.js"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1320,7 +1320,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
||||||
email.inline_files.set_all(this.inline_files);
|
email.inline_files.set_all(this.inline_files);
|
||||||
email.cid_files.set_all(this.cid_files);
|
email.cid_files.set_all(this.cid_files);
|
||||||
|
|
||||||
email.img_src_prefix = Components.WebView.INTERNAL_URL_PREFIX;
|
email.img_src_prefix = ClientWebView.INTERNAL_URL_PREFIX;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!for_draft) {
|
if (!for_draft) {
|
||||||
|
|
@ -2077,7 +2077,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
||||||
string unique_filename;
|
string unique_filename;
|
||||||
add_inline_part(byte_buffer, filename, out unique_filename);
|
add_inline_part(byte_buffer, filename, out unique_filename);
|
||||||
this.editor.insert_image(
|
this.editor.insert_image(
|
||||||
Components.WebView.INTERNAL_URL_PREFIX + unique_filename
|
ClientWebView.INTERNAL_URL_PREFIX + unique_filename
|
||||||
);
|
);
|
||||||
throw new Geary.EngineError.UNSUPPORTED("Mock method");
|
throw new Geary.EngineError.UNSUPPORTED("Mock method");
|
||||||
} catch (Error error) {
|
} catch (Error error) {
|
||||||
|
|
@ -2807,7 +2807,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
||||||
string unique_filename;
|
string unique_filename;
|
||||||
add_inline_part(file_buffer, path, out unique_filename);
|
add_inline_part(file_buffer, path, out unique_filename);
|
||||||
this.editor.insert_image(
|
this.editor.insert_image(
|
||||||
Components.WebView.INTERNAL_URL_PREFIX + unique_filename
|
ClientWebView.INTERNAL_URL_PREFIX + unique_filename
|
||||||
);
|
);
|
||||||
} catch (Error err) {
|
} catch (Error err) {
|
||||||
attachment_failed(err.message);
|
attachment_failed(err.message);
|
||||||
|
|
@ -2906,7 +2906,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.editor.insert_image(
|
this.editor.insert_image(
|
||||||
Components.WebView.INTERNAL_URL_PREFIX + unique_filename
|
ClientWebView.INTERNAL_URL_PREFIX + unique_filename
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -479,7 +479,7 @@ public class ConversationEmail : Gtk.Box, Geary.BaseInterface {
|
||||||
if (this.body_selection_message != null) {
|
if (this.body_selection_message != null) {
|
||||||
try {
|
try {
|
||||||
selection =
|
selection =
|
||||||
yield this.body_selection_message.get_selection_for_quoting();
|
yield this.body_selection_message.web_view.get_selection_for_quoting();
|
||||||
} catch (Error err) {
|
} catch (Error err) {
|
||||||
debug("Failed to get selection for quoting: %s", err.message);
|
debug("Failed to get selection for quoting: %s", err.message);
|
||||||
}
|
}
|
||||||
|
|
@ -495,7 +495,7 @@ public class ConversationEmail : Gtk.Box, Geary.BaseInterface {
|
||||||
if (this.body_selection_message != null) {
|
if (this.body_selection_message != null) {
|
||||||
try {
|
try {
|
||||||
selection =
|
selection =
|
||||||
yield this.body_selection_message.get_selection_for_find();
|
yield this.body_selection_message.web_view.get_selection_for_find();
|
||||||
} catch (Error err) {
|
} catch (Error err) {
|
||||||
debug("Failed to get selection for find: %s", err.message);
|
debug("Failed to get selection for find: %s", err.message);
|
||||||
}
|
}
|
||||||
|
|
@ -588,10 +588,12 @@ public class ConversationEmail : Gtk.Box, Geary.BaseInterface {
|
||||||
Json.Generator generator = new Json.Generator();
|
Json.Generator generator = new Json.Generator();
|
||||||
generator.set_root(builder.get_root());
|
generator.set_root(builder.get_root());
|
||||||
string js = "geary.addPrintHeaders(" + generator.to_data(null) + ");";
|
string js = "geary.addPrintHeaders(" + generator.to_data(null) + ");";
|
||||||
yield this.primary_message.run_javascript(js, null);
|
yield this.primary_message.web_view.run_javascript(js, null);
|
||||||
|
|
||||||
Gtk.Window? window = get_toplevel() as Gtk.Window;
|
Gtk.Window? window = get_toplevel() as Gtk.Window;
|
||||||
WebKit.PrintOperation op = this.primary_message.new_print_operation();
|
WebKit.PrintOperation op = new WebKit.PrintOperation(
|
||||||
|
this.primary_message.web_view
|
||||||
|
);
|
||||||
Gtk.PrintSettings settings = new Gtk.PrintSettings();
|
Gtk.PrintSettings settings = new Gtk.PrintSettings();
|
||||||
|
|
||||||
if (this.email.subject != null) {
|
if (this.email.subject != null) {
|
||||||
|
|
@ -618,14 +620,14 @@ public class ConversationEmail : Gtk.Box, Geary.BaseInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void connect_message_view_signals(ConversationMessage view) {
|
private void connect_message_view_signals(ConversationMessage view) {
|
||||||
view.content_loaded.connect(on_content_loaded);
|
|
||||||
view.flag_remote_images.connect(on_flag_remote_images);
|
view.flag_remote_images.connect(on_flag_remote_images);
|
||||||
view.internal_link_activated.connect((y) => {
|
view.internal_link_activated.connect((y) => {
|
||||||
internal_link_activated(y);
|
internal_link_activated(y);
|
||||||
});
|
});
|
||||||
view.internal_resource_loaded.connect(on_resource_loaded);
|
|
||||||
view.save_image.connect(on_save_image);
|
view.save_image.connect(on_save_image);
|
||||||
view.selection_changed.connect((has_selection) => {
|
view.web_view.internal_resource_loaded.connect(on_resource_loaded);
|
||||||
|
view.web_view.content_loaded.connect(on_content_loaded);
|
||||||
|
view.web_view.selection_changed.connect((has_selection) => {
|
||||||
this.body_selection_message = has_selection ? view : null;
|
this.body_selection_message = has_selection ? view : null;
|
||||||
body_selection_changed(has_selection);
|
body_selection_changed(has_selection);
|
||||||
});
|
});
|
||||||
|
|
@ -701,7 +703,7 @@ public class ConversationEmail : Gtk.Box, Geary.BaseInterface {
|
||||||
|
|
||||||
// Load all messages
|
// Load all messages
|
||||||
|
|
||||||
this.primary_message.add_internal_resources(cid_resources);
|
this.primary_message.web_view.add_internal_resources(cid_resources);
|
||||||
yield this.primary_message.load_message_body(
|
yield this.primary_message.load_message_body(
|
||||||
message, this.load_cancellable
|
message, this.load_cancellable
|
||||||
);
|
);
|
||||||
|
|
@ -719,7 +721,7 @@ public class ConversationEmail : Gtk.Box, Geary.BaseInterface {
|
||||||
this.config
|
this.config
|
||||||
);
|
);
|
||||||
connect_message_view_signals(attached_message);
|
connect_message_view_signals(attached_message);
|
||||||
attached_message.add_internal_resources(cid_resources);
|
attached_message.web_view.add_internal_resources(cid_resources);
|
||||||
this.sub_messages.add(attached_message);
|
this.sub_messages.add(attached_message);
|
||||||
this._attached_messages.add(attached_message);
|
this._attached_messages.add(attached_message);
|
||||||
attached_message.load_contacts.begin(this.load_cancellable);
|
attached_message.load_contacts.begin(this.load_cancellable);
|
||||||
|
|
@ -906,8 +908,8 @@ public class ConversationEmail : Gtk.Box, Geary.BaseInterface {
|
||||||
Geary.Memory.Buffer? content) {
|
Geary.Memory.Buffer? content) {
|
||||||
var main = get_toplevel() as Application.MainWindow;
|
var main = get_toplevel() as Application.MainWindow;
|
||||||
if (main != null) {
|
if (main != null) {
|
||||||
if (uri.has_prefix(Components.WebView.CID_URL_PREFIX)) {
|
if (uri.has_prefix(ClientWebView.CID_URL_PREFIX)) {
|
||||||
string cid = uri.substring(Components.WebView.CID_URL_PREFIX.length);
|
string cid = uri.substring(ClientWebView.CID_URL_PREFIX.length);
|
||||||
try {
|
try {
|
||||||
Geary.Attachment attachment = this.email.get_attachment_by_content_id(
|
Geary.Attachment attachment = this.email.get_attachment_by_content_id(
|
||||||
cid
|
cid
|
||||||
|
|
@ -954,7 +956,7 @@ public class ConversationEmail : Gtk.Box, Geary.BaseInterface {
|
||||||
private void on_content_loaded() {
|
private void on_content_loaded() {
|
||||||
bool all_loaded = true;
|
bool all_loaded = true;
|
||||||
foreach (ConversationMessage message in this) {
|
foreach (ConversationMessage message in this) {
|
||||||
if (!message.is_content_loaded) {
|
if (!message.web_view.is_content_loaded) {
|
||||||
all_loaded = false;
|
all_loaded = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -898,7 +898,7 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
||||||
*/
|
*/
|
||||||
public void zoom_in() {
|
public void zoom_in() {
|
||||||
message_view_iterator().foreach((msg_view) => {
|
message_view_iterator().foreach((msg_view) => {
|
||||||
msg_view.zoom_in();
|
msg_view.web_view.zoom_in();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -908,7 +908,7 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
||||||
*/
|
*/
|
||||||
public void zoom_out() {
|
public void zoom_out() {
|
||||||
message_view_iterator().foreach((msg_view) => {
|
message_view_iterator().foreach((msg_view) => {
|
||||||
msg_view.zoom_out();
|
msg_view.web_view.zoom_out();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -918,7 +918,7 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
||||||
*/
|
*/
|
||||||
public void zoom_reset() {
|
public void zoom_reset() {
|
||||||
message_view_iterator().foreach((msg_view) => {
|
message_view_iterator().foreach((msg_view) => {
|
||||||
msg_view.zoom_reset();
|
msg_view.web_view.zoom_reset();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -1122,7 +1122,8 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
||||||
row.get_allocation(out alloc);
|
row.get_allocation(out alloc);
|
||||||
|
|
||||||
int x = 0, y = 0;
|
int x = 0, y = 0;
|
||||||
row.view.primary_message.web_view_translate_coordinates(row, x, anchor_y, out x, out y);
|
ConversationWebView web_view = row.view.primary_message.web_view;
|
||||||
|
web_view.translate_coordinates(row, x, anchor_y, out x, out y);
|
||||||
|
|
||||||
Gtk.Adjustment adj = get_adjustment();
|
Gtk.Adjustment adj = get_adjustment();
|
||||||
y = alloc.y + y;
|
y = alloc.y + y;
|
||||||
|
|
@ -1155,13 +1156,14 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
|
||||||
ConversationMessage conversation_message = view.primary_message;
|
ConversationMessage conversation_message = view.primary_message;
|
||||||
int body_top = 0;
|
int body_top = 0;
|
||||||
int body_left = 0;
|
int body_left = 0;
|
||||||
conversation_message.web_view_translate_coordinates(
|
ConversationWebView web_view = conversation_message.web_view;
|
||||||
|
web_view.translate_coordinates(
|
||||||
this,
|
this,
|
||||||
0, 0,
|
0, 0,
|
||||||
out body_left, out body_top
|
out body_left, out body_top
|
||||||
);
|
);
|
||||||
|
|
||||||
int body_height = conversation_message.web_view_get_allocated_height();
|
int body_height = web_view.get_allocated_height();
|
||||||
int body_bottom = body_top + body_height;
|
int body_bottom = body_top + body_height;
|
||||||
|
|
||||||
// Only mark the email as read if it's actually visible
|
// Only mark the email as read if it's actually visible
|
||||||
|
|
|
||||||
|
|
@ -218,19 +218,8 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||||
[GtkChild]
|
[GtkChild]
|
||||||
internal Gtk.Grid infobars;
|
internal Gtk.Grid infobars;
|
||||||
|
|
||||||
/**
|
|
||||||
* Emitted when web_view's content has finished loaded.
|
|
||||||
*
|
|
||||||
* See {@link Components.WebView.is_content_loaded} for details.
|
|
||||||
*/
|
|
||||||
internal bool is_content_loaded {
|
|
||||||
get {
|
|
||||||
return this.web_view != null && this.web_view.is_content_loaded;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** HTML view that displays the message body. */
|
/** HTML view that displays the message body. */
|
||||||
private ConversationWebView? web_view { get; private set; }
|
internal ConversationWebView web_view { get; private set; }
|
||||||
|
|
||||||
// The message headers represented by this view
|
// The message headers represented by this view
|
||||||
private Geary.EmailHeaderSet headers;
|
private Geary.EmailHeaderSet headers;
|
||||||
|
|
@ -346,19 +335,6 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||||
string uri, string? alt_text, Geary.Memory.Buffer? buffer
|
string uri, string? alt_text, Geary.Memory.Buffer? buffer
|
||||||
);
|
);
|
||||||
|
|
||||||
/** Emitted when web_view has loaded a resource added to it. */
|
|
||||||
public signal void internal_resource_loaded(string name);
|
|
||||||
|
|
||||||
/** Emitted when web_view's selection has changed. */
|
|
||||||
public signal void selection_changed(bool has_selection);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emitted when web_view's content has finished loaded.
|
|
||||||
*
|
|
||||||
* See {@link Components.WebView.is_content_loaded} for details.
|
|
||||||
*/
|
|
||||||
public signal void content_loaded();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new view from an email's headers and body.
|
* Constructs a new view from an email's headers and body.
|
||||||
|
|
@ -400,18 +376,6 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void trigger_internal_resource_loaded(string name) {
|
|
||||||
internal_resource_loaded(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void trigger_content_loaded() {
|
|
||||||
content_loaded();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void trigger_selection_changed(bool has_selection) {
|
|
||||||
selection_changed(has_selection);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ConversationMessage(Geary.EmailHeaderSet headers,
|
private ConversationMessage(Geary.EmailHeaderSet headers,
|
||||||
string? preview,
|
string? preview,
|
||||||
bool load_remote_resources,
|
bool load_remote_resources,
|
||||||
|
|
@ -432,10 +396,19 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||||
.activate.connect(on_copy_email_address);
|
.activate.connect(on_copy_email_address);
|
||||||
add_action(ACTION_COPY_LINK, true, VariantType.STRING)
|
add_action(ACTION_COPY_LINK, true, VariantType.STRING)
|
||||||
.activate.connect(on_copy_link);
|
.activate.connect(on_copy_link);
|
||||||
|
add_action(ACTION_COPY_SELECTION, false).activate.connect(() => {
|
||||||
|
web_view.copy_clipboard();
|
||||||
|
});
|
||||||
|
add_action(ACTION_OPEN_INSPECTOR, config.enable_inspector).activate.connect(() => {
|
||||||
|
this.web_view.get_inspector().show();
|
||||||
|
});
|
||||||
add_action(ACTION_OPEN_LINK, true, VariantType.STRING)
|
add_action(ACTION_OPEN_LINK, true, VariantType.STRING)
|
||||||
.activate.connect(on_link_activated);
|
.activate.connect(on_link_activated);
|
||||||
add_action(ACTION_SAVE_IMAGE, true, new VariantType("(sms)"))
|
add_action(ACTION_SAVE_IMAGE, true, new VariantType("(sms)"))
|
||||||
.activate.connect(on_save_image);
|
.activate.connect(on_save_image);
|
||||||
|
add_action(ACTION_SELECT_ALL, true).activate.connect(() => {
|
||||||
|
web_view.select_all();
|
||||||
|
});
|
||||||
insert_action_group("msg", message_actions);
|
insert_action_group("msg", message_actions);
|
||||||
|
|
||||||
// Context menu
|
// Context menu
|
||||||
|
|
@ -488,37 +461,9 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||||
this.subject_searchable = headers.subject.value.casefold();
|
this.subject_searchable = headers.subject.value.casefold();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.body_container.set_has_tooltip(true); // Used to show link URLs
|
// Web view
|
||||||
this.show_progress_timeout = new Geary.TimeoutManager.milliseconds(
|
|
||||||
Util.Gtk.SHOW_PROGRESS_TIMEOUT_MSEC, this.on_show_progress_timeout
|
|
||||||
);
|
|
||||||
this.hide_progress_timeout = new Geary.TimeoutManager.milliseconds(
|
|
||||||
Util.Gtk.HIDE_PROGRESS_TIMEOUT_MSEC, this.on_hide_progress_timeout
|
|
||||||
);
|
|
||||||
|
|
||||||
this.progress_pulse = new Geary.TimeoutManager.milliseconds(
|
|
||||||
Util.Gtk.PROGRESS_PULSE_TIMEOUT_MSEC, this.body_progress.pulse
|
|
||||||
);
|
|
||||||
this.progress_pulse.repetition = FOREVER;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initialize_web_view() {
|
|
||||||
var viewer = get_ancestor(typeof(ConversationViewer)) as ConversationViewer;
|
|
||||||
|
|
||||||
// Ensure we share the same WebProcess with the last one
|
|
||||||
// constructed if possible.
|
|
||||||
if (viewer != null && viewer.previous_web_view != null) {
|
|
||||||
this.web_view = new ConversationWebView.with_related_view(
|
|
||||||
this.config,
|
|
||||||
viewer.previous_web_view
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.web_view = new ConversationWebView(this.config);
|
|
||||||
}
|
|
||||||
if (viewer != null) {
|
|
||||||
viewer.previous_web_view = this.web_view;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
this.web_view = new ConversationWebView(config);
|
||||||
this.web_view.context_menu.connect(on_context_menu);
|
this.web_view.context_menu.connect(on_context_menu);
|
||||||
this.web_view.deceptive_link_clicked.connect(on_deceptive_link_clicked);
|
this.web_view.deceptive_link_clicked.connect(on_deceptive_link_clicked);
|
||||||
this.web_view.link_activated.connect((link) => {
|
this.web_view.link_activated.connect((link) => {
|
||||||
|
|
@ -531,22 +476,23 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||||
this.remote_images_infobar.show();
|
this.remote_images_infobar.show();
|
||||||
});
|
});
|
||||||
this.web_view.selection_changed.connect(on_selection_changed);
|
this.web_view.selection_changed.connect(on_selection_changed);
|
||||||
this.web_view.internal_resource_loaded.connect(trigger_internal_resource_loaded);
|
|
||||||
this.web_view.content_loaded.connect(trigger_content_loaded);
|
|
||||||
this.web_view.selection_changed.connect(trigger_selection_changed);
|
|
||||||
this.web_view.set_hexpand(true);
|
this.web_view.set_hexpand(true);
|
||||||
this.web_view.set_vexpand(true);
|
this.web_view.set_vexpand(true);
|
||||||
this.web_view.show();
|
this.web_view.show();
|
||||||
|
|
||||||
|
this.body_container.set_has_tooltip(true); // Used to show link URLs
|
||||||
this.body_container.add(this.web_view);
|
this.body_container.add(this.web_view);
|
||||||
add_action(ACTION_COPY_SELECTION, false).activate.connect(() => {
|
this.show_progress_timeout = new Geary.TimeoutManager.milliseconds(
|
||||||
web_view.copy_clipboard();
|
Util.Gtk.SHOW_PROGRESS_TIMEOUT_MSEC, this.on_show_progress_timeout
|
||||||
});
|
);
|
||||||
add_action(ACTION_OPEN_INSPECTOR, config.enable_inspector).activate.connect(() => {
|
this.hide_progress_timeout = new Geary.TimeoutManager.milliseconds(
|
||||||
this.web_view.get_inspector().show();
|
Util.Gtk.HIDE_PROGRESS_TIMEOUT_MSEC, this.on_hide_progress_timeout
|
||||||
});
|
);
|
||||||
add_action(ACTION_SELECT_ALL, true).activate.connect(() => {
|
|
||||||
web_view.select_all();
|
this.progress_pulse = new Geary.TimeoutManager.milliseconds(
|
||||||
});
|
Util.Gtk.PROGRESS_PULSE_TIMEOUT_MSEC, this.body_progress.pulse
|
||||||
|
);
|
||||||
|
this.progress_pulse.repetition = FOREVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
~ConversationMessage() {
|
~ConversationMessage() {
|
||||||
|
|
@ -562,77 +508,10 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||||
base.destroy();
|
base.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async string? get_selection_for_quoting() throws Error {
|
|
||||||
if (this.web_view == null)
|
|
||||||
initialize_web_view();
|
|
||||||
return yield web_view.get_selection_for_quoting();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async string? get_selection_for_find() throws Error {
|
|
||||||
if (this.web_view == null)
|
|
||||||
initialize_web_view();
|
|
||||||
return yield web_view.get_selection_for_find();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a set of internal resources to web_view.
|
|
||||||
*
|
|
||||||
* @see add_internal_resource
|
|
||||||
*/
|
|
||||||
public void add_internal_resources(Gee.Map<string,Geary.Memory.Buffer> res) {
|
|
||||||
if (this.web_view == null)
|
|
||||||
initialize_web_view();
|
|
||||||
web_view.add_internal_resources(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
public WebKit.PrintOperation new_print_operation() {
|
|
||||||
if (this.web_view == null)
|
|
||||||
initialize_web_view();
|
|
||||||
return new WebKit.PrintOperation(web_view);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void run_javascript (string script, Cancellable? cancellable) throws Error {
|
|
||||||
if (this.web_view == null)
|
|
||||||
initialize_web_view();
|
|
||||||
yield web_view.run_javascript(script, cancellable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void zoom_in() {
|
|
||||||
if (this.web_view == null)
|
|
||||||
initialize_web_view();
|
|
||||||
web_view.zoom_in();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void zoom_out() {
|
|
||||||
if (this.web_view == null)
|
|
||||||
initialize_web_view();
|
|
||||||
web_view.zoom_out();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void zoom_reset() {
|
|
||||||
if (this.web_view == null)
|
|
||||||
initialize_web_view();
|
|
||||||
web_view.zoom_reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void web_view_translate_coordinates(Gtk.Widget widget, int x, int anchor_y, out int x1, out int y1) {
|
|
||||||
if (this.web_view == null)
|
|
||||||
initialize_web_view();
|
|
||||||
web_view.translate_coordinates(widget, x, anchor_y, out x1, out y1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int web_view_get_allocated_height() {
|
|
||||||
if (this.web_view == null)
|
|
||||||
initialize_web_view();
|
|
||||||
return web_view.get_allocated_height();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the complete message and hides the compact headers.
|
* Shows the complete message and hides the compact headers.
|
||||||
*/
|
*/
|
||||||
public void show_message_body(bool include_transitions=true) {
|
public void show_message_body(bool include_transitions=true) {
|
||||||
if (this.web_view == null)
|
|
||||||
initialize_web_view();
|
|
||||||
set_revealer(this.compact_revealer, false, include_transitions);
|
set_revealer(this.compact_revealer, false, include_transitions);
|
||||||
set_revealer(this.header_revealer, true, include_transitions);
|
set_revealer(this.header_revealer, true, include_transitions);
|
||||||
set_revealer(this.body_revealer, true, include_transitions);
|
set_revealer(this.body_revealer, true, include_transitions);
|
||||||
|
|
@ -816,10 +695,6 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||||
throw new GLib.IOError.CANCELLED("Conversation load cancelled");
|
throw new GLib.IOError.CANCELLED("Conversation load cancelled");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.web_view == null) {
|
|
||||||
initialize_web_view();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool contact_load_images = (
|
bool contact_load_images = (
|
||||||
this.primary_contact != null &&
|
this.primary_contact != null &&
|
||||||
this.primary_contact.load_remote_resources
|
this.primary_contact.load_remote_resources
|
||||||
|
|
@ -870,8 +745,6 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.web_view == null)
|
|
||||||
initialize_web_view();
|
|
||||||
uint webkit_found = yield this.web_view.highlight_search_terms(
|
uint webkit_found = yield this.web_view.highlight_search_terms(
|
||||||
search_matches, cancellable
|
search_matches, cancellable
|
||||||
);
|
);
|
||||||
|
|
@ -885,9 +758,7 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||||
foreach (ContactFlowBoxChild address in this.searchable_addresses) {
|
foreach (ContactFlowBoxChild address in this.searchable_addresses) {
|
||||||
address.unmark_search_terms();
|
address.unmark_search_terms();
|
||||||
}
|
}
|
||||||
|
this.web_view.unmark_search_terms();
|
||||||
if (this.web_view != null)
|
|
||||||
this.web_view.unmark_search_terms();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1050,8 +921,6 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||||
// returns HTML that is placed into the document in the position
|
// returns HTML that is placed into the document in the position
|
||||||
// where the MIME part was found
|
// where the MIME part was found
|
||||||
private string? inline_image_replacer(Geary.RFC822.Part part) {
|
private string? inline_image_replacer(Geary.RFC822.Part part) {
|
||||||
if (this.web_view == null)
|
|
||||||
initialize_web_view();
|
|
||||||
Geary.Mime.ContentType content_type = part.content_type;
|
Geary.Mime.ContentType content_type = part.content_type;
|
||||||
if (content_type.media_type != "image" ||
|
if (content_type.media_type != "image" ||
|
||||||
!this.web_view.can_show_mime_type(content_type.to_string())) {
|
!this.web_view.can_show_mime_type(content_type.to_string())) {
|
||||||
|
|
@ -1086,7 +955,7 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||||
return "<img alt=\"%s\" class=\"%s\" src=\"%s%s\" />".printf(
|
return "<img alt=\"%s\" class=\"%s\" src=\"%s%s\" />".printf(
|
||||||
clean_filename,
|
clean_filename,
|
||||||
REPLACED_IMAGE_CLASS,
|
REPLACED_IMAGE_CLASS,
|
||||||
Components.WebView.CID_URL_PREFIX,
|
ClientWebView.CID_URL_PREFIX,
|
||||||
Geary.HTML.escape_markup(id)
|
Geary.HTML.escape_markup(id)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -1097,9 +966,7 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||||
this.load_remote_resources = true;
|
this.load_remote_resources = true;
|
||||||
this.remote_resources_requested = 0;
|
this.remote_resources_requested = 0;
|
||||||
this.remote_resources_loaded = 0;
|
this.remote_resources_loaded = 0;
|
||||||
if (this.web_view != null) {
|
this.web_view.load_remote_images();
|
||||||
this.web_view.load_remote_images();
|
|
||||||
}
|
|
||||||
if (update_email_flag) {
|
if (update_email_flag) {
|
||||||
flag_remote_images();
|
flag_remote_images();
|
||||||
}
|
}
|
||||||
|
|
@ -1114,13 +981,11 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||||
|
|
||||||
if (placeholder != null) {
|
if (placeholder != null) {
|
||||||
this.body_placeholder = placeholder;
|
this.body_placeholder = placeholder;
|
||||||
if (this.web_view != null)
|
this.web_view.hide();
|
||||||
this.web_view.hide();
|
|
||||||
this.body_container.add(placeholder);
|
this.body_container.add(placeholder);
|
||||||
show_message_body(true);
|
show_message_body(true);
|
||||||
} else {
|
} else {
|
||||||
if (this.web_view != null)
|
this.web_view.show();
|
||||||
this.web_view.show();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1148,12 +1013,10 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_is_loading_notify() {
|
private void on_is_loading_notify() {
|
||||||
if (this.web_view != null) {
|
if (this.web_view.is_loading) {
|
||||||
if (this.web_view.is_loading) {
|
start_progress_loading();
|
||||||
start_progress_loading();
|
} else {
|
||||||
} else {
|
stop_progress_loading();
|
||||||
stop_progress_loading();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1388,7 +1251,7 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
|
||||||
alt_text = (string) alt_maybe;
|
alt_text = (string) alt_maybe;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uri.has_prefix(Components.WebView.CID_URL_PREFIX)) {
|
if (uri.has_prefix(ClientWebView.CID_URL_PREFIX)) {
|
||||||
// We can get the data directly from the attachment, so
|
// We can get the data directly from the attachment, so
|
||||||
// don't bother getting it from the web view
|
// don't bother getting it from the web view
|
||||||
save_image(uri, alt_text, null);
|
save_image(uri, alt_text, null);
|
||||||
|
|
|
||||||
|
|
@ -24,14 +24,6 @@ public class ConversationViewer : Gtk.Stack, Geary.BaseInterface {
|
||||||
get; private set; default = null;
|
get; private set; default = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The most recent web view created in this viewer.
|
|
||||||
*
|
|
||||||
* Keep the last created web view around so others can share the
|
|
||||||
* same WebKitGTK WebProcess.
|
|
||||||
*/
|
|
||||||
internal ConversationWebView? previous_web_view { get; set; default = null; }
|
|
||||||
|
|
||||||
private Application.Configuration config;
|
private Application.Configuration config;
|
||||||
|
|
||||||
private Gee.Set<Geary.App.Conversation>? selection_while_composing = null;
|
private Gee.Set<Geary.App.Conversation>? selection_while_composing = null;
|
||||||
|
|
@ -254,10 +246,7 @@ public class ConversationViewer : Gtk.Stack, Geary.BaseInterface {
|
||||||
Application.ContactStore contacts,
|
Application.ContactStore contacts,
|
||||||
bool start_mark_timer)
|
bool start_mark_timer)
|
||||||
throws GLib.Error {
|
throws GLib.Error {
|
||||||
// Keep the old ScrolledWindow around long enough for its
|
remove_current_list();
|
||||||
// descendant web views to be kept so their WebProcess can be
|
|
||||||
// re-used.
|
|
||||||
var old_scroller = remove_current_list();
|
|
||||||
|
|
||||||
ConversationListBox new_list = new ConversationListBox(
|
ConversationListBox new_list = new ConversationListBox(
|
||||||
conversation,
|
conversation,
|
||||||
|
|
@ -303,9 +292,6 @@ public class ConversationViewer : Gtk.Stack, Geary.BaseInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
yield new_list.load_conversation(scroll_to, query);
|
yield new_list.load_conversation(scroll_to, query);
|
||||||
|
|
||||||
// Not strictly necessary, but keeps the compiler happy
|
|
||||||
old_scroller.destroy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a new conversation list to the UI
|
// Add a new conversation list to the UI
|
||||||
|
|
@ -325,7 +311,7 @@ public class ConversationViewer : Gtk.Stack, Geary.BaseInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove any existing conversation list, cancelling its loading
|
// Remove any existing conversation list, cancelling its loading
|
||||||
private Gtk.ScrolledWindow remove_current_list() {
|
private void remove_current_list() {
|
||||||
if (this.find_cancellable != null) {
|
if (this.find_cancellable != null) {
|
||||||
this.find_cancellable.cancel();
|
this.find_cancellable.cancel();
|
||||||
this.find_cancellable = null;
|
this.find_cancellable = null;
|
||||||
|
|
@ -337,17 +323,15 @@ public class ConversationViewer : Gtk.Stack, Geary.BaseInterface {
|
||||||
this.current_list = null;
|
this.current_list = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var old_scroller = this.conversation_scroller;
|
|
||||||
// XXX GTK+ Bug 778190 workaround
|
// XXX GTK+ Bug 778190 workaround
|
||||||
this.conversation_page.remove(old_scroller);
|
this.conversation_scroller.destroy(); // removes the list
|
||||||
new_conversation_scroller();
|
new_conversation_scroller();
|
||||||
return old_scroller;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void new_conversation_scroller() {
|
private void new_conversation_scroller() {
|
||||||
// XXX Work around for GTK+ Bug 778190: Instead of replacing
|
// XXX Work around for GTK+ Bug 778190: Instead of replacing
|
||||||
// the Viewport that contains the current list, replace the
|
// the Viewport that contains the current list, replace the
|
||||||
// complete ScrolledWindow. Need to remove this method and
|
// complete ScrolledWindow. Need to put remove this method and
|
||||||
// put the settings back into conversation-viewer.ui when we
|
// put the settings back into conversation-viewer.ui when we
|
||||||
// can rely on it being fixed again.
|
// can rely on it being fixed again.
|
||||||
Gtk.ScrolledWindow scroller = new Gtk.ScrolledWindow(null, null);
|
Gtk.ScrolledWindow scroller = new Gtk.ScrolledWindow(null, null);
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class ConversationWebView : Components.WebView {
|
public class ConversationWebView : ClientWebView {
|
||||||
|
|
||||||
|
|
||||||
private const string DECEPTIVE_LINK_CLICKED = "deceptiveLinkClicked";
|
private const string DECEPTIVE_LINK_CLICKED = "deceptiveLinkClicked";
|
||||||
|
|
@ -41,10 +41,10 @@ public class ConversationWebView : Components.WebView {
|
||||||
|
|
||||||
public static new void load_resources()
|
public static new void load_resources()
|
||||||
throws Error {
|
throws Error {
|
||||||
ConversationWebView.app_script = Components.WebView.load_app_script(
|
ConversationWebView.app_script = ClientWebView.load_app_script(
|
||||||
"conversation-web-view.js"
|
"conversation-web-view.js"
|
||||||
);
|
);
|
||||||
ConversationWebView.app_stylesheet = Components.WebView.load_app_stylesheet(
|
ConversationWebView.app_stylesheet = ClientWebView.load_app_stylesheet(
|
||||||
"conversation-web-view.css"
|
"conversation-web-view.css"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -56,33 +56,16 @@ public class ConversationWebView : Components.WebView {
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new web view for displaying an email message body.
|
|
||||||
*
|
|
||||||
* A new WebKitGTK WebProcess will be constructed for this view.
|
|
||||||
*/
|
|
||||||
public ConversationWebView(Application.Configuration config) {
|
public ConversationWebView(Application.Configuration config) {
|
||||||
base(config);
|
base(config);
|
||||||
init();
|
|
||||||
|
|
||||||
// These only need to be added when creating a new WebProcess,
|
|
||||||
// not when sharing one
|
|
||||||
this.user_content_manager.add_script(ConversationWebView.app_script);
|
this.user_content_manager.add_script(ConversationWebView.app_script);
|
||||||
this.user_content_manager.add_style_sheet(ConversationWebView.app_stylesheet);
|
this.user_content_manager.add_style_sheet(ConversationWebView.app_stylesheet);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
register_message_handler(
|
||||||
* Constructs a new web view for displaying an email message body.
|
DECEPTIVE_LINK_CLICKED, on_deceptive_link_clicked
|
||||||
*
|
);
|
||||||
* The WebKitGTK WebProcess will be shared with the related view's
|
|
||||||
* process.
|
this.notify["preferred-height"].connect(() => queue_resize());
|
||||||
*/
|
|
||||||
internal ConversationWebView.with_related_view(
|
|
||||||
Application.Configuration config,
|
|
||||||
ConversationWebView related
|
|
||||||
) {
|
|
||||||
base.with_related_view(config, related);
|
|
||||||
init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -212,14 +195,6 @@ public class ConversationWebView : Components.WebView {
|
||||||
minimum_height = natural_height = 0;
|
minimum_height = natural_height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init() {
|
|
||||||
register_message_handler(
|
|
||||||
DECEPTIVE_LINK_CLICKED, on_deceptive_link_clicked
|
|
||||||
);
|
|
||||||
|
|
||||||
this.notify["preferred-height"].connect(() => queue_resize());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void on_deceptive_link_clicked(WebKit.JavascriptResult result) {
|
private void on_deceptive_link_clicked(WebKit.JavascriptResult result) {
|
||||||
try {
|
try {
|
||||||
JSC.Value object = result.get_js_value();
|
JSC.Value object = result.get_js_value();
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ geary_client_vala_sources = files(
|
||||||
|
|
||||||
'client-action.vala',
|
'client-action.vala',
|
||||||
|
|
||||||
|
'components/client-web-view.vala',
|
||||||
'components/components-attachment-pane.vala',
|
'components/components-attachment-pane.vala',
|
||||||
'components/components-entry-undo.vala',
|
'components/components-entry-undo.vala',
|
||||||
'components/components-inspector.vala',
|
'components/components-inspector.vala',
|
||||||
|
|
@ -40,7 +41,6 @@ geary_client_vala_sources = files(
|
||||||
'components/components-reflow-box.c',
|
'components/components-reflow-box.c',
|
||||||
'components/components-search-bar.vala',
|
'components/components-search-bar.vala',
|
||||||
'components/components-validator.vala',
|
'components/components-validator.vala',
|
||||||
'components/components-web-view.vala',
|
|
||||||
'components/count-badge.vala',
|
'components/count-badge.vala',
|
||||||
'components/folder-popover.vala',
|
'components/folder-popover.vala',
|
||||||
'components/icon-factory.vala',
|
'components/icon-factory.vala',
|
||||||
|
|
@ -142,6 +142,16 @@ geary_client_dependencies = [
|
||||||
|
|
||||||
geary_client_vala_args = geary_vala_args
|
geary_client_vala_args = geary_vala_args
|
||||||
|
|
||||||
|
# Enable shared shecondary process if available.
|
||||||
|
# See issues #558 and #559
|
||||||
|
webkit_version = webkit2gtk.version().split('.')
|
||||||
|
if webkit_version[0].to_int() <= 2 and webkit_version[1].to_int() <= 24
|
||||||
|
message('Enabling WebKitGTK shared process model')
|
||||||
|
geary_client_vala_args += [
|
||||||
|
'-D', 'HAS_WEBKIT_SHARED_PROC'
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
# Main client application library
|
# Main client application library
|
||||||
geary_client_lib = static_library('geary-client',
|
geary_client_lib = static_library('geary-client',
|
||||||
geary_client_sources,
|
geary_client_sources,
|
||||||
|
|
|
||||||
|
|
@ -32,14 +32,22 @@ public class GearyWebExtension : Object {
|
||||||
|
|
||||||
private const string[] ALLOWED_SCHEMES = { "cid", "geary", "data", "blob" };
|
private const string[] ALLOWED_SCHEMES = { "cid", "geary", "data", "blob" };
|
||||||
|
|
||||||
private const string REMOTE_LOAD_VAR = "_gearyAllowRemoteResourceLoads";
|
|
||||||
|
|
||||||
private WebKit.WebExtension extension;
|
private WebKit.WebExtension extension;
|
||||||
|
|
||||||
|
|
||||||
public GearyWebExtension(WebKit.WebExtension extension) {
|
public GearyWebExtension(WebKit.WebExtension extension) {
|
||||||
this.extension = extension;
|
this.extension = extension;
|
||||||
extension.page_created.connect(on_page_created);
|
extension.page_created.connect((extension, web_page) => {
|
||||||
|
web_page.console_message_sent.connect(on_console_message);
|
||||||
|
web_page.send_request.connect(on_send_request);
|
||||||
|
// XXX investigate whether the earliest supported
|
||||||
|
// version of WK supports the DOM "selectionchanged"
|
||||||
|
// event, and if so use that rather that doing it in
|
||||||
|
// here in the extension
|
||||||
|
web_page.get_editor().selection_changed.connect(() => {
|
||||||
|
selection_changed(web_page);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX Conditionally enable while we still depend on WK2 <2.12
|
// XXX Conditionally enable while we still depend on WK2 <2.12
|
||||||
|
|
@ -81,7 +89,14 @@ public class GearyWebExtension : Object {
|
||||||
WebKit.Frame frame = page.get_main_frame();
|
WebKit.Frame frame = page.get_main_frame();
|
||||||
JSC.Context context = frame.get_js_context();
|
JSC.Context context = frame.get_js_context();
|
||||||
try {
|
try {
|
||||||
should_load = Util.JS.to_bool(context.get_value(REMOTE_LOAD_VAR));
|
JSC.Value ret = execute_script(
|
||||||
|
context,
|
||||||
|
"geary.allowRemoteImages",
|
||||||
|
GLib.Log.FILE,
|
||||||
|
GLib.Log.METHOD,
|
||||||
|
GLib.Log.LINE
|
||||||
|
);
|
||||||
|
should_load = Util.JS.to_bool(ret);
|
||||||
} catch (GLib.Error err) {
|
} catch (GLib.Error err) {
|
||||||
debug(
|
debug(
|
||||||
"Error checking PageState::allowRemoteImages: %s",
|
"Error checking PageState::allowRemoteImages: %s",
|
||||||
|
|
@ -139,24 +154,4 @@ public class GearyWebExtension : Object {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_page_created(WebKit.WebExtension extension,
|
|
||||||
WebKit.WebPage page) {
|
|
||||||
WebKit.Frame frame = page.get_main_frame();
|
|
||||||
JSC.Context context = frame.get_js_context();
|
|
||||||
context.set_value(
|
|
||||||
REMOTE_LOAD_VAR,
|
|
||||||
new JSC.Value.boolean(context, false)
|
|
||||||
);
|
|
||||||
|
|
||||||
page.console_message_sent.connect(on_console_message);
|
|
||||||
page.send_request.connect(on_send_request);
|
|
||||||
// XXX investigate whether the earliest supported
|
|
||||||
// version of WK supports the DOM "selectionchanged"
|
|
||||||
// event, and if so use that rather that doing it in
|
|
||||||
// here in the extension
|
|
||||||
page.get_editor().selection_changed.connect(() => {
|
|
||||||
selection_changed(page);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,42 +6,35 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
public abstract class Components.WebViewTestCase<V> : TestCase {
|
public abstract class ClientWebViewTestCase<V> : TestCase {
|
||||||
|
|
||||||
protected V? test_view = null;
|
protected V? test_view = null;
|
||||||
protected Application.Configuration? config = null;
|
protected Application.Configuration? config = null;
|
||||||
|
|
||||||
protected WebViewTestCase(string name) {
|
protected ClientWebViewTestCase(string name) {
|
||||||
base(name);
|
base(name);
|
||||||
}
|
|
||||||
|
|
||||||
public override void set_up() {
|
|
||||||
this.config = new Application.Configuration(Application.Client.SCHEMA_ID);
|
this.config = new Application.Configuration(Application.Client.SCHEMA_ID);
|
||||||
this.config.enable_debug = true;
|
this.config.enable_debug = true;
|
||||||
|
ClientWebView.init_web_context(
|
||||||
WebView.init_web_context(
|
|
||||||
this.config,
|
this.config,
|
||||||
File.new_for_path(_BUILD_ROOT_DIR).get_child("src"),
|
File.new_for_path(_BUILD_ROOT_DIR).get_child("src"),
|
||||||
File.new_for_path("/tmp") // XXX use something better here
|
File.new_for_path("/tmp") // XXX use something better here
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
WebView.load_resources(GLib.File.new_for_path("/tmp"));
|
ClientWebView.load_resources(GLib.File.new_for_path("/tmp"));
|
||||||
} catch (GLib.Error err) {
|
} catch (GLib.Error err) {
|
||||||
assert_not_reached();
|
assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.test_view = set_up_test_view();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void tear_down() {
|
public override void set_up() {
|
||||||
this.config = null;
|
this.test_view = set_up_test_view();
|
||||||
this.test_view = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract V set_up_test_view();
|
protected abstract V set_up_test_view();
|
||||||
|
|
||||||
protected virtual void load_body_fixture(string html = "") {
|
protected virtual void load_body_fixture(string html = "") {
|
||||||
WebView client_view = (WebView) this.test_view;
|
ClientWebView client_view = (ClientWebView) this.test_view;
|
||||||
client_view.load_html(html);
|
client_view.load_html(html);
|
||||||
while (!client_view.is_content_loaded) {
|
while (!client_view.is_content_loaded) {
|
||||||
Gtk.main_iteration();
|
Gtk.main_iteration();
|
||||||
|
|
@ -49,7 +42,7 @@ public abstract class Components.WebViewTestCase<V> : TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected WebKit.JavascriptResult run_javascript(string command) throws Error {
|
protected WebKit.JavascriptResult run_javascript(string command) throws Error {
|
||||||
WebView view = (WebView) this.test_view;
|
ClientWebView view = (ClientWebView) this.test_view;
|
||||||
view.run_javascript.begin(
|
view.run_javascript.begin(
|
||||||
command, null, (obj, res) => { async_complete(res); }
|
command, null, (obj, res) => { async_complete(res); }
|
||||||
);
|
);
|
||||||
|
|
@ -5,10 +5,10 @@
|
||||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Components.WebViewTest : TestCase {
|
public class ClientWebViewTest : TestCase {
|
||||||
|
|
||||||
public WebViewTest() {
|
public ClientWebViewTest() {
|
||||||
base("Components.WebViewTest");
|
base("ClientWebViewTest");
|
||||||
add_test("init_web_context", init_web_context);
|
add_test("init_web_context", init_web_context);
|
||||||
add_test("load_resources", load_resources);
|
add_test("load_resources", load_resources);
|
||||||
}
|
}
|
||||||
|
|
@ -18,7 +18,7 @@ public class Components.WebViewTest : TestCase {
|
||||||
Application.Client.SCHEMA_ID
|
Application.Client.SCHEMA_ID
|
||||||
);
|
);
|
||||||
config.enable_debug = true;
|
config.enable_debug = true;
|
||||||
WebView.init_web_context(
|
ClientWebView.init_web_context(
|
||||||
config,
|
config,
|
||||||
File.new_for_path(_BUILD_ROOT_DIR).get_child("src"),
|
File.new_for_path(_BUILD_ROOT_DIR).get_child("src"),
|
||||||
File.new_for_path("/tmp") // XXX use something better here
|
File.new_for_path("/tmp") // XXX use something better here
|
||||||
|
|
@ -27,7 +27,7 @@ public class Components.WebViewTest : TestCase {
|
||||||
|
|
||||||
public void load_resources() throws GLib.Error {
|
public void load_resources() throws GLib.Error {
|
||||||
try {
|
try {
|
||||||
WebView.load_resources(GLib.File.new_for_path("/tmp"));
|
ClientWebView.load_resources(GLib.File.new_for_path("/tmp"));
|
||||||
} catch (GLib.Error err) {
|
} catch (GLib.Error err) {
|
||||||
assert_not_reached();
|
assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Composer.WebViewTest : Components.WebViewTestCase<Composer.WebView> {
|
public class Composer.WebViewTest : ClientWebViewTestCase<Composer.WebView> {
|
||||||
|
|
||||||
|
|
||||||
public WebViewTest() {
|
public WebViewTest() {
|
||||||
|
|
|
||||||
|
|
@ -5,24 +5,24 @@
|
||||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Components.PageStateTest : WebViewTestCase<WebView> {
|
class ClientPageStateTest : ClientWebViewTestCase<ClientWebView> {
|
||||||
|
|
||||||
|
|
||||||
private class TestWebView : Components.WebView {
|
private class TestClientWebView : ClientWebView {
|
||||||
|
|
||||||
public TestWebView(Application.Configuration config) {
|
public TestClientWebView(Application.Configuration config) {
|
||||||
base(config);
|
base(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public PageStateTest() {
|
public ClientPageStateTest() {
|
||||||
base("Components.PageStateTest");
|
base("ClientPageStateTest");
|
||||||
add_test("content_loaded", content_loaded);
|
add_test("content_loaded", content_loaded);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
WebView.load_resources(GLib.File.new_for_path("/tmp"));
|
ClientWebView.load_resources(GLib.File.new_for_path("/tmp"));
|
||||||
} catch (GLib.Error err) {
|
} catch (GLib.Error err) {
|
||||||
assert_not_reached();
|
assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
@ -45,7 +45,7 @@ class Components.PageStateTest : WebViewTestCase<WebView> {
|
||||||
assert(content_loaded_triggered);
|
assert(content_loaded_triggered);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override WebView set_up_test_view() {
|
protected override ClientWebView set_up_test_view() {
|
||||||
WebKit.UserScript test_script;
|
WebKit.UserScript test_script;
|
||||||
test_script = new WebKit.UserScript(
|
test_script = new WebKit.UserScript(
|
||||||
"var geary = new PageState()",
|
"var geary = new PageState()",
|
||||||
|
|
@ -55,7 +55,7 @@ class Components.PageStateTest : WebViewTestCase<WebView> {
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
WebView view = new TestWebView(this.config);
|
ClientWebView view = new TestClientWebView(this.config);
|
||||||
view.get_user_content_manager().add_script(test_script);
|
view.get_user_content_manager().add_script(test_script);
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Composer.PageStateTest : Components.WebViewTestCase<Composer.WebView> {
|
class Composer.PageStateTest : ClientWebViewTestCase<Composer.WebView> {
|
||||||
|
|
||||||
public const string COMPLETE_BODY_TEMPLATE =
|
public const string COMPLETE_BODY_TEMPLATE =
|
||||||
"""<div id="geary-body" dir="auto">%s<div><br></div><div><br></div></div><div id="geary-signature" dir="auto"></div>""";
|
"""<div id="geary-body" dir="auto">%s<div><br></div><div><br></div></div><div id="geary-signature" dir="auto"></div>""";
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* (version 2.1 or later). See the COPYING file in this distribution.
|
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ConversationPageStateTest : Components.WebViewTestCase<ConversationWebView> {
|
class ConversationPageStateTest : ClientWebViewTestCase<ConversationWebView> {
|
||||||
|
|
||||||
public ConversationPageStateTest() {
|
public ConversationPageStateTest() {
|
||||||
base("ConversationPageStateTest");
|
base("ConversationPageStateTest");
|
||||||
|
|
|
||||||
|
|
@ -82,16 +82,16 @@ geary_test_client_sources = [
|
||||||
'client/accounts/accounts-manager-test.vala',
|
'client/accounts/accounts-manager-test.vala',
|
||||||
'client/application/application-client-test.vala',
|
'client/application/application-client-test.vala',
|
||||||
'client/application/application-configuration-test.vala',
|
'client/application/application-configuration-test.vala',
|
||||||
|
'client/components/client-web-view-test.vala',
|
||||||
|
'client/components/client-web-view-test-case.vala',
|
||||||
'client/components/components-validator-test.vala',
|
'client/components/components-validator-test.vala',
|
||||||
'client/components/components-web-view-test-case.vala',
|
|
||||||
'client/components/components-web-view-test.vala',
|
|
||||||
'client/composer/composer-web-view-test.vala',
|
'client/composer/composer-web-view-test.vala',
|
||||||
'client/util/util-avatar-test.vala',
|
'client/util/util-avatar-test.vala',
|
||||||
'client/util/util-cache-test.vala',
|
'client/util/util-cache-test.vala',
|
||||||
'client/util/util-email-test.vala',
|
'client/util/util-email-test.vala',
|
||||||
'client/util/util-js-test.vala',
|
'client/util/util-js-test.vala',
|
||||||
|
|
||||||
'js/components-page-state-test.vala',
|
'js/client-page-state-test.vala',
|
||||||
'js/composer-page-state-test.vala',
|
'js/composer-page-state-test.vala',
|
||||||
'js/conversation-page-state-test.vala',
|
'js/conversation-page-state-test.vala',
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,9 +51,9 @@ int main(string[] args) {
|
||||||
client.add_suite(new Accounts.ManagerTest().get_suite());
|
client.add_suite(new Accounts.ManagerTest().get_suite());
|
||||||
client.add_suite(new Application.ClientTest().get_suite());
|
client.add_suite(new Application.ClientTest().get_suite());
|
||||||
client.add_suite(new Application.ConfigurationTest().get_suite());
|
client.add_suite(new Application.ConfigurationTest().get_suite());
|
||||||
client.add_suite(new Components.ValidatorTest().get_suite());
|
client.add_suite(new ClientWebViewTest().get_suite());
|
||||||
client.add_suite(new Components.WebViewTest().get_suite());
|
|
||||||
client.add_suite(new Composer.WebViewTest().get_suite());
|
client.add_suite(new Composer.WebViewTest().get_suite());
|
||||||
|
client.add_suite(new Components.ValidatorTest().get_suite());
|
||||||
client.add_suite(new Util.Avatar.Test().get_suite());
|
client.add_suite(new Util.Avatar.Test().get_suite());
|
||||||
client.add_suite(new Util.Cache.Test().get_suite());
|
client.add_suite(new Util.Cache.Test().get_suite());
|
||||||
client.add_suite(new Util.Email.Test().get_suite());
|
client.add_suite(new Util.Email.Test().get_suite());
|
||||||
|
|
@ -61,7 +61,7 @@ int main(string[] args) {
|
||||||
|
|
||||||
TestSuite js = new TestSuite("js");
|
TestSuite js = new TestSuite("js");
|
||||||
|
|
||||||
js.add_suite(new Components.PageStateTest().get_suite());
|
js.add_suite(new ClientPageStateTest().get_suite());
|
||||||
js.add_suite(new Composer.PageStateTest().get_suite());
|
js.add_suite(new Composer.PageStateTest().get_suite());
|
||||||
js.add_suite(new ConversationPageStateTest().get_suite());
|
js.add_suite(new ConversationPageStateTest().get_suite());
|
||||||
|
|
||||||
|
|
|
||||||
11
ui/client-web-view-allow-remote-images.js
Normal file
11
ui/client-web-view-allow-remote-images.js
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Michael Gratton <mike@vee.net>
|
||||||
|
*
|
||||||
|
* This software is licensed under the GNU Lesser General Public License
|
||||||
|
* (version 2.1 or later). See the COPYING file in this distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables remote image loading in a client web view.
|
||||||
|
*/
|
||||||
|
geary.allowRemoteImages = true;
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Application logic for Components.WebView and subclasses.
|
* Application logic for ClientWebView and subclasses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let PageState = function() {
|
let PageState = function() {
|
||||||
|
|
@ -14,6 +14,7 @@ let PageState = function() {
|
||||||
};
|
};
|
||||||
PageState.prototype = {
|
PageState.prototype = {
|
||||||
init: function() {
|
init: function() {
|
||||||
|
this.allowRemoteImages = false;
|
||||||
this.isLoaded = false;
|
this.isLoaded = false;
|
||||||
this.undoEnabled = false;
|
this.undoEnabled = false;
|
||||||
this.redoEnabled = false;
|
this.redoEnabled = false;
|
||||||
|
|
@ -107,7 +108,7 @@ PageState.prototype = {
|
||||||
window.webkit.messageHandlers.contentLoaded.postMessage(null);
|
window.webkit.messageHandlers.contentLoaded.postMessage(null);
|
||||||
},
|
},
|
||||||
loadRemoteImages: function() {
|
loadRemoteImages: function() {
|
||||||
window._gearyAllowRemoteResourceLoads = true;
|
this.allowRemoteImages = true;
|
||||||
let images = document.getElementsByTagName("IMG");
|
let images = document.getElementsByTagName("IMG");
|
||||||
for (let i = 0; i < images.length; i++) {
|
for (let i = 0; i < images.length; i++) {
|
||||||
let img = images.item(i);
|
let img = images.item(i);
|
||||||
|
|
@ -473,7 +473,6 @@
|
||||||
<object class="GtkRevealer" id="body_revealer">
|
<object class="GtkRevealer" id="body_revealer">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">False</property>
|
<property name="can_focus">False</property>
|
||||||
<property name="transition_type">slide-up</property>
|
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkGrid">
|
<object class="GtkGrid">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@
|
||||||
<file compressed="true" preprocess="xml-stripblanks">accounts_editor_servers_pane.ui</file>
|
<file compressed="true" preprocess="xml-stripblanks">accounts_editor_servers_pane.ui</file>
|
||||||
<file compressed="true" preprocess="xml-stripblanks">application-main-window.ui</file>
|
<file compressed="true" preprocess="xml-stripblanks">application-main-window.ui</file>
|
||||||
<file compressed="true" preprocess="xml-stripblanks">certificate_warning_dialog.glade</file>
|
<file compressed="true" preprocess="xml-stripblanks">certificate_warning_dialog.glade</file>
|
||||||
<file compressed="true">components-web-view.js</file>
|
<file compressed="true">client-web-view.js</file>
|
||||||
|
<file compressed="true">client-web-view-allow-remote-images.js</file>
|
||||||
<file compressed="true" preprocess="xml-stripblanks">components-attachment-pane.ui</file>
|
<file compressed="true" preprocess="xml-stripblanks">components-attachment-pane.ui</file>
|
||||||
<file compressed="true" preprocess="xml-stripblanks">components-attachment-pane-menus.ui</file>
|
<file compressed="true" preprocess="xml-stripblanks">components-attachment-pane-menus.ui</file>
|
||||||
<file compressed="true" preprocess="xml-stripblanks">components-attachment-view.ui</file>
|
<file compressed="true" preprocess="xml-stripblanks">components-attachment-view.ui</file>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue