Merge tag '0.4.4' into upstream-unstable

Bump version to 0.4.4
This commit is contained in:
Yves-Alexis Perez 2012-03-08 23:42:16 +01:00
commit 6ae8631809
78 changed files with 25888 additions and 20487 deletions

View file

@ -1,5 +1,31 @@
This file is licensed under the terms of the expat license, see the file EXPAT. This file is licensed under the terms of the expat license, see the file EXPAT.
v0.4.4:
+ Disable page cache with < 352 MB RAM
+ Display filename in download dialog
+ Fix box packing in GTK+3 (in most cases)
+ Enable experimental HTML5 fullscreen API
+ Harden IPv6 address recognition in location
+ Experimental site data policy support (see FAQ)
+ Close tabs by middle clicking close button
+ Merge cookies and other data in Clear Private Data
+ Improve KatzeArrayAction for Unity menuproxy compatibility
+ Use GDateTime for history to avoid broken C runtimes
+ Add Midori tag to DuckDuckGo default URI
+ Rewrite completion popup resizing
+ Streamline page icon loading stages and fallbacks
+ Disable clipboard work-around for WebKit >= 1.4.3
+ Re-word .desktop entry as an action
+ Display informative text in private browsing
+ Consistent clear icons in entries
+ Revised download filename generation
+ Add 'Open in Image Viewer' menu item
+ Formhistory 2.0 with GDOM support
+ Handle javascript: and mailto: links better
+ Handle = key in Ukrainian layout better
+ Fix bookmark export and deletion of bookmark folders
+ Speed dial shortcut re-reordering by DND
v0.4.3: v0.4.3:
+ Implement about:widgets to test rendering + Implement about:widgets to test rendering
+ Fix resizing of inspector by applying a minimum size + Fix resizing of inspector by applying a minimum size

View file

@ -67,6 +67,8 @@ If you want to "dry run" without WebKitGTK+ rendering, try this:
'MIDORI_UNARMED=1 _build_/default/midori/midori' 'MIDORI_UNARMED=1 _build_/default/midori/midori'
To disable Netscape plugins, use MOZ_PLUGIN_PATH=/.
To debug extensions you can specify the path: To debug extensions you can specify the path:
'export MIDORI_EXTENSION_PATH=_build_/default/extensions' 'export MIDORI_EXTENSION_PATH=_build_/default/extensions'

57
data/about.css Normal file
View file

@ -0,0 +1,57 @@
/*
about: page style template for Midori.
This file is licensed under the terms of the expat license, see the file EXPAT.
*/
body {
background-color: #eee;
margin: 0;
padding: 0;
}
#container {
background: #f6fff3;
min-width: 70%;
max-width: 70%;
margin: 2em auto 1em;
padding: 1em;
border: 0.2em solid #9acb7f;
-webkit-border-radius: 1em;
}
icon {
float: left;
padding-left: 1%;
padding-top: 1%;
}
#main {
float: right;
width: 90%;
}
h1 {
font-size: 1.4em;
font-weight: bold;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
#logo {
position: absolute; right: 15px; bottom: 15px;
z-index: -1;
}
button span,
button img {
vertical-align: middle;
padding: 2px 1px;
}
message {
font-size: 1.1em;
}
description {
font-size: 1em;
}

View file

@ -2,67 +2,11 @@
Error page template for Midori. Error page template for Midori.
This file is licensed under the terms of the expat license, see the file EXPAT. This file is licensed under the terms of the expat license, see the file EXPAT.
--> -->
<html> <html>
<head> <head>
<title>{title}</title> <title>{title}</title>
<link rel="shortcut icon" href="{icon}" /> <link rel="shortcut icon" href="{icon}" />
<style type="text/css"> <link rel="stylesheet" type="text/css" href="res://about.css" />
body {
background-color: #eee;
margin: 0;
padding: 0;
}
#container {
background: #f6fff3;
min-width: 70%;
max-width: 70%;
margin: 2em auto 1em;
padding: 1em;
border: 0.2em solid #9acb7f;
-webkit-border-radius: 1em;
}
icon {
float: left;
padding-left: 1%;
padding-top: 1%;
}
#main {
float: right;
width: 90%;
}
h1 {
font-size: 1.4em;
font-weight: bold;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
#logo {
position: absolute; right: 15px; bottom: 15px;
z-index: -1;
}
button span,
button img {
vertical-align: middle;
padding: 2px 1px;
}
message {
font-size: 1.1em;
}
description {
font-size: 1em;
}
</style>
</head> </head>
<body> <body>
<div id="container"> <div id="container">

View file

@ -3,7 +3,7 @@ Version=1.0
Type=Application Type=Application
_Name=Midori _Name=Midori
_GenericName=Web Browser _GenericName=Web Browser
_Comment=Lightweight web browser _Comment=Browse the Web
_X-GNOME-Keywords=Internet;WWW;Explorer _X-GNOME-Keywords=Internet;WWW;Explorer
_X-AppInstall-Keywords=Internet;WWW;Explorer _X-AppInstall-Keywords=Internet;WWW;Explorer
Categories=GTK;Network;WebBrowser; Categories=GTK;Network;WebBrowser;

View file

@ -55,10 +55,7 @@
width: 85%; width: 85%;
height: 75%; height: 75%;
margin: auto; margin: auto;
-webkit-box-shadow: 0 4px 18px rgba(0,0,0,.3), 0 0 2px #fff inset; -webkit-box-shadow: 0 2px 5px rgba(0,0,0,.3), 0 0 0px #fff inset;
background-image: -webkit-gradient(
linear, center top, center bottom,
from(#f6f6f6), to(#e3e3e3));
border: 1px solid #bcbcbc; border: 1px solid #bcbcbc;
border-bottom-color: #a0a0a0; border-bottom-color: #a0a0a0;
position: relative; position: relative;
@ -75,9 +72,15 @@
div.shortcut .preview.new .add { div.shortcut .preview.new .add {
display: block; display: block;
height: 100%; height: 100%;
width: 50%; width: 100%;
margin: 0 auto; margin: 0 auto;
cursor: pointer; cursor: pointer;
-webkit-box-shadow: 0 2px 5px rgba(0,0,0,.3), 0 0 0px #fff inset;
background-image: -webkit-gradient(
linear, center top, center bottom,
from(#f6f6f6), to(#e3e3e3));
background-repeat: repeat-x;
-webkit-border-radius: 3px;
} }
.title { .title {
@ -126,6 +129,11 @@
-webkit-border-bottom-left-radius: 10px; -webkit-border-bottom-left-radius: 10px;
visibility: hidden; visibility: hidden;
} }
.selected {
outline: 1px dotted black;
background-color: #eef;
}
</style> </style>
<script type="text/javascript"> <script type="text/javascript">
@ -196,6 +204,72 @@
return false; return false;
} }
var firstNode, secondNode;
var cursor;
var dial = document.getElementsByClassName("shortcut");
var get_dial_div = function (ele) {
var dial_div;
if (ele.nodeName == 'IMG')
dial_div = ele.parentNode.parentNode.parentNode;
if (ele.className == 'title')
dial_div = ele.parentNode;
if (ele.className.indexOf ('shortcut') != -1)
dial_dir = ele;
return dial_div;
}
var click = function (ev) {
ev.preventDefault();
var ele = ev.target;
cursor = ele.style.cursor;
ele.style.cursor = 'move';
var eparent = get_dial_div (ele);
if (eparent != undefined) {
eparent.className = 'shortcut selected';
firstNode = eparent.id;
}
document.RemoveEventListener('click', click, false);
};
var up = function (ev) {
ele = ev.target;
var eparent = get_dial_div (ele);
ele.style.cursor = cursor;
secondNode = eparent.id;
/* ommit just mere clicking the dial */
if (firstNode != secondNode && firstNode != undefined)
swap();
};
var over = function (ev) {
if (ev == undefined)
return;
var ele = ev.target;
var eparent = get_dial_div (ele);
if (firstNode != undefined)
{
eparent.className = 'shortcut selected';
for (var i = 0; i <= dial.length; i++) {
if (eparent.id != firstNode.id && dial[i].id != eparent.id) {
dial[i].className = 'shortcut';
}
}
}
ele.style.cursor = cursor;
}
function swap () {
console.log ("speed_dial-save-swap " + firstNode + " " + secondNode);
};
document.addEventListener('mousedown', click, false);
document.addEventListener('mouseup', up, false);
document.addEventListener('mouseover', over, false);
</script> </script>
</head> </head>
<body> <body>

View file

@ -1,6 +1,6 @@
/* /*
Copyright (C) 2009-2010 Christian Dywan <christian@twotoasts.de> Copyright (C) 2009-2012 Christian Dywan <christian@twotoasts.de>
Copyright (C) 2009 Alexander Butenko <a.butenka@gmail.com> Copyright (C) 2009-2012 Alexander Butenko <a.butenka@gmail.com>
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
@ -9,7 +9,6 @@
See the file COPYING for the full license text. See the file COPYING for the full license text.
*/ */
#include <midori/midori.h> #include <midori/midori.h>
#include <glib/gstdio.h> #include <glib/gstdio.h>
@ -35,13 +34,12 @@
#define adblock_debug(dmsg, darg1, darg2) /* nothing */ #define adblock_debug(dmsg, darg1, darg2) /* nothing */
#endif #endif
static GHashTable* pattern; static GHashTable* pattern = NULL;
static GHashTable* keys; static GHashTable* keys = NULL;
static GHashTable* optslist; static GHashTable* optslist = NULL;
static GHashTable* urlcache; static GHashTable* urlcache = NULL;
static GString* blockcss; static GHashTable* blockcssprivate = NULL;
static GString* blockcssprivate; static GString* blockcss = NULL;
static gchar* blockscript = NULL;
#ifdef G_ENABLE_DEBUG #ifdef G_ENABLE_DEBUG
static guint debug; static guint debug;
#endif #endif
@ -54,43 +52,83 @@ adblock_reload_rules (MidoriExtension* extension,
gboolean custom_only); gboolean custom_only);
static gchar* static gchar*
adblock_build_js (const gchar* private) adblock_build_js (const gchar* uri)
{ {
return g_strdup_printf ( gchar* domain;
const gchar* style;
GString* subdomain;
GString* code;
int cnt = 0, blockscnt = 0;
gchar** subdomains;
domain = midori_uri_parse_hostname (uri, NULL);
subdomains = g_strsplit (domain, ".", -1);
g_free (domain);
if (!subdomains)
return NULL;
code = g_string_new (
"window.addEventListener ('DOMContentLoaded'," "window.addEventListener ('DOMContentLoaded',"
"function () {" "function () {"
" if (document.getElementById('madblock'))" " if (document.getElementById('madblock'))"
" return;" " return;"
// Get just domain name from URL " public = '");
" var URL = location.href.match(/:\\/\\/(.[^/]+)/)[1];"
" var sites = new Array(); %s;" cnt = g_strv_length (subdomains) - 1;
" var public = '.madblockplaceholder ';" subdomain = g_string_new (subdomains [cnt]);
// Split domain into subdomain parts g_string_prepend_c (subdomain, '.');
" var subdomains = URL.split ('.');" cnt--;
" var hostname = subdomains [subdomains.length - 1];" while (cnt >= 0)
" var i = subdomains.length - 2;" {
// Check if any of subdomains do have blocking rules g_string_prepend (subdomain, subdomains[cnt]);
" while (i >= 0) {" if ((style = g_hash_table_lookup (blockcssprivate, subdomain->str)))
" hostname = subdomains [i] + '.' + hostname;" {
" if (sites [hostname])" g_string_append (code, style);
" public += ', ' + sites [hostname];" g_string_append_c (code, ',');
" i--;" blockscnt++;
" }" }
" public += ' {display: none !important}';" g_string_prepend_c (subdomain, '.');
cnt--;
}
g_string_free (subdomain, TRUE);
g_strfreev (subdomains);
if (blockscnt == 0)
return g_string_free (code, TRUE);
g_string_append (code,
" zz-non-existent {display: none !important}';"
" var mystyle = document.createElement('style');" " var mystyle = document.createElement('style');"
" mystyle.setAttribute('type', 'text/css');" " mystyle.setAttribute('type', 'text/css');"
" mystyle.setAttribute('id', 'madblock');" " mystyle.setAttribute('id', 'madblock');"
" mystyle.appendChild(document.createTextNode(public));" " mystyle.appendChild(document.createTextNode(public));"
" var head = document.getElementsByTagName('head')[0];" " var head = document.getElementsByTagName('head')[0];"
" if (head) head.appendChild(mystyle);" " if (head) head.appendChild(mystyle);"
"}, true);", "}, true);");
private); return g_string_free (code, FALSE);
} }
static GString* static GString*
adblock_fixup_regexp (const gchar* prefix, adblock_fixup_regexp (const gchar* prefix,
gchar* src); gchar* src);
static void
adblock_destroy_db ()
{
if (blockcss)
g_string_free (blockcss, TRUE);
blockcss = NULL;
g_hash_table_destroy (pattern);
pattern = NULL;
g_hash_table_destroy (optslist);
optslist = NULL;
g_hash_table_destroy (urlcache);
urlcache = NULL;
g_hash_table_destroy (blockcssprivate);
blockcssprivate = NULL;
}
static void static void
adblock_init_db () adblock_init_db ()
{ {
@ -106,12 +144,13 @@ adblock_init_db ()
urlcache = g_hash_table_new_full (g_str_hash, g_str_equal, urlcache = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free, (GDestroyNotify)g_free,
(GDestroyNotify)g_free); (GDestroyNotify)g_free);
blockcssprivate = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)g_free);
if (blockcss && blockcss->len > 0) if (blockcss && blockcss->len > 0)
g_string_free (blockcss, TRUE); g_string_free (blockcss, TRUE);
if (blockcssprivate && blockcssprivate->len > 0)
g_string_free (blockcssprivate, TRUE);
blockcss = g_string_new ("z-non-exist"); blockcss = g_string_new ("z-non-exist");
blockcssprivate = g_string_new ("");
} }
static void static void
@ -119,23 +158,9 @@ adblock_download_notify_status_cb (WebKitDownload* download,
GParamSpec* pspec, GParamSpec* pspec,
MidoriExtension* extension) MidoriExtension* extension)
{ {
gchar* path;
MidoriApp* app;
MidoriWebSettings* settings;
if (webkit_download_get_status (download) != WEBKIT_DOWNLOAD_STATUS_FINISHED) if (webkit_download_get_status (download) != WEBKIT_DOWNLOAD_STATUS_FINISHED)
return; return;
adblock_reload_rules (extension, FALSE);
path = g_filename_from_uri (webkit_download_get_destination_uri (download), NULL, NULL);
adblock_parse_file (path);
g_free (path);
app = midori_extension_get_app (extension);
settings = katze_object_get_object (app, "settings");
g_string_append (blockcss, " {display: none !important}\n");
midori_web_settings_add_style (settings, "adblock-blockcss", blockcss->str);
katze_assign (blockscript, adblock_build_js (blockcssprivate->str));
g_object_unref (settings);
} }
static gchar* static gchar*
@ -174,6 +199,8 @@ adblock_reload_rules (MidoriExtension* extension,
MidoriApp* app = midori_extension_get_app (extension); MidoriApp* app = midori_extension_get_app (extension);
MidoriWebSettings* settings = katze_object_get_object (app, "settings"); MidoriWebSettings* settings = katze_object_get_object (app, "settings");
if (pattern)
adblock_destroy_db ();
adblock_init_db (); adblock_init_db ();
custom_list = g_build_filename (midori_extension_get_config_dir (extension), custom_list = g_build_filename (midori_extension_get_config_dir (extension),
@ -215,7 +242,6 @@ adblock_reload_rules (MidoriExtension* extension,
g_strfreev (filters); g_strfreev (filters);
g_string_append (blockcss, " {display: none !important}\n"); g_string_append (blockcss, " {display: none !important}\n");
katze_assign (blockscript, adblock_build_js (blockcssprivate->str));
midori_web_settings_add_style (settings, "adblock-blockcss", blockcss->str); midori_web_settings_add_style (settings, "adblock-blockcss", blockcss->str);
g_object_unref (settings); g_object_unref (settings);
} }
@ -622,7 +648,9 @@ adblock_check_rule (GRegex* regex,
return FALSE; return FALSE;
} }
/* TODO: Domain opt check */ /* TODO: Domain opt check */
#ifdef G_ENABLE_DEBUG
adblock_debug ("blocked by pattern regexp=%s -- %s", g_regex_get_pattern (regex), req_uri); adblock_debug ("blocked by pattern regexp=%s -- %s", g_regex_get_pattern (regex), req_uri);
#endif
return TRUE; return TRUE;
} }
@ -769,11 +797,6 @@ adblock_resource_request_starting_cb (WebKitWebView* web_view,
if (midori_uri_is_blank (page_uri)) if (midori_uri_is_blank (page_uri))
return; return;
/* Never filter the main page itself */
if (web_frame == webkit_web_view_get_main_frame (web_view)
&& webkit_web_frame_get_load_status (web_frame) == WEBKIT_LOAD_PROVISIONAL)
return;
req_uri = webkit_network_request_get_uri (request); req_uri = webkit_network_request_get_uri (request);
if (!midori_uri_is_http (req_uri) if (!midori_uri_is_http (req_uri)
|| g_str_has_suffix (req_uri, "favicon.ico")) || g_str_has_suffix (req_uri, "favicon.ico"))
@ -932,13 +955,19 @@ adblock_window_object_cleared_cb (WebKitWebView* web_view,
JSObjectRef js_window) JSObjectRef js_window)
{ {
const char *page_uri; const char *page_uri;
gchar* script;
page_uri = webkit_web_frame_get_uri (web_frame); page_uri = webkit_web_frame_get_uri (web_frame);
/* Don't add adblock css into speeddial and about: pages */ /* Don't add adblock css into speeddial and about: pages */
if (!midori_uri_is_http (page_uri)) if (!midori_uri_is_http (page_uri))
return; return;
g_free (sokoke_js_script_eval (js_context, blockscript, NULL)); script = adblock_build_js (page_uri);
if (!script)
return;
g_free (sokoke_js_script_eval (js_context, script, NULL));
g_free (script);
} }
static void static void
@ -1089,7 +1118,9 @@ adblock_compile_regexp (GString* gpatt,
if (!g_regex_match_simple ("[\\*]", sig, G_REGEX_UNGREEDY, G_REGEX_MATCH_NOTEMPTY) && if (!g_regex_match_simple ("[\\*]", sig, G_REGEX_UNGREEDY, G_REGEX_MATCH_NOTEMPTY) &&
!g_hash_table_lookup (keys, sig)) !g_hash_table_lookup (keys, sig))
{ {
#ifdef G_ENABLE_DEBUG
adblock_debug ("sig: %s %s", sig, patt); adblock_debug ("sig: %s %s", sig, patt);
#endif
g_hash_table_insert (keys, sig, regex); g_hash_table_insert (keys, sig, regex);
g_hash_table_insert (optslist, sig, g_strdup (opts)); g_hash_table_insert (optslist, sig, g_strdup (opts));
signature_count++; signature_count++;
@ -1099,7 +1130,9 @@ adblock_compile_regexp (GString* gpatt,
if (g_regex_match_simple ("^\\*", sig, G_REGEX_UNGREEDY, G_REGEX_MATCH_NOTEMPTY) && if (g_regex_match_simple ("^\\*", sig, G_REGEX_UNGREEDY, G_REGEX_MATCH_NOTEMPTY) &&
!g_hash_table_lookup (pattern, patt)) !g_hash_table_lookup (pattern, patt))
{ {
#ifdef G_ENABLE_DEBUG
adblock_debug ("patt2: %s %s", sig, patt); adblock_debug ("patt2: %s %s", sig, patt);
#endif
g_hash_table_insert (pattern, patt, regex); g_hash_table_insert (pattern, patt, regex);
g_hash_table_insert (optslist, patt, g_strdup (opts)); g_hash_table_insert (optslist, patt, g_strdup (opts));
} }
@ -1115,7 +1148,9 @@ adblock_compile_regexp (GString* gpatt,
} }
else else
{ {
#ifdef G_ENABLE_DEBUG
adblock_debug ("patt: %s%s", patt, ""); adblock_debug ("patt: %s%s", patt, "");
#endif
/* Pattern is a regexp chars */ /* Pattern is a regexp chars */
g_hash_table_insert (pattern, patt, regex); g_hash_table_insert (pattern, patt, regex);
g_hash_table_insert (optslist, patt, g_strdup (opts)); g_hash_table_insert (optslist, patt, g_strdup (opts));
@ -1170,7 +1205,9 @@ adblock_add_url_pattern (gchar* prefix,
format_patt = adblock_fixup_regexp (prefix, patt); format_patt = adblock_fixup_regexp (prefix, patt);
#ifdef G_ENABLE_DEBUG
adblock_debug ("got: %s opts %s", format_patt->str, opts); adblock_debug ("got: %s opts %s", format_patt->str, opts);
#endif
should_free = adblock_compile_regexp (format_patt, opts); should_free = adblock_compile_regexp (format_patt, opts);
if (data[1] && data[2]) if (data[1] && data[2])
@ -1200,6 +1237,22 @@ adblock_frame_add (gchar* line)
g_string_append (blockcss, line); g_string_append (blockcss, line);
} }
static inline void
adblock_update_css_hash (gchar* domain,
gchar* value)
{
const gchar* olddata;
gchar* newdata;
if ((olddata = g_hash_table_lookup (blockcssprivate, domain)))
{
newdata = g_strconcat (olddata, " , ", value, NULL);
g_hash_table_replace (blockcssprivate, g_strdup (domain), newdata);
}
else
g_hash_table_insert (blockcssprivate, g_strdup (domain), g_strdup (value));
}
static inline void static inline void
adblock_frame_add_private (const gchar* line, adblock_frame_add_private (const gchar* line,
const gchar* sep) const gchar* sep)
@ -1234,15 +1287,13 @@ adblock_frame_add_private (const gchar* line,
/* strip ~ from domain */ /* strip ~ from domain */
if (domain[0] == '~') if (domain[0] == '~')
domain++; domain++;
g_string_append_printf (blockcssprivate, ";sites['%s']+=',%s'", adblock_update_css_hash (g_strstrip (domain), data[1]);
g_strstrip (domain), data[1]);
} }
g_strfreev (domains); g_strfreev (domains);
} }
else else
{ {
g_string_append_printf (blockcssprivate, ";sites['%s']+=',%s'", adblock_update_css_hash (data[0], data[1]);
data[0], data[1]);
} }
g_strfreev (data); g_strfreev (data);
} }
@ -1250,12 +1301,10 @@ adblock_frame_add_private (const gchar* line,
static gchar* static gchar*
adblock_parse_line (gchar* line) adblock_parse_line (gchar* line)
{ {
if (!line) /* Skip invalid, empty and comment lines */
return NULL; if (!(line && line[0] != ' ' && line[0] != '!' && line[0]))
g_strchomp (line);
/* Ignore comments and new lines */
if (line[0] == '!')
return NULL; return NULL;
/* FIXME: No support for whitelisting */ /* FIXME: No support for whitelisting */
if (line[0] == '@' && line[1] == '@') if (line[0] == '@' && line[1] == '@')
return NULL; return NULL;
@ -1263,9 +1312,7 @@ adblock_parse_line (gchar* line)
if (line[0] == '[') if (line[0] == '[')
return NULL; return NULL;
/* Skip garbage */ g_strchomp (line);
if (line[0] == ' ' || !line[0])
return NULL;
/* Got CSS block hider */ /* Got CSS block hider */
if (line[0] == '#' && line[1] == '#' ) if (line[0] == '#' && line[1] == '#' )
@ -1283,13 +1330,13 @@ adblock_parse_line (gchar* line)
adblock_frame_add_private (line, "##"); adblock_frame_add_private (line, "##");
return NULL; return NULL;
} }
/* Got per domain CSS hider rule. Workaround */ /* Got per domain CSS hider rule. Workaround */
if (strchr (line, '#')) if (strchr (line, '#'))
{ {
adblock_frame_add_private (line, "#"); adblock_frame_add_private (line, "#");
return NULL; return NULL;
} }
/* Got URL blocker rule */ /* Got URL blocker rule */
if (line[0] == '|' && line[1] == '|' ) if (line[0] == '|' && line[1] == '|' )
{ {
@ -1358,16 +1405,8 @@ adblock_deactivate_cb (MidoriExtension* extension,
browser, adblock_add_tab_cb, extension); browser, adblock_add_tab_cb, extension);
midori_browser_foreach (browser, (GtkCallback)adblock_deactivate_tabs, browser); midori_browser_foreach (browser, (GtkCallback)adblock_deactivate_tabs, browser);
if (blockcss) adblock_destroy_db ();
g_string_free (blockcss, TRUE);
if (blockcssprivate)
g_string_free (blockcssprivate, TRUE);
midori_web_settings_remove_style (settings, "adblock-blockcss"); midori_web_settings_remove_style (settings, "adblock-blockcss");
blockcssprivate = blockcss = NULL;
g_hash_table_destroy (pattern);
g_hash_table_destroy (optslist);
g_hash_table_destroy (urlcache);
g_object_unref (settings); g_object_unref (settings);
} }
@ -1498,7 +1537,7 @@ extension_init (void)
MidoriExtension* extension = g_object_new (MIDORI_TYPE_EXTENSION, MidoriExtension* extension = g_object_new (MIDORI_TYPE_EXTENSION,
"name", _("Advertisement blocker"), "name", _("Advertisement blocker"),
"description", _("Block advertisements according to a filter list"), "description", _("Block advertisements according to a filter list"),
"version", "0.5" MIDORI_VERSION_SUFFIX, "version", "0.6" MIDORI_VERSION_SUFFIX,
"authors", "Christian Dywan <christian@twotoasts.de>", "authors", "Christian Dywan <christian@twotoasts.de>",
NULL); NULL);
midori_extension_install_string_list (extension, "filters", NULL, G_MAXSIZE); midori_extension_install_string_list (extension, "filters", NULL, G_MAXSIZE);

View file

@ -48,11 +48,10 @@ colorful_tabs_view_notify_uri_cb (MidoriView* view,
if (!midori_uri_is_blank (midori_view_get_display_uri (view)) if (!midori_uri_is_blank (midori_view_get_display_uri (view))
&& (hostname = midori_uri_parse_hostname (midori_view_get_display_uri (view), NULL)) && (hostname = midori_uri_parse_hostname (midori_view_get_display_uri (view), NULL))
&& katze_object_get_enum (view, "load-status") == MIDORI_LOAD_FINISHED) && midori_view_get_icon_uri (view) != NULL)
{ {
icon = midori_view_get_icon (view); icon = midori_view_get_icon (view);
if (icon != NULL)
if (midori_view_get_icon_uri (view) != NULL)
{ {
GdkPixbuf* newpix; GdkPixbuf* newpix;
guchar* pixels; guchar* pixels;

View file

@ -840,7 +840,8 @@ feed_panel_init (FeedPanel* panel)
webview = webkit_web_view_new (); webview = webkit_web_view_new ();
#if GTK_CHECK_VERSION(3,0,0) #if GTK_CHECK_VERSION(3,0,0)
font_desc = gtk_style_context_get_font(gtk_widget_get_style_context(treeview), GTK_STATE_FLAG_NORMAL); font_desc = (PangoFontDescription*)gtk_style_context_get_font (
gtk_widget_get_style_context (treeview), GTK_STATE_FLAG_NORMAL);
#else #else
font_desc = treeview->style->font_desc; font_desc = treeview->style->font_desc;
#endif #endif

View file

@ -1,600 +0,0 @@
/*
Copyright (C) 2009 Alexander Butenko <a.butenka@gmail.com>
Copyright (C) 2009 Christian Dywan <christian@twotoasts.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
*/
#define MAXCHARS 60
#define MINCHARS 2
#include <midori/midori.h>
#include <glib/gstdio.h>
#include "config.h"
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
static GHashTable* global_keys;
static gchar* jsforms;
static void
formhistory_toggle_state_cb (GtkAction* action,
MidoriBrowser* browser);
static gboolean
formhistory_prepare_js ()
{
gchar* autosuggest;
gchar* style;
guint i;
gchar* file;
file = sokoke_find_data_filename ("autosuggestcontrol.js", TRUE);
if (!g_file_get_contents (file, &autosuggest, NULL, NULL))
{
g_free (file);
return FALSE;
}
g_strchomp (autosuggest);
katze_assign (file, sokoke_find_data_filename ("autosuggestcontrol.css", TRUE));
if (!g_file_get_contents (file, &style, NULL, NULL))
{
g_free (file);
return FALSE;
}
g_strchomp (style);
i = 0;
while (style[i])
{
if (style[i] == '\n')
style[i] = ' ';
i++;
}
jsforms = g_strdup_printf (
"%s"
"window.addEventListener ('DOMContentLoaded',"
"function () {"
" if (document.getElementById('formhistory'))"
" return;"
" if (!initSuggestions ())"
" return;"
" var mystyle = document.createElement('style');"
" mystyle.setAttribute('type', 'text/css');"
" mystyle.setAttribute('id', 'formhistory');"
" mystyle.appendChild(document.createTextNode('%s'));"
" var head = document.getElementsByTagName('head')[0];"
" if (head) head.appendChild(mystyle);"
"}, true);",
autosuggest,
style);
g_strstrip (jsforms);
g_free (file);
g_free (style);
g_free (autosuggest);
return TRUE;
}
static gchar*
formhistory_fixup_value (char* value)
{
guint i = 0;
g_strchomp (value);
while (value[i])
{
if (value[i] == '\n')
value[i] = ' ';
else if (value[i] == '"')
value[i] = '\'';
i++;
}
return value;
}
static gchar*
formhistory_build_js ()
{
GString* suggestions;
GHashTableIter iter;
gpointer key, value;
suggestions = g_string_new (
"function FormSuggestions(eid) { "
"arr = new Array();");
g_hash_table_iter_init (&iter, global_keys);
while (g_hash_table_iter_next (&iter, &key, &value))
{
g_string_append_printf (suggestions, " arr[\"%s\"] = [%s]; ",
(gchar*)key, (gchar*)value);
}
g_string_append (suggestions, "this.suggestions = arr[eid]; }");
g_string_append (suggestions, jsforms);
return g_string_free (suggestions, FALSE);
}
static void
formhistory_update_database (gpointer db,
const gchar* key,
const gchar* value)
{
gchar* sqlcmd;
gchar* errmsg;
gint success;
sqlcmd = sqlite3_mprintf ("INSERT INTO forms VALUES"
"('%q', '%q', '%q')",
NULL, key, value);
success = sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg);
sqlite3_free (sqlcmd);
if (success != SQLITE_OK)
{
g_printerr (_("Failed to add form value: %s\n"), errmsg);
g_free (errmsg);
return;
}
}
static gboolean
formhistory_update_main_hash (gchar* key,
gchar* value)
{
guint length;
gchar* tmp;
if (!(value && *value))
return FALSE;
length = strlen (value);
if (length > MAXCHARS || length < MINCHARS)
return FALSE;
formhistory_fixup_value (key);
formhistory_fixup_value (value);
if ((tmp = g_hash_table_lookup (global_keys, (gpointer)key)))
{
gchar* rvalue = g_strdup_printf ("\"%s\"",value);
gchar* patt = g_regex_escape_string (rvalue, -1);
if (!g_regex_match_simple (patt, tmp,
G_REGEX_CASELESS, G_REGEX_MATCH_NOTEMPTY))
{
gchar* new_value = g_strdup_printf ("%s%s,", tmp, rvalue);
g_hash_table_insert (global_keys, g_strdup (key), new_value);
g_free (rvalue);
g_free (patt);
}
else
{
g_free (rvalue);
g_free (patt);
return FALSE;
}
}
else
{
gchar* new_value = g_strdup_printf ("\"%s\",",value);
g_hash_table_replace (global_keys, g_strdup (key), new_value);
}
return TRUE;
}
static gboolean
formhistory_navigation_decision_cb (WebKitWebView* web_view,
WebKitWebFrame* web_frame,
WebKitNetworkRequest* request,
WebKitWebNavigationAction* action,
WebKitWebPolicyDecision* decision,
MidoriExtension* extension)
{
/* The script returns form data in the form "field_name|,|value|,|field_type".
We are handling only input fields with 'text' or 'password' type.
The field separator is "|||" */
const gchar* script = "function dumpForm (inputs) {"
" var out = '';"
" for (i=0;i<inputs.length;i++) {"
" if (inputs[i].getAttribute('autocomplete') == 'off')"
" continue;"
" if (inputs[i].value && (inputs[i].type == 'text' || inputs[i].type == 'password')) {"
" var ename = inputs[i].getAttribute('name');"
" var eid = inputs[i].getAttribute('id');"
" if (!ename && eid)"
" ename=eid;"
" if (inputs[i].getAttribute('autocomplete') != 'off')"
" out += ename+'|,|'+inputs[i].value +'|,|'+inputs[i].type +'|||';"
" }"
" }"
" return out;"
"}"
"dumpForm (document.getElementsByTagName('input'))";
if (webkit_web_navigation_action_get_reason (action) == WEBKIT_WEB_NAVIGATION_REASON_FORM_SUBMITTED)
{
JSContextRef js_context = webkit_web_frame_get_global_context (web_frame);
gchar* value = sokoke_js_script_eval (js_context, script, NULL);
if (value && *value)
{
gpointer db = g_object_get_data (G_OBJECT (extension), "formhistory-db");
gchar** inputs = g_strsplit (value, "|||", 0);
guint i = 0;
while (inputs[i] != NULL)
{
gchar** parts = g_strsplit (inputs[i], "|,|", 3);
if (parts && parts[0] && parts[1] && parts[2])
{
/* FIXME: We need to handle passwords */
if (strcmp (parts[2], "password"))
{
if (formhistory_update_main_hash (parts[0], parts[1]))
formhistory_update_database (db, parts[0], parts[1]);
}
}
g_strfreev (parts);
i++;
}
g_strfreev (inputs);
g_free (value);
}
}
return FALSE;
}
static void
formhistory_window_object_cleared_cb (WebKitWebView* web_view,
WebKitWebFrame* web_frame,
JSContextRef js_context,
JSObjectRef js_window)
{
gchar* script;
const gchar* page_uri;
page_uri = webkit_web_frame_get_uri (web_frame);
if (!midori_uri_is_http (page_uri))
return;
script = formhistory_build_js ();
sokoke_js_script_eval (js_context, script, NULL);
g_free (script);
}
static void
formhistory_add_tab_cb (MidoriBrowser* browser,
MidoriView* view,
MidoriExtension* extension)
{
GtkWidget* web_view = midori_view_get_web_view (view);
g_signal_connect (web_view, "window-object-cleared",
G_CALLBACK (formhistory_window_object_cleared_cb), NULL);
g_signal_connect (web_view, "navigation-policy-decision-requested",
G_CALLBACK (formhistory_navigation_decision_cb), extension);
}
static void
formhistory_deactivate_cb (MidoriExtension* extension,
MidoriBrowser* browser);
static void
formhistory_add_tab_foreach_cb (MidoriView* view,
MidoriBrowser* browser,
MidoriExtension* extension)
{
formhistory_add_tab_cb (browser, view, extension);
}
static void
formhistory_app_add_browser_cb (MidoriApp* app,
MidoriBrowser* browser,
MidoriExtension* extension)
{
GtkAccelGroup* acg = gtk_accel_group_new ();
GtkActionGroup* action_group = midori_browser_get_action_group (browser);
GtkAction* action = gtk_action_new ("FormHistoryToggleState",
_("Toggle form history state"),
_("Activate or deactivate form history for the current tab."), NULL);
gtk_window_add_accel_group (GTK_WINDOW (browser), acg);
g_object_set_data (G_OBJECT (browser), "FormHistoryExtension", extension);
g_signal_connect (action, "activate",
G_CALLBACK (formhistory_toggle_state_cb), browser);
gtk_action_group_add_action_with_accel (action_group, action, "<Ctrl><Shift>F");
gtk_action_set_accel_group (action, acg);
gtk_action_connect_accelerator (action);
if (midori_extension_get_boolean (extension, "always-load"))
{
midori_browser_foreach (browser,
(GtkCallback)formhistory_add_tab_foreach_cb, extension);
g_signal_connect (browser, "add-tab",
G_CALLBACK (formhistory_add_tab_cb), extension);
}
g_signal_connect (extension, "deactivate",
G_CALLBACK (formhistory_deactivate_cb), browser);
}
static void
formhistory_deactivate_tabs (MidoriView* view,
MidoriBrowser* browser,
MidoriExtension* extension)
{
GtkWidget* web_view = midori_view_get_web_view (view);
g_signal_handlers_disconnect_by_func (
web_view, formhistory_window_object_cleared_cb, NULL);
g_signal_handlers_disconnect_by_func (
web_view, formhistory_navigation_decision_cb, extension);
}
static void
formhistory_deactivate_cb (MidoriExtension* extension,
MidoriBrowser* browser)
{
MidoriApp* app = midori_extension_get_app (extension);
sqlite3* db;
GtkActionGroup* action_group = midori_browser_get_action_group (browser);
GtkAction* action;
g_signal_handlers_disconnect_by_func (
browser, formhistory_add_tab_cb, extension);
g_signal_handlers_disconnect_by_func (
extension, formhistory_deactivate_cb, browser);
g_signal_handlers_disconnect_by_func (
app, formhistory_app_add_browser_cb, extension);
midori_browser_foreach (browser,
(GtkCallback)formhistory_deactivate_tabs, extension);
g_object_set_data (G_OBJECT (browser), "FormHistoryExtension", NULL);
action = gtk_action_group_get_action ( action_group, "FormHistoryToggleState");
if (action != NULL)
{
gtk_action_group_remove_action (action_group, action);
g_object_unref (action);
}
katze_assign (jsforms, NULL);
if (global_keys)
g_hash_table_destroy (global_keys);
if ((db = g_object_get_data (G_OBJECT (extension), "formhistory-db")))
sqlite3_close (db);
}
static int
formhistory_add_field (gpointer data,
int argc,
char** argv,
char** colname)
{
gint i;
gint ncols = 3;
/* Test whether have the right number of columns */
g_return_val_if_fail (argc % ncols == 0, 1);
for (i = 0; i < (argc - ncols) + 1; i++)
{
if (argv[i])
{
if (colname[i] && !g_ascii_strcasecmp (colname[i], "domain")
&& colname[i + 1] && !g_ascii_strcasecmp (colname[i + 1], "field")
&& colname[i + 2] && !g_ascii_strcasecmp (colname[i + 2], "value"))
{
gchar* key = argv[i + 1];
formhistory_update_main_hash (g_strdup (key), g_strdup (argv[i + 2]));
}
}
}
return 0;
}
static void
formhistory_activate_cb (MidoriExtension* extension,
MidoriApp* app)
{
const gchar* config_dir;
gchar* filename;
sqlite3* db;
char* errmsg = NULL, *errmsg2 = NULL;
KatzeArray* browsers;
MidoriBrowser* browser;
global_keys = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)g_free);
if(!jsforms)
formhistory_prepare_js ();
config_dir = midori_extension_get_config_dir (extension);
katze_mkdir_with_parents (config_dir, 0700);
filename = g_build_filename (config_dir, "forms.db", NULL);
if (sqlite3_open (filename, &db) != SQLITE_OK)
{
/* If the folder is /, this is a test run, thus no error */
if (!g_str_equal (midori_extension_get_config_dir (extension), "/"))
g_warning (_("Failed to open database: %s\n"), sqlite3_errmsg (db));
sqlite3_close (db);
}
g_free (filename);
if ((sqlite3_exec (db, "CREATE TABLE IF NOT EXISTS "
"forms (domain text, field text, value text)",
NULL, NULL, &errmsg) == SQLITE_OK)
&& (sqlite3_exec (db, "SELECT domain, field, value FROM forms ",
formhistory_add_field,
NULL, &errmsg2) == SQLITE_OK))
g_object_set_data (G_OBJECT (extension), "formhistory-db", db);
else
{
if (errmsg)
{
g_critical (_("Failed to execute database statement: %s\n"), errmsg);
sqlite3_free (errmsg);
if (errmsg2)
{
g_critical (_("Failed to execute database statement: %s\n"), errmsg2);
sqlite3_free (errmsg2);
}
}
sqlite3_close (db);
}
browsers = katze_object_get_object (app, "browsers");
KATZE_ARRAY_FOREACH_ITEM (browser, browsers)
formhistory_app_add_browser_cb (app, browser, extension);
g_signal_connect (app, "add-browser",
G_CALLBACK (formhistory_app_add_browser_cb), extension);
g_object_unref (browsers);
}
static void
formhistory_preferences_response_cb (GtkWidget* dialog,
gint response_id,
MidoriExtension* extension)
{
GtkWidget* checkbox;
gboolean old_state;
gboolean new_state;
MidoriApp* app;
KatzeArray* browsers;
MidoriBrowser* browser;
if (response_id == GTK_RESPONSE_APPLY)
{
checkbox = g_object_get_data (G_OBJECT (dialog), "always-load-checkbox");
new_state = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox));
old_state = midori_extension_get_boolean (extension, "always-load");
if (old_state != new_state)
{
midori_extension_set_boolean (extension, "always-load", new_state);
app = midori_extension_get_app (extension);
browsers = katze_object_get_object (app, "browsers");
KATZE_ARRAY_FOREACH_ITEM (browser, browsers)
{
midori_browser_foreach (browser,
(GtkCallback)formhistory_deactivate_tabs, extension);
g_signal_handlers_disconnect_by_func (
browser, formhistory_add_tab_cb, extension);
if (new_state)
{
midori_browser_foreach (browser,
(GtkCallback)formhistory_add_tab_foreach_cb, extension);
g_signal_connect (browser, "add-tab",
G_CALLBACK (formhistory_add_tab_cb), extension);
}
}
}
}
gtk_widget_destroy (dialog);
}
static void
formhistory_preferences_cb (MidoriExtension* extension)
{
GtkWidget* dialog;
GtkWidget* content_area;
GtkWidget* checkbox;
dialog = gtk_dialog_new ();
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_APPLY, GTK_RESPONSE_APPLY);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
checkbox = gtk_check_button_new_with_label (_("only activate form history via hotkey (Ctrl+Shift+F) per tab"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbox),
!midori_extension_get_boolean (extension, "always-load"));
g_object_set_data (G_OBJECT (dialog), "always-load-checkbox", checkbox);
gtk_container_add (GTK_CONTAINER (content_area), checkbox);
g_signal_connect (dialog,
"response",
G_CALLBACK (formhistory_preferences_response_cb),
extension);
gtk_widget_show_all (dialog);
}
static void
formhistory_toggle_state_cb (GtkAction* action,
MidoriBrowser* browser)
{
MidoriView* view = MIDORI_VIEW (midori_browser_get_current_tab (browser));
MidoriExtension* extension = g_object_get_data (G_OBJECT (browser), "FormHistoryExtension");
GtkWidget* web_view = midori_view_get_web_view (view);
if (g_signal_handler_find (web_view, G_SIGNAL_MATCH_FUNC,
g_signal_lookup ("window-object-cleared", MIDORI_TYPE_VIEW), 0, NULL,
formhistory_window_object_cleared_cb, extension))
{
formhistory_deactivate_tabs (view, browser, extension);
} else {
formhistory_add_tab_cb (browser, view, extension);
}
}
#if G_ENABLE_DEBUG
/*
<html>
<head>
<title>autosuggest testcase</title>
</head>
<body>
<form method=post>
<p><input type="text" id="txt1" /></p>
<p><input type="text" name="txt2" /></p>
<input type=submit>
</form>
</body>
</html> */
#endif
MidoriExtension*
extension_init (void)
{
gboolean should_init = TRUE;
const gchar* ver;
gchar* desc;
MidoriExtension* extension;
if (formhistory_prepare_js ())
{
ver = "1.0" MIDORI_VERSION_SUFFIX;
desc = g_strdup (_("Stores history of entered form data"));
}
else
{
desc = g_strdup_printf (_("Not available: %s"),
_("Resource files not installed"));
ver = NULL;
should_init = FALSE;
}
extension = g_object_new (MIDORI_TYPE_EXTENSION,
"name", _("Form history filler"),
"description", desc,
"version", ver,
"authors", "Alexander V. Butenko <a.butenka@gmail.com>",
NULL);
g_free (desc);
if (should_init)
{
midori_extension_install_boolean (extension, "always-load", TRUE);
g_signal_connect (extension, "activate",
G_CALLBACK (formhistory_activate_cb), NULL);
g_signal_connect (extension, "open-preferences",
G_CALLBACK (formhistory_preferences_cb), NULL);
}
return extension;
}

