Repository: qutebrowser/qutebrowser

Issue:
Handle "::" in URLs specially
Split from #542. /cc @flvi0

> What exactly are those :: links anyways, is that a standard URI form for external applications? Maybe we can parse/qualify it somehow differently to make searching for scoped C++ symbols work as expected?

[QUrl](http://doc.qt.io/qt-5/qurl.html) parses `foo::bar` as a valid URL with `foo` as scheme and `:bar` as path. I'm not sure if this is something sensible to do according to the URL standard. I guess `qutebrowser.urlutils.is_url` should handle this as a special case, and maybe a Qt bug should be submitted if this is invalid according to [RFC3986](https://tools.ietf.org/html/rfc3986) and the [WHATWG living URL standard](https://url.spec.whatwg.org/)?



Discussion:
Ok I've looked into this and it seems that double colon after scheme is allowed by the generic URI syntax.:

```
URI         = scheme ":" hier-part ...
hier-part   = "//" authority path-abempty
                  / path-absolute
                  / path-rootless
                  / path-empty
path-rootless = segment-nz *( "/" segment )
segment-nz    = 1*pchar
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
```

i.e. the colon is explicitly allowed there.

That being the case, I think we might still consider checking if there's actually some sort of handler registered for a given scheme. It seems QDesktopServices is missing some getUrlHandlers method to retreive a list of all handlers which are registered with the DE (where does that specifically happen actually?). We could then combine the list with any scheme handlers registered explicitly with qutebrowser (see #540) and search for a prefix in the URI. Everything else would then be treated as a search query with the default engine.

That precludes of course the possibility to have users register scheme handlers dynamically if a yet unknown URI is entered. If that's planned, we might just stick with the slight annoyance of having to type the default search engine upfront if searching for a x::y string. Regarding #542, I still think that any named search engines should be a user setting, and if that case occurs well I have to give the default engine an explicit name.

`QDesktopServices::openUrl` seems to use `QPlatformServices::openUrl`. For Linux, this seems to be `QGenericUnixServices` from `platformsupport/services/genericunix/qgenericunixservices.cpp` which then seems to open it via the OS or a web browser (?!?).

Either way, it seems to be hard to get a list of the supported schemes. I vaguely remember [OtterBrowser/otter-browser](https://github.com/OtterBrowser/otter-browser) wanted to do something similiar but I don't think they got anywhere.

I wonder if it's a good idea to just never treat URLs with `scheme::foo` as URL. This could be added easily to `utils.urlutils:_has_explicit_scheme` (which already rejects `scheme: foo` as a valid URL).

Are there any common cases of protocols using a `scheme::foobar` URL? I'll ask if someone knows more in `#whatwg` on Freenode.

> I wonder if it's a good idea to just never treat URLs with `scheme::foo` as URL. This could be added easily to `utils.urlutils:_has_explicit_scheme` (which already rejects `scheme: foo` as a valid URL).
> 
> Are there any common cases of protocols using a `scheme::foobar` URL? I'll ask if someone knows more in `#whatwg` on Freenode.

I know of none. We could of course just start treating everything which has a colon after the first colon as a search string and see if that troubles anyone at some point. Should not be a problem to fall back to the behavior as it is now by removing that check again. If you don't get an answer from the #whatwg people I suggest we just give it a try. In that case we might want to merge #542 after all. I think not having those hardcoded searchengine aliases is actually better, following the principle of least surprise.


Resolving patch:
diff --git a/qutebrowser/utils/urlutils.py b/qutebrowser/utils/urlutils.py
--- a/qutebrowser/utils/urlutils.py
+++ b/qutebrowser/utils/urlutils.py
@@ -193,7 +193,14 @@ def _has_explicit_scheme(url):
     Args:
         url: The URL as QUrl.
     """
-    return url.isValid() and url.scheme() and not url.path().startswith(' ')
+
+    # Note that generic URI syntax actually would allow a second colon
+    # after the scheme delimiter. Since we don't know of any URIs
+    # using this and want to support e.g. searching for scoped C++
+    # symbols, we treat this as not an URI anyways.
+    return (url.isValid() and url.scheme()
+            and not url.path().startswith(' ')
+            and not url.path().startswith(':'))
 
 
 def is_special_url(url):


Test patch: