summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/dwb-js.747
-rw-r--r--api/jsapi.7.txt17
-rw-r--r--api/jsapi.txt35
-rw-r--r--doc/dwb.112
-rw-r--r--doc/dwb.1.txt4
-rw-r--r--extensions/formfiller552
-rw-r--r--extensions/unique_tabs125
-rw-r--r--extensions/userscripts760
-rw-r--r--scripts/lib/dwb.js2
-rw-r--r--scripts/lib/signals.js6
-rw-r--r--scripts/lib/util.js1
-rw-r--r--src/adblock.c3
-rw-r--r--src/commands.c21
-rw-r--r--src/config.h2
-rw-r--r--src/dom.c121
-rw-r--r--src/dom.h26
-rw-r--r--src/dwb.c256
-rw-r--r--src/dwb.h5
-rw-r--r--src/editor.c177
-rw-r--r--src/editor.h24
-rw-r--r--src/plugins.c3
-rw-r--r--src/scripts.c12
-rw-r--r--src/scripts.h1
-rw-r--r--src/view.c5
-rw-r--r--util/settings.pre1
25 files changed, 1328 insertions, 890 deletions
diff --git a/api/dwb-js.7 b/api/dwb-js.7
index 8964b910..5e0e6959 100644
--- a/api/dwb-js.7
+++ b/api/dwb-js.7
@@ -2,12 +2,12 @@
.\" Title: dwb-js
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.77.1 <http://docbook.sf.net/>
-.\" Date: 01/17/2013
+.\" Date: 01/28/2013
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
-.TH "DWB\-JS" "7" "01/17/2013" "\ \&" "\ \&"
+.TH "DWB\-JS" "7" "01/28/2013" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -90,6 +90,11 @@ for details\&.
.RS 4
Refers to the global object
.RE
+.PP
+\fIsession (SoupSession, read)\fR
+.RS 4
+The webkit session
+.RE
.SS "Methods"
.sp
.it 1 an-trap
@@ -457,7 +462,7 @@ Either the function or the optional name passed to bind\&.
.PP
\fIreturns\fR
.RS 4
-true if the function is unbinded
+true if the function was unbound
.RE
.RE
.SH "GLOBAL OBJECTS"
@@ -2456,6 +2461,42 @@ The Download
.nr an-break-flag 1
.br
.ps +1
+\fBexecuteCommand\fR
+.RS 4
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+signals\&.connect("executeCommand", function(detail));
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+Emitted before a command is executed, return true to prevent the execution\&.
+.PP
+\fIdetail\&.command\fR
+.RS 4
+The command that is executed\&.
+.RE
+.PP
+\fIdetail\&.argument\fR
+.RS 4
+The command that is executed\&.
+.RE
+.PP
+\fIdetail\&.nummod\fR
+.RS 4
+The numerical modifier, will be \-1 if no numerical modifier was used\&.
+.RE
+.RE
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
\fBframeCreated\fR
.RS 4
.sp
diff --git a/api/jsapi.7.txt b/api/jsapi.7.txt
index ec361e4d..8a0dce57 100644
--- a/api/jsapi.7.txt
+++ b/api/jsapi.7.txt
@@ -45,6 +45,7 @@ properties on the global object, see also *Global data* for details.
=== Properties
_global (Object, read)_;; Refers to the global object
+_session (SoupSession, read)_;; The webkit session
=== Methods ===
@@ -228,7 +229,7 @@ _returns_;; true if the timer was stopped
Unbind a shortcut that was previously binded with bind
_func_ or _name_;; Either the function or the optional name passed to bind.
-_returns_;; true if the function is unbinded
+_returns_;; true if the function was unbound
****
@@ -413,7 +414,6 @@ _n_;; Number of the tab
_returns_;; The corresponding webview
****
-
=== util ===
The util object implements helper methods.
@@ -1223,6 +1223,19 @@ Emitted when the DownloadStatus changes.
_download_;; The Download
****
+==== executeCommand
+****
+----
+signals.connect("executeCommand", function(detail));
+----
+
+Emitted before a command is executed, return true to prevent the execution.
+
+_detail.command_;; The command that is executed.
+_detail.argument_;; The command that is executed.
+_detail.nummod_;; The numerical modifier, will be -1 if no numerical modifier
+was used.
+****
==== frameCreated
****
diff --git a/api/jsapi.txt b/api/jsapi.txt
index efe43ff3..cefefed5 100644
--- a/api/jsapi.txt
+++ b/api/jsapi.txt
@@ -52,6 +52,18 @@ global object read
Refers to the global object.
****
+****
+[float]
+==== *session* ====
+
+[source,javascript]
+----
+session SoupSession read
+----
+
+The webkit session.
+****
+
=== Methods ===
@@ -312,7 +324,7 @@ Unbind a shortcut that was previously binded with <<bind>>
::
_func_ or _name_;; Either the function or the optional name passed to <<bind>>.
-_returns_;; +true+ if the function is unbinded
+_returns_;; +true+ if the function was unbound
****
======
@@ -758,7 +770,6 @@ _n_;; Number of the tab
_returns_;; The corresponding <<webview>>
****
-
====
.Example
[source,javascript]
@@ -2329,6 +2340,26 @@ Emitted when the <<DownloadStatus>> changes.
_download_;; The <<Download>>
****
+****
+[[executeCommand]]
+[float]
+==== *executeCommand* ====
+
+[source,javascript]
+----
+Boolean callback(detail)
+----
+
+Emitted before a command is executed, return true to prevent the execution.
+
+ ::
+
+_detail.command_;; The command that is executed.
+_detail.argument_;; The command that is executed.
+_detail.nummod_;; The numerical modifier, will be -1 if no numerical modifier
+was used.
+****
+
****
[[frameCreated]]
diff --git a/doc/dwb.1 b/doc/dwb.1
index ce26f371..2ec2fedf 100644
--- a/doc/dwb.1
+++ b/doc/dwb.1
@@ -2,12 +2,12 @@
.\" Title: dwb
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.77.1 <http://docbook.sf.net/>
-.\" Date: 01/09/2013
+.\" Date: 01/27/2013
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
-.TH "DWB" "1" "01/09/2013" "\ \&" "\ \&"
+.TH "DWB" "1" "01/27/2013" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -3038,6 +3038,14 @@ The value by which the zoom level is changed when zooming in or out\&. Possible
.RE
.SS "Other settings"
.PP
+\fBaccept\-language\fR
+.RS 4
+If set it will be used to set
+\fIAccept\-Language\fR
+header for all requests, default value:
+\fINULL\fR
+.RE
+.PP
\fBactive\-completion\-bg\-color\fR
.RS 4
The background color for an active element in tab\-completion\&. Possible values: an rgb color\-string, default value:
diff --git a/doc/dwb.1.txt b/doc/dwb.1.txt
index 23754700..05bb64f9 100644
--- a/doc/dwb.1.txt
+++ b/doc/dwb.1.txt
@@ -1148,6 +1148,10 @@ default value:
Other settings
~~~~~~~~~~~~~~
+*accept-language*::
+If set it will be used to set 'Accept-Language' header for all requests,
+default value:
+'NULL'
*active-completion-bg-color*::
The background color for an active element in tab-completion. Possible values:
diff --git a/extensions/formfiller b/extensions/formfiller
index acdeb6db..db417628 100644
--- a/extensions/formfiller
+++ b/extensions/formfiller
@@ -99,29 +99,29 @@ INFO>*/
var me = "formfiller";
var defaultConfig = {
//<DEFAULT_CONFIG
- // shortcut that gets and saves formdata
- scGetForm : "efg",
+// shortcut that gets and saves formdata
+scGetForm : "efg",
- // shortcut that fills a form
- scFillForm : "eff",
+// shortcut that fills a form
+scFillForm : "eff",
- // path to the formdata file
- formData : data.configDir + "/forms",
+// path to the formdata file
+formData : data.configDir + "/forms",
- // whether to use a gpg-encrypted file
- useGPG : false,
+// whether to use a gpg-encrypted file
+useGPG : false,
- // additional arguments passed to gpg2 when encrypting the formdata
- GPGOptEncrypt : "",
+// additional arguments passed to gpg2 when encrypting the formdata
+GPGOptEncrypt : "",
- // additional arguments passed to gpg2 when decrypting the formdata
- GPGOptDecrypt : "",
+// additional arguments passed to gpg2 when decrypting the formdata
+GPGOptDecrypt : "",
- // whether to save the password in memory when gpg is used
- keepPassword : true,
-
- // whether to save the whole formdata in memory when gpg is used
- keepFormdata : false
+// whether to save the password in memory when gpg is used
+keepPassword : true,
+
+// whether to save the whole formdata in memory when gpg is used
+keepFormdata : false
//>DEFAULT_CONFIG
};
@@ -129,286 +129,324 @@ var config = {};
var passWord = null;
var formData = null;
-var injectGetForm = function () {//{{{
- var ret = null;
- var forms = document.forms;
+var injectGetForm = function () //{{{
+{
+ var ret = null;
+ var forms = document.forms;
- function objectifyForm(f) {
- var query = "descendant::input[not(@type='hidden') and (@type='text' or @type='password' or @type='checkbox' or not(@type) or @type='email')]";
- var input, data;
- var r = document.evaluate(query, f, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
- var o = {};
- o.id = f.id || null;
- o.form = {};
- var hasValue = false;
- var hasIds = true;
+ function objectifyForm(f)
+ {
+ var query = "descendant::input[not(@type='hidden') and (@type='text' or @type='password' or @type='checkbox' or not(@type) or @type='email')]";
+ var input, data;
+ var r = document.evaluate(query, f, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
+ var o = {};
+ o.id = f.id || null;
+ o.form = {};
+ var hasValue = false;
+ var hasIds = true;
- while ((input = r.iterateNext()) !== null) {
- if (input.value && !(/^\s*$/.test(input.value))) {
- if (/^\**$/.test(input.value) )
- return null;
- if (!input.type || input.type.toLowerCase() === "text" || input.type.toLowerCase() === "password")
- hasValue = true;
- data = {};
- if (input.id)
- data.id = input.id;
- else
- hasIds = false;
- data.value = input.value;
- o.form[input.name] = data;
- }
- }
- if (hasValue) {
- var ret = {};
- o.hasIds = hasIds;
- ret[window.location.host] = o;
- return ret;
+ while ((input = r.iterateNext()) !== null)
+ {
+ if (input.value && !(/^\s*$/.test(input.value)))
+ {
+ if (/^\**$/.test(input.value) )
+ return null;
+ if (!input.type || input.type.toLowerCase() === "text" || input.type.toLowerCase() === "password")
+ hasValue = true;
+ data = {};
+ if (input.id)
+ data.id = input.id;
+ else
+ hasIds = false;
+ data.value = input.value;
+ o.form[input.name] = data;
+ }
+ }
+ if (hasValue)
+ {
+ var ret = {};
+ o.hasIds = hasIds;
+ ret[window.location.host] = o;
+ return ret;
+ }
+ return null;
}
- return null;
- }
- for (var i=0; i<forms.length; i++) {
- if ((ret = objectifyForm(forms[i])) !== null) {
- return ret;
+ for (var i=0; i<forms.length; i++)
+ {
+ if ((ret = objectifyForm(forms[i])) !== null)
+ return ret;
}
- }
- return ret;
+ return ret;
};//}}}
-var injectFillForm = function () {//{{{
- var key, i, forms, form = null, input;
- var data = arguments[0];
+var injectFillForm = function () //{{{
+{
+ var key, i, forms, form = null, input;
+ var data = arguments[0];
- function fillInput(input, key) {
- var value = data.form[key].value;
- if(input.type=="checkbox" || input.type=="radio")
- input.checked=(value.toLowerCase() !== "false" && value !== "0");
- else {
- input.value = value;
- }
- }
- function setValues(form) {
- var input, value;
- for (key in data.form) {
- if (!form[key])
- return null;
+ function fillInput(input, key)
+ {
+ var value = data.form[key].value;
+ if(input.type=="checkbox" || input.type=="radio")
+ input.checked=(value.toLowerCase() !== "false" && value !== "0");
+ else
+ input.value = value;
+
}
- for (key in data.form) {
- fillInput(form[key], key);
+ function setValues(form)
+ {
+ var input, value;
+ for (key in data.form)
+ {
+ if (!form[key])
+ return null;
+ }
+ for (key in data.form)
+ {
+ fillInput(form[key], key);
+ }
+ return form;
}
- return form;
- }
- function fillElementsById() {
- var input;
- for (key in data.form) {
- input = document.getElementById(data.form[key].id);
- if (input === null || input === undefined) {
- return null;
- }
- fillInput(input, key);
+ function fillElementsById()
+ {
+ var input;
+ for (key in data.form)
+ {
+ input = document.getElementById(data.form[key].id);
+ if (input === null || input === undefined)
+ return null;
+
+ fillInput(input, key);
+ }
+ return input.form || null;
}
- return input.form || null;
- }
- function fillFormById() {
- var form = document.getElementById(data.id);
+ function fillFormById()
+ {
+ var form = document.getElementById(data.id);
+ if (form === null)
+ return null;
+ return setValues(form);
+ }
+ if (data.hasIds)
+ form = fillElementsById();
+
+ if (form === null && data.id !== undefined && data.id !== null)
+ form = fillFormById();
+
if (form === null)
- return null;
- return setValues(form);
- }
- if (data.hasIds) {
- form = fillElementsById();
- }
- if (form === null && data.id !== undefined && data.id !== null) {
- form = fillFormById();
- }
- if (form === null) {
- forms = document.forms;
- for (i=0; i<forms.length && form === null; i++) {
- form = setValues(forms[i]);
+ {
+ forms = document.forms;
+ for (i=0; i<forms.length && form === null; i++)
+ {
+ form = setValues(forms[i]);
+ }
}
- }
- if (form !== null && data.autosubmit) {
- var buttons = form.querySelectorAll("[type='submit']");
- for (i=0; i<buttons.length; i++) {
- var e = buttons[i];
- var mouseEvent = e.ownerDocument.createEvent("MouseEvent");
- mouseEvent.initMouseEvent("click", false, true,
- e.ownerDocument.defaultView, 0, 0, 0, 0, 0, false, false, false, false,
- 0, null);
- e.dispatchEvent(mouseEvent);
+ if (form !== null && data.autosubmit)
+ {
+ var buttons = form.querySelectorAll("[type='submit']");
+ for (i=0; i<buttons.length; i++)
+ {
+ var e = buttons[i];
+ var mouseEvent = e.ownerDocument.createEvent("MouseEvent");
+ mouseEvent.initMouseEvent("click", false, true,
+ e.ownerDocument.defaultView, 0, 0, 0, 0, 0, false, false, false, false,
+ 0, null);
+ e.dispatchEvent(mouseEvent);
+ }
+ form.submit();
}
- form.submit();
- }
- return form !== null;
+ return form !== null;
};//}}}
-function getFormData(callback) {//{{{
- var stat, ret;
- if (config.useGPG) {
- if (formData !== null) {
- return formData;
- }
- getPassWord();
- stat = system.spawnSync("gpg2 " + config.GPGOptDecrypt + " --passphrase " + passWord + " --batch --no-tty --yes -d " + config.formData);
- if (stat.status == 512) {
- io.error("Wrong password");
- passWord = null;
- return null;
- }
- try {
- ret = JSON.parse(stat.stdout.replace(/\\"/g, '"'));
- if (config.keepFormdata) {
- formData = ret;
- }
- return ret;
- }
- catch(e) {
- io.debug({error : e, arguments : arguments});
- io.error("Getting form data failed : " + e.message);
- }
- }
- else {
- try {
- return JSON.parse(io.read(config.formData));
+function getFormData(callback) //{{{
+{
+ var stat, ret;
+ if (config.useGPG)
+ {
+ if (formData !== null)
+ return formData;
+
+ getPassWord();
+ stat = system.spawnSync("gpg2 " + config.GPGOptDecrypt + " --passphrase " + passWord + " --batch --no-tty --yes -d " + config.formData);
+ if (stat.status == 512)
+ {
+ io.error("Wrong password");
+ passWord = null;
+ return null;
+ }
+ try
+ {
+ ret = JSON.parse(stat.stdout.replace(/\\"/g, '"'));
+ if (config.keepFormdata)
+ formData = ret;
+
+ return ret;
+ }
+ catch(e)
+ {
+ io.debug({error : e, arguments : arguments});
+ io.error("Getting form data failed : " + e.message);
+ }
}
- catch(e) {
- io.debug({error : e, arguments : arguments});
- io.error("Getting form data failed : " + e.message);
+ else
+ {
+ try
+ {
+ return JSON.parse(io.read(config.formData));
+ }
+ catch(e)
+ {
+ io.debug({error : e, arguments : arguments});
+ io.error("Getting form data failed : " + e.message);
+ }
}
- }
- return null;
+ return null;
}//}}}
-function getPassWord() {//{{{
- if (passWord === null) {
- passWord = io.prompt("Password :", false);
- }
+function getPassWord() //{{{
+{
+ if (passWord === null)
+ passWord = io.prompt("Password :", false);
}//}}}
-function writeFormData(object) {//{{{
- var written = true, ret;
- if (config.useGPG) {
- getPassWord();
- if (passWord === null)
- return false;
+function writeFormData(object) //{{{
+{
+ var written = true, ret;
+ if (config.useGPG)
+ {
+ getPassWord();
+ if (passWord === null)
+ return false;
- ret = system.spawnSync("sh -c \"echo '" + JSON.stringify(object).replace(/"/g, "\\\"") +
- "' | gpg2 " + config.GPGOptEncrypt + " --passphrase " + passWord + " --batch --no-tty --yes -c --output " + config.formData + "\"");
- if (ret.status == 512) {
- io.error("Wrong password");
- password = null;
- return false;
+ ret = system.spawnSync("sh -c \"echo '" + JSON.stringify(object).replace(/"/g, "\\\"") +
+ "' | gpg2 " + config.GPGOptEncrypt + " --passphrase " + passWord + " --batch --no-tty --yes -c --output " + config.formData + "\"");
+ if (ret.status == 512)
+ {
+ io.error("Wrong password");
+ password = null;
+ return false;
+ }
+ written = ret.status === 0;
}
- written = ret.status === 0;
- }
- else {
- written = io.write(config.formData, "w", JSON.stringify(object, null, 2));
- }
- return written;
+ else
+ written = io.write(config.formData, "w", JSON.stringify(object, null, 2));
+
+ return written;
}//}}}
-function saveForm(form) {//{{{
- var key, object, data, written = false;
- var autosubmit = io.prompt("Autosubmit (y/n)?").toLowerCase() == "y" ? true : false;
- var saved = false;
- if (! system.fileTest(config.formData, FileTest.regular | FileTest.symlink)) {
- object = JSON.parse(form);
- for (key in object)
- break;
- object[key].autosubmit = autosubmit;
- written = writeFormData(object);
- }
- else {
- object = JSON.parse(form);
- data = getFormData();
- if (data) {
- for (key in object)
- break;
- data[key] = object[key];
- data[key].autosubmit = autosubmit;
- }
- else if (data === null) {
- return false;
+function saveForm(form) //{{{
+{
+ var key, object, data, written = false;
+ var autosubmit = io.prompt("Autosubmit (y/n)?").toLowerCase() == "y" ? true : false;
+ var saved = false;
+ if (! system.fileTest(config.formData, FileTest.regular | FileTest.symlink))
+ {
+ object = JSON.parse(form);
+ for (key in object)
+ break;
+ object[key].autosubmit = autosubmit;
+ written = writeFormData(object);
}
- else {
- data = object;
+ else
+ {
+ object = JSON.parse(form);
+ data = getFormData();
+ if (data)
+ {
+ for (key in object)
+ break;
+ data[key] = object[key];
+ data[key].autosubmit = autosubmit;
+ }
+ else if (data === null)
+ return false;
+ else
+ data = object;
+
+ written = writeFormData(data);
}
- written = writeFormData(data);
- }
- return written;
+ return written;
}//}}}
-function getForm() {//{{{
- var frames = tabs.current.allFrames;
- var form, i, formFound = false;
- for (i=0; i<frames.length; i++) {
- form = frames[i].inject(util.getBody(injectGetForm));
- if (form != "null") {
- if (saveForm(form)) {
- io.notify("Form saved");
- }
- else {
- io.notify("An error occured saving formdata");
- }
- formFound = true;
- break;
+function getForm() //{{{
+{
+ var frames = tabs.current.allFrames;
+ var form, i, formFound = false;
+ for (i=0; i<frames.length; i++)
+ {
+ form = frames[i].inject(util.getBody(injectGetForm));
+ if (form != "null")
+ {
+ if (saveForm(form))
+ io.notify("Form saved");
+ else
+ io.notify("An error occured saving formdata");
+ formFound = true;
+ break;
+ }
}
- }
- if (!config.keepPassword)
- passWord = null;
- if (!formFound)
- io.error("No storable form found");
+ if (!config.keepPassword)
+ passWord = null;
+ if (!formFound)
+ io.error("No storable form found");
}//}}}
-function getHasForms(frames) {//{{{
- var i;
- for (i=0; i<frames.length; i++) {
- if (frames[i].inject("return document.forms.length > 0;") == "true")
- return true;
- }
- return false;
+function getHasForms(frames) //{{{
+{
+ var i;
+ for (i=0; i<frames.length; i++)
+ {
+ if (frames[i].inject("return document.forms.length > 0;") == "true")
+ return true;
+ }
+ return false;
}//}}}
-function fillForm() {//{{{
- var data, frames, host, i, ret = false;
- if (! system.fileTest(config.formData, FileTest.regular | FileTest.symlink)) {
- io.error("No formdata found");
- return;
- }
- frames = tabs.current.allFrames;
- if (!getHasForms(frames)) {
- io.error("No form found");
- return;
- }
- data = getFormData();
-
- if (data === null)
- return;
- for (i=0; i<frames.length; i++) {
- host = frames[i].host;
- if (data[host]) {
- frames[i].inject(util.getBody(injectFillForm), data[host]);
+function fillForm() //{{{
+{
+ var data, frames, host, i, ret = false;
+ if (! system.fileTest(config.formData, FileTest.regular | FileTest.symlink))
+ {
+ io.error("No formdata found");
+ return;
+ }
+ frames = tabs.current.allFrames;
+ if (!getHasForms(frames))
+ {
+ io.error("No form found");
+ return;
+ }
+ data = getFormData();
+
+ if (data === null)
+ return;
+ for (i=0; i<frames.length; i++)
+ {
+ host = frames[i].host;
+ if (data[host])
+ frames[i].inject(util.getBody(injectFillForm), data[host]);
}
- }
- if (!config.keepPassword) {
- passWord = null;
- }
- io.notify("Executed formfiller");
+ if (!config.keepPassword)
+ passWord = null;
+
+ io.notify("Executed formfiller");
}//}}}
// init {{{
return {
- init : function (c) {
- config = extensions.getConfig(c, defaultConfig);
- bind(config.scGetForm, getForm, "formfillerGet");
- bind(config.scFillForm, fillForm, "formfillerFill");
- return true;
- },
- end : function () {
- unbind("formfillerGet");
- unbind("formfillerFill");
- return true;
- }
+ defaultConfig : defaultConfig,
+ init : function (c) {
+ config = c;
+ bind(config.scGetForm, getForm, "formfillerGet");
+ bind(config.scFillForm, fillForm, "formfillerFill");
+ return true;
+ },
+ end : function () {
+ unbind("formfillerGet");
+ unbind("formfillerFill");
+ return true;
+ }
}//}}}
// vim: set ft=javascript:
diff --git a/extensions/unique_tabs b/extensions/unique_tabs
new file mode 100644
index 00000000..cd52c659
--- /dev/null
+++ b/extensions/unique_tabs
@@ -0,0 +1,125 @@
+//
+// Copyright (c) 2013 Stefan Bolte <portix@gmx.net>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+//
+
+/*<INFO
+Remove duplicate tabs or avoid duplicate tabs by autoswitching to tabs with same url
+INFO>*/
+
+var defaultConfig = {
+//<DEFAULT_CONFIG
+// Shortcut that removes duplicate tabs
+shortcutRemoveDuplicates : null,
+
+// Command that removes duplicate tabs
+commandRemoveDuplicates : "ut_remove_duplicates",
+
+// Autofocus a tab if an url is already opened, if the url would be loaded in a
+// new tab the new tab is closed.
+// Setting this to true makes commandRemoveDuplicates and
+// shortcutRemoveDuplicates obsolete because there will be no duplicates.
+autoFocus : true,
+
+// Shortcut for toggling autofocus
+shortcutToggleAutoFocus : null,
+
+// Command for toggling autofocus
+commandToggleAutoFocus : "ut_toggle_autofocus",
+
+//>DEFAULT_CONFIG
+};
+
+var signalId = -1;
+
+var removeDuplicates = function()
+{
+ var uris = [];
+ for (var i=tabs.length-1; i>=0; --i)
+ {
+ var uri = tabs.nth(i).uri;
+ if (uris.fastIndexOf(uri) == -1)
+ uris.push(uri);
+ else
+ execute((i+1) + "close_tab");
+ }
+};
+var onNavigation = function(wv, frame, request)
+{
+ var uri = request.uri;
+ for (var i=tabs.length-1; i>=0; --i)
+ {
+ if (tabs.nth(i).uri == uri && i != wv.number)
+ {
+ execute((i+1) + "focus_tab");
+ if (/^\s*$/.test(wv.uri))
+ execute((wv.number + 1) + "close");
+ return true;
+ }
+ }
+ return false;
+};
+var connectAutoFocus = function()
+{
+ signalId = signals.connect("navigation", onNavigation);
+};
+var disconnectAutoFocus = function()
+{
+ if (signalId != -1)
+ {
+ signals.disconnect(signalId);
+ signalId = -1;
+ return true;
+ }
+ return false;
+};
+var toggleAutoFocus = function()
+{
+ if (disconnectAutoFocus())
+ io.notify("unique_tabs: autofocus disabled");
+ else
+ {
+ io.notify("unique_tabs: autofocus enabled");
+ connectAutoFocus();
+ }
+};
+
+return {
+ defaultConfig : defaultConfig,
+ init : function(c) {
+ if (c.shortcutRemoveDuplicates || c.commandRemoveDuplicates)
+ {
+ bind(c.shortcutRemoveDuplicates, removeDuplicates, c.commandRemoveDuplicates);
+ }
+ if (c.shortcutToggleAutoFocus || c.commandToggleAutoFocus)
+ {
+ bind(c.shortcutToggleAutoFocus, toggleAutoFocus, c.commandToggleAutoFocus);
+ }
+
+ if (c.autoFocus)
+ connectAutoFocus();
+ return true;
+ },
+ end : function() {
+ unbind(removeDuplicates);
+ unbind(toggleAutoFocus);
+ disconnectAutoFocus();
+ return true;
+ }
+}
+
+// vim:set ft=javascript:
diff --git a/extensions/userscripts b/extensions/userscripts
index e256bbe6..14b98a59 100644
--- a/extensions/userscripts
+++ b/extensions/userscripts
@@ -70,7 +70,7 @@ var sigCommitted = -1;
/*
//<DEFAULT_CONFIG
// paths to userscripts, this extension will also load all scripts in from
- // $XDG_CONFIG_HOME/.config/dwb/scripts
+ // $XDG_CONFIG_HOME/scripts
scripts : []
//>DEFAULT_CONFIG
*/
@@ -85,449 +85,471 @@ UserScript.prototype = new Function();
UserScript.prototype.constructor = UserScript;
function UserScript()
{
- this.description = null;
- this.downloadURL = null;
- this.exclude = [];
- this.icon = null;
- this.include = [];
- this.match = [];
- this.name = null;
- this.namespace = null;
- this.require = [];
- this.resource = [];
- this.runAt = "document-end";
- this.unwrap = false;
- this.updateURL = null;
- this.version = null;
- this.script = null;
- this.scriptId = null;
- // scriptish
- this.delay = 0;
- this.noframes = false;
- this.priority = 0;
+ this.description = null;
+ this.downloadURL = null;
+ this.exclude = [];
+ this.icon = null;
+ this.include = [];
+ this.match = [];
+ this.name = null;
+ this.namespace = null;
+ this.require = [];
+ this.resource = [];
+ this.runAt = "document-end";
+ this.unwrap = false;
+ this.updateURL = null;
+ this.version = null;
+ this.script = null;
+ this.scriptId = null;
+ // scriptish
+ this.delay = 0;
+ this.noframes = false;
+ this.priority = 0;
}
// Reused regular expressions
var regexes = {
- isTld : /\.tld(?:\/|:|$)/,
- isRegExp : /^\/.*\/$/
+ isTld : /\.tld(?:\/|:|$)/,
+ isRegExp : /^\/.*\/$/
};
-var GM_compatability = function () {
- var DWB_scriptPrefix = "dwb_userscript_";
- if (DWB_scriptId !== undefined) {
- DWB_scriptPrefix = DWB_scriptPrefix + DWB_scriptId + "_";
- }
- var GM_addStyle = function (styles)
- {
- var style = document.createElement("style");
- style.setAttribute("type", "text/css");
- style.appendChild(document.createTextNode(styles));
- document.getElementsByTagName("head")[0].appendChild(style);
- };
- var GM_log = function (text) {
- console.log(text);
- };
- var GM_setValue = function (key, value) {
- if (localStorage !== null && (typeof value === "string" || typeof value === "number" || typeof value == "boolean") )
- localStorage.setItem(DWB_scriptPrefix + key, value);
- else
- GM_log("GM_setValue only works with enabled localStorage and only for strings, numbers and booleans");
- };
- var GM_getValue = function (key, def) {
- if (localStorage !== null)
- return localStorage.getItem(DWB_scriptPrefix + key) || def;
- else
- GM_log("GM_getValue only works with enabled localStorage");
- return undefined;
- };
- var GM_deleteValue = function (key) {
- if (localStorage !== null)
- localStorage.removeItem(DWB_scriptPrefix + key);
- else
- GM_log("GM_deleteValue only works with enabled localStorage");
- };
- var GM_listValues = function () {
- var i;
- var a = [];
- for (i=0; i<localStorage.length; i++) {
- a.push(localStorage.key(i).replace(DWB_scriptPrefix, ""));
+var GM_compatability = function ()
+{
+ var DWB_scriptPrefix = "dwb_userscript_";
+ if (DWB_scriptId !== undefined)
+ {
+ DWB_scriptPrefix = DWB_scriptPrefix + DWB_scriptId + "_";
}
- return a;
- };
- var GM_info = function () { return undefined; };
- var GM_registerMenuCommand = function () { return undefined; };
- var GM_openInTab = function (url) { return null; };
- var GM_getResourceText = function (name) {
- // TODO implemnt
- return "";
- };
- var GM_getResourceURL = function (name) {
- // TODO implemnt
- return "";
- };
- var GM_xmlHttpRequest = function (details) {
- // TODO implemnt
- return null;
- };
+ var GM_addStyle = function (styles)
+ {
+ var style = document.createElement("style");
+ style.setAttribute("type", "text/css");
+ style.appendChild(document.createTextNode(styles));
+ document.getElementsByTagName("head")[0].appendChild(style);
+ };
+ var GM_log = function (text)
+ {
+ console.log(text);
+ };
+ var GM_setValue = function (key, value)
+ {
+ if (localStorage !== null && (typeof value === "string" || typeof value === "number" || typeof value == "boolean") )
+ localStorage.setItem(DWB_scriptPrefix + key, value);
+ else
+ GM_log("GM_setValue only works with enabled localStorage and only for strings, numbers and booleans");
+ };
+ var GM_getValue = function (key, def)
+ {
+ if (localStorage !== null)
+ return localStorage.getItem(DWB_scriptPrefix + key) || def;
+ else
+ GM_log("GM_getValue only works with enabled localStorage");
+ return undefined;
+ };
+ var GM_deleteValue = function (key)
+ {
+ if (localStorage !== null)
+ localStorage.removeItem(DWB_scriptPrefix + key);
+ else
+ GM_log("GM_deleteValue only works with enabled localStorage");
+ };
+ var GM_listValues = function ()
+ {
+ var i;
+ var a = [];
+ for (i=0; i<localStorage.length; i++) {
+ a.push(localStorage.key(i).replace(DWB_scriptPrefix, ""));
+ }
+ return a;
+ };
+ var GM_info = function () { return undefined; };
+ var GM_registerMenuCommand = function () { return undefined; };
+ var GM_openInTab = function (url) { return null; };
+ var GM_getResourceText = function (name)
+ {
+ // TODO implemnt
+ return "";
+ };
+ var GM_getResourceURL = function (name)
+ {
+ // TODO implemnt
+ return "";
+ };
+ var GM_xmlHttpRequest = function (details)
+ {
+ // TODO implemnt
+ return null;
+ };
};
function matchIncludeExclude(frame, items) //{{{
{
- var uri = frame.uri;
- var domain = frame.domain;
- var i;
- for (i=0; i<items.length; i++) {
- try {
- if (items[i].isTld && domain !== null) {
- var reg = new RegExp("(?=.)" + domain + "($|/|:)");
- var newDomain = domain.substring(0, domain.indexOf(".")) + ".tld$1";
- uri = uri.replace(reg, newDomain);
- }
- if (items[i].regExp.test(uri)) {
- return true;
- }
- }
- catch(e) {
- extensions.error(me, e);
+ var uri = frame.uri;
+ var domain = frame.domain;
+ var i;
+ for (i=0; i<items.length; i++)
+ {
+ try
+ {
+ if (items[i].isTld && domain !== null)
+ {
+ var reg = new RegExp("(?=.)" + domain + "($|/|:)");
+ var newDomain = domain.substring(0, domain.indexOf(".")) + ".tld$1";
+ uri = uri.replace(reg, newDomain);
+ }
+ if (items[i].regExp.test(uri))
+ return true;
+ }
+ catch(e)
+ {
+ extensions.error(me, e);
+ }
}
- }
- return false;
+ return false;
}//}}}
function matchMatches(frame, items) //{{{
{
- var i, item;
- var o = uriSplit(frame.uri);
- if (o === null)
- return false;
- for (i=0; i<items.length; i++) {
- item = items[i];
- if (item.allUrls ||
- (item.scheme.test(o.scheme) &&
- item.host.test(o.host) &&
- (o.path === null || item.path.test(o.path)))) {
- return true;
- }
+ var i, item;
+ var o = uriSplit(frame.uri);
+ if (o === null)
+ return false;
+ for (i=0; i<items.length; i++)
+ {
+ item = items[i];
+ if (item.allUrls ||
+ (item.scheme.test(o.scheme) &&
+ item.host.test(o.host) &&
+ (o.path === null || item.path.test(o.path))))
+ {
+ return true;
+ }
- }
+ }
return false;
}//}}}
-function doInject(frame, item) {
- if (item.delay > 0) {
- timerStart(item.delay, function() {
- frame.inject(item.script, null, item.unwrap);
- return false;
- });
+function doInject(frame, item)
+{
+ if (item.delay > 0)
+ {
+ timerStart(item.delay, function() {
+ frame.inject(item.script, null, item.unwrap);
+ return false;
+ });
}
- else {
+ else
frame.inject(item.script, null, item.unwrap);
- }
}
function handle(frame, array, isMainFrame) //{{{
{
- var i, item;
- for (i=0; i<array.length; i++) {
- item = array[i];
- if (item.noframes && !isMainFrame)
- continue;
- try {
- if (matchIncludeExclude(frame, item.exclude))
- continue;
-
- if (matchIncludeExclude(frame, item.include)) {
- doInject(frame, item);
- }
- else if (matchMatches(frame, item.match)) {
- doInject(frame, item);
- }
- }
- catch (e) {
- extensions.debug(me);
+ var i, item;
+ for (i=0; i<array.length; i++)
+ {
+ item = array[i];
+ if (item.noframes && !isMainFrame)
+ continue;
+ try
+ {
+ if (matchIncludeExclude(frame, item.exclude))
+ continue;
+
+ if (matchIncludeExclude(frame, item.include))
+ doInject(frame, item);
+ else if (matchMatches(frame, item.match))
+ doInject(frame, item);
+ }
+ catch (e)
+ {
+ extensions.debug(me);
+ }
}
- }
}//}}}
function loadFinishedCallback(wv, frame) //{{{
{
- handle(frame, onEnd, wv.mainFrame === frame);
+ handle(frame, onEnd, wv.mainFrame === frame);
}//}}}
function loadCommittedCallback(wv) //{{{
{
- handle(wv.mainFrame, onStart, true);
+ handle(wv.mainFrame, onStart, true);
}//}}}
function parseIncludeExclude(array) //{{{
{
- var i, rule;
- for (i=0; i<array.length; i++) {
- rule = array[i];
- if (regexes.isRegExp.test(rule)) {
- array[i] = {
- regExp : new RegExp(rule.substring(1, rule.length-1)),
- isTld : regexes.isTld.test(rule)
- };
- }
- else {
- array[i] = {
- regExp : new RegExp(rule.replace(/\*/g, ".*")),
- isTld : regexes.isTld.test(rule)
- };
+ var i, rule;
+ for (i=0; i<array.length; i++)
+ {
+ rule = array[i];
+ if (regexes.isRegExp.test(rule))
+ {
+ array[i] = {
+ regExp : new RegExp(rule.substring(1, rule.length-1)),
+ isTld : regexes.isTld.test(rule)
+ };
+ }
+ else
+ {
+ array[i] = {
+ regExp : new RegExp(rule.replace(/\*/g, ".*")),
+ isTld : regexes.isTld.test(rule)
+ };
+ }
}
- }
}//}}}
function uriSplit(uri)
{
- var parts, scheme, host, path, idx;
- parts = uri.split("://");
- if (parts[0] === uri)
- return null;
- scheme = parts[0];
- idx = parts[1].indexOf("/");
- if (idx == -1) {
- host = parts[1];
- path = null;
- }
- else {
- host = parts[1].substring(0, idx);
- path = parts[1].substring(idx);
- }
- return { path : path, host: host, scheme : scheme };
+ var parts, scheme, host, path, idx;
+ parts = uri.split("://");
+ if (parts[0] === uri)
+ return null;
+ scheme = parts[0];
+ idx = parts[1].indexOf("/");
+ if (idx == -1)
+ {
+ host = parts[1];
+ path = null;
+ }
+ else
+ {
+ host = parts[1].substring(0, idx);
+ path = parts[1].substring(idx);
+ }
+ return { path : path, host: host, scheme : scheme };
}
function parseMatch(m)
{
- var i, scheme, host, path, parts, j;
- if (m === "<all_urls>") {
- return { allUrls : true };
- }
+ var i, scheme, host, path, parts, j;
+ if (m === "<all_urls>") {
+ return { allUrls : true };
+ }
- var o = uriSplit(m);
- if (o === null) {
- extensions.warning(me, "Invalid or unsupported match rule: " + m);
- return null;
- }
- if (!(/\*|http|https|file/.test(o.scheme))) {
- extensions.warning(me, "Invalid scheme pattern: " + m);
- return null;
- }
- else {
- o.scheme = new RegExp(o.scheme.replace("*", ".*"));
- }
- if (! (/^(?:\*\.[^*\/]*|[^*]*|\*)$/.test(o.host))) {
- extensions.warning(me, "Invalid host pattern: " + m);
- return null;
- }
- else {
- o.host = new RegExp(o.host.replace(/([.?+^$[\]\\(){}|-])/g, "\\$1").replace("*", ".*"));
- }
- if (! (/^\/.*/.test(o.path))) {
- extensions.warning(me, "Invalid path pattern: " + m);
- return null;
- }
- else if (o.path !== null) {
- o.path = new RegExp(o.path.replace(/([.?+^$[\]\\(){}|-])/g, "\\$1").replace("*", ".*"));
- }
- return { host : o.host, scheme : o.scheme, path : o.path, allUrls : false };
+ var o = uriSplit(m);
+ if (o === null)
+ {
+ extensions.warning(me, "Invalid or unsupported match rule: " + m);
+ return null;
+ }
+ if (!(/\*|http|https|file/.test(o.scheme)))
+ {
+ extensions.warning(me, "Invalid scheme pattern: " + m);
+ return null;
+ }
+ else
+ o.scheme = new RegExp(o.scheme.replace("*", ".*"));
+
+ if (! (/^(?:\*\.[^*\/]*|[^*]*|\*)$/.test(o.host)))
+ {
+ extensions.warning(me, "Invalid host pattern: " + m);
+ return null;
+ }
+ else
+ o.host = new RegExp(o.host.replace(/([.?+^$[\]\\(){}|-])/g, "\\$1").replace("*", ".*"));
+
+ if (! (/^\/.*/.test(o.path)))
+ {
+ extensions.warning(me, "Invalid path pattern: " + m);
+ return null;
+ }
+ else if (o.path !== null)
+ o.path = new RegExp(o.path.replace(/([.?+^$[\]\\(){}|-])/g, "\\$1").replace("*", ".*"));
+
+ return { host : o.host, scheme : o.scheme, path : o.path, allUrls : false };
}
-function getRequirements(userscript) {//{{{
- var i;
- for (i=0; i<userscript.require.length; i++) {
- //io.print(userscript.require[i]);
- //sendRequest(userscript.require[0], function (response, message) {
- // ;
- // //io.print(response);
- //});
- //sendRequest(userscripts.require[i], function (response) {
- // io.print(response);
- //});
- }
+function getRequirements(userscript) //{{{
+{
+ var i;
+ for (i=0; i<userscript.require.length; i++) {
+ //io.print(userscript.require[i]);
+ //sendRequest(userscript.require[0], function (response, message) {
+ // ;
+ // //io.print(response);
+ //});
+ //sendRequest(userscripts.require[i], function (response) {
+ // io.print(response);
+ //});
+ }
}//}}}
function parseScript(path) //{{{
{
- var userscript;
- var i, items, key, value, idx, m, matches = [], numVal;
+ var userscript;
+ var i, items, key, value, idx, m, matches = [], numVal;
- var script = io.read(path);
- if (!script || (/^\s*$/).test(script))
- return;
+ var script = io.read(path);
+ if (!script || (/^\s*$/).test(script))
+ return;
- var metaStart = script.search(/(^|\n)\/\/\s*==UserScript==/);
- var metaEnd = script.search(/\n\/\/\s*==\/UserScript==/);
+ var metaStart = script.search(/(^|\n)\/\/\s*==UserScript==/);
+ var metaEnd = script.search(/\n\/\/\s*==\/UserScript==/);
- userscript = new UserScript();
+ userscript = new UserScript();
- if (metaStart == -1 || metaEnd == -1) {
- userscript.script = script;
- userscript.include = [ { regExp : /.*/, isTld : false} ];
- onEnd.push(userscript);
- return;
- }
+ if (metaStart == -1 || metaEnd == -1)
+ {
+ userscript.script = script;
+ userscript.include = [ { regExp : /.*/, isTld : false} ];
+ onEnd.push(userscript);
+ return;
+ }
- var meta = script.substring(metaStart, metaEnd).split("\n");
- var scriptStart = script.substring(metaEnd+1).indexOf("\n") + metaEnd + 1;
-
- var regValue = /\s[^\/@]\S?/;
- var regIsRule = /^\s*\/\/\s*@/;
- for (i=1; i<meta.length; i++) {
- if (! (regIsRule.test(meta[i])) )
- continue;
- try {
- items = meta[i].split(/\s+/, 2);
- key = items[1].substring(1).trim();
- idx = meta[i].search(regValue);
- value = idx >= 0 ? meta[i].substring(idx+1).trim() : null;
- if (key == "description" ||
- key == "downloadURL" ||
- key == "icon" ||
- key == "name" ||
- key == "namespace" ||
- key == "updateURL" ||
- key == "version")
- {
- userscript[key] = value;
- }
- else if (typeof userscript[key] == "number") {
- try {
- numVal = parseInt(value, 10);
- if (!isNaN(numVal))
- userscript[key] = numVal;
+ var meta = script.substring(metaStart, metaEnd).split("\n");
+ var scriptStart = script.substring(metaEnd+1).indexOf("\n") + metaEnd + 1;
+
+ var regValue = /\s[^\/@]\S?/;
+ var regIsRule = /^\s*\/\/\s*@/;
+ for (i=1; i<meta.length; i++)
+ {
+ if (! (regIsRule.test(meta[i])) )
+ continue;
+ try
+ {
+ items = meta[i].split(/\s+/, 2);
+ key = items[1].substring(1).trim();
+ idx = meta[i].search(regValue);
+ value = idx >= 0 ? meta[i].substring(idx+1).trim() : null;
+ if (key == "description" ||
+ key == "downloadURL" ||
+ key == "icon" ||
+ key == "name" ||
+ key == "namespace" ||
+ key == "updateURL" ||
+ key == "version")
+ {
+ userscript[key] = value;
+ }
+ else if (typeof userscript[key] == "number")
+ {
+ try
+ {
+ numVal = parseInt(value, 10);
+ if (!isNaN(numVal))
+ userscript[key] = numVal;
+ }
+ catch (e) {
+ extensions.debug(me, e);
+ }
+ }
+ else if (key == "unwrap")
+ userscript.unwrap = true;
+ else if (key == "noframes")
+ userscript.noframes = true;
+ else if (key == "run-at")
+ userscript.runAt = value;
+ else if (userscript[key] instanceof Array)
+ userscript[key] = userscript[key].concat(value.match(/\S+/g));
}
- catch (e) {
- extensions.debug(me, e);
+ catch(e)
+ {
+ extensions.debug(me, e);
}
- }
- else if (key == "unwrap")
- userscript.unwrap = true;
- else if (key == "noframes")
- userscript.noframes = true;
- else if (key == "run-at")
- userscript.runAt = value;
- else if (userscript[key] instanceof Array) {
- userscript[key] = userscript[key].concat(value.match(/\S+/g));
- }
- }
- catch(e) {
- extensions.debug(me, e);
- }
- }
- if (userscript.include.length === 0)
- userscript.include.push({regExp : /.*/, isTld : false});
- else
- parseIncludeExclude(userscript.include);
- parseIncludeExclude(userscript.exclude);
- // TODO resources
-
- var scriptId = new String();
- if (userscript.namespace === null || userscript.name === null)
- userscript.scriptId = path;
- else
- userscript.scriptId = userscript.namespace + "::" + userscript.name;
- userscript.scriptId = userscript.scriptId.replace(/\s+/g, "_");
- userscript.script = "var DWB_scriptId = '" + userscript.scriptId + "';" +
- util.getBody(GM_compatability) + script.substring(0, metaStart) +
- script.substring(scriptStart);
-
- getRequirements(userscript);
-
- for (i=0; i<userscript.match.length; i++) {
- m = parseMatch(userscript.match[i]);
- if (m !== null) {
- matches.push(m);
}
- }
- userscript.match = matches;
- if (userscript.runAt == "document-start")
- onStart.push(userscript);
- else
- onEnd.push(userscript);
+ if (userscript.include.length === 0)
+ userscript.include.push({regExp : /.*/, isTld : false});
+ else
+ parseIncludeExclude(userscript.include);
+ parseIncludeExclude(userscript.exclude);
+ // TODO resources
+
+ var scriptId = new String();
+ if (userscript.namespace === null || userscript.name === null)
+ userscript.scriptId = path;
+ else
+ userscript.scriptId = userscript.namespace + "::" + userscript.name;
+ userscript.scriptId = userscript.scriptId.replace(/\s+/g, "_");
+ userscript.script = "var DWB_scriptId = '" + userscript.scriptId + "';" +
+ util.getBody(GM_compatability) + script.substring(0, metaStart) +
+ script.substring(scriptStart);
+
+ getRequirements(userscript);
+
+ for (i=0; i<userscript.match.length; i++)
+ {
+ m = parseMatch(userscript.match[i]);
+ if (m !== null)
+ matches.push(m);
+ }
+ userscript.match = matches;
+ if (userscript.runAt == "document-start")
+ onStart.push(userscript);
+ else
+ onEnd.push(userscript);
}//}}}
-function userscriptsStart() {
- var ret = false;
- if (onStart.length > 0) {
- onStart.sort(function(a, b) { return b.priority - a.priority; });
- sigCommitted = signals.connect("loadCommitted", loadCommittedCallback);
- ret = true;
- }
- if (onEnd.length > 0) {
- onEnd.sort(function(a, b) { return b.priority - a.priority; });
- sigDocument = signals.connect("documentLoaded", loadFinishedCallback);
- ret = true;
- }
- //metaData = {};
- //onStart.concat(onEnd).forEach(function (v, k, obj) {
- // var o = {
- // require : obj[k].require,
- // downloadURL : obj[k].downloadURL,
- // updateURL : obj[k].updateURL,
- // version : obj[k].version,
- // resource : obj[k].resource
- // };
- // metaData[obj[k].scriptId] = o;
- //});
- //io.write(META_DATA, "w", JSON.stringify(metaData));
- return ret;
+function userscriptsStart()
+{
+ var ret = false;
+ if (onStart.length > 0)
+ {
+ onStart.sort(function(a, b) { return b.priority - a.priority; });
+ sigCommitted = signals.connect("loadCommitted", loadCommittedCallback);
+ ret = true;
+ }
+ if (onEnd.length > 0)
+ {
+ onEnd.sort(function(a, b) { return b.priority - a.priority; });
+ sigDocument = signals.connect("documentLoaded", loadFinishedCallback);
+ ret = true;
+ }
+ //metaData = {};
+ //onStart.concat(onEnd).forEach(function (v, k, obj) {
+ // var o = {
+ // require : obj[k].require,
+ // downloadURL : obj[k].downloadURL,
+ // updateURL : obj[k].updateURL,
+ // version : obj[k].version,
+ // resource : obj[k].resource
+ // };
+ // metaData[obj[k].scriptId] = o;
+ //});
+ //io.write(META_DATA, "w", JSON.stringify(metaData));
+ return ret;
}
function parseScripts(scripts) //{{{
{
- var i, path;
- var scriptDir = data.configDir + "/scripts";
- for (i=0; i<scripts.length; i++) {
- if (system.fileTest(scripts[i], FileTest.regular | FileTest.symlink)) {
- parseScript(scripts[i]);
+ var i, path;
+ var scriptDir = data.configDir + "/scripts";
+ for (i=0; i<scripts.length; i++)
+ {
+ if (system.fileTest(scripts[i], FileTest.regular | FileTest.symlink))
+ parseScript(scripts[i]);
}
- }
- if (system.fileTest(scriptDir, FileTest.dir)) {
- var lines = io.dirNames(scriptDir);
- for (i=0; i<lines.length; i++) {
- if (lines[i].charAt(0) == ".")
- continue;
- path = scriptDir + "/" + lines[i];
- if (!(/^\s*$/.test(lines[i])) && system.fileTest(path, FileTest.regular | FileTest.symlink)) {
- parseScript(path);
- }
+ if (system.fileTest(scriptDir, FileTest.dir))
+ {
+ var lines = io.dirNames(scriptDir);
+ for (i=0; i<lines.length; i++)
+ {
+ if (lines[i].charAt(0) == ".")
+ continue;
+ path = scriptDir + "/" + lines[i];
+ if (!(/^\s*$/.test(lines[i])) && system.fileTest(path, FileTest.regular | FileTest.symlink))
+ parseScript(path);
+ }
}
- }
- return userscriptsStart();
+ return userscriptsStart();
}//}}}
return {
- init : function (c) {
- //var meta;
- //if (! system.fileTest(DATA_DIR, FileTest.dir)) {
- // system.mkdir(DATA_DIR, 0700);
- //}
- //if (system.fileTest(META_DATA, FileTest.exists)) {
- // meta = io.read(META_DATA);
- // try {
- // metaData = JSON.parse(meta);
- // }
- // catch (e) {
- // io.debug(e);
- // metaData = {};
- // }
- //}
- return parseScripts(c ? c.scripts || [] : []);
- },
- end : function () {
- if (sigDocument >= 0) {
- signals.disconnect(sigDocument);
- sigDocument = -1;
- }
- if (sigCommitted >= 0) {
- signals.disconnect(sigCommitted);
- sigCommitted = -1;
+ init : function (c) {
+ return parseScripts(c ? c.scripts || [] : []);
+ },
+ end : function () {
+ if (sigDocument >= 0) {
+ signals.disconnect(sigDocument);
+ sigDocument = -1;
+ }
+ if (sigCommitted >= 0) {
+ signals.disconnect(sigCommitted);
+ sigCommitted = -1;
+ }
+
}
-
- }
};
// vim: set ft=javascript:
diff --git a/scripts/lib/dwb.js b/scripts/lib/dwb.js
index 5111c9a4..a734c7e5 100644
--- a/scripts/lib/dwb.js
+++ b/scripts/lib/dwb.js
@@ -171,7 +171,7 @@
{
var sig = this.connect(name, (function() {
this.blockSignal(sig);
- var result = callback.apply(null, arguments);
+ var result = callback.apply(callback, arguments);
this.unblockSignal(sig);
return result;
}).bind(this));
diff --git a/scripts/lib/signals.js b/scripts/lib/signals.js
index dffb429f..a89b1f14 100644
--- a/scripts/lib/signals.js
+++ b/scripts/lib/signals.js
@@ -86,17 +86,17 @@
value : function(name, callback)
{
this.connect("createTab", function(wv) {
- wv.connect(name, function() { callback.apply(null, arguments);});
+ wv.connect(name, function() { callback.apply(callback, arguments);});
});
}
},
"disconnect" :
{
- value : _disconnectByProp.bind(this, "id")
+ value : _disconnectByProp.bind(null, "id")
},
"disconnectByFunction" :
{
- value : _disconnectByProp.bind(this, "callback")
+ value : _disconnectByProp.bind(null, "callback")
},
"disconnectByName" :
{
diff --git a/scripts/lib/util.js b/scripts/lib/util.js
index 0d9986d1..f104628e 100644
--- a/scripts/lib/util.js
+++ b/scripts/lib/util.js
@@ -73,7 +73,6 @@
});
Object.freeze(util);
-
if (Object.prototype.forEach === undefined)
{
Object.defineProperty(Object.prototype, "forEach",
diff --git a/src/adblock.c b/src/adblock.c
index e6b65f4b..328403f4 100644
--- a/src/adblock.c
+++ b/src/adblock.c
@@ -23,6 +23,7 @@
#include "domain.h"
#include "adblock.h"
#include "js.h"
+#include "dom.h"
@@ -435,7 +436,7 @@ adblock_frame_load_status_cb(WebKitWebFrame *frame, GParamSpec *p, GList *gl)
if (status == WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT)
adblock_apply_element_hider(frame, gl);
else if (status == WEBKIT_LOAD_COMMITTED)
- dwb_dom_add_frame_listener(frame, "beforeload", G_CALLBACK(adblock_before_load_cb), true, gl);
+ dom_add_frame_listener(frame, "beforeload", G_CALLBACK(adblock_before_load_cb), true, gl);
}
/* adblock_frame_created_cb {{{*/
diff --git a/src/commands.c b/src/commands.c
index b8de8ffb..4b885fd3 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -30,6 +30,8 @@
#include "download.h"
#include "js.h"
#include "scripts.h"
+#include "editor.h"
+#include "dom.h"
inline static int
dwb_floor(double x) {
@@ -54,6 +56,21 @@ commands_simple_command(KeyMap *km)
completion_clean_autocompletion();
}
+ if (EMIT_SCRIPT(EXECUTE_COMMAND))
+ {
+ char *json = util_create_json(3,
+ CHAR, "command", km->map->n.first,
+ CHAR, "argument", arg->p,
+ INTEGER, "nummod", dwb.state.nummod);
+ ScriptSignal sig = { NULL, SCRIPTS_SIG_META(json, EXECUTE_COMMAND, 0) } ;
+
+ gboolean prevent = scripts_emit(&sig);
+ g_free(json);
+
+ if (prevent)
+ return STATUS_OK;
+ }
+
ret = func(km, arg);
switch (ret)
{
@@ -770,7 +787,7 @@ commands_fullscreen(KeyMap *km, Arg *arg)
DwbStatus
commands_open_editor(KeyMap *km, Arg *arg)
{
- return dwb_open_in_editor();
+ return editor_open();
}/*}}}*/
/* dwb_command_mode {{{*/
@@ -803,7 +820,7 @@ commands_set_bars(int status)
gtk_widget_set_visible(dwb.gui.topbox, (status & BAR_VIS_TOP) && (GET_BOOL("show-single-tab") || dwb.state.views->next));
gtk_widget_set_visible(dwb.gui.bottombox, status & BAR_VIS_STATUS);
if ((status & BAR_VIS_STATUS) )
- dwb_dom_remove_from_parent(WEBKIT_DOM_NODE(CURRENT_VIEW()->hover.element), NULL);
+ dom_remove_from_parent(WEBKIT_DOM_NODE(CURRENT_VIEW()->hover.element), NULL);
}
/* commands_toggle_bars {{{*/
DwbStatus
diff --git a/src/config.h b/src/config.h
index 81c6cb09..9f126c95 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1170,4 +1170,6 @@ static WebSettings DWB_SETTINGS[] = {
SETTING_GLOBAL, BOOLEAN, { .b = false }, NULL, { 0 }, },
{ { "print-previewer", "Command used for the printing preview", },
SETTING_GLOBAL, CHAR, { .p = NULL }, NULL, { 0 }, },
+ { { "accept-language", "If set will be used for 'Accept-Language' header in all requests", },
+ SETTING_GLOBAL | SETTING_ONINIT, CHAR, { .p = NULL }, (S_Func)dwb_set_accept_language, { 0 }, },
};/*}}}*/
diff --git a/src/dom.c b/src/dom.c
new file mode 100644
index 00000000..60885d51
--- /dev/null
+++ b/src/dom.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2010-2013 Stefan Bolte <portix@gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include "dwb.h"
+
+gboolean
+dom_add_frame_listener(WebKitWebFrame *frame, const char *signal, GCallback callback, gboolean bubble, GList *gl)
+{
+ char *framesrc, *tagname;
+ gboolean ret = false;
+ WebKitDOMDOMWindow *win;
+ WebKitDOMNode *node;
+ WebKitWebView *wv = webkit_web_frame_get_web_view(frame);
+ WebKitDOMDocument *doc = webkit_web_view_get_dom_document(wv);
+ const char *src = webkit_web_frame_get_uri(frame);
+ if (g_strcmp0(src, "about:blank"))
+ {
+ /* We have to find the correct frame, but there is no access from the web_frame
+ * to the Htmlelement */
+ WebKitDOMNodeList *frames = webkit_dom_document_query_selector_all(doc, "iframe, frame", NULL);
+ for (guint i=0; i<webkit_dom_node_list_get_length(frames) && ret == false; i++)
+ {
+ node = webkit_dom_node_list_item(frames, i);
+ tagname = webkit_dom_node_get_node_name(node);
+ if (!g_ascii_strcasecmp(tagname, "iframe"))
+ {
+ framesrc = webkit_dom_html_iframe_element_get_src(WEBKIT_DOM_HTML_IFRAME_ELEMENT(node));
+ win = webkit_dom_html_iframe_element_get_content_window(WEBKIT_DOM_HTML_IFRAME_ELEMENT(node));
+ }
+ else
+ {
+ framesrc = webkit_dom_html_frame_element_get_src(WEBKIT_DOM_HTML_FRAME_ELEMENT(node));
+ win = webkit_dom_html_frame_element_get_content_window(WEBKIT_DOM_HTML_FRAME_ELEMENT(node));
+ }
+ if (!g_strcmp0(src, framesrc))
+ ret = webkit_dom_event_target_add_event_listener(WEBKIT_DOM_EVENT_TARGET(win), signal, callback, true, gl);
+
+ g_free(framesrc);
+ }
+ g_object_unref(frames);
+ }
+ return ret;
+}
+
+/* dwb_get_editable(WebKitDOMElement *) {{{*/
+gboolean
+dom_get_editable(WebKitDOMElement *element)
+{
+ if (element == NULL)
+ return false;
+
+ char *tagname = webkit_dom_node_get_node_name(WEBKIT_DOM_NODE(element));
+ if (tagname == NULL)
+ return false;
+ if (!strcasecmp(tagname, "INPUT"))
+ {
+ char *type = webkit_dom_element_get_attribute((void*)element, "type");
+ if (!g_strcmp0(type, "text") || !g_strcmp0(type, "search")|| !g_strcmp0(type, "password"))
+ return true;
+ }
+ else if (!strcasecmp(tagname, "TEXTAREA"))
+ return true;
+
+ return false;
+}/*}}}*/
+
+/* dom_get_active_element(WebKitDOMDocument ) {{{*/
+WebKitDOMElement *
+dom_get_active_element(WebKitDOMDocument *doc)
+{
+ WebKitDOMElement *ret = NULL;
+ WebKitDOMDocument *d = NULL;
+
+ WebKitDOMElement *active = webkit_dom_html_document_get_active_element((void*)doc);
+ char *tagname = webkit_dom_element_get_tag_name(active);
+
+ if (! g_strcmp0(tagname, "FRAME"))
+ {
+ d = webkit_dom_html_frame_element_get_content_document(WEBKIT_DOM_HTML_FRAME_ELEMENT(active));
+ ret = dom_get_active_element(d);
+ }
+ else if (! g_strcmp0(tagname, "IFRAME"))
+ {
+ d = webkit_dom_html_iframe_element_get_content_document(WEBKIT_DOM_HTML_IFRAME_ELEMENT(active));
+ ret = dom_get_active_element(d);
+ }
+ else
+ ret = active;
+
+ return ret;
+}/*}}}*/
+
+
+/* dwb_dom_remove_from_parent(WebKitDOMNode *node, GError **error) {{{*/
+gboolean
+dom_remove_from_parent(WebKitDOMNode *node, GError **error)
+{
+ WebKitDOMNode *parent = webkit_dom_node_get_parent_node(node);
+ if (parent != NULL)
+ {
+ webkit_dom_node_remove_child(parent, node, error);
+ return true;
+ }
+ return false;
+}/*}}}*/
diff --git a/src/dom.h b/src/dom.h
new file mode 100644
index 00000000..e1b4ed4a
--- /dev/null
+++ b/src/dom.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2013 Stefan Bolte <portix@gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef DOM_H
+#define DOM_H
+
+gboolean dom_add_frame_listener(WebKitWebFrame *frame, const char *signal, GCallback callback, gboolean bubble, GList *gl);
+gboolean dom_get_editable(WebKitDOMElement *element);
+WebKitDOMElement * dom_get_active_element(WebKitDOMDocument *doc);
+gboolean dom_remove_from_parent(WebKitDOMNode *node, GError **error);
+#endif
diff --git a/src/dwb.c b/src/dwb.c
index d54c84a6..b03e4671 100644
--- a/src/dwb.c
+++ b/src/dwb.c
@@ -47,6 +47,7 @@
#include "domain.h"
#include "application.h"
#include "scripts.h"
+#include "dom.h"
/* DECLARATIONS {{{*/
static DwbStatus dwb_webkit_setting(GList *, WebSettings *);
@@ -77,6 +78,7 @@ static DwbStatus dwb_set_ntlm(GList *gl, WebSettings *s);
static DwbStatus dwb_set_find_delay(GList *gl, WebSettings *s);
static DwbStatus dwb_set_do_not_track(GList *gl, WebSettings *s);
static DwbStatus dwb_set_show_single_tab(GList *gl, WebSettings *s);
+static DwbStatus dwb_set_accept_language(GList *gl, WebSettings *s);
#ifdef WITH_LIBSOUP_2_38
static DwbStatus dwb_set_dns_lookup(GList *gl, WebSettings *s);
#endif
@@ -98,13 +100,6 @@ static void dwb_init_gui(void);
static Navigation * dwb_get_search_completion(const char *text);
static void dwb_clean_vars(void);
-typedef struct _EditorInfo {
- char *filename;
- char *id;
- GList *gl;
- WebKitDOMElement *element;
- char *tagname;
-} EditorInfo;
typedef struct _UserScriptEnv {
GIOChannel *channel;
@@ -175,6 +170,14 @@ dwb_set_adblock(GList *gl, WebSettings *s)
}
}/*}}}*/
+/*{{{*/
+static DwbStatus
+dwb_set_accept_language(GList *gl, WebSettings *s)
+{
+ g_object_set(webkit_get_default_session(), "accept-language", s->arg_local.p, NULL);
+ return STATUS_OK;
+}/*}}}*/
+
/* dwb_set_cookies {{{ */
static DwbStatus
dwb_set_cookies(GList *gl, WebSettings *s) {
@@ -584,7 +587,7 @@ dwb_hide_message()
if (gtk_widget_get_visible(dwb.gui.bottombox))
CLEAR_COMMAND_TEXT();
else
- dwb_dom_remove_from_parent(WEBKIT_DOM_NODE(CURRENT_VIEW()->status_element), NULL);
+ dom_remove_from_parent(WEBKIT_DOM_NODE(CURRENT_VIEW()->status_element), NULL);
}
return NULL;
}/*}}}*/
@@ -1049,241 +1052,12 @@ dwb_scroll(GList *gl, double step, ScrollDirection dir)
gtk_adjustment_set_value(a, scroll);
}/*}}}*/
-/* dwb_editor_watch (GChildWatchFunc) {{{*/
-static void
-dwb_editor_watch(GPid pid, int status, EditorInfo *info)
-{
- gsize length;
- WebKitDOMElement *e = NULL;
- WebKitWebView *wv;
-
- char *content = util_get_file_content(info->filename, &length);
-
- if (content == NULL)
- goto clean;
-
- if (!info->gl || !g_list_find(dwb.state.views, info->gl->data))
- {
- if (info->id == NULL)
- goto clean;
- else
- wv = CURRENT_WEBVIEW();
- }
- else
- wv = WEBVIEW(info->gl);
- if (info->id != NULL)
- {
- WebKitDOMDocument *doc = webkit_web_view_get_dom_document(wv);
- e = webkit_dom_document_get_element_by_id(doc, info->id);
-
- if (e == NULL && (e = info->element) == NULL )
- goto clean;
- }
- else
- e = info->element;
-
- /* g_file_get_contents adds an additional newline */
- if (length > 0 && content[length-1] == '\n')
- content[length-1] = 0;
-
- if (!strcasecmp(info->tagname, "INPUT"))
- webkit_dom_html_input_element_set_value(WEBKIT_DOM_HTML_INPUT_ELEMENT(e), content);
- else if (!strcasecmp(info->tagname, "TEXTAREA"))
- webkit_dom_html_text_area_element_set_value(WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT(e), content);
-
-clean:
- unlink(info->filename);
- g_free(info->filename);
- g_free(info->id);
- g_free(info);
-}/*}}}*/
-
-/* dwb_dom_remove_from_parent(WebKitDOMNode *node, GError **error) {{{*/
-gboolean
-dwb_dom_remove_from_parent(WebKitDOMNode *node, GError **error)
-{
- WebKitDOMNode *parent = webkit_dom_node_get_parent_node(node);
- if (parent != NULL)
- {
- webkit_dom_node_remove_child(parent, node, error);
- return true;
- }
- return false;
-}/*}}}*/
-
-
-gboolean
-dwb_dom_add_frame_listener(WebKitWebFrame *frame, const char *signal, GCallback callback, gboolean bubble, GList *gl)
-{
- char *framesrc, *tagname;
- gboolean ret = false;
- WebKitDOMDOMWindow *win;
- WebKitDOMNode *node;
- WebKitWebView *wv = webkit_web_frame_get_web_view(frame);
- WebKitDOMDocument *doc = webkit_web_view_get_dom_document(wv);
- const char *src = webkit_web_frame_get_uri(frame);
- if (g_strcmp0(src, "about:blank"))
- {
- /* We have to find the correct frame, but there is no access from the web_frame
- * to the Htmlelement */
- WebKitDOMNodeList *frames = webkit_dom_document_query_selector_all(doc, "iframe, frame", NULL);
- for (guint i=0; i<webkit_dom_node_list_get_length(frames) && ret == false; i++)
- {
- node = webkit_dom_node_list_item(frames, i);
- tagname = webkit_dom_node_get_node_name(node);
- if (!g_ascii_strcasecmp(tagname, "iframe"))
- {
- framesrc = webkit_dom_html_iframe_element_get_src(WEBKIT_DOM_HTML_IFRAME_ELEMENT(node));
- win = webkit_dom_html_iframe_element_get_content_window(WEBKIT_DOM_HTML_IFRAME_ELEMENT(node));
- }
- else
- {
- framesrc = webkit_dom_html_frame_element_get_src(WEBKIT_DOM_HTML_FRAME_ELEMENT(node));
- win = webkit_dom_html_frame_element_get_content_window(WEBKIT_DOM_HTML_FRAME_ELEMENT(node));
- }
- if (!g_strcmp0(src, framesrc))
- ret = webkit_dom_event_target_add_event_listener(WEBKIT_DOM_EVENT_TARGET(win), signal, callback, true, gl);
-
- g_free(framesrc);
- }
- g_object_unref(frames);
- }
- return ret;
-}
-
-/* dwb_get_editable(WebKitDOMElement *) {{{*/
-static gboolean
-dwb_get_editable(WebKitDOMElement *element)
-{
- if (element == NULL)
- return false;
-
- char *tagname = webkit_dom_node_get_node_name(WEBKIT_DOM_NODE(element));
- if (tagname == NULL)
- return false;
- if (!strcasecmp(tagname, "INPUT"))
- {
- char *type = webkit_dom_element_get_attribute((void*)element, "type");
- if (!g_strcmp0(type, "text") || !g_strcmp0(type, "search")|| !g_strcmp0(type, "password"))
- return true;
- }
- else if (!strcasecmp(tagname, "TEXTAREA"))
- return true;
-
- return false;
-}/*}}}*/
-
-/* dwb_get_active_input(WebKitDOMDocument ) {{{*/
-static WebKitDOMElement *
-dwb_get_active_element(WebKitDOMDocument *doc)
-{
- WebKitDOMElement *ret = NULL;
- WebKitDOMDocument *d = NULL;
-
- WebKitDOMElement *active = webkit_dom_html_document_get_active_element((void*)doc);
- char *tagname = webkit_dom_element_get_tag_name(active);
-
- if (! g_strcmp0(tagname, "FRAME"))
- {
- d = webkit_dom_html_frame_element_get_content_document(WEBKIT_DOM_HTML_FRAME_ELEMENT(active));
- ret = dwb_get_active_element(d);
- }
- else if (! g_strcmp0(tagname, "IFRAME"))
- {
- d = webkit_dom_html_iframe_element_get_content_document(WEBKIT_DOM_HTML_IFRAME_ELEMENT(active));
- ret = dwb_get_active_element(d);
- }
- else
- ret = active;
-
- return ret;
-}/*}}}*/
-
-/* dwb_open_in_editor(void) ret: gboolean success {{{*/
-DwbStatus
-dwb_open_in_editor(void)
-{
- DwbStatus ret = STATUS_OK;
- char **commands = NULL;
- char *commandstring = NULL, *tagname, *path;
- char *value = NULL;
- GPid pid;
- gboolean success;
-
- char *editor = GET_CHAR("editor");
-
- if (editor == NULL)
- return STATUS_ERROR;
-
- WebKitDOMDocument *doc = webkit_web_view_get_dom_document(CURRENT_WEBVIEW());
- WebKitDOMElement *active = dwb_get_active_element(doc);
-
- if (active == NULL)
- return STATUS_ERROR;
-
- tagname = webkit_dom_element_get_tag_name(active);
- if (tagname == NULL)
- {
- ret = STATUS_ERROR;
- goto clean;
- }
- if (! strcasecmp(tagname, "INPUT"))
- value = webkit_dom_html_input_element_get_value(WEBKIT_DOM_HTML_INPUT_ELEMENT(active));
- else if (! strcasecmp(tagname, "TEXTAREA"))
- value = webkit_dom_html_text_area_element_get_value(WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT(active));
-
- if (value == NULL)
- {
- ret = STATUS_ERROR;
- goto clean;
- }
-
- path = util_get_temp_filename("edit");
-
- commandstring = util_string_replace(editor, "dwb_uri", path);
- if (commandstring == NULL)
- {
- ret = STATUS_ERROR;
- goto clean;
- }
-
- g_file_set_contents(path, value, -1, NULL);
- commands = g_strsplit(commandstring, " ", -1);
- g_free(commandstring);
-
- success = g_spawn_async(NULL, commands, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, NULL);
- g_strfreev(commands);
- if (!success)
- {
- ret = STATUS_ERROR;
- goto clean;
- }
-
- EditorInfo *info = dwb_malloc(sizeof(EditorInfo));
- char *id = webkit_dom_html_element_get_id(WEBKIT_DOM_HTML_ELEMENT(active));
- if (id != NULL && strlen(id) > 0) {
- info->id = id;
- }
- else {
- info->id = NULL;
- }
- info->tagname = tagname;
- info->element = active;
- info->filename = path;
- info->gl = dwb.state.fview;
- g_child_watch_add(pid, (GChildWatchFunc)dwb_editor_watch, info);
-
-clean:
- g_free(value);
-
- return ret;
-}/*}}}*/
/* Auto insert mode {{{*/
static gboolean
dwb_auto_insert(WebKitDOMElement *element)
{
- if (dwb_get_editable(element))
+ if (dom_get_editable(element))
{
dwb_change_mode(INSERT_MODE);
return true;
@@ -1308,7 +1082,7 @@ void
dwb_check_auto_insert(GList *gl)
{
WebKitDOMDocument *doc = webkit_web_view_get_dom_document(WEBVIEW(gl));
- WebKitDOMElement *active = dwb_get_active_element(doc);
+ WebKitDOMElement *active = dom_get_active_element(doc);
if (!dwb_auto_insert(active))
{
WebKitDOMHTMLElement *element = webkit_dom_document_get_body(doc);
@@ -1820,7 +1594,7 @@ dwb_unfocus()
view_set_normal_style(dwb.state.fview);
dwb_source_remove();
CLEAR_COMMAND_TEXT();
- dwb_dom_remove_from_parent(WEBKIT_DOM_NODE(CURRENT_VIEW()->status_element), NULL);
+ dom_remove_from_parent(WEBKIT_DOM_NODE(CURRENT_VIEW()->status_element), NULL);
dwb.state.fview = NULL;
}
} /*}}}*/
@@ -3070,7 +2844,7 @@ dwb_normal_mode(gboolean clean)
CLEAR_COMMAND_TEXT();
}
- dwb_dom_remove_from_parent(WEBKIT_DOM_NODE(CURRENT_VIEW()->status_element), NULL);
+ dom_remove_from_parent(WEBKIT_DOM_NODE(CURRENT_VIEW()->status_element), NULL);
if (mode == NORMAL_MODE)
webkit_web_view_set_highlight_text_matches(CURRENT_WEBVIEW(), false);
diff --git a/src/dwb.h b/src/dwb.h
index 1e90d4ed..a951792c 100644
--- a/src/dwb.h
+++ b/src/dwb.h
@@ -465,6 +465,8 @@ enum Signal {
SIG_PLUGINS_FRAME_CREATED,
SIG_PLUGINS_LAST,
+ SIG_EDITOR_NAVIGATION,
+
SIG_KEY_PRESS,
SIG_KEY_RELEASE,
SIG_LAST,
@@ -941,7 +943,6 @@ DwbStatus dwb_set_clipboard(const char *text, GdkAtom atom);
char * dwb_clipboard_get_text(GdkAtom atom);
void dwb_paste_primary(void);
-DwbStatus dwb_open_in_editor(void);
gboolean dwb_confirm(GList *gl, char *prompt, ...);
void dwb_save_quickmark(const char *);
@@ -970,9 +971,7 @@ DwbStatus dwb_scheme_handler(GList *gl, WebKitNetworkRequest *request);
GList *dwb_get_simple_list(GList *, const char *filename);
char * dwb_prompt(gboolean visibility, char *prompt, ...);
-gboolean dwb_dom_remove_from_parent(WebKitDOMNode *node, GError **error);
char * dwb_get_raw_data(GList *gl);
-gboolean dwb_dom_add_frame_listener(WebKitWebFrame *frame, const char *signal, GCallback callback, gboolean bubble, GList *gl);
void dwb_free_list(GList *list, void (*func)(void*));
void dwb_init(void);
diff --git a/src/editor.c b/src/editor.c
new file mode 100644
index 00000000..ccef61aa
--- /dev/null
+++ b/src/editor.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2010-2013 Stefan Bolte <portix@gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <string.h>
+#include "dwb.h"
+#include "editor.h"
+#include "util.h"
+#include "dom.h"
+
+typedef struct _EditorInfo {
+ char *filename;
+ char *id;
+ GList *gl;
+ WebKitDOMElement *element;
+ char *tagname;
+} EditorInfo;
+
+/* dwb_editor_watch (GChildWatchFunc) {{{*/
+static void
+editor_watch(GPid pid, int status, EditorInfo *info)
+{
+ gsize length;
+ WebKitDOMElement *e = NULL;
+ WebKitWebView *wv;
+
+ char *content = util_get_file_content(info->filename, &length);
+
+ if (content == NULL)
+ goto clean;
+
+ if (!info->gl || !g_list_find(dwb.state.views, info->gl->data))
+ {
+ if (info->id == NULL)
+ goto clean;
+ else
+ wv = CURRENT_WEBVIEW();
+ }
+ else
+ wv = WEBVIEW(info->gl);
+ if (info->id != NULL)
+ {
+ WebKitDOMDocument *doc = webkit_web_view_get_dom_document(wv);
+ e = webkit_dom_document_get_element_by_id(doc, info->id);
+
+ if (e == NULL && (e = info->element) == NULL )
+ goto clean;
+ }
+ else if (info->element)
+ e = info->element;
+ else
+ goto clean;
+
+ /* g_file_get_contents adds an additional newline */
+ if (length > 0 && content[length-1] == '\n')
+ content[length-1] = 0;
+
+ if (!strcasecmp(info->tagname, "INPUT"))
+ webkit_dom_html_input_element_set_value(WEBKIT_DOM_HTML_INPUT_ELEMENT(e), content);
+ else if (!strcasecmp(info->tagname, "TEXTAREA"))
+ webkit_dom_html_text_area_element_set_value(WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT(e), content);
+
+clean:
+ unlink(info->filename);
+ g_free(info->filename);
+ g_free(info->id);
+ g_free(info);
+}/*}}}*/
+
+static gboolean
+navigation_cb(WebKitWebView *web, WebKitWebFrame *frame, WebKitNetworkRequest *request, WebKitWebNavigationAction *action,
+ WebKitWebPolicyDecision *policy, EditorInfo *info)
+{
+ if (frame == webkit_web_view_get_main_frame(web))
+ {
+ info->element = NULL;
+ g_free(info->id);
+ info->id = NULL;
+ g_signal_handler_disconnect(web, VIEW(info->gl)->status->signals[SIG_EDITOR_NAVIGATION]);
+ }
+ return false;
+}
+
+/* dwb_open_in_editor(void) ret: gboolean success {{{*/
+DwbStatus
+editor_open(void)
+{
+ DwbStatus ret = STATUS_OK;
+ char **commands = NULL;
+ char *commandstring = NULL, *tagname, *path;
+ char *value = NULL;
+ GPid pid;
+ gboolean success;
+
+ char *editor = GET_CHAR("editor");
+
+ if (editor == NULL)
+ return STATUS_ERROR;
+
+ WebKitDOMDocument *doc = webkit_web_view_get_dom_document(CURRENT_WEBVIEW());
+ WebKitDOMElement *active = dom_get_active_element(doc);
+
+ if (active == NULL)
+ return STATUS_ERROR;
+
+ tagname = webkit_dom_element_get_tag_name(active);
+ if (tagname == NULL)
+ {
+ ret = STATUS_ERROR;
+ goto clean;
+ }
+ if (! strcasecmp(tagname, "INPUT"))
+ value = webkit_dom_html_input_element_get_value(WEBKIT_DOM_HTML_INPUT_ELEMENT(active));
+ else if (! strcasecmp(tagname, "TEXTAREA"))
+ value = webkit_dom_html_text_area_element_get_value(WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT(active));
+
+ if (value == NULL)
+ {
+ ret = STATUS_ERROR;
+ goto clean;
+ }
+
+ path = util_get_temp_filename("edit");
+
+ commandstring = util_string_replace(editor, "dwb_uri", path);
+ if (commandstring == NULL)
+ {
+ ret = STATUS_ERROR;
+ goto clean;
+ }
+
+ g_file_set_contents(path, value, -1, NULL);
+ commands = g_strsplit(commandstring, " ", -1);
+ g_free(commandstring);
+
+ success = g_spawn_async(NULL, commands, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, NULL);
+ g_strfreev(commands);
+ if (!success)
+ {
+ ret = STATUS_ERROR;
+ goto clean;
+ }
+
+ EditorInfo *info = dwb_malloc(sizeof(EditorInfo));
+ char *id = webkit_dom_html_element_get_id(WEBKIT_DOM_HTML_ELEMENT(active));
+ if (id != NULL && strlen(id) > 0) {
+ info->id = id;
+ }
+ else {
+ info->id = NULL;
+ }
+ info->tagname = tagname;
+ info->element = active;
+ info->filename = path;
+ info->gl = dwb.state.fview;
+ g_child_watch_add(pid, (GChildWatchFunc)editor_watch, info);
+ VIEW(dwb.state.fview)->status->signals[SIG_EDITOR_NAVIGATION] =
+ g_signal_connect(CURRENT_WEBVIEW(), "navigation-policy-decision-requested", G_CALLBACK(navigation_cb), info);
+clean:
+ g_free(value);
+
+ return ret;
+}/*}}}*/
diff --git a/src/editor.h b/src/editor.h
new file mode 100644
index 00000000..634cdeb3
--- /dev/null
+++ b/src/editor.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2010-2013 Stefan Bolte <portix@gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef EDITOR_H
+#define EDITOR_H
+
+DwbStatus editor_open(void);
+
+#endif
diff --git a/src/plugins.c b/src/plugins.c
index e71c216e..10f98f83 100644
--- a/src/plugins.c
+++ b/src/plugins.c
@@ -19,6 +19,7 @@
#include "dwb.h"
#include "util.h"
#include "view.h"
+#include "dom.h"
#define ALLOWED(g) (VIEW(g)->status->allowed_plugins)
@@ -187,7 +188,7 @@ plugins_load_status_cb(WebKitWebView *wv, GParamSpec *p, GList *gl)
void
plugins_frame_load_cb(WebKitWebFrame *frame, GParamSpec *p, GList *gl)
{
- dwb_dom_add_frame_listener(frame, "beforeload", G_CALLBACK(plugins_before_load_cb), true, gl);
+ dom_add_frame_listener(frame, "beforeload", G_CALLBACK(plugins_before_load_cb), true, gl);
}
void
diff --git a/src/scripts.c b/src/scripts.c
index f3989656..b23868e9 100644
--- a/src/scripts.c
+++ b/src/scripts.c
@@ -97,6 +97,7 @@ static Sigmap s_sigmap[] = {
{ SCRIPTS_SIG_STATUS_BAR, "statusBarChange" },
{ SCRIPTS_SIG_TAB_BUTTON_PRESS, "tabButtonPress" },
{ SCRIPTS_SIG_CHANGE_MODE, "changeMode" },
+ { SCRIPTS_SIG_EXECUTE_COMMAND, "executeCommand" },
{ 0, NULL },
};
@@ -129,6 +130,7 @@ static GQuark s_ref_quark;
static JSObjectRef s_init_before, s_init_after;
static JSObjectRef s_constructors[CONSTRUCTOR_LAST];
static gboolean s_opt_force = false;
+static JSObjectRef s_soup_session;
/* Only defined once */
static JSValueRef UNDEFINED, NIL;
@@ -879,6 +881,11 @@ global_get(JSContextRef ctx, JSObjectRef object, JSStringRef js_name, JSValueRef
{
return JSContextGetGlobalObject(ctx);
}
+static JSValueRef
+global_get_webkit_session(JSContextRef ctx, JSObjectRef object, JSStringRef js_name, JSValueRef* exception)
+{
+ return s_soup_session;
+}
/* global_execute {{{*/
static JSValueRef
global_execute(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exc)
@@ -2492,6 +2499,7 @@ create_global_object()
JSStaticValue global_values[] = {
{ "global", global_get, NULL, kJSDefaultAttributes },
+ { "session", global_get_webkit_session, NULL, kJSDefaultAttributes },
{ 0, 0, 0, 0 },
};
@@ -2723,6 +2731,9 @@ create_global_object()
s_download_class = JSClassCreate(&cd);
s_constructors[CONSTRUCTOR_DOWNLOAD] = create_constructor(s_global_context, "Download", s_download_class, download_constructor_cb, NULL);
+
+ s_soup_session = make_object_for_class(s_global_context, s_gobject_class, G_OBJECT(webkit_get_default_session()), false);
+ JSValueProtect(s_global_context, s_soup_session);
}/*}}}*/
/*}}}*/
@@ -2925,6 +2936,7 @@ scripts_end()
JSValueUnprotect(s_global_context, s_array_contructor);
JSValueUnprotect(s_global_context, UNDEFINED);
JSValueUnprotect(s_global_context, NIL);
+ JSValueUnprotect(s_global_context, s_soup_session);
JSClassRelease(s_gobject_class);
JSClassRelease(s_webview_class);
JSClassRelease(s_frame_class);
diff --git a/src/scripts.h b/src/scripts.h
index 77a400a8..77203f25 100644
--- a/src/scripts.h
+++ b/src/scripts.h
@@ -47,6 +47,7 @@ enum SIGNALS {
SCRIPTS_SIG_STATUS_BAR,
SCRIPTS_SIG_TAB_BUTTON_PRESS,
SCRIPTS_SIG_CHANGE_MODE,
+ SCRIPTS_SIG_EXECUTE_COMMAND,
SCRIPTS_SIG_LAST,
} ;
diff --git a/src/view.c b/src/view.c
index e1485311..7f3b64e5 100644
--- a/src/view.c
+++ b/src/view.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2012 Stefan Bolte <portix@gmx.net>
+ * Copyright (c) 2010-2013 Stefan Bolte <portix@gmx.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,6 +32,7 @@
#include "adblock.h"
#include "js.h"
#include "scripts.h"
+#include "dom.h"
static void view_ssl_state(GList *);
static unsigned long s_click_time;
@@ -421,7 +422,7 @@ view_hovering_over_link_cb(WebKitWebView *web, char *title, char *uri, GList *gl
VIEW(gl)->status->hover_uri = NULL;
dwb_update_uri(gl);
if (! (dwb.state.bar_visible & BAR_VIS_STATUS))
- dwb_dom_remove_from_parent(WEBKIT_DOM_NODE(VIEW(gl)->hover.element), NULL);
+ dom_remove_from_parent(WEBKIT_DOM_NODE(VIEW(gl)->hover.element), NULL);
}
}/*}}}*/
diff --git a/util/settings.pre b/util/settings.pre
index 3289fb29..156c3387 100644
--- a/util/settings.pre
+++ b/util/settings.pre
@@ -15,6 +15,7 @@ zoom-level text The default zoom level
zoom-step text The zoom step
# session Network &amp Session
+accept-language text If set will be used for "Accept-Language" header in all requests
addressbar-dns-lookup checkbox Whether to first perform a dns lookup for text typed in the addressbar before loading the site
cookies-accept-policy select @always @never @nothirdparty The cookies to accept, affects also session cookies
cookies-store-policy select @session @persistent @never The storage policy for cookies