View file

@ -0,0 +1,74 @@
/*
Copyright (C) 2009-2012 Alexander Butenko <a.butenka@gmail.com>
Copyright (C) 2009-2012 Christian Dywan <christian@twotoasts.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
*/
#ifndef __FORMHISTORY_FRONTEND_H__
#define __FORMHISTORY_FRONTEND_H__
#include <midori/midori.h>
#include <glib/gstdio.h>
#include "config.h"
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if WEBKIT_CHECK_VERSION (1, 3, 1)
#define FORMHISTORY_USE_GDOM 1
#else
#define FORMHISTORY_USE_JS 1
#endif
#define MAXPASSSIZE 64
typedef struct
{
sqlite3* db;
#ifdef FORMHISTORY_USE_GDOM
WebKitDOMElement* element;
int completion_timeout;
GtkTreeModel* completion_model;
GtkWidget* treeview;
GtkWidget* popup;
gchar* oldkeyword;
glong selection_index;
#else
gchar* jsforms;
#endif
gchar* master_password;
int master_password_canceled;
} FormHistoryPriv;
typedef struct
{
gchar* domain;
gchar* form_data;
FormHistoryPriv* priv;
} FormhistoryPasswordEntry;
FormHistoryPriv*
formhistory_private_new ();
void
formhistory_private_destroy (FormHistoryPriv *priv);
gboolean
formhistory_construct_popup_gui (FormHistoryPriv* priv);
void
formhistory_setup_suggestions (WebKitWebView* web_view,
JSContextRef js_context,
MidoriExtension* extension);
#ifdef FORMHISTORY_USE_GDOM
void
formhistory_suggestions_hide_cb (WebKitDOMElement* element,
WebKitDOMEvent* dom_event,
FormHistoryPriv* priv);
#endif
#endif

View file

@ -0,0 +1,516 @@
/*
Copyright (C) 2009-2012 Alexander Butenko <a.butenka@gmail.com>
Copyright (C) 2009-2012 Christian Dywan <christian@twotoasts.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
*/
#include "formhistory-frontend.h"
#ifdef FORMHISTORY_USE_GDOM
#define COMPLETION_DELAY 200
FormHistoryPriv*
formhistory_private_new ()
{
FormHistoryPriv* priv;
priv = g_slice_new (FormHistoryPriv);
priv->oldkeyword = g_strdup ("");
priv->selection_index = -1;
return priv;
}
void
formhistory_suggestions_hide_cb (WebKitDOMElement* element,
WebKitDOMEvent* dom_event,
FormHistoryPriv* priv)
{
if (gtk_widget_get_visible (priv->popup))
gtk_widget_hide (priv->popup);
priv->selection_index = -1;
}
static void
formhistory_suggestion_set (GtkTreePath* path,
FormHistoryPriv* priv)
{
GtkTreeIter iter;
gchar* value;
if (!gtk_tree_model_get_iter (priv->completion_model, &iter, path))
return;
gtk_tree_model_get (priv->completion_model, &iter, 0, &value, -1);
g_object_set (priv->element, "value", value, NULL);
g_free (value);
}
static gboolean
formhistory_suggestion_selected_cb (GtkWidget* treeview,
GdkEventButton* event,
FormHistoryPriv* priv)
{
GtkTreePath* path;
if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (treeview),
event->x, event->y, &path, NULL, NULL, NULL))
{
formhistory_suggestion_set (path, priv);
formhistory_suggestions_hide_cb (NULL, NULL, priv);
gtk_tree_path_free (path);
return TRUE;
}
return FALSE;
}
static void
formhistory_suggestion_remove (GtkTreePath* path,
FormHistoryPriv* priv)
{
GtkTreeIter iter;
gchar* sqlcmd;
char* errmsg = NULL;
gchar* name;
gchar* value;
if (!gtk_tree_model_get_iter (priv->completion_model, &iter, path))
return;
if (!priv->db)
return;
gtk_tree_model_get (priv->completion_model, &iter, 0, &value, -1);
g_object_get (priv->element, "name", &name, NULL);
gtk_list_store_remove (GTK_LIST_STORE (priv->completion_model), &iter);
sqlcmd = sqlite3_mprintf ("DELETE FROM forms WHERE field = '%q' AND value = '%q'",
name, value);
g_free (name);
g_free (value);
sqlite3_exec (priv->db, sqlcmd, NULL, NULL, &errmsg);
sqlite3_free (sqlcmd);
}
static void
get_absolute_offset_for_element (WebKitDOMElement* element,
WebKitDOMDocument* element_document,
WebKitDOMNodeList* frames,
glong* x,
glong* y,
gboolean ismainframe)
{
WebKitDOMElement* offset_parent;
gint offset_top = 0, offset_left = 0;
gulong i;
g_object_get (element, "offset-left", &offset_left,
"offset-top", &offset_top,
"offset-parent", &offset_parent,
NULL);
*x += offset_left;
*y += offset_top;
/* To avoid deadlock check only first element of the mainframe parent */
if (ismainframe == TRUE)
return;
if (offset_parent)
goto finish;
/* Element havent returned any parents. Thats mean or there is no parents or we are inside the frame
Loop over all frames we have to find frame == element_document which is a root for our element
and get its offsets */
for (i = 0; i < webkit_dom_node_list_get_length (frames); i++)
{
WebKitDOMDocument *fdoc;
WebKitDOMNode *frame = webkit_dom_node_list_item (frames, i);
if (WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (frame))
fdoc = webkit_dom_html_iframe_element_get_content_document (WEBKIT_DOM_HTML_IFRAME_ELEMENT (frame));
else
fdoc = webkit_dom_html_frame_element_get_content_document (WEBKIT_DOM_HTML_FRAME_ELEMENT (frame));
if (fdoc == element_document)
{
offset_parent = WEBKIT_DOM_ELEMENT (frame);
ismainframe = TRUE;
/* Add extra 4px to ~cover size of borders */
*y += 4;
break;
}
}
finish:
if (offset_parent)
get_absolute_offset_for_element (offset_parent, element_document, frames, x, y, ismainframe);
}
static void
formhistory_reposition_popup (FormHistoryPriv* priv)
{
WebKitDOMDocument* element_document;
WebKitDOMNodeList* frames;
GtkWidget* view;
GdkWindow* window;
GtkWidget* toplevel;
gint rx, ry;
gint wx, wy;
glong x = 0, y = 0;
glong height;
view = g_object_get_data (G_OBJECT (priv->element), "webview");
toplevel = gtk_widget_get_toplevel (view);
/* Position of a root window */
window = gtk_widget_get_window (toplevel);
gdk_window_get_position (window, &rx, &ry);
/* Postion of webview in root window */
window = gtk_widget_get_window (view);
gdk_window_get_position (window, &wx, &wy);
/* Position of editbox on the webview */
frames = g_object_get_data (G_OBJECT (priv->element), "framelist");
element_document = g_object_get_data (G_OBJECT (priv->element), "doc");
get_absolute_offset_for_element (priv->element, element_document, frames, &x, &y, FALSE);
/* Add height as menu should start under editbox, now on top of it */
g_object_get (priv->element, "client-height", &height, NULL);
y += height + 1;
gtk_window_move (GTK_WINDOW (priv->popup), rx + wx + x, ry +wy + y);
/* Window configuration */
gtk_window_set_screen (GTK_WINDOW (priv->popup), gtk_widget_get_screen (view));
gtk_window_set_transient_for (GTK_WINDOW (priv->popup), GTK_WINDOW (toplevel));
gtk_tree_view_columns_autosize (GTK_TREE_VIEW (priv->treeview));
/* FIXME: Adjust size according to treeview width and some reasonable height */
gtk_window_resize (GTK_WINDOW (priv->popup), 50, 80);
}
static gboolean
formhistory_suggestions_show (FormHistoryPriv* priv)
{
GtkListStore* store;
static sqlite3_stmt* stmt;
gchar* value, * name;
const char* sqlcmd;
gint result;
gchar* likedvalue;
int pos = 0;
g_return_val_if_fail (priv->element, FALSE);
g_object_get (priv->element,
"name", &name,
"value", &value,
NULL);
katze_assign (priv->oldkeyword, g_strdup (value));
if (!priv->popup)
formhistory_construct_popup_gui (priv);
if (!stmt)
{
if (!priv->db)
goto free_data;
sqlcmd = "SELECT DISTINCT value FROM forms WHERE field = ?1 and value like ?2";
sqlite3_prepare_v2 (priv->db, sqlcmd, strlen (sqlcmd) + 1, &stmt, NULL);
}
likedvalue = g_strdup_printf ("%s%%", value);
sqlite3_bind_text (stmt, 1, name, -1, NULL);
sqlite3_bind_text (stmt, 2, likedvalue, -1, g_free);
result = sqlite3_step (stmt);
if (result != SQLITE_ROW)
{
if (result == SQLITE_ERROR)
g_print (_("Failed to select suggestions\n"));
sqlite3_reset (stmt);
sqlite3_clear_bindings (stmt);
formhistory_suggestions_hide_cb (NULL, NULL, priv);
goto free_data;
}
store = GTK_LIST_STORE (priv->completion_model);
gtk_list_store_clear (store);
while (result == SQLITE_ROW)
{
const unsigned char* text = sqlite3_column_text (stmt, 0);
pos++;
gtk_list_store_insert_with_values (store, NULL, pos, 0, text, -1);
result = sqlite3_step (stmt);
}
sqlite3_reset (stmt);
sqlite3_clear_bindings (stmt);
if (!gtk_widget_get_visible (priv->popup))
{
formhistory_reposition_popup (priv);
gtk_widget_show_all (priv->popup);
}
free_data:
g_free (name);
g_free (value);
return FALSE;
}
static void
formhistory_editbox_key_pressed_cb (WebKitDOMElement* element,
WebKitDOMEvent* dom_event,
FormHistoryPriv* priv)
{
glong key;
GtkTreePath* path;
gchar* keyword;
gint matches;
/* FIXME: Priv is still set after module is disabled */
g_return_if_fail (priv);
g_return_if_fail (element);
if (priv->completion_timeout > 0)
g_source_remove (priv->completion_timeout);
katze_object_assign (priv->element, g_object_ref (element));
key = webkit_dom_ui_event_get_key_code (WEBKIT_DOM_UI_EVENT (dom_event));
switch (key)
{
/* ESC key*/
case 27:
case 35:
case 36:
/* Left key*/
case 37:
/* Right key*/
case 39:
/* Enter key*/
case 13:
if (key == 27)
g_object_set (element, "value", priv->oldkeyword, NULL);
formhistory_suggestions_hide_cb (element, dom_event, priv);
return;
break;
/* Del key */
case 46:
/* Up key */
case 38:
/* Down key */
case 40:
if (!gtk_widget_get_visible (priv->popup))
{
formhistory_suggestions_show (priv);
return;
}
matches = gtk_tree_model_iter_n_children (priv->completion_model, NULL);
if (key == 38)
{
if (priv->selection_index <= 0)
priv->selection_index = matches - 1;
else
priv->selection_index = MAX (priv->selection_index - 1, 0);
}
else if (key == 40)
{
if (priv->selection_index == matches - 1)
priv->selection_index = 0;
else
priv->selection_index = MIN (priv->selection_index + 1, matches -1);
}
if (priv->selection_index == -1)
{
/* No element is selected */
return;
}
path = gtk_tree_path_new_from_indices (priv->selection_index, -1);
if (key == 46)
{
g_object_set (element, "value", priv->oldkeyword, NULL);
formhistory_suggestion_remove (path, priv);
matches--;
}
if (matches == 0)
formhistory_suggestions_hide_cb (element, dom_event, priv);
else
{
gtk_tree_view_set_cursor (GTK_TREE_VIEW (priv->treeview), path, NULL, FALSE);
formhistory_suggestion_set (path, priv);
}
gtk_tree_path_free (path);
return;
break;
/* PgUp, PgDn, Ins */
case 33:
case 34:
case 45:
/* Shift, Ctrl, Alt, Tab, Caps Lock*/
case 16:
case 17:
case 18:
case 20:
case 9:
return;
break;
}
g_object_get (element, "value", &keyword, NULL);
if (!(keyword && *keyword && *keyword != ' '))
{
formhistory_suggestions_hide_cb (element, dom_event, priv);
goto free_data;
}
/* If the same keyword is submitted there's no need to regenerate suggestions */
if (gtk_widget_get_visible (priv->popup) &&
!g_strcmp0 (keyword, priv->oldkeyword))
goto free_data;
priv->completion_timeout = g_timeout_add (COMPLETION_DELAY,
(GSourceFunc)formhistory_suggestions_show, priv);
free_data:
g_free (keyword);
}
static void
formhistory_DOMContentLoaded_cb (WebKitDOMElement* window,
WebKitDOMEvent* dom_event,
FormHistoryPriv* priv)
{
gulong i;
WebKitDOMDocument* doc;
WebKitDOMNodeList* inputs;
WebKitDOMNodeList* frames;
GtkWidget* web_view;
if (WEBKIT_DOM_IS_DOCUMENT (window))
doc = WEBKIT_DOM_DOCUMENT (window);
else
doc = webkit_dom_dom_window_get_document (WEBKIT_DOM_DOM_WINDOW (window));
inputs = webkit_dom_document_query_selector_all (doc, "input[type='text']", NULL);
frames = g_object_get_data (G_OBJECT (window), "framelist");
web_view = g_object_get_data (G_OBJECT (window), "webview");
for (i = 0; i < webkit_dom_node_list_get_length (inputs); i++)
{
WebKitDOMNode* element = webkit_dom_node_list_item (inputs, i);
#if WEBKIT_CHECK_VERSION (1, 6, 1)
gchar* autocomplete = webkit_dom_html_input_element_get_autocomplete (
WEBKIT_DOM_HTML_INPUT_ELEMENT (element));
gboolean off = !g_strcmp0 (autocomplete, "off");
g_free (autocomplete);
if (off)
continue;
#endif
g_object_set_data (G_OBJECT (element), "doc", doc);
g_object_set_data (G_OBJECT (element), "webview", web_view);
g_object_set_data (G_OBJECT (element), "framelist", frames);
/* Add dblclick? */
webkit_dom_event_target_add_event_listener (
WEBKIT_DOM_EVENT_TARGET (element), "keyup",
G_CALLBACK (formhistory_editbox_key_pressed_cb), false,
priv);
webkit_dom_event_target_add_event_listener (
WEBKIT_DOM_EVENT_TARGET (element), "blur",
G_CALLBACK (formhistory_suggestions_hide_cb), false,
priv);
}
}
void
formhistory_setup_suggestions (WebKitWebView* web_view,
JSContextRef js_context,
MidoriExtension* extension)
{
WebKitDOMDocument* doc;
WebKitDOMNodeList* frames;
gulong i;
FormHistoryPriv* priv = g_object_get_data (G_OBJECT (extension), "priv");
doc = webkit_web_view_get_dom_document (web_view);
frames = webkit_dom_document_query_selector_all (doc, "iframe, frame", NULL);
g_object_set_data (G_OBJECT (doc), "framelist", frames);
g_object_set_data (G_OBJECT (doc), "webview", web_view);
/* Connect to DOMContentLoaded of the main frame */
webkit_dom_event_target_add_event_listener(
WEBKIT_DOM_EVENT_TARGET (doc), "DOMContentLoaded",
G_CALLBACK (formhistory_DOMContentLoaded_cb), false,
priv);
/* Connect to DOMContentLoaded of frames */
for (i = 0; i < webkit_dom_node_list_get_length (frames); i++)
{
WebKitDOMDOMWindow* framewin;
WebKitDOMNode* frame = webkit_dom_node_list_item (frames, i);
if (WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (frame))
framewin = webkit_dom_html_iframe_element_get_content_window (WEBKIT_DOM_HTML_IFRAME_ELEMENT (frame));
else
framewin = webkit_dom_html_frame_element_get_content_window (WEBKIT_DOM_HTML_FRAME_ELEMENT (frame));
g_object_set_data (G_OBJECT (framewin), "framelist", frames);
g_object_set_data (G_OBJECT (framewin), "webview", (GtkWidget*)web_view);
webkit_dom_event_target_add_event_listener (
WEBKIT_DOM_EVENT_TARGET (framewin), "DOMContentLoaded",
G_CALLBACK (formhistory_DOMContentLoaded_cb), false,
priv);
}
formhistory_suggestions_hide_cb (NULL, NULL, priv);
}
void
formhistory_private_destroy (FormHistoryPriv *priv)
{
if (priv->db)
{
sqlite3_close (priv->db);
priv->db = NULL;
}
katze_assign (priv->oldkeyword, NULL);
gtk_widget_destroy (priv->popup);
priv->popup = NULL;
katze_object_assign (priv->element, NULL);
g_slice_free (FormHistoryPriv, priv);
}
gboolean
formhistory_construct_popup_gui (FormHistoryPriv* priv)
{
GtkTreeModel* model = NULL;
GtkWidget* popup;
GtkWidget* popup_frame;
GtkWidget* scrolled;
GtkWidget* treeview;
GtkCellRenderer* renderer;
GtkTreeViewColumn* column;
model = (GtkTreeModel*) gtk_list_store_new (1, G_TYPE_STRING);
priv->completion_model = model;
popup = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_type_hint (GTK_WINDOW (popup), GDK_WINDOW_TYPE_HINT_COMBO);
popup_frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (popup_frame), GTK_SHADOW_ETCHED_IN);
gtk_container_add (GTK_CONTAINER (popup), popup_frame);
scrolled = g_object_new (GTK_TYPE_SCROLLED_WINDOW,
"hscrollbar-policy", GTK_POLICY_NEVER,
"vscrollbar-policy", GTK_POLICY_AUTOMATIC, NULL);
gtk_container_add (GTK_CONTAINER (popup_frame), scrolled);
treeview = gtk_tree_view_new_with_model (model);
priv->treeview = treeview;
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
gtk_tree_view_set_hover_selection (GTK_TREE_VIEW (treeview), TRUE);
gtk_container_add (GTK_CONTAINER (scrolled), treeview);
gtk_widget_set_size_request (gtk_scrolled_window_get_vscrollbar (
GTK_SCROLLED_WINDOW (scrolled)), -1, 0);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("suggestions", renderer, "text", 0, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
priv->popup = popup;
g_signal_connect (treeview, "button-press-event",
G_CALLBACK (formhistory_suggestion_selected_cb), priv);
return TRUE;
}
#endif

View file

@ -0,0 +1,143 @@
/*
Copyright (C) 2009-2012 Alexander Butenko <a.butenka@gmail.com>
Copyright (C) 2009-2012 Christian Dywan <christian@twotoasts.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
*/
#include "formhistory-frontend.h"
#ifdef FORMHISTORY_USE_JS
FormHistoryPriv*
formhistory_private_new ()
{
FormHistoryPriv* priv;
priv = g_slice_new (FormHistoryPriv);
return priv;
}
gboolean
formhistory_construct_popup_gui (FormHistoryPriv* priv)
{
gchar* autosuggest;
gchar* style;
guint i;
gchar* file;
file = sokoke_find_data_filename ("autosuggestcontrol.js", TRUE);
if (!g_file_get_contents (file, &autosuggest, NULL, NULL))
{
g_free (file);
return FALSE;
}
g_strchomp (autosuggest);
katze_assign (file, sokoke_find_data_filename ("autosuggestcontrol.css", TRUE));
if (!g_file_get_contents (file, &style, NULL, NULL))
{
g_free (file);
return FALSE;
}
g_strchomp (style);
g_free (file);
i = 0;
while (style[i])
{
if (style[i] == '\n')
style[i] = ' ';
i++;
}
priv->jsforms = g_strdup_printf (
"%s"
"window.addEventListener ('DOMContentLoaded',"
"function () {"
" if (document.getElementById('formhistory'))"
" return;"
" if (!initSuggestions ())"
" return;"
" var mystyle = document.createElement('style');"
" mystyle.setAttribute('type', 'text/css');"
" mystyle.setAttribute('id', 'formhistory');"
" mystyle.appendChild(document.createTextNode('%s'));"
" var head = document.getElementsByTagName('head')[0];"
" if (head) head.appendChild(mystyle);"
"}, true);",
autosuggest,
style);
g_strstrip (priv->jsforms);
g_free (style);
g_free (autosuggest);
return TRUE;
}
void
formhistory_setup_suggestions (WebKitWebView* web_view,
JSContextRef js_context,
MidoriExtension* extension)
{
GString* suggestions;
FormHistoryPriv* priv;
static sqlite3_stmt* stmt;
const char* sqlcmd;
const unsigned char* key;
const unsigned char* value;
gint result, pos;
priv = g_object_get_data (G_OBJECT (extension), "priv");
if (!priv->db)
return;
if (!stmt)
{
sqlcmd = "SELECT DISTINCT group_concat(value,'\",\"'), field FROM forms \
GROUP BY field ORDER BY field";
sqlite3_prepare_v2 (priv->db, sqlcmd, strlen (sqlcmd) + 1, &stmt, NULL);
}
result = sqlite3_step (stmt);
if (result != SQLITE_ROW)
{
if (result == SQLITE_ERROR)
g_print (_("Failed to select suggestions\n"));
sqlite3_reset (stmt);
return;
}
suggestions = g_string_new (
"function FormSuggestions(eid) { "
"arr = new Array();");
while (result == SQLITE_ROW)
{
pos++;
value = sqlite3_column_text (stmt, 0);
key = sqlite3_column_text (stmt, 1);
if (value)
{
g_string_append_printf (suggestions, " arr[\"%s\"] = [\"%s\"]; ",
(gchar*)key, (gchar*)value);
}
result = sqlite3_step (stmt);
}
g_string_append (suggestions, "this.suggestions = arr[eid]; }");
g_string_append (suggestions, priv->jsforms);
sokoke_js_script_eval (js_context, suggestions->str, NULL);
g_string_free (suggestions, TRUE);
}
void
formhistory_private_destroy (FormHistoryPriv *priv)
{
if (priv->db)
{
sqlite3_close (priv->db);
priv->db = NULL;
}
katze_assign (priv->jsforms, NULL);
g_slice_free (FormHistoryPriv, priv);
}
#endif

View file

