Oxide is a Qt5/QML binding based on the Chromium Content API, it's intended to replace qtwebkit for the touch browser, webapps and the UbuntuWebView.

The Ubuntu Browser app

So what does Oxide provide for developers ? It does provide a good chunk a usefull functions :

  • Basic navigation
  • Incognito mode
  • Multiple browser contexts
  • User scripts
  • Message API
  • Dialog support
  • Accelerated compositing

WebView

Before you start make sure to add the webview to your apparmor policy file, to declare a Webview using Oxide you need to use the WebView component from com.canonical.Oxide

import com.canonical.Oxide 1.0
[...]
WebView {
    id: webview
    width: parent.width
    height: parent.height

    Component.onCompleted: {
        url = "http://daker.me"
    }
}

The WebView comes with a preferences property which allows to set a list of attributes :

  • allowFileAccessFromFileUrls (bool)
  • allowScriptsToCloseWindows (bool)
  • allowUniversalAccessFromFileUrls (bool)
  • appCacheEnabled (bool)
  • canDisplayInsecureContent (bool)
  • canRunInsecureContent (bool)
  • caretBrowsingEnabled (bool)
  • databasesEnabled (bool)
  • defaultEncoding (QString)
  • defaultFixedFontSize (uint)
  • defaultFontSize (uint)
  • fixedFontFamily (QString)
  • hyperlinkAuditingEnabled (bool)
  • javascriptCanAccessClipboard (bool)
  • javascriptEnabled (bool)
  • loadsImagesAutomatically (bool)
  • localStorageEnabled (bool)
  • minimumFontSize (uint)
  • objectName (QString)
  • passwordEchoEnabled (bool)
  • remoteFontsEnabled(bool)
  • sanSerifFontFamily (QString)
  • serifFontFamily (QString)
  • shrinksStandaloneImagesToFit (bool)
  • standardFontFamily (QString)
  • tabsToLinks (bool)
  • textAreasAreResizable (bool)
  • touchEnabled (bool)

Example

import com.canonical.Oxide 1.0
[...]
WebView {
    id: webview
    width: parent.width
    height: parent.height

    Component.onCompleted: {
        url = "http://daker.me"
    }

    preferences.localStorageEnabled: true
    preferences.loadsImagesAutomatically: false
    preferences.passwordEchoEnabled: true
}

WebContext

Oxide also provides a WebContext which allow to set other settings

  • acceptLangs (QString)
  • cachePath (QUrl)
  • cookiePolicy (CookiePolicy)
  • dataPath (QUrl)
  • objectName (QString)
  • popupBlockerEnabled (bool)
  • product (QString)
  • sessionCookieMode
  • storageAccessPermissionDelegate
  • userAgent (QString)
  • userAgentOverrideDelegate
  • userScripts

UserAgent

This example shows how you can use the WebContext to override the default UserAgent

import com.canonical.Oxide 1.0
[...]
WebContext {
    id: webcontext
    userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3"
}

WebView {
    id: webview
    width: parent.width
    height: parent.height

    context: webcontext

    Component.onCompleted: {
        url = "http://www.whatsmyuseragent.com"
    }
}

networkRequestDelegate

You can also override the http request headers by using the networkRequestDelegate, in this example i am adding a Do Not Track (DNT) an HTTP header field on the fly.

import com.canonical.Oxide 1.0
[...]
WebContext {
    id: webcontext
    networkRequestDelegate: WebContextDelegateWorker {
        source: Qt.resolvedUrl("dnt.js")
    }
}

WebView {
    id: webview
    width: parent.width
    height: parent.height

    context: webcontext

    Component.onCompleted: {
        url = "http://www.browserleaks.com/donottrack"
    }
}
/*
 dnt.js
 Made by Adnane Belmadiaf <daker AT ubuntu DOT com>
*/

exports.onBeforeSendHeaders = function(event) {
    event.setHeader("DNT", 1);
};

UserScripts

Oxide supports Greasemonkey-style user scripts, here is an example to do some DOM manipulation.

import com.canonical.Oxide 1.0
[...]
WebContext {
    id: webcontext
    userScripts: [
        UserScript {
            context: "oxide://"
            url: Qt.resolvedUrl("oxide_dom.js")
            incognitoEnabled: true
            matchAllFrames: true
        }
    ]
}

WebView {
    id: webview
    width: parent.width
    height: parent.height

    context: webcontext

    Component.onCompleted: {
        url = "http://www.ubuntu.com/"
    }
}
// ==UserScript==
// @name           Dom Manipulation
// @namespace      http://daker.me
// @description    Oxide UserScript demo
// ==/UserScript==

function oxide_dom() {
    var div = document.createElement('div');
    div.innerHTML = '<h1>Content inserted using Oxide UserScript!</h1>';
    div.style.color = 'red';
    document.getElementById("nav-global").insertBefore(div);
}

window.addEventListener('load', oxide_dom, true);

Message API

Oxide does also provide a message API, in this example the script will send a message to Oxide and Oxide will reply back.

import com.canonical.Oxide 1.0
[...]
WebContext {
    id: webcontext
    networkRequestDelegate: WebContextDelegateWorker {
        source: Qt.resolvedUrl("message-api.js")
        onMessage: console.log("Message from Oxide : ", message.msg)
        Component.onCompleted: {
            sendMessage({ msg: 'ping' })
        }
    }
}

WebView {
    id: webview
    width: parent.width
    height: parent.height

    context: webcontext

    Component.onCompleted: {
        url = "http://www.ubuntu.com/"
    }
}
/*
 message-api.js
 This script will send a message to Oxide on every request
*/
var response_msg = "";

oxide.onMessage = function(msg) {
    if ("msg" in msg) {
        if (msg["msg"] == 'ping') {
            response_msg = "pong";
        }
    }
};

exports.onBeforeSendHeaders = function(event) {
    oxide.sendMessage({msg: response_msg});
};