Merge lp:~midori/midori/moreBeans into lp:midori

Proposed by Christian Dywan
Status: Work in progress
Proposed branch: lp:~midori/midori/moreBeans
Merge into: lp:midori
Diff against target: 2151 lines (+954/-804)
29 files modified
CMakeLists.txt (+11/-2)
extensions/CMakeLists.txt (+89/-72)
extensions/about.vala (+6/-1)
extensions/example.py (+14/-0)
extensions/examplepy.plugin (+9/-0)
extensions/extension-manager.vala (+273/-0)
extensions/hsts.web.plugin (+8/-0)
extensions/hsts.web.vala (+176/-0)
extensions/tabs-minimized.c (+0/-87)
extensions/tabs-minimized.plugin (+9/-0)
extensions/tabs-minimized.vala (+68/-0)
extensions/web-extension.web.vala (+68/-0)
ipc/CMakeLists.txt (+50/-0)
ipc/ipc-tab.vala (+19/-0)
katze/katze.vapi (+1/-0)
katze/midori-paths.vala (+38/-6)
midori/main.c (+50/-0)
midori/midori-app.c (+1/-1)
midori/midori-extension.c (+13/-0)
midori/midori-frontend.c (+0/-10)
midori/midori-preferences.c (+1/-31)
midori/midori-settings.vala (+22/-0)
midori/midori-stock.h (+1/-1)
midori/midori-tab.vala (+18/-0)
midori/midori.vapi (+3/-1)
midori/webkit2gtk-web-extension-4.0.vapi (+1/-1)
panels/midori-extensions.c (+0/-544)
panels/midori-extensions.h (+0/-45)
po/POTFILES.in (+5/-2)
To merge this branch: bzr merge lp:~midori/midori/moreBeans
Reviewer Review Type Date Requested Status
Midori Devs Pending
Review via email: mp+262521@code.launchpad.net

Commit message

Implement Peas plugin loading for GUI and web process

To post a comment you must log in.
lp:~midori/midori/moreBeans updated
6967. By Christian Dywan

HSTS and Minimized Tabs implemented with activatables

6968. By Christian Dywan

Use HAVE_PEAS for easier build testing

6969. By Christian Dywan

Reincarnate Extensions panel as Extension Manager with Peas support

Unmerged revisions

6969. By Christian Dywan

Reincarnate Extensions panel as Extension Manager with Peas support

6968. By Christian Dywan

Use HAVE_PEAS for easier build testing

6967. By Christian Dywan

HSTS and Minimized Tabs implemented with activatables

6966. By Christian Dywan

Implement Peas plugin loading for GUI and web process

6965. By Christian Dywan