@ -0,0 +1,679 @@
/*
Copyright (C) 2009-2012 Alexander Butenko <a.butenka@gmail.com>
Copyright (C) 2009-2012 Christian Dywan <christian@twotoasts.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
*/
#define MAXCHARS 60
#define MINCHARS 2
#define GTK_RESPONSE_IGNORE 99
#include "formhistory-frontend.h"
static void
formhistory_toggle_state_cb (GtkAction* action,
MidoriBrowser* browser);
static void
formhistory_update_database (gpointer db,
const gchar* host,
const gchar* key,
const gchar* value)
{
gchar* sqlcmd;
gchar* errmsg;
gint success;
if (!(value && *value))
return;
sqlcmd = sqlite3_mprintf ("INSERT INTO forms VALUES"
"('%q', '%q', '%q')",
host, key, value);
success = sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg);
sqlite3_free (sqlcmd);
if (success != SQLITE_OK)
{
g_printerr (_("Failed to add form value: %s\n"), errmsg);
g_free (errmsg);
return;
}
}
static gchar*
formhistory_get_login_data (gpointer db,
const gchar* domain)
{
static sqlite3_stmt* stmt;
const char* sqlcmd;
gint result;
gchar* value = NULL;
if (!stmt)
{
sqlcmd = "SELECT value FROM forms WHERE domain = ?1 and field = 'MidoriPasswordManager' limit 1";
sqlite3_prepare_v2 (db, sqlcmd, strlen (sqlcmd) + 1, &stmt, NULL);
}
sqlite3_bind_text (stmt, 1, domain, -1, NULL);
result = sqlite3_step (stmt);
if (result == SQLITE_ROW)
value = g_strdup ((gchar*)sqlite3_column_text (stmt, 0));
sqlite3_reset (stmt);
sqlite3_clear_bindings (stmt);
return value;
}
static gboolean
formhistory_check_master_password (GtkWidget* parent,
FormHistoryPriv* priv)
{
GtkWidget* dialog;
GtkWidget* content_area;
GtkWidget* hbox;
GtkWidget* image;
GtkWidget* label;
GtkWidget* entry;
const gchar* title;
static int alive;
gboolean ret = FALSE;
/* Password is set */
if (priv->master_password && *priv->master_password)
return TRUE;
/* Other prompt is active */
if (alive == 1)
return FALSE;
/* Prompt was cancelled */
if (priv->master_password_canceled == 1)
return FALSE;
alive = 1;
title = _("Form history");
dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (parent),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_DIALOG_AUTHENTICATION);
gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
gtk_container_set_border_width (GTK_CONTAINER (content_area), 5);
hbox = gtk_hbox_new (FALSE, 8);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION,
GTK_ICON_SIZE_DIALOG);
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
label = gtk_label_new (_("Master password required\n"
"to open password database"));
gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (content_area), hbox);
entry = gtk_entry_new ();
g_object_set (entry, "truncate-multiline", TRUE, NULL);
gtk_entry_set_visibility(GTK_ENTRY (entry),FALSE);
gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
gtk_container_add (GTK_CONTAINER (content_area), entry);
gtk_widget_show_all (entry);
gtk_widget_show_all (hbox);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
{
/* FIXME: add password verification */
katze_assign (priv->master_password,
g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))));
ret = TRUE;
}
else
priv->master_password_canceled = 1;
gtk_widget_destroy (dialog);
alive = 0;
return ret;
}
static gchar*
formhistory_encrypt (const gchar* data,
const gchar* password)
{
/* TODO: Implement persistent storage/ keyring support */
return NULL;
}
static void
formhistory_remember_password_response (GtkWidget* infobar,
gint response_id,
FormhistoryPasswordEntry* entry)
{
gchar* encrypted_form;
if (response_id == GTK_RESPONSE_IGNORE)
goto cleanup;
if (formhistory_check_master_password (NULL, entry->priv))
{
if (response_id != GTK_RESPONSE_ACCEPT)
katze_assign (entry->form_data, g_strdup ("never"));
if ((encrypted_form = formhistory_encrypt (entry->form_data,
entry->priv->master_password)))
formhistory_update_database (entry->priv->db, entry->domain, "MidoriPasswordManager", encrypted_form);
g_free (encrypted_form);
}
cleanup:
g_free (entry->form_data);
g_free (entry->domain);
g_slice_free (FormhistoryPasswordEntry, entry);
gtk_widget_destroy (infobar);
}
static gboolean
formhistory_navigation_decision_cb (WebKitWebView* web_view,
WebKitWebFrame* web_frame,
WebKitNetworkRequest* request,
WebKitWebNavigationAction* action,
WebKitWebPolicyDecision* decision,
MidoriExtension* extension)
{
FormHistoryPriv* priv;
JSContextRef js_context;
gchar* value;
/* The script returns form data in the form "field_name|,|value|,|field_type".
We are handling only input fields with 'text' or 'password' type.
The field separator is "|||" */
const gchar* script = "function dumpForm (inputs) {"
" var out = '';"
" for (i=0;i<inputs.length;i++) {"
" if (inputs[i].getAttribute('autocomplete') == 'off' && "
" inputs[i].type == 'text')"
" continue;"
" if (inputs[i].value && (inputs[i].type == 'text' || inputs[i].type == 'password')) {"
" var ename = inputs[i].getAttribute('name');"
" var eid = inputs[i].getAttribute('id');"
" if (!eid && ename)"
" eid=ename;"
" out += eid+'|,|'+inputs[i].value +'|,|'+inputs[i].type +'|||';"
" }"
" }"
" return out;"
"}"
"dumpForm (document.getElementsByTagName('input'))";
if (webkit_web_navigation_action_get_reason (action) != WEBKIT_WEB_NAVIGATION_REASON_FORM_SUBMITTED)
return FALSE;
priv = g_object_get_data (G_OBJECT (extension), "priv");
js_context = webkit_web_frame_get_global_context (web_frame);
value = sokoke_js_script_eval (js_context, script, NULL);
formhistory_suggestions_hide_cb (NULL, NULL, priv);
if (value && *value)
{
gchar** inputs = g_strsplit (value, "|||", 0);
guint i = 0;
while (inputs[i] != NULL)
{
gchar** parts = g_strsplit (inputs[i], "|,|", 3);
if (parts && parts[0] && parts[1] && parts[2])
{
if (strcmp (parts[2], "password"))
formhistory_update_database (priv->db, NULL, parts[0], parts[1]);
#if WEBKIT_CHECK_VERSION (1, 3, 8)
else
{
gchar* data;
gchar* domain;
#if 0
FormhistoryPasswordEntry* entry;
#endif
domain = midori_uri_parse_hostname (webkit_web_frame_get_uri (web_frame), NULL);
data = formhistory_get_login_data (priv->db, domain);
if (data)
{
g_free (data);
g_free (domain);
break;
}
#if 0
entry = g_slice_new (FormhistoryPasswordEntry);
/* Domain and form data are freed from infopanel callback*/
entry->form_data = g_strdup (value);
entry->domain = domain;
entry->priv = priv;
g_object_set_data (G_OBJECT (web_view), "FormHistoryPasswordEntry", entry);
#endif
}
#endif
}
g_strfreev (parts);
i++;
}
g_strfreev (inputs);
g_free (value);
}
return FALSE;
}
static void
formhistory_window_object_cleared_cb (WebKitWebView* web_view,
WebKitWebFrame* web_frame,
JSContextRef js_context,
JSObjectRef js_window,
MidoriExtension* extension)
{
const gchar* page_uri;
FormhistoryPasswordEntry* entry;
GtkWidget* view;
page_uri = webkit_web_frame_get_uri (web_frame);
if (!page_uri)
return;
if (!midori_uri_is_http (page_uri) && !g_str_has_prefix (page_uri, "file"))
return;
formhistory_setup_suggestions (web_view, js_context, extension);
#if WEBKIT_CHECK_VERSION (1, 3, 8)
entry = g_object_get_data (G_OBJECT (web_view), "FormHistoryPasswordEntry");
if (entry)
{
const gchar* message = _("Remember password on this page?");
view = midori_browser_get_current_tab (midori_app_get_browser (
midori_extension_get_app (extension)));
midori_view_add_info_bar (MIDORI_VIEW (view), GTK_MESSAGE_QUESTION, message,
G_CALLBACK (formhistory_remember_password_response), entry,
_("Remember"), GTK_RESPONSE_ACCEPT,
_("Not now"), GTK_RESPONSE_IGNORE,
_("Never for this page"), GTK_RESPONSE_CANCEL, NULL);
g_object_set_data (G_OBJECT (web_view), "FormHistoryPasswordEntry", NULL);
}
#endif
}
#if WEBKIT_CHECK_VERSION (1, 3, 8)
static gchar*
formhistory_decrypt (const gchar* data,
const gchar* password)
{
/* TODO: Implement persistent storage/ keyring support */
return NULL;
}
static void
formhistory_fill_login_data (JSContextRef js_context,
FormHistoryPriv* priv,
const gchar* data)
{
gchar* decrypted_data = NULL;
guint i = 0;
GString *script;
gchar** inputs;
/* Handle case that user dont want to store password */
if (!strncmp (data, "never", 5))
return;
#if 0
if (!formhistory_check_master_password (NULL, priv))
return;
#endif
if (!(decrypted_data = formhistory_decrypt (data, priv->master_password)))
return;
script = g_string_new ("");
inputs = g_strsplit (decrypted_data, "|||", 0);
while (inputs[i] != NULL)
{
gchar** parts = g_strsplit (inputs[i], "|,|", 3);
if (parts && parts[0] && parts[1] && parts[2])
{
g_string_append_printf (script, "node = null;"
"node = document.getElementById ('%s');"
"if (!node) { node = document.getElementsByName ('%s')[0]; }"
"if (node && node.type == '%s') { node.value = '%s'; }",
parts[0], parts[0], parts[2], parts[1]);
}
g_strfreev (parts);
i++;
}
g_free (decrypted_data);
g_strfreev (inputs);
g_free (sokoke_js_script_eval (js_context, script->str, NULL));
g_string_free (script, TRUE);
}
static void
formhistory_frame_loaded_cb (WebKitWebView* web_view,
WebKitWebFrame* web_frame,
MidoriExtension* extension)
{
const gchar* page_uri;
const gchar* count_request;
FormHistoryPriv* priv;
JSContextRef js_context;
gchar* data;
gchar* domain;
gchar* count;
page_uri = webkit_web_frame_get_uri (web_frame);
if (!page_uri)
return;
count_request = "document.querySelectorAll('input[type=password]').length";
js_context = webkit_web_frame_get_global_context (web_frame);
count = sokoke_js_script_eval (js_context, count_request, NULL);
if (count && count[0] == '0')
{
g_free (count);
return;
}
g_free (count);
priv = g_object_get_data (G_OBJECT (extension), "priv");
domain = midori_uri_parse_hostname (webkit_web_frame_get_uri (web_frame), NULL);
data = formhistory_get_login_data (priv->db, domain);
g_free (domain);
if (!data)
return;
formhistory_fill_login_data (js_context, priv, data);
g_free (data);
}
#endif
static void
formhistory_deactivate_cb (MidoriExtension* extension,
MidoriBrowser* browser);
static void
formhistory_add_tab_cb (MidoriBrowser* browser,
MidoriView* view,
MidoriExtension* extension)
{
GtkWidget* web_view = midori_view_get_web_view (view);
g_signal_connect (web_view, "window-object-cleared",
G_CALLBACK (formhistory_window_object_cleared_cb), extension);
g_signal_connect (web_view, "navigation-policy-decision-requested",
G_CALLBACK (formhistory_navigation_decision_cb), extension);
#if WEBKIT_CHECK_VERSION (1, 3, 8)
g_signal_connect (web_view, "onload-event",
G_CALLBACK (formhistory_frame_loaded_cb), extension);
#endif
}
static void
formhistory_add_tab_foreach_cb (MidoriView* view,
MidoriExtension* extension)
{
formhistory_add_tab_cb (NULL, view, extension);
}
static void
formhistory_app_add_browser_cb (MidoriApp* app,
MidoriBrowser* browser,
MidoriExtension* extension)
{
GtkAccelGroup* acg = gtk_accel_group_new ();
GtkActionGroup* action_group = midori_browser_get_action_group (browser);
GtkAction* action = gtk_action_new ("FormHistoryToggleState",
_("Toggle form history state"),
_("Activate or deactivate form history for the current tab."), NULL);
gtk_window_add_accel_group (GTK_WINDOW (browser), acg);
g_object_set_data (G_OBJECT (browser), "FormHistoryExtension", extension);
g_signal_connect (action, "activate",
G_CALLBACK (formhistory_toggle_state_cb), browser);
gtk_action_group_add_action_with_accel (action_group, action, "<Ctrl><Shift>F");
gtk_action_set_accel_group (action, acg);
gtk_action_connect_accelerator (action);
if (midori_extension_get_boolean (extension, "always-load"))
{
midori_browser_foreach (browser,
(GtkCallback)formhistory_add_tab_foreach_cb, extension);
g_signal_connect (browser, "add-tab",
G_CALLBACK (formhistory_add_tab_cb), extension);
}
g_signal_connect (extension, "deactivate",
G_CALLBACK (formhistory_deactivate_cb), browser);
}
static void
formhistory_deactivate_tab (MidoriView* view,
MidoriExtension* extension)
{
GtkWidget* web_view = midori_view_get_web_view (view);
g_signal_handlers_disconnect_by_func (
web_view, formhistory_window_object_cleared_cb, extension);
g_signal_handlers_disconnect_by_func (
web_view, formhistory_navigation_decision_cb, extension);
#if WEBKIT_CHECK_VERSION (1, 3, 8)
g_signal_handlers_disconnect_by_func (
web_view, formhistory_frame_loaded_cb, extension);
#endif
}
static void
formhistory_deactivate_cb (MidoriExtension* extension,
MidoriBrowser* browser)
{
MidoriApp* app = midori_extension_get_app (extension);
FormHistoryPriv* priv = g_object_get_data (G_OBJECT (extension), "priv");
GtkActionGroup* action_group = midori_browser_get_action_group (browser);
GtkAction* action;
g_signal_handlers_disconnect_by_func (
browser, formhistory_add_tab_cb, extension);
g_signal_handlers_disconnect_by_func (
extension, formhistory_deactivate_cb, browser);
g_signal_handlers_disconnect_by_func (
app, formhistory_app_add_browser_cb, extension);
midori_browser_foreach (browser,
(GtkCallback)formhistory_deactivate_tab, extension);
g_object_set_data (G_OBJECT (browser), "FormHistoryExtension", NULL);
action = gtk_action_group_get_action (action_group, "FormHistoryToggleState");
if (action != NULL)
{
gtk_action_group_remove_action (action_group, action);
g_object_unref (action);
}
formhistory_private_destroy (priv);
}
static void
formhistory_activate_cb (MidoriExtension* extension,
MidoriApp* app)
{
const gchar* config_dir;
gchar* filename;
sqlite3* db;
char* errmsg = NULL, *errmsg2 = NULL;
KatzeArray* browsers;
MidoriBrowser* browser;
FormHistoryPriv* priv;
priv = formhistory_private_new ();
priv->master_password = NULL;
priv->master_password_canceled = 0;
formhistory_construct_popup_gui (priv);
config_dir = midori_extension_get_config_dir (extension);
katze_mkdir_with_parents (config_dir, 0700);
filename = g_build_filename (config_dir, "forms.db", NULL);
if (sqlite3_open (filename, &db) != SQLITE_OK)
{
/* If the folder is /, this is a test run, thus no error */
if (!g_str_equal (midori_extension_get_config_dir (extension), "/"))
g_warning (_("Failed to open database: %s\n"), sqlite3_errmsg (db));
sqlite3_close (db);
}
g_free (filename);
if ((sqlite3_exec (db, "CREATE TABLE IF NOT EXISTS "
"forms (domain text, field text, value text)",
NULL, NULL, &errmsg) == SQLITE_OK))
{
sqlite3_exec (db,
/* "PRAGMA synchronous = OFF; PRAGMA temp_store = MEMORY" */
"PRAGMA count_changes = OFF; PRAGMA journal_mode = TRUNCATE;",
NULL, NULL, &errmsg);
priv->db = db;
}
else
{
if (errmsg)
{
g_critical (_("Failed to execute database statement: %s\n"), errmsg);
sqlite3_free (errmsg);
if (errmsg2)
{
g_critical (_("Failed to execute database statement: %s\n"), errmsg2);
sqlite3_free (errmsg2);
}
}
sqlite3_close (db);
}
g_object_set_data (G_OBJECT (extension), "priv", priv);
browsers = katze_object_get_object (app, "browsers");
KATZE_ARRAY_FOREACH_ITEM (browser, browsers)
formhistory_app_add_browser_cb (app, browser, extension);
g_signal_connect (app, "add-browser",
G_CALLBACK (formhistory_app_add_browser_cb), extension);
g_object_unref (browsers);
}
static void
formhistory_preferences_response_cb (GtkWidget* dialog,
gint response_id,
MidoriExtension* extension)
{
GtkWidget* checkbox;
gboolean old_state;
gboolean new_state;
MidoriApp* app;
KatzeArray* browsers;
MidoriBrowser* browser;
if (response_id == GTK_RESPONSE_APPLY)
{
checkbox = g_object_get_data (G_OBJECT (dialog), "always-load-checkbox");
new_state = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox));
old_state = midori_extension_get_boolean (extension, "always-load");
if (old_state != new_state)
{
midori_extension_set_boolean (extension, "always-load", new_state);
app = midori_extension_get_app (extension);
browsers = katze_object_get_object (app, "browsers");
KATZE_ARRAY_FOREACH_ITEM (browser, browsers)
{
midori_browser_foreach (browser,
(GtkCallback)formhistory_deactivate_tab, extension);
g_signal_handlers_disconnect_by_func (
browser, formhistory_add_tab_cb, extension);
if (new_state)
{
midori_browser_foreach (browser,
(GtkCallback)formhistory_add_tab_foreach_cb, extension);
g_signal_connect (browser, "add-tab",
G_CALLBACK (formhistory_add_tab_cb), extension);
}
}
}
}
gtk_widget_destroy (dialog);
}
static void
formhistory_preferences_cb (MidoriExtension* extension)
{
GtkWidget* dialog;
GtkWidget* content_area;
GtkWidget* checkbox;
dialog = gtk_dialog_new ();
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_APPLY, GTK_RESPONSE_APPLY);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
checkbox = gtk_check_button_new_with_label (_("Only activate form history via hotkey (Ctrl+Shift+F) per tab"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbox),
!midori_extension_get_boolean (extension, "always-load"));
g_object_set_data (G_OBJECT (dialog), "always-load-checkbox", checkbox);
gtk_container_add (GTK_CONTAINER (content_area), checkbox);
/* FIXME: Add pref to disable password manager */
g_signal_connect (dialog,
"response",
G_CALLBACK (formhistory_preferences_response_cb),
extension);
gtk_widget_show_all (dialog);
}
static void
formhistory_toggle_state_cb (GtkAction* action,
MidoriBrowser* browser)
{
MidoriView* view = MIDORI_VIEW (midori_browser_get_current_tab (browser));
MidoriExtension* extension = g_object_get_data (G_OBJECT (browser), "FormHistoryExtension");
GtkWidget* web_view = midori_view_get_web_view (view);
if (g_signal_handler_find (web_view, G_SIGNAL_MATCH_FUNC,
g_signal_lookup ("window-object-cleared", MIDORI_TYPE_VIEW), 0, NULL,
formhistory_window_object_cleared_cb, extension))
{
formhistory_deactivate_tab (view, extension);
}
else
formhistory_add_tab_cb (browser, view, extension);
}
MidoriExtension*
extension_init (void)
{
MidoriExtension* extension;
extension = g_object_new (MIDORI_TYPE_EXTENSION,
"name", _("Form history filler"),
"description", _("Stores history of entered form data"),
"version", "2.0" MIDORI_VERSION_SUFFIX,
"authors", "Alexander V. Butenko <a.butenka@gmail.com>",
NULL);
midori_extension_install_boolean (extension, "always-load", TRUE);
g_signal_connect (extension, "activate",
G_CALLBACK (formhistory_activate_cb), NULL);
g_signal_connect (extension, "open-preferences",
G_CALLBACK (formhistory_preferences_cb), NULL);
return extension;
}

View file

@ -180,8 +180,6 @@ shortcuts_get_preferences_dialog (MidoriExtension* extension)
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
#endif #endif
NULL); NULL);
g_signal_connect (dialog, "destroy",
G_CALLBACK (gtk_widget_destroyed), &dialog);
gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_PROPERTIES); gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_PROPERTIES);
sokoke_widget_get_text_size (dialog, "M", &width, &height); sokoke_widget_get_text_size (dialog, "M", &width, &height);
gtk_window_set_default_size (GTK_WINDOW (dialog), width * 52, height * 24); gtk_window_set_default_size (GTK_WINDOW (dialog), width * 52, height * 24);

View file

@ -66,11 +66,14 @@ statusbar_features_browser_notify_tab_cb (MidoriBrowser* browser,
GtkWidget* combobox) GtkWidget* combobox)
{ {
MidoriView* view = MIDORI_VIEW (midori_browser_get_current_tab (browser)); MidoriView* view = MIDORI_VIEW (midori_browser_get_current_tab (browser));
gchar* zoom_level_text = g_strdup_printf ("%d%%", gchar* text;
(gint)(midori_view_get_zoom_level (view) * 100));
gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (combobox))), if (view == NULL)
zoom_level_text); return;
g_free (zoom_level_text);
text = g_strdup_printf ("%d%%", (gint)(midori_view_get_zoom_level (view) * 100));
gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (combobox))), text);
g_free (text);
} }
static void static void
@ -142,8 +145,10 @@ statusbar_features_app_add_browser_cb (MidoriApp* app,
g_signal_connect (toolbar, "notify::toolbar-style", g_signal_connect (toolbar, "notify::toolbar-style",
G_CALLBACK (statusbar_features_toolbar_notify_toolbar_style_cb), button); G_CALLBACK (statusbar_features_toolbar_notify_toolbar_style_cb), button);
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
button = katze_property_proxy (settings, "enable-plugins", "toggle"); if (midori_web_settings_has_plugin_support ())
g_object_set_data (G_OBJECT (button), "feature-label", _("Netscape plugins")); {
button = katze_property_proxy (settings, "enable-plugins", "toggle");
g_object_set_data (G_OBJECT (button), "feature-label", _("Netscape plugins"));
image = gtk_image_new_from_stock (STOCK_PLUGINS, GTK_ICON_SIZE_MENU); image = gtk_image_new_from_stock (STOCK_PLUGINS, GTK_ICON_SIZE_MENU);
gtk_button_set_image (GTK_BUTTON (button), image); gtk_button_set_image (GTK_BUTTON (button), image);
gtk_widget_set_tooltip_text (button, _("Enable Netscape plugins")); gtk_widget_set_tooltip_text (button, _("Enable Netscape plugins"));
@ -151,6 +156,7 @@ statusbar_features_app_add_browser_cb (MidoriApp* app,
g_signal_connect (toolbar, "notify::toolbar-style", g_signal_connect (toolbar, "notify::toolbar-style",
G_CALLBACK (statusbar_features_toolbar_notify_toolbar_style_cb), button); G_CALLBACK (statusbar_features_toolbar_notify_toolbar_style_cb), button);
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
}
button = katze_property_proxy (settings, "identify-as", "custom-user-agent"); button = katze_property_proxy (settings, "identify-as", "custom-user-agent");
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2); gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
button = gtk_combo_box_text_new_with_entry (); button = gtk_combo_box_text_new_with_entry ();
@ -162,8 +168,9 @@ statusbar_features_app_add_browser_cb (MidoriApp* app,
G_CALLBACK (statusbar_features_zoom_level_changed_cb), browser); G_CALLBACK (statusbar_features_zoom_level_changed_cb), browser);
g_signal_connect (browser, "notify::tab", g_signal_connect (browser, "notify::tab",
G_CALLBACK (statusbar_features_browser_notify_tab_cb), button); G_CALLBACK (statusbar_features_browser_notify_tab_cb), button);
statusbar_features_browser_notify_tab_cb (browser, NULL, button);
gtk_widget_show_all (bbox); gtk_widget_show_all (bbox);
gtk_box_pack_start (GTK_BOX (statusbar), bbox, FALSE, FALSE, 3); gtk_box_pack_end (GTK_BOX (statusbar), bbox, FALSE, FALSE, 3);
g_object_unref (statusbar); g_object_unref (statusbar);
g_signal_connect (extension, "deactivate", g_signal_connect (extension, "deactivate",

View file

@ -394,11 +394,7 @@ static TBEditorWidget *tb_editor_create_dialog(MidoriBrowser *parent)
GTK_WINDOW(parent), GTK_WINDOW(parent),
GTK_DIALOG_DESTROY_WITH_PARENT, GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
#if !GTK_CHECK_VERSION(3,0,0) vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
vbox = (GTK_DIALOG(dialog))->vbox;
#else
vbox = GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog)));
#endif
gtk_box_set_spacing(GTK_BOX(vbox), 6); gtk_box_set_spacing(GTK_BOX(vbox), 6);
gtk_widget_set_name(dialog, "GeanyDialog"); gtk_widget_set_name(dialog, "GeanyDialog");
gtk_window_set_default_size(GTK_WINDOW(dialog), -1, 400); gtk_window_set_default_size(GTK_WINDOW(dialog), -1, 400);

View file

@ -27,9 +27,9 @@ sokoke_on_entry_focus_in_event (GtkEntry* entry,
g_object_get_data (G_OBJECT (entry), "sokoke_has_default")); g_object_get_data (G_OBJECT (entry), "sokoke_has_default"));
if (has_default) if (has_default)
{ {
gtk_entry_set_text (entry, "");
g_object_set_data (G_OBJECT (entry), "sokoke_has_default", g_object_set_data (G_OBJECT (entry), "sokoke_has_default",
GINT_TO_POINTER (0)); GINT_TO_POINTER (0));
gtk_entry_set_text (entry, "");
sokoke_widget_set_pango_font_style (GTK_WIDGET (entry), sokoke_widget_set_pango_font_style (GTK_WIDGET (entry),
PANGO_STYLE_NORMAL); PANGO_STYLE_NORMAL);
} }
@ -46,9 +46,9 @@ sokoke_on_entry_focus_out_event (GtkEntry* entry,
{ {
const gchar* default_text = (const gchar*)g_object_get_data ( const gchar* default_text = (const gchar*)g_object_get_data (
G_OBJECT (entry), "sokoke_default_text"); G_OBJECT (entry), "sokoke_default_text");
gtk_entry_set_text (entry, default_text);
g_object_set_data (G_OBJECT (entry), g_object_set_data (G_OBJECT (entry),
"sokoke_has_default", GINT_TO_POINTER (1)); "sokoke_has_default", GINT_TO_POINTER (1));
gtk_entry_set_text (entry, default_text);
sokoke_widget_set_pango_font_style (GTK_WIDGET (entry), sokoke_widget_set_pango_font_style (GTK_WIDGET (entry),
PANGO_STYLE_ITALIC); PANGO_STYLE_ITALIC);
} }
@ -73,6 +73,9 @@ gtk_entry_set_placeholder_text (GtkEntry* entry,
/* Note: The default text initially overwrites any previous text */ /* Note: The default text initially overwrites any previous text */
gchar* old_value = g_object_get_data (G_OBJECT (entry), gchar* old_value = g_object_get_data (G_OBJECT (entry),
"sokoke_default_text"); "sokoke_default_text");
g_object_set_data (G_OBJECT (entry), "sokoke_default_text",
(gpointer)default_text);
if (!old_value) if (!old_value)
{ {
g_object_set_data (G_OBJECT (entry), "sokoke_has_default", g_object_set_data (G_OBJECT (entry), "sokoke_has_default",
@ -98,8 +101,12 @@ gtk_entry_set_placeholder_text (GtkEntry* entry,
PANGO_STYLE_ITALIC); PANGO_STYLE_ITALIC);
} }
} }
g_object_set_data (G_OBJECT (entry), "sokoke_default_text", }
(gpointer)default_text);
const gchar*
gtk_entry_get_placeholder_text (GtkEntry* entry)
{
return g_object_get_data (G_OBJECT (entry), "sokoke_default_text");
} }
#endif #endif

View file

@ -6,7 +6,7 @@
G_BEGIN_DECLS G_BEGIN_DECLS
#if GTK_CHECK_VERSION (3, 2, 0) #if GTK_CHECK_VERSION (3, 2, 0) && defined (GTK_DISABLE_DEPRECATED)
#define GTK_TYPE_VBOX GTK_TYPE_BOX #define GTK_TYPE_VBOX GTK_TYPE_BOX
#define GtkVBox GtkBox #define GtkVBox GtkBox
#define GtkVBoxClass GtkBoxClass #define GtkVBoxClass GtkBoxClass
@ -89,8 +89,10 @@ G_BEGIN_DECLS
#if !GTK_CHECK_VERSION (3, 2, 0) && defined (HAVE_HILDON_2_2) #if !GTK_CHECK_VERSION (3, 2, 0) && defined (HAVE_HILDON_2_2)
#define gtk_entry_set_placeholder_text hildon_gtk_entry_set_placeholder_text #define gtk_entry_set_placeholder_text hildon_gtk_entry_set_placeholder_text
#define gtk_entry_get_placeholder_text hildon_gtk_entry_get_placeholder_text
#elif !GTK_CHECK_VERSION (3, 2, 0) #elif !GTK_CHECK_VERSION (3, 2, 0)
#define gtk_entry_set_placeholder_text sokoke_entry_set_default_text void gtk_entry_set_placeholder_text (GtkEntry* entry, const gchar* text);
const gchar* gtk_entry_get_placeholder_text (GtkEntry* entry);
#endif #endif
#if !GTK_CHECK_VERSION(2, 12, 0) #if !GTK_CHECK_VERSION(2, 12, 0)

View file

