[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/cleverphp/cefpython/cefpython31/cefpython/javascript_bindings.pyx [Back]  [Original]

# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved.
# License: New BSD License.
# Website: http://code.google.com/p/cefpython/

cdef class JavascriptBindings:
    # By default binding only to top frame.
    cdef public py_bool bindToFrames
    cdef public py_bool bindToPopups
    cdef public dict functions
    cdef public dict properties
    cdef public dict objects

    def __init__(self, bindToFrames=False, bindToPopups=False):
        self.functions = {}
        self.properties = {}
        self.objects = {}

        self.bindToFrames = bool(bindToFrames)
        self.bindToPopups = bool(bindToPopups)

    cpdef py_bool GetBindToFrames(self):
        return bool(self.bindToFrames)

    cpdef py_bool GetBindToPopups(self):
        return bool(self.bindToPopups)

    cpdef py_void SetFunction(self, py_string name, object func):
        self.SetProperty(name, func)

    cpdef py_void SetObject(self, py_string name, object obj):
        if not hasattr(obj, "__class__"):
            raise Exception("JavascriptBindings.SetObject() failed: name=%s, "
                            "__class__ attribute missing, this is not an object" % name)
        cdef dict methods = {}
        cdef py_string key
        cdef object method
        cdef object predicate = inspect.ismethod
        if isinstance(obj, (PyBrowser, PyFrame)):
            predicate = inspect.isbuiltin
        for value in inspect.getmembers(obj, predicate=predicate):
            key = value[0]
            method = value[1]
            methods[key] = method
        self.objects[name] = methods

    cpdef object GetFunction(self, py_string name):
        if name in self.functions:
            return self.functions[name]

    cpdef dict GetFunctions(self):
        return self.functions

    cpdef dict GetObjects(self):
        return self.objects

    cpdef object GetObjectMethod(self, py_string objectName, py_string methodName):
        if objectName in self.objects:
            if methodName in self.objects[objectName]:
                return self.objects[objectName][methodName]

    cpdef object GetFunctionOrMethod(self, py_string name):
        # Name can be "someFunc" or "object.someMethod".
        cdef list words
        if "." in name:
            words = name.split(".")
            return self.GetObjectMethod(words[0], words[1])
        else:
            return self.GetFunction(name)

    cpdef py_void SetProperty(self, py_string name, object value):
        cdef object allowed = self.IsValueAllowedRecursively(value) # returns True or string.
        if allowed is not True:
            raise Exception("JavascriptBindings.SetProperty() failed: name=%s, "
                            "not allowed type: %s (this may be a type of a nested value)"
                            % (name, allowed))

        cdef object valueType = type(value)
        if IsFunctionOrMethod(valueType):
            self.functions[name] = value
        else:
            self.properties[name] = value


    IF CEF_VERSION == 1:
        cpdef py_void Rebind(self):
            # Rebind may also be used for first-time bindings, in
            # a case when v8 process/thread was created too fast,
            # see Browser.SetJavascriptBindings() that checks whether
            # OnContextCreated() event already happened, if so it will
            # call Rebind() to do the javascript bindings.
            assert IsThread(TID_UI), (
                    "JavascriptBindings.Rebind() may only be called on UI thread")
            cdef CefRefPtr[CefBrowser] cefBrowser
            cdef CefRefPtr[CefFrame] cefFrame
            cdef CefRefPtr[CefV8Context] v8Context
            cdef cpp_bool sameContext
            cdef PyBrowser pyBrowser
            cdef PyFrame pyFrame
            cdef list frames
            global g_pyBrowsers
            for pyBrowser in g_pyBrowsers:
                # These javascript bindings may have been binded
                # to many browsers.
                if pyBrowser.GetJavascriptBindings() != self:
                    continue
                if self.bindToFrames:
                    frames = pyBrowser.GetFrames()
                else:
                    frames = [pyBrowser.GetMainFrame()]
                for frameId in self.frames:
                    pyBrowser = self.frames[frameId][0]
                    pyFrame = self.frames[frameId][1]
                    cefBrowser = pyBrowser.GetCefBrowser()
                    cefFrame = pyFrame.GetCefFrame()
                    v8Context = cefFrame.get().GetV8Context()
                    sameContext = v8Context.get().IsSame(cef_v8_static.GetCurrentContext())
                    if not sameContext:
                        Debug("JavascriptBindings.Rebind(): inside a different context, calling v8Context.Enter()")
                        assert v8Context.get().Enter(), "v8Context.Enter() failed"
                    V8ContextHandler_OnContextCreated(cefBrowser, cefFrame, v8Context)
                    if not sameContext:
                        assert v8Context.get().Exit(), "v8Context.Exit() failed"
    ELIF CEF_VERSION == 3:
        cpdef py_void Rebind(self):
            # In CEF Python 3 due to its multi-process architecture
            # Rebind() is used for both first-time binding and rebinding.
            cdef PyBrowser pyBrowser
            cdef dict functions
            cdef dict properties
            cdef dict objects
            cdef dict methods
            global g_pyBrowsers
            for browserId, pyBrowser in g_pyBrowsers.iteritems():
                if pyBrowser.GetJavascriptBindings() != self:
                    continue
                # Send to the Renderer process: functions, properties,
                # objects and its methods, bindToFrames.
                functions = {}
                for funcName in self.functions:
                    functions[funcName] = None
                properties = self.properties
                objects = {}
                for objectName in self.objects:
                    methods = {}
                    for methodName in self.objects[objectName]:
                        methods[methodName] = None
                    objects[objectName] = methods
                pyBrowser.SendProcessMessage(cef_types.PID_RENDERER,
                        0, "DoJavascriptBindings", [{
                                "functions": functions,
                                "properties": properties,
                                "objects": objects,
                                "bindToFrames": self.bindToFrames
                                }])

    cpdef dict GetProperties(self):
        return self.properties

    @staticmethod
    def IsValueAllowed(object value):
        return JavascriptBindings.IsValueAllowedRecursively(value) is True

    @staticmethod
    def IsValueAllowedRecursively(object value, py_bool recursion=False):
        # When making changes here modify also Frame.SetProperty() as it
        # checks for FunctionType, MethodType.

        cdef object valueType = type(value)
        cdef object valueType2
        cdef object key

        if valueType == list:
            for val in value:
                valueType2 = JavascriptBindings.IsValueAllowedRecursively(val, True)
                if valueType2 is not True:
                    return valueType2.__name__
            return True
        elif valueType == bool:
            return True
        elif valueType == float:
            return True
        elif valueType == int:
            return True
        elif valueType == type(None):
            return True
        elif IsFunctionOrMethod(valueType):
            if recursion:
                return valueType.__name__
            else:
                return True
        elif valueType == dict:
            for key in value:
                valueType2 = JavascriptBindings.IsValueAllowedRecursively(value[key], True)
                if valueType2 is not True:
                    return valueType2.__name__
            return True
        elif valueType == str or valueType == bytes:
            return True
        elif PY_MAJOR_VERSION < 3 and valueType == unicode:
            # The unicode type is not defined in Python 3.
            return True
        elif valueType == tuple:
            return True
        else:
            return valueType.__name__

Web Proxy Viewer  |  New URL  |  Original Page