{"id":786,"date":"2014-08-06T12:45:40","date_gmt":"2014-08-06T10:45:40","guid":{"rendered":"http:\/\/blogs.igalia.com\/carlosgc\/?p=786"},"modified":"2014-08-06T12:45:40","modified_gmt":"2014-08-06T10:45:40","slug":"gtk-3-plugins-in-webkitgtk-and-evince-browser-plugin","status":"publish","type":"post","link":"https:\/\/blogs.igalia.com\/carlosgc\/2014\/08\/06\/gtk-3-plugins-in-webkitgtk-and-evince-browser-plugin\/","title":{"rendered":"GTK+ 3 Plugins in WebKitGTK+ and Evince Browser Plugin"},"content":{"rendered":"<h2>GTK+ 3 plugins in WebKitGTK+<\/h2>\n<p>The <a href=\"http:\/\/webkitgtk.org\/reference\/webkit2gtk\/stable\/index.html\">WebKit2 GTK+ API<\/a> has always been GTK+ 3 only, but WebKitGTK+ still had a hard dependency on GTK+ 2 because of the plugin process. Some popular browser plugins like flash or Java use GTK+ 2 unconditionally (and it seems they are not going to be ported to GTK+ 3, at least not in the short term). These plugins stopped working in Epiphany when it switched to GTK+ 3 and started to work again when Epiphany moved to WebKit2.<\/p>\n<p>To support GTK+ 2 plugins we had to build the plugin process with GTK+ 2, but also some parts of WebCore and WebKit2 (the ones depending on GTK+ and used by the plugin process) were built twice. As a result we had a WebKitPluginProcess binary of ~40MB, that was always used for all the plugins. This kind of made sense, since there were no plugins using GTK+ 3, and the GTK+ 2 dependency was harmless for plugins not using GTK+ at all. However, we realized we were making a rule for the exception, since most of the plugins don&#8217;t even use GTK+, and there weren&#8217;t plugins using GTK+ 3 because they were not supported by any browser (kind of chicken-egg problem).<\/p>\n<p>Since <a href=\"https:\/\/lists.webkit.org\/pipermail\/webkit-gtk\/2014-August\/002002.html\">WebKitGTK+ 2.5.1<\/a> we have two binaries for the plugin process: WebKitPluginProcess2 which is exactly the same 40MB binary using GTK+ 2 that we have always had, but that now is only used to load plugins using GTK+ 2; and WebKitPluginProcess, a 7,4K binary that is now used by default for everything except loading plugins that use GTK+ 2. And since it links to GTK+ 3, it might load plugins using GTK+ 3 as well. Another side effect is that now <a href=\"https:\/\/bugs.webkit.org\/show_bug.cgi?id=135505\">we can make GTK+ 2 optional<\/a>, WebKitPluginProcess2 wouldn&#8217;t be built and only plugins using GTK+ 2 wouldn&#8217;t be supported.<\/p>\n<h2>Evince Browser Plugin<\/h2>\n<p>For a long time, <a href=\"https:\/\/bugzilla.gnome.org\/show_bug.cgi?id=168933\">we have maintained that PDF documents shouldn&#8217;t be opened inside the browser<\/a>, but downloaded and then opened by the default document viewer. But then the GNOME design team came up with <a href=\"https:\/\/wiki.gnome.org\/Design\/Apps\/Web\">new mockups for Epiphany<\/a> were everything was integrated in the browser, including PDF documents. It&#8217;s something all the major browsers do nowadays, using different approaches though (Custom PDF plugin inside the web engine, JavaScript libraries, etc.).<\/p>\n<p>At the <a href=\"https:\/\/blogs.igalia.com\/carlosgc\/2012\/12\/26\/webkitgtk-hackfest-2012\/\">WebKitGTK+ hackfest in 2012<\/a> we started to think about how to implement the integrated document reading in Epiphany based on the design mockups. We quickly discarded the idea of implementing it as a NPAPI plugin, because that would mean we had to use a very old evince version using GTK+ 2. We can&#8217;t implement it inside WebKit using libevince because it&#8217;s a GPL library, so the first approach was to implement it inside Epiphany using libevince. I wrote a <a href=\"https:\/\/bugzilla.gnome.org\/show_bug.cgi?id=689992\">first patch<\/a>, it was mostly a proof of concept hack, that added a new view widget based on EvView to be used instead of a WebView when a document supported by evince was requested. This approach has a lot of limitations, since it only works when the main resource is a document, but not for documents embedded in a HTML page or an iframe, and a lot of integration problems that makes it quite difficult to maintain inside Epiphany. All of these issues would be solved by implementing it as a NPAPI plugin and it wouldn&#8217;t require any change in Epiphany. Now that WebKitGTK+ supports GTK+ 3 plugins, there&#8217;s no reason not to do so.<\/p>\n<p><a href=\"http:\/\/blogs.igalia.com\/carlosgc\/files\/2014\/08\/ephy-evince-plugin.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-788\" alt=\"Epiphany Evince Plugin\" src=\"http:\/\/blogs.igalia.com\/carlosgc\/files\/2014\/08\/ephy-evince-plugin-277x300.png\" width=\"277\" height=\"300\" srcset=\"https:\/\/blogs.igalia.com\/carlosgc\/files\/2014\/08\/ephy-evince-plugin-277x300.png 277w, https:\/\/blogs.igalia.com\/carlosgc\/files\/2014\/08\/ephy-evince-plugin.png 867w\" sizes=\"auto, (max-width: 277px) 100vw, 277px\" \/><\/a><\/p>\n<p>Thanks to a project in <a href=\"http:\/\/www.igalia.com\/\">Igalia<\/a> I&#8217;ve been able to work on it, and today I&#8217;ve <a href=\"https:\/\/git.gnome.org\/browse\/evince\/commit\/?id=2806bd5dc451e684b44024ccb5efe22d1e8e5d7e\">landed an initial implementation of the browser plugin to Evince git master<\/a>. It&#8217;s only a first implementation (written in C++ 11) with the basic features (page navigation, view modes, zoom and printing), and a very simple UI that needs to be updated to match the mockups. It can be disabled at compile time like all other frontends inside Evince (thumbnailer, previewer, nautilus properties page).<\/p>\n<table style=\"border: none;\" width=\"100%\">\n<tbody>\n<tr>\n<td style=\"border: none;\"><a href=\"http:\/\/blogs.igalia.com\/carlosgc\/files\/2014\/08\/ephy-pdf-embedded.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-789 aligncenter\" alt=\"Epiphany embedded PDF document\" src=\"http:\/\/blogs.igalia.com\/carlosgc\/files\/2014\/08\/ephy-pdf-embedded-246x300.png\" width=\"246\" height=\"300\" srcset=\"https:\/\/blogs.igalia.com\/carlosgc\/files\/2014\/08\/ephy-pdf-embedded-246x300.png 246w, https:\/\/blogs.igalia.com\/carlosgc\/files\/2014\/08\/ephy-pdf-embedded.png 663w\" sizes=\"auto, (max-width: 246px) 100vw, 246px\" \/><\/a><\/td>\n<td style=\"border: none;\"><a href=\"http:\/\/blogs.igalia.com\/carlosgc\/files\/2014\/08\/ephy-pdf-standalone.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-790 aligncenter\" alt=\"Epiphany standalone PDF document\" src=\"http:\/\/blogs.igalia.com\/carlosgc\/files\/2014\/08\/ephy-pdf-standalone-300x290.png\" width=\"300\" height=\"290\" srcset=\"https:\/\/blogs.igalia.com\/carlosgc\/files\/2014\/08\/ephy-pdf-standalone-300x290.png 300w, https:\/\/blogs.igalia.com\/carlosgc\/files\/2014\/08\/ephy-pdf-standalone.png 663w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Another advantage of being a NPAPI plugin is that it&#8217;s scriptable so that you can control the viewer using JavaScript.<\/p>\n<p><a href=\"http:\/\/blogs.igalia.com\/carlosgc\/files\/2014\/08\/ephy-pdf-scriptable.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-799\" alt=\"Epiphany scriptable PDF\" src=\"http:\/\/blogs.igalia.com\/carlosgc\/files\/2014\/08\/ephy-pdf-scriptable-300x296.png\" width=\"300\" height=\"296\" srcset=\"https:\/\/blogs.igalia.com\/carlosgc\/files\/2014\/08\/ephy-pdf-scriptable-300x296.png 300w, https:\/\/blogs.igalia.com\/carlosgc\/files\/2014\/08\/ephy-pdf-scriptable.png 738w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>And you can pass initial parameters (like current page, zoom level, view mode, etc.) from the HTML tag.<\/p>\n<pre>&lt;object data=\"test.pdf\" type=\"application\/pdf\" width=\"600\" height=\"300\" \r\n                currentPage=\"2\" zoomMode=\"fit-page\" continuous=\"false\"&gt;\r\n  The pdf could not be rendered.\r\n&lt;\/object&gt;<\/pre>\n<p>You can even hide the default toolbar and build your own one using HTML and JavaScript.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>GTK+ 3 plugins in WebKitGTK+ The WebKit2 GTK+ API has always been GTK+ 3 only, but WebKitGTK+ still had a hard dependency on GTK+ 2 because of the plugin process. Some popular browser plugins like flash or Java use GTK+ &hellip; <a href=\"https:\/\/blogs.igalia.com\/carlosgc\/2014\/08\/06\/gtk-3-plugins-in-webkitgtk-and-evince-browser-plugin\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":9,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,6,7,8],"tags":[21,12,17,22],"class_list":["post-786","post","type-post","status-publish","format-standard","hentry","category-free-software","category-gnome","category-igalia","category-webkit","tag-epiphany","tag-evince","tag-pdf","tag-webkit"],"_links":{"self":[{"href":"https:\/\/blogs.igalia.com\/carlosgc\/wp-json\/wp\/v2\/posts\/786","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.igalia.com\/carlosgc\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.igalia.com\/carlosgc\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.igalia.com\/carlosgc\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.igalia.com\/carlosgc\/wp-json\/wp\/v2\/comments?post=786"}],"version-history":[{"count":15,"href":"https:\/\/blogs.igalia.com\/carlosgc\/wp-json\/wp\/v2\/posts\/786\/revisions"}],"predecessor-version":[{"id":805,"href":"https:\/\/blogs.igalia.com\/carlosgc\/wp-json\/wp\/v2\/posts\/786\/revisions\/805"}],"wp:attachment":[{"href":"https:\/\/blogs.igalia.com\/carlosgc\/wp-json\/wp\/v2\/media?parent=786"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.igalia.com\/carlosgc\/wp-json\/wp\/v2\/categories?post=786"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.igalia.com\/carlosgc\/wp-json\/wp\/v2\/tags?post=786"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}