@ -74,6 +74,13 @@ GList* kalistglobal;
static void static void
katze_array_finalize (GObject* object); katze_array_finalize (GObject* object);
static void
_katze_array_update (KatzeArray* array)
{
g_object_set_data (G_OBJECT (array), "last-update",
GINT_TO_POINTER (time (NULL)));
}
static void static void
_katze_array_add_item (KatzeArray* array, _katze_array_add_item (KatzeArray* array,
gpointer item) gpointer item)
@ -84,6 +91,7 @@ _katze_array_add_item (KatzeArray* array,
katze_item_set_parent (item, array); katze_item_set_parent (item, array);
array->items = g_list_append (array->items, item); array->items = g_list_append (array->items, item);
_katze_array_update (array);
} }
static void static void
@ -95,6 +103,7 @@ _katze_array_remove_item (KatzeArray* array,
if (KATZE_IS_ITEM (item)) if (KATZE_IS_ITEM (item))
katze_item_set_parent (item, NULL); katze_item_set_parent (item, NULL);
g_object_unref (item); g_object_unref (item);
_katze_array_update (array);
} }
static void static void
@ -104,6 +113,7 @@ _katze_array_move_item (KatzeArray* array,
{ {
array->items = g_list_remove (array->items, item); array->items = g_list_remove (array->items, item);
array->items = g_list_insert (array->items, item, position); array->items = g_list_insert (array->items, item, position);
_katze_array_update (array);
} }
static void static void
@ -112,9 +122,10 @@ _katze_array_clear (KatzeArray* array)
GObject* item; GObject* item;
while ((item = g_list_nth_data (array->items, 0))) while ((item = g_list_nth_data (array->items, 0)))
katze_array_remove_item (array, item); g_signal_emit (array, signals[REMOVE_ITEM], 0, item);
g_list_free (array->items); g_list_free (array->items);
array->items = NULL; array->items = NULL;
_katze_array_update (array);
} }
static void static void
@ -192,7 +203,7 @@ katze_array_class_init (KatzeArrayClass* class)
"update", "update",
G_TYPE_FROM_CLASS (class), G_TYPE_FROM_CLASS (class),
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
0, G_STRUCT_OFFSET (KatzeArrayClass, update),
0, 0,
NULL, NULL,
g_cclosure_marshal_VOID__VOID, g_cclosure_marshal_VOID__VOID,
@ -205,6 +216,7 @@ katze_array_class_init (KatzeArrayClass* class)
class->remove_item = _katze_array_remove_item; class->remove_item = _katze_array_remove_item;
class->move_item = _katze_array_move_item; class->move_item = _katze_array_move_item;
class->clear = _katze_array_clear; class->clear = _katze_array_clear;
class->update = _katze_array_update;
} }
static void static void
@ -217,14 +229,11 @@ katze_array_init (KatzeArray* array)
static void static void
katze_array_finalize (GObject* object) katze_array_finalize (GObject* object)
{ {
KatzeArray* array; KatzeArray* array = KATZE_ARRAY (object);
guint i; GList* items;
gpointer item;
array = KATZE_ARRAY (object); for (items = array->items; items; items = g_list_next (items))
i = 0; g_object_unref (items->data);
while ((item = g_list_nth_data (array->items, i++)))
g_object_unref (item);
g_list_free (array->items); g_list_free (array->items);
G_OBJECT_CLASS (katze_array_parent_class)->finalize (object); G_OBJECT_CLASS (katze_array_parent_class)->finalize (object);
@ -364,37 +373,39 @@ katze_array_get_item_index (KatzeArray* array,
/** /**
* katze_array_find_token: * katze_array_find_token:
* @array: a #KatzeArray * @array: a #KatzeArray
* @token: a token string * @token: a token string, or "token keywords" string
* *
* Looks up an item in the array which has the specified token. * Looks up an item in the array which has the specified token.
* *
* This function will silently fail if the type of the list * This function will fail if the type of the list
* is not based on #GObject and only #KatzeItem children * is not based on #KatzeItem children.
* are checked for their token, any other objects are skipped.
* *
* Note that @token is by definition unique to one item. * Note that @token is by definition unique to one item.
* *
* Since 0.4.4 @token can be a "token keywords" string.
*
* Return value: an item, or %NULL * Return value: an item, or %NULL
**/ **/
gpointer gpointer
katze_array_find_token (KatzeArray* array, katze_array_find_token (KatzeArray* array,
const gchar* token) const gchar* token)
{ {
guint i; goffset token_length;
gpointer item; GList* items;
g_return_val_if_fail (KATZE_IS_ARRAY (array), NULL); g_return_val_if_fail (KATZE_IS_ARRAY (array), NULL);
g_return_val_if_fail (katze_array_is_a (array, KATZE_TYPE_ITEM), NULL);
g_return_val_if_fail (token != NULL, NULL);
i = 0; token_length = strchr (token, ' ') - token;
while ((item = g_list_nth_data (array->items, i++))) if (token_length < 1)
token_length = strlen (token);
for (items = array->items; items; items = g_list_next (items))
{ {
const gchar* found_token; const gchar* found_token = ((KatzeItem*)items->data)->token;
if (found_token != NULL && !strncmp (token, found_token, token_length))
if (!KATZE_IS_ITEM (item)) return items->data;
continue;
found_token = ((KatzeItem*)item)->token;
if (!g_strcmp0 (found_token, token))
return item;
} }
return NULL; return NULL;
} }
@ -406,9 +417,8 @@ katze_array_find_token (KatzeArray* array,
* *
* Looks up an item in the array which has the specified URI. * Looks up an item in the array which has the specified URI.
* *
* This function will silently fail if the type of the list * This function will fail if the type of the list
* is not based on #GObject and only #KatzeItem children * is not based on #KatzeItem children.
* are checked for their token, any other objects are skipped.
* *
* Return value: an item, or %NULL * Return value: an item, or %NULL
* *
@ -418,19 +428,17 @@ gpointer
katze_array_find_uri (KatzeArray* array, katze_array_find_uri (KatzeArray* array,
const gchar* uri) const gchar* uri)
{ {
guint i; GList* items;
gpointer item;
i = 0; g_return_val_if_fail (KATZE_IS_ARRAY (array), NULL);
while ((item = g_list_nth_data (array->items, i++))) g_return_val_if_fail (katze_array_is_a (array, KATZE_TYPE_ITEM), NULL);
g_return_val_if_fail (uri != NULL, NULL);
for (items = array->items; items; items = g_list_next (items))
{ {
const gchar* found_uri; const gchar* found_uri = ((KatzeItem*)items->data)->uri;
if (found_uri != NULL && !strcmp (found_uri, uri))
if (!KATZE_IS_ITEM (item)) return items->data;
continue;
found_uri = ((KatzeItem*)item)->uri;
if (!g_strcmp0 (found_uri, uri))
return item;
} }
return NULL; return NULL;
} }

View file

@ -355,11 +355,16 @@ katze_array_action_generate_menu (KatzeArrayAction* array_action,
gint summand; gint summand;
KatzeItem* item; KatzeItem* item;
GtkWidget* menuitem; GtkWidget* menuitem;
const gchar* icon_name;
GdkPixbuf* icon;
GtkWidget* image; GtkWidget* image;
GtkWidget* submenu; GtkWidget* submenu;
g_return_if_fail (KATZE_IS_ARRAY_ACTION (array_action));
g_return_if_fail (KATZE_IS_ITEM (array));
g_return_if_fail (GTK_IS_MENU_SHELL (menu));
g_return_if_fail (GTK_IS_TOOL_ITEM (proxy)
|| GTK_IS_MENU_ITEM (proxy)
|| GTK_IS_WINDOW (proxy));
if (!KATZE_IS_ARRAY (array)) if (!KATZE_IS_ARRAY (array))
return; return;
@ -385,18 +390,7 @@ katze_array_action_generate_menu (KatzeArrayAction* array_action,
} }
menuitem = katze_image_menu_item_new_ellipsized ( menuitem = katze_image_menu_item_new_ellipsized (
katze_item_get_name (item)); katze_item_get_name (item));
if ((icon_name = katze_item_get_icon (item)) && *icon_name) image = katze_item_get_image (item);
image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
else
{
if (KATZE_ITEM_IS_FOLDER (item))
icon = gtk_widget_render_icon (menuitem,
GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU, NULL);
else
icon = katze_load_cached_icon (katze_item_get_uri (item), proxy);
image = gtk_image_new_from_pixbuf (icon);
g_object_unref (icon);
}
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
gtk_image_menu_item_set_always_show_image ( gtk_image_menu_item_set_always_show_image (
GTK_IMAGE_MENU_ITEM (menuitem), TRUE); GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
@ -406,8 +400,13 @@ katze_array_action_generate_menu (KatzeArrayAction* array_action,
{ {
submenu = gtk_menu_new (); submenu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu); gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
/* Make sure menu appears to contain items */
gtk_menu_shell_append (GTK_MENU_SHELL (submenu),
gtk_separator_menu_item_new ());
g_signal_connect (menuitem, "select", g_signal_connect (menuitem, "select",
G_CALLBACK (katze_array_action_menu_item_select_cb), array_action); G_CALLBACK (katze_array_action_menu_item_select_cb), array_action);
g_signal_connect (menuitem, "activate",
G_CALLBACK (katze_array_action_menu_item_select_cb), array_action);
} }
else else
{ {
@ -421,21 +420,39 @@ katze_array_action_generate_menu (KatzeArrayAction* array_action,
} }
} }
static void static gboolean
katze_array_action_menu_item_select_cb (GtkWidget* proxy, katze_array_action_menu_item_need_update (KatzeArrayAction* array_action,
KatzeArrayAction* array_action) GtkWidget* proxy)
{ {
GtkWidget* menu; GtkWidget* menu;
KatzeArray* array; KatzeArray* array;
gint last_array_update, last_proxy_update;
gboolean handled; gboolean handled;
array = g_object_get_data (G_OBJECT (proxy), "KatzeItem");
/* last-update is set on all arrays; consider public API */
last_array_update = GPOINTER_TO_INT (
g_object_get_data (G_OBJECT (array), "last-update"));
last_proxy_update = GPOINTER_TO_INT (
g_object_get_data (G_OBJECT (proxy), "last-update"));
if (last_proxy_update > last_array_update)
return FALSE;
menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)); menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy));
gtk_container_foreach (GTK_CONTAINER (menu), gtk_container_foreach (GTK_CONTAINER (menu),
(GtkCallback)(gtk_widget_destroy), NULL); (GtkCallback)(gtk_widget_destroy), NULL);
array = g_object_get_data (G_OBJECT (proxy), "KatzeItem");
katze_array_action_generate_menu (array_action, array, GTK_MENU_SHELL (menu), proxy); katze_array_action_generate_menu (array_action, array, GTK_MENU_SHELL (menu), proxy);
g_signal_emit (array_action, signals[POPULATE_FOLDER], 0, menu, array, &handled); g_signal_emit (array_action, signals[POPULATE_FOLDER], 0, menu, array, &handled);
g_object_set_data (G_OBJECT (proxy), "last-update",
GINT_TO_POINTER (time (NULL)));
return TRUE;
}
static void
katze_array_action_menu_item_select_cb (GtkWidget* proxy,
KatzeArrayAction* array_action)
{
katze_array_action_menu_item_need_update (array_action, proxy);
} }
static void static void
@ -458,20 +475,21 @@ katze_array_action_proxy_clicked_cb (GtkWidget* proxy,
KatzeArray* array; KatzeArray* array;
gboolean handled = FALSE; gboolean handled = FALSE;
array = (KatzeArray*)g_object_get_data (G_OBJECT (proxy), "KatzeItem");
if (GTK_IS_MENU_ITEM (proxy)) if (GTK_IS_MENU_ITEM (proxy))
{ {
g_object_set_data (G_OBJECT (proxy), "KatzeItem", array_action->array); if (katze_array_action_menu_item_need_update (array_action, proxy))
katze_array_action_menu_item_select_cb (proxy, array_action); {
g_signal_emit (array_action, signals[POPULATE_FOLDER], 0, g_signal_emit (array_action, signals[POPULATE_FOLDER], 0,
gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)), gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)),
array_action->array, &handled); array, &handled);
if (!handled) if (!handled)
g_signal_emit (array_action, signals[POPULATE_POPUP], 0, g_signal_emit (array_action, signals[POPULATE_POPUP], 0,
gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy))); gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)));
}
return; return;
} }
array = (KatzeArray*)g_object_get_data (G_OBJECT (proxy), "KatzeArray");
if (KATZE_IS_ITEM (array) && katze_item_get_uri ((KatzeItem*)array)) if (KATZE_IS_ITEM (array) && katze_item_get_uri ((KatzeItem*)array))
{ {
katze_array_action_activate_item (array_action, KATZE_ITEM (array), 1); katze_array_action_activate_item (array_action, KATZE_ITEM (array), 1);
@ -552,7 +570,6 @@ katze_array_action_item_notify_cb (KatzeItem* item,
const gchar* property; const gchar* property;
const gchar* title; const gchar* title;
const gchar* desc; const gchar* desc;
GdkPixbuf* icon;
GtkWidget* image; GtkWidget* image;
if (!G_IS_PARAM_SPEC_STRING (pspec)) if (!G_IS_PARAM_SPEC_STRING (pspec))
@ -579,16 +596,13 @@ katze_array_action_item_notify_cb (KatzeItem* item,
} }
else if (KATZE_ITEM_IS_BOOKMARK (item) && !strcmp (property, "uri")) else if (KATZE_ITEM_IS_BOOKMARK (item) && !strcmp (property, "uri"))
{ {
icon = katze_load_cached_icon (katze_item_get_uri (item), GTK_WIDGET (toolitem)); image = katze_item_get_image (item);
image = gtk_image_new_from_pixbuf (icon);
g_object_unref (icon);
gtk_widget_show (image); gtk_widget_show (image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image); gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image);
} }
else if (!strcmp (property, "icon")) else if (!strcmp (property, "icon"))
{ {
image = gtk_image_new_from_icon_name (katze_item_get_icon (item), image = katze_item_get_image (item);
GTK_ICON_SIZE_MENU);
gtk_widget_show (image); gtk_widget_show (image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image); gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image);
} }
@ -600,25 +614,12 @@ katze_array_action_proxy_create_menu_proxy_cb (GtkWidget* proxy,
{ {
KatzeArrayAction* array_action; KatzeArrayAction* array_action;
GtkWidget* menuitem; GtkWidget* menuitem;
const gchar* icon_name;
GtkWidget* image; GtkWidget* image;
GdkPixbuf* icon;
array_action = g_object_get_data (G_OBJECT (proxy), "KatzeArrayAction"); array_action = g_object_get_data (G_OBJECT (proxy), "KatzeArrayAction");
menuitem = katze_image_menu_item_new_ellipsized ( menuitem = katze_image_menu_item_new_ellipsized (
katze_item_get_name (item)); katze_item_get_name (item));
if ((icon_name = katze_item_get_icon (item)) && *icon_name) image = katze_item_get_image (item);
image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
else
{
if (KATZE_ITEM_IS_FOLDER (item))
icon = gtk_widget_render_icon (menuitem,
GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU, NULL);
else
icon = katze_load_cached_icon (katze_item_get_uri (item), proxy);
image = gtk_image_new_from_pixbuf (icon);
g_object_unref (icon);
}
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
gtk_image_menu_item_set_always_show_image ( gtk_image_menu_item_set_always_show_image (
GTK_IMAGE_MENU_ITEM (menuitem), TRUE); GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
@ -674,7 +675,6 @@ katze_array_action_create_tool_item_for (KatzeArrayAction* array_action,
const gchar* uri; const gchar* uri;
const gchar* desc; const gchar* desc;
GtkToolItem* toolitem; GtkToolItem* toolitem;
GdkPixbuf* icon;
GtkWidget* image; GtkWidget* image;
GtkWidget* label; GtkWidget* label;
@ -686,20 +686,12 @@ katze_array_action_create_tool_item_for (KatzeArrayAction* array_action,
return gtk_separator_tool_item_new (); return gtk_separator_tool_item_new ();
if (KATZE_ITEM_IS_FOLDER (item)) if (KATZE_ITEM_IS_FOLDER (item))
{
toolitem = gtk_toggle_tool_button_new (); toolitem = gtk_toggle_tool_button_new ();
icon = gtk_widget_render_icon (GTK_WIDGET (toolitem),
GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU, NULL);
}
else else
{
toolitem = gtk_tool_button_new (NULL, ""); toolitem = gtk_tool_button_new (NULL, "");
icon = katze_load_cached_icon (uri, GTK_WIDGET (toolitem));
}
g_signal_connect (toolitem, "create-menu-proxy", g_signal_connect (toolitem, "create-menu-proxy",
G_CALLBACK (katze_array_action_proxy_create_menu_proxy_cb), item); G_CALLBACK (katze_array_action_proxy_create_menu_proxy_cb), item);
image = gtk_image_new_from_pixbuf (icon); image = katze_item_get_image (item);
g_object_unref (icon);
gtk_widget_show (image); gtk_widget_show (image);
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image); gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image);
label = gtk_label_new (NULL); label = gtk_label_new (NULL);
@ -739,6 +731,9 @@ static void
katze_array_action_connect_proxy (GtkAction* action, katze_array_action_connect_proxy (GtkAction* action,
GtkWidget* proxy) GtkWidget* proxy)
{ {
KatzeArrayAction* array_action = KATZE_ARRAY_ACTION (action);
g_object_set_data (G_OBJECT (proxy), "KatzeItem", array_action->array);
GTK_ACTION_CLASS (katze_array_action_parent_class)->connect_proxy ( GTK_ACTION_CLASS (katze_array_action_parent_class)->connect_proxy (
action, proxy); action, proxy);
@ -750,9 +745,10 @@ katze_array_action_connect_proxy (GtkAction* action,
else if (GTK_IS_MENU_ITEM (proxy)) else if (GTK_IS_MENU_ITEM (proxy))
{ {
gtk_menu_item_set_submenu (GTK_MENU_ITEM (proxy), gtk_menu_new ()); gtk_menu_item_set_submenu (GTK_MENU_ITEM (proxy), gtk_menu_new ());
/* FIXME: 'select' doesn't cover all ways of selection */
g_signal_connect (proxy, "select", g_signal_connect (proxy, "select",
G_CALLBACK (katze_array_action_proxy_clicked_cb), action); G_CALLBACK (katze_array_action_proxy_clicked_cb), action);
g_signal_connect (proxy, "activate",
G_CALLBACK (katze_array_action_proxy_clicked_cb), action);
} }
} }

View file

@ -27,7 +27,7 @@
#include <sqlite3.h> #include <sqlite3.h>
#define QUERY_ALL "SELECT id, name, value, host, path, expiry, lastAccessed, isSecure, isHttpOnly FROM moz_cookies;" #define QUERY_ALL "SELECT id, name, value, host, path, expiry, lastAccessed, isSecure, isHttpOnly FROM moz_cookies;"
#define CREATE_TABLE "CREATE TABLE moz_cookies (id INTEGER PRIMARY KEY, name TEXT, value TEXT, host TEXT, path TEXT,expiry INTEGER, lastAccessed INTEGER, isSecure INTEGER, isHttpOnly INTEGER)" #define CREATE_TABLE "CREATE TABLE IF NOT EXISTS moz_cookies (id INTEGER PRIMARY KEY, name TEXT, value TEXT, host TEXT, path TEXT,expiry INTEGER, lastAccessed INTEGER, isSecure INTEGER, isHttpOnly INTEGER)"
#define QUERY_INSERT "INSERT INTO moz_cookies VALUES(NULL, %Q, %Q, %Q, %Q, %d, NULL, %d, %d);" #define QUERY_INSERT "INSERT INTO moz_cookies VALUES(NULL, %Q, %Q, %Q, %Q, %d, NULL, %d, %d);"
#define QUERY_DELETE "DELETE FROM moz_cookies WHERE name=%Q AND host=%Q;" #define QUERY_DELETE "DELETE FROM moz_cookies WHERE name=%Q AND host=%Q;"
@ -71,80 +71,6 @@ G_DEFINE_TYPE_WITH_CODE (KatzeHttpCookiesSqlite, katze_http_cookies_sqlite, G_TY
Copyright (C) 2009 Collabora Ltd. Copyright (C) 2009 Collabora Ltd.
Mostly copied from libSoup 2.30, coding style retained */ Mostly copied from libSoup 2.30, coding style retained */
static void
try_create_table (sqlite3 *db)
{
char *error = NULL;
if (sqlite3_exec (db, CREATE_TABLE, NULL, NULL, &error)) {
g_warning ("Failed to execute query: %s", error);
sqlite3_free (error);
}
}
static void
exec_query_with_try_create_table (sqlite3* db,
const char* sql,
int (*callback)(void*,int,char**,char**),
void *argument)
{
char *error = NULL;
gboolean try_create = TRUE;
try_exec:
if (sqlite3_exec (db, sql, callback, argument, &error)) {
if (try_create) {
try_create = FALSE;
try_create_table (db);
sqlite3_free (error);
error = NULL;
goto try_exec;
} else {
g_warning ("Failed to execute query: %s", error);
sqlite3_free (error);
}
}
}
static int
callback (void *data, int argc, char **argv, char **colname)
{
SoupCookie *cookie = NULL;
SoupCookieJar *jar = SOUP_COOKIE_JAR (data);
char *name, *value, *host, *path;
gint64 expire_time;
time_t now;
int max_age;
gboolean http_only = FALSE, secure = FALSE;
now = time (NULL);
name = argv[COL_NAME];
value = argv[COL_VALUE];
host = argv[COL_HOST];
path = argv[COL_PATH];
expire_time = g_ascii_strtoull (argv[COL_EXPIRY], NULL, 10);
if (now >= expire_time)
return 0;
max_age = (expire_time - now <= G_MAXINT ? expire_time - now : G_MAXINT);
http_only = (g_strcmp0 (argv[COL_HTTP_ONLY], "1") == 0);
secure = (g_strcmp0 (argv[COL_SECURE], "1") == 0);
cookie = soup_cookie_new (name, value, host, path, max_age);
if (secure)
soup_cookie_set_secure (cookie, TRUE);
if (http_only)
soup_cookie_set_http_only (cookie, TRUE);
soup_cookie_jar_add_cookie (jar, cookie);
return 0;
}
/* Follows sqlite3 convention; returns TRUE on error */ /* Follows sqlite3 convention; returns TRUE on error */
static gboolean static gboolean
katze_http_cookies_sqlite_open_db (KatzeHttpCookiesSqlite* http_cookies) katze_http_cookies_sqlite_open_db (KatzeHttpCookiesSqlite* http_cookies)
@ -157,23 +83,91 @@ katze_http_cookies_sqlite_open_db (KatzeHttpCookiesSqlite* http_cookies)
return TRUE; return TRUE;
} }
if (sqlite3_exec (http_cookies->db, "PRAGMA synchronous = OFF; PRAGMA secure_delete = 1;", NULL, NULL, &error)) { if (sqlite3_exec (http_cookies->db, CREATE_TABLE, NULL, NULL, &error)) {
g_warning ("Failed to execute query: %s", error); g_warning ("Failed to execute query: %s", error);
sqlite3_free (error); sqlite3_free (error);
} }
if (sqlite3_exec (http_cookies->db, "PRAGMA secure_delete = 1;",
NULL, NULL, &error)) {
g_warning ("Failed to execute query: %s", error);
sqlite3_free (error);
}
sqlite3_exec (http_cookies->db,
/* Arguably cookies are like a cache, so performance over integrity */
"PRAGMA synchronous = OFF; PRAGMA temp_store = MEMORY;"
"PRAGMA count_changes = OFF; PRAGMA journal_mode = TRUNCATE;",
NULL, NULL, &error);
return FALSE; return FALSE;
} }
static void static void
katze_http_cookies_sqlite_load (KatzeHttpCookiesSqlite* http_cookies) katze_http_cookies_sqlite_load (KatzeHttpCookiesSqlite* http_cookies)
{ {
const char *name, *value, *host, *path;
sqlite3_stmt* stmt;
SoupCookie *cookie = NULL;
gint64 expire_time;
time_t now;
int max_age;
gboolean http_only = FALSE, secure = FALSE;
char *query;
int result;
if (http_cookies->db == NULL) { if (http_cookies->db == NULL) {
if (katze_http_cookies_sqlite_open_db (http_cookies)) if (katze_http_cookies_sqlite_open_db (http_cookies))
return; return;
} }
exec_query_with_try_create_table (http_cookies->db, QUERY_ALL, callback, http_cookies->jar); sqlite3_prepare_v2 (http_cookies->db, QUERY_ALL, strlen (QUERY_ALL) + 1, &stmt, NULL);
result = sqlite3_step (stmt);
if (result != SQLITE_ROW)
{
if (result == SQLITE_ERROR)
g_print (_("Failed to load cookies\n"));
sqlite3_reset (stmt);
return;
}
while (result == SQLITE_ROW)
{
now = time (NULL);
name = (const char*)sqlite3_column_text (stmt, COL_NAME);
value = (const char*)sqlite3_column_text (stmt, COL_VALUE);
host = (const char*)sqlite3_column_text (stmt, COL_HOST);
path = (const char*)sqlite3_column_text (stmt, COL_PATH);
expire_time = sqlite3_column_int64 (stmt,COL_EXPIRY);
secure = sqlite3_column_int (stmt, COL_SECURE);
http_only = sqlite3_column_int (stmt, COL_HTTP_ONLY);
if (now >= expire_time)
{
/* Cookie expired, remove it from database */
query = sqlite3_mprintf (QUERY_DELETE, name, host);
sqlite3_exec (http_cookies->db, QUERY_DELETE, NULL, NULL, NULL);
sqlite3_free (query);
result = sqlite3_step (stmt);
continue;
}
max_age = (expire_time - now <= G_MAXINT ? expire_time - now : G_MAXINT);
cookie = soup_cookie_new (name, value, host, path, max_age);
if (secure)
soup_cookie_set_secure (cookie, TRUE);
if (http_only)
soup_cookie_set_http_only (cookie, TRUE);
soup_cookie_jar_add_cookie (http_cookies->jar, cookie);
result = sqlite3_step (stmt);
}
if (stmt)
{
sqlite3_reset (stmt);
sqlite3_clear_bindings (stmt);
}
} }
static void static void
katze_http_cookies_sqlite_jar_changed_cb (SoupCookieJar* jar, katze_http_cookies_sqlite_jar_changed_cb (SoupCookieJar* jar,
@ -220,7 +214,7 @@ katze_http_cookies_sqlite_jar_changed_cb (SoupCookieJar* jar,
query = sqlite3_mprintf (QUERY_DELETE, query = sqlite3_mprintf (QUERY_DELETE,
old_cookie->name, old_cookie->name,
old_cookie->domain); old_cookie->domain);
exec_query_with_try_create_table (http_cookies->db, query, NULL, NULL); sqlite3_exec (http_cookies->db, query, NULL, NULL, NULL);
sqlite3_free (query); sqlite3_free (query);
} }
@ -234,7 +228,7 @@ katze_http_cookies_sqlite_jar_changed_cb (SoupCookieJar* jar,
expires, expires,
new_cookie->secure, new_cookie->secure,
new_cookie->http_only); new_cookie->http_only);
exec_query_with_try_create_table (http_cookies->db, query, NULL, NULL); sqlite3_exec (http_cookies->db, query, NULL, NULL, NULL);
sqlite3_free (query); sqlite3_free (query);
} }
} }

View file