Implement HSTS as a web extension

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2015-06-18 05:03:38 +0000
3+++ CMakeLists.txt 2015-06-22 22:20:28 +0000
4@@ -193,6 +193,12 @@
5 add_definitions("-DHAVE_GCR")
6 set(OPTS_INCLUDE_DIRS ${OPTS_INCLUDE_DIRS} ${GCR_INCLUDE_DIRS})
7 set(OPTS_LIBRARIES ${OPTS_LIBRARIES} ${GCR_LIBRARIES})
8+
9+ pkg_check_modules(PEAS REQUIRED libpeas-1.0>=1.4)
10+ set(OPTS_INCLUDE_DIRS ${OPTS_INCLUDE_DIRS} ${PEAS_INCLUDE_DIRS})
11+ set(OPTS_LIBRARIES ${OPTS_LIBRARIES} ${PEAS_LIBRARIES})
12+ set(PKGS ${PKGS} libpeas-1.0)
13+ set(VALAFLAGS ${VALAFLAGS} -D HAVE_PEAS)
14 endif ()
15
16 if (HALF_BRO_INCOM_WEBKIT2)
17@@ -204,7 +210,6 @@
18 add_definitions("-DGTK_VERSION=\"${DEPS_GTK_gtk+-3.0_VERSION}\"")
19 add_definitions("-DWEBKIT_VERSION=\"${DEPS_GTK_webkit2gtk-4.0_VERSION}\"")
20 set(PKGS ${PKGS} gtk+-3.0)
21- # set(EXTRA_VAPIS ${EXTRA_VAPIS} "${CMAKE_SOURCE_DIR}/midori/webkit2gtk-web-extension-4.0.vapi")
22 set(EXTRA_VAPIS ${EXTRA_VAPIS} "${CMAKE_SOURCE_DIR}/midori/webkit2gtk-4.0.vapi")
23 set(VALAFLAGS ${VALAFLAGS} -D HAVE_GTK3)
24 set(VALAFLAGS ${VALAFLAGS} -D HAVE_WEBKIT2)
25@@ -272,9 +277,13 @@
26 install(FILES AUTHORS COPYING ChangeLog EXPAT README DESTINATION ${CMAKE_INSTALL_DOCDIR})
27
28 add_subdirectory (midori)
29-add_subdirectory (extensions)
30+if (HALF_BRO_INCOM_WEBKIT2)
31+ set(LIBMIDORI2 "${CMAKE_PROJECT_NAME}-ipc")
32+ add_subdirectory (ipc)
33+endif ()
34 enable_testing()
35 add_subdirectory (tests)
36+add_subdirectory (extensions)
37 add_subdirectory (po)
38 add_subdirectory (icons)
39 add_subdirectory (data)
40
41=== modified file 'extensions/CMakeLists.txt'
42--- extensions/CMakeLists.txt 2015-04-19 14:06:12 +0000
43+++ extensions/CMakeLists.txt 2015-06-22 22:20:28 +0000
44@@ -8,9 +8,9 @@
45 ${DEPS_INCLUDE_DIRS}
46 ${OPTS_INCLUDE_DIRS}
47 ${DEPS_GTK_INCLUDE_DIRS}
48- ${OPTS_GTK_INCLUDE_DIRS}
49 ${CMAKE_BINARY_DIR}
50 "${CMAKE_BINARY_DIR}/midori"
51+ "${CMAKE_BINARY_DIR}/ipc"
52 )
53 file(GLOB EXTENSIONS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *)
54 if (HALF_BRO_INCOM_WEBKIT2)
55@@ -23,6 +23,11 @@
56 "nsplugin-manager.vala"
57 "tabs2one.c"
58 )
59+else ()
60+ list(REMOVE_ITEM EXTENSIONS
61+ "hsts.web.vala"
62+ "web-extension.web.vala"
63+ )
64 endif ()
65
66 # FIXME: re-enable webmedia extension
67@@ -36,99 +41,111 @@
68 list(REMOVE_ITEM EXTENSIONS "tabs2one.c")
69 endif()
70
71-foreach(UNIT_SRC ${EXTENSIONS})
72- string(FIND ${UNIT_SRC} ".c" UNIT_EXTENSION)
73- if (UNIT_EXTENSION GREATER -1)
74- string(REPLACE ".c" "" UNIT ${UNIT_SRC})
75- add_library(${UNIT} MODULE ${UNIT_SRC})
76- target_link_libraries(${UNIT}
77- ${LIBMIDORI}
78- )
79- set_target_properties(${UNIT} PROPERTIES
80- COMPILE_FLAGS ${CFLAGS}
81- )
82- install(TARGETS ${UNIT}
83- LIBRARY DESTINATION ${EXTENSIONDIR}
84- )
85+include(ValaPrecompile)
86+
87+macro(build_extension name)
88+ set(source "${ARGN}")
89+ set(SOURCE_VALA "")
90+
91+ set(PLUGIN "${CMAKE_CURRENT_SOURCE_DIR}/${name}.plugin")
92+ if (EXISTS ${PLUGIN})
93+ file(COPY ${PLUGIN} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
94 endif ()
95-endforeach ()
96
97-foreach(UNIT_SRC ${EXTENSIONS})
98- string(FIND ${UNIT_SRC} "." UNIT_EXTENSION)
99- if (UNIT_EXTENSION EQUAL -1)
100- file(GLOB UNIT_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${UNIT_SRC}/*.c")
101- file(GLOB UNIT_FILES_VALA RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${UNIT_SRC}/*.vala")
102- if (UNIT_FILES_VALA)
103- include(ValaPrecompile)
104- vala_precompile(UNIT_SRC_C ${UNIT_SRC}
105- ${UNIT_FILES_VALA}
106+ foreach(FILE ${source})
107+ string(FIND ${FILE} ".web." WEB_EXTENSION)
108+ string(FIND ${FILE} ".vala" VALA_EXTENSION)
109+ if (WEB_EXTENSION GREATER -1)
110+ string(REPLACE ".vala" "" WEB_NAME "${name}_${FILE}")
111+ string(REPLACE "." "_" WEB_NAME "${WEB_NAME}")
112+ vala_precompile(WEB_EXTENSION_C "${WEB_NAME}"
113+ ${FILE}
114 PACKAGES
115 ${PKGS}
116 OPTIONS
117 ${VALAFLAGS}
118- --use-header="${CMAKE_PROJECT_NAME}-core.h"
119- GENERATE_HEADER
120- "${UNIT_SRC}"
121- GENERATE_HEADER
122- ${UNIT}
123+ GENERATE_HEADER
124+ ${FILE}
125 CUSTOM_VAPIS
126- ${EXTRA_VAPIS}
127- "${CMAKE_SOURCE_DIR}/midori/midori.vapi"
128- "${CMAKE_BINARY_DIR}/midori/${LIBMIDORI}.vapi"
129+ "${CMAKE_BINARY_DIR}/ipc/${LIBMIDORI2}.vapi"
130+ "${CMAKE_SOURCE_DIR}/midori/webkit2gtk-web-extension-4.0.vapi"
131 )
132- set(UNIT_FILES ${UNIT_FILES} ${UNIT_SRC_C})
133- endif ()
134- if (UNIT_FILES)
135- add_library(${UNIT_SRC} MODULE ${UNIT_FILES})
136- target_link_libraries(${UNIT_SRC}
137- ${LIBMIDORI}
138- )
139- install(TARGETS ${UNIT_SRC}
140+ add_library(${WEB_NAME} MODULE ${WEB_EXTENSION_C})
141+ target_link_libraries(${WEB_NAME}
142+ ${LIBMIDORI2}
143+ )
144+ install(TARGETS ${WEB_NAME}
145 LIBRARY DESTINATION ${EXTENSIONDIR}
146 )
147- # extensions with vala code get the lenient VALA_CFLAGS
148- # others get the usual CFLAGS with -Wall and -Werror
149- if (UNIT_FILES_VALA)
150- set_target_properties(${UNIT_SRC} PROPERTIES
151- COMPILE_FLAGS ${VALA_CFLAGS}
152- )
153- else ()
154- set_target_properties(${UNIT_SRC} PROPERTIES
155- COMPILE_FLAGS ${CFLAGS}
156- )
157- endif ()
158+ # Extensions with Vala code get the lenient VALA_CFLAGS
159+ set_target_properties(${WEB_NAME} PROPERTIES
160+ COMPILE_FLAGS ${VALA_CFLAGS}
161+ )
162+ list(REMOVE_ITEM source ${FILE})
163+
164+ # Mandatory unit testing
165+ add_test(NAME "test-${WEB_NAME}" COMMAND $<TARGET_FILE:midori> -t $<TARGET_FILE:${WEB_NAME}>)
166+ contain_test("test-${WEB_NAME}" $<TARGET_FILE:midori> -t $<TARGET_FILE:${WEB_NAME}>)
167+ elseif (VALA_EXTENSION GREATER -1)
168+ list(APPEND SOURCE_VALA ${FILE})
169 endif ()
170- endif ()
171-endforeach ()
172-
173-foreach(UNIT_SRC ${EXTENSIONS})
174- string(FIND ${UNIT_SRC} ".vala" UNIT_EXTENSION)
175- if (UNIT_EXTENSION GREATER -1)
176- string(REPLACE ".vala" "" UNIT ${UNIT_SRC})
177- include(ValaPrecompile)
178- vala_precompile(UNIT_SRC_C ${UNIT}
179- ${UNIT_SRC}
180+ endforeach()
181+ if (SOURCE_VALA)
182+ vala_precompile(SOURCE_C ${name}
183+ ${SOURCE_VALA}
184 PACKAGES
185 ${PKGS}
186 OPTIONS
187- ${VALAFLAGS}
188- --use-header="${CMAKE_PROJECT_NAME}-core.h"
189+ ${VALAFLAGS}
190 GENERATE_HEADER
191- ${UNIT}
192+ ${name}
193 CUSTOM_VAPIS
194- ${EXTRA_VAPIS}
195+ ${EXTRA_VAPIS}
196 "${CMAKE_SOURCE_DIR}/midori/midori.vapi"
197 "${CMAKE_BINARY_DIR}/midori/${LIBMIDORI}.vapi"
198 )
199- add_library(${UNIT} MODULE ${UNIT_SRC_C})
200- target_link_libraries(${UNIT}
201+ set(source ${SOURCE_C})
202+ endif ()
203+ if (source)
204+ add_library(${name} MODULE ${source})
205+ target_link_libraries(${name}
206 ${LIBMIDORI}
207 )
208- set_target_properties(${UNIT} PROPERTIES
209- COMPILE_FLAGS "${VALA_CFLAGS}"
210- )
211- install(TARGETS ${UNIT}
212+ install(TARGETS ${name}
213 LIBRARY DESTINATION ${EXTENSIONDIR}
214 )
215+ if (SOURCE_VALA)
216+ # Extensions with Vala code get the lenient VALA_CFLAGS
217+ set_target_properties(${name} PROPERTIES
218+ COMPILE_FLAGS ${VALA_CFLAGS}
219+ )
220+ else ()
221+ set_target_properties(${name} PROPERTIES
222+ COMPILE_FLAGS ${CFLAGS}
223+ )
224+ endif ()
225+ # Optional unit test
226+ add_test(NAME "test-${name}" COMMAND $<TARGET_FILE:midori> -t $<TARGET_FILE:${name}>)
227+ contain_test("test-${name}" $<TARGET_FILE:midori> -t $<TARGET_FILE:${name}>)
228+ endif ()
229+endmacro(build_extension)
230+
231+foreach(UNIT_SRC ${EXTENSIONS})
232+ string(FIND ${UNIT_SRC} ".c" UNIT_EXTENSION)
233+ if (UNIT_EXTENSION GREATER -1)
234+ string(REPLACE ".c" "" UNIT ${UNIT_SRC})
235+ build_extension(${UNIT} ${UNIT_SRC})
236+ endif ()
237+
238+ string(FIND ${UNIT_SRC} "." UNIT_EXTENSION)
239+ if (UNIT_EXTENSION GREATER -1)
240+ file(GLOB UNIT_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${UNIT_SRC}/*.c" "${UNIT_SRC}/*.vala")
241+ build_extension(${UNIT_SRC} ${UNIT_FILES})
242+ endif ()
243+
244+ string(FIND ${UNIT_SRC} ".vala" UNIT_EXTENSION)
245+ if (UNIT_EXTENSION GREATER -1)
246+ string(REPLACE ".vala" "" UNIT ${UNIT_SRC})
247+ build_extension(${UNIT} ${UNIT_SRC})
248 endif ()
249 endforeach ()
250
251=== modified file 'extensions/about.vala'
252--- extensions/about.vala 2015-06-11 22:33:48 +0000
253+++ extensions/about.vala 2015-06-22 22:20:28 +0000
254@@ -140,7 +140,12 @@
255 GLib.StringBuilder ns_plugins = new GLib.StringBuilder ();
256 view.list_plugins (ns_plugins, true);
257
258- /* TODO: list active extensions */
259+#if HAVE_PEAS
260+ ns_plugins.append_printf ("</table><h2>%s</h2><table>", _("Extensions"));
261+ var engine = Peas.Engine.get_default ();
262+ foreach (unowned Peas.PluginInfo info in engine.get_plugin_list ())
263+ ns_plugins.append_printf ("<tr><td>%s <em>%s</em></td></tr>\n", info.get_name (), info.get_module_name ());
264+#endif
265
266 this.load_html (view, contents.printf (
267 _("Version numbers in brackets show the version used at runtime."),
268
269=== added file 'extensions/example.py'
270--- extensions/example.py 1970-01-01 00:00:00 +0000
271+++ extensions/example.py 2015-06-22 22:20:28 +0000
272@@ -0,0 +1,14 @@
273+# -*- coding: utf-8 py-indent-offset: 4 -*-
274+from gi.repository import GObject, Gtk, Peas
275+import os, gettext
276+
277+class ExamplePlugin(GObject.Object, Peas.Activatable):
278+ __gtype_name__ = "ExamplePlugin"
279+ object = GObject.property(type=GObject.Object)
280+
281+ def __init__(self):
282+ print("Example init")
283+ GObject.Object.__init__(self)
284+
285+ def do_activate(self):
286+ print("Example %s" % (self.object.props.uri))
287
288=== added file 'extensions/examplepy.plugin'
289--- extensions/examplepy.plugin 1970-01-01 00:00:00 +0000
290+++ extensions/examplepy.plugin 2015-06-22 22:20:28 +0000
291@@ -0,0 +1,9 @@
292+[Plugin]
293+Loader=python
294+Module=example
295+IAge=3
296+Name=Example in Python
297+Name[de]=Beispiel in Python
298+Author=Christian Dywan <christian@twotoasts.de>
299+Copyright=Copyright © 2015 Christian Dywan
300+Website=http://www.midori-browser.org
301
302=== added file 'extensions/extension-manager.vala'
303--- extensions/extension-manager.vala 1970-01-01 00:00:00 +0000
304+++ extensions/extension-manager.vala 2015-06-22 22:20:28 +0000
305@@ -0,0 +1,273 @@
306+/*
307+ Copyright (C) 2008-2015 Christian Dywan <christian@twotoasts.de>
308+
309+ This library is free software; you can redistribute it and/or
310+ modify it under the terms of the GNU Lesser General Public
311+ License as published by the Free Software Foundation; either
312+ version 2.1 of the License, or (at your option) any later version.
313+
314+ See the file COPYING for the full license text.
315+*/
316+
317+namespace Extensions {
318+ public class Sidebar : Gtk.VBox, Midori.Viewable {
319+ Gtk.Toolbar? toolbar = null;
320+ Gtk.ListStore store = new Gtk.ListStore (1, typeof (GLib.Object));
321+ Gtk.TreeView treeview;
322+ Midori.App app;
323+
324+ void on_add_item (Katze.Array extensions, GLib.Object item) {
325+ var extension = (Midori.Extension)item;
326+ Gtk.TreeIter iter;
327+ store.append (out iter);
328+ store.set (iter, 0, extension);
329+ extension.activate.connect (on_activate);
330+ extension.deactivate.connect (on_deactivate);
331+ }
332+
333+ void on_activate (Midori.Extension extension, Midori.App app) {
334+ treeview.queue_draw ();
335+ }
336+
337+ void on_deactivate (Midori.Extension extension) {
338+ treeview.queue_draw ();
339+ }
340+
341+ public unowned string get_stock_id () {
342+ return Midori.Stock.EXTENSION;
343+ }
344+
345+ public unowned string get_label () {
346+ return _("Extensions");
347+ }
348+
349+ public Gtk.Widget get_toolbar () {
350+ if (toolbar == null) {
351+ toolbar = new Gtk.Toolbar ();
352+ toolbar.set_icon_size (Gtk.IconSize.BUTTON);
353+ }
354+ return toolbar;
355+ }
356+
357+ internal Sidebar (Midori.App app) {
358+ Gtk.TreeViewColumn column;
359+
360+ treeview = new Gtk.TreeView.with_model (store);
361+ treeview.button_press_event.connect (on_button_pressed);
362+ store.set_sort_column_id (0, Gtk.SortType.ASCENDING);
363+ store.set_sort_func (0, tree_sort_func);
364+ treeview.headers_visible = false;
365+
366+ column = new Gtk.TreeViewColumn ();
367+ Gtk.CellRendererToggle renderer_toggle = new Gtk.CellRendererToggle ();
368+ column.pack_start (renderer_toggle, false);
369+ column.set_cell_data_func (renderer_toggle, on_render_tick);
370+ renderer_toggle.toggled.connect (on_renderer_toggled);
371+ treeview.append_column (column);
372+
373+ column = new Gtk.TreeViewColumn ();
374+ Gtk.CellRendererPixbuf renderer_icon = new Gtk.CellRendererPixbuf ();
375+ column.pack_start (renderer_icon, false);
376+ column.set_cell_data_func (renderer_icon, on_render_icon);
377+ treeview.append_column (column);
378+
379+ column = new Gtk.TreeViewColumn ();
380+ column.set_sizing (Gtk.TreeViewColumnSizing.AUTOSIZE);
381+ Gtk.CellRendererText renderer_text = new Gtk.CellRendererText ();
382+ column.pack_start (renderer_text, true);
383+ column.set_expand (true);
384+ column.set_cell_data_func (renderer_text, on_render_text);
385+ treeview.append_column (column);
386+
387+ column = new Midori.ExtensionsColumn ();
388+ (column as Midori.ExtensionsColumn).row_clicked.connect (on_preferences_clicked);
389+ Gtk.CellRendererPixbuf renderer_preferences = new Gtk.CellRendererPixbuf ();
390+ column.pack_start (renderer_preferences, false);
391+ column.set_sizing (Gtk.TreeViewColumnSizing.FIXED);
392+ column.set_fixed_width (30);
393+ column.set_cell_data_func (renderer_preferences, on_render_preferences);
394+ treeview.append_column (column);
395+ treeview.row_activated.connect (on_row_activated);
396+
397+ treeview.show ();
398+ pack_start (treeview, true, true, 0);
399+ assert (treeview.get_n_columns () > 0);
400+
401+ Katze.Array extensions = app.extensions;
402+ extensions.add_item.connect (on_add_item);
403+ foreach (GLib.Object extension in extensions.get_items ())
404+ on_add_item (extensions, extension);
405+
406+ this.app = app;
407+
408+#if HAVE_PEAS
409+ var engine = Peas.Engine.get_default ();
410+ engine.rescan_plugins ();
411+ foreach (unowned Peas.PluginInfo info in engine.get_plugin_list ()) {
412+ var extension = (Midori.Extension)GLib.Object.new (typeof (Midori.Extension),
413+ name: info.get_name (),
414+ description: info.get_description (),
415+ version: info.get_version () + Midori.VERSION_SUFFIX,
416+ website: info.get_website (),
417+ authors: string.joinv (",", info.get_authors ()));
418+ extension.set_data<string?> ("filename", info.get_module_name ());
419+ extension.activate.connect ((app) => { engine.try_load_plugin (info); });
420+ extension.deactivate.connect (() => { engine.try_unload_plugin (info); });
421+ extensions.add_item (extension);
422+ }
423+#endif
424+ }
425+
426+ int tree_sort_func (Gtk.TreeModel model, Gtk.TreeIter a, Gtk.TreeIter b) {
427+ Midori.Extension e1, e2;
428+ model.get (a, 0, out e1);
429+ model.get (b, 0, out e2);
430+ return strcmp (e1.name, e2.name);
431+ }
432+
433+ bool on_button_pressed (Gtk.Widget widget, Gdk.EventButton event) {
434+ bool ret = false;
435+ Gtk.TreePath path;
436+ Gtk.TreeViewColumn column;
437+ if (treeview.get_path_at_pos ((int)event.x, (int)event.y, out path, out column, null, null)) {
438+ if (path != null) {
439+ if (column is Midori.ExtensionsColumn) {
440+ uint signal_id = Signal.lookup ("row-clicked", typeof (Midori.ExtensionsColumn));
441+ if (signal_id > 0 && Signal.has_handler_pending (column, signal_id, 0, false)) {
442+ (column as Midori.ExtensionsColumn).row_clicked (treeview, path);
443+ ret = true;
444+ }
445+ }
446+ }
447+ }
448+ return ret;
449+ }
450+
451+ void on_renderer_toggled (Gtk.CellRendererToggle renderer, string path) {
452+ Gtk.TreeIter iter;
453+ if (store.get_iter_from_string (out iter, path)) {
454+ Midori.Extension extension;
455+ store.get (iter, 0, out extension);
456+ if (extension.is_active ())
457+ extension.deactivate ();
458+ else if (extension.is_prepared ())
459+ extension.activate (app);
460+ /* Make it easy for listeners to see that extensions changed */
461+ app.extensions.update ();
462+ }
463+ }
464+
465+ void on_render_tick (Gtk.CellLayout column, Gtk.CellRenderer renderer,
466+ Gtk.TreeModel model, Gtk.TreeIter iter) {
467+
468+ Midori.Extension extension;
469+ model.get (iter, 0, out extension);
470+ renderer.set ("activatable", extension.is_prepared (),
471+ "active", extension.is_active ()
472+ || extension.get_data<string>("static") != null,
473+ "xpad", 4);
474+ }
475+
476+ void on_render_icon (Gtk.CellLayout column, Gtk.CellRenderer renderer,
477+ Gtk.TreeModel model, Gtk.TreeIter iter) {
478+
479+ Midori.Extension extension;
480+ model.get (iter, 0, out extension);
481+ renderer.set ("stock-id", Midori.Stock.EXTENSION,
482+ "stock-size", Gtk.IconSize.BUTTON,
483+ "sensitive", extension.is_prepared (),
484+ "xpad", 4);
485+ }
486+
487+ void on_render_text (Gtk.CellLayout column, Gtk.CellRenderer renderer,
488+ Gtk.TreeModel model, Gtk.TreeIter iter) {
489+
490+ Midori.Extension extension;
491+ model.get (iter, 0, out extension);
492+ renderer.set ("markup", Markup.printf_escaped ("<b>%s</b> %s\n%s",
493+ extension.name, extension.version ?? "", extension.description),
494+ "ellipsize", Pango.EllipsizeMode.END,
495+ "sensitive", extension.is_prepared ());
496+ }
497+
498+ void on_render_preferences (Gtk.CellLayout column, Gtk.CellRenderer renderer,
499+ Gtk.TreeModel model, Gtk.TreeIter iter) {
500+
501+ Midori.Extension extension;
502+ model.get (iter, 0, out extension);
503+ renderer.set ("stock-id", Gtk.Stock.PREFERENCES,
504+ "stock-size", Gtk.IconSize.BUTTON,
505+ "visible", extension.has_preferences (),
506+ "sensitive", extension.is_active (),
507+ "xpad", 4);
508+ }
509+
510+ void on_preferences_clicked (Gtk.TreeView treeview, Gtk.TreePath path) {
511+ Gtk.TreeIter iter;
512+ if (store.get_iter (out iter, path)) {
513+ Midori.Extension extension;
514+ store.get (iter, 0, out extension);
515+ if (extension.is_active ())
516+ extension.open_preferences ();
517+ }
518+ }
519+
520+ void on_row_activated (Gtk.TreeView treeview, Gtk.TreePath path, Gtk.TreeViewColumn column) {
521+ Gtk.TreeIter iter;
522+ if (store.get_iter (out iter, path)) {
523+ Midori.Extension extension;
524+ store.get (iter, 0, out extension);
525+ if (extension.is_active ())
526+ extension.deactivate ();
527+ else if (extension.is_prepared ())
528+ extension.activate (app);
529+ /* Make it easy for listeners to see that extensions changed */
530+ app.extensions.update ();
531+ }
532+ }
533+ }
534+
535+ class Manager : Midori.Extension {
536+ void activated (Midori.App app) {
537+ foreach (var browser in app.get_browsers ())
538+ browser_added (browser);
539+ app.add_browser.connect (browser_added);
540+ }
541+
542+ void browser_added (Midori.Browser browser) {
543+ browser.show_preferences.connect (show_preferences);
544+ }
545+
546+ void show_preferences (Katze.Preferences preferences) {
547+ /* Check for new extensions */
548+ Midori.Extension.load_from_folder (get_app (), null, false);
549+ /* Hide if there are no extensions at all */
550+ if (get_app ().extensions.is_empty ())
551+ return;
552+ /* Reset frozen list: allow active extensions to be saved */
553+ get_app ().set_data<string[]?> ("extensions", null);
554+
555+ var viewable = new Sidebar (get_app ());
556+ viewable.show ();
557+ var scrolled = new Gtk.ScrolledWindow (null, null);
558+ /* For lack of a better way of keeping descriptions visible */
559+ scrolled.show ();
560+ scrolled.hscrollbar_policy = Gtk.PolicyType.NEVER;
561+ viewable.get_children ().nth_data (0).reparent (scrolled);
562+ var category = preferences.add_category (_("Extensions"), Midori.Stock.EXTENSION);
563+ category.pack_start (scrolled, true, true, 0);
564+ }
565+
566+ internal Manager () {
567+ GLib.Object (name: "Extension Manager",
568+ description: "Manage your extensions",
569+ version: "0.2" + Midori.VERSION_SUFFIX,
570+ authors: "Christian Dywan <christian@twotoasts.de>");
571+ activate.connect (activated);
572+ }
573+ }
574+}
575+
576+public Midori.Extension extension_init () {
577+ return new Extensions.Manager ();
578+}
579
580=== added file 'extensions/hsts.web.plugin'
581--- extensions/hsts.web.plugin 1970-01-01 00:00:00 +0000
582+++ extensions/hsts.web.plugin 2015-06-22 22:20:28 +0000
583@@ -0,0 +1,8 @@
584+[Plugin]
585+Module=hsts_web_hsts_web
586+IAge=3
587+Name=HSTS
588+Description=HTTP Strict Transport Security
589+Author=Christian Dywan <christian@twotoasts.de>
590+Copyright=Copyright © 2015 Christian Dywan
591+Website=http://www.midori-browser.org
592
593=== added file 'extensions/hsts.web.vala'
594--- extensions/hsts.web.vala 1970-01-01 00:00:00 +0000
595+++ extensions/hsts.web.vala 2015-06-22 22:20:28 +0000
596@@ -0,0 +1,176 @@
597+/*
598+ Copyright (C) 2012-2014 Christian Dywan <christian@twotoasts.de>
599+
600+ This library is free software; you can redistribute it and/or
601+ modify it under the terms of the GNU Lesser General Public
602+ License as published by the Free Software Foundation; either
603+ version 2.1 of the License, or (at your option) any later version.
604+
605+ See the file COPYING for the full license text.
606+*/
607+
608+namespace HSTS {
609+ public class Directive {
610+ public Soup.Date? expires = null;
611+ public bool sub_domains = false;
612+
613+ public Directive (bool include_sub_domains) {
614+ expires = new Soup.Date.from_now (int.MAX);
615+ sub_domains = include_sub_domains;
616+ }
617+
618+ public Directive.from_header (string header) {
619+ var param_list = Soup.header_parse_param_list (header);
620+ if (param_list == null)
621+ return;
622+
623+ string? max_age = param_list.lookup ("max-age");
624+ if (max_age != null)
625+ expires = new Soup.Date.from_now (max_age.to_int ());
626+ if ("includeSubDomains" in header)
627+ sub_domains = true;
628+ Soup.header_free_param_list (param_list);
629+ }
630+
631+ public bool is_valid () {
632+ return expires != null && !expires.is_past ();
633+ }
634+ }
635+
636+ public class Whitelist : Object {
637+ HashTable<string, Directive> whitelist;
638+ string preset = "/etc/xdg/midori/hsts";
639+ File config;
640+
641+ public Whitelist () {
642+ whitelist = new HashTable<string, Directive> (str_hash, str_equal);
643+ read_cache.begin (File.new_for_path (preset));
644+ // FIXME: config = File.new_for_path (Midori.Paths.get_config_filename_for_writing ("hsts"));
645+ string config_dir = Path.build_path (Path.DIR_SEPARATOR_S,
646+ Environment.get_user_config_dir (), "midori");
647+ config = File.new_for_path (Path.build_path (Path.DIR_SEPARATOR_S, config_dir, "hsts"));
648+ read_cache.begin (config);
649+ }
650+
651+ async void read_cache (File file) {
652+ try {
653+ var stream = new DataInputStream (yield file.read_async ());
654+ do {
655+ string? line = yield stream.read_line_async ();
656+ if (line == null)
657+ break;
658+ string[] parts = line.split (" ", 2);
659+ if (parts[0] == null || parts[1] == null)
660+ break;
661+ var directive = new Directive.from_header (parts[1]);
662+ if (directive.is_valid ())
663+ append_to_whitelist (parts[0], directive);
664+ } while (true);
665+ } catch (IOError.NOT_FOUND exist_error) {
666+ /* It's no error if no cache file exists */
667+ } catch (Error error) {
668+ warning ("Failed to read cache %s: %s", file.get_path (), error.message);
669+ }
670+ }
671+
672+ public bool should_secure_host (string host) {
673+ Directive? directive = whitelist.lookup (host);
674+ if (directive == null)
675+ directive = whitelist.lookup ("*." + host);
676+ return directive != null && directive.is_valid ();
677+ }
678+
679+ void append_to_whitelist (string host, Directive directive) {
680+ whitelist.insert (host, directive);
681+ if (directive.sub_domains)
682+ whitelist.insert ("*." + host, directive);
683+ }
684+
685+ async void append_to_cache (string host, string header) {
686+ /* FIXME: Don't write in private browsing */
687+
688+ try {
689+ var stream = yield config.append_to_async (FileCreateFlags.NONE);
690+ yield stream.write_async ((host + " " + header + "\n").data);
691+ yield stream.flush_async ();
692+ }
693+ catch (Error error) {
694+ critical ("Failed to update %s: %s", config.get_path (), error.message);
695+ }
696+ }
697+
698+ public Directive? strict_transport_security_handled (string host, Soup.MessageHeaders headers) {
699+ unowned string? hsts = headers.get_one ("Strict-Transport-Security");
700+ if (hsts == null)
701+ return null;
702+
703+ var directive = new Directive.from_header (hsts);
704+ if (directive.is_valid ()) {
705+ append_to_whitelist (host, directive);
706+ append_to_cache.begin (host, hsts);
707+ }
708+ return directive;
709+ }
710+
711+ }
712+
713+ public class WebPage : Peas.ExtensionBase, Midori.WebPageActivatable {
714+ Whitelist whitelist;
715+ bool debug = false;
716+
717+ public WebKit.WebPage web_page { owned get; set; }
718+
719+ construct {
720+ if (strcmp (Environment.get_variable ("MIDORI_DEBUG"), "hsts") == 0)
721+ debug = true;
722+ whitelist = new Whitelist ();
723+ }
724+
725+ public void document_loaded (WebKit.DOM.Document dom_document) {
726+ }
727+
728+ public bool send_request (WebKit.URIRequest request, WebKit.URIResponse? redirected_response) {
729+ Soup.MessageHeaders? headers = request.get_http_headers ();
730+ if (headers == null || !request.uri.contains ("/"))
731+ return false;
732+
733+ string host = request.uri.split ("/")[2];
734+ if (whitelist.should_secure_host (host)) {
735+ request.uri = request.uri.replace ("http://", "https://");
736+ if (debug)
737+ stdout.printf ("HSTS: Enforce %s\n", host);
738+ } else if (request.uri.has_prefix ("http://")) {
739+ var directive = whitelist.strict_transport_security_handled (host, headers);
740+ if (debug)
741+ stdout.printf ("HSTS: %s valid? %s\n",
742+ host, directive != null ? directive.is_valid ().to_string () : "/");
743+ }
744+ return false;
745+ }
746+ }
747+}
748+
749+[ModuleInit]
750+public static void peas_register_types (GLib.TypeModule module) {
751+ var object_module = (Peas.ObjectModule)module;
752+ object_module.register_extension_type (typeof (Midori.WebPageActivatable), typeof (HSTS.WebPage));
753+}
754+
755+void hsts_directive () {
756+ HSTS.Directive d;
757+ d = new HSTS.Directive.from_header ("max-age=31536000");
758+ assert (d.is_valid () && !d.sub_domains);
759+ d = new HSTS.Directive.from_header ("max-age=15768000 ; includeSubDomains");
760+ assert (d.is_valid () && d.sub_domains);
761+
762+ /* Invalid */
763+ d = new HSTS.Directive.from_header ("");
764+ assert (!d.is_valid () && !d.sub_domains);
765+ d = new HSTS.Directive.from_header ("includeSubDomains");
766+ assert (!d.is_valid () && d.sub_domains);
767+}
768+
769+public void extension_test () {
770+ Test.add_func ("/hsts/directive", hsts_directive);
771+}
772+
773
774=== removed file 'extensions/tabs-minimized.c'
775--- extensions/tabs-minimized.c 2011-11-08 00:53:53 +0000
776+++ extensions/tabs-minimized.c 1970-01-01 00:00:00 +0000
777@@ -1,87 +0,0 @@
778-/*
779- Copyright (C) 2008-2010 Christian Dywan <christian@twotoasts.de>
780-
781- This library is free software; you can redistribute it and/or
782- modify it under the terms of the GNU Lesser General Public
783- License as published by the Free Software Foundation; either
784- version 2.1 of the License, or (at your option) any later version.
785-
786- See the file COPYING for the full license text.
787-*/
788-
789-#include <midori/midori.h>
790-
791-static void
792-tabs_minimized_app_add_browser_cb (MidoriApp* app,
793- MidoriBrowser* browser,
794- MidoriExtension* extension);
795-
796-static void
797-tabs_minimized_add_tab_cb (MidoriBrowser* browser,
798- MidoriView* tab,
799- MidoriExtension* extension);
800-
801-static void
802-tabs_minimized_deactivate_cb (MidoriExtension* extension,
803- MidoriBrowser* browser)
804-{
805- MidoriApp* app = midori_extension_get_app (extension);
806-
807- g_signal_handlers_disconnect_by_func (
808- extension, tabs_minimized_deactivate_cb, browser);
809- g_signal_handlers_disconnect_by_func (
810- app, tabs_minimized_app_add_browser_cb, extension);
811- g_signal_handlers_disconnect_by_func (
812- browser, tabs_minimized_add_tab_cb, extension);
813-}
814-
815-static void
816-tabs_minimized_add_tab_cb (MidoriBrowser* browser,
817- MidoriView* tab,
818- MidoriExtension* extension)
819-{
820- g_object_set (tab, "minimized", TRUE, NULL);
821-}
822-
823-static void
824-tabs_minimized_app_add_browser_cb (MidoriApp* app,
825- MidoriBrowser* browser,
826- MidoriExtension* extension)
827-{
828- g_signal_connect (browser, "add-tab",
829- G_CALLBACK (tabs_minimized_add_tab_cb), extension);
830- g_signal_connect (extension, "deactivate",
831- G_CALLBACK (tabs_minimized_deactivate_cb), browser);
832-}
833-
834-static void
835-tabs_minimized_activate_cb (MidoriExtension* extension,
836- MidoriApp* app)
837-{
838- KatzeArray* browsers;
839- MidoriBrowser* browser;
840-
841- browsers = katze_object_get_object (app, "browsers");
842- KATZE_ARRAY_FOREACH_ITEM (browser, browsers)
843- tabs_minimized_app_add_browser_cb (app, browser, extension);
844- g_object_unref (browsers);
845- g_signal_connect (app, "add-browser",
846- G_CALLBACK (tabs_minimized_app_add_browser_cb), extension);
847-}
848-
849-MidoriExtension*
850-extension_init (void)
851-{
852- MidoriExtension* extension = g_object_new (MIDORI_TYPE_EXTENSION,
853- "name", _("Only Icons on Tabs by default"),
854- "description", _("New tabs have no label by default"),
855- "version", "0.1" MIDORI_VERSION_SUFFIX,
856- "authors", "MonkeyOfDoom <pixelmonkey@ensellitis.com>",
857- NULL);
858-
859- g_signal_connect (extension, "activate",
860- G_CALLBACK (tabs_minimized_activate_cb), NULL);
861-
862- return extension;
863-}
864-
865
866=== added file 'extensions/tabs-minimized.plugin'
867--- extensions/tabs-minimized.plugin 1970-01-01 00:00:00 +0000
868+++ extensions/tabs-minimized.plugin 2015-06-22 22:20:28 +0000
869@@ -0,0 +1,9 @@
870+[Plugin]
871+Module=tabs-minimized
872+IAge=3
873+Name=Only Icons on Tabs by default
874+Description=New tabs have no label by default
875+Version=0.1
876+Author=MonkeyOfDoom <pixelmonkey@ensellitis.com>
877+Copyright=Copyright © 2008-2010 Christian Dywan
878+Website=http://www.midori-browser.org
879
880=== added file 'extensions/tabs-minimized.vala'
881--- extensions/tabs-minimized.vala 1970-01-01 00:00:00 +0000
882+++ extensions/tabs-minimized.vala 2015-06-22 22:20:28 +0000
883@@ -0,0 +1,68 @@
884+/*
885+ Copyright (C) 2008-2010 Christian Dywan <christian@twotoasts.de>
886+
887+ This library is free software; you can redistribute it and/or
888+ modify it under the terms of the GNU Lesser General Public
889+ License as published by the Free Software Foundation; either
890+ version 2.1 of the License, or (at your option) any later version.
891+
892+ See the file COPYING for the full license text.
893+*/
894+
895+namespace Minimizer {
896+ class Manager : Midori.Extension {
897+ internal Manager () {
898+ GLib.Object (name: _("Only Icons on Tabs by default"),
899+ description: _("New tabs have no label by default"),
900+ version: "0.1" + Midori.VERSION_SUFFIX,
901+ authors: "MonkeyOfDoom <pixelmonkey@ensellitis.com>");
902+ activate.connect (activated);
903+ deactivate.connect (deactivated);
904+ }
905+
906+ void activated (Midori.App app) {
907+ foreach (var browser in app.get_browsers ())
908+ browser_added (browser);
909+ app.add_browser.connect (browser_added);
910+ }
911+
912+ void deactivated () {
913+ var app = get_app ();
914+ app.add_browser.disconnect (browser_added);
915+ foreach (var browser in app.get_browsers ())
916+ browser.add_tab.disconnect (tab_added);
917+ }
918+
919+ void browser_added (Midori.Browser browser) {
920+ browser.add_tab.connect (tab_added);
921+ foreach (var tab in browser.get_tabs ())
922+ tab_added (tab);
923+ }
924+
925+ void tab_added (Midori.Tab tab) {
926+ tab.minimized = true;
927+ }
928+ }
929+}
930+
931+public Midori.Extension extension_init () {
932+ return new Minimizer.Manager ();
933+}
934+
935+#if HAVE_PEAS
936+namespace Minimizer {
937+ public class Tab : Peas.ExtensionBase, Midori.TabActivatable {
938+ public Midori.Tab tab { owned get; set; }
939+
940+ public void created (string uri) {
941+ tab.minimized = true;
942+ }
943+ }
944+}
945+
946+[ModuleInit]
947+public static void peas_register_types (GLib.TypeModule module) {
948+ var object_module = (Peas.ObjectModule)module;
949+ object_module.register_extension_type (typeof (Midori.TabActivatable), typeof (Minimizer.Tab));
950+}
951+#endif
952
953=== added file 'extensions/web-extension.web.vala'
954--- extensions/web-extension.web.vala 1970-01-01 00:00:00 +0000
955+++ extensions/web-extension.web.vala 2015-06-22 22:20:28 +0000
956@@ -0,0 +1,68 @@
957+/*
958+ Copyright (C) 2015 Christian Dywan <christian@twotoasts.de>
959+
960+ This library is free software; you can redistribute it and/or
961+ modify it under the terms of the GNU Lesser General Public
962+ License as published by the Free Software Foundation; either
963+ version 2.1 of the License, or (at your option) any later version.
964+
965+ See the file COPYING for the full license text.
966+*/
967+
968+namespace WebExtension {
969+ public class Extension : Object {
970+ bool debug = false;
971+ Peas.Engine engine;
972+
973+ public Extension (WebKit.WebExtension web_extension, GLib.Variant user_data) {
974+ debug = (strcmp (Environment.get_variable ("MIDORI_DEBUG"), "paths") == 0);
975+ if (debug)
976+ stdout.printf ("WebKit.WebExtension: %s\n", user_data.print (true));
977+ var config = (GLib.HashTable<string, string>)user_data;
978+ var keyfile = new GLib.KeyFile ();
979+ try {
980+ keyfile.load_from_file (config["config_dir"] + "/config", GLib.KeyFileFlags.NONE);
981+ string plugins = keyfile.get_string ("settings", "plugins");
982+
983+ engine = Peas.Engine.get_default ();
984+ engine.enable_loader ("python");
985+ foreach (unowned string path in config["plugin_dirs"].split (","))
986+ engine.add_search_path (path, null);
987+ engine.loaded_plugins = plugins.split (",");
988+
989+ web_extension.page_created.connect (page_created);
990+ } catch (GLib.Error error) {
991+ // Missing config file or plugins key is no error
992+ }
993+ }
994+
995+ void page_created (WebKit.WebPage web_page) {
996+ var extensions = new Peas.ExtensionSet (null,
997+ typeof (Midori.WebPageActivatable), "web-page", web_page);
998+ web_page.set_data<Peas.ExtensionSet> ("extensions", extensions);
999+ web_page.send_request.connect (send_request);
1000+ }
1001+
1002+ public void document_loaded (WebKit.WebPage web_page) {
1003+ var extensions = web_page.get_data<Peas.ExtensionSet> ("extensions");
1004+ extensions.foreach ((@set, info, extension) => {
1005+ ((Midori.WebPageActivatable)extension).document_loaded (web_page.get_dom_document ());
1006+ });
1007+ }
1008+
1009+ bool send_request (WebKit.WebPage web_page, WebKit.URIRequest request, WebKit.URIResponse? redirected_response) {
1010+ bool block = false;
1011+ var extensions = web_page.get_data<Peas.ExtensionSet> ("extensions");
1012+ extensions.foreach ((@set, info, extension) => {
1013+ if (((Midori.WebPageActivatable)extension).send_request (request, redirected_response))
1014+ block = true;
1015+ });
1016+ return block;
1017+ }
1018+ }
1019+}
1020+
1021+WebExtension.Extension? web_extension;
1022+public void webkit_web_extension_initialize_with_user_data (WebKit.WebExtension extension, GLib.Variant user_data) {
1023+ web_extension = new WebExtension.Extension (extension, user_data);
1024+}
1025
1026=== added directory 'ipc'
1027=== added file 'ipc/CMakeLists.txt'
1028--- ipc/CMakeLists.txt 1970-01-01 00:00:00 +0000
1029+++ ipc/CMakeLists.txt 2015-06-22 22:20:28 +0000
1030@@ -0,0 +1,50 @@
1031+include(ValaPrecompile)
1032+
1033+set(LIBMIDORI2_VERSION 0.6.0)
1034+set(LIBMIDORI2_SOVERSION 0)
1035+file(GLOB LIBMIDORI2_SOURCE *.vala)
1036+
1037+vala_precompile(LIBMIDORI2_SOURCE_C ${LIBMIDORI2}
1038+ ${LIBMIDORI2_SOURCE}
1039+PACKAGES
1040+ ${PKGS}
1041+CUSTOM_VAPIS
1042+ "${CMAKE_SOURCE_DIR}/midori/webkit2gtk-web-extension-4.0.vapi"
1043+OPTIONS
1044+ ${VALAFLAGS}
1045+GENERATE_VAPI
1046+ "${LIBMIDORI2}"
1047+GENERATE_HEADER
1048+ "${LIBMIDORI2}"
1049+)
1050+
1051+add_library("${LIBMIDORI2}" SHARED ${LIBMIDORI2_SOURCE_C})
1052+target_link_libraries("${LIBMIDORI2}"
1053+ ${DEPS_LIBRARIES}
1054+ ${PEAS_LIBRARIES}
1055+ )
1056+set_target_properties("${LIBMIDORI2}" PROPERTIES
1057+ COMPILE_FLAGS "${VALA_CFLAGS}"
1058+ POSITION_INDEPENDENT_CODE ON
1059+ VERSION ${LIBMIDORI2_VERSION}
1060+ SOVERSION ${LIBMIDORI2_SOVERSION}
1061+ )
1062+
1063+include_directories(
1064+ ${CMAKE_SOURCE_DIR}
1065+ ${CMAKE_CURRENT_SOURCE_DIR}
1066+ ${CMAKE_BINARY_DIR}
1067+ ${DEPS_INCLUDE_DIRS}
1068+ ${OPTS_INCLUDE_DIRS}
1069+ ${DEPS_GTK_INCLUDE_DIRS}
1070+ )
1071+if (WIN32)
1072+ install(TARGETS ${LIBMIDORI2}
1073+ LIBRARY DESTINATION ${CMAKE_INSTALL_BINDIR}
1074+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
1075+ )
1076+else ()
1077+ install(TARGETS ${LIBMIDORI2}
1078+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
1079+ )
1080+endif ()
1081
1082=== added file 'ipc/ipc-tab.vala'
1083--- ipc/ipc-tab.vala 1970-01-01 00:00:00 +0000
1084+++ ipc/ipc-tab.vala 2015-06-22 22:20:28 +0000
1085@@ -0,0 +1,19 @@
1086+/*
1087+ Copyright (C) 2015 Christian Dywan <christian@twotoasts.de>
1088+
1089+ This library is free software; you can redistribute it and/or
1090+ modify it under the terms of the GNU Lesser General Public
1091+ License as published by the Free Software Foundation; either
1092+ version 2.1 of the License, or (at your option) any later version.
1093+
1094+ See the file COPYING for the full license text.
1095+*/
1096+
1097+namespace Midori {
1098+ public interface WebPageActivatable : GLib.Object {
1099+ public abstract WebKit.WebPage web_page { owned get; set; }
1100+
1101+ public abstract void document_loaded (WebKit.DOM.Document dom_document);
1102+ public abstract bool send_request (WebKit.URIRequest request, WebKit.URIResponse? redirected_response);
1103+ }
1104+}
1105
1106=== modified file 'katze/katze.vapi'
1107--- katze/katze.vapi 2014-02-22 14:06:19 +0000
1108+++ katze/katze.vapi 2015-06-22 22:20:28 +0000
1109@@ -21,6 +21,7 @@
1110 public uint get_length ();
1111 public GLib.List<unowned Item> get_items ();
1112 public bool is_empty ();
1113+ public void update ();
1114 }
1115
1116 [CCode (cheader_filename = "katze/katze.h")]
1117
1118=== modified file 'katze/midori-paths.vala'
1119--- katze/midori-paths.vala 2015-06-11 22:33:48 +0000
1120+++ katze/midori-paths.vala 2015-06-22 22:20:28 +0000
1121@@ -99,6 +99,7 @@
1122
1123 public static void init (RuntimeMode new_mode, string? config) {
1124 assert (mode == RuntimeMode.UNDEFINED);
1125+ assert (exec_path != null);
1126 assert (new_mode != RuntimeMode.UNDEFINED);
1127 mode = new_mode;
1128 if (mode == RuntimeMode.PORTABLE || mode == RuntimeMode.PRIVATE)
1129@@ -147,17 +148,48 @@
1130 user_data_dir = Environment.get_user_data_dir ();
1131 tmp_dir = get_runtime_dir ();
1132 }
1133+
1134+#if HAVE_PEAS
1135+ var paths = new GLib.StringBuilder ();
1136+ paths.append (Path.build_filename (user_data_dir, PACKAGE_NAME, "plugins"));
1137+ paths.append_c (',');
1138+ paths.append (Path.build_filename (get_lib_path (PACKAGE_NAME)));
1139+ string plugin_dirs = paths.str;
1140+
1141+ var engine = Peas.Engine.get_default ();
1142+ engine.ref ();
1143+ engine.load_plugin.connect ((info) => {
1144+ if (strcmp (Environment.get_variable ("MIDORI_DEBUG"), "paths") == 0)
1145+ stdout.printf ("Plugin %s loaded (%s)\n", info.get_name (), info.get_module_name ());
1146+ });
1147+ engine.enable_loader ("python");
1148+ foreach (unowned string path in plugin_dirs.split (","))
1149+ engine.add_search_path (path, null);
1150+ if (strcmp (Environment.get_variable ("MIDORI_DEBUG"), "paths") == 0) {
1151+ stdout.printf ("plugins: %s\n", plugin_dirs);
1152+ foreach (unowned Peas.PluginInfo info in engine.get_plugin_list ())
1153+ stdout.printf ("Plugin %s (%s)\n", info.get_name (), info.get_module_name ());
1154+ }
1155+#endif
1156+
1157 #if HAVE_WEBKIT2
1158+ var context = WebKit.WebContext.get_default ();
1159+#if HAVE_PEAS
1160+ context.set_web_extensions_directory (get_lib_path (PACKAGE_NAME));
1161+ context.initialize_web_extensions.connect (() => {
1162+ var user_data = new GLib.HashTable<string, string> (str_hash, str_equal);
1163+ user_data.insert ("config_dir", config_dir);
1164+ user_data.insert ("plugin_dirs", plugin_dirs);
1165+ context.set_web_extensions_initialization_user_data (user_data);
1166+ });
1167+#endif
1168 if (cache_dir != null) {
1169- /* Cache and extension dir MUST be set no later than here to work */
1170- WebKit.WebContext.get_default ().set_web_extensions_directory (
1171- Path.build_path (Path.DIR_SEPARATOR_S, cache_dir, "wk2ext"));
1172- WebKit.WebContext.get_default ().set_disk_cache_directory (
1173+ context.set_disk_cache_directory (
1174 Path.build_path (Path.DIR_SEPARATOR_S, cache_dir, "web"));
1175 }
1176
1177 if (config_dir != null) {
1178- var cookie_manager = WebKit.WebContext.get_default ().get_cookie_manager ();
1179+ var cookie_manager = context.get_cookie_manager ();
1180 cookie_manager.set_persistent_storage (Path.build_filename (config_dir, "cookies.db"),
1181 WebKit.CookiePersistentStorage.SQLITE);
1182 }
1183@@ -165,7 +197,7 @@
1184 if (user_data_dir != null) {
1185 string folder = Path.build_filename (user_data_dir, "webkit", "icondatabase");
1186 #if HAVE_WEBKIT2
1187- WebKit.WebContext.get_default ().set_favicon_database_directory (folder);
1188+ context.set_favicon_database_directory (folder);
1189 #else
1190 WebKit.get_favicon_database ().set_path (folder);
1191 #endif
1192
1193=== modified file 'midori/main.c'
1194--- midori/main.c 2014-04-23 03:34:23 +0000
1195+++ midori/main.c 2015-06-22 22:20:28 +0000
1196@@ -62,6 +62,7 @@
1197 gchar* config;
1198 gboolean private;
1199 gboolean portable;
1200+ gchar* test;
1201 gboolean plain;
1202 gboolean diagnostic_dialog = FALSE;
1203 gboolean debug = FALSE;
1204@@ -85,6 +86,8 @@
1205 { "portable", 'P', 0, G_OPTION_ARG_NONE, &portable,
1206 N_("Portable mode, all runtime files are stored in one place"), NULL },
1207 #endif
1208+ { "test", 't', 0, G_OPTION_ARG_STRING, &test,
1209+ N_("Run unit tests for the specified extension"), NULL },
1210 { "plain", '\0', 0, G_OPTION_ARG_NONE, &plain,
1211 N_("Plain GTK+ window with WebKit, akin to GtkLauncher"), NULL },
1212 { "diagnostic-dialog", 'd', 0, G_OPTION_ARG_NONE, &diagnostic_dialog,
1213@@ -118,6 +121,7 @@
1214 config = NULL;
1215 private = FALSE;
1216 portable = FALSE;
1217+ test = NULL;
1218 plain = FALSE;
1219 run = FALSE;
1220 snapshot = NULL;
1221@@ -287,6 +291,52 @@
1222 return 0;
1223 }
1224
1225+ if (test != NULL)
1226+ {
1227+ g_assert (g_module_supported ());
1228+
1229+ GModule* module = g_module_open (test, G_MODULE_BIND_LOCAL);
1230+ if (module == NULL)
1231+ g_error (_("Failed to load %s."), test);
1232+
1233+ midori_test_init (&argc, &argv);
1234+
1235+ typedef void (*extension_test_func)(void);
1236+ extension_test_func extension_test;
1237+ /* Midori.Extension */
1238+ typedef GObject* (*extension_init_func)(void);
1239+ extension_init_func extension_init;
1240+ /* WebKit.WebExtension */
1241+ typedef void (*webkit_web_extension_initialize_func)(GObject* extension);
1242+ webkit_web_extension_initialize_func web_extension_init;
1243+
1244+ if (g_module_symbol (module, "extension_init",
1245+ (gpointer) &extension_init))
1246+ {
1247+ /* It's fine to conditionally return no extension */
1248+ if (!(extension_init ()))
1249+ return 0;
1250+ midori_paths_init (MIDORI_RUNTIME_MODE_NORMAL, NULL);
1251+
1252+ /* Not all extensions have unit tests :-( */
1253+ if (!g_module_symbol (module, "extension_test", (gpointer) &extension_test))
1254+ return 0;
1255+ }
1256+ else if (g_module_symbol (module, "webkit_web_extension_initialize",
1257+ (gpointer) &web_extension_init)
1258+ || g_module_symbol (module, "webkit_web_extension_initialize_with_user_data",
1259+ (gpointer) &web_extension_init))
1260+ {
1261+ if (!g_module_symbol (module, "extension_test", (gpointer) &extension_test))
1262+ g_error (_("%s doesn't provide unit tests."), test);
1263+ }
1264+ else
1265+ g_error (_("%s doesn't look like a Midori extension."), test);
1266+
1267+ extension_test ();
1268+ return g_test_run ();
1269+ }
1270+
1271 if (plain)
1272 {
1273 GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1274
1275=== modified file 'midori/midori-app.c'
1276--- midori/midori-app.c 2015-04-14 19:13:57 +0000
1277+++ midori/midori-app.c 2015-06-22 22:20:28 +0000
1278@@ -1183,7 +1183,7 @@
1279
1280 { STOCK_BOOKMARKS, N_("_Bookmarks"), GDK_CONTROL_MASK | GDK_SHIFT_MASK, GDK_KEY_B },
1281 { STOCK_BOOKMARK_ADD, N_("Add Boo_kmark") },
1282- { STOCK_EXTENSION, N_("_Extensions") },
1283+ { MIDORI_STOCK_EXTENSION, N_("_Extensions") },
1284 { STOCK_HISTORY, N_("_History"), GDK_CONTROL_MASK | GDK_SHIFT_MASK, GDK_KEY_H },
1285 { STOCK_SCRIPT, N_("_Userscripts") },
1286 { STOCK_STYLE, N_("User_styles") },
1287
1288=== modified file 'midori/midori-extension.c'
1289--- midori/midori-extension.c 2014-04-05 19:15:34 +0000
1290+++ midori/midori-extension.c 2015-06-22 22:20:28 +0000
1291@@ -562,6 +562,7 @@
1292 g_assert (midori_extension_activate_gracefully (app, extension_path, "libtabby." G_MODULE_SUFFIX, activate));
1293 g_assert (midori_extension_activate_gracefully (app, extension_path, "libopen-with." G_MODULE_SUFFIX, activate));
1294 g_assert (midori_extension_activate_gracefully (app, extension_path, "libflummi." G_MODULE_SUFFIX, activate));
1295+ g_assert (midori_extension_activate_gracefully (app, extension_path, "libextension-manager." G_MODULE_SUFFIX, activate));
1296
1297 gint i = 0;
1298 const gchar* filename;
1299@@ -623,6 +624,17 @@
1300 if ((extension = g_hash_table_lookup (modules, module)))
1301 return extension;
1302
1303+ if (module && g_module_symbol (module, "peas_register_types", (gpointer) &extension_init))
1304+ {
1305+ /* Peas plugin: not handled here */
1306+ return NULL;
1307+ }
1308+ if (module && g_module_symbol (module, "webkit_web_extension_initialize_with_user_data", (gpointer) &extension_init))
1309+ {
1310+ /* WebKit2 web extension: not handled here */
1311+ return NULL;
1312+ }
1313+
1314 if (module && g_module_symbol (module, "extension_init",
1315 (gpointer) &extension_init))
1316 {
1317@@ -684,6 +696,7 @@
1318 && strcmp (filename, "libabout." G_MODULE_SUFFIX)
1319 && strcmp (filename, "libtabby." G_MODULE_SUFFIX)
1320 && strcmp (filename, "libopen-with." G_MODULE_SUFFIX)
1321+ && strcmp (filename, "libextension-manager." G_MODULE_SUFFIX)
1322 && strcmp (filename, "libflummi." G_MODULE_SUFFIX))
1323 katze_array_add_item (extensions, extension);
1324
1325
1326=== modified file 'midori/midori-frontend.c'
1327--- midori/midori-frontend.c 2015-06-12 20:43:52 +0000
1328+++ midori/midori-frontend.c 2015-06-22 22:20:28 +0000
1329@@ -261,14 +261,6 @@
1330 }
1331
1332 static void
1333-midori_browser_show_preferences_cb (MidoriBrowser* browser,
1334- KatzePreferences* preferences,
1335- MidoriApp* app)
1336-{
1337- midori_preferences_add_extension_category (preferences, app);
1338-}
1339-
1340-static void
1341 midori_app_add_browser_cb (MidoriApp* app,
1342 MidoriBrowser* browser,
1343 gpointer user_data)
1344@@ -287,8 +279,6 @@
1345 /* Extensions */
1346 g_signal_connect (browser, "show-preferences",
1347 G_CALLBACK (midori_browser_privacy_preferences_cb), NULL);
1348- g_signal_connect (browser, "show-preferences",
1349- G_CALLBACK (midori_browser_show_preferences_cb), app);
1350
1351 g_object_unref (panel);
1352 }
1353
1354=== modified file 'midori/midori-preferences.c'
1355--- midori/midori-preferences.c 2015-06-06 13:03:43 +0000
1356+++ midori/midori-preferences.c 2015-06-22 22:20:28 +0000
1357@@ -14,7 +14,6 @@
1358 #include "midori-app.h"
1359 #include "midori-core.h"
1360 #include "midori-extension.h"
1361-#include "panels/midori-extensions.h"
1362 #include "midori-platform.h"
1363
1364 #include <string.h>
1365@@ -603,35 +602,6 @@
1366 midori_preferences_add_extension_category (KatzePreferences* preferences,
1367 MidoriApp* app)
1368 {
1369- KatzeArray* array;
1370- GtkWidget* scrolled;
1371- GtkWidget* addon;
1372- GList* children;
1373- GtkWidget* page;
1374-
1375- array = katze_object_get_object (app, "extensions");
1376-
1377- midori_extension_load_from_folder (app, NULL, FALSE);
1378- /* Reset frozen list: allow active extensions to be saved */
1379- g_object_set_data (G_OBJECT (app), "extensions", NULL);
1380-
1381- /* Hide if there are no extensions at all */
1382- if (!katze_array_get_nth_item (array, 0))
1383- {
1384- g_object_unref (array);
1385- return;
1386- }
1387- g_object_unref (array);
1388-
1389- scrolled = gtk_scrolled_window_new (NULL, NULL);
1390- /* For lack of a better way of keeping descriptions visible */
1391- g_object_set (scrolled, "visible", TRUE, "hscrollbar-policy", GTK_POLICY_NEVER, NULL);
1392- addon = g_object_new (MIDORI_TYPE_EXTENSIONS, "app", app, NULL);
1393- children = gtk_container_get_children (GTK_CONTAINER (addon));
1394- gtk_widget_reparent (g_list_nth_data (children, 0), scrolled);
1395- g_list_free (children);
1396- page = katze_preferences_add_category (preferences,
1397- _("Extensions"), STOCK_EXTENSION);
1398- gtk_box_pack_start (GTK_BOX (page), scrolled, TRUE, TRUE, 4);
1399+ /* Superseded by extension-manager */
1400 }
1401
1402
1403=== modified file 'midori/midori-settings.vala'
1404--- midori/midori-settings.vala 2013-11-24 21:50:38 +0000
1405+++ midori/midori-settings.vala 2015-06-22 22:20:28 +0000
1406@@ -65,6 +65,28 @@
1407 /* Since: 0.4.8 */
1408 public uint inactivity_reset { get; set; default = 0; }
1409
1410+#if HAVE_PEAS
1411+ /* Since: 0.6.0 */
1412+ public string plugins { get; set; }
1413+
1414+ construct {
1415+ var engine = Peas.Engine.get_default ();
1416+ notify["plugins"].connect (() => {
1417+ if (strcmp (Environment.get_variable ("MIDORI_DEBUG"), "paths") == 0)
1418+ stdout.printf ("Plugins: %s\n", plugins);
1419+ engine.loaded_plugins = plugins.split (",");
1420+ });
1421+ engine.notify["loaded-plugins"].connect (() => {
1422+ string plugins_ = string.joinv (",", engine.loaded_plugins);
1423+ if (plugins == plugins_)
1424+ return;
1425+ if (strcmp (Environment.get_variable ("MIDORI_DEBUG"), "paths") == 0)
1426+ stdout.printf ("Plugins: %s\n", plugins_);
1427+ plugins = plugins_;
1428+ });
1429+ }
1430+#endif
1431+
1432 string? default_theme_name_ = null;
1433 /* Since: 0.5.5 */
1434 public string? default_theme_name { get {
1435
1436=== modified file 'midori/midori-stock.h'
1437--- midori/midori-stock.h 2013-04-22 23:01:10 +0000
1438+++ midori/midori-stock.h 2015-06-22 22:20:28 +0000
1439@@ -15,7 +15,7 @@
1440 /* Stock items */
1441
1442 #define STOCK_BOOKMARKS "user-bookmarks"
1443-#define STOCK_EXTENSION "extension"
1444+#define MIDORI_STOCK_EXTENSION "extension"
1445 #define STOCK_HISTORY "document-open-recent"
1446 #define MIDORI_STOCK_WEB_BROWSER "web-browser"
1447 #define STOCK_NEWS_FEED "internet-news-reader"
1448
1449=== modified file 'midori/midori-tab.vala'
1450--- midori/midori-tab.vala 2015-04-19 14:06:12 +0000
1451+++ midori/midori-tab.vala 2015-06-22 22:20:28 +0000
1452@@ -42,6 +42,12 @@
1453 NETWORK
1454 }
1455
1456+ public interface TabActivatable : GLib.Object {
1457+ public abstract Midori.Tab tab { owned get; set; }
1458+
1459+ public abstract void created (string uri);
1460+ }
1461+
1462 public class Tab : Gtk.VBox {
1463 public Tab related { get; set construct; }
1464 public WebKit.WebView web_view { get; private set; }
1465@@ -141,6 +147,18 @@
1466 #endif
1467 /* Load something to avoid a bug where WebKit might not set a main frame */
1468 web_view.load_uri ("");
1469+
1470+#if HAVE_PEAS
1471+ var extensions = new Peas.ExtensionSet (null,
1472+ typeof (TabActivatable), "tab", this);
1473+ extensions.extension_added.connect ((info, extension) => {
1474+ ((TabActivatable)extension).created (uri);
1475+ });
1476+ extensions.foreach ((@set, info, extension) => {
1477+ ((TabActivatable)extension).created (uri);
1478+ });
1479+ set_data<Peas.ExtensionSet> ("extensions", extensions);
1480+#endif
1481 }
1482
1483 public void inject_stylesheet (string stylesheet) {
1484
1485=== modified file 'midori/midori.vapi'
1486--- midori/midori.vapi 2015-05-24 00:19:21 +0000
1487+++ midori/midori.vapi 2015-06-22 22:20:28 +0000
1488@@ -8,6 +8,7 @@
1489 public const string VERSION_SUFFIX;
1490 [CCode (cheader_filename = "midori/midori-stock.h")]
1491 namespace Stock {
1492+ public const string EXTENSION;
1493 public const string WEB_BROWSER;
1494 public const string TRANSFER;
1495 public const string PLUGINS;
1496@@ -131,7 +132,7 @@
1497 [CCode (cheader_filename = "midori/midori-extension.h")]
1498 public class Extension : GLib.Object {
1499 [CCode (has_construct_function = false)]
1500- public Extension ();
1501+ protected Extension ();
1502 public unowned Midori.App get_app ();
1503
1504 public void install_boolean (string name, bool default_value);
1505@@ -168,6 +169,7 @@
1506 public signal void activate (Midori.App app);
1507 public bool is_prepared ();
1508 public bool is_active ();
1509+ public bool has_preferences ();
1510 public signal void deactivate ();
1511 public signal void open_preferences ();
1512
1513
1514=== modified file 'midori/webkit2gtk-web-extension-4.0.vapi'
1515--- midori/webkit2gtk-web-extension-4.0.vapi 2015-04-19 14:06:12 +0000
1516+++ midori/webkit2gtk-web-extension-4.0.vapi 2015-06-22 22:20:28 +0000
1517@@ -2686,7 +2686,7 @@
1518 public class URIRequest : GLib.Object {
1519 [CCode (has_construct_function = false)]
1520 public URIRequest (string uri);
1521- public Soup.MessageHeaders get_http_headers ();
1522+ public unowned Soup.MessageHeaders get_http_headers ();
1523 public unowned string get_uri ();
1524 public void set_uri (string uri);
1525 public string uri { get; set construct; }
1526
1527=== removed file 'panels/midori-extensions.c'
1528--- panels/midori-extensions.c 2013-06-21 23:18:01 +0000
1529+++ panels/midori-extensions.c 1970-01-01 00:00:00 +0000
1530@@ -1,544 +0,0 @@
1531-/*
1532- Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
1533-
1534- This library is free software; you can redistribute it and/or
1535- modify it under the terms of the GNU Lesser General Public
1536- License as published by the Free Software Foundation; either
1537- version 2.1 of the License, or (at your option) any later version.
1538-
1539- See the file COPYING for the full license text.
1540-*/
1541-
1542-#include "midori-extensions.h"
1543-
1544-#include "midori-app.h"
1545-#include "midori-extension.h"
1546-#include "midori-platform.h"
1547-#include "midori-core.h"
1548-
1549-#include <glib/gi18n.h>
1550-
1551-struct _MidoriExtensions
1552-{
1553- GtkVBox parent_instance;
1554-
1555- GtkWidget* toolbar;
1556- GtkWidget* treeview;
1557- MidoriApp* app;
1558-};
1559-
1560-struct _MidoriExtensionsClass
1561-{
1562- GtkVBoxClass parent_class;
1563-};
1564-
1565-static void
1566-midori_extensions_viewable_iface_init (MidoriViewableIface* iface);
1567-
1568-G_DEFINE_TYPE_WITH_CODE (MidoriExtensions, midori_extensions, GTK_TYPE_VBOX,
1569- G_IMPLEMENT_INTERFACE (MIDORI_TYPE_VIEWABLE,
1570- midori_extensions_viewable_iface_init));
1571-
1572-enum
1573-{
1574- PROP_0,
1575-
1576- PROP_APP
1577-};
1578-
1579-static void
1580-midori_extensions_set_property (GObject* object,
1581- guint prop_id,
1582- const GValue* value,
1583- GParamSpec* pspec);
1584-
1585-static void
1586-midori_extensions_get_property (GObject* object,
1587- guint prop_id,
1588- GValue* value,
1589- GParamSpec* pspec);
1590-
1591-static void
1592-midori_extensions_finalize (GObject* object);
1593-
1594-static void
1595-midori_extensions_class_init (MidoriExtensionsClass* class)
1596-{
1597- GObjectClass* gobject_class;
1598- GParamFlags flags;
1599-
1600- gobject_class = G_OBJECT_CLASS (class);
1601- gobject_class->set_property = midori_extensions_set_property;
1602- gobject_class->get_property = midori_extensions_get_property;
1603- gobject_class->finalize = midori_extensions_finalize;
1604-
1605- flags = G_PARAM_READWRITE;
1606-
1607- g_object_class_install_property (gobject_class,
1608- PROP_APP,
1609- g_param_spec_object (
1610- "app",
1611- "App",
1612- "The app",
1613- MIDORI_TYPE_APP,
1614- flags));
1615-}
1616-
1617-static const gchar*
1618-midori_extensions_get_label (MidoriViewable* viewable)
1619-{
1620- return _("Extensions");
1621-}
1622-
1623-static const gchar*
1624-midori_extensions_get_stock_id (MidoriViewable* viewable)
1625-{
1626- return STOCK_EXTENSION;
1627-}
1628-
1629-static GtkWidget*
1630-midori_extensions_get_toolbar (MidoriViewable* extensions)
1631-{
1632- if (!MIDORI_EXTENSIONS (extensions)->toolbar)
1633- {
1634- GtkWidget* toolbar;
1635-
1636- toolbar = gtk_toolbar_new ();
1637- MIDORI_EXTENSIONS (extensions)->toolbar = toolbar;
1638- }
1639-
1640- return MIDORI_EXTENSIONS (extensions)->toolbar;
1641-}
1642-
1643-static void
1644-midori_extensions_viewable_iface_init (MidoriViewableIface* iface)
1645-{
1646- iface->get_stock_id = midori_extensions_get_stock_id;
1647- iface->get_label = midori_extensions_get_label;
1648- iface->get_toolbar = midori_extensions_get_toolbar;
1649-}
1650-
1651-static void
1652-midori_extensions_extension_activate_cb (MidoriExtension* extension,
1653- MidoriApp* app,
1654- MidoriExtensions* extensions)
1655-{
1656- gtk_widget_queue_draw (GTK_WIDGET (extensions->treeview));
1657-}
1658-
1659-static void
1660-midori_extensions_extension_deactivate_cb (MidoriExtension* extension,
1661- MidoriExtensions* extensions)
1662-{
1663- gtk_widget_queue_draw (GTK_WIDGET (extensions->treeview));
1664-}
1665-
1666-static void
1667-midori_extensions_add_item_cb (KatzeArray* array,
1668- MidoriExtension* extension,
1669- MidoriExtensions* extensions)
1670-{
1671- GtkTreeIter iter;
1672- GtkTreeModel* model;
1673-
1674- model = gtk_tree_view_get_model (GTK_TREE_VIEW (extensions->treeview));
1675- gtk_list_store_append (GTK_LIST_STORE (model), &iter);
1676- gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, extension, -1);
1677- g_signal_connect (extension, "activate",
1678- G_CALLBACK (midori_extensions_extension_activate_cb), extensions);
1679- g_signal_connect (extension, "deactivate",
1680- G_CALLBACK (midori_extensions_extension_deactivate_cb), extensions);
1681-}
1682-
1683-static void
1684-midori_extensions_set_property (GObject* object,
1685- guint prop_id,
1686- const GValue* value,
1687- GParamSpec* pspec)
1688-{
1689- MidoriExtensions* extensions = MIDORI_EXTENSIONS (object);
1690-
1691- switch (prop_id)
1692- {
1693- case PROP_APP:
1694- {
1695- KatzeArray* array;
1696- MidoriExtension* extension;
1697-
1698- /* FIXME: Handle NULL and subsequent assignments */
1699- extensions->app = g_value_get_object (value);
1700- array = katze_object_get_object (extensions->app, "extensions");
1701- g_signal_connect (array, "add-item",
1702- G_CALLBACK (midori_extensions_add_item_cb), extensions);
1703-
1704- KATZE_ARRAY_FOREACH_ITEM (extension, array)
1705- midori_extensions_add_item_cb (array, extension, extensions);
1706- g_object_unref (array);
1707- }
1708- break;
1709- default:
1710- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1711- break;
1712- }
1713-}
1714-
1715-static void
1716-midori_extensions_get_property (GObject* object,
1717- guint prop_id,
1718- GValue* value,
1719- GParamSpec* pspec)
1720-{
1721- MidoriExtensions* extensions = MIDORI_EXTENSIONS (object);
1722-
1723- switch (prop_id)
1724- {
1725- case PROP_APP:
1726- g_value_set_object (value, extensions->app);
1727- break;
1728- default:
1729- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1730- break;
1731- }
1732-}
1733-
1734-static void
1735-midori_extensions_treeview_render_tick_cb (GtkTreeViewColumn* column,
1736- GtkCellRenderer* renderer,
1737- GtkTreeModel* model,
1738- GtkTreeIter* iter,
1739- GtkWidget* treeview)
1740-{
1741- MidoriExtension* extension;
1742-
1743- gtk_tree_model_get (model, iter, 0, &extension, -1);
1744-
1745- g_object_set (renderer,
1746- "activatable", midori_extension_is_prepared (extension),
1747- "active", midori_extension_is_active (extension) || g_object_get_data (G_OBJECT (extension), "static"),
1748- "xpad", 4,
1749- NULL);
1750-
1751- g_object_unref (extension);
1752-}
1753-
1754-static void
1755-midori_extensions_treeview_render_icon_cb (GtkTreeViewColumn* column,
1756- GtkCellRenderer* renderer,
1757- GtkTreeModel* model,
1758- GtkTreeIter* iter,
1759- GtkWidget* treeview)
1760-{
1761- MidoriExtension* extension;
1762- gchar* stock_id;
1763- gtk_tree_model_get (model, iter, 0, &extension, -1);
1764-
1765- stock_id = katze_object_get_object (extension, "stock-id");
1766- g_object_set (renderer, "stock-id", stock_id ? stock_id : STOCK_EXTENSION,
1767- "stock-size", GTK_ICON_SIZE_BUTTON,
1768- "sensitive", midori_extension_is_prepared (extension),
1769- "xpad", 4, NULL);
1770- g_free (stock_id);
1771- g_object_unref (extension);
1772-}
1773-
1774-static void
1775-midori_extensions_treeview_render_preferences_cb (GtkTreeViewColumn* column,
1776- GtkCellRenderer* renderer,
1777- GtkTreeModel* model,
1778- GtkTreeIter* iter,
1779- GtkWidget* treeview)
1780-{
1781- MidoriExtension* extension;
1782- gtk_tree_model_get (model, iter, 0, &extension, -1);
1783-
1784- g_object_set (renderer, "stock-id", GTK_STOCK_PREFERENCES,
1785- "stock-size", GTK_ICON_SIZE_BUTTON,
1786- "visible", midori_extension_has_preferences (extension),
1787- "sensitive", midori_extension_is_active (extension),
1788- "xpad", 4, NULL);
1789- g_object_unref (extension);
1790-}
1791-
1792-static void
1793-midori_extensions_treeview_render_text_cb (GtkTreeViewColumn* column,
1794- GtkCellRenderer* renderer,
1795- GtkTreeModel* model,
1796- GtkTreeIter* iter,
1797- GtkWidget* treeview)
1798-{
1799- MidoriExtension* extension;
1800- gchar* name;
1801- gchar* version;
1802- gchar* desc;
1803- gchar* text;
1804-
1805- gtk_tree_model_get (model, iter, 0, &extension, -1);
1806-
1807- name = katze_object_get_string (extension, "name");
1808- version = katze_object_get_string (extension, "version");
1809- desc = katze_object_get_string (extension, "description");
1810- if (katze_object_get_boolean (extension, "use-markup"))
1811- text = g_strdup_printf ("<b>%s</b> %s\n%s",
1812- name, version && *version ? version : "", desc);
1813- else
1814- text = g_markup_printf_escaped ("<b>%s</b> %s\n%s",
1815- name, version && *version ? version : "", desc);
1816- g_free (name);
1817- g_free (version);
1818- g_free (desc);
1819-
1820- g_object_set (renderer,
1821- "markup", text,
1822- "ellipsize", PANGO_ELLIPSIZE_END,
1823- "sensitive", midori_extension_is_prepared (extension),
1824- NULL);
1825-
1826- g_free (text);
1827- g_object_unref (extension);
1828-}
1829-
1830-static void
1831-midori_extensions_treeview_row_activated_cb (GtkTreeView* treeview,
1832- GtkTreePath* path,
1833- GtkTreeViewColumn* column,
1834- MidoriExtensions* extensions)
1835-{
1836- GtkTreeModel* model;
1837- GtkTreeIter iter;
1838-
1839- model = gtk_tree_view_get_model (treeview);
1840- if (gtk_tree_model_get_iter (model, &iter, path))
1841- {
1842- MidoriExtension* extension;
1843- KatzeArray* array = katze_object_get_object (extensions->app, "extensions");
1844-
1845- gtk_tree_model_get (model, &iter, 0, &extension, -1);
1846- if (midori_extension_is_active (extension))
1847- midori_extension_deactivate (extension);
1848- else if (midori_extension_is_prepared (extension))
1849- g_signal_emit_by_name (extension, "activate", extensions->app);
1850- /* Make it easy for listeners to see that extensions changed */
1851- katze_array_update (array);
1852-
1853- g_object_unref (array);
1854- g_object_unref (extension);
1855- }
1856-}
1857-
1858-static void
1859-midori_extensions_cell_renderer_toggled_cb (GtkCellRendererToggle* renderer,
1860- const gchar* path,
1861- MidoriExtensions* extensions)
1862-{
1863- GtkTreeModel* model;
1864- GtkTreeIter iter;
1865-
1866- model = gtk_tree_view_get_model (GTK_TREE_VIEW (extensions->treeview));
1867- if (gtk_tree_model_get_iter_from_string (model, &iter, path))
1868- {
1869- MidoriExtension* extension;
1870- KatzeArray* array = katze_object_get_object (extensions->app, "extensions");
1871-
1872- gtk_tree_model_get (model, &iter, 0, &extension, -1);
1873- if (midori_extension_is_active (extension))
1874- midori_extension_deactivate (extension);
1875- else if (midori_extension_is_prepared (extension))
1876- g_signal_emit_by_name (extension, "activate", extensions->app);
1877- /* Make it easy for listeners to see that extensions changed */
1878- katze_array_update (array);
1879-
1880- g_object_unref (array);
1881- g_object_unref (extension);
1882- }
1883-}
1884-
1885-static gint
1886-midori_extensions_tree_sort_func (GtkTreeModel* model,
1887- GtkTreeIter* a,
1888- GtkTreeIter* b,
1889- gpointer data)
1890-{
1891- MidoriExtension* e1, *e2;
1892- gchar* name1, *name2;
1893- gint result = 0;
1894-
1895- gtk_tree_model_get (model, a, 0, &e1, -1);
1896- gtk_tree_model_get (model, b, 0, &e2, -1);
1897-
1898- name1 = katze_object_get_string (e1, "name");
1899- name2 = katze_object_get_string (e2, "name");
1900-
1901- g_object_unref (e1);
1902- g_object_unref (e2);
1903-
1904- result = g_strcmp0 (name1, name2);
1905-
1906- g_free (name1);
1907- g_free (name2);
1908-
1909- return result;
1910-}
1911-
1912-static void
1913-midori_extensions_treeview_column_preference_clicked_cb (GtkWidget* widget,
1914- GtkTreeView* treeview,
1915- GtkTreePath* path)
1916-{
1917- GtkTreeModel* model;
1918- GtkTreeIter iter;
1919-
1920- model = gtk_tree_view_get_model (treeview);
1921- if (gtk_tree_model_get_iter (model, &iter, path))
1922- {
1923- MidoriExtension* extension;
1924-
1925- gtk_tree_model_get (model, &iter, 0, &extension, -1);
1926- if (midori_extension_is_active (extension))
1927- g_signal_emit_by_name (extension, "open-preferences");
1928- g_object_unref (extension);
1929- }
1930-
1931-}
1932-
1933-static gboolean
1934-midori_extensions_treeview_button_pressed_cb (GtkWidget* view,
1935- GdkEventButton* bevent,
1936- gpointer data)
1937-{
1938- gboolean ret = FALSE;
1939- GtkTreePath* path;
1940- GtkTreeViewColumn* column;
1941- guint signal_id;
1942-
1943- if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (view),
1944- bevent->x, bevent->y, &path, &column, NULL, NULL))
1945- {
1946- if (path != NULL)
1947- {
1948- if (MIDORI_IS_EXTENSIONS_COLUMN (column))
1949- {
1950- signal_id = g_signal_lookup ("row-clicked", G_OBJECT_TYPE (column));
1951-
1952- if (signal_id && g_signal_has_handler_pending (column, signal_id, 0, FALSE)) {
1953- g_signal_emit (column, signal_id, 0, GTK_TREE_VIEW (view), path);
1954- ret = TRUE;
1955- }
1956- }
1957- gtk_tree_path_free (path);
1958- }
1959- }
1960- return ret;
1961-}
1962-
1963-static gboolean
1964-extensions_column_search_equal_func (GtkTreeModel* model,
1965- gint column,
1966- const gchar* key,
1967- GtkTreeIter* iter,
1968- gpointer search_data)
1969-{
1970- MidoriExtension* extension;
1971- gchar* name;
1972- gchar* lower;
1973- gboolean match;
1974-
1975- gtk_tree_model_get (model, iter, 0, &extension, -1);
1976- name = katze_object_get_string (extension, "name");
1977- lower = g_utf8_strdown (name, -1);
1978- match = !strstr (lower, key);
1979-
1980- g_free (lower);
1981- g_free (name);
1982-
1983- return match;
1984-}
1985-
1986-static void
1987-midori_extensions_init (MidoriExtensions* extensions)
1988-{
1989- /* Create the treeview */
1990- GtkTreeViewColumn* column;
1991- GtkCellRenderer* renderer_icon;
1992- GtkCellRenderer* renderer_text;
1993- GtkCellRenderer* renderer_toggle;
1994- GtkCellRenderer* renderer_preferences;
1995- GtkListStore* liststore = gtk_list_store_new (1, G_TYPE_OBJECT);
1996- extensions->treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (liststore));
1997- g_object_connect (extensions->treeview,
1998- "signal::button-press-event",
1999- midori_extensions_treeview_button_pressed_cb, NULL,
2000- NULL);
2001- gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (liststore),
2002- 0, GTK_SORT_ASCENDING);
2003- gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (liststore),
2004- 0, midori_extensions_tree_sort_func, NULL, NULL);
2005- gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (extensions->treeview), FALSE);
2006- column = gtk_tree_view_column_new ();
2007- renderer_toggle = gtk_cell_renderer_toggle_new ();
2008- gtk_tree_view_column_pack_start (column, renderer_toggle, FALSE);
2009- gtk_tree_view_column_set_cell_data_func (column, renderer_toggle,
2010- (GtkTreeCellDataFunc)midori_extensions_treeview_render_tick_cb,
2011- extensions->treeview, NULL);
2012- g_signal_connect (renderer_toggle, "toggled",
2013- G_CALLBACK (midori_extensions_cell_renderer_toggled_cb), extensions);
2014- gtk_tree_view_append_column (GTK_TREE_VIEW (extensions->treeview), column);
2015- column = gtk_tree_view_column_new ();
2016- renderer_icon = gtk_cell_renderer_pixbuf_new ();
2017- gtk_tree_view_column_pack_start (column, renderer_icon, FALSE);
2018- gtk_tree_view_column_set_cell_data_func (column, renderer_icon,
2019- (GtkTreeCellDataFunc)midori_extensions_treeview_render_icon_cb,
2020- extensions->treeview, NULL);
2021- gtk_tree_view_append_column (GTK_TREE_VIEW (extensions->treeview), column);
2022- column = gtk_tree_view_column_new ();
2023- gtk_tree_view_column_set_expand (column, TRUE);
2024- renderer_text = gtk_cell_renderer_text_new ();
2025- gtk_tree_view_column_pack_start (column, renderer_text, TRUE);
2026- gtk_tree_view_column_set_cell_data_func (column, renderer_text,
2027- (GtkTreeCellDataFunc)midori_extensions_treeview_render_text_cb,
2028- extensions->treeview, NULL);
2029- gtk_tree_view_append_column (GTK_TREE_VIEW (extensions->treeview), column);
2030- column = GTK_TREE_VIEW_COLUMN (midori_extensions_column_new ());
2031- g_signal_connect (column,
2032- "row-clicked",
2033- G_CALLBACK (midori_extensions_treeview_column_preference_clicked_cb),
2034- NULL);
2035- renderer_preferences = gtk_cell_renderer_pixbuf_new ();
2036- gtk_tree_view_column_pack_start (column, renderer_preferences, FALSE);
2037- gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
2038- gtk_tree_view_column_set_fixed_width (column, 30);
2039- gtk_tree_view_column_set_cell_data_func (column, renderer_preferences,
2040- (GtkTreeCellDataFunc)midori_extensions_treeview_render_preferences_cb,
2041- extensions->treeview, NULL);
2042- gtk_tree_view_append_column (GTK_TREE_VIEW (extensions->treeview), column);
2043- g_object_unref (liststore);
2044- g_object_connect (extensions->treeview,
2045- "signal::row-activated",
2046- midori_extensions_treeview_row_activated_cb, extensions,
2047- NULL);
2048- gtk_tree_view_set_search_column (GTK_TREE_VIEW (extensions->treeview), 0);
2049- gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (extensions->treeview),
2050- extensions_column_search_equal_func, NULL, NULL);
2051- gtk_widget_show (extensions->treeview);
2052- gtk_box_pack_start (GTK_BOX (extensions), extensions->treeview, TRUE, TRUE, 0);
2053-}
2054-
2055-static void
2056-midori_extensions_finalize (GObject* object)
2057-{
2058- MidoriExtensions* extensions = MIDORI_EXTENSIONS (object);
2059- KatzeArray* array = katze_object_get_object (extensions->app, "extensions");
2060- MidoriExtension* extension;
2061-
2062- KATZE_ARRAY_FOREACH_ITEM (extension, array)
2063- {
2064- g_signal_handlers_disconnect_by_func (extension,
2065- midori_extensions_extension_activate_cb, extensions);
2066- g_signal_handlers_disconnect_by_func (extension,
2067- midori_extensions_extension_deactivate_cb, extensions);
2068- }
2069- g_signal_handlers_disconnect_by_func (array,
2070- midori_extensions_add_item_cb, extensions);
2071-
2072- g_object_unref (array);
2073-}
2074-
2075
2076=== removed file 'panels/midori-extensions.h'
2077--- panels/midori-extensions.h 2008-12-04 00:44:33 +0000
2078+++ panels/midori-extensions.h 1970-01-01 00:00:00 +0000
2079@@ -1,45 +0,0 @@
2080-/*
2081- Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
2082-
2083- This library is free software; you can redistribute it and/or
2084- modify it under the terms of the GNU Lesser General Public
2085- License as published by the Free Software Foundation; either
2086- version 2.1 of the License, or (at your option) any later version.
2087-
2088- See the file COPYING for the full license text.
2089-*/
2090-
2091-#ifndef __MIDORI_EXTENSIONS_H__
2092-#define __MIDORI_EXTENSIONS_H__
2093-
2094-#include <gtk/gtk.h>
2095-
2096-#include <katze/katze.h>
2097-
2098-G_BEGIN_DECLS
2099-
2100-#define MIDORI_TYPE_EXTENSIONS \
2101- (midori_extensions_get_type ())
2102-#define MIDORI_EXTENSIONS(obj) \
2103- (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_EXTENSIONS, MidoriExtensions))
2104-#define MIDORI_EXTENSIONS_CLASS(klass) \
2105- (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_EXTENSIONS, MidoriExtensionsClass))
2106-#define MIDORI_IS_EXTENSIONS(obj) \
2107- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_EXTENSIONS))
2108-#define MIDORI_IS_EXTENSIONS_CLASS(klass) \
2109- (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_EXTENSIONS))
2110-#define MIDORI_EXTENSIONS_GET_CLASS(obj) \
2111- (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_EXTENSIONS, MidoriExtensionsClass))
2112-
2113-typedef struct _MidoriExtensions MidoriExtensions;
2114-typedef struct _MidoriExtensionsClass MidoriExtensionsClass;
2115-
2116-GType
2117-midori_extensions_get_type (void);
2118-
2119-GtkWidget*
2120-midori_extensions_new (void);
2121-
2122-G_END_DECLS
2123-
2124-#endif /* __MIDORI_EXTENSIONS_H__ */
2125
2126=== modified file 'po/POTFILES.in'
2127--- po/POTFILES.in 2015-05-24 00:19:21 +0000
2128+++ po/POTFILES.in 2015-06-22 22:20:28 +0000
2129@@ -27,7 +27,7 @@
2130 midori/sokoke.c
2131 toolbars/midori-findbar.c
2132 panels/midori-bookmarks.c
2133-panels/midori-extensions.c
2134+extensions/extensions.vala
2135 panels/midori-history.c
2136 katze/katze-http-auth.c
2137 katze/katze-utils.c
2138@@ -65,9 +65,12 @@
2139 extensions/status-clock.c
2140 extensions/statusbar-features.c
2141 extensions/tab-panel.c
2142-extensions/tabs-minimized.c
2143+extensions/tabs-minimized.vala
2144 extensions/tabs2one.c
2145 extensions/toolbar-editor.c
2146+extensions/hsts.web.vala
2147+extensions/web-extension.web.vala
2148+ipc/ipc-tab.vala
2149 katze/katze-cellrenderercomboboxtext.c
2150 katze/midori-hsts.vala
2151 katze/katze-separatoraction.vala

Subscribers

People subscribed via source and target branches

to all changes: