Merge branch 'upstream-unstable'
This commit is contained in:
commit
bf2d83aba2
78 changed files with 25888 additions and 20487 deletions
26
ChangeLog
26
ChangeLog
|
@ -1,5 +1,31 @@
|
|||
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:
|
||||
+ Implement about:widgets to test rendering
|
||||
+ Fix resizing of inspector by applying a minimum size
|
||||
|
|
2
INSTALL
2
INSTALL
|
@ -67,6 +67,8 @@ If you want to "dry run" without WebKitGTK+ rendering, try this:
|
|||
|
||||
'MIDORI_UNARMED=1 _build_/default/midori/midori'
|
||||
|
||||
To disable Netscape plugins, use MOZ_PLUGIN_PATH=/.
|
||||
|
||||
To debug extensions you can specify the path:
|
||||
|
||||
'export MIDORI_EXTENSION_PATH=_build_/default/extensions'
|
||||
|
|
57
data/about.css
Normal file
57
data/about.css
Normal 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;
|
||||
}
|
|
@ -2,67 +2,11 @@
|
|||
Error page template for Midori.
|
||||
This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>{title}</title>
|
||||
<link rel="shortcut icon" href="{icon}" />
|
||||
<style type="text/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>
|
||||
<link rel="stylesheet" type="text/css" href="res://about.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="container">
|
||||
|
|
|
@ -3,7 +3,7 @@ Version=1.0
|
|||
Type=Application
|
||||
_Name=Midori
|
||||
_GenericName=Web Browser
|
||||
_Comment=Lightweight web browser
|
||||
_Comment=Browse the Web
|
||||
_X-GNOME-Keywords=Internet;WWW;Explorer
|
||||
_X-AppInstall-Keywords=Internet;WWW;Explorer
|
||||
Categories=GTK;Network;WebBrowser;
|
||||
|
|
|
@ -55,10 +55,7 @@
|
|||
width: 85%;
|
||||
height: 75%;
|
||||
margin: auto;
|
||||
-webkit-box-shadow: 0 4px 18px rgba(0,0,0,.3), 0 0 2px #fff inset;
|
||||
background-image: -webkit-gradient(
|
||||
linear, center top, center bottom,
|
||||
from(#f6f6f6), to(#e3e3e3));
|
||||
-webkit-box-shadow: 0 2px 5px rgba(0,0,0,.3), 0 0 0px #fff inset;
|
||||
border: 1px solid #bcbcbc;
|
||||
border-bottom-color: #a0a0a0;
|
||||
position: relative;
|
||||
|
@ -75,9 +72,15 @@
|
|||
div.shortcut .preview.new .add {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 50%;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
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 {
|
||||
|
@ -126,6 +129,11 @@
|
|||
-webkit-border-bottom-left-radius: 10px;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.selected {
|
||||
outline: 1px dotted black;
|
||||
background-color: #eef;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
@ -196,6 +204,72 @@
|
|||
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>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2009-2010 Christian Dywan <christian@twotoasts.de>
|
||||
Copyright (C) 2009 Alexander Butenko <a.butenka@gmail.com>
|
||||
Copyright (C) 2009-2012 Christian Dywan <christian@twotoasts.de>
|
||||
Copyright (C) 2009-2012 Alexander Butenko <a.butenka@gmail.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -9,7 +9,6 @@
|
|||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#include <midori/midori.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
|
@ -35,13 +34,12 @@
|
|||
#define adblock_debug(dmsg, darg1, darg2) /* nothing */
|
||||
#endif
|
||||
|
||||
static GHashTable* pattern;
|
||||
static GHashTable* keys;
|
||||
static GHashTable* optslist;
|
||||
static GHashTable* urlcache;
|
||||
static GString* blockcss;
|
||||
static GString* blockcssprivate;
|
||||
static gchar* blockscript = NULL;
|
||||
static GHashTable* pattern = NULL;
|
||||
static GHashTable* keys = NULL;
|
||||
static GHashTable* optslist = NULL;
|
||||
static GHashTable* urlcache = NULL;
|
||||
static GHashTable* blockcssprivate = NULL;
|
||||
static GString* blockcss = NULL;
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
static guint debug;
|
||||
#endif
|
||||
|
@ -54,43 +52,83 @@ adblock_reload_rules (MidoriExtension* extension,
|
|||
gboolean custom_only);
|
||||
|
||||
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',"
|
||||
"function () {"
|
||||
" if (document.getElementById('madblock'))"
|
||||
" return;"
|
||||
// Get just domain name from URL
|
||||
" var URL = location.href.match(/:\\/\\/(.[^/]+)/)[1];"
|
||||
" var sites = new Array(); %s;"
|
||||
" var public = '.madblockplaceholder ';"
|
||||
// Split domain into subdomain parts
|
||||
" var subdomains = URL.split ('.');"
|
||||
" var hostname = subdomains [subdomains.length - 1];"
|
||||
" var i = subdomains.length - 2;"
|
||||
// Check if any of subdomains do have blocking rules
|
||||
" while (i >= 0) {"
|
||||
" hostname = subdomains [i] + '.' + hostname;"
|
||||
" if (sites [hostname])"
|
||||
" public += ', ' + sites [hostname];"
|
||||
" i--;"
|
||||
" }"
|
||||
" public += ' {display: none !important}';"
|
||||
" public = '");
|
||||
|
||||
cnt = g_strv_length (subdomains) - 1;
|
||||
subdomain = g_string_new (subdomains [cnt]);
|
||||
g_string_prepend_c (subdomain, '.');
|
||||
cnt--;
|
||||
while (cnt >= 0)
|
||||
{
|
||||
g_string_prepend (subdomain, subdomains[cnt]);
|
||||
if ((style = g_hash_table_lookup (blockcssprivate, subdomain->str)))
|
||||
{
|
||||
g_string_append (code, style);
|
||||
g_string_append_c (code, ',');
|
||||
blockscnt++;
|
||||
}
|
||||
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');"
|
||||
" mystyle.setAttribute('type', 'text/css');"
|
||||
" mystyle.setAttribute('id', 'madblock');"
|
||||
" mystyle.appendChild(document.createTextNode(public));"
|
||||
" var head = document.getElementsByTagName('head')[0];"
|
||||
" if (head) head.appendChild(mystyle);"
|
||||
"}, true);",
|
||||
private);
|
||||
"}, true);");
|
||||
return g_string_free (code, FALSE);
|
||||
}
|
||||
|
||||
static GString*
|
||||
adblock_fixup_regexp (const gchar* prefix,
|
||||
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
|
||||
adblock_init_db ()
|
||||
{
|
||||
|
@ -106,12 +144,13 @@ adblock_init_db ()
|
|||
urlcache = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
(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)
|
||||
g_string_free (blockcss, TRUE);
|
||||
if (blockcssprivate && blockcssprivate->len > 0)
|
||||
g_string_free (blockcssprivate, TRUE);
|
||||
blockcss = g_string_new ("z-non-exist");
|
||||
blockcssprivate = g_string_new ("");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -119,23 +158,9 @@ adblock_download_notify_status_cb (WebKitDownload* download,
|
|||
GParamSpec* pspec,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
gchar* path;
|
||||
MidoriApp* app;
|
||||
MidoriWebSettings* settings;
|
||||
|
||||
if (webkit_download_get_status (download) != WEBKIT_DOWNLOAD_STATUS_FINISHED)
|
||||
return;
|
||||
|
||||
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);
|
||||
adblock_reload_rules (extension, FALSE);
|
||||
}
|
||||
|
||||
static gchar*
|
||||
|
@ -174,6 +199,8 @@ adblock_reload_rules (MidoriExtension* extension,
|
|||
MidoriApp* app = midori_extension_get_app (extension);
|
||||
MidoriWebSettings* settings = katze_object_get_object (app, "settings");
|
||||
|
||||
if (pattern)
|
||||
adblock_destroy_db ();
|
||||
adblock_init_db ();
|
||||
|
||||
custom_list = g_build_filename (midori_extension_get_config_dir (extension),
|
||||
|
@ -215,7 +242,6 @@ adblock_reload_rules (MidoriExtension* extension,
|
|||
g_strfreev (filters);
|
||||
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);
|
||||
g_object_unref (settings);
|
||||
}
|
||||
|
@ -622,7 +648,9 @@ adblock_check_rule (GRegex* regex,
|
|||
return FALSE;
|
||||
}
|
||||
/* TODO: Domain opt check */
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
adblock_debug ("blocked by pattern regexp=%s -- %s", g_regex_get_pattern (regex), req_uri);
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -769,11 +797,6 @@ adblock_resource_request_starting_cb (WebKitWebView* web_view,
|
|||
if (midori_uri_is_blank (page_uri))
|
||||
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);
|
||||
if (!midori_uri_is_http (req_uri)
|
||||
|| g_str_has_suffix (req_uri, "favicon.ico"))
|
||||
|
@ -932,13 +955,19 @@ adblock_window_object_cleared_cb (WebKitWebView* web_view,
|
|||
JSObjectRef js_window)
|
||||
{
|
||||
const char *page_uri;
|
||||
gchar* script;
|
||||
|
||||
page_uri = webkit_web_frame_get_uri (web_frame);
|
||||
/* Don't add adblock css into speeddial and about: pages */
|
||||
if (!midori_uri_is_http (page_uri))
|
||||
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
|
||||
|
@ -1089,7 +1118,9 @@ adblock_compile_regexp (GString* gpatt,
|
|||
if (!g_regex_match_simple ("[\\*]", sig, G_REGEX_UNGREEDY, G_REGEX_MATCH_NOTEMPTY) &&
|
||||
!g_hash_table_lookup (keys, sig))
|
||||
{
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
adblock_debug ("sig: %s %s", sig, patt);
|
||||
#endif
|
||||
g_hash_table_insert (keys, sig, regex);
|
||||
g_hash_table_insert (optslist, sig, g_strdup (opts));
|
||||
signature_count++;
|
||||
|
@ -1099,7 +1130,9 @@ adblock_compile_regexp (GString* gpatt,
|
|||
if (g_regex_match_simple ("^\\*", sig, G_REGEX_UNGREEDY, G_REGEX_MATCH_NOTEMPTY) &&
|
||||
!g_hash_table_lookup (pattern, patt))
|
||||
{
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
adblock_debug ("patt2: %s %s", sig, patt);
|
||||
#endif
|
||||
g_hash_table_insert (pattern, patt, regex);
|
||||
g_hash_table_insert (optslist, patt, g_strdup (opts));
|
||||
}
|
||||
|
@ -1115,7 +1148,9 @@ adblock_compile_regexp (GString* gpatt,
|
|||
}
|
||||
else
|
||||
{
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
adblock_debug ("patt: %s%s", patt, "");
|
||||
#endif
|
||||
/* Pattern is a regexp chars */
|
||||
g_hash_table_insert (pattern, patt, regex);
|
||||
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);
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
adblock_debug ("got: %s opts %s", format_patt->str, opts);
|
||||
#endif
|
||||
should_free = adblock_compile_regexp (format_patt, opts);
|
||||
|
||||
if (data[1] && data[2])
|
||||
|
@ -1200,6 +1237,22 @@ adblock_frame_add (gchar* 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
|
||||
adblock_frame_add_private (const gchar* line,
|
||||
const gchar* sep)
|
||||
|
@ -1234,15 +1287,13 @@ adblock_frame_add_private (const gchar* line,
|
|||
/* strip ~ from domain */
|
||||
if (domain[0] == '~')
|
||||
domain++;
|
||||
g_string_append_printf (blockcssprivate, ";sites['%s']+=',%s'",
|
||||
g_strstrip (domain), data[1]);
|
||||
adblock_update_css_hash (g_strstrip (domain), data[1]);
|
||||
}
|
||||
g_strfreev (domains);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_string_append_printf (blockcssprivate, ";sites['%s']+=',%s'",
|
||||
data[0], data[1]);
|
||||
adblock_update_css_hash (data[0], data[1]);
|
||||
}
|
||||
g_strfreev (data);
|
||||
}
|
||||
|
@ -1250,12 +1301,10 @@ adblock_frame_add_private (const gchar* line,
|
|||
static gchar*
|
||||
adblock_parse_line (gchar* line)
|
||||
{
|
||||
if (!line)
|
||||
return NULL;
|
||||
g_strchomp (line);
|
||||
/* Ignore comments and new lines */
|
||||
if (line[0] == '!')
|
||||
/* Skip invalid, empty and comment lines */
|
||||
if (!(line && line[0] != ' ' && line[0] != '!' && line[0]))
|
||||
return NULL;
|
||||
|
||||
/* FIXME: No support for whitelisting */
|
||||
if (line[0] == '@' && line[1] == '@')
|
||||
return NULL;
|
||||
|
@ -1263,9 +1312,7 @@ adblock_parse_line (gchar* line)
|
|||
if (line[0] == '[')
|
||||
return NULL;
|
||||
|
||||
/* Skip garbage */
|
||||
if (line[0] == ' ' || !line[0])
|
||||
return NULL;
|
||||
g_strchomp (line);
|
||||
|
||||
/* Got CSS block hider */
|
||||
if (line[0] == '#' && line[1] == '#' )
|
||||
|
@ -1283,13 +1330,13 @@ adblock_parse_line (gchar* line)
|
|||
adblock_frame_add_private (line, "##");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Got per domain CSS hider rule. Workaround */
|
||||
if (strchr (line, '#'))
|
||||
{
|
||||
adblock_frame_add_private (line, "#");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Got URL blocker rule */
|
||||
if (line[0] == '|' && line[1] == '|' )
|
||||
{
|
||||
|
@ -1358,16 +1405,8 @@ adblock_deactivate_cb (MidoriExtension* extension,
|
|||
browser, adblock_add_tab_cb, extension);
|
||||
midori_browser_foreach (browser, (GtkCallback)adblock_deactivate_tabs, browser);
|
||||
|
||||
if (blockcss)
|
||||
g_string_free (blockcss, TRUE);
|
||||
if (blockcssprivate)
|
||||
g_string_free (blockcssprivate, TRUE);
|
||||
|
||||
adblock_destroy_db ();
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1498,7 +1537,7 @@ extension_init (void)
|
|||
MidoriExtension* extension = g_object_new (MIDORI_TYPE_EXTENSION,
|
||||
"name", _("Advertisement blocker"),
|
||||
"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>",
|
||||
NULL);
|
||||
midori_extension_install_string_list (extension, "filters", NULL, G_MAXSIZE);
|
||||
|
|
|
@ -48,11 +48,10 @@ colorful_tabs_view_notify_uri_cb (MidoriView* view,
|
|||
|
||||
if (!midori_uri_is_blank (midori_view_get_display_uri (view))
|
||||
&& (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);
|
||||
|
||||
if (midori_view_get_icon_uri (view) != NULL)
|
||||
if (icon != NULL)
|
||||
{
|
||||
GdkPixbuf* newpix;
|
||||
guchar* pixels;
|
||||
|
|
|
@ -840,7 +840,8 @@ feed_panel_init (FeedPanel* panel)
|
|||
|
||||
webview = webkit_web_view_new ();
|
||||
#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
|
||||
font_desc = treeview->style->font_desc;
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
}
|
74
extensions/formhistory/formhistory-frontend.h
Normal file
74
extensions/formhistory/formhistory-frontend.h
Normal 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
|
516
extensions/formhistory/formhistory-gdom-frontend.c
Normal file
516
extensions/formhistory/formhistory-gdom-frontend.c
Normal 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
|
143
extensions/formhistory/formhistory-js-frontend.c
Normal file
143
extensions/formhistory/formhistory-js-frontend.c
Normal 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
|
679
extensions/formhistory/formhistory.c
Normal file
679
extensions/formhistory/formhistory.c
Normal 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;
|
||||
}
|
|
@ -180,8 +180,6 @@ shortcuts_get_preferences_dialog (MidoriExtension* extension)
|
|||
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
|
||||
#endif
|
||||
NULL);
|
||||
g_signal_connect (dialog, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &dialog);
|
||||
gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_PROPERTIES);
|
||||
sokoke_widget_get_text_size (dialog, "M", &width, &height);
|
||||
gtk_window_set_default_size (GTK_WINDOW (dialog), width * 52, height * 24);
|
||||
|
|
|
@ -66,11 +66,14 @@ statusbar_features_browser_notify_tab_cb (MidoriBrowser* browser,
|
|||
GtkWidget* combobox)
|
||||
{
|
||||
MidoriView* view = MIDORI_VIEW (midori_browser_get_current_tab (browser));
|
||||
gchar* zoom_level_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))),
|
||||
zoom_level_text);
|
||||
g_free (zoom_level_text);
|
||||
gchar* text;
|
||||
|
||||
if (view == NULL)
|
||||
return;
|
||||
|
||||
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
|
||||
|
@ -142,8 +145,10 @@ statusbar_features_app_add_browser_cb (MidoriApp* app,
|
|||
g_signal_connect (toolbar, "notify::toolbar-style",
|
||||
G_CALLBACK (statusbar_features_toolbar_notify_toolbar_style_cb), button);
|
||||
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
|
||||
button = katze_property_proxy (settings, "enable-plugins", "toggle");
|
||||
g_object_set_data (G_OBJECT (button), "feature-label", _("Netscape plugins"));
|
||||
if (midori_web_settings_has_plugin_support ())
|
||||
{
|
||||
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);
|
||||
gtk_button_set_image (GTK_BUTTON (button), image);
|
||||
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_CALLBACK (statusbar_features_toolbar_notify_toolbar_style_cb), button);
|
||||
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
|
||||
}
|
||||
button = katze_property_proxy (settings, "identify-as", "custom-user-agent");
|
||||
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
|
||||
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_signal_connect (browser, "notify::tab",
|
||||
G_CALLBACK (statusbar_features_browser_notify_tab_cb), button);
|
||||
statusbar_features_browser_notify_tab_cb (browser, NULL, button);
|
||||
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_signal_connect (extension, "deactivate",
|
||||
|
|
|
@ -394,11 +394,7 @@ static TBEditorWidget *tb_editor_create_dialog(MidoriBrowser *parent)
|
|||
GTK_WINDOW(parent),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
|
||||
#if !GTK_CHECK_VERSION(3,0,0)
|
||||
vbox = (GTK_DIALOG(dialog))->vbox;
|
||||
#else
|
||||
vbox = GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog)));
|
||||
#endif
|
||||
vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
|
||||
gtk_box_set_spacing(GTK_BOX(vbox), 6);
|
||||
gtk_widget_set_name(dialog, "GeanyDialog");
|
||||
gtk_window_set_default_size(GTK_WINDOW(dialog), -1, 400);
|
||||
|
|
|
@ -27,9 +27,9 @@ sokoke_on_entry_focus_in_event (GtkEntry* entry,
|
|||
g_object_get_data (G_OBJECT (entry), "sokoke_has_default"));
|
||||
if (has_default)
|
||||
{
|
||||
gtk_entry_set_text (entry, "");
|
||||
g_object_set_data (G_OBJECT (entry), "sokoke_has_default",
|
||||
GINT_TO_POINTER (0));
|
||||
gtk_entry_set_text (entry, "");
|
||||
sokoke_widget_set_pango_font_style (GTK_WIDGET (entry),
|
||||
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 (
|
||||
G_OBJECT (entry), "sokoke_default_text");
|
||||
gtk_entry_set_text (entry, default_text);
|
||||
g_object_set_data (G_OBJECT (entry),
|
||||
"sokoke_has_default", GINT_TO_POINTER (1));
|
||||
gtk_entry_set_text (entry, default_text);
|
||||
sokoke_widget_set_pango_font_style (GTK_WIDGET (entry),
|
||||
PANGO_STYLE_ITALIC);
|
||||
}
|
||||
|
@ -73,6 +73,9 @@ gtk_entry_set_placeholder_text (GtkEntry* entry,
|
|||
/* Note: The default text initially overwrites any previous text */
|
||||
gchar* old_value = g_object_get_data (G_OBJECT (entry),
|
||||
"sokoke_default_text");
|
||||
g_object_set_data (G_OBJECT (entry), "sokoke_default_text",
|
||||
(gpointer)default_text);
|
||||
|
||||
if (!old_value)
|
||||
{
|
||||
g_object_set_data (G_OBJECT (entry), "sokoke_has_default",
|
||||
|
@ -98,8 +101,12 @@ gtk_entry_set_placeholder_text (GtkEntry* entry,
|
|||
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
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
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 GtkVBox GtkBox
|
||||
#define GtkVBoxClass GtkBoxClass
|
||||
|
@ -89,8 +89,10 @@ G_BEGIN_DECLS
|
|||
|
||||
#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_get_placeholder_text hildon_gtk_entry_get_placeholder_text
|
||||
#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
|
||||
|
||||
#if !GTK_CHECK_VERSION(2, 12, 0)
|
||||
|
|
|
@ -74,6 +74,13 @@ GList* kalistglobal;
|
|||
static void
|
||||
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
|
||||
_katze_array_add_item (KatzeArray* array,
|
||||
gpointer item)
|
||||
|
@ -84,6 +91,7 @@ _katze_array_add_item (KatzeArray* array,
|
|||
katze_item_set_parent (item, array);
|
||||
|
||||
array->items = g_list_append (array->items, item);
|
||||
_katze_array_update (array);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -95,6 +103,7 @@ _katze_array_remove_item (KatzeArray* array,
|
|||
if (KATZE_IS_ITEM (item))
|
||||
katze_item_set_parent (item, NULL);
|
||||
g_object_unref (item);
|
||||
_katze_array_update (array);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -104,6 +113,7 @@ _katze_array_move_item (KatzeArray* array,
|
|||
{
|
||||
array->items = g_list_remove (array->items, item);
|
||||
array->items = g_list_insert (array->items, item, position);
|
||||
_katze_array_update (array);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -112,9 +122,10 @@ _katze_array_clear (KatzeArray* array)
|
|||
GObject* item;
|
||||
|
||||
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);
|
||||
array->items = NULL;
|
||||
_katze_array_update (array);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -192,7 +203,7 @@ katze_array_class_init (KatzeArrayClass* class)
|
|||
"update",
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||||
0,
|
||||
G_STRUCT_OFFSET (KatzeArrayClass, update),
|
||||
0,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
|
@ -205,6 +216,7 @@ katze_array_class_init (KatzeArrayClass* class)
|
|||
class->remove_item = _katze_array_remove_item;
|
||||
class->move_item = _katze_array_move_item;
|
||||
class->clear = _katze_array_clear;
|
||||
class->update = _katze_array_update;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -217,14 +229,11 @@ katze_array_init (KatzeArray* array)
|
|||
static void
|
||||
katze_array_finalize (GObject* object)
|
||||
{
|
||||
KatzeArray* array;
|
||||
guint i;
|
||||
gpointer item;
|
||||
KatzeArray* array = KATZE_ARRAY (object);
|
||||
GList* items;
|
||||
|
||||
array = KATZE_ARRAY (object);
|
||||
i = 0;
|
||||
while ((item = g_list_nth_data (array->items, i++)))
|
||||
g_object_unref (item);
|
||||
for (items = array->items; items; items = g_list_next (items))
|
||||
g_object_unref (items->data);
|
||||
g_list_free (array->items);
|
||||
|
||||
G_OBJECT_CLASS (katze_array_parent_class)->finalize (object);
|
||||
|
@ -364,37 +373,39 @@ katze_array_get_item_index (KatzeArray* array,
|
|||
/**
|
||||
* katze_array_find_token:
|
||||
* @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.
|
||||
*
|
||||
* This function will silently fail if the type of the list
|
||||
* is not based on #GObject and only #KatzeItem children
|
||||
* are checked for their token, any other objects are skipped.
|
||||
* This function will fail if the type of the list
|
||||
* is not based on #KatzeItem children.
|
||||
*
|
||||
* 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
|
||||
**/
|
||||
gpointer
|
||||
katze_array_find_token (KatzeArray* array,
|
||||
const gchar* token)
|
||||
{
|
||||
guint i;
|
||||
gpointer item;
|
||||
goffset token_length;
|
||||
GList* items;
|
||||
|
||||
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;
|
||||
while ((item = g_list_nth_data (array->items, i++)))
|
||||
token_length = strchr (token, ' ') - token;
|
||||
if (token_length < 1)
|
||||
token_length = strlen (token);
|
||||
|
||||
for (items = array->items; items; items = g_list_next (items))
|
||||
{
|
||||
const gchar* found_token;
|
||||
|
||||
if (!KATZE_IS_ITEM (item))
|
||||
continue;
|
||||
found_token = ((KatzeItem*)item)->token;
|
||||
if (!g_strcmp0 (found_token, token))
|
||||
return item;
|
||||
const gchar* found_token = ((KatzeItem*)items->data)->token;
|
||||
if (found_token != NULL && !strncmp (token, found_token, token_length))
|
||||
return items->data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -406,9 +417,8 @@ katze_array_find_token (KatzeArray* array,
|
|||
*
|
||||
* Looks up an item in the array which has the specified URI.
|
||||
*
|
||||
* This function will silently fail if the type of the list
|
||||
* is not based on #GObject and only #KatzeItem children
|
||||
* are checked for their token, any other objects are skipped.
|
||||
* This function will fail if the type of the list
|
||||
* is not based on #KatzeItem children.
|
||||
*
|
||||
* Return value: an item, or %NULL
|
||||
*
|
||||
|
@ -418,19 +428,17 @@ gpointer
|
|||
katze_array_find_uri (KatzeArray* array,
|
||||
const gchar* uri)
|
||||
{
|
||||
guint i;
|
||||
gpointer item;
|
||||
GList* items;
|
||||
|
||||
i = 0;
|
||||
while ((item = g_list_nth_data (array->items, i++)))
|
||||
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 (uri != NULL, NULL);
|
||||
|
||||
for (items = array->items; items; items = g_list_next (items))
|
||||
{
|
||||
const gchar* found_uri;
|
||||
|
||||
if (!KATZE_IS_ITEM (item))
|
||||
continue;
|
||||
found_uri = ((KatzeItem*)item)->uri;
|
||||
if (!g_strcmp0 (found_uri, uri))
|
||||
return item;
|
||||
const gchar* found_uri = ((KatzeItem*)items->data)->uri;
|
||||
if (found_uri != NULL && !strcmp (found_uri, uri))
|
||||
return items->data;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -355,11 +355,16 @@ katze_array_action_generate_menu (KatzeArrayAction* array_action,
|
|||
gint summand;
|
||||
KatzeItem* item;
|
||||
GtkWidget* menuitem;
|
||||
const gchar* icon_name;
|
||||
GdkPixbuf* icon;
|
||||
GtkWidget* image;
|
||||
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))
|
||||
return;
|
||||
|
||||
|
@ -385,18 +390,7 @@ katze_array_action_generate_menu (KatzeArrayAction* array_action,
|
|||
}
|
||||
menuitem = katze_image_menu_item_new_ellipsized (
|
||||
katze_item_get_name (item));
|
||||
if ((icon_name = katze_item_get_icon (item)) && *icon_name)
|
||||
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);
|
||||
}
|
||||
image = katze_item_get_image (item);
|
||||
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
|
||||
gtk_image_menu_item_set_always_show_image (
|
||||
GTK_IMAGE_MENU_ITEM (menuitem), TRUE);
|
||||
|
@ -406,8 +400,13 @@ katze_array_action_generate_menu (KatzeArrayAction* array_action,
|
|||
{
|
||||
submenu = gtk_menu_new ();
|
||||
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_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
|
||||
{
|
||||
|
@ -421,21 +420,39 @@ katze_array_action_generate_menu (KatzeArrayAction* array_action,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
katze_array_action_menu_item_select_cb (GtkWidget* proxy,
|
||||
KatzeArrayAction* array_action)
|
||||
static gboolean
|
||||
katze_array_action_menu_item_need_update (KatzeArrayAction* array_action,
|
||||
GtkWidget* proxy)
|
||||
{
|
||||
GtkWidget* menu;
|
||||
KatzeArray* array;
|
||||
gint last_array_update, last_proxy_update;
|
||||
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));
|
||||
gtk_container_foreach (GTK_CONTAINER (menu),
|
||||
(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);
|
||||
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
|
||||
|
@ -458,20 +475,21 @@ katze_array_action_proxy_clicked_cb (GtkWidget* proxy,
|
|||
KatzeArray* array;
|
||||
gboolean handled = FALSE;
|
||||
|
||||
array = (KatzeArray*)g_object_get_data (G_OBJECT (proxy), "KatzeItem");
|
||||
if (GTK_IS_MENU_ITEM (proxy))
|
||||
{
|
||||
g_object_set_data (G_OBJECT (proxy), "KatzeItem", array_action->array);
|
||||
katze_array_action_menu_item_select_cb (proxy, array_action);
|
||||
g_signal_emit (array_action, signals[POPULATE_FOLDER], 0,
|
||||
gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)),
|
||||
array_action->array, &handled);
|
||||
if (!handled)
|
||||
g_signal_emit (array_action, signals[POPULATE_POPUP], 0,
|
||||
gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)));
|
||||
if (katze_array_action_menu_item_need_update (array_action, proxy))
|
||||
{
|
||||
g_signal_emit (array_action, signals[POPULATE_FOLDER], 0,
|
||||
gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)),
|
||||
array, &handled);
|
||||
if (!handled)
|
||||
g_signal_emit (array_action, signals[POPULATE_POPUP], 0,
|
||||
gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
array = (KatzeArray*)g_object_get_data (G_OBJECT (proxy), "KatzeArray");
|
||||
if (KATZE_IS_ITEM (array) && katze_item_get_uri ((KatzeItem*)array))
|
||||
{
|
||||
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* title;
|
||||
const gchar* desc;
|
||||
GdkPixbuf* icon;
|
||||
GtkWidget* image;
|
||||
|
||||
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"))
|
||||
{
|
||||
icon = katze_load_cached_icon (katze_item_get_uri (item), GTK_WIDGET (toolitem));
|
||||
image = gtk_image_new_from_pixbuf (icon);
|
||||
g_object_unref (icon);
|
||||
image = katze_item_get_image (item);
|
||||
gtk_widget_show (image);
|
||||
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image);
|
||||
}
|
||||
else if (!strcmp (property, "icon"))
|
||||
{
|
||||
image = gtk_image_new_from_icon_name (katze_item_get_icon (item),
|
||||
GTK_ICON_SIZE_MENU);
|
||||
image = katze_item_get_image (item);
|
||||
gtk_widget_show (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;
|
||||
GtkWidget* menuitem;
|
||||
const gchar* icon_name;
|
||||
GtkWidget* image;
|
||||
GdkPixbuf* icon;
|
||||
|
||||
array_action = g_object_get_data (G_OBJECT (proxy), "KatzeArrayAction");
|
||||
menuitem = katze_image_menu_item_new_ellipsized (
|
||||
katze_item_get_name (item));
|
||||
if ((icon_name = katze_item_get_icon (item)) && *icon_name)
|
||||
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);
|
||||
}
|
||||
image = katze_item_get_image (item);
|
||||
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
|
||||
gtk_image_menu_item_set_always_show_image (
|
||||
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* desc;
|
||||
GtkToolItem* toolitem;
|
||||
GdkPixbuf* icon;
|
||||
GtkWidget* image;
|
||||
GtkWidget* label;
|
||||
|
||||
|
@ -686,20 +686,12 @@ katze_array_action_create_tool_item_for (KatzeArrayAction* array_action,
|
|||
return gtk_separator_tool_item_new ();
|
||||
|
||||
if (KATZE_ITEM_IS_FOLDER (item))
|
||||
{
|
||||
toolitem = gtk_toggle_tool_button_new ();
|
||||
icon = gtk_widget_render_icon (GTK_WIDGET (toolitem),
|
||||
GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
toolitem = gtk_tool_button_new (NULL, "");
|
||||
icon = katze_load_cached_icon (uri, GTK_WIDGET (toolitem));
|
||||
}
|
||||
g_signal_connect (toolitem, "create-menu-proxy",
|
||||
G_CALLBACK (katze_array_action_proxy_create_menu_proxy_cb), item);
|
||||
image = gtk_image_new_from_pixbuf (icon);
|
||||
g_object_unref (icon);
|
||||
image = katze_item_get_image (item);
|
||||
gtk_widget_show (image);
|
||||
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image);
|
||||
label = gtk_label_new (NULL);
|
||||
|
@ -739,6 +731,9 @@ static void
|
|||
katze_array_action_connect_proxy (GtkAction* action,
|
||||
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 (
|
||||
action, proxy);
|
||||
|
||||
|
@ -750,9 +745,10 @@ katze_array_action_connect_proxy (GtkAction* action,
|
|||
else if (GTK_IS_MENU_ITEM (proxy))
|
||||
{
|
||||
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_CALLBACK (katze_array_action_proxy_clicked_cb), action);
|
||||
g_signal_connect (proxy, "activate",
|
||||
G_CALLBACK (katze_array_action_proxy_clicked_cb), action);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <sqlite3.h>
|
||||
|
||||
#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_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.
|
||||
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 */
|
||||
static gboolean
|
||||
katze_http_cookies_sqlite_open_db (KatzeHttpCookiesSqlite* http_cookies)
|
||||
|
@ -157,23 +83,91 @@ katze_http_cookies_sqlite_open_db (KatzeHttpCookiesSqlite* http_cookies)
|
|||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
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 (katze_http_cookies_sqlite_open_db (http_cookies))
|
||||
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
|
||||
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,
|
||||
old_cookie->name,
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -234,7 +228,7 @@ katze_http_cookies_sqlite_jar_changed_cb (SoupCookieJar* jar,
|
|||
expires,
|
||||
new_cookie->secure,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -315,6 +315,8 @@ katze_item_set_name (KatzeItem* item,
|
|||
g_return_if_fail (KATZE_IS_ITEM (item));
|
||||
|
||||
katze_assign (item->name, g_strdup (name));
|
||||
if (item->parent)
|
||||
katze_array_update ((KatzeArray*)item->parent);
|
||||
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));
|
||||
|
||||
katze_item_set_meta_string (item, "icon", icon);
|
||||
if (item->parent)
|
||||
katze_array_update ((KatzeArray*)item->parent);
|
||||
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:
|
||||
* @item: a #KatzeItem
|
||||
|
@ -527,17 +571,22 @@ katze_item_set_meta_data_value (KatzeItem* item,
|
|||
* Return value: a string, or %NULL
|
||||
*
|
||||
* Since: 0.1.8
|
||||
*
|
||||
* Since 0.4.4 "" is treated like %NULL.
|
||||
**/
|
||||
const gchar*
|
||||
katze_item_get_meta_string (KatzeItem* item,
|
||||
const gchar* key)
|
||||
{
|
||||
const gchar* value;
|
||||
|
||||
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
|
||||
g_return_val_if_fail (key != NULL, NULL);
|
||||
|
||||
if (g_str_has_prefix (key, "midori:"))
|
||||
key = &key[7];
|
||||
return g_hash_table_lookup (item->metadata, key);
|
||||
value = g_hash_table_lookup (item->metadata, key);
|
||||
return value && *value ? value : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#ifndef __KATZE_ITEM_H__
|
||||
#define __KATZE_ITEM_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -91,6 +91,9 @@ void
|
|||
katze_item_set_icon (KatzeItem* item,
|
||||
const gchar* icon);
|
||||
|
||||
GtkWidget*
|
||||
katze_item_get_image (KatzeItem* item);
|
||||
|
||||
const gchar*
|
||||
katze_item_get_token (KatzeItem* item);
|
||||
|
||||
|
|
|
@ -97,12 +97,12 @@ katze_throbber_realize (GtkWidget* widget);
|
|||
#if GTK_CHECK_VERSION (3, 0, 0)
|
||||
static void
|
||||
katze_throbber_get_preferred_height (GtkWidget *widget,
|
||||
gint *minimal_width,
|
||||
gint *natural_width);
|
||||
gint *minimal_height,
|
||||
gint *natural_height);
|
||||
static void
|
||||
katze_throbber_get_preferred_width (GtkWidget *widget,
|
||||
gint *minimal_width,
|
||||
gint *natural_width);
|
||||
gint *minimal_width,
|
||||
gint *natural_width);
|
||||
#endif
|
||||
static void
|
||||
katze_throbber_unrealize (GtkWidget* widget);
|
||||
|
@ -495,8 +495,8 @@ katze_throbber_set_animated (KatzeThrobber* throbber,
|
|||
(GSourceFunc)katze_throbber_timeout,
|
||||
throbber,
|
||||
(GDestroyNotify)katze_throbber_timeout_destroy);
|
||||
gtk_widget_queue_draw (GTK_WIDGET (throbber));
|
||||
#endif
|
||||
gtk_widget_queue_draw (GTK_WIDGET (throbber));
|
||||
|
||||
g_object_notify (G_OBJECT (throbber), "animated");
|
||||
}
|
||||
|
@ -857,14 +857,14 @@ katze_throbber_size_request (GtkWidget* widget,
|
|||
#if GTK_CHECK_VERSION (3, 0, 0)
|
||||
static void
|
||||
katze_throbber_get_preferred_height (GtkWidget *widget,
|
||||
gint *minimal_width,
|
||||
gint *natural_width)
|
||||
gint *minimal_height,
|
||||
gint *natural_height)
|
||||
{
|
||||
GtkRequisition requisition;
|
||||
|
||||
katze_throbber_size_request (widget, &requisition);
|
||||
|
||||
*minimal_width = *natural_width = requisition.height;
|
||||
*minimal_height = *natural_height = requisition.height;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -902,6 +902,7 @@ katze_throbber_aligned_coords (GtkWidget* widget,
|
|||
#endif
|
||||
|
||||
#if GTK_CHECK_VERSION (3, 0, 0)
|
||||
allocation.x = allocation.y = 0;
|
||||
allocation.width = gtk_widget_get_allocated_width (widget);
|
||||
allocation.height = gtk_widget_get_allocated_height (widget);
|
||||
gtk_widget_get_preferred_size (widget, &requisition, NULL);
|
||||
|
|
|
@ -910,21 +910,29 @@ katze_widget_popup_position_menu (GtkMenu* menu,
|
|||
GtkRequisition widget_req;
|
||||
KatzePopupInfo* info = user_data;
|
||||
GtkWidget* widget = info->widget;
|
||||
GdkWindow* window = gtk_widget_get_window (widget);
|
||||
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 */
|
||||
if (!gtk_widget_get_has_window (widget))
|
||||
{
|
||||
gdk_window_get_position (gtk_widget_get_window (widget), &wx, &wy);
|
||||
wx += allocation.x;
|
||||
wy += allocation.y;
|
||||
}
|
||||
else
|
||||
gdk_window_get_origin (gtk_widget_get_window (widget), &wx, &wy);
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
gdk_window_get_origin (window, &wx, &wy);
|
||||
wx += allocation.x;
|
||||
wy += allocation.y;
|
||||
#if GTK_CHECK_VERSION (3, 0, 0)
|
||||
gtk_widget_get_preferred_size (GTK_WIDGET (menu), &menu_req, NULL);
|
||||
gtk_widget_get_preferred_size (widget, &widget_req, NULL);
|
||||
#else
|
||||
gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
|
||||
gtk_widget_size_request (widget, &widget_req);
|
||||
#endif
|
||||
menu_width = menu_req.width;
|
||||
widget_height = widget_req.height; /* Better than allocation.height */
|
||||
|
||||
|
@ -1190,6 +1198,16 @@ katze_strip_mnemonics (const gchar* original)
|
|||
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:
|
||||
* @object: a #GObject
|
||||
|
@ -1520,6 +1538,8 @@ katze_uri_entry_changed_cb (GtkWidget* entry,
|
|||
{
|
||||
const gchar* uri = gtk_entry_get_text (GTK_ENTRY (entry));
|
||||
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)
|
||||
{
|
||||
GdkColor bg_color = { 0 };
|
||||
|
|
|
@ -58,6 +58,20 @@ G_BEGIN_DECLS
|
|||
**/
|
||||
#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*
|
||||
katze_property_proxy (gpointer object,
|
||||
const gchar* property,
|
||||
|
@ -101,6 +115,9 @@ katze_bookmark_populate_tree_view (KatzeArray* array,
|
|||
gchar*
|
||||
katze_strip_mnemonics (const gchar* original);
|
||||
|
||||
const gchar*
|
||||
katze_skip_whitespace (const gchar* str);
|
||||
|
||||
gboolean
|
||||
katze_object_has_property (gpointer object,
|
||||
const gchar* property);
|
||||
|
|
|
@ -85,6 +85,9 @@ namespace Midori {
|
|||
if (uri == null)
|
||||
return keywords;
|
||||
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)
|
||||
return uri.printf (escaped);
|
||||
return uri + escaped;
|
||||
|
@ -122,8 +125,17 @@ namespace Midori {
|
|||
FIXME: Schemes are not handled
|
||||
hostname_is_ip_address () is not used because
|
||||
we'd have to separate the path from the URI first. */
|
||||
return uri != null && uri[0].isdigit ()
|
||||
&& (uri.chr (4, '.') != null || uri.chr (4, ':') != null);
|
||||
if (uri == 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) {
|
||||
return uri != null
|
||||
|
|
162
midori/main.c
162
midori/main.c
|
@ -441,7 +441,10 @@ midori_history_initialize (KatzeArray* array,
|
|||
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)
|
||||
{
|
||||
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' "
|
||||
" AND folder = '%q'",
|
||||
katze_item_get_uri (item),
|
||||
katze_item_get_meta_string (item, "folder"));
|
||||
katze_str_non_null (katze_item_get_meta_string (item, "folder")));
|
||||
|
||||
else
|
||||
sqlcmd = sqlite3_mprintf (
|
||||
"DELETE FROM bookmarks WHERE title = '%q'"
|
||||
" AND folder = '%q'",
|
||||
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)
|
||||
{
|
||||
|
@ -958,16 +961,19 @@ midori_soup_session_settings_accept_language_cb (SoupSession* session,
|
|||
if (referer && destination && !strstr (referer, destination->host))
|
||||
{
|
||||
SoupURI* stripped_uri = soup_uri_new (referer);
|
||||
gchar* stripped_referer;
|
||||
soup_uri_set_path (stripped_uri, NULL);
|
||||
soup_uri_set_query (stripped_uri, NULL);
|
||||
stripped_referer = soup_uri_to_string (stripped_uri, FALSE);
|
||||
soup_uri_free (stripped_uri);
|
||||
if (g_getenv ("MIDORI_SOUP_DEBUG"))
|
||||
g_message ("Referer stripped");
|
||||
soup_message_headers_replace (msg->request_headers, "Referer",
|
||||
stripped_referer);
|
||||
g_free (stripped_referer);
|
||||
if (stripped_uri != NULL)
|
||||
{
|
||||
gchar* stripped_referer;
|
||||
soup_uri_set_path (stripped_uri, NULL);
|
||||
soup_uri_set_query (stripped_uri, NULL);
|
||||
stripped_referer = soup_uri_to_string (stripped_uri, FALSE);
|
||||
soup_uri_free (stripped_uri);
|
||||
if (g_getenv ("MIDORI_SOUP_DEBUG"))
|
||||
g_message ("Referer %s stripped to %s", referer, 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);
|
||||
#endif
|
||||
|
||||
g_object_set_data (G_OBJECT (session), "midori-settings", settings);
|
||||
soup_session_settings_notify_http_proxy_cb (settings, NULL, session);
|
||||
g_signal_connect (settings, "notify::http-proxy",
|
||||
G_CALLBACK (soup_session_settings_notify_http_proxy_cb), session);
|
||||
|
@ -1474,21 +1481,6 @@ snapshot_load_finished_cb (GtkWidget* web_view,
|
|||
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*
|
||||
midori_web_app_browser_new_window_cb (MidoriBrowser* browser,
|
||||
MidoriBrowser* new_browser,
|
||||
|
@ -1521,9 +1513,7 @@ midori_prepare_uri (const gchar *uri)
|
|||
{
|
||||
gchar* uri_ready;
|
||||
|
||||
if (g_path_is_absolute (uri))
|
||||
return g_filename_to_uri (uri, NULL, NULL);
|
||||
else if (g_str_has_prefix(uri, "javascript:"))
|
||||
if (g_str_has_prefix(uri, "javascript:"))
|
||||
return NULL;
|
||||
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
|
||||
midori_clear_web_cookies_cb (void)
|
||||
{
|
||||
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);
|
||||
GSList* cookies = soup_cookie_jar_all_cookies (SOUP_COOKIE_JAR (jar));
|
||||
SoupSessionFeature* feature;
|
||||
gchar* cache;
|
||||
|
||||
/* HTTP Cookies/ Web Cookies */
|
||||
for (; cookies != NULL; cookies = g_slist_next (cookies))
|
||||
{
|
||||
SoupCookie* cookie = cookies->data;
|
||||
soup_cookie_jar_delete_cookie ((SoupCookieJar*)jar, cookie);
|
||||
const gchar* domain = ((SoupCookie*)cookies->data)->domain;
|
||||
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);
|
||||
/* Removing KatzeHttpCookies makes it save outstanding changes */
|
||||
|
@ -1764,18 +1747,36 @@ midori_clear_web_cookies_cb (void)
|
|||
soup_session_add_feature (session, feature);
|
||||
g_object_unref (feature);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
static void
|
||||
midori_clear_flash_cookies_cb (void)
|
||||
{
|
||||
gchar* cache = g_build_filename (g_get_home_dir (), ".macromedia",
|
||||
"Flash_Player", NULL);
|
||||
/* Local shared objects/ Flash cookies */
|
||||
if (midori_web_settings_has_plugin_support ())
|
||||
{
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
cache = g_build_filename (g_get_home_dir (), ".macromedia", "Flash_Player", NULL);
|
||||
sokoke_remove_path (cache, TRUE);
|
||||
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
|
||||
midori_clear_saved_logins_cb (void)
|
||||
|
@ -1794,35 +1795,33 @@ midori_clear_saved_logins_cb (void)
|
|||
g_free (path);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_clear_html5_databases_cb (void)
|
||||
{
|
||||
webkit_remove_all_web_databases ();
|
||||
}
|
||||
|
||||
#if WEBKIT_CHECK_VERSION (1, 3, 11)
|
||||
static void
|
||||
midori_clear_web_cache_cb (void)
|
||||
{
|
||||
SoupSession* session = webkit_get_default_session ();
|
||||
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_flush (SOUP_CACHE (feature));
|
||||
sokoke_remove_path (path, TRUE);
|
||||
g_free (path);
|
||||
sokoke_remove_path (cache, TRUE);
|
||||
g_free (cache);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WEBKIT_CHECK_VERSION (1, 3, 13)
|
||||
static void
|
||||
midori_clear_offline_appcache_cb (void)
|
||||
midori_clear_page_icons_cb (void)
|
||||
{
|
||||
/* Changing the size implies clearing the cache */
|
||||
unsigned long long maximum = webkit_application_cache_get_maximum_size ();
|
||||
webkit_application_cache_set_maximum_size (maximum - 1);
|
||||
gchar* cache = g_build_filename (g_get_user_cache_dir (),
|
||||
PACKAGE_NAME, "icons", NULL);
|
||||
/* 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
|
||||
midori_log_to_file (const gchar* log_domain,
|
||||
|
@ -2009,6 +2008,9 @@ main (int argc,
|
|||
else
|
||||
g_set_application_name (_("Midori"));
|
||||
|
||||
/* Versioned prgname to override menuproxy blacklist */
|
||||
g_set_prgname (PACKAGE_NAME "4");
|
||||
|
||||
if (version)
|
||||
{
|
||||
g_print (
|
||||
|
@ -2104,34 +2106,24 @@ main (int argc,
|
|||
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 */
|
||||
sokoke_register_privacy_item ("formhistory", _("Saved logins and _passwords"),
|
||||
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));
|
||||
#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)
|
||||
/* TODO: Preserve page icons of search engines and merge privacy items */
|
||||
sokoke_register_privacy_item ("web-cache", _("Web Cache"),
|
||||
G_CALLBACK (midori_clear_web_cache_cb));
|
||||
sokoke_register_privacy_item ("offline-appcache", _("Offline Application Cache"),
|
||||
G_CALLBACK (midori_clear_offline_appcache_cb));
|
||||
#endif
|
||||
sokoke_register_privacy_item ("page-icons", _("Website icons"),
|
||||
G_CALLBACK (midori_clear_page_icons_cb));
|
||||
|
||||
/* Web Application or Private Browsing support */
|
||||
if (webapp || private || run)
|
||||
{
|
||||
SoupSession* session = webkit_get_default_session ();
|
||||
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_CALLBACK (midori_web_app_browser_new_window_cb), NULL);
|
||||
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)
|
||||
midori_browser_add_uri (browser, "about:blank");
|
||||
|
||||
|
|
|
@ -69,7 +69,6 @@ struct _MidoriApp
|
|||
GObject parent_instance;
|
||||
|
||||
MidoriBrowser* browser;
|
||||
GtkAccelGroup* accel_group;
|
||||
|
||||
gchar* name;
|
||||
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_BROWSER (browser));
|
||||
|
||||
gtk_window_add_accel_group (GTK_WINDOW (browser), app->accel_group);
|
||||
g_object_connect (browser,
|
||||
"signal::focus-in-event", midori_browser_focus_in_event_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 HAVE_UNIQUE
|
||||
const gchar* config = sokoke_set_config_dir (NULL);
|
||||
gchar* name_hash;
|
||||
name_hash = g_compute_checksum_for_string (G_CHECKSUM_MD5, config, -1);
|
||||
app->name = g_strconcat ("midori", "_", name_hash, NULL);
|
||||
g_free (name_hash);
|
||||
g_object_notify (G_OBJECT (app), "name");
|
||||
#else
|
||||
app->name = g_strdup (PACKAGE_NAME);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!(display = gdk_display_get_default ()))
|
||||
|
@ -767,8 +769,6 @@ midori_app_create_instance (MidoriApp* app)
|
|||
static void
|
||||
midori_app_init (MidoriApp* app)
|
||||
{
|
||||
app->accel_group = gtk_accel_group_new ();
|
||||
|
||||
app->settings = NULL;
|
||||
app->bookmarks = NULL;
|
||||
app->trash = NULL;
|
||||
|
@ -793,8 +793,6 @@ midori_app_finalize (GObject* object)
|
|||
{
|
||||
MidoriApp* app = MIDORI_APP (object);
|
||||
|
||||
g_object_unref (app->accel_group);
|
||||
|
||||
katze_assign (app->name, NULL);
|
||||
katze_object_assign (app->settings, 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
|
||||
* 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);
|
||||
#endif
|
||||
|
||||
#if ENABLE_NLS
|
||||
setlocale (LC_ALL, "");
|
||||
|
|
|
@ -1067,28 +1067,32 @@ katze_array_from_sqlite (sqlite3* db,
|
|||
}
|
||||
|
||||
/**
|
||||
* midori_array_query:
|
||||
* midori_array_query_recursive:
|
||||
* @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
|
||||
* @recursive: if %TRUE include children
|
||||
*
|
||||
* Stores the result in a #KatzeArray.
|
||||
*
|
||||
* Return value: a #KatzeArray on success, %NULL otherwise
|
||||
*
|
||||
* Since: 0.4.3
|
||||
* Since: 0.4.4
|
||||
**/
|
||||
KatzeArray*
|
||||
midori_array_query (KatzeArray* bookmarks,
|
||||
const gchar* fields,
|
||||
const gchar* condition,
|
||||
const gchar* value)
|
||||
midori_array_query_recursive (KatzeArray* bookmarks,
|
||||
const gchar* fields,
|
||||
const gchar* condition,
|
||||
const gchar* value,
|
||||
gboolean recursive)
|
||||
{
|
||||
sqlite3* db;
|
||||
gchar* sqlcmd;
|
||||
char* sqlcmd_value;
|
||||
KatzeArray* array;
|
||||
KatzeItem* item;
|
||||
GList* list;
|
||||
|
||||
g_return_val_if_fail (KATZE_IS_ARRAY (bookmarks), NULL);
|
||||
g_return_val_if_fail (fields, NULL);
|
||||
|
@ -1108,6 +1112,45 @@ midori_array_query (KatzeArray* bookmarks,
|
|||
else
|
||||
array = katze_array_from_sqlite (db, 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,13 @@ midori_array_query (KatzeArray* array,
|
|||
const gchar* condition,
|
||||
const gchar* value);
|
||||
|
||||
KatzeArray*
|
||||
midori_array_query_recursive (KatzeArray* array,
|
||||
const gchar* fields,
|
||||
const gchar* condition,
|
||||
const gchar* value,
|
||||
gboolean recursive);
|
||||
|
||||
KatzeArray*
|
||||
katze_array_from_sqlite (sqlite3* db,
|
||||
const gchar* sqlcmd);
|
||||
|
|
|
@ -37,10 +37,6 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef HAVE_HILDON_2_2
|
||||
#include <dbus/dbus.h>
|
||||
#include <mce/mode-names.h>
|
||||
|
@ -65,7 +61,6 @@ struct _MidoriBrowser
|
|||
|
||||
GtkActionGroup* action_group;
|
||||
GtkWidget* menubar;
|
||||
GtkWidget* menu_tools;
|
||||
GtkWidget* throbber;
|
||||
GtkWidget* navigationbar;
|
||||
GtkWidget* bookmarkbar;
|
||||
|
@ -177,11 +172,6 @@ midori_bookmarks_import_array_db (sqlite3* db,
|
|||
KatzeArray* array,
|
||||
gchar* folder);
|
||||
|
||||
void
|
||||
midori_bookmarks_export_array_db (sqlite3* db,
|
||||
KatzeArray* array,
|
||||
const gchar* folder);
|
||||
|
||||
void
|
||||
midori_browser_open_bookmark (MidoriBrowser* browser,
|
||||
KatzeItem* item);
|
||||
|
@ -303,8 +293,7 @@ _midori_browser_update_interface (MidoriBrowser* browser)
|
|||
_action_set_sensitive (browser, "Next",
|
||||
midori_view_get_next_page (view) != NULL);
|
||||
|
||||
gtk_action_set_visible (_action_by_name (browser, "AddSpeedDial"),
|
||||
!midori_view_is_blank (view));
|
||||
_action_set_visible (browser, "AddSpeedDial", !midori_view_is_blank (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, "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 (action), STOCK_NEWS_FEED);
|
||||
gtk_action_set_sensitive (_action_by_name (browser, "AddNewsFeed"), TRUE);
|
||||
_action_set_sensitive (browser, "AddNewsFeed", TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
midori_location_action_set_secondary_icon (
|
||||
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 (action), midori_view_get_security (view));
|
||||
|
@ -484,19 +473,16 @@ midori_view_notify_icon_cb (MidoriView* view,
|
|||
GParamSpec* pspec,
|
||||
MidoriBrowser* browser)
|
||||
{
|
||||
const gchar* uri;
|
||||
GtkAction* action;
|
||||
|
||||
if (midori_browser_get_current_tab (browser) != (GtkWidget*)view)
|
||||
return;
|
||||
|
||||
uri = midori_view_get_display_uri (view);
|
||||
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_view_get_icon (view));
|
||||
if (sokoke_is_app_or_private ())
|
||||
gtk_window_set_icon (GTK_WINDOW (browser), midori_view_get_icon (view));
|
||||
}
|
||||
|
||||
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
|
||||
with speed dial open. */
|
||||
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");
|
||||
|
@ -995,14 +981,9 @@ midori_browser_prepare_download (MidoriBrowser* browser,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
midori_browser_save_source (const gchar* uri,
|
||||
const gchar* data,
|
||||
const size_t len,
|
||||
const gchar* outfile);
|
||||
|
||||
static void
|
||||
midori_browser_save_uri (MidoriBrowser* browser,
|
||||
MidoriView* view,
|
||||
const gchar* uri)
|
||||
{
|
||||
static gchar* last_dir = NULL;
|
||||
|
@ -1011,7 +992,6 @@ midori_browser_save_uri (MidoriBrowser* browser,
|
|||
gchar* filename;
|
||||
gchar* dirname;
|
||||
gchar* last_slash;
|
||||
gchar* folder;
|
||||
|
||||
if (!gtk_widget_get_visible (GTK_WIDGET (browser)))
|
||||
return;
|
||||
|
@ -1049,24 +1029,11 @@ midori_browser_save_uri (MidoriBrowser* browser,
|
|||
|
||||
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));
|
||||
folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
|
||||
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);
|
||||
midori_view_save_source (view, uri, filename);
|
||||
|
||||
g_free (last_dir);
|
||||
last_dir = folder;
|
||||
katze_assign (last_dir,
|
||||
gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)));
|
||||
}
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
@ -1076,10 +1043,8 @@ midori_view_save_as_cb (GtkWidget* menuitem,
|
|||
const gchar* uri,
|
||||
GtkWidget* view)
|
||||
{
|
||||
MidoriBrowser* browser;
|
||||
|
||||
browser = midori_browser_get_for_widget (menuitem);
|
||||
midori_browser_save_uri (browser, uri);
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (view);
|
||||
midori_browser_save_uri (browser, MIDORI_VIEW (view), uri);
|
||||
}
|
||||
|
||||
static gchar*
|
||||
|
@ -1185,7 +1150,7 @@ midori_view_activate_action_cb (GtkWidget* view,
|
|||
const gchar* action,
|
||||
MidoriBrowser* browser)
|
||||
{
|
||||
_midori_browser_activate_action (browser, action);
|
||||
midori_browser_activate_action (browser, action);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
gtk_window_set_opacity (GTK_WINDOW (browser), 1);
|
||||
return 0;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1351,20 +1316,129 @@ midori_view_download_save_as_response_cb (GtkWidget* 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
|
||||
midori_view_download_requested_cb (GtkWidget* view,
|
||||
WebKitDownload* download,
|
||||
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"))
|
||||
{
|
||||
static GtkWidget* dialog = NULL;
|
||||
|
||||
if (!dialog)
|
||||
{
|
||||
gchar* folder;
|
||||
dialog = sokoke_file_chooser_dialog_new (_("Save file"),
|
||||
GTK_WINDOW (browser), GTK_FILE_CHOOSER_ACTION_SAVE);
|
||||
gtk_file_chooser_set_do_overwrite_confirmation (
|
||||
|
@ -1385,58 +1459,12 @@ midori_view_download_requested_cb (GtkWidget* view,
|
|||
}
|
||||
else
|
||||
{
|
||||
const gchar* suggested;
|
||||
gchar* basename;
|
||||
gchar* filename;
|
||||
gchar* uri;
|
||||
|
||||
if (g_object_get_data (G_OBJECT (download), "open-download"))
|
||||
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);
|
||||
gchar* folder = g_object_get_data (G_OBJECT (download), "open-download")
|
||||
? NULL : katze_object_get_string (browser->settings, "download-folder");
|
||||
gchar* destination_uri =
|
||||
midori_browser_download_prepare_destination_uri (download, folder);
|
||||
midori_browser_prepare_download (browser, download, destination_uri);
|
||||
g_free (destination_uri);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -1488,20 +1516,18 @@ midori_browser_notebook_resize (MidoriBrowser* browser,
|
|||
GdkRectangle* allocation)
|
||||
{
|
||||
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;
|
||||
gint min_size;
|
||||
gint icon_size = 16;
|
||||
GtkAllocation notebook_size;
|
||||
GList* children;
|
||||
|
||||
g_return_if_fail (n > 0);
|
||||
|
||||
if (allocation != NULL)
|
||||
notebook_size.width = allocation->width;
|
||||
else
|
||||
gtk_widget_get_allocation (browser->notebook, ¬ebook_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_MENU, &icon_size, NULL);
|
||||
|
@ -1672,14 +1698,14 @@ midori_browser_key_press_event (GtkWidget* widget,
|
|||
&& event->keyval == GDK_KEY_Tab
|
||||
&& (event->state & GDK_CONTROL_MASK))
|
||||
{
|
||||
gtk_action_activate (_action_by_name (browser, "TabNext"));
|
||||
midori_browser_activate_action (browser, "TabNext");
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->keyval == GDK_KEY_ISO_Left_Tab
|
||||
&& (event->state & GDK_CONTROL_MASK)
|
||||
&& (event->state & GDK_SHIFT_MASK))
|
||||
{
|
||||
gtk_action_activate (_action_by_name (browser, "TabPrevious"));
|
||||
midori_browser_activate_action (browser, "TabPrevious");
|
||||
return TRUE;
|
||||
}
|
||||
/* Interpret Ctrl+= as Zoom In for compatibility */
|
||||
|
@ -1692,7 +1718,7 @@ midori_browser_key_press_event (GtkWidget* widget,
|
|||
/* Interpret F5 as reloading for compatibility */
|
||||
else if (event->keyval == GDK_KEY_F5)
|
||||
{
|
||||
gtk_action_activate (_action_by_name (browser, "Reload"));
|
||||
midori_browser_activate_action (browser, "Reload");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1741,12 +1767,12 @@ midori_browser_key_press_event (GtkWidget* widget,
|
|||
if ((event->keyval == GDK_KEY_BackSpace)
|
||||
&& (event->state & GDK_SHIFT_MASK))
|
||||
{
|
||||
gtk_action_activate (_action_by_name (browser, "Forward"));
|
||||
midori_browser_activate_action (browser, "Forward");
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->keyval == GDK_KEY_BackSpace)
|
||||
{
|
||||
gtk_action_activate (_action_by_name (browser, "Back"));
|
||||
midori_browser_activate_action (browser, "Back");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -2246,8 +2272,7 @@ static void
|
|||
_action_private_browsing_activate (GtkAction* action,
|
||||
MidoriBrowser* browser)
|
||||
{
|
||||
const gchar* uri = midori_browser_get_current_uri (browser);
|
||||
sokoke_spawn_app (uri && *uri ? uri : "about:blank", TRUE);
|
||||
sokoke_spawn_app ("about:private", TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2313,7 +2338,8 @@ static void
|
|||
_action_save_as_activate (GtkAction* action,
|
||||
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
|
||||
|
@ -2597,6 +2623,7 @@ _action_copy_activate (GtkAction* action,
|
|||
MidoriBrowser* 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 */
|
||||
if (WEBKIT_IS_WEB_VIEW (widget))
|
||||
{
|
||||
|
@ -2606,6 +2633,7 @@ _action_copy_activate (GtkAction* action,
|
|||
sokoke_widget_copy_clipboard (widget, selected);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (G_LIKELY (widget) && g_signal_lookup ("copy-clipboard", G_OBJECT_TYPE (widget)))
|
||||
g_signal_emit_by_name (widget, "copy-clipboard");
|
||||
}
|
||||
|
@ -3032,6 +3060,7 @@ _action_compact_menu_populate_popup (GtkAction* action,
|
|||
{ NULL },
|
||||
{ "Fullscreen" },
|
||||
{ "Panel" },
|
||||
{ "Bookmarkbar" },
|
||||
{ "-" },
|
||||
#endif
|
||||
{ NULL },
|
||||
|
@ -3103,7 +3132,7 @@ midori_preferences_response_help_cb (GtkWidget* preferences,
|
|||
MidoriBrowser* browser)
|
||||
{
|
||||
if (response == GTK_RESPONSE_HELP)
|
||||
gtk_action_activate (_action_by_name (browser, "HelpFAQ"));
|
||||
midori_browser_activate_action (browser, "HelpFAQ");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -3129,6 +3158,19 @@ _action_preferences_activate (GtkAction* action,
|
|||
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
|
||||
_action_menubar_activate (GtkToggleAction* menubar_action,
|
||||
MidoriBrowser* browser)
|
||||
|
@ -3139,6 +3181,9 @@ _action_menubar_activate (GtkToggleAction* menubar_action,
|
|||
GList* children;
|
||||
gchar* items;
|
||||
|
||||
if (midori_browser_has_native_menubar ())
|
||||
active = FALSE;
|
||||
|
||||
toolbar_items = g_string_new (NULL);
|
||||
children = gtk_container_get_children (GTK_CONTAINER (browser->navigationbar));
|
||||
for (; children != NULL; children = g_list_next (children))
|
||||
|
@ -3232,13 +3277,14 @@ _action_reload_stop_activate (GtkAction* action,
|
|||
{
|
||||
GdkModifierType state = (GdkModifierType)0;
|
||||
gint x, y;
|
||||
GdkWindow* window;
|
||||
gboolean from_cache = TRUE;
|
||||
|
||||
if (!strcmp (gtk_action_get_name (action), "ReloadUncached"))
|
||||
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)
|
||||
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
|
||||
_action_source_view_activate (GtkAction* action,
|
||||
MidoriBrowser* browser)
|
||||
{
|
||||
WebKitWebDataSource *data_source;
|
||||
WebKitWebFrame *frame;
|
||||
const GString *data;
|
||||
GtkWidget* view;
|
||||
GtkWidget* web_view;
|
||||
gchar* text_editor;
|
||||
gchar* filename = NULL;
|
||||
const gchar* uri;
|
||||
|
||||
if (!(view = midori_browser_get_current_tab (browser)))
|
||||
return;
|
||||
|
||||
filename = midori_view_save_source (MIDORI_VIEW (view), NULL, 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))
|
||||
{
|
||||
GtkWidget* source;
|
||||
|
@ -3454,6 +3407,9 @@ _action_fullscreen_activate (GtkAction* action,
|
|||
state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (browser)));
|
||||
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"))
|
||||
gtk_widget_show (browser->panel);
|
||||
|
||||
|
@ -3471,6 +3427,7 @@ _action_fullscreen_activate (GtkAction* action,
|
|||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_hide (browser->menubar);
|
||||
gtk_widget_hide (browser->panel);
|
||||
gtk_widget_hide (browser->bookmarkbar);
|
||||
gtk_widget_hide (browser->navigationbar);
|
||||
|
@ -3680,51 +3637,49 @@ static void
|
|||
_action_location_reset_uri (GtkAction* action,
|
||||
MidoriBrowser* browser)
|
||||
{
|
||||
const gchar* uri;
|
||||
|
||||
uri = midori_browser_get_current_uri (browser);
|
||||
midori_location_action_set_text (MIDORI_LOCATION_ACTION (action), uri);
|
||||
GtkWidget* view;
|
||||
if ((view = midori_browser_get_current_tab (browser)))
|
||||
{
|
||||
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
|
||||
_action_location_submit_uri (GtkAction* action,
|
||||
const gchar* uri,
|
||||
gboolean new_tab,
|
||||
MidoriBrowser* browser)
|
||||
{
|
||||
gchar* stripped_uri;
|
||||
gchar* new_uri;
|
||||
gint n;
|
||||
|
||||
stripped_uri = g_strdup (uri);
|
||||
g_strstrip (stripped_uri);
|
||||
new_uri = sokoke_magic_uri (stripped_uri);
|
||||
uri = katze_skip_whitespace (uri);
|
||||
new_uri = sokoke_magic_uri (uri);
|
||||
if (!new_uri)
|
||||
{
|
||||
gchar** parts;
|
||||
gchar* keywords = NULL;
|
||||
const gchar* keywords = NULL;
|
||||
const gchar* search_uri = NULL;
|
||||
KatzeItem* item;
|
||||
|
||||
/* Do we have a keyword and a string? */
|
||||
parts = g_strsplit (stripped_uri, " ", 2);
|
||||
if (parts[0] && browser->search_engines)
|
||||
if (browser->search_engines
|
||||
&& (item = katze_array_find_token (browser->search_engines, uri)))
|
||||
{
|
||||
KatzeItem* item;
|
||||
if ((item = katze_array_find_token (browser->search_engines, parts[0])))
|
||||
{
|
||||
keywords = g_strdup (parts[1] ? parts[1] : "");
|
||||
search_uri = katze_item_get_uri (item);
|
||||
}
|
||||
keywords = strchr (uri, ' ');
|
||||
if (keywords != NULL)
|
||||
keywords++;
|
||||
else
|
||||
keywords = "";
|
||||
search_uri = katze_item_get_uri (item);
|
||||
}
|
||||
g_strfreev (parts);
|
||||
|
||||
if (keywords)
|
||||
g_free (stripped_uri);
|
||||
else
|
||||
if (keywords == NULL)
|
||||
{
|
||||
keywords = stripped_uri;
|
||||
keywords = uri;
|
||||
search_uri = browser->location_entry_search;
|
||||
}
|
||||
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)
|
||||
sqlite3_clear_bindings (statement);
|
||||
}
|
||||
|
||||
g_free (keywords);
|
||||
}
|
||||
else
|
||||
g_free (stripped_uri);
|
||||
|
||||
if (new_tab)
|
||||
{
|
||||
|
@ -4348,7 +4299,6 @@ _action_bookmarks_export_activate (GtkAction* action,
|
|||
const gchar* format;
|
||||
gchar* path = NULL;
|
||||
GError* error;
|
||||
sqlite3* db;
|
||||
KatzeArray* bookmarks;
|
||||
|
||||
if (!browser->bookmarks || !gtk_widget_get_visible (GTK_WIDGET (browser)))
|
||||
|
@ -4389,9 +4339,8 @@ wrong_format:
|
|||
return;
|
||||
|
||||
error = NULL;
|
||||
db = g_object_get_data (G_OBJECT (browser->history), "db");
|
||||
bookmarks = katze_array_new (KATZE_TYPE_ARRAY);
|
||||
midori_bookmarks_export_array_db (db, bookmarks, "");
|
||||
bookmarks = midori_array_query_recursive (browser->bookmarks,
|
||||
"*", "folder='%q'", "", TRUE);
|
||||
if (!midori_array_to_file (bookmarks, path, format, &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))
|
||||
{
|
||||
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 FALSE;
|
||||
|
@ -4947,10 +4896,10 @@ midori_panel_close_cb (MidoriPanel* panel,
|
|||
}
|
||||
|
||||
static void
|
||||
gtk_notebook_switch_page_cb (GtkWidget* notebook,
|
||||
gpointer page,
|
||||
guint page_num,
|
||||
MidoriBrowser* browser)
|
||||
midori_browser_notebook_switch_page_cb (GtkWidget* notebook,
|
||||
gpointer page,
|
||||
guint page_num,
|
||||
MidoriBrowser* browser)
|
||||
{
|
||||
GtkWidget* widget;
|
||||
GtkAction* action;
|
||||
|
@ -4966,10 +4915,10 @@ gtk_notebook_switch_page_cb (GtkWidget* notebook,
|
|||
}
|
||||
|
||||
static void
|
||||
gtk_notebook_switch_page_after_cb (GtkWidget* notebook,
|
||||
gpointer page,
|
||||
guint page_num,
|
||||
MidoriBrowser* browser)
|
||||
midori_browser_notebook_switch_page_after_cb (GtkWidget* notebook,
|
||||
gpointer page,
|
||||
guint page_num,
|
||||
MidoriBrowser* browser)
|
||||
{
|
||||
GtkWidget* widget;
|
||||
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_icon (MIDORI_LOCATION_ACTION (action),
|
||||
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)
|
||||
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);
|
||||
if (new_browser)
|
||||
{
|
||||
GtkWidget* new_notebook = katze_object_get_object (new_browser, "notebook");
|
||||
g_object_unref (new_notebook);
|
||||
gtk_window_move (GTK_WINDOW (browser), x, y);
|
||||
GtkWidget* new_notebook = new_browser->notebook;
|
||||
gtk_window_move (GTK_WINDOW (new_browser), x, y);
|
||||
return new_notebook;
|
||||
}
|
||||
else /* No MidoriApp, so this is app or private mode */
|
||||
|
@ -5041,8 +4991,8 @@ midori_browser_notebook_create_window_cb (GtkNotebook* notebook,
|
|||
}
|
||||
|
||||
static void
|
||||
midori_browser_switch_tab_cb (GtkWidget* menuitem,
|
||||
MidoriBrowser* browser)
|
||||
midori_browser_menu_item_switch_tab_cb (GtkWidget* menuitem,
|
||||
MidoriBrowser* browser)
|
||||
{
|
||||
gint page = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem), "index"));
|
||||
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);
|
||||
g_object_set_data (G_OBJECT (menuitem), "index", GINT_TO_POINTER (i));
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (midori_browser_switch_tab_cb), browser);
|
||||
G_CALLBACK (midori_browser_menu_item_switch_tab_cb), browser);
|
||||
i++;
|
||||
}
|
||||
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)
|
||||
window_state = MIDORI_WINDOW_FULLSCREEN;
|
||||
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
|
||||
|
@ -5857,8 +5794,8 @@ midori_browser_init (MidoriBrowser* browser)
|
|||
GtkSettings* gtk_settings;
|
||||
GtkWidget* hpaned;
|
||||
GtkWidget* vpaned;
|
||||
GtkRcStyle* rcstyle;
|
||||
GtkWidget* scrolled;
|
||||
KatzeArray* dummy_array;
|
||||
|
||||
browser->settings = midori_web_settings_new ();
|
||||
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);
|
||||
gtk_window_set_role (GTK_WINDOW (browser), "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);
|
||||
gtk_container_add (GTK_CONTAINER (browser), vbox);
|
||||
gtk_widget_show (vbox);
|
||||
|
@ -5911,7 +5851,7 @@ midori_browser_init (MidoriBrowser* browser)
|
|||
}
|
||||
|
||||
/* 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,
|
||||
"name", "Separator",
|
||||
|
@ -5986,12 +5926,14 @@ midori_browser_init (MidoriBrowser* browser)
|
|||
gtk_action_group_add_action_with_accel (browser->action_group, 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,
|
||||
"name", "Bookmarks",
|
||||
"label", _("_Bookmarks"),
|
||||
"stock-id", STOCK_BOOKMARKS,
|
||||
"tooltip", _("Show the saved bookmarks"),
|
||||
"array", browser->proxy_array, /* Use a non-empty array here */
|
||||
"array", dummy_array /* updated, unique */,
|
||||
NULL);
|
||||
g_object_connect (action,
|
||||
"signal::populate-folder",
|
||||
|
@ -6001,12 +5943,15 @@ midori_browser_init (MidoriBrowser* browser)
|
|||
NULL);
|
||||
gtk_action_group_add_action_with_accel (browser->action_group, 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,
|
||||
"name", "Tools",
|
||||
"label", _("_Tools"),
|
||||
"stock-id", GTK_STOCK_PREFERENCES,
|
||||
"array", katze_array_new (KATZE_TYPE_ITEM),
|
||||
"array", dummy_array /* updated, unique */,
|
||||
NULL);
|
||||
g_object_connect (action,
|
||||
"signal::populate-popup",
|
||||
|
@ -6016,6 +5961,7 @@ midori_browser_init (MidoriBrowser* browser)
|
|||
NULL);
|
||||
gtk_action_group_add_action (browser->action_group, action);
|
||||
g_object_unref (action);
|
||||
g_object_unref (dummy_array);
|
||||
|
||||
action = g_object_new (KATZE_TYPE_ARRAY_ACTION,
|
||||
"name", "Window",
|
||||
|
@ -6051,6 +5997,7 @@ midori_browser_init (MidoriBrowser* browser)
|
|||
browser->menubar = gtk_ui_manager_get_widget (ui_manager, "/menubar");
|
||||
gtk_box_pack_start (GTK_BOX (vbox), browser->menubar, FALSE, FALSE, 0);
|
||||
gtk_widget_hide (browser->menubar);
|
||||
_action_set_visible (browser, "Menubar", !midori_browser_has_native_menubar ());
|
||||
#if HAVE_HILDON
|
||||
#if HILDON_CHECK_VERSION (2, 2, 0)
|
||||
browser->menubar = hildon_app_menu_new ();
|
||||
|
@ -6082,7 +6029,6 @@ midori_browser_init (MidoriBrowser* browser)
|
|||
#endif
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (browser->menubar), menuitem);
|
||||
#endif
|
||||
browser->menu_tools = gtk_menu_new ();
|
||||
|
||||
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (
|
||||
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_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_visible (browser, "LastSession", FALSE);
|
||||
#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_widget_show (vpaned);
|
||||
browser->notebook = gtk_notebook_new ();
|
||||
#if !GTK_CHECK_VERSION (3, 0, 0)
|
||||
{
|
||||
/* Remove the inner border between scrollbars and the window border */
|
||||
rcstyle = gtk_rc_style_new ();
|
||||
GtkRcStyle* rcstyle = gtk_rc_style_new ();
|
||||
rcstyle->xthickness = 0;
|
||||
gtk_widget_modify_style (browser->notebook, rcstyle);
|
||||
g_object_unref (rcstyle);
|
||||
}
|
||||
#endif
|
||||
gtk_notebook_set_scrollable (GTK_NOTEBOOK (browser->notebook), TRUE);
|
||||
gtk_paned_pack1 (GTK_PANED (vpaned), browser->notebook, FALSE, FALSE);
|
||||
g_signal_connect (browser->notebook, "switch-page",
|
||||
G_CALLBACK (gtk_notebook_switch_page_cb),
|
||||
G_CALLBACK (midori_browser_notebook_switch_page_cb),
|
||||
browser);
|
||||
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);
|
||||
g_signal_connect (browser->notebook, "page-reordered",
|
||||
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);
|
||||
|
||||
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);
|
||||
#endif
|
||||
gtk_toolbar_set_show_arrow (GTK_TOOLBAR (browser->transferbar), FALSE);
|
||||
gtk_widget_show (browser->transferbar);
|
||||
|
||||
|
@ -6676,29 +6628,21 @@ midori_browser_settings_notify (MidoriWebSettings* web_settings,
|
|||
_toggle_tabbar_smartly (browser, FALSE);
|
||||
else if (name == g_intern_string ("show-menubar"))
|
||||
{
|
||||
gtk_toggle_action_set_active (
|
||||
GTK_TOGGLE_ACTION (_action_by_name (browser, "Menubar")),
|
||||
g_value_get_boolean (&value));
|
||||
_action_set_active (browser, "Menubar", g_value_get_boolean (&value));
|
||||
}
|
||||
else if (name == g_intern_string ("show-navigationbar"))
|
||||
{
|
||||
browser->show_navigationbar = g_value_get_boolean (&value);
|
||||
gtk_toggle_action_set_active (
|
||||
GTK_TOGGLE_ACTION (_action_by_name (browser, "Navigationbar")),
|
||||
g_value_get_boolean (&value));
|
||||
_action_set_active (browser, "Navigationbar", g_value_get_boolean (&value));
|
||||
}
|
||||
else if (name == g_intern_string ("show-bookmarkbar"))
|
||||
{
|
||||
gtk_toggle_action_set_active (
|
||||
GTK_TOGGLE_ACTION (_action_by_name (browser, "Bookmarkbar")),
|
||||
g_value_get_boolean (&value));
|
||||
_action_set_active (browser, "Bookmarkbar", g_value_get_boolean (&value));
|
||||
}
|
||||
else if (name == g_intern_string ("show-statusbar"))
|
||||
{
|
||||
browser->show_statusbar = g_value_get_boolean (&value);
|
||||
gtk_toggle_action_set_active (
|
||||
GTK_TOGGLE_ACTION (_action_by_name (browser, "Statusbar")),
|
||||
g_value_get_boolean (&value));
|
||||
_action_set_active (browser, "Statusbar", g_value_get_boolean (&value));
|
||||
}
|
||||
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);
|
||||
if (midori_view_is_blank (MIDORI_VIEW (view)))
|
||||
gtk_action_activate (_action_by_name (browser, "Location"));
|
||||
midori_browser_activate_action (browser, "Location");
|
||||
else
|
||||
gtk_widget_grab_focus (view);
|
||||
|
||||
|
|
|
@ -277,43 +277,96 @@ midori_location_action_create_model (void)
|
|||
}
|
||||
|
||||
static void
|
||||
midori_location_action_popup_position (GtkWidget* popup,
|
||||
GtkWidget* widget)
|
||||
midori_location_action_popup_position (MidoriLocationAction* action,
|
||||
gint matches)
|
||||
{
|
||||
GtkWidget* popup = action->popup;
|
||||
GtkWidget* widget = action->entry;
|
||||
GdkWindow* window = gtk_widget_get_window (widget);
|
||||
gint wx, wy;
|
||||
gint wx, wy, x_border, y_border, items;
|
||||
GtkRequisition menu_req;
|
||||
GtkRequisition widget_req;
|
||||
GdkScreen* screen;
|
||||
gint monitor_num;
|
||||
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);
|
||||
|
||||
if (!gtk_widget_get_has_window (widget))
|
||||
{
|
||||
GtkAllocation alloc;
|
||||
gtk_widget_get_allocation (widget, &alloc);
|
||||
wx += alloc.x;
|
||||
wy += alloc.y;
|
||||
}
|
||||
#if GTK_CHECK_VERSION (3, 0, 0)
|
||||
wx += alloc.x;
|
||||
wy += alloc.y + (alloc.height - widget_req.height) / 2;
|
||||
#endif
|
||||
/* _gtk_entry_get_borders (GTK_ENTRY (widget), &x_border, &y_border); */
|
||||
x_border = y_border = 0;
|
||||
|
||||
gtk_widget_size_request (popup, &menu_req);
|
||||
gtk_widget_size_request (widget, &widget_req);
|
||||
gtk_tree_view_column_cell_get_size (
|
||||
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);
|
||||
monitor_num = gdk_screen_get_monitor_at_window (screen, window);
|
||||
gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
|
||||
|
||||
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;
|
||||
toplevel = gtk_widget_get_toplevel (widget);
|
||||
gtk_window_get_size (GTK_WINDOW (toplevel), NULL, &toplevel_height);
|
||||
toplevel_height = MIN (toplevel_height, monitor.height);
|
||||
if (wy > toplevel_height / 2)
|
||||
items = MIN (matches, ((monitor.y + wy) / height) - 1);
|
||||
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;
|
||||
gtk_window_move (GTK_WINDOW (popup), wx, wy);
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
gtk_window_resize (GTK_WINDOW (popup), allocation.width, 1);
|
||||
above = TRUE;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -357,28 +410,21 @@ midori_location_action_popup_timeout_cb (gpointer data)
|
|||
gint result;
|
||||
static sqlite3_stmt* stmt;
|
||||
const gchar* sqlcmd;
|
||||
gint matches, searches, height, screen_height, browser_height, sep;
|
||||
MidoriBrowser* browser;
|
||||
gint matches, searches;
|
||||
GtkStyle* style;
|
||||
|
||||
if (!action->entry || !gtk_widget_has_focus (action->entry) || !action->history)
|
||||
return FALSE;
|
||||
|
||||
/* 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);
|
||||
if (parts && *parts && parts[1]
|
||||
&& katze_array_find_token (action->search_engines, *parts))
|
||||
{
|
||||
g_strfreev (parts);
|
||||
midori_location_action_popdown_completion (action);
|
||||
return FALSE;
|
||||
}
|
||||
g_strfreev (parts);
|
||||
midori_location_action_popdown_completion (action);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* 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 != ' '))
|
||||
{
|
||||
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);
|
||||
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);
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (popup_frame), GTK_SHADOW_ETCHED_IN);
|
||||
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);
|
||||
|
||||
matches = searches = 0;
|
||||
gtk_widget_realize (action->treeview);
|
||||
style = gtk_widget_get_style (action->treeview);
|
||||
while (result == SQLITE_ROW)
|
||||
{
|
||||
|
@ -507,9 +556,11 @@ midori_location_action_popup_timeout_cb (gpointer data)
|
|||
else if (type == 2 /* search_view */)
|
||||
{
|
||||
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,
|
||||
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);
|
||||
g_free (search_desc);
|
||||
g_free (search_title);
|
||||
}
|
||||
if (icon != NULL)
|
||||
|
@ -518,8 +569,12 @@ midori_location_action_popup_timeout_cb (gpointer data)
|
|||
matches++;
|
||||
result = sqlite3_step (stmt);
|
||||
}
|
||||
sqlite3_reset (stmt);
|
||||
sqlite3_clear_bindings (stmt);
|
||||
|
||||
if (stmt)
|
||||
{
|
||||
sqlite3_reset (stmt);
|
||||
sqlite3_clear_bindings (stmt);
|
||||
}
|
||||
|
||||
if (action->search_engines)
|
||||
{
|
||||
|
@ -529,17 +584,22 @@ midori_location_action_popup_timeout_cb (gpointer data)
|
|||
{
|
||||
gchar* uri;
|
||||
gchar* title;
|
||||
const gchar* text;
|
||||
gchar* desc;
|
||||
GdkPixbuf* icon;
|
||||
|
||||
uri = midori_uri_for_search (katze_item_get_uri (item), action->key);
|
||||
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);
|
||||
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,
|
||||
STYLE_COL, 1, FAVICON_COL, icon, -1);
|
||||
g_free (uri);
|
||||
g_free (title);
|
||||
g_free (desc);
|
||||
if (icon != NULL)
|
||||
g_object_unref (icon);
|
||||
i++;
|
||||
|
@ -553,22 +613,10 @@ midori_location_action_popup_timeout_cb (gpointer data)
|
|||
gtk_window_set_screen (GTK_WINDOW (action->popup),
|
||||
gtk_widget_get_screen (action->entry));
|
||||
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);
|
||||
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);
|
||||
midori_location_action_popup_position (action, matches + searches);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1532,30 +1580,22 @@ midori_location_action_add_item (MidoriLocationAction* location_action,
|
|||
#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
|
||||
midori_location_action_set_icon_for_uri (MidoriLocationAction* location_action,
|
||||
GdkPixbuf* icon,
|
||||
const gchar* uri)
|
||||
{
|
||||
#if !HAVE_HILDON
|
||||
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
|
||||
midori_location_action_set_icon (location_action, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1659,16 +1699,20 @@ midori_location_action_set_security_hint (MidoriLocationAction* location_action,
|
|||
for (; proxies != NULL; proxies = g_slist_next (proxies))
|
||||
if (GTK_IS_TOOL_ITEM (proxies->data))
|
||||
{
|
||||
#if !GTK_CHECK_VERSION (3, 0, 0)
|
||||
const gchar* bg_color = NULL;
|
||||
const gchar* fg_color = NULL;
|
||||
#endif
|
||||
GtkWidget* entry = midori_location_action_entry_for_proxy (proxies->data);
|
||||
GdkScreen* screen = gtk_widget_get_screen (entry);
|
||||
GtkIconTheme* icon_theme = gtk_icon_theme_get_for_screen (screen);
|
||||
|
||||
if (hint == MIDORI_SECURITY_UNKNOWN)
|
||||
{
|
||||
#if !GTK_CHECK_VERSION (3, 0, 0)
|
||||
bg_color = "#ef7070";
|
||||
fg_color = "#000";
|
||||
#endif
|
||||
#if !HAVE_HILDON
|
||||
if (gtk_icon_theme_has_icon (icon_theme, "channel-insecure-symbolic"))
|
||||
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)
|
||||
{
|
||||
#if !GTK_CHECK_VERSION (3, 0, 0)
|
||||
bg_color = "#d1eeb9";
|
||||
fg_color = "#000";
|
||||
#endif
|
||||
#if !HAVE_HILDON
|
||||
if (gtk_icon_theme_has_icon (icon_theme, "channel-secure-symbolic"))
|
||||
gtk_icon_entry_set_icon_from_icon_name (GTK_ICON_ENTRY (entry),
|
||||
|
|
|
@ -393,6 +393,13 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
|
|||
INDENTED_ADD (button);
|
||||
button = katze_property_proxy (settings, "flash-window-on-new-bg-tabs", NULL);
|
||||
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);
|
||||
button = katze_property_label (settings, "preferred-languages");
|
||||
INDENTED_ADD (button);
|
||||
|
|
|
@ -312,6 +312,7 @@ midori_search_action_create_tool_item (GtkAction* action)
|
|||
|
||||
toolitem = GTK_WIDGET (gtk_tool_item_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_PRIMARY, TRUE);
|
||||
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);
|
||||
}
|
||||
|
||||
static inline const gchar*
|
||||
STR_NON_NULL (const gchar* string)
|
||||
{
|
||||
return string ? string : "";
|
||||
}
|
||||
|
||||
static void
|
||||
midori_search_action_get_editor (MidoriSearchAction* search_action,
|
||||
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);
|
||||
if (!new_engine)
|
||||
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_container_add (GTK_CONTAINER (content_area), 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);
|
||||
if (!new_engine)
|
||||
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_container_add (GTK_CONTAINER (content_area), hbox);
|
||||
gtk_widget_show_all (hbox);
|
||||
|
@ -972,10 +967,11 @@ midori_search_action_get_editor (MidoriSearchAction* search_action,
|
|||
#else
|
||||
NULL);
|
||||
#endif
|
||||
g_object_set_data (G_OBJECT (entry_uri), "allow_%s", (void*)1);
|
||||
gtk_entry_set_activates_default (GTK_ENTRY (entry_uri), TRUE);
|
||||
if (!new_engine)
|
||||
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_container_add (GTK_CONTAINER (content_area), 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);
|
||||
if (!new_engine)
|
||||
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_container_add (GTK_CONTAINER (content_area), 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);
|
||||
if (!new_engine)
|
||||
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_container_add (GTK_CONTAINER (content_area), hbox);
|
||||
gtk_widget_show_all (hbox);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -197,6 +197,11 @@ midori_view_can_view_source (MidoriView* view);
|
|||
gboolean
|
||||
midori_view_can_save (MidoriView* view);
|
||||
|
||||
gchar*
|
||||
midori_view_save_source (MidoriView* view,
|
||||
const gchar* uri,
|
||||
const gchar* outfile);
|
||||
|
||||
gboolean
|
||||
midori_view_can_find (MidoriView* view);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "midori-websettings.h"
|
||||
|
||||
#include "sokoke.h"
|
||||
#include <midori/midori-core.h> /* Vala API */
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
@ -85,6 +86,7 @@ struct _MidoriWebSettings
|
|||
|
||||
gint clear_private_data;
|
||||
gchar* clear_data;
|
||||
gchar* site_data_rules;
|
||||
#if !WEBKIT_CHECK_VERSION (1, 3, 13)
|
||||
gboolean enable_dns_prefetching;
|
||||
#endif
|
||||
|
@ -145,6 +147,8 @@ enum
|
|||
PROP_OPEN_TABS_NEXT_TO_CURRENT,
|
||||
PROP_OPEN_POPUPS_IN_TABS,
|
||||
PROP_FLASH_WINDOW_ON_BG_TABS,
|
||||
PROP_ENABLE_WEBGL,
|
||||
PROP_ENABLE_FULLSCREEN,
|
||||
|
||||
PROP_AUTO_LOAD_IMAGES,
|
||||
PROP_ENABLE_SCRIPTS,
|
||||
|
@ -173,6 +177,7 @@ enum
|
|||
|
||||
PROP_CLEAR_PRIVATE_DATA,
|
||||
PROP_CLEAR_DATA,
|
||||
PROP_SITE_DATA_RULES,
|
||||
PROP_ENABLE_DNS_PREFETCHING,
|
||||
PROP_STRIP_REFERER,
|
||||
PROP_ENFORCE_FONT_FAMILY,
|
||||
|
@ -339,6 +344,21 @@ midori_get_download_dir (void)
|
|||
}
|
||||
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
|
||||
midori_web_settings_class_init (MidoriWebSettingsClass* class)
|
||||
|
@ -727,13 +747,8 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
|
|||
"enable-plugins",
|
||||
_("Enable Netscape plugins"),
|
||||
_("Enable embedded Netscape plugin objects"),
|
||||
#ifdef G_OS_WIN32
|
||||
FALSE,
|
||||
G_PARAM_READABLE));
|
||||
#else
|
||||
TRUE,
|
||||
flags));
|
||||
#endif
|
||||
midori_web_settings_has_plugin_support (),
|
||||
midori_web_settings_has_plugin_support () ? flags : G_PARAM_READABLE));
|
||||
/* Override properties to override defaults */
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_ENABLE_DEVELOPER_EXTRAS,
|
||||
|
@ -777,7 +792,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
|
|||
g_param_spec_boolean ("enable-page-cache",
|
||||
"Enable page cache",
|
||||
"Whether the page cache should be used",
|
||||
TRUE,
|
||||
!midori_web_settings_low_memory_profile (),
|
||||
flags));
|
||||
#endif
|
||||
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"),
|
||||
FALSE,
|
||||
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:
|
||||
|
@ -1021,6 +1056,22 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
|
|||
_("The data selected for deletion"),
|
||||
NULL,
|
||||
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)
|
||||
/**
|
||||
* MidoriWebSettings:enable-dns-prefetching:
|
||||
|
@ -1180,6 +1231,74 @@ midori_web_settings_finalize (GObject* 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)
|
||||
static gchar*
|
||||
get_sys_name (gchar** architecture)
|
||||
|
@ -1544,6 +1663,9 @@ midori_web_settings_set_property (GObject* object,
|
|||
case PROP_CLEAR_DATA:
|
||||
katze_assign (web_settings->clear_data, g_value_dup_string (value));
|
||||
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)
|
||||
case PROP_ENABLE_DNS_PREFETCHING:
|
||||
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:
|
||||
web_settings->flash_window_on_bg_tabs = g_value_get_boolean (value);
|
||||
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:
|
||||
{
|
||||
gint old_len = web_settings->user_stylesheet_uri_cached
|
||||
|
@ -1845,6 +1975,9 @@ midori_web_settings_get_property (GObject* object,
|
|||
case PROP_CLEAR_DATA:
|
||||
g_value_set_string (value, web_settings->clear_data);
|
||||
break;
|
||||
case PROP_SITE_DATA_RULES:
|
||||
g_value_set_string (value, web_settings->site_data_rules);
|
||||
break;
|
||||
#if !WEBKIT_CHECK_VERSION (1, 3, 13)
|
||||
case PROP_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:
|
||||
g_value_set_boolean (value, web_settings->flash_window_on_bg_tabs);
|
||||
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:
|
||||
g_value_take_string (value, katze_object_get_string (web_settings,
|
||||
"WebKitWebSettings::user-stylesheet-uri"));
|
||||
|
|
|
@ -173,6 +173,21 @@ const gchar*
|
|||
midori_web_settings_get_system_name (gchar** architecture,
|
||||
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
|
||||
|
||||
#endif /* __MIDORI_WEB_SETTINGS_H__ */
|
||||
|
|
223
midori/socket.c
223
midori/socket.c
|
@ -54,9 +54,6 @@
|
|||
#endif
|
||||
|
||||
#include "socket.h"
|
||||
#if USE_SSL
|
||||
# include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
# define debug_print g_debug
|
||||
|
@ -562,10 +559,6 @@ gboolean sock_has_read_data(SockInfo *sock)
|
|||
#ifdef G_OS_WIN32
|
||||
gulong val;
|
||||
|
||||
#if USE_SSL
|
||||
if (sock->ssl)
|
||||
return TRUE;
|
||||
#endif
|
||||
if (ioctlsocket(sock->sock, FIONREAD, &val) < 0) {
|
||||
g_warning("sock_has_read_data(): ioctlsocket() failed: %d\n",
|
||||
WSAGetLastError());
|
||||
|
@ -595,22 +588,6 @@ static gboolean sock_check(GSource *source)
|
|||
fd_set fds;
|
||||
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_SET(sock->sock, &fds);
|
||||
|
||||
|
@ -647,19 +624,6 @@ guint sock_add_watch(SockInfo *sock, GIOCondition condition, SockFunc func,
|
|||
sock->callback = func;
|
||||
sock->condition = condition;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1375,10 +1339,6 @@ gint sock_read(SockInfo *sock, gchar *buf, gint len)
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1394,44 +1354,10 @@ gint fd_read(gint fd, gchar *buf, gint len)
|
|||
#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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1459,34 +1385,10 @@ gint fd_write(gint fd, const gchar *buf, gint len)
|
|||
#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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1506,24 +1408,6 @@ gint fd_write_all(gint fd, const gchar *buf, gint len)
|
|||
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)
|
||||
{
|
||||
#ifdef G_OS_WIN32
|
||||
|
@ -1570,38 +1454,10 @@ gint fd_gets(gint fd, gchar *buf, gint len)
|
|||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1630,42 +1486,11 @@ gint fd_getline(gint fd, gchar **line)
|
|||
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)
|
||||
{
|
||||
g_return_val_if_fail(sock != 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);
|
||||
}
|
||||
|
||||
|
@ -1679,44 +1504,10 @@ gint sock_puts(SockInfo *sock, const gchar *buf)
|
|||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1727,11 +1518,6 @@ gint sock_close(SockInfo *sock)
|
|||
if (!sock)
|
||||
return 0;
|
||||
|
||||
#if USE_SSL
|
||||
if (sock->ssl)
|
||||
ssl_done_socket(sock);
|
||||
#endif
|
||||
|
||||
if (sock->sock_ch) {
|
||||
g_io_channel_shutdown(sock->sock_ch, FALSE, NULL);
|
||||
g_io_channel_unref(sock->sock_ch);
|
||||
|
@ -1759,13 +1545,4 @@ gint fd_close(gint fd)
|
|||
#endif
|
||||
}
|
||||
|
||||
#if USE_SSL
|
||||
void ssl_done_socket(SockInfo *sockinfo)
|
||||
{
|
||||
if (sockinfo->ssl) {
|
||||
SSL_free(sockinfo->ssl);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
|
||||
typedef struct _SockInfo SockInfo;
|
||||
|
||||
#if USE_SSL
|
||||
# include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CONN_READY,
|
||||
|
@ -42,11 +38,6 @@ typedef gboolean (*SockFunc) (SockInfo *sock,
|
|||
struct _SockInfo
|
||||
{
|
||||
gint sock;
|
||||
#if USE_SSL
|
||||
SSL *ssl;
|
||||
#else
|
||||
gpointer ssl;
|
||||
#endif
|
||||
GIOChannel *sock_ch;
|
||||
|
||||
gchar *hostname;
|
||||
|
@ -111,15 +102,4 @@ gint fd_gets (gint sock, gchar *buf, gint len);
|
|||
gint fd_getline (gint sock, gchar **line);
|
||||
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__ */
|
||||
|
|
144
midori/sokoke.c
144
midori/sokoke.c
|
@ -64,13 +64,15 @@ sokoke_js_script_eval (JSContextRef js_context,
|
|||
{
|
||||
gchar* value;
|
||||
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 (script, FALSE);
|
||||
|
||||
JSStringRef js_script = JSStringCreateWithUTF8CString (script);
|
||||
JSValueRef js_exception = NULL;
|
||||
JSValueRef js_value = JSEvaluateScript (js_context, js_script,
|
||||
js_script = JSStringCreateWithUTF8CString (script);
|
||||
js_value = JSEvaluateScript (js_context, js_script,
|
||||
JSContextGetGlobalObject (js_context), NULL, 0, &js_exception);
|
||||
JSStringRelease (js_script);
|
||||
|
||||
|
@ -649,7 +651,7 @@ sokoke_magic_uri (const gchar* uri)
|
|||
|
||||
/* Add file:// if we have a local path */
|
||||
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 */
|
||||
if (!strncmp (uri, "geo:", 4))
|
||||
{
|
||||
|
@ -684,7 +686,7 @@ sokoke_magic_uri (const gchar* uri)
|
|||
search = NULL;
|
||||
if (!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);
|
||||
if ((!strcmp (uri, "localhost") || strchr (uri, '/'))
|
||||
&& sokoke_resolve_hostname (uri))
|
||||
|
@ -793,7 +795,6 @@ sokoke_xfce_header_new (const gchar* icon,
|
|||
if (sokoke_get_desktop () == SOKOKE_DESKTOP_XFCE)
|
||||
{
|
||||
GtkWidget* entry;
|
||||
GtkStyle* style;
|
||||
gchar* markup;
|
||||
GtkWidget* xfce_heading;
|
||||
GtkWidget* hbox;
|
||||
|
@ -804,9 +805,7 @@ sokoke_xfce_header_new (const gchar* icon,
|
|||
|
||||
xfce_heading = gtk_event_box_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);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
|
||||
if (icon)
|
||||
|
@ -816,8 +815,6 @@ sokoke_xfce_header_new (const gchar* icon,
|
|||
GTK_ICON_SIZE_DIALOG);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
|
||||
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>",
|
||||
title);
|
||||
gtk_label_set_markup (GTK_LABEL (label), markup);
|
||||
|
@ -826,6 +823,16 @@ sokoke_xfce_header_new (const gchar* icon,
|
|||
g_free (markup);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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:
|
||||
* @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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -121,10 +121,6 @@ sokoke_action_create_popup_menu_item (GtkAction* action);
|
|||
gint64
|
||||
sokoke_time_t_to_julian (const time_t* timestamp);
|
||||
|
||||
gint
|
||||
sokoke_days_between (const time_t* day1,
|
||||
const time_t* day2);
|
||||
|
||||
const gchar*
|
||||
sokoke_set_config_dir (const gchar* new_config_dir);
|
||||
|
||||
|
@ -202,4 +198,8 @@ sokoke_build_thumbnail_path (const gchar* name);
|
|||
gchar*
|
||||
midori_download_prepare_tooltip_text (WebKitDownload* download);
|
||||
|
||||
void
|
||||
sokoke_entry_set_clear_button_visible (GtkEntry* entry,
|
||||
gboolean visible);
|
||||
|
||||
#endif /* !__SOKOKE_H__ */
|
||||
|
|
|
@ -7,7 +7,7 @@ import platform
|
|||
|
||||
progressive = True
|
||||
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'
|
||||
|
||||
if progressive or Options.commands['check']:
|
||||
|
|
|
@ -925,11 +925,7 @@ midori_bookmarks_init (MidoriBookmarks* bookmarks)
|
|||
gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry),
|
||||
GTK_ICON_ENTRY_PRIMARY,
|
||||
GTK_STOCK_FIND);
|
||||
gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry),
|
||||
GTK_ICON_ENTRY_SECONDARY,
|
||||
GTK_STOCK_CLEAR);
|
||||
gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (entry),
|
||||
GTK_ICON_ENTRY_SECONDARY, TRUE);
|
||||
sokoke_entry_set_clear_button_visible (GTK_ENTRY (entry), TRUE);
|
||||
g_signal_connect (entry, "icon-release",
|
||||
G_CALLBACK (midori_bookmarks_filter_entry_clear_cb), bookmarks);
|
||||
g_signal_connect (entry, "changed",
|
||||
|
|
|
@ -116,18 +116,59 @@ midori_history_get_stock_id (MidoriViewable* viewable)
|
|||
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*
|
||||
midori_history_format_date (KatzeItem *item)
|
||||
{
|
||||
gint age;
|
||||
gint64 day;
|
||||
gchar token[50];
|
||||
gint64 day = katze_item_get_added (item);
|
||||
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;
|
||||
|
||||
current_time = time (NULL);
|
||||
day = katze_item_get_added (item);
|
||||
|
||||
age = sokoke_days_between ((time_t*)&day, ¤t_time);
|
||||
|
||||
/* 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"));
|
||||
else
|
||||
sdate = g_strdup (_("Yesterday"));
|
||||
#endif
|
||||
return sdate;
|
||||
}
|
||||
|
||||
|
@ -412,9 +454,8 @@ midori_history_add_item_cb (KatzeArray* array,
|
|||
GtkTreeModel* model = gtk_tree_view_get_model (treeview);
|
||||
GtkTreeIter iter;
|
||||
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))
|
||||
{
|
||||
gint64 day;
|
||||
|
@ -423,7 +464,18 @@ midori_history_add_item_cb (KatzeArray* array,
|
|||
gtk_tree_model_get (model, &iter, 0, &today, -1);
|
||||
|
||||
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, ¤t_time) == 0;
|
||||
#endif
|
||||
g_object_unref (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_PRIMARY,
|
||||
GTK_STOCK_FIND);
|
||||
gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry),
|
||||
GTK_ICON_ENTRY_SECONDARY,
|
||||
GTK_STOCK_CLEAR);
|
||||
gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (entry),
|
||||
GTK_ICON_ENTRY_SECONDARY,
|
||||
TRUE);
|
||||
sokoke_entry_set_clear_button_visible (GTK_ENTRY (entry), TRUE);
|
||||
g_signal_connect (entry, "icon-release",
|
||||
G_CALLBACK (midori_history_filter_entry_clear_cb), history);
|
||||
g_signal_connect (entry, "changed",
|
||||
|
|
|
@ -39,7 +39,9 @@ extensions/feed-panel/feed-panel.c
|
|||
extensions/feed-panel/feed-parse.c
|
||||
extensions/feed-panel/feed-rss.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/mouse-gestures.c
|
||||
extensions/shortcuts.c
|
||||
|
|
1613
po/pt_BR.po
1613
po/pt_BR.po
File diff suppressed because it is too large
Load diff
1443
po/zh_CN.po
1443
po/zh_CN.po
File diff suppressed because it is too large
Load diff
1121
po/zh_TW.po
1121
po/zh_TW.po
File diff suppressed because it is too large
Load diff
|
@ -94,6 +94,38 @@ browser_tooltips (void)
|
|||
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
|
||||
main (int argc,
|
||||
char** argv)
|
||||
|
@ -106,6 +138,7 @@ main (int argc,
|
|||
|
||||
g_test_add_func ("/browser/create", browser_create);
|
||||
g_test_add_func ("/browser/tooltips", browser_tooltips);
|
||||
g_test_add_func ("/browser/site_data", browser_site_data);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <midori/midori.h>
|
||||
|
||||
#define SM "http://www.searchmash.com/search/"
|
||||
#define HTTP_PREFIX "midori-unit-test-expected-http-prefix"
|
||||
|
||||
static void
|
||||
test_input (const gchar* input,
|
||||
|
@ -20,6 +21,7 @@ test_input (const gchar* input,
|
|||
{
|
||||
static KatzeArray* search_engines = NULL;
|
||||
gchar* uri;
|
||||
gchar* real_expected = NULL;
|
||||
|
||||
if (G_UNLIKELY (!search_engines))
|
||||
{
|
||||
|
@ -41,28 +43,29 @@ test_input (const gchar* input,
|
|||
uri = sokoke_magic_uri (input);
|
||||
if (!uri)
|
||||
{
|
||||
gchar** parts;
|
||||
gchar* keywords = NULL;
|
||||
const gchar* keywords = NULL;
|
||||
const gchar* search_uri = NULL;
|
||||
KatzeItem* item;
|
||||
|
||||
/* Do we have a keyword and a string? */
|
||||
parts = g_strsplit (input, " ", 2);
|
||||
if (parts[0])
|
||||
if ((item = katze_array_find_token (search_engines, input)))
|
||||
{
|
||||
KatzeItem* item;
|
||||
if ((item = katze_array_find_token (search_engines, parts[0])))
|
||||
{
|
||||
keywords = g_strdup (parts[1] ? parts[1] : "");
|
||||
search_uri = katze_item_get_uri (item);
|
||||
}
|
||||
keywords = strchr (input, ' ');
|
||||
if (keywords != NULL)
|
||||
keywords++;
|
||||
else
|
||||
keywords = "";
|
||||
search_uri = katze_item_get_uri (item);
|
||||
}
|
||||
g_strfreev (parts);
|
||||
|
||||
uri = keywords ? midori_uri_for_search (search_uri, keywords) : NULL;
|
||||
|
||||
g_free (keywords);
|
||||
uri = search_uri ? midori_uri_for_search (search_uri, keywords) : NULL;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -97,6 +100,13 @@ magic_uri_uri (void)
|
|||
/* test_input ("foo:f1o2o3@bar.baz", "http://f1o2o3: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";
|
||||
g_assert_cmpstr ("bugs.launchpad.net", ==, midori_uri_parse_hostname (uri, NULL));
|
||||
uri = "https://bugs.launchpad.net/midori";
|
||||
|
|
|
@ -154,13 +154,13 @@ properties_object_get_set (GObject* object)
|
|||
static void
|
||||
properties_object_test (gconstpointer object)
|
||||
{
|
||||
if (GTK_IS_OBJECT (object))
|
||||
if (GTK_IS_WIDGET (object))
|
||||
g_object_ref_sink ((GObject*)object);
|
||||
|
||||
properties_object_get_set ((GObject*)object);
|
||||
|
||||
if (GTK_IS_OBJECT (object))
|
||||
gtk_object_destroy (GTK_OBJECT (object));
|
||||
if (GTK_IS_WIDGET (object))
|
||||
gtk_widget_destroy (GTK_WIDGET (object));
|
||||
g_object_unref ((GObject*)object);
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,6 @@ midori_findbar_entry_clear_icon_released_cb (GtkIconEntry* entry,
|
|||
{
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
@ -265,8 +264,7 @@ midori_findbar_init (MidoriFindbar* findbar)
|
|||
gtk_toolbar_insert (GTK_TOOLBAR (findbar), toolitem, -1);
|
||||
findbar->find_text = gtk_icon_entry_new ();
|
||||
midori_findbar_set_icon (findbar, GTK_ICON_ENTRY_PRIMARY, "edit-find");
|
||||
gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (findbar->find_text),
|
||||
GTK_ICON_ENTRY_SECONDARY, TRUE);
|
||||
sokoke_entry_set_clear_button_visible (GTK_ENTRY (findbar->find_text), TRUE);
|
||||
g_signal_connect (findbar->find_text, "icon-release",
|
||||
G_CALLBACK (midori_findbar_entry_clear_icon_released_cb), findbar);
|
||||
g_signal_connect (findbar->find_text, "activate",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#! /bin/sh
|
||||
|
||||
# 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
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -23,17 +24,30 @@
|
|||
# a bit of configuration
|
||||
root_dir=$MINGW_PREFIX
|
||||
|
||||
if [ "$MINGW_PREFIX" == "" ]; then
|
||||
echo "Warning! MINGW_PREFIX variable is empty!"
|
||||
sleep 5s
|
||||
fi
|
||||
|
||||
# create temporary working directory
|
||||
temp_dir=`mktemp -d`
|
||||
|
||||
# check if we can use 7zip
|
||||
have_7zip=`which 7za`
|
||||
|
||||
if [ "$1" != "" ]; then
|
||||
if [ "$1" == "debug" ]; then
|
||||
DEBUG_BUILD=1
|
||||
else
|
||||
version_tag=$1
|
||||
fi
|
||||
fi
|
||||
|
||||
# generate unique filename
|
||||
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
|
||||
ARCHIVE=midori$1-`date +%Y%m%d%H%M`.zip
|
||||
ARCHIVE=midori$version_tag-`date +%Y%m%d%H%M`.zip
|
||||
fi
|
||||
|
||||
# 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`" ]
|
||||
do
|
||||
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
|
||||
done
|
||||
|
||||
|
@ -64,16 +78,36 @@ dll_recursive ()
|
|||
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 ."
|
||||
|
||||
# create destination folder
|
||||
mkdir $temp_dir/midori$1
|
||||
workdir=$temp_dir/midori$version_tag
|
||||
mkdir $workdir
|
||||
|
||||
echo -n .
|
||||
|
||||
# auto generate dll list, only of existing files
|
||||
pushd $root_dir/bin > /dev/null
|
||||
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`
|
||||
rm $temp_dir/midori.exe.lst
|
||||
popd > /dev/null
|
||||
|
@ -82,46 +116,80 @@ echo -n .
|
|||
|
||||
# copy auto generate dll list
|
||||
pushd $root_dir/bin > /dev/null
|
||||
mkdir $temp_dir/midori$1/bin
|
||||
cp $files $temp_dir/midori$1/bin
|
||||
mkdir $workdir/bin
|
||||
cp -L $files $workdir/bin
|
||||
popd > /dev/null
|
||||
|
||||
echo -n .
|
||||
|
||||
# copy etc
|
||||
pushd $root_dir > /dev/null
|
||||
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/{} ";"
|
||||
popd > /dev/null
|
||||
grab_files etc midori
|
||||
grab_files etc gtkrc
|
||||
|
||||
# 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 .
|
||||
|
||||
# copy lib
|
||||
pushd $root_dir > /dev/null
|
||||
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/{} ";"
|
||||
popd > /dev/null
|
||||
grab_files lib midori
|
||||
grab_files lib gtk-2.0
|
||||
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 .
|
||||
|
||||
# copy share
|
||||
pushd $root_dir > /dev/null
|
||||
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 midori
|
||||
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
|
||||
# so we have translated stock items, file dialogs
|
||||
|
||||
find share "(" -name "midori.mo" ")" > locale.list
|
||||
mkdir -p $temp_dir/midori$1/share/locale/
|
||||
for LOCALE in $(cat locale.list); do
|
||||
pushd $root_dir > /dev/null
|
||||
find share "(" -name "midori.mo" ")" > $temp_dir/locale.list
|
||||
mkdir -p $workdir/share/locale/
|
||||
for LOCALE in $(cat $temp_dir/locale.list); do
|
||||
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
|
||||
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
|
||||
|
||||
echo -n .
|
||||
|
||||
# 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 .
|
||||
|
||||
|
@ -130,9 +198,9 @@ ARCHIVE=`pwd`/$ARCHIVE
|
|||
# store as zip/7z file
|
||||
pushd $temp_dir > /dev/null
|
||||
if [ "$have_7zip" != "" ]; then
|
||||
7za a -m0=lzma -mx=9 $ARCHIVE midori$1
|
||||
7za a -m0=lzma $ARCHIVE midori$version_tag
|
||||
else
|
||||
zip -rq $ARCHIVE midori$1
|
||||
zip -rq $ARCHIVE midori$version_tag
|
||||
fi
|
||||
popd > /dev/null
|
||||
|
||||
|
|
15
wscript
15
wscript
|
@ -29,7 +29,7 @@ from Configure import find_program_impl
|
|||
|
||||
major = 0
|
||||
minor = 4
|
||||
micro = 3
|
||||
micro = 4
|
||||
|
||||
APPNAME = 'midori'
|
||||
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 False
|
||||
|
||||
def is_win32 (env):
|
||||
return is_mingw (env) or Options.platform == 'win32'
|
||||
|
||||
# Compile Win32 res files to (resource) object files
|
||||
def rc_file(self, node):
|
||||
rctask = self.create_task ('winrc')
|
||||
|
@ -109,7 +112,7 @@ def configure (conf):
|
|||
else:
|
||||
icons = 'no '
|
||||
|
||||
if is_mingw (conf.env) or Options.platform == 'win32':
|
||||
if is_win32 (conf.env):
|
||||
conf.find_program ('windres', var='WINRC')
|
||||
conf.env['platform'] = 'win32'
|
||||
|
||||
|
@ -271,8 +274,6 @@ def configure (conf):
|
|||
if not conf.env['HAVE_UNIQUE']:
|
||||
if Options.platform == 'win32':
|
||||
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.check (header_name='sys/wait.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)
|
||||
|
||||
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 ('addons', 'building of extensions', group)
|
||||
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/*')
|
||||
|
||||
for desktop in [APPNAME + '.desktop', APPNAME + '-private.desktop']:
|
||||
if is_mingw (bld.env) or Options.platform == 'win32':
|
||||
if is_win32 (bld.env):
|
||||
break
|
||||
if bld.env['HAVE_HILDON']:
|
||||
appdir = '${MDATADIR}/applications/hildon'
|
||||
|
@ -497,7 +498,7 @@ def build (bld):
|
|||
else:
|
||||
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_as ( \
|
||||
'${MDATADIR}/' + APPNAME + '/res/speeddial-head-%s.html' % VERSION, \
|
||||
|
|
Loading…
Reference in a new issue