Repository: qutebrowser/qutebrowser

Issue:
Add option to disable third-party cookies.
The `content -> cookies-accept` setting should get a new value (`no-3rdparty` or so?) to not accept 3rd-party cookies.
- [Test page](https://dl.dropboxusercontent.com/u/105727/web/3rd/third-party-cookies.html)
- [More informations](http://en.wikipedia.org/wiki/HTTP_cookie#Third-party_cookie)
- [RFC 6265](https://tools.ietf.org/html/rfc6265#section-7.1)
- [Related commit in Otter](https://github.com/OtterBrowser/otter-browser/commit/eaed7a67d70686a31cc9497b86d1e09aaa423bac)



Discussion:
Hi The-Compiler! As a former luakit user I found the way luakit blocked cookies quite convenient. Instead of blocking 3rd-party cookies, luakit offered simple domain-based cookie blocking via cookie.blacklist and cookie.whitelist which were placed in ~/.config/luakit. This part of the code consisted only of 73 lines so it seems to be easier to implement (at least on this stage of development).

The luakit's config file had to be then extended like this:

require "cookies"   # simple cookie manager
requrie "cookie_blocking"   # the abovementioned, short code
cookies.default_allow = false   # to block all cookies by default and hence disable cookie.blacklist

I don't know how time-consuming it would be to convert a Lua code into Python though... Anyway, if you like this suggestion, I could try to implement it.

This (and much more) will become possible when domain-wide settings (#27) are implemented.
So at the moment I think it's a bad idea to do a very specialized implementation (even if it would probably be easy), and then have two ways of doing the same thing.

That being said, 3rd party cookie filtering also should be an easy thing to implement - so if you feel like working on that, please let me know and I'll help where I can!

@moozzz since you started working on this, can you open a work-in-progress pull request so nothing gets lost and I can take a first look at the code? If you're still struggling with getting the original URL for a page, I'm happy to help :smile:

You can use `QWebSettings::ThirdPartyCookiePolicy` to disable 3rd party cookies. See: http://doc.qt.io/qt-5/qwebsettings.html#ThirdPartyCookiePolicy-enum

Did you work on this @moozzz ? I saw you forked the repo on the 24th (same date as comment), but no commits? Otherwise I'll do it since this is a feature I would very much like before I actually start using QuteBrowser :-)

As discussed in IRC, according to @Emdek of Otter Browser, using `QWebSettings::ThirdPartyCookiePolicy` doesn't work (probably because we're using a custom `QNetworkCookieJar` subclass?).

He ended up using [some custom code](https://github.com/OtterBrowser/otter-browser/commit/eaed7a67d70686a31cc9497b86d1e09aaa423bac), and I think something similiar to that is what @moozzz was working on, but I haven't seen the code yet :wink:

@The-Compiler  I added this line in `init()` in `config/websettings.py` as a test:

```
QWebSettings.globalSettings().setThirdPartyCookiePolicy(QWebSettings.AlwaysBlockThirdPartyCookies)
```

And this seems to work. Starting with `--temp_basedir` **without** this line and visiting arstechnica gives me:

```
[/tmp/qutebrowser-basedir-q7dhe0av]% grep -Eo 'domain=[^ ]*' data/cookies | cut -d= -f2 | sort -u
.254a.com;
.adnxs.com;
.adsby.bidtheatre.com;
.adsrvr.org;
.advertising.com;
.arstechnica.com;
.bidswitch.net;
.c.appier.net;
.condenast.demdex.net;
.connexity.net;
.demdex.net;
.doubleclick.net;
.m6r.eu;
.mathtag.com;
.netseer.com;
.parsely.com;
.pixel.rubiconproject.com;
.revenuemantra.com;
.revsci.net;
.rfihub.com;
.rubiconproject.com;
.scorecardresearch.com;
.simpli.fi;
.tidaltv.com;
.turn.com;
.w55c.net;
arstechnica.com;
cdn.turn.com;
match.rundsp.com;
tap.rubiconproject.com;
tap2-cdn.rubiconproject.com;
```

and **with** this line:

```
[/tmp/qutebrowser-basedir-dy1esjbm]% grep -Eo 'domain=[^ ]*' data/cookies | cut -d= -f2 | sort -u
.arstechnica.com;
arstechnica.com;
```

We probably _do_ need some custom code once we want to allow cookie settigns on a per-domain basis, but right now this seems like a good temporary solution?

Oh, that's unexpected (and nice!). I'll add that to the `cookies-accept` setting after I'm done with some other things I'm working on, unless you submitted a PR until then already :wink:


Resolving patch:
diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py
--- a/qutebrowser/config/configdata.py
+++ b/qutebrowser/config/configdata.py
@@ -674,8 +674,8 @@ def data(readonly=False):
              "local urls."),
 
             ('cookies-accept',
-             SettingValue(typ.AcceptCookies(), 'default'),
-             "Whether to accept cookies."),
+             SettingValue(typ.AcceptCookies(), 'no-3rdparty'),
+             "Control which cookies to accept."),
 
             ('cookies-store',
              SettingValue(typ.Bool(), 'true'),
diff --git a/qutebrowser/config/configtypes.py b/qutebrowser/config/configtypes.py
--- a/qutebrowser/config/configtypes.py
+++ b/qutebrowser/config/configtypes.py
@@ -1323,9 +1323,14 @@ class LastClose(BaseType):
 
 class AcceptCookies(BaseType):
 
-    """Whether to accept a cookie."""
-
-    valid_values = ValidValues(('default', "Default QtWebKit behavior."),
+    """Control which cookies to accept."""
+
+    valid_values = ValidValues(('all', "Accept all cookies."),
+                               ('no-3rdparty', "Accept cookies from the same"
+                                " origin only."),
+                               ('no-unknown-3rdparty', "Accept cookies from "
+                                "the same origin only, unless a cookie is "
+                                "already set for the domain."),
                                ('never', "Don't accept cookies at all."))
 
 
diff --git a/qutebrowser/config/websettings.py b/qutebrowser/config/websettings.py
--- a/qutebrowser/config/websettings.py
+++ b/qutebrowser/config/websettings.py
@@ -238,6 +238,25 @@ def _set(self, value, qws=None):
         self._setter(*args)
 
 
+class CookiePolicy(Base):
+
+    """The ThirdPartyCookiePolicy setting is different from other settings."""
+
+    MAPPING = {
+        'all': QWebSettings.AlwaysAllowThirdPartyCookies,
+        'no-3rdparty': QWebSettings.AlwaysBlockThirdPartyCookies,
+        'never': QWebSettings.AlwaysBlockThirdPartyCookies,
+        'no-unknown-3rdparty': QWebSettings.AllowThirdPartyWithExistingCookies,
+    }
+
+    def get(self, qws=None):
+        return config.get('content', 'cookies-accept')
+
+    def _set(self, value, qws=None):
+        QWebSettings.globalSettings().setThirdPartyCookiePolicy(
+            self.MAPPING[value])
+
+
 MAPPINGS = {
     'content': {
         'allow-images':
@@ -264,6 +283,8 @@ def _set(self, value, qws=None):
             Attribute(QWebSettings.LocalContentCanAccessRemoteUrls),
         'local-content-can-access-file-urls':
             Attribute(QWebSettings.LocalContentCanAccessFileUrls),
+        'cookies-accept':
+            CookiePolicy(),
     },
     'network': {
         'dns-prefetch':


Test patch: