Use mouse context menu to go Back/Forward in history navigation.

Google Search

http://www.google.com/

User agent

Popup

window.open('wxpython.html')

HTML5 video and accelerated content

HTML 5 video
Accelerated canvas
Accelerated layers

Javascript bindings

PyPrint('printing in python console from js')
window.alert(window.pyProperty)
window.alert(JSON.stringify(window.pyConfig))
external.Print('printing again from js')
external.TestAllTypes (undefined, null, true, 1, ((1<<31)>>>0), 2.14, 'Date not yet supported', 'string', {key1: 1, key2: 2}, {key1: {'key1.1': 'nested object'}, 'key1.2': [1]}, [1, 2], [1, [2.1, 'nested array']], [{key1: [{}]}])
<script>
function JavascriptAlert(message) { window.alert(message); }
</script>
external.ExecuteFunction('JavascriptAlert', 'python called from js and then js called from python')

Javascript callbacks

<script>
function JSCallback(arg1) {
    window.alert(arg1)
}
</script>
def TestJSCallback(self, jsCallback):
    print("jsCallback.GetFunctionName() = %s" % jsCallback.GetFunctionName())
    print("jsCallback.GetFrame().GetIdentifier() = %s" % \
            jsCallback.GetFrame().GetIdentifier())
    jsCallback.Call("This message was sent from python using js callback")
external.TestJSCallback(JSCallback)
<script>
function JSCallback2() {
    window.alert(JSON.stringify(arguments))
}
</script>
def TestJSCallbackComplexArguments(self, jsObject):
    jsCallback = jsObject["myCallback"];
    jsCallback.Call(1, None, 2.14, "string", ["list", ["nested list", \
            {"nested object":None}]], \
            {"nested list next":[{"deeply nested object":1}]})
external.TestJSCallbackComplexArguments({"myCallback": JSCallback2})

Python callbacks

<script>
function JSCallback3(pyCallback) {
    pyCallback(1, 2.14, "string", [1, [2, {"key": "value"}]], {"list": [1,2]});
}
</script>
def TestPythonCallback(self, jsCallback):
    jsCallback.Call(PyCallback)

def PyCallback(self, *args):
        message = "PyCallback() was executed successfully! Arguments: %s" \
                % str(args)
        print(message)
        self.mainBrowser.GetMainFrame().ExecuteJavascript(
                "window.alert(\"%s\")" % message)
external.TestPythonCallback(JSCallback3)

Display handler

See messages in the console.
def OnLoadingStateChange(self, browser, isLoading, canGoBack, 
        canGoForward):
    print("ClientHandler::OnLoadingStateChange()")
    print("isLoading = %s, canGoBack = %s, canGoForward = %s" \
            % (isLoading, canGoBack, canGoForward))

def OnAddressChange(self, browser, frame, url):
    print("ClientHandler::OnAddressChange()")
    print("url = %s" % url)

def OnTitleChange(self, browser, title):
    print("ClientHandler::OnTitleChange()")
    print("title = %s" % title)

def OnTooltip(self, browser, text):
    print("ClientHandler::OnTooltip()")
    print("text = %s")

def OnStatusMessage(self, browser, value):
    if not value:
        # Do not notify in the console about empty statuses.
        return
    self.statusMessageCount += 1
    if self.statusMessageCount > 3:
        # Do not spam too much.
        return
    print("DisplayHandler::OnStatusMessage()")
    print("value = %s" % value)

def OnConsoleMessage(self, browser, message, source, line):
    print("ClientHandler::OnConsoleMessage()")
    print("message = %s" % message)
    print("source = %s" % source)
    print("line = %s" % line)

Keyboard handler

Click anywhere in the window first to set keyboard focus. Next press F5 to reload the page.

def OnPreKeyEvent(self, browser, event, eventHandle, 
        isKeyboardShortcutOut):
    print("ClientHandler::OnPreKeyEvent()")

def OnKeyEvent(self, browser, event, eventHandle):
    print("ClientHandler::OnKeyEvent()")
    print("native_key_code = %s" % event["native_key_code"])
    if platform.system() == "Linux":
        # F5 = 71
        if event["native_key_code"] == 71:
            print("F5 pressed! Reloading page..")
            browser.ReloadIgnoreCache()

Request handler

def OnBeforeResourceLoad(self, browser, frame, request):
    print("RequestHandler::OnBeforeResourceLoad()")
    print("url = %s" % request.GetUrl()[:70])
    return False
See messages in the console.
def OnResourceRedirect(self, browser, frame, oldUrl, newUrlOut):
    print("RequestHandler::OnResourceRedirect()")
    print("old url = %s" % oldUrl[:70])
    print("new url = %s" % newUrlOut[0][:70])
Try this: http://tinyurl.com/google404redirect
def GetAuthCredentials(self, browser, frame, isProxy, host, port, realm,
        scheme, callback):
    print("RequestHandler::GetAuthCredentials()")
    print("host = %s" % host)
    print("realm = %s" % realm)
    callback.Continue(username="test", password="test")
    return True
Try this: http://browserspy.dk/password-ok.php
def OnQuotaRequest(self, browser, originUrl, newSize, callback):
    print("RequestHandler::OnQuotaRequest()")
    print("origin url = %s" % originUrl)
    print("new size = %s" % newSize)
    callback.Continue(True)
    return True
<script>
function DoRequestQuota() {
    // Request Quota (only for File System API)  
    try {
        navigator.webkitPersistentStorage.requestQuota(PERSISTENT, 1024*1024,
                function(bytes){ window.alert("Granted bytes: "+bytes);},
                function(error){ window.alert(error); });
    } catch(e) {
        navigator.webkitPersistentStorage.requestQuota(1024*1024,
                function(bytes){ window.alert("Granted bytes: "+bytes);},
                function(error){ window.alert(error); });
    }
}
</script>
Try this: https://googledrive.com/host/0B1di2XiBBfacMnhRRkI1YlotUEk/requestquota.html
def OnProtocolExecution(self, browser, url, allowExecutionOut):
    # There's no default implementation for OnProtocolExecution on Linux,
    # you have to make OS system call on your own. You probably also need
    # to use LoadHandler::OnLoadError() when implementing this on Linux.
    print("RequestHandler::OnProtocolExecution()")
    print("url = %s" % url)
    if url.startswith("magnet:"):
        print("Magnet link allowed!")
        allowExecutionOut[0] = True
Try this: magnet:?xt=urn:btih:a4224b45b27f436374391379cc5c7e629e2e5189
def _OnBeforePluginLoad(self, browser, url, policyUrl, info):
    # Plugins are loaded on demand, only when website requires it,
    # the same plugin may be called multiple times.
    print("RequestHandler::OnBeforePluginLoad()")
    print("url = %s" % url)
    print("policy url = %s" % policyUrl)
    print("info.GetName() = %s" % info.GetName())
    print("info.GetPath() = %s" % info.GetPath())
    print("info.GetVersion() = %s" % info.GetVersion())
    print("info.GetDescription() = %s" % info.GetDescription())
    # False to allow, True to block plugin.
    return False
Try OnBeforePluginLoad() with Flash: http://www.adobe.com/software/flash/about/
def _OnCertificateError(self, certError, requestUrl, callback):
    print("RequestHandler::OnCertificateError()")
    print("certError = %s" % certError)
    print("requestUrl = %s" % requestUrl)
    if requestUrl.startswith(
            "https://sage.math.washington.edu:8091/do-not-allow"):
        print("Not allowed!")
        return False
    if requestUrl.startswith(
            "https://sage.math.washington.edu:8091/hudson/job/"):
        print("Allowed!")
        callback.Continue(True)
        return True
    return False
This won't be allowed: https://sage.math.washington.edu:8091/do-not-allow
This will be allowed: https://sage.math.washington.edu:8091/hudson/job/cython-docs/

Cookie tests

See messages in the console.
 def GetCookieManager(self, browser, mainUrl):
    # Create unique cookie manager for each browser.
    # --
    # Buggy implementation in CEF, reported here:
    # https://code.google.com/p/chromiumembedded/issues/detail?id=1043
    cookieManager = browser.GetUserData("cookieManager")
    if cookieManager:
        return cookieManager
    else:
        cookieManager = cefpython.CookieManager.CreateManager("")
        browser.SetUserData("cookieManager", cookieManager)
        return cookieManager
RequestHandler.GetCookieManager() - an example of having an unique cookie manager for each browser. Visit http://www.html-kit.com/tools/cookietester/ and set some cookie, then go back to this page using the context menu and open a new popup window, the cookie should not appear in the popup browser window.

CookieManager.VisitAllCookies() - visit all cookies: external.VisitAllCookies() (note: visit some http:// webpage first, otherwise cookie manager is not yet created)

CookieManager.VisitUrlCookies("http://www.html-kit.com/tools/cookietester/") - visit a subset of cookies given the url, test: external.VisitUrlCookies()

CookieManager.SetCookie("http://www.html-kit.com/tools/cookietester/", {name:"Created_Via_Python", value:"yeah really"}) - create the cookie: external.SetCookie()

CookieManager.DeleteCookies() - delete the single cookie previously created via SetCookie(): external.DeleteCookies()

Load Handler

def OnLoadStart(self, browser, frame):
    print("LoadHandler::OnLoadStart()")
    print("frame url = %s" % frame.GetUrl()[:70])
See messages in the console.
def OnLoadEnd(self, browser, frame, httpStatusCode):
    print("LoadHandler::OnLoadEnd()")
    print("frame url = %s" % frame.GetUrl()[:70])
    # For file:// urls the status code = 0
    print("http status code = %s" % httpStatusCode)
See messages in the console.
def OnLoadError(self, browser, frame, errorCode, errorTextList, failedUrl):
    print("LoadHandler::OnLoadError()")
    print("frame url = %s" % frame.GetUrl()[:70])
    print("error code = %s" % errorCode)
    print("error text = %s" % errorTextList[0])
    print("failed url = %s" % failedUrl)
    customErrorMessage = "My custom error message!"
    frame.LoadUrl("data:text/html,%s" % customErrorMessage)
Try this: http://www.non-existent.nono/
def OnRendererProcessTerminated(self, browser, status):
    print("LoadHandler::OnRendererProcessTerminated()")
    statuses = {
        cefpython.TS_ABNORMAL_TERMINATION: "TS_ABNORMAL_TERMINATION",
        cefpython.TS_PROCESS_WAS_KILLED: "TS_PROCESS_WAS_KILLED",
        cefpython.TS_PROCESS_CRASHED: "TS_PROCESS_CRASHED"
    }
    statusName = "Unknown"
    if status in statuses:
        statusName = statuses[status]
    print("status = %s" % statusName)
Try to terminate the "subprocess.exe" renderer process through process/task manager.
def OnPluginCrashed(self, browser, pluginPath):
    print("LoadHandler::OnPluginCrashed()")
    print("plugin path = %s" % pluginPath)
No test for that yet.