CEFPython Test (utf-8: ąśö)

### Links

http://www.google.com/ http://en.wikipedia.org/

### UTF-8

Plain: ąśö
HTML: €ö

### User agent

### Popup

window.open('http://www.google.com')

### Select Tag

### Input Tag

Your name:
Please send me spam about everything
You are: male female

### TextArea Tag

utf-8: ąśö

### HTML5 video and accelerated content

HTML 5 video
Accelerated canvas
Accelerated layers

### Javascript dialogs

alert('test (utf-8: ąśö)')
confirm('test (utf-8: ąśö)')
cprompt('test (utf-8: ąśö)', 'test (utf-8: ąśö)')

### External

### 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')
GetSource() to console
GetText() to console

### 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

    def OnLoadingStateChange(self, browser, isLoading, canGoBack,
            canGoForward):
        print("ClientHandler::OnLoadingStateChange()")
        print("isLoading = %s, canGoBack = %s, canGoForward = %s" \
                % (isLoading, canGoBack, canGoForward))

See messages in the console during loading of a webpage.

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

See messages in the console during loading of a webpage.

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

See messages in the console during loading of a webpage.

    def OnTooltip(self, browser, textOut):
        # OnTooltip not yet implemented (both Linux and Windows),
        # will be fixed in next CEF release, see Issue 783:
        # https://code.google.com/p/chromiumembedded/issues/detail?id=783
        print("DisplayHandler::OnTooltip()")
        print("text = %s" % textOut[0])

See messages in the console when hovering over a google logo: http://www.google.com/

    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)

See messages in the console when hovering over links.

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

Try this: http://patik.com/code/console-log-polyfill/

### Keyboard handler

Press F5 to reload the page.
On Linux it is required to click anywhere in the window first so that keyboard focus is set. See Issue 77 in the CEF Python Issue Tracker.

    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/
(After you see the custom error message you have to hit twice the Back from the context menu, to get back to this page)

    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.

### Other tests

- external.GoBack()
- external.GoForward()