@ -315,6 +315,8 @@ katze_item_set_name (KatzeItem* item,
g_return_if_fail (KATZE_IS_ITEM (item)); g_return_if_fail (KATZE_IS_ITEM (item));
katze_assign (item->name, g_strdup (name)); katze_assign (item->name, g_strdup (name));
if (item->parent)
katze_array_update ((KatzeArray*)item->parent);
g_object_notify (G_OBJECT (item), "name"); g_object_notify (G_OBJECT (item), "name");
} }
@ -414,9 +416,51 @@ katze_item_set_icon (KatzeItem* item,
g_return_if_fail (KATZE_IS_ITEM (item)); g_return_if_fail (KATZE_IS_ITEM (item));
katze_item_set_meta_string (item, "icon", icon); katze_item_set_meta_string (item, "icon", icon);
if (item->parent)
katze_array_update ((KatzeArray*)item->parent);
g_object_notify (G_OBJECT (item), "icon"); g_object_notify (G_OBJECT (item), "icon");
} }
/**
* katze_item_get_image:
* @item: a #KatzeItem
*
* Retrieves a #GtkImage fit to display @item.
*
* Return value: the icon of the item
*
* Since: 0.4.4
**/
GtkWidget*
katze_item_get_image (KatzeItem* item)
{
GtkWidget* image;
GdkPixbuf* pixbuf;
const gchar* icon;
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
if (KATZE_ITEM_IS_FOLDER (item))
image = gtk_image_new_from_stock (GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU);
else if ((pixbuf = g_object_get_data (G_OBJECT (item), "pixbuf")))
image = gtk_image_new_from_pixbuf (pixbuf);
else if ((icon = katze_item_get_icon (item)) && !strchr (icon, '/'))
image = gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_MENU);
else
{
if (!(icon && (pixbuf = katze_load_cached_icon (icon, NULL))))
pixbuf = katze_load_cached_icon (item->uri, NULL);
if (pixbuf)
{
image = gtk_image_new_from_pixbuf (pixbuf);
g_object_unref (pixbuf);
}
else
image = gtk_image_new_from_stock (GTK_STOCK_FILE, GTK_ICON_SIZE_MENU);
}
return image;
}
/** /**
* katze_item_get_token: * katze_item_get_token:
* @item: a #KatzeItem * @item: a #KatzeItem
@ -527,17 +571,22 @@ katze_item_set_meta_data_value (KatzeItem* item,
* Return value: a string, or %NULL * Return value: a string, or %NULL
* *
* Since: 0.1.8 * Since: 0.1.8
*
* Since 0.4.4 "" is treated like %NULL.
**/ **/
const gchar* const gchar*
katze_item_get_meta_string (KatzeItem* item, katze_item_get_meta_string (KatzeItem* item,
const gchar* key) const gchar* key)
{ {
const gchar* value;
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL); g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
g_return_val_if_fail (key != NULL, NULL); g_return_val_if_fail (key != NULL, NULL);
if (g_str_has_prefix (key, "midori:")) if (g_str_has_prefix (key, "midori:"))
key = &key[7]; key = &key[7];
return g_hash_table_lookup (item->metadata, key); value = g_hash_table_lookup (item->metadata, key);
return value && *value ? value : NULL;
} }
/** /**

View file

@ -12,7 +12,7 @@
#ifndef __KATZE_ITEM_H__ #ifndef __KATZE_ITEM_H__
#define __KATZE_ITEM_H__ #define __KATZE_ITEM_H__
#include <glib-object.h> #include <gtk/gtk.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -91,6 +91,9 @@ void
katze_item_set_icon (KatzeItem* item, katze_item_set_icon (KatzeItem* item,
const gchar* icon); const gchar* icon);
GtkWidget*
katze_item_get_image (KatzeItem* item);
const gchar* const gchar*
katze_item_get_token (KatzeItem* item); katze_item_get_token (KatzeItem* item);

View file

@ -97,12 +97,12 @@ katze_throbber_realize (GtkWidget* widget);
#if GTK_CHECK_VERSION (3, 0, 0) #if GTK_CHECK_VERSION (3, 0, 0)
static void static void
katze_throbber_get_preferred_height (GtkWidget *widget, katze_throbber_get_preferred_height (GtkWidget *widget,
gint *minimal_width, gint *minimal_height,
gint *natural_width); gint *natural_height);
static void static void
katze_throbber_get_preferred_width (GtkWidget *widget, katze_throbber_get_preferred_width (GtkWidget *widget,
gint *minimal_width, gint *minimal_width,
gint *natural_width); gint *natural_width);
#endif #endif
static void static void
katze_throbber_unrealize (GtkWidget* widget); katze_throbber_unrealize (GtkWidget* widget);
@ -495,8 +495,8 @@ katze_throbber_set_animated (KatzeThrobber* throbber,
(GSourceFunc)katze_throbber_timeout, (GSourceFunc)katze_throbber_timeout,
throbber, throbber,
(GDestroyNotify)katze_throbber_timeout_destroy); (GDestroyNotify)katze_throbber_timeout_destroy);
gtk_widget_queue_draw (GTK_WIDGET (throbber));
#endif #endif
gtk_widget_queue_draw (GTK_WIDGET (throbber));
g_object_notify (G_OBJECT (throbber), "animated"); g_object_notify (G_OBJECT (throbber), "animated");
} }
@ -857,14 +857,14 @@ katze_throbber_size_request (GtkWidget* widget,
#if GTK_CHECK_VERSION (3, 0, 0) #if GTK_CHECK_VERSION (3, 0, 0)
static void static void
katze_throbber_get_preferred_height (GtkWidget *widget, katze_throbber_get_preferred_height (GtkWidget *widget,
gint *minimal_width, gint *minimal_height,
gint *natural_width) gint *natural_height)
{ {
GtkRequisition requisition; GtkRequisition requisition;
katze_throbber_size_request (widget, &requisition); katze_throbber_size_request (widget, &requisition);
*minimal_width = *natural_width = requisition.height; *minimal_height = *natural_height = requisition.height;
} }
static void static void
@ -902,6 +902,7 @@ katze_throbber_aligned_coords (GtkWidget* widget,
#endif #endif
#if GTK_CHECK_VERSION (3, 0, 0) #if GTK_CHECK_VERSION (3, 0, 0)
allocation.x = allocation.y = 0;
allocation.width = gtk_widget_get_allocated_width (widget); allocation.width = gtk_widget_get_allocated_width (widget);
allocation.height = gtk_widget_get_allocated_height (widget); allocation.height = gtk_widget_get_allocated_height (widget);
gtk_widget_get_preferred_size (widget, &requisition, NULL); gtk_widget_get_preferred_size (widget, &requisition, NULL);

View file

@ -910,21 +910,29 @@ katze_widget_popup_position_menu (GtkMenu* menu,
GtkRequisition widget_req; GtkRequisition widget_req;
KatzePopupInfo* info = user_data; KatzePopupInfo* info = user_data;
GtkWidget* widget = info->widget; GtkWidget* widget = info->widget;
GdkWindow* window = gtk_widget_get_window (widget);
gint widget_height; gint widget_height;
gtk_widget_get_allocation (widget, &allocation); if (!window)
return;
#if !GTK_CHECK_VERSION (3, 0, 0)
if (GTK_IS_ENTRY (widget))
window = gdk_window_get_parent (window);
#endif
/* Retrieve size and position of both widget and menu */ /* Retrieve size and position of both widget and menu */
if (!gtk_widget_get_has_window (widget)) gtk_widget_get_allocation (widget, &allocation);
{ gdk_window_get_origin (window, &wx, &wy);
gdk_window_get_position (gtk_widget_get_window (widget), &wx, &wy); wx += allocation.x;
wx += allocation.x; wy += allocation.y;
wy += allocation.y; #if GTK_CHECK_VERSION (3, 0, 0)
} gtk_widget_get_preferred_size (GTK_WIDGET (menu), &menu_req, NULL);
else gtk_widget_get_preferred_size (widget, &widget_req, NULL);
gdk_window_get_origin (gtk_widget_get_window (widget), &wx, &wy); #else
gtk_widget_size_request (GTK_WIDGET (menu), &menu_req); gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
gtk_widget_size_request (widget, &widget_req); gtk_widget_size_request (widget, &widget_req);
#endif
menu_width = menu_req.width; menu_width = menu_req.width;
widget_height = widget_req.height; /* Better than allocation.height */ widget_height = widget_req.height; /* Better than allocation.height */
@ -1190,6 +1198,16 @@ katze_strip_mnemonics (const gchar* original)
return result; return result;
} }
const gchar*
katze_skip_whitespace (const gchar* str)
{
if (str == NULL)
return NULL;
while (*str == ' ' || *str == '\t' || *str == '\n')
str++;
return str;
}
/** /**
* katze_object_has_property: * katze_object_has_property:
* @object: a #GObject * @object: a #GObject
@ -1520,6 +1538,8 @@ katze_uri_entry_changed_cb (GtkWidget* entry,
{ {
const gchar* uri = gtk_entry_get_text (GTK_ENTRY (entry)); const gchar* uri = gtk_entry_get_text (GTK_ENTRY (entry));
gboolean valid = midori_uri_is_location (uri); gboolean valid = midori_uri_is_location (uri);
if (!valid && g_object_get_data (G_OBJECT (entry), "allow_%s"))
valid = uri && g_str_has_prefix (uri, "%s");
if (*uri && !valid) if (*uri && !valid)
{ {
GdkColor bg_color = { 0 }; GdkColor bg_color = { 0 };

View file

@ -58,6 +58,20 @@ G_BEGIN_DECLS
**/ **/
#define katze_strv_assign(lvalue, rvalue) lvalue = (g_strfreev (lvalue), rvalue) #define katze_strv_assign(lvalue, rvalue) lvalue = (g_strfreev (lvalue), rvalue)
/**
* katze_str_non_null:
* @str: a string, or %NULL
*
* Returns "" if @str is %NULL.
*
* Since: 0.4.4
**/
static inline const gchar*
katze_str_non_null (const gchar* str)
{
return str ? str : "";
}
GtkWidget* GtkWidget*
katze_property_proxy (gpointer object, katze_property_proxy (gpointer object,
const gchar* property, const gchar* property,
@ -101,6 +115,9 @@ katze_bookmark_populate_tree_view (KatzeArray* array,
gchar* gchar*
katze_strip_mnemonics (const gchar* original); katze_strip_mnemonics (const gchar* original);
const gchar*
katze_skip_whitespace (const gchar* str);
gboolean gboolean
katze_object_has_property (gpointer object, katze_object_has_property (gpointer object,
const gchar* property); const gchar* property);

View file

@ -85,6 +85,9 @@ namespace Midori {
if (uri == null) if (uri == null)
return keywords; return keywords;
string escaped = GLib.Uri.escape_string (keywords, ":/", true); string escaped = GLib.Uri.escape_string (keywords, ":/", true);
/* Allow DuckDuckGo to distinguish Midori and in turn share revenue */
if (uri == "https://duckduckgo.com/?q=%s")
return "https://duckduckgo.com/?q=%s&t=midori".printf (escaped);
if (uri.str ("%s") != null) if (uri.str ("%s") != null)
return uri.printf (escaped); return uri.printf (escaped);
return uri + escaped; return uri + escaped;
@ -122,8 +125,17 @@ namespace Midori {
FIXME: Schemes are not handled FIXME: Schemes are not handled
hostname_is_ip_address () is not used because hostname_is_ip_address () is not used because
we'd have to separate the path from the URI first. */ we'd have to separate the path from the URI first. */
return uri != null && uri[0].isdigit () if (uri == null)
&& (uri.chr (4, '.') != null || uri.chr (4, ':') != null); return false;
/* IPv4 */
if (uri[0].isdigit () && (uri.chr (4, '.') != null))
return true;
/* IPv6 */
if (uri[0].isalnum () && uri[1].isalnum ()
&& uri[2].isalnum () && uri[3].isalnum () && uri[4] == ':'
&& (uri[5] == ':' || uri[5].isalnum ()))
return true;
return false;
} }
public static bool is_valid (string? uri) { public static bool is_valid (string? uri) {
return uri != null return uri != null

View file

@ -441,7 +441,10 @@ midori_history_initialize (KatzeArray* array,
return FALSE; return FALSE;
} }
sqlite3_exec (db, "PRAGMA journal_mode = TRUNCATE;", NULL, NULL, errmsg); sqlite3_exec (db,
/* "PRAGMA synchronous = OFF; PRAGMA temp_store = MEMORY" */
"PRAGMA count_changes = OFF; PRAGMA journal_mode = TRUNCATE;",
NULL, NULL, errmsg);
if (*errmsg) if (*errmsg)
{ {
g_warning ("Failed to set journal mode: %s", *errmsg); g_warning ("Failed to set journal mode: %s", *errmsg);
@ -528,14 +531,14 @@ midori_bookmarks_remove_item_cb (KatzeArray* array,
"DELETE FROM bookmarks WHERE uri = '%q' " "DELETE FROM bookmarks WHERE uri = '%q' "
" AND folder = '%q'", " AND folder = '%q'",
katze_item_get_uri (item), katze_item_get_uri (item),
katze_item_get_meta_string (item, "folder")); katze_str_non_null (katze_item_get_meta_string (item, "folder")));
else else
sqlcmd = sqlite3_mprintf ( sqlcmd = sqlite3_mprintf (
"DELETE FROM bookmarks WHERE title = '%q'" "DELETE FROM bookmarks WHERE title = '%q'"
" AND folder = '%q'", " AND folder = '%q'",
katze_item_get_name (item), katze_item_get_name (item),
katze_item_get_meta_string (item, "folder")); katze_str_non_null (katze_item_get_meta_string (item, "folder")));
if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK) if (sqlite3_exec (db, sqlcmd, NULL, NULL, &errmsg) != SQLITE_OK)
{ {
@ -958,16 +961,19 @@ midori_soup_session_settings_accept_language_cb (SoupSession* session,
if (referer && destination && !strstr (referer, destination->host)) if (referer && destination && !strstr (referer, destination->host))
{ {
SoupURI* stripped_uri = soup_uri_new (referer); SoupURI* stripped_uri = soup_uri_new (referer);
gchar* stripped_referer; if (stripped_uri != NULL)
soup_uri_set_path (stripped_uri, NULL); {
soup_uri_set_query (stripped_uri, NULL); gchar* stripped_referer;
stripped_referer = soup_uri_to_string (stripped_uri, FALSE); soup_uri_set_path (stripped_uri, NULL);
soup_uri_free (stripped_uri); soup_uri_set_query (stripped_uri, NULL);
if (g_getenv ("MIDORI_SOUP_DEBUG")) stripped_referer = soup_uri_to_string (stripped_uri, FALSE);
g_message ("Referer stripped"); soup_uri_free (stripped_uri);
soup_message_headers_replace (msg->request_headers, "Referer", if (g_getenv ("MIDORI_SOUP_DEBUG"))
stripped_referer); g_message ("Referer %s stripped to %s", referer, stripped_referer);
g_free (stripped_referer); soup_message_headers_replace (msg->request_headers, "Referer",
stripped_referer);
g_free (stripped_referer);
}
} }
} }
} }
@ -1029,6 +1035,7 @@ midori_load_soup_session (gpointer settings)
NULL); NULL);
#endif #endif
g_object_set_data (G_OBJECT (session), "midori-settings", settings);
soup_session_settings_notify_http_proxy_cb (settings, NULL, session); soup_session_settings_notify_http_proxy_cb (settings, NULL, session);
g_signal_connect (settings, "notify::http-proxy", g_signal_connect (settings, "notify::http-proxy",
G_CALLBACK (soup_session_settings_notify_http_proxy_cb), session); G_CALLBACK (soup_session_settings_notify_http_proxy_cb), session);
@ -1474,21 +1481,6 @@ snapshot_load_finished_cb (GtkWidget* web_view,
gtk_main_quit (); gtk_main_quit ();
} }
static void
midori_web_app_browser_notify_load_status_cb (MidoriBrowser* browser,
GParamSpec* pspec,
gpointer data)
{
if (katze_object_get_enum (browser, "load-status") != MIDORI_LOAD_PROVISIONAL)
{
GtkWidget* view = midori_browser_get_current_tab (browser);
GdkPixbuf* icon = midori_view_get_icon (MIDORI_VIEW (view));
if (midori_view_is_blank (MIDORI_VIEW (view)))
icon = NULL;
gtk_window_set_icon (GTK_WINDOW (browser), icon);
}
}
static MidoriBrowser* static MidoriBrowser*
midori_web_app_browser_new_window_cb (MidoriBrowser* browser, midori_web_app_browser_new_window_cb (MidoriBrowser* browser,
MidoriBrowser* new_browser, MidoriBrowser* new_browser,
@ -1521,9 +1513,7 @@ midori_prepare_uri (const gchar *uri)
{ {
gchar* uri_ready; gchar* uri_ready;
if (g_path_is_absolute (uri)) if (g_str_has_prefix(uri, "javascript:"))
return g_filename_to_uri (uri, NULL, NULL);
else if (g_str_has_prefix(uri, "javascript:"))
return NULL; return NULL;
else if (g_file_test (uri, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) else if (g_file_test (uri, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
{ {
@ -1729,31 +1719,24 @@ midori_setup_inactivity_reset (MidoriBrowser* browser,
} }
} }
static void
midori_clear_page_icons_cb (void)
{
gchar* cache = g_build_filename (g_get_user_cache_dir (),
PACKAGE_NAME, "icons", NULL);
sokoke_remove_path (cache, TRUE);
g_free (cache);
cache = g_build_filename (g_get_user_data_dir (),
"webkit", "icondatabase", NULL);
sokoke_remove_path (cache, TRUE);
g_free (cache);
}
static void static void
midori_clear_web_cookies_cb (void) midori_clear_web_cookies_cb (void)
{ {
SoupSession* session = webkit_get_default_session (); SoupSession* session = webkit_get_default_session ();
MidoriWebSettings* settings = g_object_get_data (G_OBJECT (session), "midori-settings");
SoupSessionFeature* jar = soup_session_get_feature (session, SOUP_TYPE_COOKIE_JAR); SoupSessionFeature* jar = soup_session_get_feature (session, SOUP_TYPE_COOKIE_JAR);
GSList* cookies = soup_cookie_jar_all_cookies (SOUP_COOKIE_JAR (jar)); GSList* cookies = soup_cookie_jar_all_cookies (SOUP_COOKIE_JAR (jar));
SoupSessionFeature* feature; SoupSessionFeature* feature;
gchar* cache;
/* HTTP Cookies/ Web Cookies */
for (; cookies != NULL; cookies = g_slist_next (cookies)) for (; cookies != NULL; cookies = g_slist_next (cookies))
{ {
SoupCookie* cookie = cookies->data; const gchar* domain = ((SoupCookie*)cookies->data)->domain;
soup_cookie_jar_delete_cookie ((SoupCookieJar*)jar, cookie); if (midori_web_settings_get_site_data_policy (settings, domain)
== MIDORI_SITE_DATA_PRESERVE)
continue;
soup_cookie_jar_delete_cookie ((SoupCookieJar*)jar, cookies->data);
} }
soup_cookies_free (cookies); soup_cookies_free (cookies);
/* Removing KatzeHttpCookies makes it save outstanding changes */ /* Removing KatzeHttpCookies makes it save outstanding changes */
@ -1764,18 +1747,36 @@ midori_clear_web_cookies_cb (void)
soup_session_add_feature (session, feature); soup_session_add_feature (session, feature);
g_object_unref (feature); g_object_unref (feature);
} }
}
#ifdef GDK_WINDOWING_X11 /* Local shared objects/ Flash cookies */
static void if (midori_web_settings_has_plugin_support ())
midori_clear_flash_cookies_cb (void) {
{ #ifdef GDK_WINDOWING_X11
gchar* cache = g_build_filename (g_get_home_dir (), ".macromedia", cache = g_build_filename (g_get_home_dir (), ".macromedia", "Flash_Player", NULL);
"Flash_Player", NULL);
sokoke_remove_path (cache, TRUE); sokoke_remove_path (cache, TRUE);
g_free (cache); g_free (cache);
#elif defined(GDK_WINDOWING_WIN32)
cache = g_build_filename (g_get_user_data_dir (), "Macromedia", "Flash Player", NULL);
sokoke_remove_path (cache, TRUE);
g_free (cache);
#elif defined(GDK_WINDOWING_QUARTZ)
cache = g_build_filename (g_get_home_dir (), "Library", "Preferences",
"Macromedia", "Flash Player", NULL);
sokoke_remove_path (cache, TRUE);
g_free (cache);
#endif
}
/* HTML5 databases */
webkit_remove_all_web_databases ();
/* HTML5 offline application caches */
#if WEBKIT_CHECK_VERSION (1, 3, 13)
/* Changing the size implies clearing the cache */
webkit_application_cache_set_maximum_size (
webkit_application_cache_get_maximum_size () - 1);
#endif
} }
#endif
static void static void
midori_clear_saved_logins_cb (void) midori_clear_saved_logins_cb (void)
@ -1794,35 +1795,33 @@ midori_clear_saved_logins_cb (void)
g_free (path); g_free (path);
} }
static void
midori_clear_html5_databases_cb (void)
{
webkit_remove_all_web_databases ();
}
#if WEBKIT_CHECK_VERSION (1, 3, 11) #if WEBKIT_CHECK_VERSION (1, 3, 11)
static void static void
midori_clear_web_cache_cb (void) midori_clear_web_cache_cb (void)
{ {
SoupSession* session = webkit_get_default_session (); SoupSession* session = webkit_get_default_session ();
SoupSessionFeature* feature = soup_session_get_feature (session, SOUP_TYPE_CACHE); SoupSessionFeature* feature = soup_session_get_feature (session, SOUP_TYPE_CACHE);
gchar* path = g_build_filename (g_get_user_cache_dir (), PACKAGE_NAME, "web", NULL); gchar* cache = g_build_filename (g_get_user_cache_dir (), PACKAGE_NAME, "web", NULL);
soup_cache_clear (SOUP_CACHE (feature)); soup_cache_clear (SOUP_CACHE (feature));
soup_cache_flush (SOUP_CACHE (feature)); soup_cache_flush (SOUP_CACHE (feature));
sokoke_remove_path (path, TRUE); sokoke_remove_path (cache, TRUE);
g_free (path); g_free (cache);
} }
#endif #endif
#if WEBKIT_CHECK_VERSION (1, 3, 13)
static void static void
midori_clear_offline_appcache_cb (void) midori_clear_page_icons_cb (void)
{ {
/* Changing the size implies clearing the cache */ gchar* cache = g_build_filename (g_get_user_cache_dir (),
unsigned long long maximum = webkit_application_cache_get_maximum_size (); PACKAGE_NAME, "icons", NULL);
webkit_application_cache_set_maximum_size (maximum - 1); /* FIXME: Exclude search engine icons */
sokoke_remove_path (cache, TRUE);
g_free (cache);
cache = g_build_filename (g_get_user_data_dir (),
"webkit", "icondatabase", NULL);
sokoke_remove_path (cache, TRUE);
g_free (cache);
} }
#endif
static void static void
midori_log_to_file (const gchar* log_domain, midori_log_to_file (const gchar* log_domain,
@ -2009,6 +2008,9 @@ main (int argc,
else else
g_set_application_name (_("Midori")); g_set_application_name (_("Midori"));
/* Versioned prgname to override menuproxy blacklist */
g_set_prgname (PACKAGE_NAME "4");
if (version) if (version)
{ {
g_print ( g_print (
@ -2104,34 +2106,24 @@ main (int argc,
g_log_set_default_handler (midori_log_to_file, (gpointer)logfile); g_log_set_default_handler (midori_log_to_file, (gpointer)logfile);
} }
sokoke_register_privacy_item ("page-icons", _("Website icons"),
G_CALLBACK (midori_clear_page_icons_cb));
/* i18n: Logins and passwords in websites and web forms */ /* i18n: Logins and passwords in websites and web forms */
sokoke_register_privacy_item ("formhistory", _("Saved logins and _passwords"), sokoke_register_privacy_item ("formhistory", _("Saved logins and _passwords"),
G_CALLBACK (midori_clear_saved_logins_cb)); G_CALLBACK (midori_clear_saved_logins_cb));
sokoke_register_privacy_item ("web-cookies", _("Cookies"), sokoke_register_privacy_item ("web-cookies", _("Cookies and Website data"),
G_CALLBACK (midori_clear_web_cookies_cb)); G_CALLBACK (midori_clear_web_cookies_cb));
#ifdef GDK_WINDOWING_X11
sokoke_register_privacy_item ("flash-cookies", _("'Flash' Cookies"),
G_CALLBACK (midori_clear_flash_cookies_cb));
#endif
sokoke_register_privacy_item ("html5-databases", _("HTML5 _Databases"),
G_CALLBACK (midori_clear_html5_databases_cb));
#if WEBKIT_CHECK_VERSION (1, 3, 11) #if WEBKIT_CHECK_VERSION (1, 3, 11)
/* TODO: Preserve page icons of search engines and merge privacy items */
sokoke_register_privacy_item ("web-cache", _("Web Cache"), sokoke_register_privacy_item ("web-cache", _("Web Cache"),
G_CALLBACK (midori_clear_web_cache_cb)); G_CALLBACK (midori_clear_web_cache_cb));
sokoke_register_privacy_item ("offline-appcache", _("Offline Application Cache"),
G_CALLBACK (midori_clear_offline_appcache_cb));
#endif #endif
sokoke_register_privacy_item ("page-icons", _("Website icons"),
G_CALLBACK (midori_clear_page_icons_cb));
/* Web Application or Private Browsing support */ /* Web Application or Private Browsing support */
if (webapp || private || run) if (webapp || private || run)
{ {
SoupSession* session = webkit_get_default_session (); SoupSession* session = webkit_get_default_session ();
MidoriBrowser* browser = midori_browser_new (); MidoriBrowser* browser = midori_browser_new ();
/* Update window icon according to page */
g_signal_connect (browser, "notify::load-status",
G_CALLBACK (midori_web_app_browser_notify_load_status_cb), NULL);
g_signal_connect (browser, "new-window", g_signal_connect (browser, "new-window",
G_CALLBACK (midori_web_app_browser_new_window_cb), NULL); G_CALLBACK (midori_web_app_browser_new_window_cb), NULL);
g_object_set_data (G_OBJECT (webkit_get_default_session ()), g_object_set_data (G_OBJECT (webkit_get_default_session ()),
@ -2283,6 +2275,10 @@ main (int argc,
} }
} }
/* Informative text for private browsing unless we have a URI */
if (private && webapp == NULL && uris == NULL)
midori_browser_add_uri (browser, "about:private");
if (midori_browser_get_current_uri (browser) == NULL) if (midori_browser_get_current_uri (browser) == NULL)
midori_browser_add_uri (browser, "about:blank"); midori_browser_add_uri (browser, "about:blank");

View file

@ -69,7 +69,6 @@ struct _MidoriApp
GObject parent_instance; GObject parent_instance;
MidoriBrowser* browser; MidoriBrowser* browser;
GtkAccelGroup* accel_group;
gchar* name; gchar* name;
MidoriWebSettings* settings; MidoriWebSettings* settings;
@ -216,7 +215,6 @@ _midori_app_add_browser (MidoriApp* app,
g_return_if_fail (MIDORI_IS_APP (app)); g_return_if_fail (MIDORI_IS_APP (app));
g_return_if_fail (MIDORI_IS_BROWSER (browser)); g_return_if_fail (MIDORI_IS_BROWSER (browser));
gtk_window_add_accel_group (GTK_WINDOW (browser), app->accel_group);
g_object_connect (browser, g_object_connect (browser,
"signal::focus-in-event", midori_browser_focus_in_event_cb, app, "signal::focus-in-event", midori_browser_focus_in_event_cb, app,
"signal::new-window", midori_browser_new_window_cb, app, "signal::new-window", midori_browser_new_window_cb, app,
@ -722,12 +720,16 @@ midori_app_create_instance (MidoriApp* app)
if (!app->name) if (!app->name)
{ {
#if HAVE_UNIQUE
const gchar* config = sokoke_set_config_dir (NULL); const gchar* config = sokoke_set_config_dir (NULL);
gchar* name_hash; gchar* name_hash;
name_hash = g_compute_checksum_for_string (G_CHECKSUM_MD5, config, -1); name_hash = g_compute_checksum_for_string (G_CHECKSUM_MD5, config, -1);
app->name = g_strconcat ("midori", "_", name_hash, NULL); app->name = g_strconcat ("midori", "_", name_hash, NULL);
g_free (name_hash); g_free (name_hash);
g_object_notify (G_OBJECT (app), "name"); g_object_notify (G_OBJECT (app), "name");
#else
app->name = g_strdup (PACKAGE_NAME);
#endif
} }
if (!(display = gdk_display_get_default ())) if (!(display = gdk_display_get_default ()))
@ -767,8 +769,6 @@ midori_app_create_instance (MidoriApp* app)
static void static void
midori_app_init (MidoriApp* app) midori_app_init (MidoriApp* app)
{ {
app->accel_group = gtk_accel_group_new ();
app->settings = NULL; app->settings = NULL;
app->bookmarks = NULL; app->bookmarks = NULL;
app->trash = NULL; app->trash = NULL;
@ -793,8 +793,6 @@ midori_app_finalize (GObject* object)
{ {
MidoriApp* app = MIDORI_APP (object); MidoriApp* app = MIDORI_APP (object);
g_object_unref (app->accel_group);
katze_assign (app->name, NULL); katze_assign (app->name, NULL);
katze_object_assign (app->settings, NULL); katze_object_assign (app->settings, NULL);
katze_object_assign (app->bookmarks, NULL); katze_object_assign (app->bookmarks, NULL);
@ -1351,7 +1349,9 @@ midori_app_setup (gchar** argument_vector)
/* libSoup uses threads, therefore if WebKit is built with libSoup /* libSoup uses threads, therefore if WebKit is built with libSoup
* or Midori is using it, we need to initialize threads. */ * or Midori is using it, we need to initialize threads. */
#if !GLIB_CHECK_VERSION (2, 32, 0)
if (!g_thread_supported ()) g_thread_init (NULL); if (!g_thread_supported ()) g_thread_init (NULL);
#endif
#if ENABLE_NLS #if ENABLE_NLS
setlocale (LC_ALL, ""); setlocale (LC_ALL, "");

View file

@ -1067,28 +1067,32 @@ katze_array_from_sqlite (sqlite3* db,
} }
/** /**
* midori_array_query: * midori_array_query_recursive:
* @array: the main bookmark array * @array: the main bookmark array
* @fields: comma separated list of fields * @fields: comma separated list of fields
* @condition: condition, like "folder = '%q'" * @condition: condition, like "folder = '%q'"
* @value: a value to be inserted if @condition contains %q * @value: a value to be inserted if @condition contains %q
* @recursive: if %TRUE include children
* *
* Stores the result in a #KatzeArray. * Stores the result in a #KatzeArray.
* *
* Return value: a #KatzeArray on success, %NULL otherwise * Return value: a #KatzeArray on success, %NULL otherwise
* *
* Since: 0.4.3 * Since: 0.4.4
**/ **/
KatzeArray* KatzeArray*
midori_array_query (KatzeArray* bookmarks, midori_array_query_recursive (KatzeArray* bookmarks,
const gchar* fields, const gchar* fields,
const gchar* condition, const gchar* condition,
const gchar* value) const gchar* value,
gboolean recursive)
{ {
sqlite3* db; sqlite3* db;
gchar* sqlcmd; gchar* sqlcmd;
char* sqlcmd_value; char* sqlcmd_value;
KatzeArray* array; KatzeArray* array;
KatzeItem* item;
GList* list;
g_return_val_if_fail (KATZE_IS_ARRAY (bookmarks), NULL); g_return_val_if_fail (KATZE_IS_ARRAY (bookmarks), NULL);
g_return_val_if_fail (fields, NULL); g_return_val_if_fail (fields, NULL);
@ -1108,6 +1112,45 @@ midori_array_query (KatzeArray* bookmarks,
else else
array = katze_array_from_sqlite (db, sqlcmd); array = katze_array_from_sqlite (db, sqlcmd);
g_free (sqlcmd); g_free (sqlcmd);
if (!recursive)
return array;
KATZE_ARRAY_FOREACH_ITEM_L (item, array, list)
{
if (KATZE_ITEM_IS_FOLDER (item))
{
KatzeArray* subarray = midori_array_query_recursive (bookmarks,
fields, "folder='%q'", item->name, TRUE);
katze_item_set_name (KATZE_ITEM (subarray), item->name);
katze_array_add_item (array, subarray);
}
}
g_list_free (list);
return array; return array;
} }
/**
* midori_array_query:
* @array: the main bookmark array
* @fields: comma separated list of fields
* @condition: condition, like "folder = '%q'"
* @value: a value to be inserted if @condition contains %q
*
* Stores the result in a #KatzeArray.
*
* Return value: a #KatzeArray on success, %NULL otherwise
*
* Since: 0.4.3
*
* Deprecated: 0.4.4: Use midori_array_query_recursive() instead.
**/
KatzeArray*
midori_array_query (KatzeArray* bookmarks,
const gchar* fields,
const gchar* condition,
const gchar* value)
{
return midori_array_query_recursive (bookmarks, fields, condition, value, FALSE);
}

View file

@ -36,6 +36,13 @@ midori_array_query (KatzeArray* array,
const gchar* condition, const gchar* condition,
const gchar* value); const gchar* value);
KatzeArray*
midori_array_query_recursive (KatzeArray* array,
const gchar* fields,
const gchar* condition,
const gchar* value,
gboolean recursive);
KatzeArray* KatzeArray*
katze_array_from_sqlite (sqlite3* db, katze_array_from_sqlite (sqlite3* db,
const gchar* sqlcmd); const gchar* sqlcmd);

View file

@ -37,10 +37,6 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef HAVE_HILDON_2_2 #ifdef HAVE_HILDON_2_2
#include <dbus/dbus.h> #include <dbus/dbus.h>
#include <mce/mode-names.h> #include <mce/mode-names.h>
@ -65,7 +61,6 @@ struct _MidoriBrowser
GtkActionGroup* action_group; GtkActionGroup* action_group;
GtkWidget* menubar; GtkWidget* menubar;
GtkWidget* menu_tools;
GtkWidget* throbber; GtkWidget* throbber;
GtkWidget* navigationbar; GtkWidget* navigationbar;
GtkWidget* bookmarkbar; GtkWidget* bookmarkbar;
@ -177,11 +172,6 @@ midori_bookmarks_import_array_db (sqlite3* db,
KatzeArray* array, KatzeArray* array,
gchar* folder); gchar* folder);
void
midori_bookmarks_export_array_db (sqlite3* db,
KatzeArray* array,
const gchar* folder);
void void
midori_browser_open_bookmark (MidoriBrowser* browser, midori_browser_open_bookmark (MidoriBrowser* browser,
KatzeItem* item); KatzeItem* item);
@ -303,8 +293,7 @@ _midori_browser_update_interface (MidoriBrowser* browser)
_action_set_sensitive (browser, "Next", _action_set_sensitive (browser, "Next",
midori_view_get_next_page (view) != NULL); midori_view_get_next_page (view) != NULL);
gtk_action_set_visible (_action_by_name (browser, "AddSpeedDial"), _action_set_visible (browser, "AddSpeedDial", !midori_view_is_blank (view));
!midori_view_is_blank (view));
_action_set_sensitive (browser, "SaveAs", midori_view_can_save (view)); _action_set_sensitive (browser, "SaveAs", midori_view_can_save (view));
_action_set_sensitive (browser, "Print", midori_view_can_print (view)); _action_set_sensitive (browser, "Print", midori_view_can_print (view));
_action_set_sensitive (browser, "ZoomIn", midori_view_can_zoom_in (view)); _action_set_sensitive (browser, "ZoomIn", midori_view_can_zoom_in (view));
@ -355,13 +344,13 @@ _midori_browser_update_interface (MidoriBrowser* browser)
{ {
midori_location_action_set_secondary_icon ( midori_location_action_set_secondary_icon (
MIDORI_LOCATION_ACTION (action), STOCK_NEWS_FEED); MIDORI_LOCATION_ACTION (action), STOCK_NEWS_FEED);
gtk_action_set_sensitive (_action_by_name (browser, "AddNewsFeed"), TRUE); _action_set_sensitive (browser, "AddNewsFeed", TRUE);
} }
else else
{ {
midori_location_action_set_secondary_icon ( midori_location_action_set_secondary_icon (
MIDORI_LOCATION_ACTION (action), GTK_STOCK_JUMP_TO); MIDORI_LOCATION_ACTION (action), GTK_STOCK_JUMP_TO);
gtk_action_set_sensitive (_action_by_name (browser, "AddNewsFeed"), FALSE); _action_set_sensitive (browser, "AddNewsFeed", FALSE);
} }
midori_location_action_set_security_hint ( midori_location_action_set_security_hint (
MIDORI_LOCATION_ACTION (action), midori_view_get_security (view)); MIDORI_LOCATION_ACTION (action), midori_view_get_security (view));
@ -484,19 +473,16 @@ midori_view_notify_icon_cb (MidoriView* view,
GParamSpec* pspec, GParamSpec* pspec,
MidoriBrowser* browser) MidoriBrowser* browser)
{ {
const gchar* uri;
GtkAction* action; GtkAction* action;
if (midori_browser_get_current_tab (browser) != (GtkWidget*)view) if (midori_browser_get_current_tab (browser) != (GtkWidget*)view)
return; return;
uri = midori_view_get_display_uri (view);
action = _action_by_name (browser, "Location"); action = _action_by_name (browser, "Location");
if (browser->maximum_history_age)
midori_location_action_set_icon_for_uri (
MIDORI_LOCATION_ACTION (action), midori_view_get_icon (view), uri);
midori_location_action_set_icon (MIDORI_LOCATION_ACTION (action), midori_location_action_set_icon (MIDORI_LOCATION_ACTION (action),
midori_view_get_icon (view)); midori_view_get_icon (view));
if (sokoke_is_app_or_private ())
gtk_window_set_icon (GTK_WINDOW (browser), midori_view_get_icon (view));
} }
static void static void
@ -532,7 +518,7 @@ midori_view_notify_load_status_cb (GtkWidget* widget,
/* This is a hack to ensure that the address entry is focussed /* This is a hack to ensure that the address entry is focussed
with speed dial open. */ with speed dial open. */
if (midori_view_is_blank (view)) if (midori_view_is_blank (view))
gtk_action_activate (_action_by_name (browser, "Location")); midori_browser_activate_action (browser, "Location");
} }
g_object_notify (G_OBJECT (browser), "load-status"); g_object_notify (G_OBJECT (browser), "load-status");
@ -995,14 +981,9 @@ midori_browser_prepare_download (MidoriBrowser* browser,
return TRUE; return TRUE;
} }
static gchar*
midori_browser_save_source (const gchar* uri,
const gchar* data,
const size_t len,
const gchar* outfile);
static void static void
midori_browser_save_uri (MidoriBrowser* browser, midori_browser_save_uri (MidoriBrowser* browser,
MidoriView* view,
const gchar* uri) const gchar* uri)
{ {
static gchar* last_dir = NULL; static gchar* last_dir = NULL;
@ -1011,7 +992,6 @@ midori_browser_save_uri (MidoriBrowser* browser,
gchar* filename; gchar* filename;
gchar* dirname; gchar* dirname;
gchar* last_slash; gchar* last_slash;
gchar* folder;
if (!gtk_widget_get_visible (GTK_WIDGET (browser))) if (!gtk_widget_get_visible (GTK_WIDGET (browser)))
return; return;
@ -1049,24 +1029,11 @@ midori_browser_save_uri (MidoriBrowser* browser,
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK)
{ {
GtkWidget* view;
GtkWidget* web_view;
WebKitWebDataSource *data_source;
WebKitWebFrame *frame;
const GString *data;
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)); midori_view_save_source (view, uri, filename);
view = midori_browser_get_current_tab (browser);
web_view = midori_view_get_web_view (MIDORI_VIEW (view));
frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view));
data_source = webkit_web_frame_get_data_source (frame);
data = webkit_web_data_source_get_data (data_source);
if (data)
midori_browser_save_source (uri, data->str, data->len, filename);
g_free (last_dir); katze_assign (last_dir,
last_dir = folder; gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)));
} }
gtk_widget_destroy (dialog); gtk_widget_destroy (dialog);
} }
@ -1076,10 +1043,8 @@ midori_view_save_as_cb (GtkWidget* menuitem,
const gchar* uri, const gchar* uri,
GtkWidget* view) GtkWidget* view)
{ {
MidoriBrowser* browser; MidoriBrowser* browser = midori_browser_get_for_widget (view);
midori_browser_save_uri (browser, MIDORI_VIEW (view), uri);
browser = midori_browser_get_for_widget (menuitem);
midori_browser_save_uri (browser, uri);
} }
static gchar* static gchar*
@ -1185,7 +1150,7 @@ midori_view_activate_action_cb (GtkWidget* view,
const gchar* action, const gchar* action,
MidoriBrowser* browser) MidoriBrowser* browser)
{ {
_midori_browser_activate_action (browser, action); midori_browser_activate_action (browser, action);
} }
static void static void
@ -1246,11 +1211,11 @@ midori_browser_view_copy_history (GtkWidget* view_to,
} }
} }
static gint static gboolean
midori_browser_notify_new_tab_timeout_cb (MidoriBrowser *browser) midori_browser_notify_new_tab_timeout_cb (MidoriBrowser *browser)
{ {
gtk_window_set_opacity (GTK_WINDOW (browser), 1); gtk_window_set_opacity (GTK_WINDOW (browser), 1);
return 0; return G_SOURCE_REMOVE;
} }
static void static void
@ -1351,20 +1316,129 @@ midori_view_download_save_as_response_cb (GtkWidget* dialog,
gtk_widget_hide (dialog); gtk_widget_hide (dialog);
} }
static void
midori_browser_download_status_cb (WebKitDownload* download,
GParamSpec* pspec,
gpointer user_data)
{
const gchar* uri = webkit_download_get_destination_uri (download);
switch (webkit_download_get_status (download))
{
case WEBKIT_DOWNLOAD_STATUS_FINISHED:
if (!g_app_info_launch_default_for_uri (uri, NULL, NULL))
{
sokoke_message_dialog (GTK_MESSAGE_ERROR,
_("Error opening the image!"),
_("Can not open selected image in a default viewer."), FALSE);
}
break;
case WEBKIT_DOWNLOAD_STATUS_ERROR:
webkit_download_cancel (download);
sokoke_message_dialog (GTK_MESSAGE_ERROR,
_("Error downloading the image!"),
_("Can not downlaod selected image."), FALSE);
break;
case WEBKIT_DOWNLOAD_STATUS_CREATED:
case WEBKIT_DOWNLOAD_STATUS_STARTED:
case WEBKIT_DOWNLOAD_STATUS_CANCELLED:
break;
}
}
static gchar*
midori_browser_download_prepare_filename (gchar* filename)
{
if (g_file_test (filename, G_FILE_TEST_EXISTS))
{
int i = 1;
const gchar* dot_pos;
const gchar* last_separator;
gchar* serial;
GString* tmp_filename;
gssize position;
last_separator = strrchr (filename, G_DIR_SEPARATOR);
dot_pos = strrchr ((last_separator) ? last_separator : filename, '.');
position = dot_pos ? (dot_pos - filename) : (gssize) strlen (filename);
tmp_filename = g_string_new (NULL);
do
{
serial = g_strdup_printf ("-%d", i++);
g_string_assign (tmp_filename, filename);
g_string_insert (tmp_filename, position, serial);
g_free (serial);
} while (g_file_test (tmp_filename->str, G_FILE_TEST_EXISTS));
g_free (filename);
filename = g_string_free (tmp_filename, FALSE);
}
return filename;
}
static gchar*
midori_browser_download_prepare_destination_uri (WebKitDownload* download,
const gchar* folder)
{
const gchar* suggested_filename;
GFile* file_source;
gchar* file_basename;
gchar* download_dir = NULL;
gchar* destination_uri;
gchar* destination_filename;
gchar* midori_tmp_dir;
suggested_filename = webkit_download_get_suggested_filename (download);
file_source = g_file_new_for_uri (suggested_filename);
file_basename = g_file_get_basename (file_source);
if (folder == NULL)
{
midori_tmp_dir = g_strconcat ("midori-", g_get_user_name (), NULL);
download_dir = g_build_filename (g_get_tmp_dir (), midori_tmp_dir, NULL);
g_free (midori_tmp_dir);
}
else
download_dir = (gchar*)folder;
destination_filename = g_build_filename (download_dir, file_basename, NULL);
destination_filename = midori_browser_download_prepare_filename (destination_filename);
destination_uri = g_filename_to_uri (destination_filename, NULL, NULL);
if (!g_file_test (download_dir, G_FILE_TEST_EXISTS))
katze_mkdir_with_parents (download_dir, 0700);
g_free (file_basename);
if (folder == NULL)
g_free (download_dir);
g_free (destination_filename);
g_object_unref (file_source);
return destination_uri;
}
static gboolean static gboolean
midori_view_download_requested_cb (GtkWidget* view, midori_view_download_requested_cb (GtkWidget* view,
WebKitDownload* download, WebKitDownload* download,
MidoriBrowser* browser) MidoriBrowser* browser)
{ {
if (!webkit_download_get_destination_uri (download)) if (g_object_get_data (G_OBJECT (download), "open-in-viewer"))
{
gchar* destination_uri =
midori_browser_download_prepare_destination_uri (download, NULL);
midori_browser_prepare_download (browser, download, destination_uri);
g_signal_connect (download, "notify::status",
G_CALLBACK (midori_browser_download_status_cb), (gpointer) browser);
webkit_download_start (download);
g_free (destination_uri);
}
else if (!webkit_download_get_destination_uri (download))
{ {
gchar* folder;
if (g_object_get_data (G_OBJECT (download), "save-as-download")) if (g_object_get_data (G_OBJECT (download), "save-as-download"))
{ {
static GtkWidget* dialog = NULL; static GtkWidget* dialog = NULL;
if (!dialog) if (!dialog)
{ {
gchar* folder;
dialog = sokoke_file_chooser_dialog_new (_("Save file"), dialog = sokoke_file_chooser_dialog_new (_("Save file"),
GTK_WINDOW (browser), GTK_FILE_CHOOSER_ACTION_SAVE); GTK_WINDOW (browser), GTK_FILE_CHOOSER_ACTION_SAVE);
gtk_file_chooser_set_do_overwrite_confirmation ( gtk_file_chooser_set_do_overwrite_confirmation (
@ -1385,58 +1459,12 @@ midori_view_download_requested_cb (GtkWidget* view,
} }
else else
{ {
const gchar* suggested; gchar* folder = g_object_get_data (G_OBJECT (download), "open-download")
gchar* basename; ? NULL : katze_object_get_string (browser->settings, "download-folder");
gchar* filename; gchar* destination_uri =
gchar* uri; midori_browser_download_prepare_destination_uri (download, folder);
midori_browser_prepare_download (browser, download, destination_uri);
if (g_object_get_data (G_OBJECT (download), "open-download")) g_free (destination_uri);
folder = g_strdup (g_get_tmp_dir ());
else
folder = katze_object_get_string (browser->settings, "download-folder");
suggested = webkit_download_get_suggested_filename (download);
/* The suggested name may contain a folder name */
basename = g_path_get_basename (suggested);
filename = g_build_filename (folder, basename, NULL);
g_free (basename);
/* If the filename exists, choose a different name */
if (g_access (filename, F_OK) == 0)
{
/* Put the number in front of the extension */
gchar* extension = strrchr (filename, '.');
gsize length = extension ? (gsize)(extension - filename) : strlen (filename);
do
{
if (g_ascii_isdigit (filename[length - 1]))
filename[length - 1] += 1; /* FIXME: This will increment '9' to ':' */
else
{
gchar* new_filename;
if (extension)
{
/* Change the '.' to a '\0' to put the 0 in between */
*extension++ = '\0';
new_filename= g_strconcat (filename, "0.", extension, NULL);
}
else
new_filename = g_strconcat (filename, "0", NULL);
katze_assign (filename, new_filename);
if (extension)
{
extension = strrchr (filename, '.');
length = extension - filename;
}
else
length = strlen (filename);
}
}
while (g_access (filename, F_OK) == 0);
}
g_free (folder);
uri = g_filename_to_uri (filename, NULL, NULL);
g_free (filename);
midori_browser_prepare_download (browser, download, uri);
g_free (uri);
} }
} }
return TRUE; return TRUE;
@ -1488,20 +1516,18 @@ midori_browser_notebook_resize (MidoriBrowser* browser,
GdkRectangle* allocation) GdkRectangle* allocation)
{ {
gint new_size = 0; gint new_size = 0;
gint n = gtk_notebook_get_n_pages (GTK_NOTEBOOK(browser->notebook)); gint n = MAX (1, gtk_notebook_get_n_pages (GTK_NOTEBOOK (browser->notebook)));
const gint max_size = 150; const gint max_size = 150;
gint min_size; gint min_size;
gint icon_size = 16; gint icon_size = 16;
GtkAllocation notebook_size; GtkAllocation notebook_size;
GList* children; GList* children;
g_return_if_fail (n > 0);
if (allocation != NULL) if (allocation != NULL)
notebook_size.width = allocation->width; notebook_size.width = allocation->width;
else else
gtk_widget_get_allocation (browser->notebook, &notebook_size); gtk_widget_get_allocation (browser->notebook, &notebook_size);
new_size = notebook_size.width / n - 7; new_size = notebook_size.width / n;
gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (browser->notebook), gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (browser->notebook),
GTK_ICON_SIZE_MENU, &icon_size, NULL); GTK_ICON_SIZE_MENU, &icon_size, NULL);
@ -1672,14 +1698,14 @@ midori_browser_key_press_event (GtkWidget* widget,
&& event->keyval == GDK_KEY_Tab && event->keyval == GDK_KEY_Tab
&& (event->state & GDK_CONTROL_MASK)) && (event->state & GDK_CONTROL_MASK))
{ {
gtk_action_activate (_action_by_name (browser, "TabNext")); midori_browser_activate_action (browser, "TabNext");
return TRUE; return TRUE;
} }
else if (event->keyval == GDK_KEY_ISO_Left_Tab else if (event->keyval == GDK_KEY_ISO_Left_Tab
&& (event->state & GDK_CONTROL_MASK) && (event->state & GDK_CONTROL_MASK)
&& (event->state & GDK_SHIFT_MASK)) && (event->state & GDK_SHIFT_MASK))
{ {
gtk_action_activate (_action_by_name (browser, "TabPrevious")); midori_browser_activate_action (browser, "TabPrevious");
return TRUE; return TRUE;
} }
/* Interpret Ctrl+= as Zoom In for compatibility */ /* Interpret Ctrl+= as Zoom In for compatibility */
@ -1692,7 +1718,7 @@ midori_browser_key_press_event (GtkWidget* widget,
/* Interpret F5 as reloading for compatibility */ /* Interpret F5 as reloading for compatibility */
else if (event->keyval == GDK_KEY_F5) else if (event->keyval == GDK_KEY_F5)
{ {
gtk_action_activate (_action_by_name (browser, "Reload")); midori_browser_activate_action (browser, "Reload");
return TRUE; return TRUE;
} }
@ -1741,12 +1767,12 @@ midori_browser_key_press_event (GtkWidget* widget,
if ((event->keyval == GDK_KEY_BackSpace) if ((event->keyval == GDK_KEY_BackSpace)
&& (event->state & GDK_SHIFT_MASK)) && (event->state & GDK_SHIFT_MASK))
{ {
gtk_action_activate (_action_by_name (browser, "Forward")); midori_browser_activate_action (browser, "Forward");
return TRUE; return TRUE;
} }
else if (event->keyval == GDK_KEY_BackSpace) else if (event->keyval == GDK_KEY_BackSpace)
{ {
gtk_action_activate (_action_by_name (browser, "Back")); midori_browser_activate_action (browser, "Back");
return TRUE; return TRUE;
} }
@ -2246,8 +2272,7 @@ static void
_action_private_browsing_activate (GtkAction* action, _action_private_browsing_activate (GtkAction* action,
MidoriBrowser* browser) MidoriBrowser* browser)
{ {
const gchar* uri = midori_browser_get_current_uri (browser); sokoke_spawn_app ("about:private", TRUE);
sokoke_spawn_app (uri && *uri ? uri : "about:blank", TRUE);
} }
static void static void
@ -2313,7 +2338,8 @@ static void
_action_save_as_activate (GtkAction* action, _action_save_as_activate (GtkAction* action,
MidoriBrowser* browser) MidoriBrowser* browser)
{ {
midori_browser_save_uri (browser, midori_browser_get_current_uri (browser)); GtkWidget* view = midori_browser_get_current_tab (browser);
midori_browser_save_uri (browser, MIDORI_VIEW (view), NULL);
} }
static void static void
@ -2597,6 +2623,7 @@ _action_copy_activate (GtkAction* action,
MidoriBrowser* browser) MidoriBrowser* browser)
{ {
GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser)); GtkWidget* widget = gtk_window_get_focus (GTK_WINDOW (browser));
#if !WEBKIT_CHECK_VERSION (1, 4, 3)
/* Work around broken clipboard handling for the sake of the user */ /* Work around broken clipboard handling for the sake of the user */
if (WEBKIT_IS_WEB_VIEW (widget)) if (WEBKIT_IS_WEB_VIEW (widget))
{ {
@ -2606,6 +2633,7 @@ _action_copy_activate (GtkAction* action,
sokoke_widget_copy_clipboard (widget, selected); sokoke_widget_copy_clipboard (widget, selected);
return; return;
} }
#endif
if (G_LIKELY (widget) && g_signal_lookup ("copy-clipboard", G_OBJECT_TYPE (widget))) if (G_LIKELY (widget) && g_signal_lookup ("copy-clipboard", G_OBJECT_TYPE (widget)))
g_signal_emit_by_name (widget, "copy-clipboard"); g_signal_emit_by_name (widget, "copy-clipboard");
} }
@ -3032,6 +3060,7 @@ _action_compact_menu_populate_popup (GtkAction* action,
{ NULL }, { NULL },
{ "Fullscreen" }, { "Fullscreen" },
{ "Panel" }, { "Panel" },
{ "Bookmarkbar" },
{ "-" }, { "-" },
#endif #endif
{ NULL }, { NULL },
@ -3103,7 +3132,7 @@ midori_preferences_response_help_cb (GtkWidget* preferences,
MidoriBrowser* browser) MidoriBrowser* browser)
{ {
if (response == GTK_RESPONSE_HELP) if (response == GTK_RESPONSE_HELP)
gtk_action_activate (_action_by_name (browser, "HelpFAQ")); midori_browser_activate_action (browser, "HelpFAQ");
} }
static void static void
@ -3129,6 +3158,19 @@ _action_preferences_activate (GtkAction* action,
gtk_window_present (GTK_WINDOW (dialog)); gtk_window_present (GTK_WINDOW (dialog));
} }
static gboolean
midori_browser_has_native_menubar (void)
{
#if HAVE_HILDON
return TRUE;
#else
static const gchar* ubuntu_menuproxy = NULL;
if (ubuntu_menuproxy == NULL)
ubuntu_menuproxy = g_getenv ("UBUNTU_MENUPROXY");
return ubuntu_menuproxy && strstr (ubuntu_menuproxy, ".so") != NULL;
#endif
}
static void static void
_action_menubar_activate (GtkToggleAction* menubar_action, _action_menubar_activate (GtkToggleAction* menubar_action,
MidoriBrowser* browser) MidoriBrowser* browser)
@ -3139,6 +3181,9 @@ _action_menubar_activate (GtkToggleAction* menubar_action,
GList* children; GList* children;
gchar* items; gchar* items;
if (midori_browser_has_native_menubar ())
active = FALSE;
toolbar_items = g_string_new (NULL); toolbar_items = g_string_new (NULL);
children = gtk_container_get_children (GTK_CONTAINER (browser->navigationbar)); children = gtk_container_get_children (GTK_CONTAINER (browser->navigationbar));
for (; children != NULL; children = g_list_next (children)) for (; children != NULL; children = g_list_next (children))
@ -3232,13 +3277,14 @@ _action_reload_stop_activate (GtkAction* action,
{ {
GdkModifierType state = (GdkModifierType)0; GdkModifierType state = (GdkModifierType)0;
gint x, y; gint x, y;
GdkWindow* window;
gboolean from_cache = TRUE; gboolean from_cache = TRUE;
if (!strcmp (gtk_action_get_name (action), "ReloadUncached")) if (!strcmp (gtk_action_get_name (action), "ReloadUncached"))
from_cache = FALSE; from_cache = FALSE;
else else if ((window = gtk_widget_get_window (GTK_WIDGET (browser))))
{ {
gdk_window_get_pointer (NULL, &x, &y, &state); gdk_window_get_pointer (window, &x, &y, &state);
if (state & GDK_SHIFT_MASK) if (state & GDK_SHIFT_MASK)
from_cache = FALSE; from_cache = FALSE;
} }
@ -3304,112 +3350,19 @@ _action_view_encoding_activate (GtkAction* action,
} }
} }
static gchar*
midori_browser_get_uri_extension (const gchar* uri)
{
gchar* slash;
gchar* period;
gchar* ext_end;
/* Find the last slash in the URI and search for the last period
*after* the last slash. This is not completely accurate
but should cover most (simple) URIs */
slash = strrchr (uri, '/');
/* Huh, URI without slashes? */
if (!slash)
return NULL;
ext_end = period = strrchr (slash, '.');
if (!period)
return NULL;
/* Skip the period */
ext_end++;
/* If *ext_end is 0 here, the URI ended with a period, so skip */
if (!*ext_end)
return NULL;
/* Find the end of the extension */
while (*ext_end && g_ascii_isalnum (*ext_end))
ext_end++;
*ext_end = 0;
return g_strdup (period);
}
static gchar*
midori_browser_save_source (const gchar* uri,
const gchar* data,
const size_t len,
const gchar* outfile)
{
gchar* unique_filename;
gint fd;
FILE* fp;
size_t ret;
if (!outfile)
{
gchar* filename;
gchar* extension;
extension = midori_browser_get_uri_extension (uri);
filename = g_strdup_printf ("%uXXXXXX%s",
g_str_hash (uri), extension && *extension ? extension : ".htm");
g_free (extension);
fd = g_file_open_tmp (filename, &unique_filename, NULL);
g_free (filename);
}
else
{
unique_filename = g_strdup (outfile);
fd = g_open (unique_filename, O_WRONLY|O_CREAT, 0644);
}
if (fd != -1)
{
if ((fp = fdopen (fd, "w")))
{
ret = fwrite (data, 1, len, fp);
fclose (fp);
if ((ret - len) != 0)
{
g_warning ("Error writing to file %s "
"in midori_browser_source_transfer_cb()", unique_filename);
katze_assign (unique_filename, NULL);
}
}
close (fd);
}
return unique_filename;
}
static void static void
_action_source_view_activate (GtkAction* action, _action_source_view_activate (GtkAction* action,
MidoriBrowser* browser) MidoriBrowser* browser)
{ {
WebKitWebDataSource *data_source;
WebKitWebFrame *frame;
const GString *data;
GtkWidget* view; GtkWidget* view;
GtkWidget* web_view;
gchar* text_editor; gchar* text_editor;
gchar* filename = NULL; gchar* filename = NULL;
const gchar* uri;
if (!(view = midori_browser_get_current_tab (browser))) if (!(view = midori_browser_get_current_tab (browser)))
return; return;
filename = midori_view_save_source (MIDORI_VIEW (view), NULL, NULL);
g_object_get (browser->settings, "text-editor", &text_editor, NULL); g_object_get (browser->settings, "text-editor", &text_editor, NULL);
uri = midori_view_get_display_uri (MIDORI_VIEW (view));
web_view = midori_view_get_web_view (MIDORI_VIEW (view));
frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view));
data_source = webkit_web_frame_get_data_source (frame);
data = webkit_web_data_source_get_data (data_source);
if (!data)
return;
filename = midori_browser_save_source (uri, data->str, data->len, NULL);
if (!(text_editor && *text_editor)) if (!(text_editor && *text_editor))
{ {
GtkWidget* source; GtkWidget* source;
@ -3454,6 +3407,9 @@ _action_fullscreen_activate (GtkAction* action,
state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (browser))); state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (browser)));
if (state & GDK_WINDOW_STATE_FULLSCREEN) if (state & GDK_WINDOW_STATE_FULLSCREEN)
{ {
if (katze_object_get_boolean (G_OBJECT (browser->settings), "show-menubar"))
gtk_widget_show (browser->menubar);
if (katze_object_get_boolean (G_OBJECT (browser->settings), "show-panel")) if (katze_object_get_boolean (G_OBJECT (browser->settings), "show-panel"))
gtk_widget_show (browser->panel); gtk_widget_show (browser->panel);
@ -3471,6 +3427,7 @@ _action_fullscreen_activate (GtkAction* action,
} }
else else
{ {
gtk_widget_hide (browser->menubar);
gtk_widget_hide (browser->panel); gtk_widget_hide (browser->panel);
gtk_widget_hide (browser->bookmarkbar); gtk_widget_hide (browser->bookmarkbar);
gtk_widget_hide (browser->navigationbar); gtk_widget_hide (browser->navigationbar);
@ -3680,51 +3637,49 @@ static void
_action_location_reset_uri (GtkAction* action, _action_location_reset_uri (GtkAction* action,
MidoriBrowser* browser) MidoriBrowser* browser)
{ {
const gchar* uri; GtkWidget* view;
if ((view = midori_browser_get_current_tab (browser)))
uri = midori_browser_get_current_uri (browser); {
midori_location_action_set_text (MIDORI_LOCATION_ACTION (action), uri); midori_location_action_set_text (MIDORI_LOCATION_ACTION (action),
midori_view_get_display_uri (MIDORI_VIEW (view)));
midori_location_action_set_icon (MIDORI_LOCATION_ACTION (action),
midori_view_get_icon (MIDORI_VIEW (view)));
}
} }
static void static void
_action_location_submit_uri (GtkAction* action, _action_location_submit_uri (GtkAction* action,
const gchar* uri, const gchar* uri,
gboolean new_tab, gboolean new_tab,
MidoriBrowser* browser) MidoriBrowser* browser)
{ {
gchar* stripped_uri;
gchar* new_uri; gchar* new_uri;
gint n; gint n;
stripped_uri = g_strdup (uri); uri = katze_skip_whitespace (uri);
g_strstrip (stripped_uri); new_uri = sokoke_magic_uri (uri);
new_uri = sokoke_magic_uri (stripped_uri);
if (!new_uri) if (!new_uri)
{ {
gchar** parts; const gchar* keywords = NULL;
gchar* keywords = NULL;
const gchar* search_uri = NULL; const gchar* search_uri = NULL;
KatzeItem* item;
/* Do we have a keyword and a string? */ /* Do we have a keyword and a string? */
parts = g_strsplit (stripped_uri, " ", 2); if (browser->search_engines
if (parts[0] && browser->search_engines) && (item = katze_array_find_token (browser->search_engines, uri)))
{ {
KatzeItem* item; keywords = strchr (uri, ' ');
if ((item = katze_array_find_token (browser->search_engines, parts[0]))) if (keywords != NULL)
{ keywords++;
keywords = g_strdup (parts[1] ? parts[1] : ""); else
search_uri = katze_item_get_uri (item); keywords = "";
} search_uri = katze_item_get_uri (item);
} }
g_strfreev (parts);
if (keywords) if (keywords == NULL)
g_free (stripped_uri);
else
{ {
keywords = stripped_uri; keywords = uri;
search_uri = browser->location_entry_search; search_uri = browser->location_entry_search;
} }
new_uri = midori_uri_for_search (search_uri, keywords); new_uri = midori_uri_for_search (search_uri, keywords);
@ -3753,11 +3708,7 @@ _action_location_submit_uri (GtkAction* action,
if (sqlite3_step (statement) == SQLITE_DONE) if (sqlite3_step (statement) == SQLITE_DONE)
sqlite3_clear_bindings (statement); sqlite3_clear_bindings (statement);
} }
g_free (keywords);
} }
else
g_free (stripped_uri);
if (new_tab) if (new_tab)
{ {
@ -4348,7 +4299,6 @@ _action_bookmarks_export_activate (GtkAction* action,
const gchar* format; const gchar* format;
gchar* path = NULL; gchar* path = NULL;
GError* error; GError* error;
sqlite3* db;
KatzeArray* bookmarks; KatzeArray* bookmarks;
if (!browser->bookmarks || !gtk_widget_get_visible (GTK_WIDGET (browser))) if (!browser->bookmarks || !gtk_widget_get_visible (GTK_WIDGET (browser)))
@ -4389,9 +4339,8 @@ wrong_format:
return; return;
error = NULL; error = NULL;
db = g_object_get_data (G_OBJECT (browser->history), "db"); bookmarks = midori_array_query_recursive (browser->bookmarks,
bookmarks = katze_array_new (KATZE_TYPE_ARRAY); "*", "folder='%q'", "", TRUE);
midori_bookmarks_export_array_db (db, bookmarks, "");
if (!midori_array_to_file (bookmarks, path, format, &error)) if (!midori_array_to_file (bookmarks, path, format, &error))
{ {
sokoke_message_dialog (GTK_MESSAGE_ERROR, sokoke_message_dialog (GTK_MESSAGE_ERROR,
@ -4873,7 +4822,7 @@ midori_panel_cycle_child_focus_cb (GtkWidget* hpaned,
|| !gtk_widget_get_ancestor (focus, GTK_TYPE_PANED)) || !gtk_widget_get_ancestor (focus, GTK_TYPE_PANED))
{ {
g_signal_stop_emission_by_name (hpaned, "cycle-child-focus"); g_signal_stop_emission_by_name (hpaned, "cycle-child-focus");
gtk_action_activate (_action_by_name (browser, "Location")); midori_browser_activate_action (browser, "Location");
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
@ -4947,10 +4896,10 @@ midori_panel_close_cb (MidoriPanel* panel,
} }
static void static void
gtk_notebook_switch_page_cb (GtkWidget* notebook, midori_browser_notebook_switch_page_cb (GtkWidget* notebook,
gpointer page, gpointer page,
guint page_num, guint page_num,
MidoriBrowser* browser) MidoriBrowser* browser)
{ {
GtkWidget* widget; GtkWidget* widget;
GtkAction* action; GtkAction* action;
@ -4966,10 +4915,10 @@ gtk_notebook_switch_page_cb (GtkWidget* notebook,
} }
static void static void
gtk_notebook_switch_page_after_cb (GtkWidget* notebook, midori_browser_notebook_switch_page_after_cb (GtkWidget* notebook,
gpointer page, gpointer page,
guint page_num, guint page_num,
MidoriBrowser* browser) MidoriBrowser* browser)
{ {
GtkWidget* widget; GtkWidget* widget;
MidoriView* view; MidoriView* view;
@ -4988,6 +4937,8 @@ gtk_notebook_switch_page_after_cb (GtkWidget* notebook,
midori_location_action_set_text (MIDORI_LOCATION_ACTION (action), uri); midori_location_action_set_text (MIDORI_LOCATION_ACTION (action), uri);
midori_location_action_set_icon (MIDORI_LOCATION_ACTION (action), midori_location_action_set_icon (MIDORI_LOCATION_ACTION (action),
midori_view_get_icon (view)); midori_view_get_icon (view));
if (sokoke_is_app_or_private ())
gtk_window_set_icon (GTK_WINDOW (browser), midori_view_get_icon (view));
if (browser->proxy_array) if (browser->proxy_array)
katze_item_set_meta_integer (KATZE_ITEM (browser->proxy_array), "current", katze_item_set_meta_integer (KATZE_ITEM (browser->proxy_array), "current",
@ -5031,9 +4982,8 @@ midori_browser_notebook_create_window_cb (GtkNotebook* notebook,
g_signal_emit (browser, signals[NEW_WINDOW], 0, NULL, &new_browser); g_signal_emit (browser, signals[NEW_WINDOW], 0, NULL, &new_browser);
if (new_browser) if (new_browser)
{ {
GtkWidget* new_notebook = katze_object_get_object (new_browser, "notebook"); GtkWidget* new_notebook = new_browser->notebook;
g_object_unref (new_notebook); gtk_window_move (GTK_WINDOW (new_browser), x, y);
gtk_window_move (GTK_WINDOW (browser), x, y);
return new_notebook; return new_notebook;
} }
else /* No MidoriApp, so this is app or private mode */ else /* No MidoriApp, so this is app or private mode */
@ -5041,8 +4991,8 @@ midori_browser_notebook_create_window_cb (GtkNotebook* notebook,
} }
static void static void
midori_browser_switch_tab_cb (GtkWidget* menuitem, midori_browser_menu_item_switch_tab_cb (GtkWidget* menuitem,
MidoriBrowser* browser) MidoriBrowser* browser)
{ {
gint page = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem), "index")); gint page = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem), "index"));
midori_browser_set_current_page (browser, page); midori_browser_set_current_page (browser, page);
@ -5091,7 +5041,7 @@ midori_browser_notebook_button_press_event_after_cb (GtkNotebook* notebook,
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
g_object_set_data (G_OBJECT (menuitem), "index", GINT_TO_POINTER (i)); g_object_set_data (G_OBJECT (menuitem), "index", GINT_TO_POINTER (i));
g_signal_connect (menuitem, "activate", g_signal_connect (menuitem, "activate",
G_CALLBACK (midori_browser_switch_tab_cb), browser); G_CALLBACK (midori_browser_menu_item_switch_tab_cb), browser);
i++; i++;
} }
g_list_free (tabs); g_list_free (tabs);
@ -5416,19 +5366,6 @@ midori_browser_window_state_event_cb (MidoriBrowser* browser,
else if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) else if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)
window_state = MIDORI_WINDOW_FULLSCREEN; window_state = MIDORI_WINDOW_FULLSCREEN;
g_object_set (browser->settings, "last-window-state", window_state, NULL); g_object_set (browser->settings, "last-window-state", window_state, NULL);
if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN)
{
if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)
{
gtk_widget_hide (browser->menubar);
}
else
{
if (katze_object_get_boolean (browser->settings, "show-menubar"))
gtk_widget_show (browser->menubar);
}
}
} }
static gboolean static gboolean
@ -5857,8 +5794,8 @@ midori_browser_init (MidoriBrowser* browser)
GtkSettings* gtk_settings; GtkSettings* gtk_settings;
GtkWidget* hpaned; GtkWidget* hpaned;
GtkWidget* vpaned; GtkWidget* vpaned;
GtkRcStyle* rcstyle;
GtkWidget* scrolled; GtkWidget* scrolled;
KatzeArray* dummy_array;
browser->settings = midori_web_settings_new (); browser->settings = midori_web_settings_new ();
browser->proxy_array = katze_array_new (KATZE_TYPE_ARRAY); browser->proxy_array = katze_array_new (KATZE_TYPE_ARRAY);
@ -5878,6 +5815,9 @@ midori_browser_init (MidoriBrowser* browser)
G_CALLBACK (midori_browser_destroy_cb), NULL); G_CALLBACK (midori_browser_destroy_cb), NULL);
gtk_window_set_role (GTK_WINDOW (browser), "browser"); gtk_window_set_role (GTK_WINDOW (browser), "browser");
gtk_window_set_icon_name (GTK_WINDOW (browser), "web-browser"); gtk_window_set_icon_name (GTK_WINDOW (browser), "web-browser");
#if GTK_CHECK_VERSION (3, 4, 0)
gtk_window_set_hide_titlebar_when_maximized (GTK_WINDOW (browser), TRUE);
#endif
vbox = gtk_vbox_new (FALSE, 0); vbox = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (browser), vbox); gtk_container_add (GTK_CONTAINER (browser), vbox);
gtk_widget_show (vbox); gtk_widget_show (vbox);
@ -5911,7 +5851,7 @@ midori_browser_init (MidoriBrowser* browser)
} }
/* Hide the 'Dummy' which only holds otherwise unused actions */ /* Hide the 'Dummy' which only holds otherwise unused actions */
g_object_set (_action_by_name (browser, "Dummy"), "visible", FALSE, NULL); _action_set_visible (browser, "Dummy", FALSE);
action = g_object_new (KATZE_TYPE_SEPARATOR_ACTION, action = g_object_new (KATZE_TYPE_SEPARATOR_ACTION,
"name", "Separator", "name", "Separator",
@ -5986,12 +5926,14 @@ midori_browser_init (MidoriBrowser* browser)
gtk_action_group_add_action_with_accel (browser->action_group, action, ""); gtk_action_group_add_action_with_accel (browser->action_group, action, "");
g_object_unref (action); g_object_unref (action);
dummy_array = katze_array_new (KATZE_TYPE_ARRAY);
katze_array_update (dummy_array);
action = g_object_new (KATZE_TYPE_ARRAY_ACTION, action = g_object_new (KATZE_TYPE_ARRAY_ACTION,
"name", "Bookmarks", "name", "Bookmarks",
"label", _("_Bookmarks"), "label", _("_Bookmarks"),
"stock-id", STOCK_BOOKMARKS, "stock-id", STOCK_BOOKMARKS,
"tooltip", _("Show the saved bookmarks"), "tooltip", _("Show the saved bookmarks"),
"array", browser->proxy_array, /* Use a non-empty array here */ "array", dummy_array /* updated, unique */,
NULL); NULL);
g_object_connect (action, g_object_connect (action,
"signal::populate-folder", "signal::populate-folder",
@ -6001,12 +5943,15 @@ midori_browser_init (MidoriBrowser* browser)
NULL); NULL);
gtk_action_group_add_action_with_accel (browser->action_group, action, ""); gtk_action_group_add_action_with_accel (browser->action_group, action, "");
g_object_unref (action); g_object_unref (action);
g_object_unref (dummy_array);
dummy_array = katze_array_new (KATZE_TYPE_ITEM);
katze_array_update (dummy_array);
action = g_object_new (KATZE_TYPE_ARRAY_ACTION, action = g_object_new (KATZE_TYPE_ARRAY_ACTION,
"name", "Tools", "name", "Tools",
"label", _("_Tools"), "label", _("_Tools"),
"stock-id", GTK_STOCK_PREFERENCES, "stock-id", GTK_STOCK_PREFERENCES,
"array", katze_array_new (KATZE_TYPE_ITEM), "array", dummy_array /* updated, unique */,
NULL); NULL);
g_object_connect (action, g_object_connect (action,
"signal::populate-popup", "signal::populate-popup",
@ -6016,6 +5961,7 @@ midori_browser_init (MidoriBrowser* browser)
NULL); NULL);
gtk_action_group_add_action (browser->action_group, action); gtk_action_group_add_action (browser->action_group, action);
g_object_unref (action); g_object_unref (action);
g_object_unref (dummy_array);
action = g_object_new (KATZE_TYPE_ARRAY_ACTION, action = g_object_new (KATZE_TYPE_ARRAY_ACTION,
"name", "Window", "name", "Window",
@ -6051,6 +5997,7 @@ midori_browser_init (MidoriBrowser* browser)
browser->menubar = gtk_ui_manager_get_widget (ui_manager, "/menubar"); browser->menubar = gtk_ui_manager_get_widget (ui_manager, "/menubar");
gtk_box_pack_start (GTK_BOX (vbox), browser->menubar, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), browser->menubar, FALSE, FALSE, 0);
gtk_widget_hide (browser->menubar); gtk_widget_hide (browser->menubar);
_action_set_visible (browser, "Menubar", !midori_browser_has_native_menubar ());
#if HAVE_HILDON #if HAVE_HILDON
#if HILDON_CHECK_VERSION (2, 2, 0) #if HILDON_CHECK_VERSION (2, 2, 0)
browser->menubar = hildon_app_menu_new (); browser->menubar = hildon_app_menu_new ();
@ -6082,7 +6029,6 @@ midori_browser_init (MidoriBrowser* browser)
#endif #endif
gtk_menu_shell_append (GTK_MENU_SHELL (browser->menubar), menuitem); gtk_menu_shell_append (GTK_MENU_SHELL (browser->menubar), menuitem);
#endif #endif
browser->menu_tools = gtk_menu_new ();
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM ( gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (
gtk_ui_manager_get_widget (ui_manager, "/menubar/File/WindowNew")), NULL); gtk_ui_manager_get_widget (ui_manager, "/menubar/File/WindowNew")), NULL);
@ -6105,9 +6051,6 @@ midori_browser_init (MidoriBrowser* browser)
g_signal_connect (forward, "button-press-event", g_signal_connect (forward, "button-press-event",
G_CALLBACK (midori_browser_menu_item_middle_click_event_cb), browser); G_CALLBACK (midori_browser_menu_item_middle_click_event_cb), browser);
#if HAVE_HILDON
_action_set_visible (browser, "Menubar", FALSE);
#endif
_action_set_sensitive (browser, "EncodingCustom", FALSE); _action_set_sensitive (browser, "EncodingCustom", FALSE);
_action_set_visible (browser, "LastSession", FALSE); _action_set_visible (browser, "LastSession", FALSE);
#if !HAVE_HILDON && !defined (GDK_WINDOWING_X11) #if !HAVE_HILDON && !defined (GDK_WINDOWING_X11)
@ -6207,18 +6150,22 @@ midori_browser_init (MidoriBrowser* browser)
gtk_paned_pack2 (GTK_PANED (hpaned), vpaned, TRUE, FALSE); gtk_paned_pack2 (GTK_PANED (hpaned), vpaned, TRUE, FALSE);
gtk_widget_show (vpaned); gtk_widget_show (vpaned);
browser->notebook = gtk_notebook_new (); browser->notebook = gtk_notebook_new ();
#if !GTK_CHECK_VERSION (3, 0, 0)
{
/* Remove the inner border between scrollbars and the window border */ /* Remove the inner border between scrollbars and the window border */
rcstyle = gtk_rc_style_new (); GtkRcStyle* rcstyle = gtk_rc_style_new ();
rcstyle->xthickness = 0; rcstyle->xthickness = 0;
gtk_widget_modify_style (browser->notebook, rcstyle); gtk_widget_modify_style (browser->notebook, rcstyle);
g_object_unref (rcstyle); g_object_unref (rcstyle);
}
#endif
gtk_notebook_set_scrollable (GTK_NOTEBOOK (browser->notebook), TRUE); gtk_notebook_set_scrollable (GTK_NOTEBOOK (browser->notebook), TRUE);
gtk_paned_pack1 (GTK_PANED (vpaned), browser->notebook, FALSE, FALSE); gtk_paned_pack1 (GTK_PANED (vpaned), browser->notebook, FALSE, FALSE);
g_signal_connect (browser->notebook, "switch-page", g_signal_connect (browser->notebook, "switch-page",
G_CALLBACK (gtk_notebook_switch_page_cb), G_CALLBACK (midori_browser_notebook_switch_page_cb),
browser); browser);
g_signal_connect_after (browser->notebook, "switch-page", g_signal_connect_after (browser->notebook, "switch-page",
G_CALLBACK (gtk_notebook_switch_page_after_cb), G_CALLBACK (midori_browser_notebook_switch_page_after_cb),
browser); browser);
g_signal_connect (browser->notebook, "page-reordered", g_signal_connect (browser->notebook, "page-reordered",
G_CALLBACK (midori_browser_notebook_page_reordered_cb), G_CALLBACK (midori_browser_notebook_page_reordered_cb),
@ -6285,7 +6232,12 @@ midori_browser_init (MidoriBrowser* browser)
gtk_box_pack_start (GTK_BOX (vbox), browser->statusbar, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), browser->statusbar, FALSE, FALSE, 0);
browser->transferbar = g_object_new (MIDORI_TYPE_TRANSFERBAR, NULL); browser->transferbar = g_object_new (MIDORI_TYPE_TRANSFERBAR, NULL);
#if GTK_CHECK_VERSION (3, 0, 0)
/* FIXME: Transfers should go between text and statusbar features like GTK+2 */
gtk_box_pack_end (GTK_BOX (browser->statusbar_contents), browser->transferbar, FALSE, FALSE, 3);
#else
gtk_box_pack_start (GTK_BOX (browser->statusbar_contents), browser->transferbar, FALSE, FALSE, 3); gtk_box_pack_start (GTK_BOX (browser->statusbar_contents), browser->transferbar, FALSE, FALSE, 3);
#endif
gtk_toolbar_set_show_arrow (GTK_TOOLBAR (browser->transferbar), FALSE); gtk_toolbar_set_show_arrow (GTK_TOOLBAR (browser->transferbar), FALSE);
gtk_widget_show (browser->transferbar); gtk_widget_show (browser->transferbar);
@ -6676,29 +6628,21 @@ midori_browser_settings_notify (MidoriWebSettings* web_settings,
_toggle_tabbar_smartly (browser, FALSE); _toggle_tabbar_smartly (browser, FALSE);
else if (name == g_intern_string ("show-menubar")) else if (name == g_intern_string ("show-menubar"))
{ {
gtk_toggle_action_set_active ( _action_set_active (browser, "Menubar", g_value_get_boolean (&value));
GTK_TOGGLE_ACTION (_action_by_name (browser, "Menubar")),
g_value_get_boolean (&value));
} }
else if (name == g_intern_string ("show-navigationbar")) else if (name == g_intern_string ("show-navigationbar"))
{ {
browser->show_navigationbar = g_value_get_boolean (&value); browser->show_navigationbar = g_value_get_boolean (&value);
gtk_toggle_action_set_active ( _action_set_active (browser, "Navigationbar", g_value_get_boolean (&value));
GTK_TOGGLE_ACTION (_action_by_name (browser, "Navigationbar")),
g_value_get_boolean (&value));
} }
else if (name == g_intern_string ("show-bookmarkbar")) else if (name == g_intern_string ("show-bookmarkbar"))
{ {
gtk_toggle_action_set_active ( _action_set_active (browser, "Bookmarkbar", g_value_get_boolean (&value));
GTK_TOGGLE_ACTION (_action_by_name (browser, "Bookmarkbar")),
g_value_get_boolean (&value));
} }
else if (name == g_intern_string ("show-statusbar")) else if (name == g_intern_string ("show-statusbar"))
{ {
browser->show_statusbar = g_value_get_boolean (&value); browser->show_statusbar = g_value_get_boolean (&value);
gtk_toggle_action_set_active ( _action_set_active (browser, "Statusbar", g_value_get_boolean (&value));
GTK_TOGGLE_ACTION (_action_by_name (browser, "Statusbar")),
g_value_get_boolean (&value));
} }
else if (name == g_intern_string ("location-entry-search")) else if (name == g_intern_string ("location-entry-search"))
{ {
@ -7336,7 +7280,7 @@ midori_browser_set_current_page (MidoriBrowser* browser,
gtk_notebook_set_current_page (GTK_NOTEBOOK (browser->notebook), n); gtk_notebook_set_current_page (GTK_NOTEBOOK (browser->notebook), n);
if (midori_view_is_blank (MIDORI_VIEW (view))) if (midori_view_is_blank (MIDORI_VIEW (view)))
gtk_action_activate (_action_by_name (browser, "Location")); midori_browser_activate_action (browser, "Location");
else else
gtk_widget_grab_focus (view); gtk_widget_grab_focus (view);

View file

@ -277,43 +277,96 @@ midori_location_action_create_model (void)
} }
static void static void
midori_location_action_popup_position (GtkWidget* popup, midori_location_action_popup_position (MidoriLocationAction* action,
GtkWidget* widget) gint matches)
{ {
GtkWidget* popup = action->popup;
GtkWidget* widget = action->entry;
GdkWindow* window = gtk_widget_get_window (widget); GdkWindow* window = gtk_widget_get_window (widget);
gint wx, wy; gint wx, wy, x_border, y_border, items;
GtkRequisition menu_req; GtkRequisition menu_req;
GtkRequisition widget_req; GtkRequisition widget_req;
GdkScreen* screen; GdkScreen* screen;
gint monitor_num; gint monitor_num;
GdkRectangle monitor; GdkRectangle monitor;
GtkAllocation allocation; GtkAllocation alloc;
gint height, sep, width, toplevel_height;
gboolean above;
GtkWidget* scrolled = gtk_widget_get_parent (action->treeview);
GtkWidget* toplevel;
GtkTreePath* path;
if (!window)
return;
gtk_widget_get_allocation (widget, &alloc);
#if GTK_CHECK_VERSION (3, 0, 0)
gtk_widget_get_preferred_size (widget, &widget_req, NULL);
#else
gtk_widget_size_request (widget, &widget_req);
#endif
gdk_window_get_origin (window, &wx, &wy); gdk_window_get_origin (window, &wx, &wy);
if (!gtk_widget_get_has_window (widget)) #if GTK_CHECK_VERSION (3, 0, 0)
{ wx += alloc.x;
GtkAllocation alloc; wy += alloc.y + (alloc.height - widget_req.height) / 2;
gtk_widget_get_allocation (widget, &alloc); #endif
wx += alloc.x; /* _gtk_entry_get_borders (GTK_ENTRY (widget), &x_border, &y_border); */
wy += alloc.y; x_border = y_border = 0;
}
gtk_widget_size_request (popup, &menu_req); gtk_tree_view_column_cell_get_size (
gtk_widget_size_request (widget, &widget_req); gtk_tree_view_get_column (GTK_TREE_VIEW (action->treeview), 0),
NULL, NULL, NULL, NULL, &height);
gtk_widget_style_get (action->treeview, "vertical-separator", &sep, NULL);
height += sep;
/* Constrain to screen/ window size */
screen = gtk_widget_get_screen (widget); screen = gtk_widget_get_screen (widget);
monitor_num = gdk_screen_get_monitor_at_window (screen, window); monitor_num = gdk_screen_get_monitor_at_window (screen, window);
gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor); gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
toplevel = gtk_widget_get_toplevel (widget);
if (wy + widget_req.height + menu_req.height <= monitor.y + monitor.height gtk_window_get_size (GTK_WINDOW (toplevel), NULL, &toplevel_height);
|| wy - monitor.y < (monitor.y + monitor.height) - (wy + widget_req.height)) toplevel_height = MIN (toplevel_height, monitor.height);
wy += widget_req.height; if (wy > toplevel_height / 2)
items = MIN (matches, ((monitor.y + wy) / height) - 1);
else else
items = MIN (matches, ((toplevel_height - wy) / height) - 1);
width = MIN (alloc.width, monitor.width) - 2 * x_border;
gtk_tree_view_columns_autosize (GTK_TREE_VIEW (action->treeview));
#if GTK_CHECK_VERSION (3, 0, 0)
gtk_widget_set_size_request (scrolled, width, -1);
gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW (scrolled), width);
gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (scrolled), items * height);
gtk_widget_get_preferred_size (popup, &menu_req, NULL);
#else
gtk_widget_set_size_request (scrolled, width, items * height);
gtk_widget_size_request (popup, &menu_req);
#endif
if (wx < monitor.x)
wx = monitor.x;
else if (wx + menu_req.width > monitor.x + monitor.width)
wx = monitor.x + monitor.width - menu_req.width;
if (wy + widget_req.height + menu_req.height <= monitor.y + monitor.height ||
wy - monitor.y < (monitor.y + monitor.height) - (wy + widget_req.height))
{
wy += widget_req.height;
above = FALSE;
}
else
{
wy -= menu_req.height; wy -= menu_req.height;
gtk_window_move (GTK_WINDOW (popup), wx, wy); above = TRUE;
gtk_widget_get_allocation (widget, &allocation); }
gtk_window_resize (GTK_WINDOW (popup), allocation.width, 1);
path = gtk_tree_path_new_from_indices (above ? matches - 1 : 0, -1);
gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (action->treeview), path,
NULL, FALSE, 0.0, 0.0);
gtk_tree_path_free (path);
gtk_window_move (GTK_WINDOW (popup), wx, wy);
} }
static gboolean static gboolean
@ -357,28 +410,21 @@ midori_location_action_popup_timeout_cb (gpointer data)
gint result; gint result;
static sqlite3_stmt* stmt; static sqlite3_stmt* stmt;
const gchar* sqlcmd; const gchar* sqlcmd;
gint matches, searches, height, screen_height, browser_height, sep; gint matches, searches;
MidoriBrowser* browser;
GtkStyle* style; GtkStyle* style;
if (!action->entry || !gtk_widget_has_focus (action->entry) || !action->history) if (!action->entry || !gtk_widget_has_focus (action->entry) || !action->history)
return FALSE; return FALSE;
/* No completion when typing a search token */ /* No completion when typing a search token */
if (action->search_engines != NULL) if (action->search_engines
&& katze_array_find_token (action->search_engines, action->key))
{ {
gchar** parts = g_strsplit (action->key, " ", 2); midori_location_action_popdown_completion (action);
if (parts && *parts && parts[1] return FALSE;
&& katze_array_find_token (action->search_engines, *parts))
{
g_strfreev (parts);
midori_location_action_popdown_completion (action);
return FALSE;
}
g_strfreev (parts);
} }
/* Empaty string or starting with a space means: no completion */ /* Empty string or starting with a space means: no completion */
if (!(action->key && *action->key && *action->key != ' ')) if (!(action->key && *action->key && *action->key != ' '))
{ {
midori_location_action_popdown_completion (action); midori_location_action_popdown_completion (action);
@ -443,6 +489,8 @@ midori_location_action_popup_timeout_cb (gpointer data)
popup = gtk_window_new (GTK_WINDOW_POPUP); popup = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_type_hint (GTK_WINDOW (popup), GDK_WINDOW_TYPE_HINT_COMBO); gtk_window_set_type_hint (GTK_WINDOW (popup), GDK_WINDOW_TYPE_HINT_COMBO);
/* Window managers may ignore programmatic resize without this */
gtk_window_set_resizable (GTK_WINDOW (popup), FALSE);
popup_frame = gtk_frame_new (NULL); popup_frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (popup_frame), GTK_SHADOW_ETCHED_IN); gtk_frame_set_shadow_type (GTK_FRAME (popup_frame), GTK_SHADOW_ETCHED_IN);
gtk_container_add (GTK_CONTAINER (popup), popup_frame); gtk_container_add (GTK_CONTAINER (popup), popup_frame);
@ -489,6 +537,7 @@ midori_location_action_popup_timeout_cb (gpointer data)
gtk_list_store_clear (store); gtk_list_store_clear (store);
matches = searches = 0; matches = searches = 0;
gtk_widget_realize (action->treeview);
style = gtk_widget_get_style (action->treeview); style = gtk_widget_get_style (action->treeview);
while (result == SQLITE_ROW) while (result == SQLITE_ROW)
{ {
@ -507,9 +556,11 @@ midori_location_action_popup_timeout_cb (gpointer data)
else if (type == 2 /* search_view */) else if (type == 2 /* search_view */)
{ {
gchar* search_title = g_strdup_printf (_("Search for %s"), title); gchar* search_title = g_strdup_printf (_("Search for %s"), title);
gchar* search_desc = g_strdup_printf ("%s\n%s", search_title, uri);
gtk_list_store_insert_with_values (store, NULL, matches, gtk_list_store_insert_with_values (store, NULL, matches,
URI_COL, uri, TITLE_COL, search_title, YALIGN_COL, 0.25, URI_COL, uri, TITLE_COL, search_desc, YALIGN_COL, 0.25,
STYLE_COL, 1, FAVICON_COL, icon, -1); STYLE_COL, 1, FAVICON_COL, icon, -1);
g_free (search_desc);
g_free (search_title); g_free (search_title);
} }
if (icon != NULL) if (icon != NULL)
@ -518,8 +569,12 @@ midori_location_action_popup_timeout_cb (gpointer data)
matches++; matches++;
result = sqlite3_step (stmt); result = sqlite3_step (stmt);
} }
sqlite3_reset (stmt);
sqlite3_clear_bindings (stmt); if (stmt)
{
sqlite3_reset (stmt);
sqlite3_clear_bindings (stmt);
}
if (action->search_engines) if (action->search_engines)
{ {
@ -529,17 +584,22 @@ midori_location_action_popup_timeout_cb (gpointer data)
{ {
gchar* uri; gchar* uri;
gchar* title; gchar* title;
const gchar* text;
gchar* desc;
GdkPixbuf* icon; GdkPixbuf* icon;
uri = midori_uri_for_search (katze_item_get_uri (item), action->key); uri = midori_uri_for_search (katze_item_get_uri (item), action->key);
title = g_strdup_printf (_("Search with %s"), katze_item_get_name (item)); title = g_strdup_printf (_("Search with %s"), katze_item_get_name (item));
text = katze_item_get_text (item);
desc = g_strdup_printf ("%s\n%s", title, text ? text : uri);
icon = midori_search_action_get_icon (item, action->treeview, NULL, FALSE); icon = midori_search_action_get_icon (item, action->treeview, NULL, FALSE);
gtk_list_store_insert_with_values (store, NULL, matches + i, gtk_list_store_insert_with_values (store, NULL, matches + i,
URI_COL, uri, TITLE_COL, title, YALIGN_COL, 0.25, URI_COL, uri, TITLE_COL, desc, YALIGN_COL, 0.25,
BACKGROUND_COL, style ? &style->bg[GTK_STATE_NORMAL] : NULL, BACKGROUND_COL, style ? &style->bg[GTK_STATE_NORMAL] : NULL,
STYLE_COL, 1, FAVICON_COL, icon, -1); STYLE_COL, 1, FAVICON_COL, icon, -1);
g_free (uri); g_free (uri);
g_free (title); g_free (title);
g_free (desc);
if (icon != NULL) if (icon != NULL)
g_object_unref (icon); g_object_unref (icon);
i++; i++;
@ -553,22 +613,10 @@ midori_location_action_popup_timeout_cb (gpointer data)
gtk_window_set_screen (GTK_WINDOW (action->popup), gtk_window_set_screen (GTK_WINDOW (action->popup),
gtk_widget_get_screen (action->entry)); gtk_widget_get_screen (action->entry));
gtk_window_set_transient_for (GTK_WINDOW (action->popup), GTK_WINDOW (toplevel)); gtk_window_set_transient_for (GTK_WINDOW (action->popup), GTK_WINDOW (toplevel));
gtk_tree_view_columns_autosize (GTK_TREE_VIEW (action->treeview)); gtk_widget_show_all (action->popup);
} }
browser = midori_browser_get_for_widget (action->entry); midori_location_action_popup_position (action, matches + searches);
column = gtk_tree_view_get_column (GTK_TREE_VIEW (action->treeview), 0);
gtk_tree_view_column_cell_get_size (column, NULL, NULL, NULL, NULL, &height);
screen_height = gdk_screen_get_height (gtk_widget_get_screen (action->popup));
gtk_window_get_size (GTK_WINDOW (browser), NULL, &browser_height);
screen_height = MIN (MIN (browser_height, screen_height / 1.5), screen_height / 1.5);
gtk_widget_style_get (action->treeview, "vertical-separator", &sep, NULL);
/* FIXME: Instead of 1.5 we should relate to the height of one line */
height = MIN (matches * height + (matches + searches) * sep
+ searches * height / 1.5, screen_height);
gtk_widget_set_size_request (action->treeview, -1, height);
midori_location_action_popup_position (action->popup, action->entry);
gtk_widget_show_all (action->popup);
return FALSE; return FALSE;
} }
@ -1532,30 +1580,22 @@ midori_location_action_add_item (MidoriLocationAction* location_action,
#endif #endif
} }
/**
* midori_location_action_set_icon_for_uri:
* @location_action: a #MidoriLocationAction
* @icon: a #GdkPixbuf
* @uri: an URI string
*
* Sets the icon for the specified URI.
*
* Deprecated: 0.4.4
**/
void void
midori_location_action_set_icon_for_uri (MidoriLocationAction* location_action, midori_location_action_set_icon_for_uri (MidoriLocationAction* location_action,
GdkPixbuf* icon, GdkPixbuf* icon,
const gchar* uri) const gchar* uri)
{ {
#if !HAVE_HILDON midori_location_action_set_icon (location_action, icon);
GSList* proxies;
#endif
g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action));
g_return_if_fail (!icon || GDK_IS_PIXBUF (icon));
g_return_if_fail (uri != NULL);
#if !HAVE_HILDON
proxies = gtk_action_get_proxies (GTK_ACTION (location_action));
for (; proxies != NULL; proxies = g_slist_next (proxies))
if (GTK_IS_TOOL_ITEM (proxies->data))
{
GtkWidget* entry = midori_location_action_entry_for_proxy (proxies->data);
gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_PRIMARY, icon);
}
#endif
} }
/** /**
@ -1659,16 +1699,20 @@ midori_location_action_set_security_hint (MidoriLocationAction* location_action,
for (; proxies != NULL; proxies = g_slist_next (proxies)) for (; proxies != NULL; proxies = g_slist_next (proxies))
if (GTK_IS_TOOL_ITEM (proxies->data)) if (GTK_IS_TOOL_ITEM (proxies->data))
{ {
#if !GTK_CHECK_VERSION (3, 0, 0)
const gchar* bg_color = NULL; const gchar* bg_color = NULL;
const gchar* fg_color = NULL; const gchar* fg_color = NULL;
#endif
GtkWidget* entry = midori_location_action_entry_for_proxy (proxies->data); GtkWidget* entry = midori_location_action_entry_for_proxy (proxies->data);
GdkScreen* screen = gtk_widget_get_screen (entry); GdkScreen* screen = gtk_widget_get_screen (entry);
GtkIconTheme* icon_theme = gtk_icon_theme_get_for_screen (screen); GtkIconTheme* icon_theme = gtk_icon_theme_get_for_screen (screen);
if (hint == MIDORI_SECURITY_UNKNOWN) if (hint == MIDORI_SECURITY_UNKNOWN)
{ {
#if !GTK_CHECK_VERSION (3, 0, 0)
bg_color = "#ef7070"; bg_color = "#ef7070";
fg_color = "#000"; fg_color = "#000";
#endif
#if !HAVE_HILDON #if !HAVE_HILDON
if (gtk_icon_theme_has_icon (icon_theme, "channel-insecure-symbolic")) if (gtk_icon_theme_has_icon (icon_theme, "channel-insecure-symbolic"))
gtk_icon_entry_set_icon_from_icon_name (GTK_ICON_ENTRY (entry), gtk_icon_entry_set_icon_from_icon_name (GTK_ICON_ENTRY (entry),
@ -1685,8 +1729,10 @@ midori_location_action_set_security_hint (MidoriLocationAction* location_action,
} }
else if (hint == MIDORI_SECURITY_TRUSTED) else if (hint == MIDORI_SECURITY_TRUSTED)
{ {
#if !GTK_CHECK_VERSION (3, 0, 0)
bg_color = "#d1eeb9"; bg_color = "#d1eeb9";
fg_color = "#000"; fg_color = "#000";
#endif
#if !HAVE_HILDON #if !HAVE_HILDON
if (gtk_icon_theme_has_icon (icon_theme, "channel-secure-symbolic")) if (gtk_icon_theme_has_icon (icon_theme, "channel-secure-symbolic"))
gtk_icon_entry_set_icon_from_icon_name (GTK_ICON_ENTRY (entry), gtk_icon_entry_set_icon_from_icon_name (GTK_ICON_ENTRY (entry),

View file

@ -393,6 +393,13 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
INDENTED_ADD (button); INDENTED_ADD (button);
button = katze_property_proxy (settings, "flash-window-on-new-bg-tabs", NULL); button = katze_property_proxy (settings, "flash-window-on-new-bg-tabs", NULL);
SPANNED_ADD (button); SPANNED_ADD (button);
if (katze_object_has_property (settings, "enable-webgl"))
{
button = katze_property_proxy (settings, "enable-webgl", NULL);
INDENTED_ADD (button);
}
FRAME_NEW (NULL); FRAME_NEW (NULL);
button = katze_property_label (settings, "preferred-languages"); button = katze_property_label (settings, "preferred-languages");
INDENTED_ADD (button); INDENTED_ADD (button);

View file

@ -312,6 +312,7 @@ midori_search_action_create_tool_item (GtkAction* action)
toolitem = GTK_WIDGET (gtk_tool_item_new ()); toolitem = GTK_WIDGET (gtk_tool_item_new ());
entry = gtk_icon_entry_new (); entry = gtk_icon_entry_new ();
sokoke_entry_set_clear_button_visible (GTK_ENTRY (entry), TRUE);
gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (entry), gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_PRIMARY, TRUE); GTK_ICON_ENTRY_PRIMARY, TRUE);
alignment = gtk_alignment_new (0, 0.5, 1, 0.1); alignment = gtk_alignment_new (0, 0.5, 1, 0.1);
@ -876,12 +877,6 @@ midori_search_action_editor_name_changed_cb (GtkWidget* entry,
GTK_RESPONSE_ACCEPT, text && *text); GTK_RESPONSE_ACCEPT, text && *text);
} }
static inline const gchar*
STR_NON_NULL (const gchar* string)
{
return string ? string : "";
}
static void static void
midori_search_action_get_editor (MidoriSearchAction* search_action, midori_search_action_get_editor (MidoriSearchAction* search_action,
gboolean new_engine) gboolean new_engine)
@ -942,7 +937,7 @@ midori_search_action_get_editor (MidoriSearchAction* search_action,
gtk_entry_set_activates_default (GTK_ENTRY (entry_name), TRUE); gtk_entry_set_activates_default (GTK_ENTRY (entry_name), TRUE);
if (!new_engine) if (!new_engine)
gtk_entry_set_text (GTK_ENTRY (entry_name), gtk_entry_set_text (GTK_ENTRY (entry_name),
STR_NON_NULL (katze_item_get_name (item))); katze_str_non_null (katze_item_get_name (item)));
gtk_box_pack_start (GTK_BOX (hbox), entry_name, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), entry_name, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (content_area), hbox); gtk_container_add (GTK_CONTAINER (content_area), hbox);
gtk_widget_show_all (hbox); gtk_widget_show_all (hbox);
@ -956,7 +951,7 @@ midori_search_action_get_editor (MidoriSearchAction* search_action,
gtk_entry_set_activates_default (GTK_ENTRY (entry_description), TRUE); gtk_entry_set_activates_default (GTK_ENTRY (entry_description), TRUE);
if (!new_engine) if (!new_engine)
gtk_entry_set_text (GTK_ENTRY (entry_description) gtk_entry_set_text (GTK_ENTRY (entry_description)
, STR_NON_NULL (katze_item_get_text (item))); , katze_str_non_null (katze_item_get_text (item)));
gtk_box_pack_start (GTK_BOX (hbox), entry_description, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), entry_description, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (content_area), hbox); gtk_container_add (GTK_CONTAINER (content_area), hbox);
gtk_widget_show_all (hbox); gtk_widget_show_all (hbox);
@ -972,10 +967,11 @@ midori_search_action_get_editor (MidoriSearchAction* search_action,
#else #else
NULL); NULL);
#endif #endif
g_object_set_data (G_OBJECT (entry_uri), "allow_%s", (void*)1);
gtk_entry_set_activates_default (GTK_ENTRY (entry_uri), TRUE); gtk_entry_set_activates_default (GTK_ENTRY (entry_uri), TRUE);
if (!new_engine) if (!new_engine)
gtk_entry_set_text (GTK_ENTRY (entry_uri) gtk_entry_set_text (GTK_ENTRY (entry_uri)
, STR_NON_NULL (katze_item_get_uri (item))); , katze_str_non_null (katze_item_get_uri (item)));
gtk_box_pack_start (GTK_BOX (hbox), entry_uri, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), entry_uri, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (content_area), hbox); gtk_container_add (GTK_CONTAINER (content_area), hbox);
gtk_widget_show_all (hbox); gtk_widget_show_all (hbox);
@ -989,7 +985,7 @@ midori_search_action_get_editor (MidoriSearchAction* search_action,
gtk_entry_set_activates_default (GTK_ENTRY (entry_icon), TRUE); gtk_entry_set_activates_default (GTK_ENTRY (entry_icon), TRUE);
if (!new_engine) if (!new_engine)
gtk_entry_set_text (GTK_ENTRY (entry_icon) gtk_entry_set_text (GTK_ENTRY (entry_icon)
, STR_NON_NULL (katze_item_get_icon (item))); , katze_str_non_null (katze_item_get_icon (item)));
gtk_box_pack_start (GTK_BOX (hbox), entry_icon, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), entry_icon, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (content_area), hbox); gtk_container_add (GTK_CONTAINER (content_area), hbox);
gtk_widget_show_all (hbox); gtk_widget_show_all (hbox);
@ -1003,7 +999,7 @@ midori_search_action_get_editor (MidoriSearchAction* search_action,
gtk_entry_set_activates_default (GTK_ENTRY (entry_token), TRUE); gtk_entry_set_activates_default (GTK_ENTRY (entry_token), TRUE);
if (!new_engine) if (!new_engine)
gtk_entry_set_text (GTK_ENTRY (entry_token) gtk_entry_set_text (GTK_ENTRY (entry_token)
, STR_NON_NULL (katze_item_get_token (item))); , katze_str_non_null (katze_item_get_token (item)));
gtk_box_pack_start (GTK_BOX (hbox), entry_token, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (hbox), entry_token, TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (content_area), hbox); gtk_container_add (GTK_CONTAINER (content_area), hbox);
gtk_widget_show_all (hbox); gtk_widget_show_all (hbox);

File diff suppressed because it is too large Load diff

View file

@ -197,6 +197,11 @@ midori_view_can_view_source (MidoriView* view);
gboolean gboolean
midori_view_can_save (MidoriView* view); midori_view_can_save (MidoriView* view);
gchar*
midori_view_save_source (MidoriView* view,
const gchar* uri,
const gchar* outfile);
gboolean gboolean
midori_view_can_find (MidoriView* view); midori_view_can_find (MidoriView* view);

View file

@ -13,6 +13,7 @@
#include "midori-websettings.h" #include "midori-websettings.h"
#include "sokoke.h" #include "sokoke.h"
#include <midori/midori-core.h> /* Vala API */
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <glib/gstdio.h> #include <glib/gstdio.h>
@ -85,6 +86,7 @@ struct _MidoriWebSettings
gint clear_private_data; gint clear_private_data;
gchar* clear_data; gchar* clear_data;
gchar* site_data_rules;
#if !WEBKIT_CHECK_VERSION (1, 3, 13) #if !WEBKIT_CHECK_VERSION (1, 3, 13)
gboolean enable_dns_prefetching; gboolean enable_dns_prefetching;
#endif #endif
@ -145,6 +147,8 @@ enum
PROP_OPEN_TABS_NEXT_TO_CURRENT, PROP_OPEN_TABS_NEXT_TO_CURRENT,
PROP_OPEN_POPUPS_IN_TABS, PROP_OPEN_POPUPS_IN_TABS,
PROP_FLASH_WINDOW_ON_BG_TABS, PROP_FLASH_WINDOW_ON_BG_TABS,
PROP_ENABLE_WEBGL,
PROP_ENABLE_FULLSCREEN,
PROP_AUTO_LOAD_IMAGES, PROP_AUTO_LOAD_IMAGES,
PROP_ENABLE_SCRIPTS, PROP_ENABLE_SCRIPTS,
@ -173,6 +177,7 @@ enum
PROP_CLEAR_PRIVATE_DATA, PROP_CLEAR_PRIVATE_DATA,
PROP_CLEAR_DATA, PROP_CLEAR_DATA,
PROP_SITE_DATA_RULES,
PROP_ENABLE_DNS_PREFETCHING, PROP_ENABLE_DNS_PREFETCHING,
PROP_STRIP_REFERER, PROP_STRIP_REFERER,
PROP_ENFORCE_FONT_FAMILY, PROP_ENFORCE_FONT_FAMILY,
@ -339,6 +344,21 @@ midori_get_download_dir (void)
} }
return g_get_home_dir (); return g_get_home_dir ();
} }
static gboolean
midori_web_settings_low_memory_profile ()
{
gchar* contents;
const gchar* total;
if (!g_file_get_contents ("/proc/meminfo", &contents, NULL, NULL))
return FALSE;
if (contents && (total = strstr (contents, "MemTotal:")) && *total)
{
const gchar* value = katze_skip_whitespace (total + 9);
gdouble mem_total = g_ascii_strtoll (value, NULL, 0);
return mem_total / 1024.0 < 352 + 1;
}
return FALSE;
}
static void static void
midori_web_settings_class_init (MidoriWebSettingsClass* class) midori_web_settings_class_init (MidoriWebSettingsClass* class)
@ -727,13 +747,8 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
"enable-plugins", "enable-plugins",
_("Enable Netscape plugins"), _("Enable Netscape plugins"),
_("Enable embedded Netscape plugin objects"), _("Enable embedded Netscape plugin objects"),
#ifdef G_OS_WIN32 midori_web_settings_has_plugin_support (),
FALSE, midori_web_settings_has_plugin_support () ? flags : G_PARAM_READABLE));
G_PARAM_READABLE));
#else
TRUE,
flags));
#endif
/* Override properties to override defaults */ /* Override properties to override defaults */
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
PROP_ENABLE_DEVELOPER_EXTRAS, PROP_ENABLE_DEVELOPER_EXTRAS,
@ -777,7 +792,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
g_param_spec_boolean ("enable-page-cache", g_param_spec_boolean ("enable-page-cache",
"Enable page cache", "Enable page cache",
"Whether the page cache should be used", "Whether the page cache should be used",
TRUE, !midori_web_settings_low_memory_profile (),
flags)); flags));
#endif #endif
g_object_class_install_property (gobject_class, g_object_class_install_property (gobject_class,
@ -788,6 +803,26 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("Flash the browser window if a new tab was opened in the background"), _("Flash the browser window if a new tab was opened in the background"),
FALSE, FALSE,
flags)); flags));
if (g_object_class_find_property (gobject_class, "enable-webgl"))
g_object_class_install_property (gobject_class,
PROP_ENABLE_WEBGL,
g_param_spec_boolean (
"enable-webgl",
_("Enable WebGL support"),
_("Allow websites to use OpenGL rendering"),
/* Enable by default for git builds */
!g_str_equal (PACKAGE_VERSION, MIDORI_VERSION),
flags));
if (g_object_class_find_property (gobject_class, "enable-fullscreen"))
g_object_class_install_property (gobject_class,
PROP_ENABLE_FULLSCREEN,
g_param_spec_boolean (
"enable-fullscreen",
"Enable Fullscreen",
"Allow experimental fullscreen API",
TRUE,
flags));
/** /**
* MidoriWebSettings:zoom-text-and-images: * MidoriWebSettings:zoom-text-and-images:
@ -1021,6 +1056,22 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
_("The data selected for deletion"), _("The data selected for deletion"),
NULL, NULL,
flags)); flags));
/**
* MidoriWebSettings:site-data-rules:
*
* Rules for accepting, denying and preserving cookies and other data.
* See midori_web_settings_get_site_data_policy() for details.
*
* Since: 0.4.4
*/
g_object_class_install_property (gobject_class,
PROP_SITE_DATA_RULES,
g_param_spec_string (
"site-data-rules",
"Rules for accepting, denying and preserving cookies and other data",
"Cookies, HTML5 databases, local storage and application cache blocking",
NULL,
flags));
#if !WEBKIT_CHECK_VERSION (1, 3, 13) #if !WEBKIT_CHECK_VERSION (1, 3, 13)
/** /**
* MidoriWebSettings:enable-dns-prefetching: * MidoriWebSettings:enable-dns-prefetching:
@ -1180,6 +1231,74 @@ midori_web_settings_finalize (GObject* object)
G_OBJECT_CLASS (midori_web_settings_parent_class)->finalize (object); G_OBJECT_CLASS (midori_web_settings_parent_class)->finalize (object);
} }
/**
* midori_web_settings_has_plugin_support:
*
* Determines if Netscape plugins are supported.
*
* Returns: %TRUE if Netscape plugins can be used
*
* Since: 0.4.4
**/
gboolean
midori_web_settings_has_plugin_support (void)
{
#ifdef G_OS_WIN32
return FALSE;
#else
return g_getenv ("MIDORI_UNARMED") == NULL
&& g_strcmp0 (g_getenv ("MOZ_PLUGIN_PATH"), "/");
#endif
}
/**
* midori_web_settings_get_site_data_policy:
*
* Tests if @uri may store site data.
*
* Returns: a #MidoriSiteDataPolicy
*
* Since: 0.4.4
**/
MidoriSiteDataPolicy
midori_web_settings_get_site_data_policy (MidoriWebSettings* settings,
const gchar* uri)
{
MidoriSiteDataPolicy policy = MIDORI_SITE_DATA_UNDETERMINED;
gchar* hostname;
const gchar* match;
g_return_val_if_fail (MIDORI_IS_WEB_SETTINGS (settings), policy);
if (!(settings->site_data_rules && *settings->site_data_rules))
return policy;
/*
* Values prefixed with "-" are always blocked
* Values prefixed with "+" are always accepted
* Values prefixed with "!" are not cleared in Clear Private Data
* FIXME: "*" is a wildcard
* FIXME: indicate type of storage the rule applies to
* FIXME: support matching of the whole URI
**/
hostname = midori_uri_parse_hostname (uri, NULL);
match = strstr (settings->site_data_rules, hostname ? hostname : uri);
if (match != NULL && match != settings->site_data_rules)
{
const gchar* prefix = match - 1;
if (*prefix == '-')
policy = MIDORI_SITE_DATA_BLOCK;
else if (*prefix == '+')
policy = MIDORI_SITE_DATA_ACCEPT;
else if (*prefix == '!')
policy = MIDORI_SITE_DATA_PRESERVE;
else
g_warning ("%s: Matched with no prefix '%s'", G_STRFUNC, match);
}
g_free (hostname);
return policy;
}
#if (!HAVE_OSX && defined (G_OS_UNIX)) || defined (G_OS_WIN32) #if (!HAVE_OSX && defined (G_OS_UNIX)) || defined (G_OS_WIN32)
static gchar* static gchar*
get_sys_name (gchar** architecture) get_sys_name (gchar** architecture)
@ -1544,6 +1663,9 @@ midori_web_settings_set_property (GObject* object,
case PROP_CLEAR_DATA: case PROP_CLEAR_DATA:
katze_assign (web_settings->clear_data, g_value_dup_string (value)); katze_assign (web_settings->clear_data, g_value_dup_string (value));
break; break;
case PROP_SITE_DATA_RULES:
katze_assign (web_settings->site_data_rules, g_value_dup_string (value));
break;
#if !WEBKIT_CHECK_VERSION (1, 3, 13) #if !WEBKIT_CHECK_VERSION (1, 3, 13)
case PROP_ENABLE_DNS_PREFETCHING: case PROP_ENABLE_DNS_PREFETCHING:
web_settings->enable_dns_prefetching = g_value_get_boolean (value); web_settings->enable_dns_prefetching = g_value_get_boolean (value);
@ -1574,6 +1696,14 @@ midori_web_settings_set_property (GObject* object,
case PROP_FLASH_WINDOW_ON_BG_TABS: case PROP_FLASH_WINDOW_ON_BG_TABS:
web_settings->flash_window_on_bg_tabs = g_value_get_boolean (value); web_settings->flash_window_on_bg_tabs = g_value_get_boolean (value);
break; break;
case PROP_ENABLE_WEBGL:
g_object_set (web_settings, "WebKitWebSettings::enable-webgl",
g_value_get_boolean (value), NULL);
break;
case PROP_ENABLE_FULLSCREEN:
g_object_set (web_settings, "WebKitWebSettings::enable-fullscreen",
g_value_get_boolean (value), NULL);
break;
case PROP_USER_STYLESHEET_URI: case PROP_USER_STYLESHEET_URI:
{ {
gint old_len = web_settings->user_stylesheet_uri_cached gint old_len = web_settings->user_stylesheet_uri_cached
@ -1845,6 +1975,9 @@ midori_web_settings_get_property (GObject* object,
case PROP_CLEAR_DATA: case PROP_CLEAR_DATA:
g_value_set_string (value, web_settings->clear_data); g_value_set_string (value, web_settings->clear_data);
break; break;
case PROP_SITE_DATA_RULES:
g_value_set_string (value, web_settings->site_data_rules);
break;
#if !WEBKIT_CHECK_VERSION (1, 3, 13) #if !WEBKIT_CHECK_VERSION (1, 3, 13)
case PROP_ENABLE_DNS_PREFETCHING: case PROP_ENABLE_DNS_PREFETCHING:
g_value_set_boolean (value, web_settings->enable_dns_prefetching); g_value_set_boolean (value, web_settings->enable_dns_prefetching);
@ -1859,6 +1992,14 @@ midori_web_settings_get_property (GObject* object,
case PROP_FLASH_WINDOW_ON_BG_TABS: case PROP_FLASH_WINDOW_ON_BG_TABS:
g_value_set_boolean (value, web_settings->flash_window_on_bg_tabs); g_value_set_boolean (value, web_settings->flash_window_on_bg_tabs);
break; break;
case PROP_ENABLE_WEBGL:
g_value_set_boolean (value, katze_object_get_boolean (web_settings,
"WebKitWebSettings::enable-webgl"));
break;
case PROP_ENABLE_FULLSCREEN:
g_value_set_boolean (value, katze_object_get_boolean (web_settings,
"WebKitWebSettings::enable-fullscreen"));
break;
case PROP_USER_STYLESHEET_URI: case PROP_USER_STYLESHEET_URI:
g_value_take_string (value, katze_object_get_string (web_settings, g_value_take_string (value, katze_object_get_string (web_settings,
"WebKitWebSettings::user-stylesheet-uri")); "WebKitWebSettings::user-stylesheet-uri"));

View file

@ -173,6 +173,21 @@ const gchar*
midori_web_settings_get_system_name (gchar** architecture, midori_web_settings_get_system_name (gchar** architecture,
gchar** platform); gchar** platform);
gboolean
midori_web_settings_has_plugin_support (void);
typedef enum
{
MIDORI_SITE_DATA_UNDETERMINED,
MIDORI_SITE_DATA_BLOCK,
MIDORI_SITE_DATA_ACCEPT,
MIDORI_SITE_DATA_PRESERVE,
} MidoriSiteDataPolicy;
MidoriSiteDataPolicy
midori_web_settings_get_site_data_policy (MidoriWebSettings* settings,
const gchar* uri);
G_END_DECLS G_END_DECLS
#endif /* __MIDORI_WEB_SETTINGS_H__ */ #endif /* __MIDORI_WEB_SETTINGS_H__ */

View file

@ -54,9 +54,6 @@
#endif #endif
#include "socket.h" #include "socket.h"
#if USE_SSL
# include <openssl/ssl.h>
#endif
#ifdef G_ENABLE_DEBUG #ifdef G_ENABLE_DEBUG
# define debug_print g_debug # define debug_print g_debug
@ -562,10 +559,6 @@ gboolean sock_has_read_data(SockInfo *sock)
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
gulong val; gulong val;
#if USE_SSL
if (sock->ssl)
return TRUE;
#endif
if (ioctlsocket(sock->sock, FIONREAD, &val) < 0) { if (ioctlsocket(sock->sock, FIONREAD, &val) < 0) {
g_warning("sock_has_read_data(): ioctlsocket() failed: %d\n", g_warning("sock_has_read_data(): ioctlsocket() failed: %d\n",
WSAGetLastError()); WSAGetLastError());
@ -595,22 +588,6 @@ static gboolean sock_check(GSource *source)
fd_set fds; fd_set fds;
GIOCondition condition = sock->condition; GIOCondition condition = sock->condition;
#if USE_SSL
if (sock->ssl) {
if (condition & G_IO_IN) {
if (SSL_pending(sock->ssl) > 0)
return TRUE;
if (SSL_want_write(sock->ssl))
condition |= G_IO_OUT;
}
if (condition & G_IO_OUT) {
if (SSL_want_read(sock->ssl))
condition |= G_IO_IN;
}
}
#endif
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(sock->sock, &fds); FD_SET(sock->sock, &fds);
@ -647,19 +624,6 @@ guint sock_add_watch(SockInfo *sock, GIOCondition condition, SockFunc func,
sock->callback = func; sock->callback = func;
sock->condition = condition; sock->condition = condition;
sock->data = data; sock->data = data;
#if USE_SSL
if (sock->ssl) {
GSource *source;
source = g_source_new(&sock_watch_funcs, sizeof(SockSource));
((SockSource *)source)->sock = sock;
g_source_set_priority(source, G_PRIORITY_DEFAULT);
g_source_set_can_recurse(source, FALSE);
return g_source_attach(source, NULL);
}
#endif
return g_io_add_watch(sock->sock_ch, condition, sock_watch_cb, sock); return g_io_add_watch(sock->sock_ch, condition, sock_watch_cb, sock);
} }
@ -1375,10 +1339,6 @@ gint sock_read(SockInfo *sock, gchar *buf, gint len)
{ {
g_return_val_if_fail(sock != NULL, -1); g_return_val_if_fail(sock != NULL, -1);
#if USE_SSL
if (sock->ssl)
return ssl_read(sock->ssl, buf, len);
#endif
return fd_read(sock->sock, buf, len); return fd_read(sock->sock, buf, len);
} }
@ -1394,44 +1354,10 @@ gint fd_read(gint fd, gchar *buf, gint len)
#endif #endif
} }
#if USE_SSL
gint ssl_read(SSL *ssl, gchar *buf, gint len)
{
gint err, ret;
if (SSL_pending(ssl) == 0) {
if (fd_check_io(SSL_get_rfd(ssl), G_IO_IN) < 0)
return -1;
}
ret = SSL_read(ssl, buf, len);
switch ((err = SSL_get_error(ssl, ret))) {
case SSL_ERROR_NONE:
return ret;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
errno = EAGAIN;
return -1;
case SSL_ERROR_ZERO_RETURN:
return 0;
default:
g_warning("SSL_read() returned error %d, ret = %d\n", err, ret);
if (ret == 0)
return 0;
return -1;
}
}
#endif
gint sock_write(SockInfo *sock, const gchar *buf, gint len) gint sock_write(SockInfo *sock, const gchar *buf, gint len)
{ {
g_return_val_if_fail(sock != NULL, -1); g_return_val_if_fail(sock != NULL, -1);
#if USE_SSL
if (sock->ssl)
return ssl_write(sock->ssl, buf, len);
#endif
return fd_write(sock->sock, buf, len); return fd_write(sock->sock, buf, len);
} }
@ -1459,34 +1385,10 @@ gint fd_write(gint fd, const gchar *buf, gint len)
#endif #endif
} }
#if USE_SSL
gint ssl_write(SSL *ssl, const gchar *buf, gint len)
{
gint ret;
ret = SSL_write(ssl, buf, len);
switch (SSL_get_error(ssl, ret)) {
case SSL_ERROR_NONE:
return ret;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
errno = EAGAIN;
return -1;
default:
return -1;
}
}
#endif
gint sock_write_all(SockInfo *sock, const gchar *buf, gint len) gint sock_write_all(SockInfo *sock, const gchar *buf, gint len)
{ {
g_return_val_if_fail(sock != NULL, -1); g_return_val_if_fail(sock != NULL, -1);
#if USE_SSL
if (sock->ssl)
return ssl_write_all(sock->ssl, buf, len);
#endif
return fd_write_all(sock->sock, buf, len); return fd_write_all(sock->sock, buf, len);
} }
@ -1506,24 +1408,6 @@ gint fd_write_all(gint fd, const gchar *buf, gint len)
return wrlen; return wrlen;
} }
#if USE_SSL
gint ssl_write_all(SSL *ssl, const gchar *buf, gint len)
{
gint n, wrlen = 0;
while (len) {
n = ssl_write(ssl, buf, len);
if (n <= 0)
return -1;
len -= n;
wrlen += n;
buf += n;
}
return wrlen;
}
#endif
gint fd_recv(gint fd, gchar *buf, gint len, gint flags) gint fd_recv(gint fd, gchar *buf, gint len, gint flags)
{ {
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
@ -1570,38 +1454,10 @@ gint fd_gets(gint fd, gchar *buf, gint len)
return bp - buf; return bp - buf;
} }
#if USE_SSL
gint ssl_gets(SSL *ssl, gchar *buf, gint len)
{
gchar *newline, *bp = buf;
gint n;
if (--len < 1)
return -1;
do {
if ((n = ssl_peek(ssl, bp, len)) <= 0)
return -1;
if ((newline = memchr(bp, '\n', n)) != NULL)
n = newline - bp + 1;
if ((n = ssl_read(ssl, bp, n)) < 0)
return -1;
bp += n;
len -= n;
} while (!newline && len);
*bp = '\0';
return bp - buf;
}
#endif
gint sock_gets(SockInfo *sock, gchar *buf, gint len) gint sock_gets(SockInfo *sock, gchar *buf, gint len)
{ {
g_return_val_if_fail(sock != NULL, -1); g_return_val_if_fail(sock != NULL, -1);
#if USE_SSL
if (sock->ssl)
return ssl_gets(sock->ssl, buf, len);
#endif
return fd_gets(sock->sock, buf, len); return fd_gets(sock->sock, buf, len);
} }
@ -1630,42 +1486,11 @@ gint fd_getline(gint fd, gchar **line)
return (gint)size; return (gint)size;
} }
#if USE_SSL
gint ssl_getline(SSL *ssl, gchar **line)
{
gchar buf[BUFFSIZE];
gchar *str = NULL;
gint len;
gulong size = 0;
gulong cur_offset = 0;
while ((len = ssl_gets(ssl, buf, sizeof(buf))) > 0) {
size += len;
str = g_realloc(str, size + 1);
memcpy(str + cur_offset, buf, len + 1);
cur_offset += len;
if (buf[len - 1] == '\n')
break;
}
*line = str;
if (!str)
return -1;
else
return (gint)size;
}
#endif
gint sock_getline(SockInfo *sock, gchar **line) gint sock_getline(SockInfo *sock, gchar **line)
{ {
g_return_val_if_fail(sock != NULL, -1); g_return_val_if_fail(sock != NULL, -1);
g_return_val_if_fail(line != NULL, -1); g_return_val_if_fail(line != NULL, -1);
#if USE_SSL
if (sock->ssl)
return ssl_getline(sock->ssl, line);
#endif
return fd_getline(sock->sock, line); return fd_getline(sock->sock, line);
} }
@ -1679,44 +1504,10 @@ gint sock_puts(SockInfo *sock, const gchar *buf)
} }
/* peek at the socket data without actually reading it */ /* peek at the socket data without actually reading it */
#if USE_SSL
gint ssl_peek(SSL *ssl, gchar *buf, gint len)
{
gint err, ret;
if (SSL_pending(ssl) == 0) {
if (fd_check_io(SSL_get_rfd(ssl), G_IO_IN) < 0)
return -1;
}
ret = SSL_peek(ssl, buf, len);
switch ((err = SSL_get_error(ssl, ret))) {
case SSL_ERROR_NONE:
return ret;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
errno = EAGAIN;
return -1;
case SSL_ERROR_ZERO_RETURN:
return 0;
default:
g_warning("SSL_peek() returned error %d, ret = %d\n", err, ret);
if (ret == 0)
return 0;
return -1;
}
}
#endif
gint sock_peek(SockInfo *sock, gchar *buf, gint len) gint sock_peek(SockInfo *sock, gchar *buf, gint len)
{ {
g_return_val_if_fail(sock != NULL, -1); g_return_val_if_fail(sock != NULL, -1);
#if USE_SSL
if (sock->ssl)
return ssl_peek(sock->ssl, buf, len);
#endif
return fd_recv(sock->sock, buf, len, MSG_PEEK); return fd_recv(sock->sock, buf, len, MSG_PEEK);
} }
@ -1727,11 +1518,6 @@ gint sock_close(SockInfo *sock)
if (!sock) if (!sock)
return 0; return 0;
#if USE_SSL
if (sock->ssl)
ssl_done_socket(sock);
#endif
if (sock->sock_ch) { if (sock->sock_ch) {
g_io_channel_shutdown(sock->sock_ch, FALSE, NULL); g_io_channel_shutdown(sock->sock_ch, FALSE, NULL);
g_io_channel_unref(sock->sock_ch); g_io_channel_unref(sock->sock_ch);
@ -1759,13 +1545,4 @@ gint fd_close(gint fd)
#endif #endif
} }
#if USE_SSL
void ssl_done_socket(SockInfo *sockinfo)
{
if (sockinfo->ssl) {
SSL_free(sockinfo->ssl);
}
}
#endif
#endif #endif

