Merge lp:~midori/midori/hstsWebExtension into lp:midori
- hstsWebExtension
- Merge into trunk
Proposed by
Cris Dywan
Status: | Work in progress |
---|---|
Proposed branch: | lp:~midori/midori/hstsWebExtension |
Merge into: | lp:midori |
Diff against target: |
528 lines (+330/-89) 5 files modified
CMakeLists.txt (+1/-1) extensions/CMakeLists.txt (+92/-82) extensions/hsts.web.vala (+177/-0) katze/midori-paths.vala (+10/-6) midori/main.c (+50/-0) |
To merge this branch: | bzr merge lp:~midori/midori/hstsWebExtension |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Midori Devs | Pending | ||
Review via email: mp+261897@code.launchpad.net |
Commit message
Implement HSTS as a web extension
Description of the change
This branch enables building of separate web extensions.
Note: At this point we probably want to go for libpeas rather than the direct WebKit2 API. That would save us an additional porting step later if we do it in one go. And give us control over extensions that we can't have otherwise.
To post a comment you must log in.
Unmerged revisions
- 6965. By Cris 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-03-23 11:33:24 +0000 | |||
3 | +++ CMakeLists.txt 2015-06-13 13:38:06 +0000 | |||
4 | @@ -268,9 +268,9 @@ | |||
5 | 268 | install(FILES AUTHORS COPYING ChangeLog EXPAT README DESTINATION ${CMAKE_INSTALL_DOCDIR}) | 268 | install(FILES AUTHORS COPYING ChangeLog EXPAT README DESTINATION ${CMAKE_INSTALL_DOCDIR}) |
6 | 269 | 269 | ||
7 | 270 | add_subdirectory (midori) | 270 | add_subdirectory (midori) |
8 | 271 | add_subdirectory (extensions) | ||
9 | 272 | enable_testing() | 271 | enable_testing() |
10 | 273 | add_subdirectory (tests) | 272 | add_subdirectory (tests) |
11 | 273 | add_subdirectory (extensions) | ||
12 | 274 | add_subdirectory (po) | 274 | add_subdirectory (po) |
13 | 275 | add_subdirectory (icons) | 275 | add_subdirectory (icons) |
14 | 276 | add_subdirectory (data) | 276 | add_subdirectory (data) |
15 | 277 | 277 | ||
16 | === modified file 'extensions/CMakeLists.txt' | |||
17 | --- extensions/CMakeLists.txt 2015-04-19 14:06:12 +0000 | |||
18 | +++ extensions/CMakeLists.txt 2015-06-13 13:38:06 +0000 | |||
19 | @@ -23,6 +23,10 @@ | |||
20 | 23 | "nsplugin-manager.vala" | 23 | "nsplugin-manager.vala" |
21 | 24 | "tabs2one.c" | 24 | "tabs2one.c" |
22 | 25 | ) | 25 | ) |
23 | 26 | else () | ||
24 | 27 | list(REMOVE_ITEM EXTENSIONS | ||
25 | 28 | "hsts.web.vala" | ||
26 | 29 | ) | ||
27 | 26 | endif () | 30 | endif () |
28 | 27 | 31 | ||
29 | 28 | # FIXME: re-enable webmedia extension | 32 | # FIXME: re-enable webmedia extension |
30 | @@ -36,99 +40,105 @@ | |||
31 | 36 | list(REMOVE_ITEM EXTENSIONS "tabs2one.c") | 40 | list(REMOVE_ITEM EXTENSIONS "tabs2one.c") |
32 | 37 | endif() | 41 | endif() |
33 | 38 | 42 | ||
50 | 39 | foreach(UNIT_SRC ${EXTENSIONS}) | 43 | include(ValaPrecompile) |
35 | 40 | string(FIND ${UNIT_SRC} ".c" UNIT_EXTENSION) | ||
36 | 41 | if (UNIT_EXTENSION GREATER -1) | ||
37 | 42 | string(REPLACE ".c" "" UNIT ${UNIT_SRC}) | ||
38 | 43 | add_library(${UNIT} MODULE ${UNIT_SRC}) | ||
39 | 44 | target_link_libraries(${UNIT} | ||
40 | 45 | ${LIBMIDORI} | ||
41 | 46 | ) | ||
42 | 47 | set_target_properties(${UNIT} PROPERTIES | ||
43 | 48 | COMPILE_FLAGS ${CFLAGS} | ||
44 | 49 | ) | ||
45 | 50 | install(TARGETS ${UNIT} | ||
46 | 51 | LIBRARY DESTINATION ${EXTENSIONDIR} | ||
47 | 52 | ) | ||
48 | 53 | endif () | ||
49 | 54 | endforeach () | ||
51 | 55 | 44 | ||
62 | 56 | foreach(UNIT_SRC ${EXTENSIONS}) | 45 | macro(build_extension name) |
63 | 57 | string(FIND ${UNIT_SRC} "." UNIT_EXTENSION) | 46 | set(source "${ARGN}") |
64 | 58 | if (UNIT_EXTENSION EQUAL -1) | 47 | set(SOURCE_VALA "") |
65 | 59 | file(GLOB UNIT_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${UNIT_SRC}/*.c") | 48 | foreach(FILE ${source}) |
66 | 60 | file(GLOB UNIT_FILES_VALA RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${UNIT_SRC}/*.vala") | 49 | string(FIND ${FILE} ".web." WEB_EXTENSION) |
67 | 61 | if (UNIT_FILES_VALA) | 50 | string(FIND ${FILE} ".vala" VALA_EXTENSION) |
68 | 62 | include(ValaPrecompile) | 51 | if (WEB_EXTENSION GREATER -1) |
69 | 63 | vala_precompile(UNIT_SRC_C ${UNIT_SRC} | 52 | string(REPLACE ".vala" "" WEB_NAME "${name}_${FILE}") |
70 | 64 | ${UNIT_FILES_VALA} | 53 | string(REPLACE "." "_" WEB_NAME "${WEB_NAME}") |
71 | 65 | PACKAGES | 54 | vala_precompile(WEB_EXTENSION_C "${WEB_NAME}" |
72 | 55 | ${FILE} | ||
73 | 56 | PACKAGES | ||
74 | 66 | ${PKGS} | 57 | ${PKGS} |
93 | 67 | OPTIONS | 58 | OPTIONS |
94 | 68 | ${VALAFLAGS} | 59 | ${VALAFLAGS} |
95 | 69 | --use-header="${CMAKE_PROJECT_NAME}-core.h" | 60 | GENERATE_HEADER |
96 | 70 | GENERATE_HEADER | 61 | ${FILE} |
97 | 71 | "${UNIT_SRC}" | 62 | CUSTOM_VAPIS |
98 | 72 | GENERATE_HEADER | 63 | "${CMAKE_SOURCE_DIR}/midori/webkit2gtk-web-extension-4.0.vapi" |
99 | 73 | ${UNIT} | 64 | ) |
100 | 74 | CUSTOM_VAPIS | 65 | add_library(${WEB_NAME} MODULE ${WEB_EXTENSION_C}) |
101 | 75 | ${EXTRA_VAPIS} | 66 | target_link_libraries(${WEB_NAME} |
102 | 76 | "${CMAKE_SOURCE_DIR}/midori/midori.vapi" | 67 | ${LIBMIDORI2} |
103 | 77 | "${CMAKE_BINARY_DIR}/midori/${LIBMIDORI}.vapi" | 68 | ) |
104 | 78 | ) | 69 | install(TARGETS ${WEB_NAME} |
105 | 79 | set(UNIT_FILES ${UNIT_FILES} ${UNIT_SRC_C}) | 70 | LIBRARY DESTINATION ${EXTENSIONDIR} |
106 | 80 | endif () | 71 | ) |
107 | 81 | if (UNIT_FILES) | 72 | # Extensions with Vala code get the lenient VALA_CFLAGS |
108 | 82 | add_library(${UNIT_SRC} MODULE ${UNIT_FILES}) | 73 | set_target_properties(${WEB_NAME} PROPERTIES |
109 | 83 | target_link_libraries(${UNIT_SRC} | 74 | COMPILE_FLAGS ${VALA_CFLAGS} |
92 | 84 | ${LIBMIDORI} | ||
110 | 85 | ) | 75 | ) |
128 | 86 | install(TARGETS ${UNIT_SRC} | 76 | list(REMOVE_ITEM source ${FILE}) |
112 | 87 | LIBRARY DESTINATION ${EXTENSIONDIR} | ||
113 | 88 | ) | ||
114 | 89 | # extensions with vala code get the lenient VALA_CFLAGS | ||
115 | 90 | # others get the usual CFLAGS with -Wall and -Werror | ||
116 | 91 | if (UNIT_FILES_VALA) | ||
117 | 92 | set_target_properties(${UNIT_SRC} PROPERTIES | ||
118 | 93 | COMPILE_FLAGS ${VALA_CFLAGS} | ||
119 | 94 | ) | ||
120 | 95 | else () | ||
121 | 96 | set_target_properties(${UNIT_SRC} PROPERTIES | ||
122 | 97 | COMPILE_FLAGS ${CFLAGS} | ||
123 | 98 | ) | ||
124 | 99 | endif () | ||
125 | 100 | endif () | ||
126 | 101 | endif () | ||
127 | 102 | endforeach () | ||
129 | 103 | 77 | ||
137 | 104 | foreach(UNIT_SRC ${EXTENSIONS}) | 78 | # Mandatory unit testing |
138 | 105 | string(FIND ${UNIT_SRC} ".vala" UNIT_EXTENSION) | 79 | add_test(NAME "test-${WEB_NAME}" COMMAND $<TARGET_FILE:midori> -t $<TARGET_FILE:${WEB_NAME}>) |
139 | 106 | if (UNIT_EXTENSION GREATER -1) | 80 | contain_test("test-${WEB_NAME}" $<TARGET_FILE:midori> -t $<TARGET_FILE:${WEB_NAME}>) |
140 | 107 | string(REPLACE ".vala" "" UNIT ${UNIT_SRC}) | 81 | elseif (VALA_EXTENSION GREATER -1) |
141 | 108 | include(ValaPrecompile) | 82 | list(APPEND SOURCE_VALA ${FILE}) |
142 | 109 | vala_precompile(UNIT_SRC_C ${UNIT} | 83 | endif () |
143 | 110 | ${UNIT_SRC} | 84 | endforeach() |
144 | 85 | if (SOURCE_VALA) | ||
145 | 86 | vala_precompile(SOURCE_C ${name} | ||
146 | 87 | ${SOURCE_VALA} | ||
147 | 111 | PACKAGES | 88 | PACKAGES |
148 | 112 | ${PKGS} | 89 | ${PKGS} |
149 | 113 | OPTIONS | 90 | OPTIONS |
152 | 114 | ${VALAFLAGS} | 91 | ${VALAFLAGS} |
151 | 115 | --use-header="${CMAKE_PROJECT_NAME}-core.h" | ||
153 | 116 | GENERATE_HEADER | 92 | GENERATE_HEADER |
155 | 117 | ${UNIT} | 93 | ${name} |
156 | 118 | CUSTOM_VAPIS | 94 | CUSTOM_VAPIS |
158 | 119 | ${EXTRA_VAPIS} | 95 | ${EXTRA_VAPIS} |
159 | 120 | "${CMAKE_SOURCE_DIR}/midori/midori.vapi" | 96 | "${CMAKE_SOURCE_DIR}/midori/midori.vapi" |
160 | 97 | # "${CMAKE_SOURCE_DIR}/katze/katze.vapi" | ||
161 | 121 | "${CMAKE_BINARY_DIR}/midori/${LIBMIDORI}.vapi" | 98 | "${CMAKE_BINARY_DIR}/midori/${LIBMIDORI}.vapi" |
162 | 122 | ) | 99 | ) |
173 | 123 | add_library(${UNIT} MODULE ${UNIT_SRC_C}) | 100 | set(source ${SOURCE_C}) |
174 | 124 | target_link_libraries(${UNIT} | 101 | endif () |
175 | 125 | ${LIBMIDORI} | 102 | if (source) |
176 | 126 | ) | 103 | add_library(${name} MODULE ${source}) |
177 | 127 | set_target_properties(${UNIT} PROPERTIES | 104 | target_link_libraries(${name} |
178 | 128 | COMPILE_FLAGS "${VALA_CFLAGS}" | 105 | ${LIBMIDORI} |
179 | 129 | ) | 106 | ) |
180 | 130 | install(TARGETS ${UNIT} | 107 | install(TARGETS ${name} |
181 | 131 | LIBRARY DESTINATION ${EXTENSIONDIR} | 108 | LIBRARY DESTINATION ${EXTENSIONDIR} |
182 | 132 | ) | 109 | ) |
183 | 110 | if (SOURCE_VALA) | ||
184 | 111 | # Extensions with Vala code get the lenient VALA_CFLAGS | ||
185 | 112 | set_target_properties(${name} PROPERTIES | ||
186 | 113 | COMPILE_FLAGS ${VALA_CFLAGS} | ||
187 | 114 | ) | ||
188 | 115 | else () | ||
189 | 116 | set_target_properties(${name} PROPERTIES | ||
190 | 117 | COMPILE_FLAGS ${CFLAGS} | ||
191 | 118 | ) | ||
192 | 119 | endif () | ||
193 | 120 | # Optional unit test | ||
194 | 121 | add_test(NAME "test-${name}" COMMAND $<TARGET_FILE:midori> -t $<TARGET_FILE:${name}>) | ||
195 | 122 | contain_test("test-${name}" $<TARGET_FILE:midori> -t $<TARGET_FILE:${name}>) | ||
196 | 123 | endif () | ||
197 | 124 | endmacro(build_extension) | ||
198 | 125 | |||
199 | 126 | foreach(UNIT_SRC ${EXTENSIONS}) | ||
200 | 127 | string(FIND ${UNIT_SRC} ".c" UNIT_EXTENSION) | ||
201 | 128 | if (UNIT_EXTENSION GREATER -1) | ||
202 | 129 | string(REPLACE ".c" "" UNIT ${UNIT_SRC}) | ||
203 | 130 | build_extension(${UNIT} ${UNIT_SRC}) | ||
204 | 131 | endif () | ||
205 | 132 | |||
206 | 133 | string(FIND ${UNIT_SRC} "." UNIT_EXTENSION) | ||
207 | 134 | if (UNIT_EXTENSION GREATER -1) | ||
208 | 135 | file(GLOB UNIT_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${UNIT_SRC}/*.c" "${UNIT_SRC}/*.vala") | ||
209 | 136 | build_extension(${UNIT_SRC} ${UNIT_FILES}) | ||
210 | 137 | endif () | ||
211 | 138 | |||
212 | 139 | string(FIND ${UNIT_SRC} ".vala" UNIT_EXTENSION) | ||
213 | 140 | if (UNIT_EXTENSION GREATER -1) | ||
214 | 141 | string(REPLACE ".vala" "" UNIT ${UNIT_SRC}) | ||
215 | 142 | build_extension(${UNIT} ${UNIT_SRC}) | ||
216 | 133 | endif () | 143 | endif () |
217 | 134 | endforeach () | 144 | endforeach () |
218 | 135 | 145 | ||
219 | === added file 'extensions/hsts.web.vala' | |||
220 | --- extensions/hsts.web.vala 1970-01-01 00:00:00 +0000 | |||
221 | +++ extensions/hsts.web.vala 2015-06-13 13:38:06 +0000 | |||
222 | @@ -0,0 +1,177 @@ | |||
223 | 1 | /* | ||
224 | 2 | Copyright (C) 2012-2014 Christian Dywan <christian@twotoasts.de> | ||
225 | 3 | |||
226 | 4 | This library is free software; you can redistribute it and/or | ||
227 | 5 | modify it under the terms of the GNU Lesser General Public | ||
228 | 6 | License as published by the Free Software Foundation; either | ||
229 | 7 | version 2.1 of the License, or (at your option) any later version. | ||
230 | 8 | |||
231 | 9 | See the file COPYING for the full license text. | ||
232 | 10 | */ | ||
233 | 11 | |||
234 | 12 | namespace HSTS { | ||
235 | 13 | public class Directive { | ||
236 | 14 | public Soup.Date? expires = null; | ||
237 | 15 | public bool sub_domains = false; | ||
238 | 16 | |||
239 | 17 | public Directive (bool include_sub_domains) { | ||
240 | 18 | expires = new Soup.Date.from_now (int.MAX); | ||
241 | 19 | sub_domains = include_sub_domains; | ||
242 | 20 | } | ||
243 | 21 | |||
244 | 22 | public Directive.from_header (string header) { | ||
245 | 23 | var param_list = Soup.header_parse_param_list (header); | ||
246 | 24 | if (param_list == null) | ||
247 | 25 | return; | ||
248 | 26 | |||
249 | 27 | string? max_age = param_list.lookup ("max-age"); | ||
250 | 28 | if (max_age != null) | ||
251 | 29 | expires = new Soup.Date.from_now (max_age.to_int ()); | ||
252 | 30 | if ("includeSubDomains" in header) | ||
253 | 31 | sub_domains = true; | ||
254 | 32 | Soup.header_free_param_list (param_list); | ||
255 | 33 | } | ||
256 | 34 | |||
257 | 35 | public bool is_valid () { | ||
258 | 36 | return expires != null && !expires.is_past (); | ||
259 | 37 | } | ||
260 | 38 | } | ||
261 | 39 | |||
262 | 40 | public class Whitelist : Object { | ||
263 | 41 | HashTable<string, Directive> whitelist; | ||
264 | 42 | string preset = "/etc/xdg/midori/hsts"; | ||
265 | 43 | File config; | ||
266 | 44 | |||
267 | 45 | public Whitelist () { | ||
268 | 46 | whitelist = new HashTable<string, Directive> (str_hash, str_equal); | ||
269 | 47 | read_cache.begin (File.new_for_path (preset)); | ||
270 | 48 | // FIXME: config = File.new_for_path (Midori.Paths.get_config_filename_for_writing ("hsts")); | ||
271 | 49 | string config_dir = Path.build_path (Path.DIR_SEPARATOR_S, | ||
272 | 50 | Environment.get_user_config_dir (), "midori"); | ||
273 | 51 | config = File.new_for_path (Path.build_path (Path.DIR_SEPARATOR_S, config_dir, "hsts")); | ||
274 | 52 | read_cache.begin (config); | ||
275 | 53 | } | ||
276 | 54 | |||
277 | 55 | async void read_cache (File file) { | ||
278 | 56 | try { | ||
279 | 57 | var stream = new DataInputStream (yield file.read_async ()); | ||
280 | 58 | do { | ||
281 | 59 | string? line = yield stream.read_line_async (); | ||
282 | 60 | if (line == null) | ||
283 | 61 | break; | ||
284 | 62 | string[] parts = line.split (" ", 2); | ||
285 | 63 | if (parts[0] == null || parts[1] == null) | ||
286 | 64 | break; | ||
287 | 65 | var directive = new Directive.from_header (parts[1]); | ||
288 | 66 | if (directive.is_valid ()) | ||
289 | 67 | append_to_whitelist (parts[0], directive); | ||
290 | 68 | } while (true); | ||
291 | 69 | } catch (IOError.NOT_FOUND exist_error) { | ||
292 | 70 | /* It's no error if no cache file exists */ | ||
293 | 71 | } catch (Error error) { | ||
294 | 72 | warning ("Failed to read cache %s: %s", file.get_path (), error.message); | ||
295 | 73 | } | ||
296 | 74 | } | ||
297 | 75 | |||
298 | 76 | public bool should_secure_host (string host) { | ||
299 | 77 | Directive? directive = whitelist.lookup (host); | ||
300 | 78 | if (directive == null) | ||
301 | 79 | directive = whitelist.lookup ("*." + host); | ||
302 | 80 | return directive != null && directive.is_valid (); | ||
303 | 81 | } | ||
304 | 82 | |||
305 | 83 | void append_to_whitelist (string host, Directive directive) { | ||
306 | 84 | whitelist.insert (host, directive); | ||
307 | 85 | if (directive.sub_domains) | ||
308 | 86 | whitelist.insert ("*." + host, directive); | ||
309 | 87 | } | ||
310 | 88 | |||
311 | 89 | async void append_to_cache (string host, string header) { | ||
312 | 90 | /* FIXME: Don't write in private browsing */ | ||
313 | 91 | |||
314 | 92 | try { | ||
315 | 93 | var stream = yield config.append_to_async (FileCreateFlags.NONE); | ||
316 | 94 | yield stream.write_async ((host + " " + header + "\n").data); | ||
317 | 95 | yield stream.flush_async (); | ||
318 | 96 | } | ||
319 | 97 | catch (Error error) { | ||
320 | 98 | critical ("Failed to update %s: %s", config.get_path (), error.message); | ||
321 | 99 | } | ||
322 | 100 | } | ||
323 | 101 | |||
324 | 102 | public Directive? strict_transport_security_handled (string host, Soup.MessageHeaders headers) { | ||
325 | 103 | unowned string? hsts = headers.get_one ("Strict-Transport-Security"); | ||
326 | 104 | if (hsts == null) | ||
327 | 105 | return null; | ||
328 | 106 | |||
329 | 107 | var directive = new Directive.from_header (hsts); | ||
330 | 108 | if (directive.is_valid ()) { | ||
331 | 109 | append_to_whitelist (host, directive); | ||
332 | 110 | append_to_cache.begin (host, hsts); | ||
333 | 111 | } | ||
334 | 112 | return directive; | ||
335 | 113 | } | ||
336 | 114 | |||
337 | 115 | } | ||
338 | 116 | |||
339 | 117 | public class Extension : Object { | ||
340 | 118 | Whitelist whitelist; | ||
341 | 119 | bool debug = false; | ||
342 | 120 | |||
343 | 121 | public Extension (WebKit.WebExtension extension) { | ||
344 | 122 | if (strcmp (Environment.get_variable ("MIDORI_DEBUG"), "hsts") == 0) | ||
345 | 123 | debug = true; | ||
346 | 124 | whitelist = new Whitelist (); | ||
347 | 125 | extension.page_created.connect (page_created); | ||
348 | 126 | } | ||
349 | 127 | |||
350 | 128 | void page_created (WebKit.WebPage page) { | ||
351 | 129 | page.send_request.connect (send_request); | ||
352 | 130 | } | ||
353 | 131 | |||
354 | 132 | bool send_request (WebKit.URIRequest request, WebKit.URIResponse? redirect) { | ||
355 | 133 | Soup.MessageHeaders? headers = request.get_http_headers (); | ||
356 | 134 | if (headers == null || !request.uri.contains ("/")) | ||
357 | 135 | return false; | ||
358 | 136 | |||
359 | 137 | string host = request.uri.split ("/")[2]; | ||
360 | 138 | if (whitelist.should_secure_host (host)) { | ||
361 | 139 | request.uri = request.uri.replace ("http://", "https://"); | ||
362 | 140 | if (debug) | ||
363 | 141 | stdout.printf ("HSTS: Enforce %s\n", host); | ||
364 | 142 | } else if (request.uri.has_prefix ("http://")) { | ||
365 | 143 | var directive = whitelist.strict_transport_security_handled (host, headers); | ||
366 | 144 | if (debug) | ||
367 | 145 | stdout.printf ("HSTS: %s valid? %s\n", | ||
368 | 146 | host, directive != null ? directive.is_valid ().to_string () : "/"); | ||
369 | 147 | } | ||
370 | 148 | return false; | ||
371 | 149 | } | ||
372 | 150 | } | ||
373 | 151 | } | ||
374 | 152 | |||
375 | 153 | HSTS.Extension? hsts; | ||
376 | 154 | // public void webkit_web_extension_initialize_with_user_data (WebKit.WebExtension extension, Variant user_data) { | ||
377 | 155 | public void webkit_web_extension_initialize (WebKit.WebExtension extension) { | ||
378 | 156 | // FIXME: Midori.Paths.init_with_user_data (user_data); | ||
379 | 157 | hsts = new HSTS.Extension (extension); | ||
380 | 158 | } | ||
381 | 159 | |||
382 | 160 | void hsts_directive () { | ||
383 | 161 | HSTS.Directive d; | ||
384 | 162 | d = new HSTS.Directive.from_header ("max-age=31536000"); | ||
385 | 163 | assert (d.is_valid () && !d.sub_domains); | ||
386 | 164 | d = new HSTS.Directive.from_header ("max-age=15768000 ; includeSubDomains"); | ||
387 | 165 | assert (d.is_valid () && d.sub_domains); | ||
388 | 166 | |||
389 | 167 | /* Invalid */ | ||
390 | 168 | d = new HSTS.Directive.from_header (""); | ||
391 | 169 | assert (!d.is_valid () && !d.sub_domains); | ||
392 | 170 | d = new HSTS.Directive.from_header ("includeSubDomains"); | ||
393 | 171 | assert (!d.is_valid () && d.sub_domains); | ||
394 | 172 | } | ||
395 | 173 | |||
396 | 174 | public void extension_test () { | ||
397 | 175 | Test.add_func ("/hsts/directive", hsts_directive); | ||
398 | 176 | } | ||
399 | 177 | |||
400 | 0 | 178 | ||
401 | === added directory 'ipc' | |||
402 | === modified file 'katze/midori-paths.vala' | |||
403 | --- katze/midori-paths.vala 2015-06-11 22:33:48 +0000 | |||
404 | +++ katze/midori-paths.vala 2015-06-13 13:38:06 +0000 | |||
405 | @@ -99,6 +99,7 @@ | |||
406 | 99 | 99 | ||
407 | 100 | public static void init (RuntimeMode new_mode, string? config) { | 100 | public static void init (RuntimeMode new_mode, string? config) { |
408 | 101 | assert (mode == RuntimeMode.UNDEFINED); | 101 | assert (mode == RuntimeMode.UNDEFINED); |
409 | 102 | assert (exec_path != null); | ||
410 | 102 | assert (new_mode != RuntimeMode.UNDEFINED); | 103 | assert (new_mode != RuntimeMode.UNDEFINED); |
411 | 103 | mode = new_mode; | 104 | mode = new_mode; |
412 | 104 | if (mode == RuntimeMode.PORTABLE || mode == RuntimeMode.PRIVATE) | 105 | if (mode == RuntimeMode.PORTABLE || mode == RuntimeMode.PRIVATE) |
413 | @@ -148,16 +149,19 @@ | |||
414 | 148 | tmp_dir = get_runtime_dir (); | 149 | tmp_dir = get_runtime_dir (); |
415 | 149 | } | 150 | } |
416 | 150 | #if HAVE_WEBKIT2 | 151 | #if HAVE_WEBKIT2 |
417 | 152 | var context = WebKit.WebContext.get_default (); | ||
418 | 153 | context.set_web_extensions_directory (get_lib_path (PACKAGE_NAME)); | ||
419 | 154 | context.initialize_web_extensions.connect (() => { | ||
420 | 155 | /* TODO: Pass user data */ | ||
421 | 156 | context.set_web_extensions_initialization_user_data (""); | ||
422 | 157 | }); | ||
423 | 151 | if (cache_dir != null) { | 158 | if (cache_dir != null) { |
428 | 152 | /* Cache and extension dir MUST be set no later than here to work */ | 159 | context.set_disk_cache_directory ( |
425 | 153 | WebKit.WebContext.get_default ().set_web_extensions_directory ( | ||
426 | 154 | Path.build_path (Path.DIR_SEPARATOR_S, cache_dir, "wk2ext")); | ||
427 | 155 | WebKit.WebContext.get_default ().set_disk_cache_directory ( | ||
429 | 156 | Path.build_path (Path.DIR_SEPARATOR_S, cache_dir, "web")); | 160 | Path.build_path (Path.DIR_SEPARATOR_S, cache_dir, "web")); |
430 | 157 | } | 161 | } |
431 | 158 | 162 | ||
432 | 159 | if (config_dir != null) { | 163 | if (config_dir != null) { |
434 | 160 | var cookie_manager = WebKit.WebContext.get_default ().get_cookie_manager (); | 164 | var cookie_manager = context.get_cookie_manager (); |
435 | 161 | cookie_manager.set_persistent_storage (Path.build_filename (config_dir, "cookies.db"), | 165 | cookie_manager.set_persistent_storage (Path.build_filename (config_dir, "cookies.db"), |
436 | 162 | WebKit.CookiePersistentStorage.SQLITE); | 166 | WebKit.CookiePersistentStorage.SQLITE); |
437 | 163 | } | 167 | } |
438 | @@ -165,7 +169,7 @@ | |||
439 | 165 | if (user_data_dir != null) { | 169 | if (user_data_dir != null) { |
440 | 166 | string folder = Path.build_filename (user_data_dir, "webkit", "icondatabase"); | 170 | string folder = Path.build_filename (user_data_dir, "webkit", "icondatabase"); |
441 | 167 | #if HAVE_WEBKIT2 | 171 | #if HAVE_WEBKIT2 |
443 | 168 | WebKit.WebContext.get_default ().set_favicon_database_directory (folder); | 172 | context.set_favicon_database_directory (folder); |
444 | 169 | #else | 173 | #else |
445 | 170 | WebKit.get_favicon_database ().set_path (folder); | 174 | WebKit.get_favicon_database ().set_path (folder); |
446 | 171 | #endif | 175 | #endif |
447 | 172 | 176 | ||
448 | === modified file 'midori/main.c' | |||
449 | --- midori/main.c 2014-04-23 03:34:23 +0000 | |||
450 | +++ midori/main.c 2015-06-13 13:38:06 +0000 | |||
451 | @@ -62,6 +62,7 @@ | |||
452 | 62 | gchar* config; | 62 | gchar* config; |
453 | 63 | gboolean private; | 63 | gboolean private; |
454 | 64 | gboolean portable; | 64 | gboolean portable; |
455 | 65 | gchar* test; | ||
456 | 65 | gboolean plain; | 66 | gboolean plain; |
457 | 66 | gboolean diagnostic_dialog = FALSE; | 67 | gboolean diagnostic_dialog = FALSE; |
458 | 67 | gboolean debug = FALSE; | 68 | gboolean debug = FALSE; |
459 | @@ -85,6 +86,8 @@ | |||
460 | 85 | { "portable", 'P', 0, G_OPTION_ARG_NONE, &portable, | 86 | { "portable", 'P', 0, G_OPTION_ARG_NONE, &portable, |
461 | 86 | N_("Portable mode, all runtime files are stored in one place"), NULL }, | 87 | N_("Portable mode, all runtime files are stored in one place"), NULL }, |
462 | 87 | #endif | 88 | #endif |
463 | 89 | { "test", 't', 0, G_OPTION_ARG_STRING, &test, | ||
464 | 90 | N_("Run unit tests for the specified extension"), NULL }, | ||
465 | 88 | { "plain", '\0', 0, G_OPTION_ARG_NONE, &plain, | 91 | { "plain", '\0', 0, G_OPTION_ARG_NONE, &plain, |
466 | 89 | N_("Plain GTK+ window with WebKit, akin to GtkLauncher"), NULL }, | 92 | N_("Plain GTK+ window with WebKit, akin to GtkLauncher"), NULL }, |
467 | 90 | { "diagnostic-dialog", 'd', 0, G_OPTION_ARG_NONE, &diagnostic_dialog, | 93 | { "diagnostic-dialog", 'd', 0, G_OPTION_ARG_NONE, &diagnostic_dialog, |
468 | @@ -118,6 +121,7 @@ | |||
469 | 118 | config = NULL; | 121 | config = NULL; |
470 | 119 | private = FALSE; | 122 | private = FALSE; |
471 | 120 | portable = FALSE; | 123 | portable = FALSE; |
472 | 124 | test = NULL; | ||
473 | 121 | plain = FALSE; | 125 | plain = FALSE; |
474 | 122 | run = FALSE; | 126 | run = FALSE; |
475 | 123 | snapshot = NULL; | 127 | snapshot = NULL; |
476 | @@ -287,6 +291,52 @@ | |||
477 | 287 | return 0; | 291 | return 0; |
478 | 288 | } | 292 | } |
479 | 289 | 293 | ||
480 | 294 | if (test != NULL) | ||
481 | 295 | { | ||
482 | 296 | g_assert (g_module_supported ()); | ||
483 | 297 | |||
484 | 298 | GModule* module = g_module_open (test, G_MODULE_BIND_LOCAL); | ||
485 | 299 | if (module == NULL) | ||
486 | 300 | g_error (_("Failed to load %s."), test); | ||
487 | 301 | |||
488 | 302 | midori_test_init (&argc, &argv); | ||
489 | 303 | |||
490 | 304 | typedef void (*extension_test_func)(void); | ||
491 | 305 | extension_test_func extension_test; | ||
492 | 306 | /* Midori.Extension */ | ||
493 | 307 | typedef GObject* (*extension_init_func)(void); | ||
494 | 308 | extension_init_func extension_init; | ||
495 | 309 | /* WebKit.WebExtension */ | ||
496 | 310 | typedef void (*webkit_web_extension_initialize_func)(GObject* extension); | ||
497 | 311 | webkit_web_extension_initialize_func web_extension_init; | ||
498 | 312 | |||
499 | 313 | if (g_module_symbol (module, "extension_init", | ||
500 | 314 | (gpointer) &extension_init)) | ||
501 | 315 | { | ||
502 | 316 | /* It's fine to conditionally return no extension */ | ||
503 | 317 | if (!(extension_init ())) | ||
504 | 318 | return 0; | ||
505 | 319 | midori_paths_init (MIDORI_RUNTIME_MODE_NORMAL, NULL); | ||
506 | 320 | |||
507 | 321 | /* Not all extensions have unit tests :-( */ | ||
508 | 322 | if (!g_module_symbol (module, "extension_test", (gpointer) &extension_test)) | ||
509 | 323 | return 0; | ||
510 | 324 | } | ||
511 | 325 | else if (g_module_symbol (module, "webkit_web_extension_initialize", | ||
512 | 326 | (gpointer) &web_extension_init) | ||
513 | 327 | || g_module_symbol (module, "webkit_web_extension_initialize_with_user_data", | ||
514 | 328 | (gpointer) &web_extension_init)) | ||
515 | 329 | { | ||
516 | 330 | if (!g_module_symbol (module, "extension_test", (gpointer) &extension_test)) | ||
517 | 331 | g_error (_("%s doesn't provide unit tests."), test); | ||
518 | 332 | } | ||
519 | 333 | else | ||
520 | 334 | g_error (_("%s doesn't look like a Midori extension."), test); | ||
521 | 335 | |||
522 | 336 | extension_test (); | ||
523 | 337 | return g_test_run (); | ||
524 | 338 | } | ||
525 | 339 | |||
526 | 290 | if (plain) | 340 | if (plain) |
527 | 291 | { | 341 | { |
528 | 292 | GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL); | 342 | GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL); |