View file

@ -20,10 +20,6 @@
typedef struct _SockInfo SockInfo; typedef struct _SockInfo SockInfo;
#if USE_SSL
# include <openssl/ssl.h>
#endif
typedef enum typedef enum
{ {
CONN_READY, CONN_READY,
@ -42,11 +38,6 @@ typedef gboolean (*SockFunc) (SockInfo *sock,
struct _SockInfo struct _SockInfo
{ {
gint sock; gint sock;
#if USE_SSL
SSL *ssl;
#else
gpointer ssl;
#endif
GIOChannel *sock_ch; GIOChannel *sock_ch;
gchar *hostname; gchar *hostname;
@ -111,15 +102,4 @@ gint fd_gets (gint sock, gchar *buf, gint len);
gint fd_getline (gint sock, gchar **line); gint fd_getline (gint sock, gchar **line);
gint fd_close (gint sock); gint fd_close (gint sock);
/* Functions for SSL */
#if USE_SSL
gint ssl_read (SSL *ssl, gchar *buf, gint len);
gint ssl_write (SSL *ssl, const gchar *buf, gint len);
gint ssl_write_all (SSL *ssl, const gchar *buf, gint len);
gint ssl_gets (SSL *ssl, gchar *buf, gint len);
gint ssl_getline (SSL *ssl, gchar **line);
gint ssl_peek (SSL *ssl, gchar *buf, gint len);
void ssl_done_socket (SockInfo *sockinfo);
#endif
#endif /* __SYLPH_SOCKET_H__ */ #endif /* __SYLPH_SOCKET_H__ */

View file

@ -64,13 +64,15 @@ sokoke_js_script_eval (JSContextRef js_context,
{ {
gchar* value; gchar* value;
JSStringRef js_value_string; JSStringRef js_value_string;
JSStringRef js_script;
JSValueRef js_exception = NULL;
JSValueRef js_value;
g_return_val_if_fail (js_context, FALSE); g_return_val_if_fail (js_context, FALSE);
g_return_val_if_fail (script, FALSE); g_return_val_if_fail (script, FALSE);
JSStringRef js_script = JSStringCreateWithUTF8CString (script); js_script = JSStringCreateWithUTF8CString (script);
JSValueRef js_exception = NULL; js_value = JSEvaluateScript (js_context, js_script,
JSValueRef js_value = JSEvaluateScript (js_context, js_script,
JSContextGetGlobalObject (js_context), NULL, 0, &js_exception); JSContextGetGlobalObject (js_context), NULL, 0, &js_exception);
JSStringRelease (js_script); JSStringRelease (js_script);
@ -649,7 +651,7 @@ sokoke_magic_uri (const gchar* uri)
/* Add file:// if we have a local path */ /* Add file:// if we have a local path */
if (g_path_is_absolute (uri)) if (g_path_is_absolute (uri))
return g_strconcat ("file://", uri, NULL); return g_filename_to_uri (uri, NULL, NULL);
/* Parse geo URI geo:48.202778,16.368472;crs=wgs84;u=40 as a location */ /* Parse geo URI geo:48.202778,16.368472;crs=wgs84;u=40 as a location */
if (!strncmp (uri, "geo:", 4)) if (!strncmp (uri, "geo:", 4))
{ {
@ -684,7 +686,7 @@ sokoke_magic_uri (const gchar* uri)
search = NULL; search = NULL;
if (!strchr (uri, ' ') && if (!strchr (uri, ' ') &&
((search = strchr (uri, ':')) || (search = strchr (uri, '@'))) && ((search = strchr (uri, ':')) || (search = strchr (uri, '@'))) &&
search[0] && !g_ascii_isalpha (search[1])) search[0] && g_ascii_isdigit (search[1]))
return g_strconcat ("http://", uri, NULL); return g_strconcat ("http://", uri, NULL);
if ((!strcmp (uri, "localhost") || strchr (uri, '/')) if ((!strcmp (uri, "localhost") || strchr (uri, '/'))
&& sokoke_resolve_hostname (uri)) && sokoke_resolve_hostname (uri))
@ -793,7 +795,6 @@ sokoke_xfce_header_new (const gchar* icon,
if (sokoke_get_desktop () == SOKOKE_DESKTOP_XFCE) if (sokoke_get_desktop () == SOKOKE_DESKTOP_XFCE)
{ {
GtkWidget* entry; GtkWidget* entry;
GtkStyle* style;
gchar* markup; gchar* markup;
GtkWidget* xfce_heading; GtkWidget* xfce_heading;
GtkWidget* hbox; GtkWidget* hbox;
@ -804,9 +805,7 @@ sokoke_xfce_header_new (const gchar* icon,
xfce_heading = gtk_event_box_new (); xfce_heading = gtk_event_box_new ();
entry = gtk_entry_new (); entry = gtk_entry_new ();
style = gtk_widget_get_style (entry);
gtk_widget_modify_bg (xfce_heading, GTK_STATE_NORMAL,
&style->base[GTK_STATE_NORMAL]);
hbox = gtk_hbox_new (FALSE, 12); hbox = gtk_hbox_new (FALSE, 12);
gtk_container_set_border_width (GTK_CONTAINER (hbox), 6); gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
if (icon) if (icon)
@ -816,8 +815,6 @@ sokoke_xfce_header_new (const gchar* icon,
GTK_ICON_SIZE_DIALOG); GTK_ICON_SIZE_DIALOG);
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
label = gtk_label_new (NULL); label = gtk_label_new (NULL);
gtk_widget_modify_fg (label, GTK_STATE_NORMAL
, &style->text[GTK_STATE_NORMAL]);
markup = g_strdup_printf ("<span size='large' weight='bold'>%s</span>", markup = g_strdup_printf ("<span size='large' weight='bold'>%s</span>",
title); title);
gtk_label_set_markup (GTK_LABEL (label), markup); gtk_label_set_markup (GTK_LABEL (label), markup);
@ -826,6 +823,16 @@ sokoke_xfce_header_new (const gchar* icon,
g_free (markup); g_free (markup);
gtk_widget_destroy (entry); gtk_widget_destroy (entry);
#if !GTK_CHECK_VERSION (3, 0, 0)
{
GtkStyle* style = gtk_widget_get_style (entry);
gtk_widget_modify_bg (xfce_heading, GTK_STATE_NORMAL,
&style->base[GTK_STATE_NORMAL]);
gtk_widget_modify_fg (label, GTK_STATE_NORMAL
, &style->text[GTK_STATE_NORMAL]);
}
#endif
vbox = gtk_vbox_new (FALSE, 0); vbox = gtk_vbox_new (FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), xfce_heading, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (vbox), xfce_heading, FALSE, FALSE, 0);
@ -1029,37 +1036,6 @@ sokoke_time_t_to_julian (const time_t* timestamp)
return julian; return julian;
} }
/**
* sokoke_days_between:
* @day1: a time_t timestamp value
* @day2: a time_t timestamp value
*
* Calculates the number of days between two timestamps.
*
* Return value: an integer.
**/
gint
sokoke_days_between (const time_t* day1,
const time_t* day2)
{
GDate* date1;
GDate* date2;
gint age;
date1 = g_date_new ();
date2 = g_date_new ();
g_date_set_time_t (date1, *day1);
g_date_set_time_t (date2, *day2);
age = g_date_days_between (date1, date2);
g_date_free (date1);
g_date_free (date2);
return age;
}
/** /**
* sokoke_set_config_dir: * sokoke_set_config_dir:
* @new_config_dir: an absolute path, or %NULL * @new_config_dir: an absolute path, or %NULL
@ -1731,3 +1707,87 @@ midori_download_prepare_tooltip_text (WebKitDownload* download)
return g_string_free (tooltip, FALSE); return g_string_free (tooltip, FALSE);
} }
static gboolean
sokoke_entry_has_placeholder_text (GtkEntry* entry)
{
const gchar* text = gtk_entry_get_text (entry);
const gchar* hint = gtk_entry_get_placeholder_text (entry);
if (!gtk_widget_has_focus (GTK_WIDGET (entry))
&& hint != NULL
&& (text == NULL || !strcmp (text, hint)))
return TRUE;
return FALSE;
}
static void
sokoke_entry_changed_cb (GtkEditable* editable,
GtkEntry* entry)
{
const gchar* text = gtk_entry_get_text (entry);
gboolean visible = text && *text
&& ! sokoke_entry_has_placeholder_text (entry);
gtk_icon_entry_set_icon_from_stock (
GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_SECONDARY,
visible ? GTK_STOCK_CLEAR : NULL);
}
static gboolean
sokoke_entry_focus_out_event_cb (GtkEditable* editable,
GdkEventFocus* event,
GtkEntry* entry)
{
sokoke_entry_changed_cb (editable, entry);
return FALSE;
}
static void
sokoke_entry_icon_released_cb (GtkEntry* entry,
GtkIconEntryPosition icon_pos,
GdkEvent* event,
gpointer user_data)
{
if (icon_pos != GTK_ICON_ENTRY_SECONDARY)
return;
gtk_entry_set_text (entry, "");
gtk_widget_grab_focus (GTK_WIDGET (entry));
}
void
sokoke_entry_set_clear_button_visible (GtkEntry* entry,
gboolean visible)
{
g_return_if_fail (GTK_IS_ENTRY (entry));
gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_SECONDARY, TRUE);
if (visible)
{
g_object_connect (entry,
"signal::icon-release",
G_CALLBACK (sokoke_entry_icon_released_cb), NULL,
"signal::focus-in-event",
G_CALLBACK (sokoke_entry_focus_out_event_cb), entry,
"signal::focus-out-event",
G_CALLBACK (sokoke_entry_focus_out_event_cb), entry,
"signal::changed",
G_CALLBACK (sokoke_entry_changed_cb), entry, NULL);
sokoke_entry_changed_cb ((GtkEditable*)entry, entry);
}
else
{
g_object_disconnect (entry,
"any_signal::icon-release",
G_CALLBACK (sokoke_entry_icon_released_cb), NULL,
"any_signal::focus-in-event",
G_CALLBACK (sokoke_entry_focus_out_event_cb), entry,
"any_signal::focus-out-event",
G_CALLBACK (sokoke_entry_focus_out_event_cb), entry,
"any_signal::changed",
G_CALLBACK (sokoke_entry_changed_cb), entry, NULL);
gtk_icon_entry_set_icon_from_stock (
GTK_ICON_ENTRY (entry), GTK_ICON_ENTRY_SECONDARY, NULL);
}
}

View file

@ -121,10 +121,6 @@ sokoke_action_create_popup_menu_item (GtkAction* action);
gint64 gint64
sokoke_time_t_to_julian (const time_t* timestamp); sokoke_time_t_to_julian (const time_t* timestamp);
gint
sokoke_days_between (const time_t* day1,
const time_t* day2);
const gchar* const gchar*
sokoke_set_config_dir (const gchar* new_config_dir); sokoke_set_config_dir (const gchar* new_config_dir);
@ -202,4 +198,8 @@ sokoke_build_thumbnail_path (const gchar* name);
gchar* gchar*
midori_download_prepare_tooltip_text (WebKitDownload* download); midori_download_prepare_tooltip_text (WebKitDownload* download);
void
sokoke_entry_set_clear_button_visible (GtkEntry* entry,
gboolean visible);
#endif /* !__SOKOKE_H__ */ #endif /* !__SOKOKE_H__ */

View file

@ -7,7 +7,7 @@ import platform
progressive = True progressive = True
libs = 'M UNIQUE LIBSOUP GMODULE GTHREAD LIBIDN GIO GTK SQLITE ' \ libs = 'M UNIQUE LIBSOUP GMODULE GTHREAD LIBIDN GIO GTK SQLITE ' \
'LIBNOTIFY WEBKIT JAVASCRIPTCOREGTK LIBXML X11 XSS WS2_32 OPENSSL HILDON' \ 'LIBNOTIFY WEBKIT JAVASCRIPTCOREGTK LIBXML X11 XSS WS2_32 HILDON' \
'HILDON_FM' 'HILDON_FM'
if progressive or Options.commands['check']: if progressive or Options.commands['check']:

View file

@ -925,11 +925,7 @@ midori_bookmarks_init (MidoriBookmarks* bookmarks)
gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry), gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_PRIMARY, GTK_ICON_ENTRY_PRIMARY,
GTK_STOCK_FIND); GTK_STOCK_FIND);
gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry), sokoke_entry_set_clear_button_visible (GTK_ENTRY (entry), TRUE);
GTK_ICON_ENTRY_SECONDARY,
GTK_STOCK_CLEAR);
gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_SECONDARY, TRUE);
g_signal_connect (entry, "icon-release", g_signal_connect (entry, "icon-release",
G_CALLBACK (midori_bookmarks_filter_entry_clear_cb), bookmarks); G_CALLBACK (midori_bookmarks_filter_entry_clear_cb), bookmarks);
g_signal_connect (entry, "changed", g_signal_connect (entry, "changed",

View file

@ -116,18 +116,59 @@ midori_history_get_stock_id (MidoriViewable* viewable)
return STOCK_HISTORY; return STOCK_HISTORY;
} }
#if !GLIB_CHECK_VERSION (2, 26, 0)
static gint
sokoke_days_between (const time_t* day1,
const time_t* day2)
{
GDate* date1;
GDate* date2;
gint age;
date1 = g_date_new ();
date2 = g_date_new ();
g_date_set_time_t (date1, *day1);
g_date_set_time_t (date2, *day2);
age = g_date_days_between (date1, date2);
g_date_free (date1);
g_date_free (date2);
return age;
}
#endif
static gchar* static gchar*
midori_history_format_date (KatzeItem *item) midori_history_format_date (KatzeItem *item)
{ {
gint age; gint64 day = katze_item_get_added (item);
gint64 day;
gchar token[50];
gchar* sdate; gchar* sdate;
gint age;
#if GLIB_CHECK_VERSION (2, 26, 0)
GDateTime* now = g_date_time_new_now_local ();
GDateTime* then = g_date_time_new_from_unix_local (day);
age = g_date_time_get_day_of_year (now) - g_date_time_get_day_of_year (then);
if (g_date_time_get_year (now) != g_date_time_get_year (then))
age = 999;
if (age == 0)
sdate = g_strdup (_("Today"));
else if (age == 1)
sdate = g_strdup (_("Yesterday"));
else if (age < 7)
sdate = g_strdup_printf (ngettext ("%d day ago",
"%d days ago", (gint)age), (gint)age);
else if (age == 7)
sdate = g_strdup (_("A week ago"));
else
sdate = g_date_time_format (then, "%x");
#else
gchar token[50];
time_t current_time; time_t current_time;
current_time = time (NULL); current_time = time (NULL);
day = katze_item_get_added (item);
age = sokoke_days_between ((time_t*)&day, &current_time); age = sokoke_days_between ((time_t*)&day, &current_time);
/* A negative age is a date in the future, the clock is probably off */ /* A negative age is a date in the future, the clock is probably off */
@ -147,6 +188,7 @@ midori_history_format_date (KatzeItem *item)
sdate = g_strdup (_("Today")); sdate = g_strdup (_("Today"));
else else
sdate = g_strdup (_("Yesterday")); sdate = g_strdup (_("Yesterday"));
#endif
return sdate; return sdate;
} }
@ -412,9 +454,8 @@ midori_history_add_item_cb (KatzeArray* array,
GtkTreeModel* model = gtk_tree_view_get_model (treeview); GtkTreeModel* model = gtk_tree_view_get_model (treeview);
GtkTreeIter iter; GtkTreeIter iter;
KatzeItem* today; KatzeItem* today;
time_t current_time; time_t current_time = time (NULL);
current_time = time (NULL);
if (gtk_tree_model_iter_children (model, &iter, NULL)) if (gtk_tree_model_iter_children (model, &iter, NULL))
{ {
gint64 day; gint64 day;
@ -423,7 +464,18 @@ midori_history_add_item_cb (KatzeArray* array,
gtk_tree_model_get (model, &iter, 0, &today, -1); gtk_tree_model_get (model, &iter, 0, &today, -1);
day = katze_item_get_added (today); day = katze_item_get_added (today);
#if GLIB_CHECK_VERSION (2, 26, 0)
has_today = g_date_time_get_day_of_month (
g_date_time_new_from_unix_local (day))
== g_date_time_get_day_of_month (
g_date_time_new_from_unix_local (current_time))
&& g_date_time_get_day_of_year (
g_date_time_new_from_unix_local (day))
== g_date_time_get_day_of_year (
g_date_time_new_from_unix_local (current_time));
#else
has_today = sokoke_days_between ((time_t*)&day, &current_time) == 0; has_today = sokoke_days_between ((time_t*)&day, &current_time) == 0;
#endif
g_object_unref (today); g_object_unref (today);
if (has_today) if (has_today)
{ {
@ -945,12 +997,7 @@ midori_history_init (MidoriHistory* history)
gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry), gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_PRIMARY, GTK_ICON_ENTRY_PRIMARY,
GTK_STOCK_FIND); GTK_STOCK_FIND);
gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry), sokoke_entry_set_clear_button_visible (GTK_ENTRY (entry), TRUE);
GTK_ICON_ENTRY_SECONDARY,
GTK_STOCK_CLEAR);
gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (entry),
GTK_ICON_ENTRY_SECONDARY,
TRUE);
g_signal_connect (entry, "icon-release", g_signal_connect (entry, "icon-release",
G_CALLBACK (midori_history_filter_entry_clear_cb), history); G_CALLBACK (midori_history_filter_entry_clear_cb), history);
g_signal_connect (entry, "changed", g_signal_connect (entry, "changed",

View file

@ -39,7 +39,9 @@ extensions/feed-panel/feed-panel.c
extensions/feed-panel/feed-parse.c extensions/feed-panel/feed-parse.c
extensions/feed-panel/feed-rss.c extensions/feed-panel/feed-rss.c
extensions/feed-panel/main.c extensions/feed-panel/main.c
extensions/formhistory.c extensions/formhistory/formhistory.c
extensions/formhistory/formhistory-gdom-frontend.c
extensions/formhistory/formhistory-js-frontend.c
extensions/history-list.vala extensions/history-list.vala
extensions/mouse-gestures.c extensions/mouse-gestures.c
extensions/shortcuts.c extensions/shortcuts.c

2211
po/ar.po

File diff suppressed because it is too large Load diff

2032
po/ca.po

File diff suppressed because it is too large Load diff

1721
po/cs.po

File diff suppressed because it is too large Load diff

1008
po/da.po

File diff suppressed because it is too large Load diff

1483
po/de.po

File diff suppressed because it is too large Load diff

2793
po/eo.po Normal file

File diff suppressed because it is too large Load diff

1546
po/es.po

File diff suppressed because it is too large Load diff

1481
po/he.po

File diff suppressed because it is too large Load diff

2656
po/hu.po

File diff suppressed because it is too large Load diff

2073
po/id.po

File diff suppressed because it is too large Load diff

2225
po/it.po

File diff suppressed because it is too large Load diff

1307
po/ja.po

File diff suppressed because it is too large Load diff

1675
po/ko.po

File diff suppressed because it is too large Load diff

2751
po/lt.po

File diff suppressed because it is too large Load diff

1193
po/nl.po

File diff suppressed because it is too large Load diff

1002
po/pl.po

File diff suppressed because it is too large Load diff

1612
po/pt.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1460
po/ru.po

File diff suppressed because it is too large Load diff

1206
po/sk.po

File diff suppressed because it is too large Load diff

2100
po/tr.po

File diff suppressed because it is too large Load diff

1270
po/uk.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -94,6 +94,38 @@ browser_tooltips (void)
g_error ("Tooltip errors"); g_error ("Tooltip errors");
} }
static void
browser_site_data (void)
{
typedef struct
{
const gchar* url;
MidoriSiteDataPolicy policy;
} PolicyItem;
static const PolicyItem items[] = {
{ "google.com", MIDORI_SITE_DATA_BLOCK },
{ "facebook.com", MIDORI_SITE_DATA_BLOCK },
{ "bugzilla.gnome.org", MIDORI_SITE_DATA_PRESERVE },
{ "bugs.launchpad.net", MIDORI_SITE_DATA_ACCEPT },
};
const gchar* rules = "-google.com,-facebook.com,!bugzilla.gnome.org,+bugs.launchpad.net";
MidoriWebSettings* settings = g_object_new (MIDORI_TYPE_WEB_SETTINGS,
"site-data-rules", rules, NULL);
guint i;
for (i = 0; i < G_N_ELEMENTS (items); i++)
{
MidoriSiteDataPolicy policy = midori_web_settings_get_site_data_policy (
settings, items[i].url);
if (policy != items[i].policy)
g_error ("Match '%s' yields %d but %d expected",
items[i].url, policy, items[i].policy);
}
g_object_unref (settings);
}
int int
main (int argc, main (int argc,
char** argv) char** argv)
@ -106,6 +138,7 @@ main (int argc,
g_test_add_func ("/browser/create", browser_create); g_test_add_func ("/browser/create", browser_create);
g_test_add_func ("/browser/tooltips", browser_tooltips); g_test_add_func ("/browser/tooltips", browser_tooltips);
g_test_add_func ("/browser/site_data", browser_site_data);
return g_test_run (); return g_test_run ();
} }

View file

@ -13,6 +13,7 @@
#include <midori/midori.h> #include <midori/midori.h>
#define SM "http://www.searchmash.com/search/" #define SM "http://www.searchmash.com/search/"
#define HTTP_PREFIX "midori-unit-test-expected-http-prefix"
static void static void
test_input (const gchar* input, test_input (const gchar* input,
@ -20,6 +21,7 @@ test_input (const gchar* input,
{ {
static KatzeArray* search_engines = NULL; static KatzeArray* search_engines = NULL;
gchar* uri; gchar* uri;
gchar* real_expected = NULL;
if (G_UNLIKELY (!search_engines)) if (G_UNLIKELY (!search_engines))
{ {
@ -41,28 +43,29 @@ test_input (const gchar* input,
uri = sokoke_magic_uri (input); uri = sokoke_magic_uri (input);
if (!uri) if (!uri)
{ {
gchar** parts; const gchar* keywords = NULL;
gchar* keywords = NULL;
const gchar* search_uri = NULL; const gchar* search_uri = NULL;
KatzeItem* item;
/* Do we have a keyword and a string? */ /* Do we have a keyword and a string? */
parts = g_strsplit (input, " ", 2); if ((item = katze_array_find_token (search_engines, input)))
if (parts[0])
{ {
KatzeItem* item; keywords = strchr (input, ' ');
if ((item = katze_array_find_token (search_engines, parts[0]))) if (keywords != NULL)
{ keywords++;
keywords = g_strdup (parts[1] ? parts[1] : ""); else
search_uri = katze_item_get_uri (item); keywords = "";
} search_uri = katze_item_get_uri (item);
} }
g_strfreev (parts);
uri = keywords ? midori_uri_for_search (search_uri, keywords) : NULL; uri = search_uri ? midori_uri_for_search (search_uri, keywords) : NULL;
g_free (keywords);
} }
katze_assert_str_equal (input, uri, expected);
if (!g_strcmp0 (expected, HTTP_PREFIX))
real_expected = g_strconcat ("http://", input, NULL);
katze_assert_str_equal (input, uri, real_expected ? real_expected : expected);
g_free (real_expected);
g_free (uri); g_free (uri);
} }
@ -97,6 +100,13 @@ magic_uri_uri (void)
/* test_input ("foo:f1o2o3@bar.baz", "http://f1o2o3:foo@bar.baz"); */ /* test_input ("foo:f1o2o3@bar.baz", "http://f1o2o3:foo@bar.baz"); */
/* test_input ("foo:foo@bar.baz", "http://foo:foo@bar.baz"); */ /* test_input ("foo:foo@bar.baz", "http://foo:foo@bar.baz"); */
test_input ("2001:0db8:85a3:0000:0000:8a2e:0370:7334", HTTP_PREFIX);
test_input ("fe80:0:0:0:202:b3ff:fe1e:8329", HTTP_PREFIX);
test_input ("fe80::202:b3ff:fe1e:8329", HTTP_PREFIX);
test_input ("fe80::76e5:bff:fe04:38e0/64", HTTP_PREFIX);
test_input ("content::browser", NULL);
test_input ("std::copy", NULL);
uri = "http://bugs.launchpad.net/midori"; uri = "http://bugs.launchpad.net/midori";
g_assert_cmpstr ("bugs.launchpad.net", ==, midori_uri_parse_hostname (uri, NULL)); g_assert_cmpstr ("bugs.launchpad.net", ==, midori_uri_parse_hostname (uri, NULL));
uri = "https://bugs.launchpad.net/midori"; uri = "https://bugs.launchpad.net/midori";

View file

@ -154,13 +154,13 @@ properties_object_get_set (GObject* object)
static void static void
properties_object_test (gconstpointer object) properties_object_test (gconstpointer object)
{ {
if (GTK_IS_OBJECT (object)) if (GTK_IS_WIDGET (object))
g_object_ref_sink ((GObject*)object); g_object_ref_sink ((GObject*)object);
properties_object_get_set ((GObject*)object); properties_object_get_set ((GObject*)object);
if (GTK_IS_OBJECT (object)) if (GTK_IS_WIDGET (object))
gtk_object_destroy (GTK_OBJECT (object)); gtk_widget_destroy (GTK_WIDGET (object));
g_object_unref ((GObject*)object); g_object_unref ((GObject*)object);
} }

View file

@ -112,7 +112,6 @@ midori_findbar_entry_clear_icon_released_cb (GtkIconEntry* entry,
{ {
if (icon_pos == GTK_ICON_ENTRY_SECONDARY) if (icon_pos == GTK_ICON_ENTRY_SECONDARY)
{ {
gtk_entry_set_text (GTK_ENTRY (entry), "");
midori_findbar_set_icon (findbar, GTK_ICON_ENTRY_PRIMARY, "edit-find"); midori_findbar_set_icon (findbar, GTK_ICON_ENTRY_PRIMARY, "edit-find");
} }
} }
@ -265,8 +264,7 @@ midori_findbar_init (MidoriFindbar* findbar)
gtk_toolbar_insert (GTK_TOOLBAR (findbar), toolitem, -1); gtk_toolbar_insert (GTK_TOOLBAR (findbar), toolitem, -1);
findbar->find_text = gtk_icon_entry_new (); findbar->find_text = gtk_icon_entry_new ();
midori_findbar_set_icon (findbar, GTK_ICON_ENTRY_PRIMARY, "edit-find"); midori_findbar_set_icon (findbar, GTK_ICON_ENTRY_PRIMARY, "edit-find");
gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (findbar->find_text), sokoke_entry_set_clear_button_visible (GTK_ENTRY (findbar->find_text), TRUE);
GTK_ICON_ENTRY_SECONDARY, TRUE);
g_signal_connect (findbar->find_text, "icon-release", g_signal_connect (findbar->find_text, "icon-release",
G_CALLBACK (midori_findbar_entry_clear_icon_released_cb), findbar); G_CALLBACK (midori_findbar_entry_clear_icon_released_cb), findbar);
g_signal_connect (findbar->find_text, "activate", g_signal_connect (findbar->find_text, "activate",

View file

@ -1,6 +1,7 @@
#! /bin/sh #! /bin/sh
# Copyright (C) 2010-2011 Peter de Ridder <peter@xfce.org> # Copyright (C) 2010-2011 Peter de Ridder <peter@xfce.org>
# Copyright (C) 2012 Paweł Forysiuk <tuxator@o2.pl>
# #
# This library is free software; you can redistribute it and/or # This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public # modify it under the terms of the GNU Lesser General Public
@ -23,17 +24,30 @@
# a bit of configuration # a bit of configuration
root_dir=$MINGW_PREFIX root_dir=$MINGW_PREFIX
if [ "$MINGW_PREFIX" == "" ]; then
echo "Warning! MINGW_PREFIX variable is empty!"
sleep 5s
fi
# create temporary working directory # create temporary working directory
temp_dir=`mktemp -d` temp_dir=`mktemp -d`
# check if we can use 7zip # check if we can use 7zip
have_7zip=`which 7za` have_7zip=`which 7za`
if [ "$1" != "" ]; then
if [ "$1" == "debug" ]; then
DEBUG_BUILD=1
else
version_tag=$1
fi
fi
# generate unique filename # generate unique filename
if [ "$have_7zip" != "" ]; then if [ "$have_7zip" != "" ]; then
ARCHIVE=midori$1-`date +%Y%m%d%H%M`.7z ARCHIVE=midori$version_tag-`date +%Y%m%d%H%M`.7z
else else
ARCHIVE=midori$1-`date +%Y%m%d%H%M`.zip ARCHIVE=midori$version_tag-`date +%Y%m%d%H%M`.zip
fi fi
# function: dll-recursive <list of exe and dll files ...> # function: dll-recursive <list of exe and dll files ...>
@ -55,7 +69,7 @@ dll_recursive ()
while [ "x`sha1sum - < $temp_file_new`" != "x`sha1sum - < $temp_file_old`" ] while [ "x`sha1sum - < $temp_file_new`" != "x`sha1sum - < $temp_file_old`" ]
do do
files=`cat $temp_file_new $temp_file_old | sort | uniq -u` files=`cat $temp_file_new $temp_file_old | sort | uniq -u`
cp $temp_file_new $temp_file_old cp -L $temp_file_new $temp_file_old
strings $files 2> /dev/null | grep \\.dll | cat - $temp_file_old | sort | uniq > $temp_file_new strings $files 2> /dev/null | grep \\.dll | cat - $temp_file_old | sort | uniq > $temp_file_new
done done
@ -64,16 +78,36 @@ dll_recursive ()
rm $temp_file_new $temp_file_old rm $temp_file_new $temp_file_old
} }
grab_files ()
{
local dir="$1"
pushd $root_dir > /dev/null
shift
while [ "$1" ]; do
find $dir "(" -name "$1" ")" -prune -exec mkdir -p $workdir/{} ";" -exec rmdir --ignore-fail-on-non-empty $workdir/{} ";" -exec cp -Lr {} $workdir/{} ";"
shift
done
popd > /dev/null
}
echo -n "Creating $ARCHIVE ." echo -n "Creating $ARCHIVE ."
# create destination folder # create destination folder
mkdir $temp_dir/midori$1 workdir=$temp_dir/midori$version_tag
mkdir $workdir
echo -n . echo -n .
# auto generate dll list, only of existing files # auto generate dll list, only of existing files
pushd $root_dir/bin > /dev/null pushd $root_dir/bin > /dev/null
dll_recursive midori*.exe gspawn-*-helper*.exe libhunspell*.dll > $temp_dir/midori.exe.lst dll_recursive midori*.exe gspawn-*-helper*.exe libhunspell*.dll > $temp_dir/midori.exe.lst
dll_recursive ../lib/gio/modules/*.dll >> $temp_dir/midori.exe.lst
dll_recursive iconv.dll >> $temp_dir/midori.exe.lst
if [ "$DEBUG_BUILD" != "" ]; then
dll_recursive gdb.exe GtkLauncher.exe >> $temp_dir/midori.exe.lst
fi
files=`ls | cat - $temp_dir/midori.exe.lst | sort | uniq -d` files=`ls | cat - $temp_dir/midori.exe.lst | sort | uniq -d`
rm $temp_dir/midori.exe.lst rm $temp_dir/midori.exe.lst
popd > /dev/null popd > /dev/null
@ -82,46 +116,80 @@ echo -n .
# copy auto generate dll list # copy auto generate dll list
pushd $root_dir/bin > /dev/null pushd $root_dir/bin > /dev/null
mkdir $temp_dir/midori$1/bin mkdir $workdir/bin
cp $files $temp_dir/midori$1/bin cp -L $files $workdir/bin
popd > /dev/null popd > /dev/null
echo -n . echo -n .
# copy etc # copy etc
pushd $root_dir > /dev/null grab_files etc midori
find etc "(" -name "*midori*" -o -name "gtkrc" ")" -prune -exec mkdir -p $temp_dir/midori$1/{} ";" -exec rmdir --ignore-fail-on-non-empty $temp_dir/midori$1/{} ";" -exec cp -r {} $temp_dir/midori$1/{} ";" grab_files etc gtkrc
popd > /dev/null
# If modules are not compiled we need a list of them
grab_files etc pango
# Freetype is preferred font backend
# copy configuration, otherwise webkit will crash
grab_files etc fonts
echo -n . echo -n .
# copy lib # copy lib
pushd $root_dir > /dev/null grab_files lib midori
find lib "(" -path "lib/midori/*" -o -path "lib/gtk-2.0/*" -o -path "lib/enchant/*" -o -path "lib/engines/*" ")" -a -name "*.dll" -prune -exec mkdir -p $temp_dir/midori$1/{} ";" -exec rmdir --ignore-fail-on-non-empty $temp_dir/midori$1/{} ";" -exec cp -r {} $temp_dir/midori$1/{} ";" grab_files lib gtk-2.0
popd > /dev/null grab_files lib/engines "*"
grab_files lib gdk-pixbuf-2.0
grab_files lib enchant
grab_files lib gio
# Fedora ships on-demand pango modules, check just in case
grab_files lib pango
echo -n . echo -n .
# copy share # copy share
pushd $root_dir > /dev/null grab_files share midori
find share "(" -name "*midori*" -o -name "icons" -o -name "MS-Windows" -o -name "mime" ")" -prune -exec mkdir -p $temp_dir/midori$1/{} ";" -exec rmdir --ignore-fail-on-non-empty $temp_dir/midori$1/{} ";" -exec cp -r {} $temp_dir/midori$1/{} ";" grab_files share icons
grab_files share MS-Windows
grab_files share mime
grab_files share midori.mo
grab_files share webkitgtk-1.0
if [ "$DEBUG_BUILD" == "" ];then
pushd $workdir > /dev/null
find -iname *.debug -exec rm {} \;
popd > /dev/null
fi
# copy locales for gtk # copy locales for gtk
# so we have translated stock items, file dialogs # so we have translated stock items, file dialogs
find share "(" -name "midori.mo" ")" > locale.list pushd $root_dir > /dev/null
mkdir -p $temp_dir/midori$1/share/locale/ find share "(" -name "midori.mo" ")" > $temp_dir/locale.list
for LOCALE in $(cat locale.list); do mkdir -p $workdir/share/locale/
for LOCALE in $(cat $temp_dir/locale.list); do
LOCALE=$(echo $LOCALE|awk -F/ '{print $3}') LOCALE=$(echo $LOCALE|awk -F/ '{print $3}')
cp /usr/share/locale/$LOCALE/LC_MESSAGES/gtk20.mo $temp_dir/midori$1/share/locale/$LOCALE/LC_MESSAGES/ cp /usr/share/locale/$LOCALE/LC_MESSAGES/gtk20.mo $workdir/share/locale/$LOCALE/LC_MESSAGES/
done done
rm locale.list rm $temp_dir/locale.list
# Use small icons and tango icons
gtk_etc_dir="$workdir/etc/gtk-2.0/"
mkdir -p $gtk_etc_dir
cat > $gtk_etc_dir/gtkrc << _EOF
gtk-theme-name = "MS-Windows"
gtk-fallback-icon-theme = "Tango"
gtk-toolbar-style = GTK_TOOLBAR_ICONS
_EOF
popd > /dev/null popd > /dev/null
echo -n . echo -n .
# copy doc files to root # copy doc files to root
cp $temp_dir/midori$1/share/doc/midori/{COPYING,AUTHORS} $temp_dir/midori$1 cp -L $workdir/share/doc/midori/{COPYING,AUTHORS} $workdir
echo -n . echo -n .
@ -130,9 +198,9 @@ ARCHIVE=`pwd`/$ARCHIVE
# store as zip/7z file # store as zip/7z file
pushd $temp_dir > /dev/null pushd $temp_dir > /dev/null
if [ "$have_7zip" != "" ]; then if [ "$have_7zip" != "" ]; then
7za a -m0=lzma -mx=9 $ARCHIVE midori$1 7za a -m0=lzma $ARCHIVE midori$version_tag
else else
zip -rq $ARCHIVE midori$1 zip -rq $ARCHIVE midori$version_tag
fi fi
popd > /dev/null popd > /dev/null

15
wscript
View file

@ -29,7 +29,7 @@ from Configure import find_program_impl
major = 0 major = 0
minor = 4 minor = 4
micro = 3 micro = 4
APPNAME = 'midori' APPNAME = 'midori'
VERSION = VERSION_FULL = str (major) + '.' + str (minor) + '.' + str (micro) VERSION = VERSION_FULL = str (major) + '.' + str (minor) + '.' + str (micro)
@ -62,6 +62,9 @@ def is_mingw (env):
return cc.find ('mingw') != -1# or cc.find ('wine') != -1 return cc.find ('mingw') != -1# or cc.find ('wine') != -1
return False return False
def is_win32 (env):
return is_mingw (env) or Options.platform == 'win32'
# Compile Win32 res files to (resource) object files # Compile Win32 res files to (resource) object files
def rc_file(self, node): def rc_file(self, node):
rctask = self.create_task ('winrc') rctask = self.create_task ('winrc')
@ -109,7 +112,7 @@ def configure (conf):
else: else:
icons = 'no ' icons = 'no '
if is_mingw (conf.env) or Options.platform == 'win32': if is_win32 (conf.env):
conf.find_program ('windres', var='WINRC') conf.find_program ('windres', var='WINRC')
conf.env['platform'] = 'win32' conf.env['platform'] = 'win32'
@ -271,8 +274,6 @@ def configure (conf):
if not conf.env['HAVE_UNIQUE']: if not conf.env['HAVE_UNIQUE']:
if Options.platform == 'win32': if Options.platform == 'win32':
conf.check (lib='ws2_32') conf.check (lib='ws2_32')
check_pkg ('openssl', mandatory=False)
conf.define ('USE_SSL', [0,1][conf.env['HAVE_OPENSSL'] == 1])
conf.define ('HAVE_NETDB_H', [0,1][conf.check (header_name='netdb.h')]) conf.define ('HAVE_NETDB_H', [0,1][conf.check (header_name='netdb.h')])
conf.check (header_name='sys/wait.h') conf.check (header_name='sys/wait.h')
conf.check (header_name='sys/select.h') conf.check (header_name='sys/select.h')
@ -391,7 +392,7 @@ def set_options (opt):
add_enable_option ('apidocs', 'API documentation', group, disable=True) add_enable_option ('apidocs', 'API documentation', group, disable=True)
group = opt.add_option_group ('Optional features', '') group = opt.add_option_group ('Optional features', '')
add_enable_option ('unique', 'single instance support', group) add_enable_option ('unique', 'single instance support', group, disable=is_win32 (os.environ))
add_enable_option ('libnotify', 'notification support', group) add_enable_option ('libnotify', 'notification support', group)
add_enable_option ('addons', 'building of extensions', group) add_enable_option ('addons', 'building of extensions', group)
add_enable_option ('tests', 'building of tests', group, disable=True) add_enable_option ('tests', 'building of tests', group, disable=True)
@ -452,7 +453,7 @@ def build (bld):
bld.install_files ('${DOCDIR}/api/', blddir + '/docs/api/*') bld.install_files ('${DOCDIR}/api/', blddir + '/docs/api/*')
for desktop in [APPNAME + '.desktop', APPNAME + '-private.desktop']: for desktop in [APPNAME + '.desktop', APPNAME + '-private.desktop']:
if is_mingw (bld.env) or Options.platform == 'win32': if is_win32 (bld.env):
break break
if bld.env['HAVE_HILDON']: if bld.env['HAVE_HILDON']:
appdir = '${MDATADIR}/applications/hildon' appdir = '${MDATADIR}/applications/hildon'
@ -497,7 +498,7 @@ def build (bld):
else: else:
Utils.pprint ('BLUE', "logo-shade could not be rasterized.") Utils.pprint ('BLUE', "logo-shade could not be rasterized.")
for res_file in ['error.html', 'close.png']: for res_file in ['about.css', 'error.html', 'close.png']:
bld.install_files ('${MDATADIR}/' + APPNAME + '/res', 'data/' + res_file) bld.install_files ('${MDATADIR}/' + APPNAME + '/res', 'data/' + res_file)
bld.install_as ( \ bld.install_as ( \
'${MDATADIR}/' + APPNAME + '/res/speeddial-head-%s.html' % VERSION, \ '${MDATADIR}/' + APPNAME + '/res/speeddial-head-%s.html' % VERSION, \