From 523362f6b7f14a4880079619a69d9b505569d2de Mon Sep 17 00:00:00 2001 From: linesight Date: Sat, 27 Jan 2024 20:59:55 -0800 Subject: [PATCH 01/35] py3 update for automate-git.py and automate.py --- tools/automate-git.py | 50 +++++++++++++++++++++---------------------- tools/automate.py | 7 +----- 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/tools/automate-git.py b/tools/automate-git.py index b819c7bd9..734dd54e3 100644 --- a/tools/automate-git.py +++ b/tools/automate-git.py @@ -138,7 +138,7 @@ import sys import tempfile import urllib -import urllib2 +from urllib.request import urlopen, FancyURLopener import zipfile ## @@ -258,7 +258,7 @@ def exec_cmd(cmd, path): stderr=subprocess.PIPE, shell=(sys.platform == 'win32')) out, err = process.communicate() - except IOError, (errno, strerror): + except IOError: raise except: raise @@ -300,7 +300,7 @@ def download_and_extract(src, target): if src[:4] == 'http': # Attempt to download a URL. - opener = urllib.FancyURLopener({}) + opener = FancyURLopener({}) response = opener.open(src) temporary = True @@ -462,7 +462,7 @@ def onerror(func, path, exc_info): def read_json_url(url): """ Read a JSON URL. """ msg('Downloading %s' % url) - response = urllib2.urlopen(url) + response = urlopen(url) return json.loads(response.read()) @@ -1051,7 +1051,7 @@ def check_pattern_matches(output_file=None): (options, args) = parser.parse_args() if options.downloaddir is None: - print "The --download-dir option is required." + print("The --download-dir option is required.") parser.print_help(sys.stderr) sys.exit() @@ -1074,7 +1074,7 @@ def check_pattern_matches(output_file=None): if (options.nocefupdate and options.forceupdate): pass else: - print "Invalid combination of options." + print("Invalid combination of options.") parser.print_help(sys.stderr) sys.exit() # -- @@ -1083,17 +1083,17 @@ def check_pattern_matches(output_file=None): (options.minimaldistrib or options.minimaldistribonly or \ options.clientdistrib or options.clientdistribonly)) or \ (options.minimaldistribonly + options.clientdistribonly + options.sandboxdistribonly > 1): - print 'Invalid combination of options.' + print('Invalid combination of options.') parser.print_help(sys.stderr) sys.exit() if options.x64build and options.armbuild: - print 'Invalid combination of options.' + print('Invalid combination of options.') parser.print_help(sys.stderr) sys.exit() if (options.buildtests or options.runtests) and len(options.testtarget) == 0: - print "A test target must be specified via --test-target." + print("A test target must be specified via --test-target.") parser.print_help(sys.stderr) sys.exit() @@ -1101,7 +1101,7 @@ def check_pattern_matches(output_file=None): if options.dryrun and options.dryrunplatform is not None: platform = options.dryrunplatform if not platform in ['windows', 'macosx', 'linux']: - print 'Invalid dry-run-platform value: %s' % (platform) + print('Invalid dry-run-platform value: %s' % (platform)) sys.exit() elif sys.platform == 'win32': platform = 'windows' @@ -1110,7 +1110,7 @@ def check_pattern_matches(output_file=None): elif sys.platform.startswith('linux'): platform = 'linux' else: - print 'Unknown operating system platform' + print('Unknown operating system platform') sys.exit() # Script extension. @@ -1125,25 +1125,25 @@ def check_pattern_matches(output_file=None): else: client_app = 'cefclient' if options.buildtarget.find(client_app) == -1: - print 'A client distribution cannot be generated if --build-target '+\ - 'excludes %s.' % client_app + print('A client distribution cannot be generated if --build-target '+\ + 'excludes %s.' % client_app) parser.print_help(sys.stderr) sys.exit() if platform != 'windows' and (options.sandboxdistrib or options.sandboxdistribonly): - print 'The sandbox distribution is only supported on Windows.' + print('The sandbox distribution is only supported on Windows.') sys.exit() # CEF branch. if options.branch != 'trunk' and not options.branch.isdigit(): - print 'Invalid branch value: %s' % (options.branch) + print('Invalid branch value: %s' % (options.branch)) sys.exit() cef_branch = options.branch if cef_branch != 'trunk' and int(cef_branch) <= 1453: - print 'The requested branch is too old to build using this tool.' + print('The requested branch is too old to build using this tool.') sys.exit() # True if the requested branch is 2272 or newer. @@ -1166,28 +1166,28 @@ def check_pattern_matches(output_file=None): use_gn = bool(int(os.environ.get('CEF_USE_GN', '0'))) if use_gn: if branch_is_2743_or_older: - print 'GN is not supported with branch 2743 and older (set CEF_USE_GN=0).' + print('GN is not supported with branch 2743 and older (set CEF_USE_GN=0).') sys.exit() if options.armbuild: if platform != 'linux': - print 'The ARM build option is only supported on Linux.' + print('The ARM build option is only supported on Linux.') sys.exit() if not branch_is_newer_than_2785: - print 'The ARM build option is not supported with branch 2785 and older.' + print('The ARM build option is not supported with branch 2785 and older.') sys.exit() else: if options.armbuild: - print 'The ARM build option is not supported by GYP.' + print('The ARM build option is not supported by GYP.') sys.exit() if options.x64build and platform != 'windows' and platform != 'macosx': - print 'The x64 build option is only used on Windows and Mac OS X.' + print('The x64 build option is only used on Windows and Mac OS X.') sys.exit() if platform == 'windows' and not 'GYP_MSVS_VERSION' in os.environ.keys(): - print 'You must set the GYP_MSVS_VERSION environment variable on Windows.' + print('You must set the GYP_MSVS_VERSION environment variable on Windows.') sys.exit() # True if GYP_DEFINES=target_arch=x64 must be set. @@ -1203,8 +1203,8 @@ def check_pattern_matches(output_file=None): deps_file = '.DEPS.git' if platform == 'macosx' and not options.x64build and branch_is_2272_or_newer: - print '32-bit Mac OS X builds are no longer supported with 2272 branch and '+\ - 'newer. Add --x64-build flag to generate a 64-bit build.' + print('32-bit Mac OS X builds are no longer supported with 2272 branch and '+\ + 'newer. Add --x64-build flag to generate a 64-bit build.') sys.exit() # Options that force the sources to change. @@ -1214,7 +1214,7 @@ def check_pattern_matches(output_file=None): discard_local_changes = force_change or options.forcecefupdate if options.resave and (options.forcepatchupdate or discard_local_changes): - print '--resave cannot be combined with options that modify or discard patches.' + print('--resave cannot be combined with options that modify or discard patches.') parser.print_help(sys.stderr) sys.exit() diff --git a/tools/automate.py b/tools/automate.py index 2ba882785..80cb4ff7f 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -93,7 +93,6 @@ import shutil import multiprocessing from collections import OrderedDict -from setuptools.msvc import msvc9_query_vcvarsall # Constants CEF_UPSTREAM_GIT_URL = "https://bitbucket.org/chromiumembedded/cef.git" @@ -147,11 +146,6 @@ def main(): setup_options(docopt.docopt(__doc__)) if Options.build_cef: - if not sys.version_info[:2] == (2, 7): - print("ERROR: To build CEF from sources you need Python 2.7.") - print(" Upstream automate-git.py works only with that") - print(" version of python.") - sys.exit(1) build_cef() elif Options.prebuilt_cef: prebuilt_cef() @@ -525,6 +519,7 @@ def build_wrapper_library_windows(runtime_library, msvs, vcvars): if msvs == "2010": # When Using WinSDK 7.1 vcvarsall.bat doesn't work. Use # setuptools.msvc.msvc9_query_vcvarsall to query env vars. + from setuptools.msvc import msvc9_query_vcvarsall env.update(msvc9_query_vcvarsall(10.0, arch=VS_PLATFORM_ARG)) # On Python 2.7 env values returned by both distutils # and setuptools are unicode, but Python expects env From 5a5df9513b0458361ecfc0887bd1df075be25209 Mon Sep 17 00:00:00 2001 From: linesight Date: Sat, 27 Jan 2024 23:22:15 -0800 Subject: [PATCH 02/35] --disable-syntax-validation option at gclient has been removed from upstream --- tools/automate-git.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/automate-git.py b/tools/automate-git.py index 734dd54e3..717334687 100644 --- a/tools/automate-git.py +++ b/tools/automate-git.py @@ -1431,7 +1431,7 @@ def check_pattern_matches(output_file=None): # Initial Chromium checkout. if not options.nochromiumupdate and not os.path.exists(chromium_src_dir): chromium_checkout_new = True - run("gclient sync --nohooks --with_branch_heads --disable-syntax-validation --jobs 16", \ + run("gclient sync --nohooks --with_branch_heads --jobs 16", \ chromium_dir, depot_tools_dir) else: chromium_checkout_new = False @@ -1523,7 +1523,7 @@ def check_pattern_matches(output_file=None): os.environ['GYP_CHROMIUM_NO_ACTION'] = '1' # Update third-party dependencies including branch/tag information. - run("gclient sync %s--with_branch_heads --disable-syntax-validation --jobs 16" % \ + run("gclient sync %s--with_branch_heads --jobs 16" % \ ('--reset ' if discard_local_changes else ''), chromium_dir, depot_tools_dir) # Clear the GYP_CHROMIUM_NO_ACTION value. From 41e0b97428f5bfbca1e852348a647aa446a9cf24 Mon Sep 17 00:00:00 2001 From: gary Date: Sun, 14 Feb 2021 12:03:24 -0800 Subject: [PATCH 03/35] Add support for Python 3.8 and Upgrade Cython (#594) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/cztomczak/cefpython/issues/546 Had to include harfbuzz manually as newer Pango change this. See: https://github.com/eiskaltdcpp/eiskaltdcpp/issues/413 https://gitlab.gnome.org/GNOME/pango/-/issues/387 Also had to add `-Wno-deprecated-declarations` to get this to compile because of the following errors that didn't seem to be coming from this code directly: warning: ‘GTimeVal’ is deprecated: Use 'GDateTime' instead warning: ‘GTypeDebugFlags’ is deprecated --- README.md | 6 +++--- src/common/cefpython_public_api.h | 2 ++ tools/build.py | 2 +- tools/build_distrib.py | 2 +- tools/common.py | 2 ++ tools/installer/cefpython3.__init__.py | 3 +++ tools/installer/cefpython3.setup.py | 1 + tools/requirements.txt | 2 +- 8 files changed, 14 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 24370549b..4b1b67166 100644 --- a/README.md +++ b/README.md @@ -154,9 +154,9 @@ support old operating systems then choose the v31 release. OS | Py2 | Py3 | 32bit | 64bit | Requirements --- | --- | --- | --- | --- | --- -Windows | 2.7 | 3.4 / 3.5 / 3.6 / 3.7 | Yes | Yes | Windows 7+ -Linux | 2.7 | 3.4 / 3.5 / 3.6 / 3.7 | Yes | Yes | Debian 8+, Ubuntu 14.04+,
Fedora 24+, openSUSE 13.3+ -Mac | 2.7 | 3.4 / 3.5 / 3.6 / 3.7 | No | Yes | MacOS 10.9+ +Windows | 2.7 | 3.4 / 3.5 / 3.6 / 3.7 / 3.8 | Yes | Yes | Windows 7+ +Linux | 2.7 | 3.4 / 3.5 / 3.6 / 3.7 3.8 | Yes | Yes | Debian 8+, Ubuntu 14.04+,
Fedora 24+, openSUSE 13.3+ +Mac | 2.7 | 3.4 / 3.5 / 3.6 / 3.7 / 3.8 | No | Yes | MacOS 10.9+ These platforms are not supported yet: - ARM - see [Issue #267](../../issues/267) diff --git a/src/common/cefpython_public_api.h b/src/common/cefpython_public_api.h index 53ad62c63..8e4ff60b6 100644 --- a/src/common/cefpython_public_api.h +++ b/src/common/cefpython_public_api.h @@ -46,6 +46,8 @@ #include "../../build/build_cefpython/cefpython_py36_fixed.h" #elif PY_MINOR_VERSION == 7 #include "../../build/build_cefpython/cefpython_py37_fixed.h" +#elif PY_MINOR_VERSION == 8 +#include "../../build/build_cefpython/cefpython_py38_fixed.h" #endif // PY_MINOR_VERSION #endif // PY_MAJOR_VERSION diff --git a/tools/build.py b/tools/build.py index 5e578b943..53c20936a 100644 --- a/tools/build.py +++ b/tools/build.py @@ -290,7 +290,7 @@ def setup_environ(): print("[build.py] PYTHON_INCLUDE: {python_include}" .format(python_include=os.environ["PYTHON_INCLUDE"])) - os.environ["CEF_CCFLAGS"] = "-std=gnu++11 -DNDEBUG -Wall -Werror" + os.environ["CEF_CCFLAGS"] = "-std=gnu++11 -DNDEBUG -Wall -Werror -Wno-deprecated-declarations" if FAST_FLAG: os.environ["CEF_CCFLAGS"] += " -O0" else: diff --git a/tools/build_distrib.py b/tools/build_distrib.py index 8ff5a6b87..7e9d87d42 100644 --- a/tools/build_distrib.py +++ b/tools/build_distrib.py @@ -79,7 +79,7 @@ ALLOW_PARTIAL = False # Python versions -SUPPORTED_PYTHON_VERSIONS = [(2, 7), (3, 4), (3, 5), (3, 6), (3, 7)] +SUPPORTED_PYTHON_VERSIONS = [(2, 7), (3, 4), (3, 5), (3, 6), (3, 7), (3, 8)] # Python search paths. It will use first Python found for specific version. # Supports replacement of one environment variable in path eg.: %ENV_KEY%. diff --git a/tools/common.py b/tools/common.py index 113bcd9eb..226fd391e 100644 --- a/tools/common.py +++ b/tools/common.py @@ -473,6 +473,8 @@ def get_msvs_for_python(vs_prefix=False): return "VS2015" if vs_prefix else "2015" elif sys.version_info[:2] == (3, 7): return "VS2015" if vs_prefix else "2015" + elif sys.version_info[:2] == (3, 8): + return "VS2015" if vs_prefix else "2015" else: print("ERROR: This version of Python is not supported") sys.exit(1) diff --git a/tools/installer/cefpython3.__init__.py b/tools/installer/cefpython3.__init__.py index fc00000dc..794f4941c 100644 --- a/tools/installer/cefpython3.__init__.py +++ b/tools/installer/cefpython3.__init__.py @@ -60,5 +60,8 @@ elif sys.version_info[:2] == (3, 7): # noinspection PyUnresolvedReferences from . import cefpython_py37 as cefpython +elif sys.version_info[:2] == (3, 8): + # noinspection PyUnresolvedReferences + from . import cefpython_py38 as cefpython else: raise Exception("Python version not supported: " + sys.version) diff --git a/tools/installer/cefpython3.setup.py b/tools/installer/cefpython3.setup.py index 6814cbb77..2a9269137 100644 --- a/tools/installer/cefpython3.setup.py +++ b/tools/installer/cefpython3.setup.py @@ -148,6 +148,7 @@ def main(): "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Topic :: Desktop Environment", "Topic :: Internet", "Topic :: Internet :: WWW/HTTP", diff --git a/tools/requirements.txt b/tools/requirements.txt index 81ebc0c5c..4b0835794 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -1,4 +1,4 @@ -Cython == 0.28.4 +Cython == 0.29.21 docopt >= 0.6.2 setuptools wheel From 92a6c6924aec0f53bf038a32300b97138a1dadc2 Mon Sep 17 00:00:00 2001 From: linesight Date: Sun, 28 Jan 2024 11:18:26 -0800 Subject: [PATCH 04/35] update spotify prebuilt cef url --- docs/Build-instructions.md | 2 +- tools/automate.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index 5df63bec2..62e79567f 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -279,7 +279,7 @@ mkdir build/ cd build/ ``` -2) Download CEF binaries from [Spotify Automated Builds](http://opensource.spotify.com/cefbuilds/index.html). +2) Download CEF binaries from [Spotify Automated Builds](https://cef-builds.spotifycdn.com/index.html). The version of the binaries must match exactly the CEF version from the "cefpython/src/version/" directory (look for CEF_VERSION constant in .h file). diff --git a/tools/automate.py b/tools/automate.py index 80cb4ff7f..3cb1b56b4 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -14,7 +14,7 @@ Option 2 is to use CEF binaries from Spotify Automated Builds using the --prebuilt-cef flag. In such case check the cefpython/src/version/ directory to know which version of CEF to download from Spotify: -http://opensource.spotify.com/cefbuilds/index.html +https://cef-builds.spotifycdn.com/index.html Download and extract it so that for example you have such a directory: cefpython/build/cef_binary_3.2883.1553.g80bd606_windows32/ . From e8a5dc74a49b8e67f0683e8488a1f8bc966fd814 Mon Sep 17 00:00:00 2001 From: linesight Date: Sun, 28 Jan 2024 22:27:09 -0800 Subject: [PATCH 05/35] fix --- src/common/cefpython_public_api.h | 4 +++ src/compile_time_constants.pxi | 4 --- src/extern/cef/cef_request.pxd | 1 + src/extern/cef/cef_values.pxd | 4 ++- src/version/cef_version_win.h | 12 ++++----- tools/automate-git.py | 45 ++++++++++++++++++------------- tools/automate.py | 6 +++-- tools/build.py | 1 + tools/build_cpp_projects.py | 2 +- tools/build_distrib.py | 10 +++---- tools/common.py | 14 ++++++---- tools/cython_setup.py | 2 ++ tools/requirements.txt | 2 +- 13 files changed, 64 insertions(+), 43 deletions(-) diff --git a/src/common/cefpython_public_api.h b/src/common/cefpython_public_api.h index 8e4ff60b6..ea4d4dfbd 100644 --- a/src/common/cefpython_public_api.h +++ b/src/common/cefpython_public_api.h @@ -48,6 +48,10 @@ #include "../../build/build_cefpython/cefpython_py37_fixed.h" #elif PY_MINOR_VERSION == 8 #include "../../build/build_cefpython/cefpython_py38_fixed.h" +#elif PY_MINOR_VERSION == 9 +#include "../../build/build_cefpython/cefpython_py39_fixed.h" +#elif PY_MINOR_VERSION == 10 +#include "../../build/build_cefpython/cefpython_py310_fixed.h" #endif // PY_MINOR_VERSION #endif // PY_MAJOR_VERSION diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 609470c1d..632aab59c 100644 --- a/src/compile_time_constants.pxi +++ b/src/compile_time_constants.pxi @@ -1,7 +1,3 @@ # This file was generated by setup.py - -# Type this command to ignore changes to this file: -# git update-index --assume-unchanged src/compile_time_constants.pxi - DEF UNAME_SYSNAME = "Windows" DEF PY_MAJOR_VERSION = 3 diff --git a/src/extern/cef/cef_request.pxd b/src/extern/cef/cef_request.pxd index e7bd336d0..0ec425ae3 100644 --- a/src/extern/cef/cef_request.pxd +++ b/src/extern/cef/cef_request.pxd @@ -53,6 +53,7 @@ cdef extern from "include/cef_request.h": # noinspection PyUnresolvedReferences ctypedef cef_postdataelement_type_t ElementType + @staticmethod cdef CefRefPtr[CefPostDataElement] CefPostDataElement_Create \ "CefPostDataElement::Create"() cdef cppclass CefPostDataElement: diff --git a/src/extern/cef/cef_values.pxd b/src/extern/cef/cef_values.pxd index ee0bf5065..003d19e4c 100644 --- a/src/extern/cef/cef_values.pxd +++ b/src/extern/cef/cef_values.pxd @@ -9,6 +9,7 @@ from libcpp.vector cimport vector from cef_types cimport cef_value_type_t cdef extern from "include/cef_values.h": + @staticmethod cdef CefRefPtr[CefBinaryValue] CefBinaryValue_Create \ "CefBinaryValue::Create"(const void* data, size_t data_size) @@ -31,7 +32,8 @@ cdef extern from "include/cef_values.h": CefRefPtr[CefBinaryValue] Copy() size_t GetSize() size_t GetData(void* buffer_, size_t buffer_size, size_t data_offset) - + + @staticmethod cdef CefRefPtr[CefDictionaryValue] CefDictionaryValue_Create \ "CefDictionaryValue::Create"() diff --git a/src/version/cef_version_win.h b/src/version/cef_version_win.h index 50e9b4efd..38503e344 100644 --- a/src/version/cef_version_win.h +++ b/src/version/cef_version_win.h @@ -35,16 +35,16 @@ #ifndef CEF_INCLUDE_CEF_VERSION_H_ #define CEF_INCLUDE_CEF_VERSION_H_ -#define CEF_VERSION "3.3359.1774.gd49d25f" +#define CEF_VERSION "120.2.7+g4bc6a59+chromium-120.0.6099.234" #define CEF_VERSION_MAJOR 3 -#define CEF_COMMIT_NUMBER 1774 -#define CEF_COMMIT_HASH "d49d25f881b68f418e243e12801cbbb7caebb563" +#define CEF_COMMIT_NUMBER 6099 +#define CEF_COMMIT_HASH "4bc6a5995a1aaa0bd39c87dc87a10c713a3d1553" #define COPYRIGHT_YEAR 2018 -#define CHROME_VERSION_MAJOR 66 +#define CHROME_VERSION_MAJOR 120 #define CHROME_VERSION_MINOR 0 -#define CHROME_VERSION_BUILD 3359 -#define CHROME_VERSION_PATCH 181 +#define CHROME_VERSION_BUILD 6099 +#define CHROME_VERSION_PATCH 234 #define DO_MAKE_STRING(p) #p #define MAKE_STRING(p) DO_MAKE_STRING(p) diff --git a/tools/automate-git.py b/tools/automate-git.py index 717334687..8c5a13b97 100644 --- a/tools/automate-git.py +++ b/tools/automate-git.py @@ -940,6 +940,12 @@ def check_pattern_matches(output_file=None): dest='armbuild', default=False, help='Create an ARM build.') +parser.add_option( + '--with-pgo-profiles', + action='store_true', + dest='withpgoprofiles', + default=False, + help='Download PGO profiles for the build.') # Test-related options. parser.add_option( @@ -1401,25 +1407,28 @@ def check_pattern_matches(output_file=None): # Exclude unnecessary directories. Intentionally written without newlines. gclient_spec = \ "solutions = [{"+\ - "u'managed': False,"+\ - "u'name': u'src', "+\ - "u'url': u'" + chromium_url + "', "+\ - "u'custom_deps': {"+\ - "u'build': None, "+\ - "u'build/scripts/command_wrapper/bin': None, "+\ - "u'build/scripts/gsd_generate_index': None, "+\ - "u'build/scripts/private/data/reliability': None, "+\ - "u'build/scripts/tools/deps2git': None, "+\ - "u'build/third_party/lighttpd': None, "+\ - "u'commit-queue': None, "+\ - "u'depot_tools': None, "+\ - "u'src/chrome_frame/tools/test/reference_build/chrome': None, "+\ - "u'src/chrome/tools/test/reference_build/chrome_linux': None, "+\ - "u'src/chrome/tools/test/reference_build/chrome_mac': None, "+\ - "u'src/chrome/tools/test/reference_build/chrome_win': None, "+\ + "'managed': False,"+\ + "'name': 'src', "+\ + "'url': '" + chromium_url + "', "+\ + "'custom_vars': {"+\ + "'checkout_pgo_profiles': " + ('True' if options.withpgoprofiles else 'False') + ", "+\ + "}, "+\ + "'custom_deps': {"+\ + "'build': None, "+\ + "'build/scripts/command_wrapper/bin': None, "+\ + "'build/scripts/gsd_generate_index': None, "+\ + "'build/scripts/private/data/reliability': None, "+\ + "'build/scripts/tools/deps2git': None, "+\ + "'build/third_party/lighttpd': None, "+\ + "'commit-queue': None, "+\ + "'depot_tools': None, "+\ + "'src/chrome_frame/tools/test/reference_build/chrome': None, "+\ + "'src/chrome/tools/test/reference_build/chrome_linux': None, "+\ + "'src/chrome/tools/test/reference_build/chrome_mac': None, "+\ + "'src/chrome/tools/test/reference_build/chrome_win': None, "+\ "}, "+\ - "u'deps_file': u'" + deps_file + "', "+\ - "u'safesync_url': u''"+\ + "'deps_file': '" + deps_file + "', "+\ + "'safesync_url': ''"+\ "}]" msg('Writing file: %s' % gclient_file) diff --git a/tools/automate.py b/tools/automate.py index 3cb1b56b4..f43fef0b4 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -180,7 +180,7 @@ def setup_options(docopt_args): # --gyp-msvs-version if not Options.gyp_msvs_version: if int(Options.cef_branch) >= 2704: - Options.gyp_msvs_version = "2015" + Options.gyp_msvs_version = "2022" else: Options.gyp_msvs_version = "2013" @@ -870,6 +870,7 @@ def get_available_python_compilers(): ("2008", VS2008_VCVARS), ("2010", VS2010_VCVARS), ("2015", VS2015_VCVARS), + ("2022", VS2015_VCVARS), ]) ret_compilers = OrderedDict() for msvs in all_python_compilers: @@ -980,7 +981,7 @@ def run_automate_git(): """ Example automate-git.py command: C:\chromium>call python automate-git.py --download-dir=./test/ - --branch=2526 --no-debug-build --verbose-build + --branch=2526 --no-debug-build --verbose-build --with-pgo-profiles Run ninja build manually: cd chromium/src ninja -v -j2 -Cout\Release cefclient @@ -1006,6 +1007,7 @@ def run_automate_git(): if Options.force_chromium_update: args.append("--force-update") args.append("--no-distrib-archive") + args.append("--with-pgo-profiles") if platform.system() == "Linux": # Building cefclient target isn't supported on Linux when # using sysroot (cef/#1916). However building cefclient diff --git a/tools/build.py b/tools/build.py index 53c20936a..bb29797e3 100644 --- a/tools/build.py +++ b/tools/build.py @@ -779,6 +779,7 @@ def build_cefpython_module(): enable_line_tracing=enable_line_tracing)) if FAST_FLAG: command += " --fast" + print('cython:', command) ret = subprocess.call(command, shell=True) # if DEBUG_FLAG: diff --git a/tools/build_cpp_projects.py b/tools/build_cpp_projects.py index e8e152668..aa6ea38c0 100644 --- a/tools/build_cpp_projects.py +++ b/tools/build_cpp_projects.py @@ -160,7 +160,7 @@ def build_cefpython_app_library(): def build_subprocess_executable(): - print("[buil_cpp_projects.py] Build executable: subprocess") + print("[build_cpp_projects.py] Build executable: subprocess") compiler = get_compiler(static=True) sources = get_sources(SUBPROCESS_DIR, exclude_names=["print_handler_gtk.cpp"]) diff --git a/tools/build_distrib.py b/tools/build_distrib.py index 7e9d87d42..55fee70e4 100644 --- a/tools/build_distrib.py +++ b/tools/build_distrib.py @@ -79,7 +79,7 @@ ALLOW_PARTIAL = False # Python versions -SUPPORTED_PYTHON_VERSIONS = [(2, 7), (3, 4), (3, 5), (3, 6), (3, 7), (3, 8)] +SUPPORTED_PYTHON_VERSIONS = [(2, 7), (3, 4), (3, 5), (3, 6), (3, 7), (3, 8), (3, 9), (3, 10)] # Python search paths. It will use first Python found for specific version. # Supports replacement of one environment variable in path eg.: %ENV_KEY%. @@ -273,7 +273,7 @@ def search_for_pythons(search_arch): .format(executable=python)) sys.exit(1) version_str = subprocess.check_output([python, "-c", - version_code]) + version_code]).decode() version_str = version_str.strip() match = re.search("^\((\d+), (\d+), (\d+)\)$", version_str) assert match, version_str @@ -284,7 +284,7 @@ def search_for_pythons(search_arch): version_tuple3 = (int(major), int(minor), int(micro)) arch_code = ("import platform;" "print(str(platform.architecture()[0]));") - arch = subprocess.check_output([python, "-c", arch_code]) + arch = subprocess.check_output([python, "-c", arch_code]).decode() arch = arch.strip() if version_tuple2 in SUPPORTED_PYTHON_VERSIONS \ and arch == search_arch: @@ -376,8 +376,8 @@ def uninstall_cefpython3_packages(pythons): command = ("\"{python}\" -m pip show cefpython3" .format(python=python["executable"])) try: - output = subprocess.check_output(command, shell=True) - except subprocess.CalledProcessError, exc: + output = subprocess.check_output(command, shell=True).decode() + except subprocess.CalledProcessError as exc: # pip show returns error code when package is not installed output = exc.output if not len(output.strip()): diff --git a/tools/common.py b/tools/common.py index 226fd391e..e3fd621e6 100644 --- a/tools/common.py +++ b/tools/common.py @@ -48,7 +48,7 @@ CEF_POSTFIX2 = "unknown" # Upstream CEF binaries postfix if OS_POSTFIX == "win": - OS_POSTFIX2 = "win32" if ARCH32 else "win64" + OS_POSTFIX2 = "windows32" if ARCH32 else "windows64" CEF_POSTFIX2 = "windows32" if ARCH32 else "windows64" elif OS_POSTFIX == "mac": OS_POSTFIX2 = "mac32" if ARCH32 else "mac64" @@ -219,8 +219,7 @@ VS_PLATFORM_ARG = "x86" if ARCH32 else "amd64" -VS2015_VCVARS = ("C:\\Program Files (x86)\\Microsoft Visual Studio 14.0" - "\\VC\\vcvarsall.bat") +VS2015_VCVARS = (r"C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat") VS2013_VCVARS = ("C:\\Program Files (x86)\\Microsoft Visual Studio 12.0" "\\VC\\vcvarsall.bat") @@ -270,7 +269,8 @@ def get_python_include_path(): # 3) ~/.pyenv/versions/3.4.6/include/python2.7m # 4) /usr/include/python2.7 base_dir = os.path.dirname(sys.executable) - try_dirs = ["{base_dir}/include", + try_dirs = [r"C:\Users\opopp\AppData\Local\Programs\Python\Python310\include", + "{base_dir}/include", "{base_dir}/../include/python{ver}", "{base_dir}/../include/python{ver}*", ("{base_dir}/../Frameworks/Python.framework/Versions/{ver}" @@ -451,7 +451,7 @@ def get_cefpython_version(): def get_version_from_file(header_file): - with open(header_file, "rU") as fp: + with open(header_file, "r") as fp: contents = fp.read() # no need to decode() as "rU" specified ret = dict() matches = re.findall(r'^#define (\w+) "?([^\s"]+)"?', contents, @@ -475,6 +475,10 @@ def get_msvs_for_python(vs_prefix=False): return "VS2015" if vs_prefix else "2015" elif sys.version_info[:2] == (3, 8): return "VS2015" if vs_prefix else "2015" + elif sys.version_info[:2] == (3, 9): + return "VS2015" if vs_prefix else "2015" + elif sys.version_info[:2] == (3, 10): + return "VS2015" if vs_prefix else "2022" else: print("ERROR: This version of Python is not supported") sys.exit(1) diff --git a/tools/cython_setup.py b/tools/cython_setup.py index 4f0cafc6e..f7dc3e878 100644 --- a/tools/cython_setup.py +++ b/tools/cython_setup.py @@ -147,6 +147,7 @@ def get_winsdk_lib(): if WINDOWS: if ARCH32: winsdk_libs = [ + r"C:\Program Files (x86)\Microsoft SDKs\Windows Kits\10", r"C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Lib", r"C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0\\Lib", # Visual Studio 2008 installation @@ -154,6 +155,7 @@ def get_winsdk_lib(): ] elif ARCH64: winsdk_libs = [ + r"C:\Program Files (x86)\Microsoft SDKs\Windows Kits\10", r"C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Lib\\x64", r"C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0\\Lib\\x64", # Visual Studio 2008 installation diff --git a/tools/requirements.txt b/tools/requirements.txt index 4b0835794..0cf341874 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -1,4 +1,4 @@ -Cython == 0.29.21 +Cython == 0.29.37 docopt >= 0.6.2 setuptools wheel From f49ab606fd9f4554b2342185a51d0a47f4d2992c Mon Sep 17 00:00:00 2001 From: linesight Date: Sat, 11 May 2024 10:52:55 -0700 Subject: [PATCH 06/35] add support for cef 123 version --- .gitignore | 3 + api/LifespanHandler.md | 20 +- examples/hello_world.py | 3 +- examples/pysdl2.py | 9 +- examples/pywin32.py | 3 +- examples/qt.py | 29 +- examples/screenshot.py | 8 +- examples/tkinter_.py | 3 +- examples/tutorial.py | 4 +- examples/wxpython.py | 3 +- src/browser.pyx | 111 +- src/cefpython.pyx | 26 +- src/client_handler/client_handler.cpp | 18 +- src/client_handler/client_handler.h | 1 + src/client_handler/cookie_visitor.h | 2 +- src/client_handler/dialog_handler.cpp | 2 - src/client_handler/dialog_handler.h | 1 - src/client_handler/display_handler.cpp | 9 + src/client_handler/display_handler.h | 6 + src/client_handler/dpi_aware.cpp | 3 +- src/client_handler/lifespan_handler.cpp | 3 +- src/client_handler/lifespan_handler.h | 1 + src/client_handler/render_handler.cpp | 14 +- src/client_handler/render_handler.h | 8 +- .../request_context_handler.cpp | 38 +- src/client_handler/request_context_handler.h | 12 +- src/client_handler/request_handler.cpp | 37 +- src/client_handler/request_handler.h | 25 +- src/client_handler/resource_handler.cpp | 18 +- src/client_handler/resource_handler.h | 8 +- src/client_handler/string_visitor.h | 2 +- src/client_handler/task.cpp | 11 +- src/client_handler/task.h | 2 +- src/client_handler/web_request_client.cpp | 8 +- src/client_handler/web_request_client.h | 14 +- src/compile_time_constants.pxi | 3 + src/cookie.pyx | 96 +- src/dpi_aware_win.pyx | 4 +- src/extern/cef/cef_app.pxd | 2 - src/extern/cef/cef_browser.pxd | 15 +- src/extern/cef/cef_browser_static.pxd | 2 + src/extern/cef/cef_cookie.pxd | 3 - src/extern/cef/cef_frame.pxd | 6 +- src/extern/cef/cef_ptr.pxd | 4 + src/extern/cef/cef_request_context.pxd | 2 +- src/extern/cef/cef_request_handler.pxd | 4 - src/extern/cef/cef_response.pxd | 2 +- src/extern/cef/cef_scoped_ptr.pxd | 17 - src/extern/cef/cef_task.pxd | 4 +- src/extern/cef/cef_time.pxd | 4 + src/extern/cef/cef_types.pxd | 50 +- src/extern/cef/cef_web_plugin.pxd | 14 - src/extern/cef/cef_win.pxd | 5 +- src/extern/main_message_loop.pxd | 4 +- src/extern/task.pxd | 4 +- src/frame.pyx | 84 +- src/handlers/display_handler.pyx | 20 + src/handlers/lifespan_handler.pyx | 31 +- src/handlers/render_handler.pyx | 27 +- src/handlers/request_handler.pyx | 117 +- src/handlers/resource_handler.pyx | 6 +- src/handlers/v8context_handler.pyx | 10 +- src/handlers/v8function_handler.pyx | 4 +- src/include/base/cef_atomic_flag.h | 97 + src/include/base/cef_atomic_ref_count.h | 164 +- src/include/base/cef_atomicops.h | 199 - src/include/base/cef_auto_reset.h | 90 + src/include/base/cef_bind.h | 823 +- src/include/base/cef_bind_helpers.h | 579 - src/include/base/cef_build.h | 238 +- src/include/base/cef_callback.h | 889 +- src/include/base/cef_callback_forward.h | 24 +- src/include/base/cef_callback_helpers.h | 222 +- src/include/base/cef_callback_list.h | 650 +- src/include/base/cef_cancelable_callback.h | 308 +- src/include/base/cef_compiler_specific.h | 382 + src/include/base/cef_lock.h | 52 +- src/include/base/cef_logging.h | 301 +- src/include/base/cef_macros.h | 183 +- src/include/base/cef_move.h | 261 - src/include/base/cef_platform_thread.h | 48 +- .../base/{cef_basictypes.h => cef_ptr_util.h} | 75 +- src/include/base/cef_ref_counted.h | 543 +- src/include/base/cef_scoped_ptr.h | 625 - src/include/base/cef_scoped_refptr.h | 420 + src/include/base/cef_string16.h | 214 - src/include/base/cef_template_util.h | 214 - src/include/base/cef_thread_checker.h | 94 +- .../base/cef_thread_collision_warner.h | 276 - src/include/base/cef_trace_event.h | 546 +- src/include/base/cef_tuple.h | 1624 +-- src/include/base/cef_weak_ptr.h | 452 +- src/include/base/internal/README-TRANSFER.txt | 6 + .../base/internal/cef_atomicops_arm_gcc.h | 325 - .../cef_atomicops_atomicword_compat.h | 124 - src/include/base/internal/cef_atomicops_mac.h | 223 - .../base/internal/cef_atomicops_x86_gcc.h | 268 - .../base/internal/cef_atomicops_x86_msvc.h | 221 - src/include/base/internal/cef_bind_internal.h | 4064 ++---- .../base/internal/cef_bind_internal_win.h | 396 - .../base/internal/cef_callback_internal.h | 323 +- src/include/base/internal/cef_lock_impl.h | 8 +- .../base/internal/cef_net_error_list.h | 1041 ++ .../cef_raw_scoped_refptr_mismatch_checker.h | 144 +- src/include/base/internal/cef_scoped_policy.h | 53 + .../capi/cef_accessibility_handler_capi.h | 81 + src/include/capi/cef_app_capi.h | 194 + src/include/capi/cef_audio_handler_capi.h | 121 + src/include/capi/cef_auth_callback_capi.h | 76 + src/include/capi/cef_base_capi.h | 107 + src/include/capi/cef_browser_capi.h | 1017 ++ .../capi/cef_browser_process_handler_capi.h | 177 + src/include/capi/cef_callback_capi.h | 88 + src/include/capi/cef_client_capi.h | 210 + src/include/capi/cef_command_handler_capi.h | 120 + src/include/capi/cef_command_line_capi.h | 215 + .../capi/cef_context_menu_handler_capi.h | 367 + src/include/capi/cef_cookie_capi.h | 199 + src/include/capi/cef_crash_util_capi.h | 154 + .../capi/cef_devtools_message_observer_capi.h | 148 + src/include/capi/cef_dialog_handler_capi.h | 111 + src/include/capi/cef_display_handler_capi.h | 178 + src/include/capi/cef_dom_capi.h | 345 + src/include/capi/cef_download_handler_capi.h | 150 + src/include/capi/cef_download_item_capi.h | 174 + src/include/capi/cef_drag_data_capi.h | 240 + src/include/capi/cef_drag_handler_capi.h | 92 + src/include/capi/cef_extension_capi.h | 130 + src/include/capi/cef_extension_handler_capi.h | 212 + src/include/capi/cef_file_util_capi.h | 132 + src/include/capi/cef_find_handler_capi.h | 82 + src/include/capi/cef_focus_handler_capi.h | 93 + src/include/capi/cef_frame_capi.h | 257 + src/include/capi/cef_frame_handler_capi.h | 195 + src/include/capi/cef_i18n_util_capi.h | 58 + src/include/capi/cef_image_capi.h | 206 + src/include/capi/cef_jsdialog_handler_capi.h | 141 + src/include/capi/cef_keyboard_handler_capi.h | 90 + src/include/capi/cef_life_span_handler_capi.h | 253 + src/include/capi/cef_load_handler_capi.h | 126 + src/include/capi/cef_media_router_capi.h | 342 + src/include/capi/cef_menu_model_capi.h | 517 + .../capi/cef_menu_model_delegate_capi.h | 123 + src/include/capi/cef_navigation_entry_capi.h | 133 + src/include/capi/cef_origin_whitelist_capi.h | 112 + src/include/capi/cef_parser_capi.h | 184 + src/include/capi/cef_path_util_capi.h | 59 + .../capi/cef_permission_handler_capi.h | 164 + src/include/capi/cef_preference_capi.h | 148 + src/include/capi/cef_print_handler_capi.h | 160 + src/include/capi/cef_print_settings_capi.h | 202 + src/include/capi/cef_process_message_capi.h | 111 + src/include/capi/cef_process_util_capi.h | 65 + src/include/capi/cef_registration_capi.h | 63 + src/include/capi/cef_render_handler_capi.h | 261 + .../capi/cef_render_process_handler_capi.h | 168 + src/include/capi/cef_request_capi.h | 355 + src/include/capi/cef_request_context_capi.h | 398 + .../capi/cef_request_context_handler_capi.h | 108 + src/include/capi/cef_request_handler_capi.h | 247 + src/include/capi/cef_resource_bundle_capi.h | 104 + .../capi/cef_resource_bundle_handler_capi.h | 105 + src/include/capi/cef_resource_handler_capi.h | 210 + .../capi/cef_resource_request_handler_capi.h | 255 + src/include/capi/cef_response_capi.h | 177 + src/include/capi/cef_response_filter_capi.h | 110 + src/include/capi/cef_scheme_capi.h | 140 + src/include/capi/cef_server_capi.h | 328 + .../capi/cef_shared_memory_region_capi.h | 79 + .../cef_shared_process_message_builder_capi.h | 101 + src/include/capi/cef_ssl_info_capi.h | 82 + src/include/capi/cef_ssl_status_capi.h | 95 + src/include/capi/cef_stream_capi.h | 263 + src/include/capi/cef_string_visitor_capi.h | 69 + src/include/capi/cef_task_capi.h | 158 + src/include/capi/cef_thread_capi.h | 117 + src/include/capi/cef_trace_capi.h | 120 + src/include/capi/cef_urlrequest_capi.h | 211 + src/include/capi/cef_v8_capi.h | 1027 ++ src/include/capi/cef_values_capi.h | 761 + src/include/capi/cef_waitable_event_capi.h | 117 + src/include/capi/cef_x509_certificate_capi.h | 199 + src/include/capi/cef_xml_reader_capi.h | 274 + src/include/capi/cef_zip_reader_capi.h | 148 + src/include/capi/test/cef_test_helpers_capi.h | 74 + src/include/capi/test/cef_test_server_capi.h | 197 + .../capi/test/cef_translator_test_capi.h | 763 + src/include/capi/views/cef_box_layout_capi.h | 88 + .../capi/views/cef_browser_view_capi.h | 123 + .../views/cef_browser_view_delegate_capi.h | 150 + src/include/capi/views/cef_button_capi.h | 104 + .../capi/views/cef_button_delegate_capi.h | 80 + src/include/capi/views/cef_display_capi.h | 175 + src/include/capi/views/cef_fill_layout_capi.h | 65 + .../capi/views/cef_label_button_capi.h | 163 + src/include/capi/views/cef_layout_capi.h | 85 + src/include/capi/views/cef_menu_button_capi.h | 99 + .../views/cef_menu_button_delegate_capi.h | 89 + .../capi/views/cef_overlay_controller_capi.h | 217 + src/include/capi/views/cef_panel_capi.h | 151 + .../capi/views/cef_panel_delegate_capi.h | 65 + src/include/capi/views/cef_scroll_view_capi.h | 112 + src/include/capi/views/cef_textfield_capi.h | 275 + .../capi/views/cef_textfield_delegate_capi.h | 83 + src/include/capi/views/cef_view_capi.h | 413 + .../capi/views/cef_view_delegate_capi.h | 149 + src/include/capi/views/cef_window_capi.h | 379 + .../capi/views/cef_window_delegate_capi.h | 233 + src/include/cef_accessibility_handler.h | 14 +- src/include/cef_api_hash.h | 71 + src/include/cef_app.h | 149 +- src/include/cef_application_mac.h | 110 - src/include/cef_audio_handler.h | 111 + src/include/cef_auth_callback.h | 8 +- src/include/cef_base.h | 138 +- src/include/cef_browser.h | 803 +- src/include/cef_browser_process_handler.h | 127 +- src/include/cef_callback.h | 10 +- src/include/cef_client.h | 110 +- src/include/cef_command_handler.h | 114 + src/include/cef_command_ids.h | 432 + src/include/cef_command_line.h | 88 +- src/include/cef_config.h | 40 + src/include/cef_context_menu_handler.h | 199 +- src/include/cef_cookie.h | 151 +- src/include/cef_crash_util.h | 181 +- src/include/cef_devtools_message_observer.h | 132 + src/include/cef_dialog_handler.h | 50 +- src/include/cef_display_handler.h | 79 +- src/include/cef_dom.h | 116 +- src/include/cef_download_handler.h | 56 +- src/include/cef_download_item.h | 64 +- src/include/cef_drag_data.h | 85 +- src/include/cef_drag_handler.h | 24 +- src/include/cef_extension.h | 49 +- src/include/cef_extension_handler.h | 119 +- src/include/cef_file_util.h | 81 +- src/include/cef_find_handler.h | 16 +- src/include/cef_focus_handler.h | 20 +- src/include/cef_frame.h | 136 +- src/include/cef_frame_handler.h | 177 + src/include/cef_i18n_util.h | 49 + src/include/cef_image.h | 97 +- src/include/cef_jsdialog_handler.h | 60 +- src/include/cef_keyboard_handler.h | 22 +- src/include/cef_life_span_handler.h | 271 +- src/include/cef_load_handler.h | 63 +- src/include/cef_media_router.h | 317 + src/include/cef_menu_model.h | 286 +- src/include/cef_menu_model_delegate.h | 28 +- src/include/cef_navigation_entry.h | 39 +- src/include/cef_origin_whitelist.h | 77 +- src/include/cef_pack_resources.h | 1684 +++ src/include/cef_pack_strings.h | 11495 ++++++++++++++++ src/include/cef_parser.h | 105 +- src/include/cef_path_util.h | 15 +- src/include/cef_permission_handler.h | 149 + src/include/cef_preference.h | 134 + src/include/cef_print_handler.h | 51 +- src/include/cef_print_settings.h | 62 +- src/include/cef_process_message.h | 28 +- src/include/cef_process_util.h | 16 +- src/include/cef_registration.h | 49 + src/include/cef_render_handler.h | 158 +- src/include/cef_render_process_handler.h | 78 +- src/include/cef_request.h | 153 +- src/include/cef_request_context.h | 399 +- src/include/cef_request_context_handler.h | 80 +- src/include/cef_request_handler.h | 324 +- src/include/cef_resource_bundle.h | 52 +- src/include/cef_resource_bundle_handler.h | 38 +- src/include/cef_resource_handler.h | 159 +- src/include/cef_resource_request_handler.h | 250 + src/include/cef_response.h | 66 +- src/include/cef_response_filter.h | 65 +- src/include/cef_sandbox_win.h | 41 +- src/include/cef_scheme.h | 125 +- src/include/cef_server.h | 233 +- src/include/cef_shared_memory_region.h | 69 + .../cef_shared_process_message_builder.h | 87 + src/include/cef_ssl_info.h | 17 +- src/include/cef_ssl_status.h | 14 +- src/include/cef_stream.h | 116 +- src/include/cef_string_visitor.h | 4 +- src/include/cef_task.h | 75 +- src/include/cef_thread.h | 60 +- src/include/cef_trace.h | 73 +- src/include/cef_urlrequest.h | 115 +- src/include/cef_v8.h | 756 +- src/include/cef_values.h | 443 +- src/include/cef_version.h | 81 + src/include/cef_waitable_event.h | 58 +- src/include/cef_web_plugin.h | 215 - src/include/cef_x509_certificate.h | 78 +- src/include/cef_xml_reader.h | 114 +- src/include/cef_zip_reader.h | 56 +- src/include/internal/cef_app_win.h | 100 + src/include/internal/cef_linux.h | 127 - src/include/internal/cef_logging_internal.h | 12 +- src/include/internal/cef_mac.h | 134 - src/include/internal/cef_ptr.h | 304 +- src/include/internal/cef_string.h | 2 +- src/include/internal/cef_string_list.h | 22 +- src/include/internal/cef_string_map.h | 23 +- src/include/internal/cef_string_multimap.h | 26 +- src/include/internal/cef_string_types.h | 104 +- src/include/internal/cef_string_wrappers.h | 527 +- src/include/internal/cef_thread_internal.h | 8 +- src/include/internal/cef_time.h | 104 +- src/include/internal/cef_time_wrappers.h | 111 + .../internal/cef_trace_event_internal.h | 57 +- src/include/internal/cef_types.h | 3024 ++-- .../internal/cef_types_content_settings.h | 443 + src/include/internal/cef_types_geometry.h | 78 + src/include/internal/cef_types_linux.h | 111 - src/include/internal/cef_types_mac.h | 121 - src/include/internal/cef_types_win.h | 50 +- src/include/internal/cef_types_wrappers.h | 627 +- src/include/internal/cef_win.h | 123 +- src/include/test/cef_test_helpers.h | 13 +- src/include/test/cef_test_server.h | 184 + src/include/test/cef_translator_test.h | 252 +- src/include/views/cef_box_layout.h | 26 +- src/include/views/cef_browser_view.h | 51 +- src/include/views/cef_browser_view_delegate.h | 84 +- src/include/views/cef_button.h | 21 +- src/include/views/cef_button_delegate.h | 10 +- src/include/views/cef_display.h | 90 +- src/include/views/cef_fill_layout.h | 6 +- src/include/views/cef_label_button.h | 69 +- src/include/views/cef_layout.h | 12 +- src/include/views/cef_menu_button.h | 40 +- src/include/views/cef_menu_button_delegate.h | 16 +- src/include/views/cef_overlay_controller.h | 210 + src/include/views/cef_panel.h | 40 +- src/include/views/cef_panel_delegate.h | 4 +- src/include/views/cef_scroll_view.h | 24 +- src/include/views/cef_textfield.h | 117 +- src/include/views/cef_textfield_delegate.h | 14 +- src/include/views/cef_view.h | 234 +- src/include/views/cef_view_delegate.h | 59 +- src/include/views/cef_window.h | 209 +- src/include/views/cef_window_delegate.h | 145 +- src/include/wrapper/cef_byte_read_handler.h | 29 +- src/include/wrapper/cef_closure_task.h | 107 +- src/include/wrapper/cef_helpers.h | 103 +- src/include/wrapper/cef_message_router.h | 258 +- src/include/wrapper/cef_resource_manager.h | 221 +- src/include/wrapper/cef_scoped_temp_dir.h | 60 +- .../wrapper/cef_stream_resource_handler.h | 49 +- src/include/wrapper/cef_xml_object.h | 110 +- src/include/wrapper/cef_zip_archive.h | 58 +- src/javascript_bindings.pyx | 2 +- src/javascript_callback.pyx | 10 +- src/process_message_utils.pyx | 25 +- src/request.pyx | 2 +- src/response.pyx | 8 +- src/settings.pyx | 111 +- src/subprocess/cefpython_app.cpp | 96 +- src/subprocess/cefpython_app.h | 13 +- src/subprocess/javascript_callback.cpp | 12 +- src/subprocess/main.cpp | 3 - .../main_message_loop/main_message_loop.cpp | 14 +- .../main_message_loop/main_message_loop.h | 33 +- .../main_message_loop_external_pump.cpp | 10 +- .../main_message_loop_external_pump.h | 12 +- .../main_message_loop_external_pump_win.cpp | 43 +- .../main_message_loop/main_message_loop_std.h | 10 +- src/subprocess/v8function_handler.cpp | 9 +- src/subprocess/v8function_handler.h | 2 +- src/subprocess/v8utils.cpp | 10 +- src/time_utils.pyx | 16 + src/utils.pyx | 4 +- src/version/cef_version_win.h | 12 +- src/web_plugin_info.pyx | 26 - src/web_request.pyx | 11 +- src/window_info.pyx | 14 +- tools/automate.py | 3 +- tools/build_cpp_projects.py | 2 + tools/build_distrib.py | 7 +- tools/common.py | 6 +- tools/cython_setup.py | 6 +- tools/installer/cefpython3.__init__.py | 19 +- tools/installer/cefpython3.setup.py | 3 + tools/make_installer.py | 10 +- tools/requirements.txt | 2 +- unittests/_common.py | 40 +- unittests/main_test.py | 71 +- unittests/osr_test.py | 4 +- 389 files changed, 52165 insertions(+), 20327 deletions(-) delete mode 100644 src/extern/cef/cef_scoped_ptr.pxd delete mode 100644 src/extern/cef/cef_web_plugin.pxd create mode 100644 src/include/base/cef_atomic_flag.h delete mode 100644 src/include/base/cef_atomicops.h create mode 100644 src/include/base/cef_auto_reset.h delete mode 100644 src/include/base/cef_bind_helpers.h create mode 100644 src/include/base/cef_compiler_specific.h delete mode 100644 src/include/base/cef_move.h rename src/include/base/{cef_basictypes.h => cef_ptr_util.h} (51%) delete mode 100644 src/include/base/cef_scoped_ptr.h create mode 100644 src/include/base/cef_scoped_refptr.h delete mode 100644 src/include/base/cef_string16.h delete mode 100644 src/include/base/cef_template_util.h delete mode 100644 src/include/base/cef_thread_collision_warner.h create mode 100644 src/include/base/internal/README-TRANSFER.txt delete mode 100644 src/include/base/internal/cef_atomicops_arm_gcc.h delete mode 100644 src/include/base/internal/cef_atomicops_atomicword_compat.h delete mode 100644 src/include/base/internal/cef_atomicops_mac.h delete mode 100644 src/include/base/internal/cef_atomicops_x86_gcc.h delete mode 100644 src/include/base/internal/cef_atomicops_x86_msvc.h delete mode 100644 src/include/base/internal/cef_bind_internal_win.h create mode 100644 src/include/base/internal/cef_net_error_list.h create mode 100644 src/include/base/internal/cef_scoped_policy.h create mode 100644 src/include/capi/cef_accessibility_handler_capi.h create mode 100644 src/include/capi/cef_app_capi.h create mode 100644 src/include/capi/cef_audio_handler_capi.h create mode 100644 src/include/capi/cef_auth_callback_capi.h create mode 100644 src/include/capi/cef_base_capi.h create mode 100644 src/include/capi/cef_browser_capi.h create mode 100644 src/include/capi/cef_browser_process_handler_capi.h create mode 100644 src/include/capi/cef_callback_capi.h create mode 100644 src/include/capi/cef_client_capi.h create mode 100644 src/include/capi/cef_command_handler_capi.h create mode 100644 src/include/capi/cef_command_line_capi.h create mode 100644 src/include/capi/cef_context_menu_handler_capi.h create mode 100644 src/include/capi/cef_cookie_capi.h create mode 100644 src/include/capi/cef_crash_util_capi.h create mode 100644 src/include/capi/cef_devtools_message_observer_capi.h create mode 100644 src/include/capi/cef_dialog_handler_capi.h create mode 100644 src/include/capi/cef_display_handler_capi.h create mode 100644 src/include/capi/cef_dom_capi.h create mode 100644 src/include/capi/cef_download_handler_capi.h create mode 100644 src/include/capi/cef_download_item_capi.h create mode 100644 src/include/capi/cef_drag_data_capi.h create mode 100644 src/include/capi/cef_drag_handler_capi.h create mode 100644 src/include/capi/cef_extension_capi.h create mode 100644 src/include/capi/cef_extension_handler_capi.h create mode 100644 src/include/capi/cef_file_util_capi.h create mode 100644 src/include/capi/cef_find_handler_capi.h create mode 100644 src/include/capi/cef_focus_handler_capi.h create mode 100644 src/include/capi/cef_frame_capi.h create mode 100644 src/include/capi/cef_frame_handler_capi.h create mode 100644 src/include/capi/cef_i18n_util_capi.h create mode 100644 src/include/capi/cef_image_capi.h create mode 100644 src/include/capi/cef_jsdialog_handler_capi.h create mode 100644 src/include/capi/cef_keyboard_handler_capi.h create mode 100644 src/include/capi/cef_life_span_handler_capi.h create mode 100644 src/include/capi/cef_load_handler_capi.h create mode 100644 src/include/capi/cef_media_router_capi.h create mode 100644 src/include/capi/cef_menu_model_capi.h create mode 100644 src/include/capi/cef_menu_model_delegate_capi.h create mode 100644 src/include/capi/cef_navigation_entry_capi.h create mode 100644 src/include/capi/cef_origin_whitelist_capi.h create mode 100644 src/include/capi/cef_parser_capi.h create mode 100644 src/include/capi/cef_path_util_capi.h create mode 100644 src/include/capi/cef_permission_handler_capi.h create mode 100644 src/include/capi/cef_preference_capi.h create mode 100644 src/include/capi/cef_print_handler_capi.h create mode 100644 src/include/capi/cef_print_settings_capi.h create mode 100644 src/include/capi/cef_process_message_capi.h create mode 100644 src/include/capi/cef_process_util_capi.h create mode 100644 src/include/capi/cef_registration_capi.h create mode 100644 src/include/capi/cef_render_handler_capi.h create mode 100644 src/include/capi/cef_render_process_handler_capi.h create mode 100644 src/include/capi/cef_request_capi.h create mode 100644 src/include/capi/cef_request_context_capi.h create mode 100644 src/include/capi/cef_request_context_handler_capi.h create mode 100644 src/include/capi/cef_request_handler_capi.h create mode 100644 src/include/capi/cef_resource_bundle_capi.h create mode 100644 src/include/capi/cef_resource_bundle_handler_capi.h create mode 100644 src/include/capi/cef_resource_handler_capi.h create mode 100644 src/include/capi/cef_resource_request_handler_capi.h create mode 100644 src/include/capi/cef_response_capi.h create mode 100644 src/include/capi/cef_response_filter_capi.h create mode 100644 src/include/capi/cef_scheme_capi.h create mode 100644 src/include/capi/cef_server_capi.h create mode 100644 src/include/capi/cef_shared_memory_region_capi.h create mode 100644 src/include/capi/cef_shared_process_message_builder_capi.h create mode 100644 src/include/capi/cef_ssl_info_capi.h create mode 100644 src/include/capi/cef_ssl_status_capi.h create mode 100644 src/include/capi/cef_stream_capi.h create mode 100644 src/include/capi/cef_string_visitor_capi.h create mode 100644 src/include/capi/cef_task_capi.h create mode 100644 src/include/capi/cef_thread_capi.h create mode 100644 src/include/capi/cef_trace_capi.h create mode 100644 src/include/capi/cef_urlrequest_capi.h create mode 100644 src/include/capi/cef_v8_capi.h create mode 100644 src/include/capi/cef_values_capi.h create mode 100644 src/include/capi/cef_waitable_event_capi.h create mode 100644 src/include/capi/cef_x509_certificate_capi.h create mode 100644 src/include/capi/cef_xml_reader_capi.h create mode 100644 src/include/capi/cef_zip_reader_capi.h create mode 100644 src/include/capi/test/cef_test_helpers_capi.h create mode 100644 src/include/capi/test/cef_test_server_capi.h create mode 100644 src/include/capi/test/cef_translator_test_capi.h create mode 100644 src/include/capi/views/cef_box_layout_capi.h create mode 100644 src/include/capi/views/cef_browser_view_capi.h create mode 100644 src/include/capi/views/cef_browser_view_delegate_capi.h create mode 100644 src/include/capi/views/cef_button_capi.h create mode 100644 src/include/capi/views/cef_button_delegate_capi.h create mode 100644 src/include/capi/views/cef_display_capi.h create mode 100644 src/include/capi/views/cef_fill_layout_capi.h create mode 100644 src/include/capi/views/cef_label_button_capi.h create mode 100644 src/include/capi/views/cef_layout_capi.h create mode 100644 src/include/capi/views/cef_menu_button_capi.h create mode 100644 src/include/capi/views/cef_menu_button_delegate_capi.h create mode 100644 src/include/capi/views/cef_overlay_controller_capi.h create mode 100644 src/include/capi/views/cef_panel_capi.h create mode 100644 src/include/capi/views/cef_panel_delegate_capi.h create mode 100644 src/include/capi/views/cef_scroll_view_capi.h create mode 100644 src/include/capi/views/cef_textfield_capi.h create mode 100644 src/include/capi/views/cef_textfield_delegate_capi.h create mode 100644 src/include/capi/views/cef_view_capi.h create mode 100644 src/include/capi/views/cef_view_delegate_capi.h create mode 100644 src/include/capi/views/cef_window_capi.h create mode 100644 src/include/capi/views/cef_window_delegate_capi.h create mode 100644 src/include/cef_api_hash.h delete mode 100644 src/include/cef_application_mac.h create mode 100644 src/include/cef_audio_handler.h create mode 100644 src/include/cef_command_handler.h create mode 100644 src/include/cef_command_ids.h create mode 100644 src/include/cef_config.h create mode 100644 src/include/cef_devtools_message_observer.h create mode 100644 src/include/cef_frame_handler.h create mode 100644 src/include/cef_i18n_util.h create mode 100644 src/include/cef_media_router.h create mode 100644 src/include/cef_pack_resources.h create mode 100644 src/include/cef_pack_strings.h create mode 100644 src/include/cef_permission_handler.h create mode 100644 src/include/cef_preference.h create mode 100644 src/include/cef_registration.h create mode 100644 src/include/cef_resource_request_handler.h create mode 100644 src/include/cef_shared_memory_region.h create mode 100644 src/include/cef_shared_process_message_builder.h create mode 100644 src/include/cef_version.h delete mode 100644 src/include/cef_web_plugin.h create mode 100644 src/include/internal/cef_app_win.h delete mode 100644 src/include/internal/cef_linux.h delete mode 100644 src/include/internal/cef_mac.h create mode 100644 src/include/internal/cef_time_wrappers.h create mode 100644 src/include/internal/cef_types_content_settings.h create mode 100644 src/include/internal/cef_types_geometry.h delete mode 100644 src/include/internal/cef_types_linux.h delete mode 100644 src/include/internal/cef_types_mac.h create mode 100644 src/include/test/cef_test_server.h create mode 100644 src/include/views/cef_overlay_controller.h delete mode 100644 src/web_plugin_info.pyx diff --git a/.gitignore b/.gitignore index b786188bc..928c0a70f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .idea/ build/ dist/ +venv/ *.log __pycache__/ *.pyc @@ -16,3 +17,5 @@ unittests/GPUCache/ unittests/blob_storage/ unittests/webrtc_event_logs/ .DS_Store +MediaDeviceSalts +MediaDeviceSalts-journal diff --git a/api/LifespanHandler.md b/api/LifespanHandler.md index 2b9295126..5e964b951 100644 --- a/api/LifespanHandler.md +++ b/api/LifespanHandler.md @@ -112,13 +112,13 @@ the popup window and parent window will not be able to script each other. There will be no "window.opener" property available in the popup window. `WindowOpenDisposition` constants in the cefpython module: -* WOD_UNKNOWN, -* WOD_CURRENT_TAB, -* WOD_SINGLETON_TAB, -* WOD_NEW_FOREGROUND_TAB, -* WOD_NEW_BACKGROUND_TAB, -* WOD_NEW_POPUP, -* WOD_NEW_WINDOW, -* WOD_SAVE_TO_DISK, -* WOD_OFF_THE_RECORD, -* WOD_IGNORE_ACTION +* CEF_WOD_UNKNOWN, +* CEF_WOD_CURRENT_TAB, +* CEF_WOD_SINGLETON_TAB, +* CEF_WOD_NEW_FOREGROUND_TAB, +* CEF_WOD_NEW_BACKGROUND_TAB, +* CEF_WOD_NEW_POPUP, +* CEF_WOD_NEW_WINDOW, +* CEF_WOD_SAVE_TO_DISK, +* CEF_WOD_OFF_THE_RECORD, +* CEF_WOD_IGNORE_ACTION diff --git a/examples/hello_world.py b/examples/hello_world.py index 478c70604..e7cfdb6da 100644 --- a/examples/hello_world.py +++ b/examples/hello_world.py @@ -4,6 +4,7 @@ from cefpython3 import cefpython as cef import platform import sys +from pkg_resources import parse_version def main(): @@ -24,7 +25,7 @@ def check_versions(): print("[hello_world.py] Python {ver} {arch}".format( ver=platform.python_version(), arch=platform.architecture()[0])) - assert cef.__version__ >= "57.0", "CEF Python v57.0+ required to run this" + assert parse_version(cef.__version__) >= parse_version("57.0"), "CEF Python v57.0+ required to run this" if __name__ == '__main__': diff --git a/examples/pysdl2.py b/examples/pysdl2.py index 97f9293dc..89226a8a2 100644 --- a/examples/pysdl2.py +++ b/examples/pysdl2.py @@ -127,6 +127,11 @@ def main(): dest='renderer', choices=['software', 'hardware'] ) + parser.add_argument( + '--debug', + help='debug app', + action='store_true' + ) args = parser.parse_args() logLevel = logging.INFO if args.verbose: @@ -135,7 +140,7 @@ def main(): format='[%(filename)s %(levelname)s]: %(message)s', level=logLevel ) - logging.info("Using PySDL2 %s" % sdl2.__version__) + logging.info("Using PySDL2 %s", sdl2.__version__) version = sdl2.SDL_version() sdl2.SDL_GetVersion(version) logging.info( @@ -224,7 +229,7 @@ def main(): browser.SetClientHandler(renderHandler) # Must call WasResized at least once to let know CEF that # viewport size is available and that OnPaint may be called. - browser.SendFocusEvent(True) + # browser.SendFocus(True) browser.WasResized() # Begin the main rendering loop diff --git a/examples/pywin32.py b/examples/pywin32.py index bf8d2b9be..0ca8f7482 100644 --- a/examples/pywin32.py +++ b/examples/pywin32.py @@ -16,6 +16,7 @@ from cefpython3 import cefpython as cef import distutils.sysconfig +from pkg_resources import parse_version import math import os import platform @@ -108,7 +109,7 @@ def check_versions(): pywin32_version = fp.read().strip() print("[pywin32.py] pywin32 {ver}".format(ver=pywin32_version)) - assert cef.__version__ >= "57.0", "CEF Python v57.0+ required to run this" + assert parse_version(cef.__version__) >= parse_version("57.0"), "CEF Python v57.0+ required to run this" def create_browser(window_info, settings, url): diff --git a/examples/qt.py b/examples/qt.py index a272b80d1..75b1412f7 100644 --- a/examples/qt.py +++ b/examples/qt.py @@ -18,10 +18,12 @@ import os import platform import sys +from pkg_resources import parse_version # GLOBALS PYQT4 = False PYQT5 = False +PYQT6 = False PYSIDE = False PYSIDE2 = False @@ -39,6 +41,14 @@ from PyQt5.QtCore import * # noinspection PyUnresolvedReferences from PyQt5.QtWidgets import * +elif "pyqt6" in sys.argv: + PYQT6 = True + # noinspection PyUnresolvedReferences + from PyQt6.QtGui import * + # noinspection PyUnresolvedReferences + from PyQt6.QtCore import * + # noinspection PyUnresolvedReferences + from PyQt6.QtWidgets import * elif "pyside" in sys.argv: PYSIDE = True # noinspection PyUnresolvedReferences @@ -65,6 +75,7 @@ print("USAGE:") print(" qt.py pyqt4") print(" qt.py pyqt5") + print(" qt.py pyqt6") print(" qt.py pyside") print(" qt.py pyside2") sys.exit(1) @@ -104,7 +115,10 @@ def main(): main_window.show() main_window.activateWindow() main_window.raise_() - app.exec_() + if PYQT6: + app.exec() + else: + app.exec_() if not cef.GetAppSetting("external_message_pump"): app.stopTimer() del main_window # Just to be safe, similarly to "del app" @@ -116,7 +130,7 @@ def check_versions(): print("[qt.py] CEF Python {ver}".format(ver=cef.__version__)) print("[qt.py] Python {ver} {arch}".format( ver=platform.python_version(), arch=platform.architecture()[0])) - if PYQT4 or PYQT5: + if PYQT4 or PYQT5 or PYQT6: print("[qt.py] PyQt {v1} (qt {v2})".format( v1=PYQT_VERSION_STR, v2=qVersion())) elif PYSIDE: @@ -126,7 +140,7 @@ def check_versions(): print("[qt.py] PySide2 {v1} (qt {v2})".format( v1=PySide2.__version__, v2=QtCore.__version__)) # CEF Python version requirement - assert cef.__version__ >= "55.4", "CEF Python v55.4+ required to run this" + assert parse_version(cef.__version__) >= parse_version("55.4"), "CEF Python v55.4+ required to run this" class MainWindow(QMainWindow): @@ -142,11 +156,16 @@ def __init__(self): self.setWindowTitle("PyQt4 example") elif PYQT5: self.setWindowTitle("PyQt5 example") + elif PYQT6: + self.setWindowTitle("PyQt6 example") elif PYSIDE: self.setWindowTitle("PySide example") elif PYSIDE2: self.setWindowTitle("PySide2 example") - self.setFocusPolicy(Qt.StrongFocus) + if PYQT6: + self.setFocusPolicy(Qt.FocusPolicy.StrongFocus) + else: + self.setFocusPolicy(Qt.StrongFocus) self.setupLayout() def setupLayout(self): @@ -167,7 +186,7 @@ def setupLayout(self): frame.setLayout(layout) self.setCentralWidget(frame) - if (PYSIDE2 or PYQT5) and WINDOWS: + if (PYSIDE2 or PYQT5 or PYQT6) and WINDOWS: # On Windows with PyQt5 main window must be shown first # before CEF browser is embedded, otherwise window is # not resized and application hangs during resize. diff --git a/examples/screenshot.py b/examples/screenshot.py index d6dc661c8..938bf3c15 100644 --- a/examples/screenshot.py +++ b/examples/screenshot.py @@ -36,13 +36,14 @@ """ from cefpython3 import cefpython as cef +from pkg_resources import parse_version import os import platform import subprocess import sys try: - from PIL import Image, PILLOW_VERSION + from PIL import Image, __version__ as PILLOW_VERSION except ImportError: print("[screenshot.py] Error: PIL module not available. To install" " type: pip install Pillow") @@ -99,7 +100,7 @@ def check_versions(): ver=platform.python_version(), arch=platform.architecture()[0])) print("[screenshot.py] Pillow {ver}".format(ver=PILLOW_VERSION)) - assert cef.__version__ >= "57.0", "CEF Python v57.0+ required to run this" + assert parse_version(cef.__version__) >= parse_version("57.0"), "CEF Python v57.0+ required to run this" def command_line_arguments(): @@ -139,9 +140,10 @@ def create_browser(settings): browser = cef.CreateBrowserSync(window_info=window_info, settings=settings, url=URL) + print('created browser ', browser) browser.SetClientHandler(LoadHandler()) browser.SetClientHandler(RenderHandler()) - browser.SendFocusEvent(True) + # browser.SendFocus(True) # You must call WasResized at least once to let know CEF that # viewport size is available and that OnPaint may be called. browser.WasResized() diff --git a/examples/tkinter_.py b/examples/tkinter_.py index c823f3dc9..7e7fac429 100644 --- a/examples/tkinter_.py +++ b/examples/tkinter_.py @@ -26,6 +26,7 @@ import os import platform import logging as _logging +from pkg_resources import parse_version # Fix for PyCharm hints warnings WindowUtils = cef.WindowUtils() @@ -53,7 +54,7 @@ def main(): logger.info("Python {ver} {arch}".format( ver=platform.python_version(), arch=platform.architecture()[0])) logger.info("Tk {ver}".format(ver=tk.Tcl().eval('info patchlevel'))) - assert cef.__version__ >= "55.3", "CEF Python v55.3+ required to run this" + assert parse_version(cef.__version__) >= parse_version("55.3"), "CEF Python v55.3+ required to run this" sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error root = tk.Tk() app = MainFrame(root) diff --git a/examples/tutorial.py b/examples/tutorial.py index 860bbe12c..d02059d43 100644 --- a/examples/tutorial.py +++ b/examples/tutorial.py @@ -6,6 +6,7 @@ import platform import sys import threading +from pkg_resources import parse_version # HTML code. Browser will navigate to a Data uri created # from this html code. @@ -85,7 +86,7 @@ def check_versions(): print("[tutorial.py] Python {ver} {arch}".format( ver=platform.python_version(), arch=platform.architecture()[0])) - assert cef.__version__ >= "57.0", "CEF Python v57.0+ required to run this" + assert parse_version(cef.__version__) >= parse_version("57.0"), "CEF Python v57.0+ required to run this" def html_to_data_uri(html, js_callback=None): @@ -188,6 +189,7 @@ def __init__(self, browser): def test_multiple_callbacks(self, js_callback): """Test both javascript and python callbacks.""" + print('in test_multiple_callbacks') js_print(self.browser, "Python", "test_multiple_callbacks", "Called from Javascript. Will call Javascript callback now.") diff --git a/examples/wxpython.py b/examples/wxpython.py index 92dd7d834..4f263e9da 100644 --- a/examples/wxpython.py +++ b/examples/wxpython.py @@ -12,6 +12,7 @@ import platform import sys import os +from pkg_resources import parse_version # Platforms WINDOWS = (platform.system() == "Windows") @@ -65,7 +66,7 @@ def check_versions(): ver=platform.python_version(), arch=platform.architecture()[0])) print("[wxpython.py] wxPython {ver}".format(ver=wx.version())) # CEF Python version requirement - assert cef.__version__ >= "66.0", "CEF Python v66.0+ required to run this" + assert parse_version(cef.__version__) >= parse_version("66.0"), "CEF Python v66.0+ required to run this" def scale_window_size_for_high_dpi(width, height): diff --git a/src/browser.pyx b/src/browser.pyx index d378ca220..3d2a4d861 100644 --- a/src/browser.pyx +++ b/src/browser.pyx @@ -5,6 +5,8 @@ include "cefpython.pyx" cimport cef_types +from libc.stdint cimport uint32_t, int64_t +from libcpp cimport nullptr from cef_types cimport cef_state_t IF UNAME_SYSNAME == "Linux": cimport x11 @@ -59,7 +61,7 @@ cdef PyBrowser GetPyBrowser(CefRefPtr[CefBrowser] cefBrowser, global g_pyBrowsers - if cefBrowser == NULL or not cefBrowser.get(): + if not cefBrowser or not cefBrowser.get(): raise Exception("{caller}: CefBrowser reference is NULL" .format(caller=callerIdStr)) @@ -148,7 +150,7 @@ cdef void RemovePyBrowser(int browserId) except *: # noinspection PyUnresolvedReferences Debug("del g_pyBrowsers[%s]" % browserId) pyBrowser = g_pyBrowsers[browserId] - pyBrowser.cefBrowser.Assign(NULL) + pyBrowser.cefBrowser.Assign(nullptr) del pyBrowser del g_pyBrowsers[browserId] g_unreferenced_browsers.append(browserId) @@ -207,7 +209,7 @@ cdef class PyBrowser: cdef void* imageBuffer cdef CefRefPtr[CefBrowser] GetCefBrowser(self) except *: - if self.cefBrowser != NULL and self.cefBrowser.get(): + if self.cefBrowser and self.cefBrowser.get(): return self.cefBrowser raise Exception("PyBrowser.GetCefBrowser() failed: CefBrowser " "was destroyed") @@ -215,7 +217,7 @@ cdef class PyBrowser: cdef CefRefPtr[CefBrowserHost] GetCefBrowserHost(self) except *: cdef CefRefPtr[CefBrowserHost] cefBrowserHost = ( self.GetCefBrowser().get().GetHost()) - if cefBrowserHost != NULL and cefBrowserHost.get(): + if cefBrowserHost and cefBrowserHost.get(): return cefBrowserHost raise Exception("PyBrowser.GetCefBrowserHost() failed: this " "method can only be called in the browser " @@ -267,6 +269,9 @@ cdef class PyBrowser: "OnScrollOffsetChanged", "StartDragging", "UpdateDragCursor", "OnTextSelectionChanged"] + # V8ContextHandler + self.allowedClientCallbacks += ["OnContextCreated", + "OnContextReleased"] # JavascriptDialogHandler self.allowedClientCallbacks += ["OnJavascriptDialog", "OnBeforeUnloadJavascriptDialog", @@ -391,9 +396,9 @@ cdef class PyBrowser: # If using GetCookieManager to implement custom cookie managers # then flushing of cookies would need to be handled manually. self.GetCefBrowserHost().get().GetRequestContext().get() \ - .GetDefaultCookieManager( - NULL) \ - .get().FlushStore(NULL) + .GetCookieManager( + nullptr) \ + .get().FlushStore(nullptr) cdef int browserId = self.GetCefBrowser().get().GetIdentifier() self.GetCefBrowserHost().get().CloseBrowser(bool(forceClose)) @@ -410,12 +415,12 @@ cdef class PyBrowser: py_string scriptUrl="", int startLine=1): self.GetMainFrame().ExecuteJavascript(jsCode, scriptUrl, startLine) - cpdef py_void Find(self, int searchId, py_string searchText, + cpdef py_void Find(self, py_string searchText, py_bool forward, py_bool matchCase, py_bool findNext): cdef CefString cefSearchText PyToCefString(searchText, cefSearchText) - self.GetCefBrowserHost().get().Find(searchId, cefSearchText, + self.GetCefBrowserHost().get().Find(cefSearchText, bool(forward), bool(matchCase), bool(findNext)) cpdef PyFrame GetFocusedFrame(self): @@ -423,16 +428,18 @@ cdef class PyBrowser: "Browser.GetFocusedFrame() may only be called on UI thread") return GetPyFrame(self.GetCefBrowser().get().GetFocusedFrame()) - cpdef PyFrame GetFrame(self, py_string name): + cpdef PyFrame GetFrameByName(self, py_string name): assert IsThread(TID_UI), ( - "Browser.GetFrame() may only be called on the UI thread") + "Browser.GetFrameByName() may only be called on the UI thread") cdef CefString cefName PyToCefString(name, cefName) - return GetPyFrame(self.GetCefBrowser().get().GetFrame(cefName)) + return GetPyFrame(self.GetCefBrowser().get().GetFrameByName(cefName)) - cpdef object GetFrameByIdentifier(self, object identifier): - return GetPyFrame(self.GetCefBrowser().get().GetFrame( - identifier)) + cpdef object GetFrameByIdentifier(self, py_string identifier): + cdef CefString cefIdentifier + PyToCefString(identifier, cefIdentifier) + return GetPyFrame(self.GetCefBrowser().get().GetFrameByIdentifier( + cefIdentifier)) cpdef list GetFrameNames(self): assert IsThread(TID_UI), ( @@ -453,7 +460,7 @@ cdef class PyBrowser: cdef PyFrame frame cdef list frames = [] for name in names: - frame = self.GetFrame(name) + frame = self.GetFrameByName(name) frames.append(frame) return frames @@ -585,7 +592,7 @@ cdef class PyBrowser: cdef CefBrowserSettings settings cdef CefPoint inspect_element_at self.GetCefBrowserHost().get().ShowDevTools( - window_info, NULL, settings, + window_info, nullptr, settings, inspect_element_at) cpdef py_void StopLoad(self): @@ -658,7 +665,7 @@ cdef class PyBrowser: right = monitorInfo.rcMonitor.right bottom = monitorInfo.rcMonitor.bottom # noinspection PyUnresolvedReferences - SetWindowPos(hwnd, NULL, + SetWindowPos(hwnd, nullptr, left, top, right-left, bottom-top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED) else: @@ -668,7 +675,7 @@ cdef class PyBrowser: if not for_metro: (left, top, right, bottom) = self.windowRect # noinspection PyUnresolvedReferences - SetWindowPos(hwnd, NULL, + SetWindowPos(hwnd, nullptr, int(left), int(top), int(right-left), int(bottom-top), SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED) @@ -683,7 +690,7 @@ cdef class PyBrowser: if "type" in pyEvent: cefEvent.type = int(pyEvent["type"]) if "modifiers" in pyEvent: - cefEvent.modifiers = pyEvent["modifiers"] + cefEvent.modifiers = pyEvent["modifiers"] # Always set CefKeyEvent.windows_key_code in SendKeyEvent, even on # Linux. When sending key event for 'backspace' on Linux and setting # "native_key_code", "character", "unmodified_character" it doesn't @@ -732,8 +739,8 @@ cdef class PyBrowser: self.GetCefBrowserHost().get().SendMouseWheelEvent(mouseEvent, deltaX, deltaY) - cpdef py_void SendFocusEvent(self, py_bool setFocus): - self.GetCefBrowserHost().get().SendFocusEvent(bool(setFocus)) + # cpdef py_void SendFocusEvent(self, py_bool setFocus): + # self.GetCefBrowserHost().get().SendFocusEvent(bool(setFocus)) cpdef py_void SendCaptureLostEvent(self): self.GetCefBrowserHost().get().SendCaptureLostEvent() @@ -742,12 +749,12 @@ cdef class PyBrowser: self.GetCefBrowserHost().get().StartDownload(PyToCefStringValue( url)) - cpdef py_void SetMouseCursorChangeDisabled(self, py_bool disabled): - self.GetCefBrowserHost().get().SetMouseCursorChangeDisabled( - bool(disabled)) + # cpdef py_void SetMouseCursorChangeDisabled(self, py_bool disabled): + # self.GetCefBrowserHost().get().SetMouseCursorChangeDisabled( + # bool(disabled)) - cpdef py_bool IsMouseCursorChangeDisabled(self): - return self.GetCefBrowserHost().get().IsMouseCursorChangeDisabled() + # cpdef py_bool IsMouseCursorChangeDisabled(self): + # return self.GetCefBrowserHost().get().IsMouseCursorChangeDisabled() cpdef py_bool TryCloseBrowser(self): return self.GetCefBrowserHost().get().TryCloseBrowser() @@ -761,35 +768,35 @@ cdef class PyBrowser: cpdef py_void NotifyScreenInfoChanged(self): self.GetCefBrowserHost().get().NotifyScreenInfoChanged() - cdef void SendProcessMessage(self, cef_process_id_t targetProcess, - object frameId, py_string messageName, list pyArguments - ) except *: - cdef CefRefPtr[CefProcessMessage] message = \ - CefProcessMessage_Create(PyToCefStringValue(messageName)) - # This does not work, no idea why, the CEF implementation - # seems not to allow it, both Assign() and swap() do not work: - # | message.get().GetArgumentList().Assign(arguments.get()) - # | message.get().GetArgumentList().swap(arguments) - cdef CefRefPtr[CefListValue] messageArguments = \ - message.get().GetArgumentList() - PyListToExistingCefListValue(self.GetIdentifier(), frameId, - pyArguments, messageArguments) - Debug("SendProcessMessage(): message=%s, arguments size=%d" % ( - messageName, - message.get().GetArgumentList().get().GetSize())) - cdef cpp_bool success = \ - self.GetCefBrowser().get().SendProcessMessage( - targetProcess, message) - if not success: - raise Exception("Browser.SendProcessMessage() failed: "\ - "messageName=%s" % messageName) + # cdef void SendProcessMessage(self, cef_process_id_t targetProcess, + # object frameId, py_string messageName, list pyArguments + # ) except *: + # cdef CefRefPtr[CefProcessMessage] message = \ + # CefProcessMessage_Create(PyToCefStringValue(messageName)) + # # This does not work, no idea why, the CEF implementation + # # seems not to allow it, both Assign() and swap() do not work: + # # | message.get().GetArgumentList().Assign(arguments.get()) + # # | message.get().GetArgumentList().swap(arguments) + # cdef CefRefPtr[CefListValue] messageArguments = \ + # message.get().GetArgumentList() + # PyListToExistingCefListValue(self.GetIdentifier(), frameId, + # pyArguments, messageArguments) + # Debug("SendProcessMessage(): message=%s, arguments size=%d" % ( + # messageName, + # message.get().GetArgumentList().get().GetSize())) + # cdef cpp_bool success = \ + # self.GetCefBrowser().get().GetMainFrame().SendProcessMessage( + # targetProcess, message) + # if not success: + # raise Exception("Browser.SendProcessMessage() failed: "\ + # "messageName=%s" % messageName) # ------------------------------------------------------------------------- # OSR drag & drop # ------------------------------------------------------------------------- cpdef py_void DragTargetDragEnter(self, DragData drag_data, int x, int y, - uint32 allowed_ops): + uint32_t allowed_ops): cdef CefMouseEvent mouse_event mouse_event.x = x mouse_event.y = y @@ -797,7 +804,7 @@ cdef class PyBrowser: drag_data.cef_drag_data, mouse_event, allowed_ops) - cpdef py_void DragTargetDragOver(self, int x, int y, uint32 allowed_ops): + cpdef py_void DragTargetDragOver(self, int x, int y, uint32_t allowed_ops): cdef CefMouseEvent mouse_event mouse_event.x = x mouse_event.y = y @@ -813,7 +820,7 @@ cdef class PyBrowser: mouse_event.y = y self.GetCefBrowserHost().get().DragTargetDrop(mouse_event) - cpdef py_void DragSourceEndedAt(self, int x, int y, uint32 operation): + cpdef py_void DragSourceEndedAt(self, int x, int y, uint32_t operation): self.GetCefBrowserHost().get().DragSourceEndedAt( x, y, operation) diff --git a/src/cefpython.pyx b/src/cefpython.pyx index aff190a07..837ee4ee8 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -197,6 +197,8 @@ from libcpp.string cimport string as cpp_string # noinspection PyUnresolvedReferences from wstring cimport wstring as cpp_wstring # noinspection PyUnresolvedReferences +from libcpp.memory cimport unique_ptr +# noinspection PyUnresolvedReferences from libc.string cimport strlen # noinspection PyUnresolvedReferences from libc.string cimport memcpy @@ -254,16 +256,12 @@ from cef_types cimport ( CefSettings, CefBrowserSettings, CefRect, CefSize, CefPoint, CefKeyEvent, CefMouseEvent, CefScreenInfo, PathKey, PK_DIR_EXE, PK_DIR_MODULE, - int32, uint32, int64, uint64, cef_log_severity_t, ) # noinspection PyUnresolvedReferences from cef_ptr cimport CefRefPtr -# noinspection PyUnresolvedReferences -from cef_scoped_ptr cimport scoped_ptr - from cef_task cimport * from cef_platform cimport * from cef_app cimport * @@ -277,7 +275,6 @@ from cef_time cimport * from cef_values cimport * from cefpython_app cimport * from cef_process_message cimport * -from cef_web_plugin cimport * from cef_request_handler cimport * from cef_request cimport * from cef_cookie cimport * @@ -325,7 +322,7 @@ g_browser_settings = {} # noinspection PyUnresolvedReferences cdef CefRefPtr[CefRequestContext] g_shared_request_context -cdef scoped_ptr[MainMessageLoopExternalPump] g_external_message_pump +cdef unique_ptr[MainMessageLoopExternalPump] g_external_message_pump cdef py_bool g_MessageLoop_called = False cdef py_bool g_MessageLoopWork_called = False @@ -362,7 +359,6 @@ include "window_info.pyx" include "process_message_utils.pyx" include "javascript_callback.pyx" include "python_callback.pyx" -include "web_plugin_info.pyx" include "request.pyx" include "cookie.pyx" include "string_visitor.pyx" @@ -585,8 +581,6 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): # ------------------------------------------------------------------------ if not "multi_threaded_message_loop" in application_settings: application_settings["multi_threaded_message_loop"] = False - if not "single_process" in application_settings: - application_settings["single_process"] = False # ------------------------------------------------------------------------ # ------------------------------------------------------------------------ @@ -597,7 +591,6 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): if not application_settings["cache_path"]: g_commandLineSwitches["disable-gpu-shader-disk-cache"] = "" - cdef CefRefPtr[CefApp] cefApp = new CefPythonApp() IF UNAME_SYSNAME == "Windows": @@ -631,8 +624,9 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): Debug("Create external message pump") # Using .reset() here to assign new instance was causing # MainMessageLoopExternalPump destructor to be called. Strange. - g_external_message_pump.Assign( - MainMessageLoopExternalPump.Create()) + # g_external_message_pump.Assign( + # MainMessageLoopExternalPump.Create()) + g_external_message_pump.reset() Debug("CefInitialize()") cdef cpp_bool ret @@ -767,14 +761,16 @@ def CreateBrowserSync(windowInfo=None, else: cefRequestContext.Assign(g_shared_request_context.get()) + cdef CefRefPtr[CefDictionaryValue] extra_info + # CEF browser creation. with nogil: cefBrowser = cef_browser_static.CreateBrowserSync( cefWindowInfo, clientHandler, - cefNavigateUrl, cefBrowserSettings, + cefNavigateUrl, cefBrowserSettings, extra_info, cefRequestContext) - if cefBrowser == NULL or not cefBrowser.get(): + if not cefBrowser or not cefBrowser.get(): Debug("CefBrowser::CreateBrowserSync() failed") return None else: @@ -977,7 +973,7 @@ cpdef py_void SetGlobalClientCallback(py_string name, object callback): # Accept both with and without a prefix. if name.startswith("_"): name = name[1:] - if name in ["OnCertificateError", "OnBeforePluginLoad", "OnAfterCreated", + if name in ["OnCertificateError", "OnAfterCreated", "OnAccessibilityTreeChange", "OnAccessibilityLocationChange"]: g_globalClientCallbacks[name] = callback else: diff --git a/src/client_handler/client_handler.cpp b/src/client_handler/client_handler.cpp index daf9a4e59..d64fba748 100644 --- a/src/client_handler/client_handler.cpp +++ b/src/client_handler/client_handler.cpp @@ -27,6 +27,7 @@ bool ClientHandler::OnProcessMessageReceived( CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) { @@ -34,15 +35,16 @@ bool ClientHandler::OnProcessMessageReceived( if (source_process != PID_RENDERER) { return false; } - std::string messageName = message->GetName().ToString(); + const std::string& messageName = message->GetName(); std::string logMessage = "[Browser process] OnProcessMessageReceived(): "; logMessage.append(messageName.c_str()); LOG(INFO) << logMessage.c_str(); if (messageName == "OnContextCreated") { CefRefPtr arguments = message->GetArgumentList(); - if (arguments->GetSize() == 1 && arguments->GetType(0) == VTYPE_INT) { - int64 frameId = arguments->GetInt(0); - CefRefPtr frame = browser->GetFrame(frameId); + if (arguments->GetSize() == 1 && arguments->GetType(0) == VTYPE_STRING) { + CefString frameId = arguments->GetString(0); + LOG(INFO) << "[Browser process] frameId " << frameId.c_str(); + CefRefPtr frame = browser->GetFrameByIdentifier(frameId); if (!frame.get()) { // Frame was already destroyed while IPC messaging was // executing. Issue #431. User callback will not be @@ -60,9 +62,9 @@ bool ClientHandler::OnProcessMessageReceived( CefRefPtr arguments = message->GetArgumentList(); if (arguments->GetSize() == 2 \ && arguments->GetType(0) == VTYPE_INT \ - && arguments->GetType(1) == VTYPE_INT) { + && arguments->GetType(1) == VTYPE_STRING) { int browserId = arguments->GetInt(0); - int64 frameId = arguments->GetInt(1); + CefString frameId = arguments->GetString(1); // Even if frame was alrady destroyed (Issue #431) you still // want to call V8ContextHandler_OnContextReleased as it releases // some resources. Thus passing IDs instead of actual @@ -79,12 +81,12 @@ bool ClientHandler::OnProcessMessageReceived( CefRefPtr arguments = message->GetArgumentList(); if (arguments->GetSize() == 3 // frameId - && arguments->GetType(0) == VTYPE_INT + && arguments->GetType(0) == VTYPE_STRING // functionName && arguments->GetType(1) == VTYPE_STRING // functionArguments && arguments->GetType(2) == VTYPE_LIST) { - int64 frameId = arguments->GetInt(0); + CefString frameId = arguments->GetString(0); CefString functionName = arguments->GetString(1); CefRefPtr functionArguments = arguments->GetList(2); // Even if frame was already destroyed (Issue #431) you still diff --git a/src/client_handler/client_handler.h b/src/client_handler/client_handler.h index 3e9e3917b..e52d0b50c 100644 --- a/src/client_handler/client_handler.h +++ b/src/client_handler/client_handler.h @@ -87,6 +87,7 @@ class ClientHandler : public CefClient, } bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message ) override; diff --git a/src/client_handler/cookie_visitor.h b/src/client_handler/cookie_visitor.h index 54c2b53fd..0b990baca 100644 --- a/src/client_handler/cookie_visitor.h +++ b/src/client_handler/cookie_visitor.h @@ -24,7 +24,7 @@ class CookieVisitor : public CefCookieVisitor int count, int total, bool& deleteCookie - ) OVERRIDE; + ) override; protected: IMPLEMENT_REFCOUNTING(CookieVisitor); diff --git a/src/client_handler/dialog_handler.cpp b/src/client_handler/dialog_handler.cpp index ab90de9b6..6946e4f65 100644 --- a/src/client_handler/dialog_handler.cpp +++ b/src/client_handler/dialog_handler.cpp @@ -19,7 +19,6 @@ bool DialogHandler::OnFileDialog(CefRefPtr browser, const CefString& title, const CefString& default_file_path, const std::vector& accept_filters, - int selected_accept_filter, CefRefPtr callback) { #if defined(OS_LINUX) @@ -28,7 +27,6 @@ bool DialogHandler::OnFileDialog(CefRefPtr browser, title, default_file_path, accept_filters, - selected_accept_filter, callback); #else return false; diff --git a/src/client_handler/dialog_handler.h b/src/client_handler/dialog_handler.h index 21d79a60d..2cea565f6 100644 --- a/src/client_handler/dialog_handler.h +++ b/src/client_handler/dialog_handler.h @@ -23,7 +23,6 @@ class DialogHandler : public CefDialogHandler const CefString& title, const CefString& default_file_path, const std::vector& accept_filters, - int selected_accept_filter, CefRefPtr callback) override; diff --git a/src/client_handler/display_handler.cpp b/src/client_handler/display_handler.cpp index b00bf6a51..573549e26 100644 --- a/src/client_handler/display_handler.cpp +++ b/src/client_handler/display_handler.cpp @@ -59,4 +59,13 @@ void DisplayHandler::OnLoadingProgressChange(CefRefPtr browser, double progress) { REQUIRE_UI_THREAD(); return DisplayHandler_OnLoadingProgressChange(browser, progress); +} + +bool DisplayHandler::OnCursorChange(CefRefPtr browser, + CefCursorHandle cursor, + cef_cursor_type_t type, + const CefCursorInfo& custom_cursor_info) +{ + REQUIRE_UI_THREAD(); + return DisplayHandler_OnCursorChange(browser, cursor); } \ No newline at end of file diff --git a/src/client_handler/display_handler.h b/src/client_handler/display_handler.h index a281713d9..382bceeaa 100644 --- a/src/client_handler/display_handler.h +++ b/src/client_handler/display_handler.h @@ -38,6 +38,12 @@ class DisplayHandler : public CefDisplayHandler void OnLoadingProgressChange(CefRefPtr browser, double progress) override; + + bool OnCursorChange(CefRefPtr browser, + CefCursorHandle cursor, + cef_cursor_type_t type, + const CefCursorInfo& custom_cursor_info + ) override; private: IMPLEMENT_REFCOUNTING(DisplayHandler); diff --git a/src/client_handler/dpi_aware.cpp b/src/client_handler/dpi_aware.cpp index 48e2a13f7..9ee258d65 100644 --- a/src/client_handler/dpi_aware.cpp +++ b/src/client_handler/dpi_aware.cpp @@ -11,6 +11,7 @@ #include "include/wrapper/cef_closure_task.h" #include "include/base/cef_bind.h" #include "include/base/cef_logging.h" +#include "include/base/cef_callback.h" const int DEFAULT_DPIX = 96; @@ -219,7 +220,7 @@ void SetBrowserDpiSettings(CefRefPtr cefBrowser, CefPostDelayedTask( TID_UI, CefCreateClosureTask( - base::Bind(&SetBrowserDpiSettings, + base::BindOnce(&SetBrowserDpiSettings, cefBrowser, autoZooming) ), 50 diff --git a/src/client_handler/lifespan_handler.cpp b/src/client_handler/lifespan_handler.cpp index b4d7d52f6..d9d6010d6 100644 --- a/src/client_handler/lifespan_handler.cpp +++ b/src/client_handler/lifespan_handler.cpp @@ -19,6 +19,7 @@ bool LifespanHandler::OnBeforePopup(CefRefPtr browser, CefWindowInfo& windowInfo, CefRefPtr& client, CefBrowserSettings& settings, + CefRefPtr& extra_info, bool* no_javascript_access) { REQUIRE_UI_THREAD(); @@ -27,7 +28,7 @@ bool LifespanHandler::OnBeforePopup(CefRefPtr browser, return LifespanHandler_OnBeforePopup(browser, frame, target_url, target_frame_name, target_disposition, user_gesture, popupFeaturesNotImpl, windowInfo, client, settings, - no_javascript_access); + extra_info, no_javascript_access); } diff --git a/src/client_handler/lifespan_handler.h b/src/client_handler/lifespan_handler.h index 91244eff9..6b38d7dda 100644 --- a/src/client_handler/lifespan_handler.h +++ b/src/client_handler/lifespan_handler.h @@ -24,6 +24,7 @@ class LifespanHandler : public CefLifeSpanHandler CefWindowInfo& windowInfo, CefRefPtr& client, CefBrowserSettings& settings, + CefRefPtr& extra_info, bool* no_javascript_access) override; void OnAfterCreated(CefRefPtr browser) override; bool DoClose(CefRefPtr browser) override; diff --git a/src/client_handler/render_handler.cpp b/src/client_handler/render_handler.cpp index cf45d15ee..1935a3baf 100644 --- a/src/client_handler/render_handler.cpp +++ b/src/client_handler/render_handler.cpp @@ -13,11 +13,11 @@ bool RenderHandler::GetRootScreenRect(CefRefPtr browser, } -bool RenderHandler::GetViewRect(CefRefPtr browser, +void RenderHandler::GetViewRect(CefRefPtr browser, CefRect& rect) { REQUIRE_UI_THREAD(); - return RenderHandler_GetViewRect(browser, rect); + RenderHandler_GetViewRect(browser, rect); } @@ -69,16 +69,6 @@ void RenderHandler::OnPaint(CefRefPtr browser, } -void RenderHandler::OnCursorChange(CefRefPtr browser, - CefCursorHandle cursor, - CursorType type, - const CefCursorInfo& custom_cursor_info) -{ - REQUIRE_UI_THREAD(); - RenderHandler_OnCursorChange(browser, cursor); -} - - void RenderHandler::OnScrollOffsetChanged(CefRefPtr browser, double x, double y) diff --git a/src/client_handler/render_handler.h b/src/client_handler/render_handler.h index 75eee86c5..c87c52354 100644 --- a/src/client_handler/render_handler.h +++ b/src/client_handler/render_handler.h @@ -22,7 +22,7 @@ class RenderHandler : public CefRenderHandler, bool GetRootScreenRect(CefRefPtr browser, CefRect& rect) override; - bool GetViewRect(CefRefPtr browser, + void GetViewRect(CefRefPtr browser, CefRect& rect) override; bool GetScreenPoint(CefRefPtr browser, @@ -46,12 +46,6 @@ class RenderHandler : public CefRenderHandler, const void* buffer, int width, int height) override; - void OnCursorChange(CefRefPtr browser, - CefCursorHandle cursor, - CursorType type, - const CefCursorInfo& custom_cursor_info - ) override; - void OnScrollOffsetChanged(CefRefPtr browser, double x, double y) override; diff --git a/src/client_handler/request_context_handler.cpp b/src/client_handler/request_context_handler.cpp index bf816cf51..b0afa5b7d 100644 --- a/src/client_handler/request_context_handler.cpp +++ b/src/client_handler/request_context_handler.cpp @@ -9,31 +9,15 @@ // CefRequestContextHandler // -------------------------------------------------------------------------- -CefRefPtr RequestContextHandler::GetCookieManager() { - REQUIRE_IO_THREAD(); - if (browser_.get()) { - return RequestHandler_GetCookieManager(browser_, - browser_->GetMainFrame()->GetURL()); - } else { - CefString mainUrl; - return RequestHandler_GetCookieManager(browser_, mainUrl); - } - // Default: return NULL. -} +// CefRefPtr RequestContextHandler::GetCookieManager() { +// REQUIRE_IO_THREAD(); +// if (browser_.get()) { +// return RequestHandler_GetCookieManager(browser_, +// browser_->GetMainFrame()->GetURL()); +// } else { +// CefString mainUrl; +// return RequestHandler_GetCookieManager(browser_, mainUrl); +// } +// // Default: return NULL. +// } -bool RequestContextHandler::OnBeforePluginLoad( - const CefString& mime_type, - const CefString& plugin_url, - bool is_main_frame, - const CefString& top_origin_url, - CefRefPtr plugin_info, - PluginPolicy* plugin_policy) { - // Called on multiple threads - return RequestHandler_OnBeforePluginLoad(browser_, - mime_type, - plugin_url, - is_main_frame, - top_origin_url, - plugin_info, - plugin_policy); -} diff --git a/src/client_handler/request_context_handler.h b/src/client_handler/request_context_handler.h index b8bf25f3a..0fb8eb876 100644 --- a/src/client_handler/request_context_handler.h +++ b/src/client_handler/request_context_handler.h @@ -10,12 +10,14 @@ #include "common/cefpython_public_api.h" +#include "include/cef_request_context_handler.h" +#include "include/base/cef_callback.h" + class RequestContextHandler : public CefRequestContextHandler { private: CefRefPtr browser_; - typedef cef_plugin_policy_t PluginPolicy; public: // Browser may be NULL when instantiated from cefpython.CreateBrowserSync. @@ -29,13 +31,7 @@ class RequestContextHandler : browser_ = browser; } - virtual CefRefPtr GetCookieManager() OVERRIDE; - virtual bool OnBeforePluginLoad(const CefString& mime_type, - const CefString& plugin_url, - bool is_main_frame, - const CefString& top_origin_url, - CefRefPtr plugin_info, - PluginPolicy* plugin_policy) OVERRIDE; + // virtual CefRefPtr GetCookieManager() override; private: IMPLEMENT_REFCOUNTING(RequestContextHandler); diff --git a/src/client_handler/request_handler.cpp b/src/client_handler/request_handler.cpp index 5227b8921..8358bc564 100644 --- a/src/client_handler/request_handler.cpp +++ b/src/client_handler/request_handler.cpp @@ -4,6 +4,7 @@ #include "request_handler.h" #include "include/base/cef_logging.h" +#include "include/base/cef_callback.h" bool RequestHandler::OnBeforeBrowse(CefRefPtr browser, @@ -22,7 +23,7 @@ ReturnValue RequestHandler::OnBeforeResourceLoad( CefRefPtr browser, CefRefPtr frame, CefRefPtr request, - CefRefPtr callback) + CefRefPtr callback) { REQUIRE_IO_THREAD(); bool retval = RequestHandler_OnBeforeResourceLoad(browser, frame, request); @@ -73,8 +74,8 @@ bool RequestHandler::GetAuthCredentials(CefRefPtr browser, bool RequestHandler::OnQuotaRequest(CefRefPtr browser, const CefString& origin_url, - int64 new_size, - CefRefPtr callback) { + int64_t new_size, + CefRefPtr callback) { REQUIRE_IO_THREAD(); return RequestHandler_OnQuotaRequest(browser, origin_url, new_size, callback); @@ -94,7 +95,7 @@ bool RequestHandler::OnCertificateError( cef_errorcode_t cert_error, const CefString& request_url, CefRefPtr ssl_info, // not used - CefRefPtr callback) + CefRefPtr callback) { REQUIRE_UI_THREAD(); return RequestHandler_OnCertificateError(cert_error, request_url, @@ -118,17 +119,17 @@ void RequestHandler::OnPluginCrashed(CefRefPtr browser, RequestHandler_OnPluginCrashed(browser, plugin_path); } -bool RequestHandler::CanGetCookies(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr request) { - REQUIRE_IO_THREAD(); - return RequestHandler_CanGetCookies(browser, frame, request); -} - -bool RequestHandler::CanSetCookie(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr request, - const CefCookie& cookie) { - REQUIRE_IO_THREAD(); - return RequestHandler_CanSetCookie(browser, frame, request, cookie); -} +// bool RequestHandler::CanGetCookies(CefRefPtr browser, +// CefRefPtr frame, +// CefRefPtr request) { +// REQUIRE_IO_THREAD(); +// return RequestHandler_CanGetCookies(browser, frame, request); +// } + +// bool RequestHandler::CanSetCookie(CefRefPtr browser, +// CefRefPtr frame, +// CefRefPtr request, +// const CefCookie& cookie) { +// REQUIRE_IO_THREAD(); +// return RequestHandler_CanSetCookie(browser, frame, request, cookie); +// } diff --git a/src/client_handler/request_handler.h b/src/client_handler/request_handler.h index 7e5e0e6c3..77b22c552 100644 --- a/src/client_handler/request_handler.h +++ b/src/client_handler/request_handler.h @@ -4,6 +4,7 @@ #include "common/cefpython_public_api.h" #include "include/cef_request_handler.h" +#include "include/base/cef_callback.h" typedef cef_return_value_t ReturnValue; @@ -23,19 +24,19 @@ class RequestHandler : public CefRequestHandler ReturnValue OnBeforeResourceLoad(CefRefPtr browser, CefRefPtr frame, CefRefPtr request, - CefRefPtr callback - ) override; + CefRefPtr callback + ) ; CefRefPtr GetResourceHandler( CefRefPtr browser, CefRefPtr frame, - CefRefPtr request) override; + CefRefPtr request) ; void OnResourceRedirect(CefRefPtr browser, CefRefPtr frame, CefRefPtr request, CefRefPtr response, - CefString& new_url) override; + CefString& new_url) ; bool GetAuthCredentials(CefRefPtr browser, CefRefPtr frame, @@ -44,37 +45,37 @@ class RequestHandler : public CefRequestHandler int port, const CefString& realm, const CefString& scheme, - CefRefPtr callback) override; + CefRefPtr callback) ; bool OnQuotaRequest(CefRefPtr browser, const CefString& origin_url, - int64 new_size, - CefRefPtr callback) override; + int64_t new_size, + CefRefPtr callback) ; void OnProtocolExecution(CefRefPtr browser, const CefString& url, - bool& allow_os_execution) override; + bool& allow_os_execution) ; bool OnCertificateError(CefRefPtr browser, cef_errorcode_t cert_error, const CefString& request_url, CefRefPtr ssl_info, - CefRefPtr callback) override; + CefRefPtr callback) override; void OnRenderProcessTerminated(CefRefPtr browser, cef_termination_status_t status) override; void OnPluginCrashed(CefRefPtr browser, - const CefString& plugin_path) override; + const CefString& plugin_path) ; bool CanGetCookies(CefRefPtr browser, CefRefPtr frame, - CefRefPtr request) override; + CefRefPtr request) ; bool CanSetCookie(CefRefPtr browser, CefRefPtr frame, CefRefPtr request, - const CefCookie& cookie) override; + const CefCookie& cookie) ; private: IMPLEMENT_REFCOUNTING(RequestHandler); diff --git a/src/client_handler/resource_handler.cpp b/src/client_handler/resource_handler.cpp index 963575928..a2d2defbd 100644 --- a/src/client_handler/resource_handler.cpp +++ b/src/client_handler/resource_handler.cpp @@ -12,7 +12,7 @@ bool ResourceHandler::ProcessRequest(CefRefPtr request, } void ResourceHandler::GetResponseHeaders(CefRefPtr response, - int64& response_length, + int64_t& response_length, CefString& redirectUrl) { REQUIRE_IO_THREAD(); ResourceHandler_GetResponseHeaders(resourceHandlerId_, response, @@ -28,15 +28,15 @@ bool ResourceHandler::ReadResponse(void* data_out, bytes_to_read, bytes_read, callback); } -bool ResourceHandler::CanGetCookie(const CefCookie& cookie) { - REQUIRE_IO_THREAD(); - return ResourceHandler_CanGetCookie(resourceHandlerId_, cookie); -} +// bool ResourceHandler::CanGetCookie(const CefCookie& cookie) { +// REQUIRE_IO_THREAD(); +// return ResourceHandler_CanGetCookie(resourceHandlerId_, cookie); +// } -bool ResourceHandler::CanSetCookie(const CefCookie& cookie) { - REQUIRE_IO_THREAD(); - return ResourceHandler_CanSetCookie(resourceHandlerId_, cookie); -} +// bool ResourceHandler::CanSetCookie(const CefCookie& cookie) { +// REQUIRE_IO_THREAD(); +// return ResourceHandler_CanSetCookie(resourceHandlerId_, cookie); +// } void ResourceHandler::Cancel() { REQUIRE_IO_THREAD(); diff --git a/src/client_handler/resource_handler.h b/src/client_handler/resource_handler.h index 3bf5e41f6..329c68bc8 100644 --- a/src/client_handler/resource_handler.h +++ b/src/client_handler/resource_handler.h @@ -23,7 +23,7 @@ class ResourceHandler : public CefResourceHandler CefRefPtr callback) override; virtual void GetResponseHeaders(CefRefPtr response, - int64& response_length, + int64_t& response_length, CefString& redirectUrl) override; virtual bool ReadResponse(void* data_out, @@ -31,11 +31,11 @@ class ResourceHandler : public CefResourceHandler int& bytes_read, CefRefPtr callback) override; - virtual bool CanGetCookie(const CefCookie& cookie) override; + // virtual bool CanGetCookie(const CefCookie& cookie) ; - virtual bool CanSetCookie(const CefCookie& cookie) override; + // virtual bool CanSetCookie(const CefCookie& cookie) ; - virtual void Cancel() OVERRIDE; + virtual void Cancel() override; private: IMPLEMENT_REFCOUNTING(ResourceHandler); diff --git a/src/client_handler/string_visitor.h b/src/client_handler/string_visitor.h index 3765442c5..c36cf40f6 100644 --- a/src/client_handler/string_visitor.h +++ b/src/client_handler/string_visitor.h @@ -21,7 +21,7 @@ class StringVisitor : public CefStringVisitor virtual void Visit( const CefString& string - ) OVERRIDE; + ) override; protected: IMPLEMENT_REFCOUNTING(StringVisitor); diff --git a/src/client_handler/task.cpp b/src/client_handler/task.cpp index ec032a2d6..62a9fcbff 100644 --- a/src/client_handler/task.cpp +++ b/src/client_handler/task.cpp @@ -5,21 +5,22 @@ #include "task.h" #include "include/wrapper/cef_closure_task.h" #include "include/base/cef_bind.h" +#include "include/base/cef_callback.h" void PostTaskWrapper(int threadId, int taskId) { CefPostTask( static_cast(threadId), - CefCreateClosureTask(base::Bind( + CefCreateClosureTask(base::BindOnce( &PyTaskRunnable, taskId )) ); } -void PostDelayedTaskWrapper(int threadId, int64 delay_ms, int taskId) { +void PostDelayedTaskWrapper(int threadId, int64_t delay_ms, int taskId) { CefPostDelayedTask( static_cast(threadId), - CefCreateClosureTask(base::Bind( + CefCreateClosureTask(base::BindOnce( &PyTaskRunnable, taskId )), @@ -33,7 +34,7 @@ CefRefPtr CreateTask_SetCookie( const CefCookie& cookie, CefRefPtr callback) { - return CefCreateClosureTask(base::Bind( + return CefCreateClosureTask(base::BindOnce( base::IgnoreResult(&CefCookieManager::SetCookie), obj, url, cookie, @@ -47,7 +48,7 @@ CefRefPtr CreateTask_DeleteCookies( const CefString& cookie_name, CefRefPtr callback) { - return CefCreateClosureTask(base::Bind( + return CefCreateClosureTask(base::BindOnce( base::IgnoreResult(&CefCookieManager::DeleteCookies), obj, url, cookie_name, diff --git a/src/client_handler/task.h b/src/client_handler/task.h index 1839d9e32..a7d8c5b38 100644 --- a/src/client_handler/task.h +++ b/src/client_handler/task.h @@ -9,7 +9,7 @@ #include "include/cef_task.h" void PostTaskWrapper(int threadId, int taskId); -void PostDelayedTaskWrapper(int threadId, int64 delay_ms, int taskId); +void PostDelayedTaskWrapper(int threadId, int64_t delay_ms, int taskId); CefRefPtr CreateTask_SetCookie( CefCookieManager* obj, diff --git a/src/client_handler/web_request_client.cpp b/src/client_handler/web_request_client.cpp index 965de919b..509a72eda 100644 --- a/src/client_handler/web_request_client.cpp +++ b/src/client_handler/web_request_client.cpp @@ -9,14 +9,14 @@ void WebRequestClient::OnRequestComplete(CefRefPtr request) { } void WebRequestClient::OnUploadProgress(CefRefPtr request, - int64 current, - int64 total) { + int64_t current, + int64_t total) { WebRequestClient_OnUploadProgress(webRequestId_, request, current, total); } void WebRequestClient::OnDownloadProgress(CefRefPtr request, - int64 current, - int64 total) { + int64_t current, + int64_t total) { WebRequestClient_OnDownloadProgress(webRequestId_, request, current, total); } diff --git a/src/client_handler/web_request_client.h b/src/client_handler/web_request_client.h index 8b815a968..8f5bce96a 100644 --- a/src/client_handler/web_request_client.h +++ b/src/client_handler/web_request_client.h @@ -20,26 +20,26 @@ class WebRequestClient : public CefURLRequestClient } virtual ~WebRequestClient(){} - virtual void OnRequestComplete(CefRefPtr request) OVERRIDE; + virtual void OnRequestComplete(CefRefPtr request) override; virtual void OnUploadProgress(CefRefPtr request, - int64 current, - int64 total) OVERRIDE; + int64_t current, + int64_t total) override; virtual void OnDownloadProgress(CefRefPtr request, - int64 current, - int64 total) OVERRIDE; + int64_t current, + int64_t total) override; virtual void OnDownloadData(CefRefPtr request, const void* data, - size_t data_length) OVERRIDE; + size_t data_length) override; virtual bool GetAuthCredentials(bool isProxy, const CefString& host, int port, const CefString& realm, const CefString& scheme, - CefRefPtr callback) OVERRIDE; + CefRefPtr callback) override; protected: IMPLEMENT_REFCOUNTING(WebRequestClient); diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 632aab59c..023e1b0e9 100644 --- a/src/compile_time_constants.pxi +++ b/src/compile_time_constants.pxi @@ -1,3 +1,6 @@ # This file was generated by setup.py DEF UNAME_SYSNAME = "Windows" DEF PY_MAJOR_VERSION = 3 +cdef extern from "limits.h": + cdef int INT_MIN + cdef int INT_MAX diff --git a/src/cookie.pyx b/src/cookie.pyx index ce078c10e..d41fd22e7 100644 --- a/src/cookie.pyx +++ b/src/cookie.pyx @@ -154,16 +154,20 @@ cdef class Cookie: return self.cefCookie.httponly cpdef py_void SetCreation(self, object creation): - DatetimeToCefTimeT(creation, self.cefCookie.creation) + # DatetimeToCefBasetimeT(creation, self.cefCookie.creation) + pass cpdef object GetCreation(self): - return CefTimeTToDatetime(self.cefCookie.creation) + # return CefBasetimeTToDatetime(self.cefCookie.creation) + pass cpdef py_void SetLastAccess(self, object lastAccess): - DatetimeToCefTimeT(lastAccess, self.cefCookie.last_access) + # DatetimeToCefBasetimeT(lastAccess, self.cefCookie.last_access) + pass cpdef object GetLastAccess(self): - return CefTimeTToDatetime(self.cefCookie.last_access) + # return CefBasetimeTToDatetime(self.cefCookie.last_access) + pass cpdef py_void SetHasExpires(self, py_bool hasExpires): self.cefCookie.has_expires = bool(hasExpires) @@ -172,10 +176,12 @@ cdef class Cookie: return self.cefCookie.has_expires cpdef py_void SetExpires(self, object expires): - DatetimeToCefTimeT(expires, self.cefCookie.expires) + # DatetimeToCefBasetimeT(expires, self.cefCookie.expires) + pass cpdef object GetExpires(self): - return CefTimeTToDatetime(self.cefCookie.expires) + # return CefBasetimeTToDatetime(self.cefCookie.expires) + pass # ------------------------------------------------------------------------------ # CookieManager @@ -191,36 +197,36 @@ class CookieManager(object): cdef CefRefPtr[CefCookieManager] cefCookieManager if not g_globalCookieManager: cefCookieManager = CefCookieManager_GetGlobalManager( - NULL) + nullptr) g_globalCookieManager = CreatePyCookieManager(cefCookieManager) return g_globalCookieManager - @classmethod - def GetBlockingManager(cls): - return CreatePyCookieManager(CefCookieManager_GetBlockingManager()) - - @classmethod - def CreateManager(cls, py_string path, - py_bool persist_session_cookies=False): - """ - Create a new cookie manager. - :param path: - :type path: str - :param persist_session_cookies: - :type path: bool - :return: CookieManager object - :rtype: CookieManager - """ - # When PyCharm generates a stub for the cefpython module - # it doesn't use the above docstring for code inspections. - # No idea why. - cdef CefRefPtr[CefCookieManager] cefCookieManager - cefCookieManager = CefCookieManager_CreateManager( - PyToCefStringValue(path), bool(persist_session_cookies), - NULL) - if cefCookieManager != NULL and cefCookieManager.get(): - return CreatePyCookieManager(cefCookieManager) - return None + # @classmethod + # def GetBlockingManager(cls): + # return CreatePyCookieManager(CefCookieManager_GetBlockingManager()) + + # @classmethod + # def CreateManager(cls, py_string path, + # py_bool persist_session_cookies=False): + # """ + # Create a new cookie manager. + # :param path: + # :type path: str + # :param persist_session_cookies: + # :type path: bool + # :return: CookieManager object + # :rtype: CookieManager + # """ + # # When PyCharm generates a stub for the cefpython module + # # it doesn't use the above docstring for code inspections. + # # No idea why. + # cdef CefRefPtr[CefCookieManager] cefCookieManager + # cefCookieManager = CefCookieManager_CreateManager( + # PyToCefStringValue(path), bool(persist_session_cookies), + # nullptr) + # if cefCookieManager != NULL and cefCookieManager.get(): + # return CreatePyCookieManager(cefCookieManager) + # return None # ------------------------------------------------------------------------------ # PyCookieManager @@ -235,12 +241,12 @@ cdef PyCookieManager CreatePyCookieManager( cdef class PyCookieManager: cdef CefRefPtr[CefCookieManager] cefCookieManager - cpdef py_void SetSupportedSchemes(self, list schemes): - cdef cpp_vector[CefString] schemesVector - for scheme in schemes: - schemesVector.push_back(PyToCefStringValue(scheme)) - self.cefCookieManager.get().SetSupportedSchemes(schemesVector, - NULL) + # cpdef py_void SetSupportedSchemes(self, list schemes): + # cdef cpp_vector[CefString] schemesVector + # for scheme in schemes: + # schemesVector.push_back(PyToCefStringValue(scheme)) + # self.cefCookieManager.get().SetSupportedSchemes(schemesVector, + # nullptr) cdef py_void ValidateUserCookieVisitor(self, object userCookieVisitor): if userCookieVisitor and hasattr(userCookieVisitor, "Visit") and ( @@ -274,23 +280,17 @@ cdef class PyCookieManager: CefPostTask(TID_IO, CreateTask_SetCookie( self.cefCookieManager.get(), PyToCefStringValue(url), cookie.cefCookie, - NULL)) + nullptr)) cpdef py_void DeleteCookies(self, py_string url, py_string cookie_name): CefPostTask(TID_IO, CreateTask_DeleteCookies( self.cefCookieManager.get(), PyToCefStringValue(url), PyToCefStringValue(cookie_name), - NULL)) - - cpdef py_bool SetStoragePath(self, py_string path, - py_bool persistSessionCookies=False): - return self.cefCookieManager.get().SetStoragePath( - PyToCefStringValue(path), bool(persistSessionCookies), - NULL) + nullptr)) cpdef py_bool FlushStore(self, callback=None): return self.cefCookieManager.get().FlushStore( - NULL) + nullptr) # ------------------------------------------------------------------------------ diff --git a/src/dpi_aware_win.pyx b/src/dpi_aware_win.pyx index a7fc345fa..026414a81 100644 --- a/src/dpi_aware_win.pyx +++ b/src/dpi_aware_win.pyx @@ -67,4 +67,6 @@ class DpiAware: def EnableHighDpiSupport(cls): # This CEF function sets process to be DPI aware. This # CEF func is also called in subprocesses. - CefEnableHighDPISupport() + #CefEnableHighDPISupport() + pass + diff --git a/src/extern/cef/cef_app.pxd b/src/extern/cef/cef_app.pxd index ef270f1fc..1715c0cfd 100644 --- a/src/extern/cef/cef_app.pxd +++ b/src/extern/cef/cef_app.pxd @@ -23,8 +23,6 @@ cdef extern from "include/cef_app.h": cdef cppclass CefApp: pass - cdef void CefEnableHighDPISupport() nogil - cdef int CefExecuteProcess(CefMainArgs& args, CefRefPtr[CefApp] application, void* windows_sandbox_info diff --git a/src/extern/cef/cef_browser.pxd b/src/extern/cef/cef_browser.pxd index da209d5c3..44a187bb7 100644 --- a/src/extern/cef/cef_browser.pxd +++ b/src/extern/cef/cef_browser.pxd @@ -9,9 +9,10 @@ from cef_string cimport CefString from cef_client cimport CefClient from libcpp cimport bool as cpp_bool from libcpp.vector cimport vector as cpp_vector +from libc.stdint cimport int64_t from cef_frame cimport CefFrame cimport cef_types -from cef_types cimport int64, cef_state_t, CefSize +from cef_types cimport cef_state_t, CefSize from cef_types cimport CefBrowserSettings, CefPoint from cef_drag_data cimport CefDragData from cef_types cimport CefMouseEvent @@ -54,7 +55,7 @@ cdef extern from "include/cef_browser.h": cpp_bool mouseLeave) void SendMouseWheelEvent(cef_types.CefMouseEvent, int deltaX, int deltaY) - void SendFocusEvent(cpp_bool setFocus) + # void SendFocusEvent(cpp_bool setFocus) void SendCaptureLostEvent() void ShowDevTools(const CefWindowInfo& windowInfo, @@ -66,7 +67,7 @@ cdef extern from "include/cef_browser.h": CefRefPtr[CefRequestContext] GetRequestContext() - void Find(int identifier, const CefString& searchText, cpp_bool forward, + void Find(const CefString& searchText, cpp_bool forward, cpp_bool matchCase, cpp_bool findNext) void StopFinding(cpp_bool clearSelection) void Print() @@ -100,8 +101,8 @@ cdef extern from "include/cef_browser.h": cpp_bool CanGoBack() cpp_bool CanGoForward() CefRefPtr[CefFrame] GetFocusedFrame() - CefRefPtr[CefFrame] GetFrame(CefString& name) - CefRefPtr[CefFrame] GetFrame(int64 identifier) + CefRefPtr[CefFrame] GetFrameByName(CefString& name) + CefRefPtr[CefFrame] GetFrameByIdentifier(CefString& identifier) void GetFrameNames(cpp_vector[CefString]& names) CefRefPtr[CefFrame] GetMainFrame() void GoBack() @@ -113,5 +114,5 @@ cdef extern from "include/cef_browser.h": void StopLoad() cpp_bool IsLoading() int GetIdentifier() - cpp_bool SendProcessMessage(CefProcessId target_process, - CefRefPtr[CefProcessMessage] message) + # cpp_bool SendProcessMessage(CefProcessId target_process, + # CefRefPtr[CefProcessMessage] message) diff --git a/src/extern/cef/cef_browser_static.pxd b/src/extern/cef/cef_browser_static.pxd index 17b1a283d..fafa76aac 100644 --- a/src/extern/cef/cef_browser_static.pxd +++ b/src/extern/cef/cef_browser_static.pxd @@ -14,6 +14,7 @@ ELIF UNAME_SYSNAME == "Darwin": # noinspection PyUnresolvedReferences from cef_client cimport CefClient from cef_types cimport CefBrowserSettings +from cef_values cimport CefDictionaryValue # noinspection PyUnresolvedReferences from cef_request_context cimport CefRequestContext # noinspection PyUnresolvedReferences @@ -28,4 +29,5 @@ cdef extern from "include/cef_browser.h" namespace "CefBrowserHost": CefRefPtr[CefClient], CefString&, CefBrowserSettings&, + CefRefPtr[CefDictionaryValue], CefRefPtr[CefRequestContext]) nogil diff --git a/src/extern/cef/cef_cookie.pxd b/src/extern/cef/cef_cookie.pxd index c113aea9a..cff03ea1e 100644 --- a/src/extern/cef/cef_cookie.pxd +++ b/src/extern/cef/cef_cookie.pxd @@ -50,9 +50,6 @@ cdef extern from "include/cef_cookie.h": cpp_bool DeleteCookies(const CefString& url, const CefString& cookie_name, CefRefPtr[CefDeleteCookiesCallback] callback) - cpp_bool SetStoragePath(const CefString& path, - cpp_bool persist_session_cookies, - CefRefPtr[CefCompletionCallback] callback) cpp_bool FlushStore(CefRefPtr[CefCompletionCallback] callback) cdef cppclass CefCookieVisitor: diff --git a/src/extern/cef/cef_frame.pxd b/src/extern/cef/cef_frame.pxd index 28cdceee2..54efdd373 100644 --- a/src/extern/cef/cef_frame.pxd +++ b/src/extern/cef/cef_frame.pxd @@ -4,12 +4,12 @@ include "compile_time_constants.pxi" -from cef_types cimport int64 from cef_string cimport CefString from libcpp cimport bool as cpp_bool from cef_ptr cimport CefRefPtr from cef_browser cimport CefBrowser from cef_string_visitor cimport CefStringVisitor +from cef_process_message cimport CefProcessMessage, CefProcessId cdef extern from "include/cef_frame.h": @@ -17,7 +17,7 @@ cdef extern from "include/cef_frame.h": cpp_bool IsValid() void ExecuteJavaScript(CefString& jsCode, CefString& scriptUrl, int startLine) CefString GetURL() - int64 GetIdentifier() + CefString GetIdentifier() cpp_bool IsMain() void LoadURL(CefString& url) void Undo() @@ -35,3 +35,5 @@ cdef extern from "include/cef_frame.h": CefString GetName() CefRefPtr[CefFrame] GetParent() CefRefPtr[CefBrowser] GetBrowser() + cpp_bool SendProcessMessage(CefProcessId target_process, + CefRefPtr[CefProcessMessage] message) diff --git a/src/extern/cef/cef_ptr.pxd b/src/extern/cef/cef_ptr.pxd index c5d9877cf..0f99fe7a1 100644 --- a/src/extern/cef/cef_ptr.pxd +++ b/src/extern/cef/cef_ptr.pxd @@ -1,6 +1,7 @@ # Copyright (c) 2012 CEF Python, see the Authors file. # All rights reserved. Licensed under BSD 3-clause license. # Project website: https://github.com/cztomczak/cefpython +from libcpp cimport nullptr_t, bool cdef extern from "include/internal/cef_ptr.h": cdef cppclass CefRefPtr[T]: @@ -14,4 +15,7 @@ cdef extern from "include/internal/cef_ptr.h": # noinspection PyUnresolvedReferences void swap(CefRefPtr[T]& r) # noinspection PyUnresolvedReferences + CefRefPtr[T]& Assign "operator="(nullptr_t) CefRefPtr[T]& Assign "operator="(T* p) + bool operator bool() + bool operator!() \ No newline at end of file diff --git a/src/extern/cef/cef_request_context.pxd b/src/extern/cef/cef_request_context.pxd index 116741749..1107cb6fc 100644 --- a/src/extern/cef/cef_request_context.pxd +++ b/src/extern/cef/cef_request_context.pxd @@ -16,5 +16,5 @@ cdef extern from "include/cef_request_context.h": CefRefPtr[CefRequestContext] CreateContext( CefRefPtr[CefRequestContext] other, CefRefPtr[CefRequestContextHandler] handler) - CefRefPtr[CefCookieManager] GetDefaultCookieManager( + CefRefPtr[CefCookieManager] GetCookieManager( CefRefPtr[CefCompletionCallback] callback) diff --git a/src/extern/cef/cef_request_handler.pxd b/src/extern/cef/cef_request_handler.pxd index 96a7d88c6..a6e320488 100644 --- a/src/extern/cef/cef_request_handler.pxd +++ b/src/extern/cef/cef_request_handler.pxd @@ -11,7 +11,3 @@ cdef extern from "include/cef_auth_callback.h": const CefString& password) void Cancel() -cdef extern from "include/cef_request_handler.h": - cdef cppclass CefRequestCallback: - void Continue(cpp_bool allow) - void Cancel() diff --git a/src/extern/cef/cef_response.pxd b/src/extern/cef/cef_response.pxd index ef6729f12..9c08a0ec1 100644 --- a/src/extern/cef/cef_response.pxd +++ b/src/extern/cef/cef_response.pxd @@ -21,6 +21,6 @@ cdef extern from "include/cef_response.h": void SetStatusText(CefString& statusText) CefString GetMimeType() void SetMimeType(CefString& mimeType) - CefString GetHeader(CefString& name) + CefString GetHeaderByName(CefString& name) void GetHeaderMap(CefResponseHeaderMap& headerMap) void SetHeaderMap(CefResponseHeaderMap& headerMap) diff --git a/src/extern/cef/cef_scoped_ptr.pxd b/src/extern/cef/cef_scoped_ptr.pxd deleted file mode 100644 index 2e770a5b9..000000000 --- a/src/extern/cef/cef_scoped_ptr.pxd +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2016 CEF Python, see the Authors file. -# All rights reserved. Licensed under BSD 3-clause license. -# Project website: https://github.com/cztomczak/cefpython - -cdef extern from "include/base/cef_scoped_ptr.h": - cdef cppclass scoped_ptr[T]: - scoped_ptr() - # noinspection PyUnresolvedReferences - scoped_ptr(T* p) - # noinspection PyUnresolvedReferences - void reset() - # noinspection PyUnresolvedReferences - void reset(T* p) - # noinspection PyUnresolvedReferences - T* get() - # noinspection PyUnresolvedReferences - scoped_ptr[T]& Assign "operator="(scoped_ptr[T] p) diff --git a/src/extern/cef/cef_task.pxd b/src/extern/cef/cef_task.pxd index fbc0181e0..c7dfcdf02 100644 --- a/src/extern/cef/cef_task.pxd +++ b/src/extern/cef/cef_task.pxd @@ -3,9 +3,9 @@ # Project website: https://github.com/cztomczak/cefpython from libcpp cimport bool as cpp_bool +from libc.stdint cimport int64_t # noinspection PyUnresolvedReferences cimport cef_types -from cef_types cimport int64 from cef_ptr cimport CefRefPtr cdef extern from "include/cef_task.h": @@ -16,7 +16,7 @@ cdef extern from "include/cef_task.h": CefRefPtr[CefTask] task) cdef cpp_bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr[CefTask] task, - int64 delay_ms) + int64_t delay_ms) cdef cppclass CefTask: pass diff --git a/src/extern/cef/cef_time.pxd b/src/extern/cef/cef_time.pxd index cdbdc639f..8b01ad9ab 100644 --- a/src/extern/cef/cef_time.pxd +++ b/src/extern/cef/cef_time.pxd @@ -3,6 +3,7 @@ # Project website: https://github.com/cztomczak/cefpython from ctime cimport time_t +from libc.stdint cimport int64_t cdef extern from "include/internal/cef_time.h": ctypedef struct cef_time_t: @@ -15,6 +16,9 @@ cdef extern from "include/internal/cef_time.h": int second int millisecond +ctypedef struct cef_basetime_t: + int64_t val + cdef extern from "include/internal/cef_types.h": cdef cppclass CefTime: CefTime() diff --git a/src/extern/cef/cef_types.pxd b/src/extern/cef/cef_types.pxd index 6bd21ba46..ad150bb77 100644 --- a/src/extern/cef/cef_types.pxd +++ b/src/extern/cef/cef_types.pxd @@ -15,26 +15,16 @@ from libc.limits cimport UINT_MAX cdef extern from "include/internal/cef_types.h": - # noinspection PyUnresolvedReferences - ctypedef int32_t int32 - # noinspection PyUnresolvedReferences - ctypedef uint32_t uint32 - # noinspection PyUnresolvedReferences - ctypedef int64_t int64 - # noinspection PyUnresolvedReferences - ctypedef uint64_t uint64 - IF UNAME_SYSNAME == "Windows": # noinspection PyUnresolvedReferences - ctypedef wchar_t char16 + ctypedef wchar_t char16_t ELSE: - ctypedef unsigned short char16 + ctypedef unsigned short char16_t - ctypedef uint32 cef_color_t + ctypedef uint32_t cef_color_t ctypedef struct CefSettings: cef_string_t accept_language_list - int single_process cef_string_t browser_subprocess_path int command_line_args_disabled cef_string_t cache_path @@ -191,12 +181,12 @@ cdef extern from "include/internal/cef_types.h": KEYEVENT_CHAR ctypedef struct _cef_key_event_t: cef_key_event_type_t type - uint32 modifiers + uint32_t modifiers int windows_key_code int native_key_code int is_system_key - char16 character - char16 unmodified_character + char16_t character + char16_t unmodified_character cpp_bool focus_on_editable_field ctypedef _cef_key_event_t CefKeyEvent ctypedef enum cef_event_flags_t: @@ -287,7 +277,7 @@ cdef extern from "include/internal/cef_types.h": ctypedef struct cef_mouse_event_t: int x int y - uint32 modifiers + uint32_t modifiers ctypedef cef_mouse_event_t CefMouseEvent # RenderHandler > GetScreenInfo(): @@ -323,16 +313,16 @@ cdef extern from "include/internal/cef_types.h": # LifespanHandler and RequestHandler ctypedef enum cef_window_open_disposition_t: - WOD_UNKNOWN, - WOD_CURRENT_TAB, - WOD_SINGLETON_TAB, - WOD_NEW_FOREGROUND_TAB, - WOD_NEW_BACKGROUND_TAB, - WOD_NEW_POPUP, - WOD_NEW_WINDOW, - WOD_SAVE_TO_DISK, - WOD_OFF_THE_RECORD, - WOD_IGNORE_ACTION + CEF_WOD_UNKNOWN, + CEF_WOD_CURRENT_TAB, + CEF_WOD_SINGLETON_TAB, + CEF_WOD_NEW_FOREGROUND_TAB, + CEF_WOD_NEW_BACKGROUND_TAB, + CEF_WOD_NEW_POPUP, + CEF_WOD_NEW_WINDOW, + CEF_WOD_SAVE_TO_DISK, + CEF_WOD_OFF_THE_RECORD, + CEF_WOD_IGNORE_ACTION ctypedef cef_window_open_disposition_t WindowOpenDisposition ctypedef enum cef_path_key_t: @@ -347,12 +337,6 @@ cdef extern from "include/internal/cef_types.h": PK_DIR_RESOURCES, ctypedef cef_path_key_t PathKey - ctypedef enum cef_plugin_policy_t: - PLUGIN_POLICY_ALLOW, - PLUGIN_POLICY_DETECT_IMPORTANT, - PLUGIN_POLICY_BLOCK, - PLUGIN_POLICY_DISABLE, - # Drag & drop ctypedef enum cef_drag_operations_mask_t: diff --git a/src/extern/cef/cef_web_plugin.pxd b/src/extern/cef/cef_web_plugin.pxd deleted file mode 100644 index 25d33fa9d..000000000 --- a/src/extern/cef/cef_web_plugin.pxd +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013 CEF Python, see the Authors file. -# All rights reserved. Licensed under BSD 3-clause license. -# Project website: https://github.com/cztomczak/cefpython - -from cef_string cimport CefString - -# CEF 3 only. - -cdef extern from "include/cef_web_plugin.h": - cdef cppclass CefWebPluginInfo: - CefString GetName() - CefString GetPath() - CefString GetVersion() - CefString GetDescription() diff --git a/src/extern/cef/cef_win.pxd b/src/extern/cef/cef_win.pxd index 5e341b75b..e6844e58c 100644 --- a/src/extern/cef/cef_win.pxd +++ b/src/extern/cef/cef_win.pxd @@ -5,9 +5,10 @@ include "compile_time_constants.pxi" # noinspection PyUnresolvedReferences -from windows cimport HWND, RECT, HINSTANCE, HCURSOR +from windows cimport HWND, HINSTANCE, HCURSOR from cef_string cimport CefString from libcpp cimport bool as cpp_bool +from cef_types cimport CefRect cdef extern from "include/internal/cef_win.h": @@ -18,7 +19,7 @@ cdef extern from "include/internal/cef_win.h": cdef cppclass CefWindowInfo: void SetAsChild(CefWindowHandle parent, - RECT windowRect) + const CefRect windowRect) void SetAsPopup(CefWindowHandle parent, const CefString& windowName) void SetAsWindowless(CefWindowHandle parent) diff --git a/src/extern/main_message_loop.pxd b/src/extern/main_message_loop.pxd index 486f309af..af05e1100 100644 --- a/src/extern/main_message_loop.pxd +++ b/src/extern/main_message_loop.pxd @@ -2,11 +2,11 @@ # All rights reserved. Licensed under BSD 3-clause license. # Project website: https://github.com/cztomczak/cefpython -from cef_scoped_ptr cimport scoped_ptr +from libcpp.memory cimport unique_ptr cdef extern from \ "subprocess/main_message_loop/main_message_loop_external_pump.h": cdef cppclass MainMessageLoopExternalPump: @staticmethod - scoped_ptr[MainMessageLoopExternalPump] Create() + unique_ptr[MainMessageLoopExternalPump] Create() diff --git a/src/extern/task.pxd b/src/extern/task.pxd index 14f2777b4..3c883ad95 100644 --- a/src/extern/task.pxd +++ b/src/extern/task.pxd @@ -11,13 +11,13 @@ from cef_cookie cimport CefCookie, CefCookieManager from cef_cookie cimport CefSetCookieCallback, CefDeleteCookiesCallback # noinspection PyUnresolvedReferences from libcpp cimport bool as cpp_bool -from cef_types cimport int64 +from libc.stdint cimport int64_t cdef extern from "client_handler/task.h": void PostTaskWrapper(int threadId, int taskId) nogil - void PostDelayedTaskWrapper(int threadId, int64 delay_ms, int taskId) nogil + void PostDelayedTaskWrapper(int threadId, int64_t delay_ms, int taskId) nogil cdef CefRefPtr[CefTask] CreateTask_SetCookie( CefCookieManager* obj, diff --git a/src/frame.pyx b/src/frame.pyx index ec3ef8bcb..72650491d 100644 --- a/src/frame.pyx +++ b/src/frame.pyx @@ -11,10 +11,10 @@ cdef dict g_pyFrames = {} # it shouldn't be kept global anymore. cdef list g_unreferenced_frames = [] # [str unique identifier, ..] -cdef object GetUniqueFrameId(int browserId, object frameId): - return str(browserId) +"#"+ str(frameId) +cdef str GetUniqueFrameId(int browserId, py_string frameId): + return str(browserId) +"#"+ frameId -cdef PyFrame GetPyFrameById(int browserId, object frameId): +cdef PyFrame GetPyFrameById(int browserId, py_string frameId): cdef object uniqueFrameId = GetUniqueFrameId(browserId, frameId) if uniqueFrameId in g_pyFrames: return g_pyFrames[uniqueFrameId] @@ -23,23 +23,23 @@ cdef PyFrame GetPyFrameById(int browserId, object frameId): cdef PyFrame GetPyFrame(CefRefPtr[CefFrame] cefFrame): global g_pyFrames - if cefFrame == NULL or not cefFrame.get(): + if not cefFrame or not cefFrame.get(): raise Exception("GetPyFrame(): CefFrame reference is NULL") cdef PyFrame pyFrame - cdef object frameId = cefFrame.get().GetIdentifier() # int64 + cdef CefString frameId = cefFrame.get().GetIdentifier() cdef int browserId = cefFrame.get().GetBrowser().get().GetIdentifier() - assert (frameId and browserId), "frameId or browserId empty" - cdef object uniqueFrameId = GetUniqueFrameId(browserId, frameId) + assert (not frameId.empty() and browserId), "frameId or browserId empty" + cdef str uniqueFrameId = GetUniqueFrameId(browserId, CefToPyString(frameId)) - if frameId < 0: + if frameId.empty(): # Underlying frame does not yet exist. In such case PyFrame # is not stored in g_pyFrames since frameId is invalid. # However even though frame is not supposed to exist, you # can still call CefFrame.ExecuteFunction and it works fine # in tutorial.py example. Debug("GetPyFrame(): underlying frame does not yet exist:" - " browserId = {0}, frameId = {1}".format(browserId, frameId)) + " browserId = {0}, frameId = {1}".format(browserId, CefToPyString(frameId))) else: if uniqueFrameId in g_pyFrames: return g_pyFrames[uniqueFrameId] @@ -56,11 +56,11 @@ cdef PyFrame GetPyFrame(CefRefPtr[CefFrame] cefFrame): del g_pyFrames[uFid] # ---- - pyFrame = PyFrame(browserId, frameId) + pyFrame = PyFrame(browserId, CefToPyString(frameId)) pyFrame.cefFrame = cefFrame if uniqueFrameId in g_unreferenced_frames \ - or frameId < 0 \ + or frameId.empty() \ or browserId in g_unreferenced_browsers \ or browserId in g_closed_browsers: # Browser was already globally unreferenced in OnBeforeClose, @@ -77,19 +77,19 @@ cdef PyFrame GetPyFrame(CefRefPtr[CefFrame] cefFrame): # SIDE EFFECT: two calls to GetPyFrame for the same frame object # may return two different PyFrame objects. Compare # frame objects always using GetIdentifier(). - Debug("GetPyFrame(): create new PyFrame, frameId=%s" % frameId) + Debug("GetPyFrame(): create new PyFrame, frameId=%s" % CefToPyString(frameId)) g_pyFrames[uniqueFrameId] = pyFrame return pyFrame -cdef void RemovePyFrame(int browserId, object frameId) except *: +cdef void RemovePyFrame(int browserId, str frameId) except *: # Called from V8ContextHandler_OnContextReleased(). global g_pyFrames cdef PyFrame pyFrame - cdef object uniqueFrameId = GetUniqueFrameId(browserId, frameId) + cdef str uniqueFrameId = GetUniqueFrameId(browserId, frameId) if uniqueFrameId in g_pyFrames: Debug("del g_pyFrames[%s]" % uniqueFrameId) pyFrame = g_pyFrames[uniqueFrameId] - pyFrame.cefFrame.Assign(NULL) + pyFrame.cefFrame.Assign(nullptr) del pyFrame del g_pyFrames[uniqueFrameId] g_unreferenced_frames.append(uniqueFrameId) @@ -109,7 +109,7 @@ cdef void RemovePyFramesForBrowser(int browserId) except *: for uniqueFrameId in toRemove: Debug("del g_pyFrames[%s]" % uniqueFrameId) pyFrame = g_pyFrames[uniqueFrameId] - pyFrame.cefFrame.Assign(NULL) + pyFrame.cefFrame.Assign(nullptr) del pyFrame del g_pyFrames[uniqueFrameId] g_unreferenced_frames.append(uniqueFrameId) @@ -119,22 +119,22 @@ cdef void RemovePyFramesForBrowser(int browserId) except *: cdef class PyFrame: cdef CefRefPtr[CefFrame] cefFrame cdef int browserId - cdef object frameId + cdef str frameId cdef CefRefPtr[CefFrame] GetCefFrame(self) except *: # Do not call IsValid() here, if the frame does not exist # then no big deal, no reason to crash the application. # The CEF calls will fail, but they also won't cause crash. - if self.cefFrame != NULL and self.cefFrame.get(): + if self.cefFrame.get(): return self.cefFrame raise Exception("PyFrame.GetCefFrame() failed: CefFrame was destroyed") - def __init__(self, int browserId, int frameId): + def __init__(self, int browserId, py_string frameId): self.browserId = browserId self.frameId = frameId cpdef py_bool IsValid(self): - if self.cefFrame != NULL and self.cefFrame.get() \ + if self.cefFrame and self.cefFrame.get() \ and self.cefFrame.get().IsValid(): return True return False @@ -168,7 +168,7 @@ cdef class PyFrame: self.GetCefFrame().get().ExecuteJavaScript(PyToCefStringValue(jsCode), PyToCefStringValue(scriptUrl), startLine) - cpdef object GetIdentifier(self): + cpdef str GetIdentifier(self): # It is better to save browser and frame identifiers during # browser instantiation. When freeing PyBrowser and PyFrame # we need these identifiers. CefFrame and CefBrowser may already @@ -203,12 +203,12 @@ cdef class PyFrame: cpdef py_bool IsMain(self): return self.GetCefFrame().get().IsMain() - cpdef py_void LoadString(self, py_string value, py_string url): - cdef CefString cefValue - cdef CefString cefUrl - PyToCefString(value, cefValue) - PyToCefString(url, cefUrl) - self.GetCefFrame().get().LoadString(cefValue, cefUrl) + # cpdef py_void LoadString(self, py_string value, py_string url): + # cdef CefString cefValue + # cdef CefString cefUrl + # PyToCefString(value, cefValue) + # PyToCefString(url, cefUrl) + # self.GetCefFrame().get().LoadString(cefValue, cefUrl) cpdef py_void LoadUrl(self, py_string url): url = GetNavigateUrl(url) @@ -230,3 +230,33 @@ cdef class PyFrame: cpdef py_void ViewSource(self): self.GetCefFrame().get().ViewSource() + + cpdef py_void SendProcessMessage(self, cef_process_id_t targetProcess, + py_string frameId, py_string messageName, list pyArguments + ) : + cdef CefRefPtr[CefProcessMessage] message = \ + CefProcessMessage_Create(PyToCefStringValue(messageName)) + # This does not work, no idea why, the CEF implementation + # seems not to allow it, both Assign() and swap() do not work: + # | message.get().GetArgumentList().Assign(arguments.get()) + # | message.get().GetArgumentList().swap(arguments) + cdef CefRefPtr[CefListValue] messageArguments = \ + message.get().GetArgumentList() + PyListToExistingCefListValue(self.GetBrowserIdentifier(), + frameId, + pyArguments, messageArguments) + Debug("SendProcessMessage(): message=%s, arguments size=%d" % ( + messageName, + message.get().GetArgumentList().get().GetSize())) + #lc test + # cdef cpp_bool success = \ + # self.GetCefFrame().get().SendProcessMessage( + # targetProcess, + # message) + # if not success: + # raise Exception("Frame.SendProcessMessage() failed: "\ + # "messageName=%s" % messageName) + + self.GetCefFrame().get().SendProcessMessage(targetProcess, message) + + diff --git a/src/handlers/display_handler.pyx b/src/handlers/display_handler.pyx index 7d66d00f7..f729a7dee 100644 --- a/src/handlers/display_handler.pyx +++ b/src/handlers/display_handler.pyx @@ -143,3 +143,23 @@ cdef public void DisplayHandler_OnLoadingProgressChange( except: (exc_type, exc_value, exc_trace) = sys.exc_info() sys.excepthook(exc_type, exc_value, exc_trace) + +cdef public cpp_bool DisplayHandler_OnCursorChange( + CefRefPtr[CefBrowser] cefBrowser, + CefCursorHandle cursor + ) except * with gil: + cdef PyBrowser pyBrowser + try: + pyBrowser = GetPyBrowser(cefBrowser, "OnCursorChange") + callback = pyBrowser.GetClientCallback("OnCursorChange") + if callback: + ret = callback(browser=pyBrowser, cursor=cursor) + if ret: + return True + else: + return False + else: + return False + except: + (exc_type, exc_value, exc_trace) = sys.exc_info() + sys.excepthook(exc_type, exc_value, exc_trace) diff --git a/src/handlers/lifespan_handler.pyx b/src/handlers/lifespan_handler.pyx index bfe22bd11..7c354881b 100644 --- a/src/handlers/lifespan_handler.pyx +++ b/src/handlers/lifespan_handler.pyx @@ -11,16 +11,16 @@ from cef_types cimport WindowOpenDisposition cimport cef_types # WindowOpenDisposition -WOD_UNKNOWN = cef_types.WOD_UNKNOWN -WOD_CURRENT_TAB = cef_types.WOD_CURRENT_TAB -WOD_SINGLETON_TAB = cef_types.WOD_SINGLETON_TAB -WOD_NEW_FOREGROUND_TAB = cef_types.WOD_NEW_FOREGROUND_TAB -WOD_NEW_BACKGROUND_TAB = cef_types.WOD_NEW_BACKGROUND_TAB -WOD_NEW_POPUP = cef_types.WOD_NEW_POPUP -WOD_NEW_WINDOW = cef_types.WOD_NEW_WINDOW -WOD_SAVE_TO_DISK = cef_types.WOD_SAVE_TO_DISK -WOD_OFF_THE_RECORD = cef_types.WOD_OFF_THE_RECORD -WOD_IGNORE_ACTION = cef_types.WOD_IGNORE_ACTION +CEF_WOD_UNKNOWN = cef_types.CEF_WOD_UNKNOWN +CEF_WOD_CURRENT_TAB = cef_types.CEF_WOD_CURRENT_TAB +CEF_WOD_SINGLETON_TAB = cef_types.CEF_WOD_SINGLETON_TAB +CEF_WOD_NEW_FOREGROUND_TAB = cef_types.CEF_WOD_NEW_FOREGROUND_TAB +CEF_WOD_NEW_BACKGROUND_TAB = cef_types.CEF_WOD_NEW_BACKGROUND_TAB +CEF_WOD_NEW_POPUP = cef_types.CEF_WOD_NEW_POPUP +CEF_WOD_NEW_WINDOW = cef_types.CEF_WOD_NEW_WINDOW +CEF_WOD_SAVE_TO_DISK = cef_types.CEF_WOD_SAVE_TO_DISK +CEF_WOD_OFF_THE_RECORD = cef_types.CEF_WOD_OFF_THE_RECORD +CEF_WOD_IGNORE_ACTION = cef_types.CEF_WOD_IGNORE_ACTION cdef public cpp_bool LifespanHandler_OnBeforePopup( @@ -34,6 +34,7 @@ cdef public cpp_bool LifespanHandler_OnBeforePopup( CefWindowInfo& windowInfo, CefRefPtr[CefClient]& client, CefBrowserSettings& settings, + CefRefPtr[CefDictionaryValue]& extra_info, cpp_bool* noJavascriptAccess ) except * with gil: # Empty place-holders: popupFeatures, client. @@ -133,13 +134,13 @@ cdef public void LifespanHandler_OnBeforeClose( # GetCookieManager to implement custom cookie managers then # flushing of cookies would need to be handled manually. cefBrowser.get().GetHost().get().GetRequestContext().get() \ - .GetDefaultCookieManager( - NULL) \ - .get().FlushStore(NULL) + .GetCookieManager( + nullptr) \ + .get().FlushStore(nullptr) browserId = pyBrowser.GetIdentifier() - pyBrowser.cefBrowser.Assign(NULL) - cefBrowser.Assign(NULL) + pyBrowser.cefBrowser.Assign(nullptr) + cefBrowser.Assign(nullptr) del pyBrowser RemovePythonCallbacksForBrowser(browserId) diff --git a/src/handlers/render_handler.pyx b/src/handlers/render_handler.pyx index a8ad49124..a282c8893 100644 --- a/src/handlers/render_handler.pyx +++ b/src/handlers/render_handler.pyx @@ -7,6 +7,7 @@ include "../browser.pyx" include "../string_utils.pyx" cimport cef_types +from libc.stdint cimport uint32_t from cef_types cimport CefRange # cef_paint_element_type_t, PaintElementType @@ -73,7 +74,13 @@ cdef public cpp_bool RenderHandler_GetViewRect( else: return False else: - return False + # without a default cefRect, pysdl2 example will fail + # the value is inspired by https://github.com/obsproject/obs-browser/blob/master/browser-client.cpp#L280 + cefRect.x = 0 + cefRect.y = 0 + cefRect.width = 16 + cefRect.height = 16 + return True except: (exc_type, exc_value, exc_trace) = sys.exc_info() sys.excepthook(exc_type, exc_value, exc_trace) @@ -219,20 +226,6 @@ cdef public void RenderHandler_OnPaint( (exc_type, exc_value, exc_trace) = sys.exc_info() sys.excepthook(exc_type, exc_value, exc_trace) -cdef public void RenderHandler_OnCursorChange( - CefRefPtr[CefBrowser] cefBrowser, - CefCursorHandle cursor - ) except * with gil: - cdef PyBrowser pyBrowser - try: - pyBrowser = GetPyBrowser(cefBrowser, "OnCursorChange") - callback = pyBrowser.GetClientCallback("OnCursorChange") - if callback: - callback(browser=pyBrowser, cursor=cursor) - except: - (exc_type, exc_value, exc_trace) = sys.exc_info() - sys.excepthook(exc_type, exc_value, exc_trace) - cdef public void RenderHandler_OnScrollOffsetChanged( CefRefPtr[CefBrowser] cefBrowser ) except * with gil: @@ -249,7 +242,7 @@ cdef public void RenderHandler_OnScrollOffsetChanged( cdef public cpp_bool RenderHandler_StartDragging( CefRefPtr[CefBrowser] cef_browser, CefRefPtr[CefDragData] cef_drag_data, - uint32 allowed_ops, + uint32_t allowed_ops, int x, int y ) except * with gil: cdef PyBrowser browser @@ -278,7 +271,7 @@ cdef public cpp_bool RenderHandler_StartDragging( cdef public void RenderHandler_UpdateDragCursor( CefRefPtr[CefBrowser] cef_browser, - uint32 operation, + uint32_t operation, ) except * with gil: cdef PyBrowser browser try: diff --git a/src/handlers/request_handler.pyx b/src/handlers/request_handler.pyx index 866942bfd..b9579cc69 100644 --- a/src/handlers/request_handler.pyx +++ b/src/handlers/request_handler.pyx @@ -8,6 +8,7 @@ include "../cookie.pyx" # cef_termination_status_t cimport cef_types +from libc.stdint cimport int64_t TS_ABNORMAL_TERMINATION = cef_types.TS_ABNORMAL_TERMINATION TS_PROCESS_WAS_KILLED = cef_types.TS_PROCESS_WAS_KILLED TS_PROCESS_CRASHED = cef_types.TS_PROCESS_CRASHED @@ -37,16 +38,16 @@ cdef class PyAuthCallback: # ----------------------------------------------------------------------------- cdef PyRequestCallback CreatePyRequestCallback( - CefRefPtr[CefRequestCallback] cefCallback): + CefRefPtr[CefCallback] cefCallback): cdef PyRequestCallback pyCallback = PyRequestCallback() pyCallback.cefCallback = cefCallback return pyCallback cdef class PyRequestCallback: - cdef CefRefPtr[CefRequestCallback] cefCallback + cdef CefRefPtr[CefCallback] cefCallback - cpdef py_void Continue(self, py_bool allow): - self.cefCallback.get().Continue(bool(allow)) + cpdef py_void Continue(self): + self.cefCallback.get().Continue() cpdef py_void Cancel(self): self.cefCallback.get().Cancel() @@ -140,7 +141,7 @@ cdef public CefRefPtr[CefResourceHandler] RequestHandler_GetResourceHandler( # Issue #455: CefRequestHandler callbacks still executed after # browser was closed. if IsBrowserClosed(cefBrowser): - return NULL + return nullptr pyBrowser = GetPyBrowser(cefBrowser, "GetResourceHandler") pyFrame = GetPyFrame(cefFrame) @@ -154,9 +155,9 @@ cdef public CefRefPtr[CefResourceHandler] RequestHandler_GetResourceHandler( if returnValue: return CreateResourceHandler(returnValue) else: - return NULL + return nullptr else: - return NULL + return nullptr except: (exc_type, exc_value, exc_trace) = sys.exc_info() sys.excepthook(exc_type, exc_value, exc_trace) @@ -279,8 +280,8 @@ cdef public cpp_bool RequestHandler_GetAuthCredentials( cdef public cpp_bool RequestHandler_OnQuotaRequest( CefRefPtr[CefBrowser] cefBrowser, const CefString& cefOriginUrl, - int64 newSize, - CefRefPtr[CefRequestCallback] cefRequestCallback + int64_t newSize, + CefRefPtr[CefCallback] cefCallback ) except * with gil: cdef PyBrowser pyBrowser cdef py_string pyOriginUrl @@ -300,7 +301,7 @@ cdef public cpp_bool RequestHandler_OnQuotaRequest( browser=pyBrowser, origin_url=pyOriginUrl, new_size=newSize, - callback=CreatePyRequestCallback(cefRequestCallback)) + callback=CreatePyRequestCallback(cefCallback)) return bool(returnValue) else: return False @@ -309,47 +310,48 @@ cdef public cpp_bool RequestHandler_OnQuotaRequest( sys.excepthook(exc_type, exc_value, exc_trace) -cdef public CefRefPtr[CefCookieManager] RequestHandler_GetCookieManager( - CefRefPtr[CefBrowser] cefBrowser, - const CefString& cefMainUrl - ) except * with gil: - # In CEF the GetCookieManager callback belongs to - # CefRequestContextHandler. - # In an exceptional case the browser parameter may be None - # due to limitation in CEF API. No workaround as of now. - cdef PyBrowser pyBrowser - cdef str pyMainUrl - cdef object clientCallback - cdef PyCookieManager returnValue - try: - # Issue #429: in some cases due to a race condition the browser - # may be NULL. - if not cefBrowser.get(): - return NULL - - # Issue #455: CefRequestHandler callbacks still executed after - # browser was closed. - if IsBrowserClosed(cefBrowser): - return NULL - - pyBrowser = GetPyBrowser(cefBrowser, "GetCookieManager") - pyMainUrl = CefToPyString(cefMainUrl) - clientCallback = pyBrowser.GetClientCallback("GetCookieManager") - if clientCallback: - returnValue = clientCallback( - browser=pyBrowser, - main_url=pyMainUrl) - if returnValue: - if isinstance(returnValue, PyCookieManager): - return returnValue.cefCookieManager - else: - raise Exception("Expected a CookieManager object") - return NULL - else: - return NULL - except: - (exc_type, exc_value, exc_trace) = sys.exc_info() - sys.excepthook(exc_type, exc_value, exc_trace) +#LC TEST +# cdef public CefRefPtr[CefCookieManager] RequestHandler_GetCookieManager( +# CefRefPtr[CefBrowser] cefBrowser, +# const CefString& cefMainUrl +# ) except * with gil: +# # In CEF the GetCookieManager callback belongs to +# # CefRequestContextHandler. +# # In an exceptional case the browser parameter may be None +# # due to limitation in CEF API. No workaround as of now. +# cdef PyBrowser pyBrowser +# cdef str pyMainUrl +# cdef object clientCallback +# cdef PyCookieManager returnValue +# try: +# # Issue #429: in some cases due to a race condition the browser +# # may be NULL. +# if not cefBrowser.get(): +# return NULL + +# # Issue #455: CefRequestHandler callbacks still executed after +# # browser was closed. +# if IsBrowserClosed(cefBrowser): +# return NULL + +# pyBrowser = GetPyBrowser(cefBrowser, "GetCookieManager") +# pyMainUrl = CefToPyString(cefMainUrl) +# clientCallback = pyBrowser.GetClientCallback("GetCookieManager") +# if clientCallback: +# returnValue = clientCallback( +# browser=pyBrowser, +# main_url=pyMainUrl) +# if returnValue: +# if isinstance(returnValue, PyCookieManager): +# return returnValue.cefCookieManager +# else: +# raise Exception("Expected a CookieManager object") +# return NULL +# else: +# return NULL +# except: +# (exc_type, exc_value, exc_trace) = sys.exc_info() +# sys.excepthook(exc_type, exc_value, exc_trace) cdef public void RequestHandler_OnProtocolExecution( @@ -393,12 +395,9 @@ cdef public cpp_bool RequestHandler_OnBeforePluginLoad( const CefString& mime_type, const CefString& plugin_url, cpp_bool is_main_frame, - const CefString& top_origin_url, - CefRefPtr[CefWebPluginInfo] plugin_info, - cef_types.cef_plugin_policy_t* plugin_policy + const CefString& top_origin_url ) except * with gil: cdef PyBrowser pyBrowser - cdef PyWebPluginInfo pyInfo cdef py_bool returnValue cdef object clientCallback try: @@ -418,7 +417,6 @@ cdef public cpp_bool RequestHandler_OnBeforePluginLoad( return False py_browser = GetPyBrowser(browser, "OnBeforePluginLoad") - py_plugin_info = CreatePyWebPluginInfo(plugin_info) clientCallback = GetGlobalClientCallback("OnBeforePluginLoad") if clientCallback: returnValue = clientCallback( @@ -426,10 +424,7 @@ cdef public cpp_bool RequestHandler_OnBeforePluginLoad( mime_type=CefToPyString(mime_type), plugin_url=CefToPyString(plugin_url), is_main_frame=bool(is_main_frame), - top_origin_url=CefToPyString(top_origin_url), - plugin_info=py_plugin_info) - if returnValue: - plugin_policy[0] = cef_types.PLUGIN_POLICY_DISABLE + top_origin_url=CefToPyString(top_origin_url)) return bool(returnValue) else: return False @@ -441,7 +436,7 @@ cdef public cpp_bool RequestHandler_OnBeforePluginLoad( cdef public cpp_bool RequestHandler_OnCertificateError( int certError, const CefString& cefRequestUrl, - CefRefPtr[CefRequestCallback] cefCertCallback + CefRefPtr[CefCallback] cefCertCallback ) except * with gil: cdef py_bool returnValue cdef object clientCallback diff --git a/src/handlers/resource_handler.pyx b/src/handlers/resource_handler.pyx index 1c379f192..5b9f14d3f 100644 --- a/src/handlers/resource_handler.pyx +++ b/src/handlers/resource_handler.pyx @@ -3,7 +3,7 @@ # Project website: https://github.com/cztomczak/cefpython include "../cefpython.pyx" - +from libc.stdint cimport int64_t import weakref # ----------------------------------------------------------------------------- @@ -102,7 +102,7 @@ cdef public cpp_bool ResourceHandler_ProcessRequest( cdef public void ResourceHandler_GetResponseHeaders( int resourceHandlerId, CefRefPtr[CefResponse] cefResponse, - int64& cefResponseLength, + int64_t& cefResponseLength, CefString& cefRedirectUrl ) except * with gil: cdef PyResourceHandler pyResourceHandler @@ -122,7 +122,7 @@ cdef public void ResourceHandler_GetResponseHeaders( if userCallback: returnValue = userCallback(pyResponse, responseLengthOut, redirectUrlOut) - (&cefResponseLength)[0] = responseLengthOut[0] + (&cefResponseLength)[0] = responseLengthOut[0] if redirectUrlOut[0]: PyToCefString(redirectUrlOut[0], cefRedirectUrl) return diff --git a/src/handlers/v8context_handler.pyx b/src/handlers/v8context_handler.pyx index fccdad562..2766d9a5f 100644 --- a/src/handlers/v8context_handler.pyx +++ b/src/handlers/v8context_handler.pyx @@ -11,6 +11,7 @@ include "../cefpython.pyx" include "../browser.pyx" include "../frame.pyx" +from libc.stdint cimport int64_t cdef public void V8ContextHandler_OnContextCreated( CefRefPtr[CefBrowser] cefBrowser, @@ -20,7 +21,6 @@ cdef public void V8ContextHandler_OnContextCreated( cdef PyFrame pyFrame cdef object clientCallback try: - Debug("V8ContextHandler_OnContextCreated()") pyBrowser = GetPyBrowser(cefBrowser, "OnContextCreated") pyBrowser.SetUserData("__v8ContextCreated", True) pyFrame = GetPyFrame(cefFrame) @@ -34,7 +34,7 @@ cdef public void V8ContextHandler_OnContextCreated( cdef public void V8ContextHandler_OnContextReleased( int browserId, - int64 frameId + CefString frameId ) except * with gil: cdef PyBrowser pyBrowser cdef PyFrame pyFrame @@ -53,16 +53,16 @@ cdef public void V8ContextHandler_OnContextReleased( if not pyBrowser: Debug("OnContextReleased: Browser doesn't exist anymore, id={id}" .format(id=str(browserId))) - RemovePyFrame(browserId, frameId) + RemovePyFrame(browserId, CefToPyString(frameId)) return - pyFrame = GetPyFrameById(browserId, frameId) + pyFrame = GetPyFrameById(browserId, CefToPyString(frameId)) # Frame may already be destroyed while IPC messaging was executing # (Issue #431). if pyFrame: clientCallback = pyBrowser.GetClientCallback("OnContextReleased") if clientCallback: clientCallback(browser=pyBrowser, frame=pyFrame) - RemovePyFrame(browserId, frameId) + RemovePyFrame(browserId, CefToPyString(frameId)) except: (exc_type, exc_value, exc_trace) = sys.exc_info() sys.excepthook(exc_type, exc_value, exc_trace) diff --git a/src/handlers/v8function_handler.pyx b/src/handlers/v8function_handler.pyx index ee73619f8..8121674af 100644 --- a/src/handlers/v8function_handler.pyx +++ b/src/handlers/v8function_handler.pyx @@ -8,7 +8,7 @@ include "../frame.pyx" cdef public void V8FunctionHandler_Execute( CefRefPtr[CefBrowser] cefBrowser, - int64 frameId, + CefString& frameId, CefString& cefFuncName, CefRefPtr[CefListValue] cefFuncArgs ) except * with gil: @@ -22,7 +22,7 @@ cdef public void V8FunctionHandler_Execute( cdef py_string errorMessage try: pyBrowser = GetPyBrowser(cefBrowser, "V8FunctionHandler_Execute") - cefFrame = cefBrowser.get().GetFrame(frameId) + cefFrame = cefBrowser.get().GetFrameByName(frameId) if cefFrame.get(): pyFrame = GetPyFrame(cefFrame) else: diff --git a/src/include/base/cef_atomic_flag.h b/src/include/base/cef_atomic_flag.h new file mode 100644 index 000000000..3a2fdbc1d --- /dev/null +++ b/src/include/base/cef_atomic_flag.h @@ -0,0 +1,97 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011 +// Google Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the name Chromium Embedded +// Framework nor the names of its contributors may be used to endorse +// or promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CEF_INCLUDE_BASE_CEF_ATOMIC_FLAG_H_ +#define CEF_INCLUDE_BASE_CEF_ATOMIC_FLAG_H_ +#pragma once + +#if defined(USING_CHROMIUM_INCLUDES) +// When building CEF include the Chromium header directly. +#include "base/synchronization/atomic_flag.h" + +#else // !USING_CHROMIUM_INCLUDES +// The following is substantially similar to the Chromium implementation. +// If the Chromium implementation diverges the below implementation should be +// updated to match. + +#include + +#include + +#include "include/base/cef_thread_checker.h" + +namespace base { + +/// +/// A flag that can safely be set from one thread and read from other threads. +/// +/// This class IS NOT intended for synchronization between threads. +/// +class AtomicFlag { + public: + AtomicFlag(); + + AtomicFlag(const AtomicFlag&) = delete; + AtomicFlag& operator=(const AtomicFlag&) = delete; + + ~AtomicFlag(); + + /// + /// Set the flag. Must always be called from the same thread. + /// + void Set(); + + /// + /// Returns true iff the flag was set. If this returns true, the current + /// thread is guaranteed to be synchronized with all memory operations on the + /// thread which invoked Set() up until at least the first call to Set() on + /// it. + /// + bool IsSet() const { + // Inline here: this has a measurable performance impact on base::WeakPtr. + return flag_.load(std::memory_order_acquire) != 0; + } + + /// + /// Resets the flag. Be careful when using this: callers might not expect + /// IsSet() to return false after returning true once. + /// + void UnsafeResetForTesting(); + + private: + std::atomic flag_{0}; + base::ThreadChecker set_thread_checker_; +}; + +} // namespace base + +#endif // !USING_CHROMIUM_INCLUDES + +#endif // CEF_INCLUDE_BASE_CEF_ATOMIC_FLAG_H_ diff --git a/src/include/base/cef_atomic_ref_count.h b/src/include/base/cef_atomic_ref_count.h index 4d6777970..38e8f93b7 100644 --- a/src/include/base/cef_atomic_ref_count.h +++ b/src/include/base/cef_atomic_ref_count.h @@ -43,120 +43,78 @@ // When building CEF include the Chromium header directly. #include "base/atomic_ref_count.h" -// Used when declaring a base::AtomicRefCount value. This is an object type with -// Chromium headers. -#define ATOMIC_DECLARATION (0) - -// Maintaining compatibility with AtompicRefCount* functions that were removed -// from Chromium in http://crrev.com/ee96d561. -namespace base { - -// Increment a reference count by 1. -inline void AtomicRefCountInc(volatile AtomicRefCount* ptr) { - const_cast(ptr)->Increment(); -} - -// Decrement a reference count by 1 and return whether the result is non-zero. -// Insert barriers to ensure that state written before the reference count -// became zero will be visible to a thread that has just made the count zero. -inline bool AtomicRefCountDec(volatile AtomicRefCount* ptr) { - return const_cast(ptr)->Decrement(); -} - -// Return whether the reference count is one. If the reference count is used -// in the conventional way, a refrerence count of 1 implies that the current -// thread owns the reference and no other thread shares it. This call performs -// the test for a reference count of one, and performs the memory barrier -// needed for the owning thread to act on the object, knowing that it has -// exclusive access to the object. -inline bool AtomicRefCountIsOne(volatile AtomicRefCount* ptr) { - return const_cast(ptr)->IsOne(); -} - -// Return whether the reference count is zero. With conventional object -// referencing counting, the object will be destroyed, so the reference count -// should never be zero. Hence this is generally used for a debug check. -inline bool AtomicRefCountIsZero(volatile AtomicRefCount* ptr) { - return const_cast(ptr)->IsZero(); -} - -} // namespace base - #else // !USING_CHROMIUM_INCLUDES // The following is substantially similar to the Chromium implementation. // If the Chromium implementation diverges the below implementation should be // updated to match. -#include "include/base/cef_atomicops.h" - -// Annotations are not currently supported. -#define ANNOTATE_HAPPENS_BEFORE(obj) /* empty */ -#define ANNOTATE_HAPPENS_AFTER(obj) /* empty */ - -// Used when declaring a base::AtomicRefCount value. This is an integer/ptr type -// with CEF headers. -#define ATOMIC_DECLARATION = 0 +#include namespace base { -typedef subtle::Atomic32 AtomicRefCount; - -// Increment a reference count by "increment", which must exceed 0. -inline void AtomicRefCountIncN(volatile AtomicRefCount* ptr, - AtomicRefCount increment) { - subtle::NoBarrier_AtomicIncrement(ptr, increment); -} - -// Decrement a reference count by "decrement", which must exceed 0, -// and return whether the result is non-zero. -// Insert barriers to ensure that state written before the reference count -// became zero will be visible to a thread that has just made the count zero. -inline bool AtomicRefCountDecN(volatile AtomicRefCount* ptr, - AtomicRefCount decrement) { - ANNOTATE_HAPPENS_BEFORE(ptr); - bool res = (subtle::Barrier_AtomicIncrement(ptr, -decrement) != 0); - if (!res) { - ANNOTATE_HAPPENS_AFTER(ptr); +class AtomicRefCount { + public: + constexpr AtomicRefCount() : ref_count_(0) {} + explicit constexpr AtomicRefCount(int initial_value) + : ref_count_(initial_value) {} + + /// + /// Increment a reference count. + /// Returns the previous value of the count. + /// + int Increment() { return Increment(1); } + + /// + /// Increment a reference count by "increment", which must exceed 0. + /// Returns the previous value of the count. + /// + int Increment(int increment) { + return ref_count_.fetch_add(increment, std::memory_order_relaxed); + } + + /// + /// Decrement a reference count, and return whether the result is non-zero. + /// Insert barriers to ensure that state written before the reference count + /// became zero will be visible to a thread that has just made the count zero. + /// + bool Decrement() { + // TODO(jbroman): Technically this doesn't need to be an acquire operation + // unless the result is 1 (i.e., the ref count did indeed reach zero). + // However, there are toolchain issues that make that not work as well at + // present (notably TSAN doesn't like it). + return ref_count_.fetch_sub(1, std::memory_order_acq_rel) != 1; } - return res; -} - -// Increment a reference count by 1. -inline void AtomicRefCountInc(volatile AtomicRefCount* ptr) { - base::AtomicRefCountIncN(ptr, 1); -} - -// Decrement a reference count by 1 and return whether the result is non-zero. -// Insert barriers to ensure that state written before the reference count -// became zero will be visible to a thread that has just made the count zero. -inline bool AtomicRefCountDec(volatile AtomicRefCount* ptr) { - return base::AtomicRefCountDecN(ptr, 1); -} - -// Return whether the reference count is one. If the reference count is used -// in the conventional way, a refrerence count of 1 implies that the current -// thread owns the reference and no other thread shares it. This call performs -// the test for a reference count of one, and performs the memory barrier -// needed for the owning thread to act on the object, knowing that it has -// exclusive access to the object. -inline bool AtomicRefCountIsOne(volatile AtomicRefCount* ptr) { - bool res = (subtle::Acquire_Load(ptr) == 1); - if (res) { - ANNOTATE_HAPPENS_AFTER(ptr); + + /// + /// Return whether the reference count is one. If the reference count is used + /// in the conventional way, a refrerence count of 1 implies that the current + /// thread owns the reference and no other thread shares it. This call + /// performs the test for a reference count of one, and performs the memory + /// barrier needed for the owning thread to act on the object, knowing that it + /// has exclusive access to the object. + /// + bool IsOne() const { return ref_count_.load(std::memory_order_acquire) == 1; } + + /// + /// Return whether the reference count is zero. With conventional object + /// referencing counting, the object will be destroyed, so the reference count + /// should never be zero. Hence this is generally used for a debug check. + /// + bool IsZero() const { + return ref_count_.load(std::memory_order_acquire) == 0; } - return res; -} - -// Return whether the reference count is zero. With conventional object -// referencing counting, the object will be destroyed, so the reference count -// should never be zero. Hence this is generally used for a debug check. -inline bool AtomicRefCountIsZero(volatile AtomicRefCount* ptr) { - bool res = (subtle::Acquire_Load(ptr) == 0); - if (res) { - ANNOTATE_HAPPENS_AFTER(ptr); + + /// + /// Returns the current reference count (with no barriers). This is subtle, + /// and should be used only for debugging. + /// + int SubtleRefCountForDebug() const { + return ref_count_.load(std::memory_order_relaxed); } - return res; -} + + private: + std::atomic_int ref_count_; +}; } // namespace base diff --git a/src/include/base/cef_atomicops.h b/src/include/base/cef_atomicops.h deleted file mode 100644 index 96aebabf8..000000000 --- a/src/include/base/cef_atomicops.h +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012 -// Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// For atomic operations on reference counts, see cef_atomic_ref_count.h. - -// The routines exported by this module are subtle. If you use them, even if -// you get the code right, it will depend on careful reasoning about atomicity -// and memory ordering; it will be less readable, and harder to maintain. If -// you plan to use these routines, you should have a good reason, such as solid -// evidence that performance would otherwise suffer, or there being no -// alternative. You should assume only properties explicitly guaranteed by the -// specifications in this file. You are almost certainly _not_ writing code -// just for the x86; if you assume x86 semantics, x86 hardware bugs and -// implementations on other archtectures will cause your code to break. If you -// do not know what you are doing, avoid these routines, and use a Mutex. -// -// It is incorrect to make direct assignments to/from an atomic variable. -// You should use one of the Load or Store routines. The NoBarrier -// versions are provided when no barriers are needed: -// NoBarrier_Store() -// NoBarrier_Load() -// Although there are currently no compiler enforcement, you are encouraged -// to use these. -// - -#ifndef CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_ -#define CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_ -#pragma once - -#if defined(BASE_ATOMICOPS_H_) -// Do nothing if the Chromium header has already been included. -// This can happen in cases where Chromium code is used directly by the -// client application. When using Chromium code directly always include -// the Chromium header first to avoid type conflicts. -#elif defined(USING_CHROMIUM_INCLUDES) -// When building CEF include the Chromium header directly. -#include "base/atomicops.h" -#else // !USING_CHROMIUM_INCLUDES -// The following is substantially similar to the Chromium implementation. -// If the Chromium implementation diverges the below implementation should be -// updated to match. - -#include - -#include "include/base/cef_build.h" - -#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS) -// windows.h #defines this (only on x64). This causes problems because the -// public API also uses MemoryBarrier at the public name for this fence. So, on -// X64, undef it, and call its documented -// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx) -// implementation directly. -#undef MemoryBarrier -#endif - -namespace base { -namespace subtle { - -typedef int32_t Atomic32; -#ifdef ARCH_CPU_64_BITS -// We need to be able to go between Atomic64 and AtomicWord implicitly. This -// means Atomic64 and AtomicWord should be the same type on 64-bit. -#if defined(__ILP32__) || defined(OS_NACL) -// NaCl's intptr_t is not actually 64-bits on 64-bit! -// http://code.google.com/p/nativeclient/issues/detail?id=1162 -typedef int64_t Atomic64; -#else -typedef intptr_t Atomic64; -#endif -#endif - -// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or -// Atomic64 routines below, depending on your architecture. -typedef intptr_t AtomicWord; - -// Atomically execute: -// result = *ptr; -// if (*ptr == old_value) -// *ptr = new_value; -// return result; -// -// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". -// Always return the old value of "*ptr" -// -// This routine implies no memory barriers. -Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value); - -// Atomically store new_value into *ptr, returning the previous value held in -// *ptr. This routine implies no memory barriers. -Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value); - -// Atomically increment *ptr by "increment". Returns the new value of -// *ptr with the increment applied. This routine implies no memory barriers. -Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment); - -Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment); - -// These following lower-level operations are typically useful only to people -// implementing higher-level synchronization operations like spinlocks, -// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or -// a store with appropriate memory-ordering instructions. "Acquire" operations -// ensure that no later memory access can be reordered ahead of the operation. -// "Release" operations ensure that no previous memory access can be reordered -// after the operation. "Barrier" operations have both "Acquire" and "Release" -// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory -// access. -Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value); -Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value); - -void MemoryBarrier(); -void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value); -void Acquire_Store(volatile Atomic32* ptr, Atomic32 value); -void Release_Store(volatile Atomic32* ptr, Atomic32 value); - -Atomic32 NoBarrier_Load(volatile const Atomic32* ptr); -Atomic32 Acquire_Load(volatile const Atomic32* ptr); -Atomic32 Release_Load(volatile const Atomic32* ptr); - -// 64-bit atomic operations (only available on 64-bit processors). -#ifdef ARCH_CPU_64_BITS -Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value); -Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value); -Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); -Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); - -Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value); -Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value); -void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value); -void Acquire_Store(volatile Atomic64* ptr, Atomic64 value); -void Release_Store(volatile Atomic64* ptr, Atomic64 value); -Atomic64 NoBarrier_Load(volatile const Atomic64* ptr); -Atomic64 Acquire_Load(volatile const Atomic64* ptr); -Atomic64 Release_Load(volatile const Atomic64* ptr); -#endif // ARCH_CPU_64_BITS - -} // namespace subtle -} // namespace base - -// Include our platform specific implementation. -#if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY) -#include "include/base/internal/cef_atomicops_x86_msvc.h" -#elif defined(OS_MACOSX) -#include "include/base/internal/cef_atomicops_mac.h" -#elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY) -#include "include/base/internal/cef_atomicops_x86_gcc.h" -#elif defined(COMPILER_GCC) && defined(__ARM_ARCH) -#include "include/base/internal/cef_atomicops_arm_gcc.h" -#else -#error "Atomic operations are not supported on your platform" -#endif - -// On some platforms we need additional declarations to make -// AtomicWord compatible with our other Atomic* types. -#if defined(OS_MACOSX) || defined(OS_OPENBSD) -#include "include/base/internal/cef_atomicops_atomicword_compat.h" -#endif - -#endif // !USING_CHROMIUM_INCLUDES - -#endif // CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_ diff --git a/src/include/base/cef_auto_reset.h b/src/include/base/cef_auto_reset.h new file mode 100644 index 000000000..be3a05da5 --- /dev/null +++ b/src/include/base/cef_auto_reset.h @@ -0,0 +1,90 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011 +// Google Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the name Chromium Embedded +// Framework nor the names of its contributors may be used to endorse +// or promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// base::AutoReset<> is useful for setting a variable to a new value only within +// a particular scope. An base::AutoReset<> object resets a variable to its +// original value upon destruction, making it an alternative to writing +// "var = false;" or "var = old_val;" at all of a block's exit points. +// +// This should be obvious, but note that an base::AutoReset<> instance should +// have a shorter lifetime than its scoped_variable, to prevent invalid memory +// writes when the base::AutoReset<> object is destroyed. + +#ifndef CEF_INCLUDE_BASE_CEF_AUTO_RESET_H_ +#define CEF_INCLUDE_BASE_CEF_AUTO_RESET_H_ +#pragma once + +#if defined(USING_CHROMIUM_INCLUDES) +// When building CEF include the Chromium header directly. +#include "base/auto_reset.h" +#else // !USING_CHROMIUM_INCLUDES +// The following is substantially similar to the Chromium implementation. +// If the Chromium implementation diverges the below implementation should be +// updated to match. + +#include + +namespace base { + +template +class AutoReset { + public: + template + AutoReset(T* scoped_variable, U&& new_value) + : scoped_variable_(scoped_variable), + original_value_( + std::exchange(*scoped_variable_, std::forward(new_value))) {} + + AutoReset(AutoReset&& other) + : scoped_variable_(std::exchange(other.scoped_variable_, nullptr)), + original_value_(std::move(other.original_value_)) {} + + AutoReset& operator=(AutoReset&& rhs) { + scoped_variable_ = std::exchange(rhs.scoped_variable_, nullptr); + original_value_ = std::move(rhs.original_value_); + return *this; + } + + ~AutoReset() { + if (scoped_variable_) { + *scoped_variable_ = std::move(original_value_); + } + } + + private: + T* scoped_variable_; + T original_value_; +}; + +} // namespace base + +#endif // !USING_CHROMIUM_INCLUDES + +#endif // CEF_INCLUDE_BASE_CEF_AUTO_RESET_H_ diff --git a/src/include/base/cef_bind.h b/src/include/base/cef_bind.h index 77c9c5573..e879b5694 100644 --- a/src/include/base/cef_bind.h +++ b/src/include/base/cef_bind.h @@ -28,546 +28,361 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/// +/// \file +/// base::BindOnce() and base::BindRepeating() are helpers for creating +/// base::OnceCallback and base::RepeatingCallback objects respectively. +/// +/// For a runnable object of n-arity, the base::Bind*() family allows partial +/// application of the first m arguments. The remaining n - m arguments must be +/// passed when invoking the callback with Run(). +/// +///
+///   // The first argument is bound at callback creation; the remaining
+///   // two must be passed when calling Run() on the callback object.
+///   base::OnceCallback cb = base::BindOnce(
+///       [](short x, int y, long z) { return x * y * z; }, 42);
+/// 
+/// +/// When binding to a method, the receiver object must also be specified at +/// callback creation time. When Run() is invoked, the method will be invoked on +/// the specified receiver object. +/// +///
+///   class C : public base::RefCounted { void F(); };
+///   auto instance = base::MakeRefCounted();
+///   auto cb = base::BindOnce(&C::F, instance);
+///   std::move(cb).Run();  // Identical to instance->F()
+/// 
+/// +/// See https://chromium.googlesource.com/chromium/src/+/lkgr/docs/callback.md +/// for the full documentation. +/// + +// Implementation notes +// +// If you're reading the implementation, before proceeding further, you should +// read the top comment of base/internal/cef_bind_internal.h for a definition +// of common terms and concepts. + #ifndef CEF_INCLUDE_BASE_CEF_BIND_H_ #define CEF_INCLUDE_BASE_CEF_BIND_H_ #pragma once -#if defined(BASE_BIND_H_) -// Do nothing if the Chromium header has already been included. -// This can happen in cases where Chromium code is used directly by the -// client application. When using Chromium code directly always include -// the Chromium header first to avoid type conflicts. -#elif defined(USING_CHROMIUM_INCLUDES) +#if defined(USING_CHROMIUM_INCLUDES) // When building CEF include the Chromium header directly. -#include "base/bind.h" +#include "base/functional/bind.h" #else // !USING_CHROMIUM_INCLUDES // The following is substantially similar to the Chromium implementation. // If the Chromium implementation diverges the below implementation should be // updated to match. +#include +#include +#include +#include + +#include "include/base/cef_build.h" +#include "include/base/cef_compiler_specific.h" #include "include/base/internal/cef_bind_internal.h" -#include "include/base/internal/cef_callback_internal.h" -// ----------------------------------------------------------------------------- -// Usage documentation -// ----------------------------------------------------------------------------- -// -// See base/cef_callback.h for documentation. -// -// -// ----------------------------------------------------------------------------- -// Implementation notes -// ----------------------------------------------------------------------------- -// -// If you're reading the implementation, before proceeding further, you should -// read the top comment of base/bind_internal.h for a definition of common -// terms and concepts. -// -// RETURN TYPES -// -// Though Bind()'s result is meant to be stored in a Callback<> type, it -// cannot actually return the exact type without requiring a large amount -// of extra template specializations. The problem is that in order to -// discern the correct specialization of Callback<>, Bind would need to -// unwrap the function signature to determine the signature's arity, and -// whether or not it is a method. -// -// Each unique combination of (arity, function_type, num_prebound) where -// function_type is one of {function, method, const_method} would require -// one specialization. We eventually have to do a similar number of -// specializations anyways in the implementation (see the Invoker<>, -// classes). However, it is avoidable in Bind if we return the result -// via an indirection like we do below. -// -// TODO(ajwong): We might be able to avoid this now, but need to test. -// -// It is possible to move most of the COMPILE_ASSERT asserts into BindState<>, -// but it feels a little nicer to have the asserts here so people do not -// need to crack open bind_internal.h. On the other hand, it makes Bind() -// harder to read. +#if defined(OS_APPLE) && !HAS_FEATURE(objc_arc) +#include "include/base/internal/cef_scoped_block_mac.h" +#endif namespace base { -template -base::Callback::RunnableType, - typename cef_internal::FunctorTraits::RunType, - void()>::UnboundRunType> -Bind(Functor functor) { - // Typedefs for how to store and run the functor. - typedef - typename cef_internal::FunctorTraits::RunnableType RunnableType; - typedef typename cef_internal::FunctorTraits::RunType RunType; - - typedef cef_internal::BindState BindState; - - return Callback( - new BindState(cef_internal::MakeRunnable(functor))); +/// +/// Bind as OnceCallback. +/// +template +inline OnceCallback> +BindOnce(Functor&& functor, Args&&... args) { + static_assert(!cef_internal::IsOnceCallback>() || + (std::is_rvalue_reference() && + !std::is_const>()), + "BindOnce requires non-const rvalue for OnceCallback binding." + " I.e.: base::BindOnce(std::move(callback))."); + static_assert( + std::conjunction>...>::value, + "Use std::move() instead of base::Passed() with base::BindOnce()"); + + return cef_internal::BindImpl(std::forward(functor), + std::forward(args)...); } -template -base::Callback::RunnableType, - typename cef_internal::FunctorTraits::RunType, - void(typename cef_internal::CallbackParamTraits::StorageType)>:: - UnboundRunType> -Bind(Functor functor, const P1& p1) { - // Typedefs for how to store and run the functor. - typedef - typename cef_internal::FunctorTraits::RunnableType RunnableType; - typedef typename cef_internal::FunctorTraits::RunType RunType; - - // Use RunnableType::RunType instead of RunType above because our - // checks should below for bound references need to know what the actual - // functor is going to interpret the argument as. - typedef cef_internal::FunctionTraits - BoundFunctorTraits; - - // Do not allow binding a non-const reference parameter. Non-const reference - // parameters are disallowed by the Google style guide. Also, binding a - // non-const reference parameter can make for subtle bugs because the - // invoked function will receive a reference to the stored copy of the - // argument and not the original. - COMPILE_ASSERT( - !(is_non_const_reference::value), - do_not_bind_functions_with_nonconst_ref); - - // For methods, we need to be careful for parameter 1. We do not require - // a scoped_refptr because BindState<> itself takes care of AddRef() for - // methods. We also disallow binding of an array as the method's target - // object. - COMPILE_ASSERT(cef_internal::HasIsMethodTag::value || - !cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::HasIsMethodTag::value || - !is_array::value, - first_bound_argument_to_method_cannot_be_array); - typedef cef_internal::BindState< - RunnableType, RunType, - void(typename cef_internal::CallbackParamTraits::StorageType)> - BindState; - - return Callback( - new BindState(cef_internal::MakeRunnable(functor), p1)); +/// +/// Bind as RepeatingCallback. +/// +template +inline RepeatingCallback> +BindRepeating(Functor&& functor, Args&&... args) { + static_assert( + !cef_internal::IsOnceCallback>(), + "BindRepeating cannot bind OnceCallback. Use BindOnce with std::move()."); + + return cef_internal::BindImpl( + std::forward(functor), std::forward(args)...); } -template -base::Callback::RunnableType, - typename cef_internal::FunctorTraits::RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)>:: - UnboundRunType> -Bind(Functor functor, const P1& p1, const P2& p2) { - // Typedefs for how to store and run the functor. - typedef - typename cef_internal::FunctorTraits::RunnableType RunnableType; - typedef typename cef_internal::FunctorTraits::RunType RunType; - - // Use RunnableType::RunType instead of RunType above because our - // checks should below for bound references need to know what the actual - // functor is going to interpret the argument as. - typedef cef_internal::FunctionTraits - BoundFunctorTraits; - - // Do not allow binding a non-const reference parameter. Non-const reference - // parameters are disallowed by the Google style guide. Also, binding a - // non-const reference parameter can make for subtle bugs because the - // invoked function will receive a reference to the stored copy of the - // argument and not the original. - COMPILE_ASSERT( - !(is_non_const_reference::value || - is_non_const_reference::value), - do_not_bind_functions_with_nonconst_ref); - - // For methods, we need to be careful for parameter 1. We do not require - // a scoped_refptr because BindState<> itself takes care of AddRef() for - // methods. We also disallow binding of an array as the method's target - // object. - COMPILE_ASSERT(cef_internal::HasIsMethodTag::value || - !cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::HasIsMethodTag::value || - !is_array::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p2_is_refcounted_type_and_needs_scoped_refptr); - typedef cef_internal::BindState< - RunnableType, RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)> - BindState; - - return Callback( - new BindState(cef_internal::MakeRunnable(functor), p1, p2)); +/// +/// Special cases for binding to a base::Callback without extra bound arguments. +/// We CHECK() the validity of callback to guard against null pointers +/// accidentally ending up in posted tasks, causing hard-to-debug crashes. +/// +template +OnceCallback BindOnce(OnceCallback callback) { + CHECK(callback); + return callback; } -template -base::Callback::RunnableType, - typename cef_internal::FunctorTraits::RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)>:: - UnboundRunType> -Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3) { - // Typedefs for how to store and run the functor. - typedef - typename cef_internal::FunctorTraits::RunnableType RunnableType; - typedef typename cef_internal::FunctorTraits::RunType RunType; - - // Use RunnableType::RunType instead of RunType above because our - // checks should below for bound references need to know what the actual - // functor is going to interpret the argument as. - typedef cef_internal::FunctionTraits - BoundFunctorTraits; - - // Do not allow binding a non-const reference parameter. Non-const reference - // parameters are disallowed by the Google style guide. Also, binding a - // non-const reference parameter can make for subtle bugs because the - // invoked function will receive a reference to the stored copy of the - // argument and not the original. - COMPILE_ASSERT( - !(is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value), - do_not_bind_functions_with_nonconst_ref); - - // For methods, we need to be careful for parameter 1. We do not require - // a scoped_refptr because BindState<> itself takes care of AddRef() for - // methods. We also disallow binding of an array as the method's target - // object. - COMPILE_ASSERT(cef_internal::HasIsMethodTag::value || - !cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::HasIsMethodTag::value || - !is_array::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p2_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p3_is_refcounted_type_and_needs_scoped_refptr); - typedef cef_internal::BindState< - RunnableType, RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)> - BindState; - - return Callback( - new BindState(cef_internal::MakeRunnable(functor), p1, p2, p3)); +template +OnceCallback BindOnce(RepeatingCallback callback) { + CHECK(callback); + return callback; } -template -base::Callback::RunnableType, - typename cef_internal::FunctorTraits::RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)>:: - UnboundRunType> -Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4) { - // Typedefs for how to store and run the functor. - typedef - typename cef_internal::FunctorTraits::RunnableType RunnableType; - typedef typename cef_internal::FunctorTraits::RunType RunType; - - // Use RunnableType::RunType instead of RunType above because our - // checks should below for bound references need to know what the actual - // functor is going to interpret the argument as. - typedef cef_internal::FunctionTraits - BoundFunctorTraits; - - // Do not allow binding a non-const reference parameter. Non-const reference - // parameters are disallowed by the Google style guide. Also, binding a - // non-const reference parameter can make for subtle bugs because the - // invoked function will receive a reference to the stored copy of the - // argument and not the original. - COMPILE_ASSERT( - !(is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value), - do_not_bind_functions_with_nonconst_ref); - - // For methods, we need to be careful for parameter 1. We do not require - // a scoped_refptr because BindState<> itself takes care of AddRef() for - // methods. We also disallow binding of an array as the method's target - // object. - COMPILE_ASSERT(cef_internal::HasIsMethodTag::value || - !cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::HasIsMethodTag::value || - !is_array::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p2_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p3_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p4_is_refcounted_type_and_needs_scoped_refptr); - typedef cef_internal::BindState< - RunnableType, RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)> - BindState; - - return Callback( - new BindState(cef_internal::MakeRunnable(functor), p1, p2, p3, p4)); +template +RepeatingCallback BindRepeating( + RepeatingCallback callback) { + CHECK(callback); + return callback; } -template -base::Callback::RunnableType, - typename cef_internal::FunctorTraits::RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)>:: - UnboundRunType> -Bind(Functor functor, - const P1& p1, - const P2& p2, - const P3& p3, - const P4& p4, - const P5& p5) { - // Typedefs for how to store and run the functor. - typedef - typename cef_internal::FunctorTraits::RunnableType RunnableType; - typedef typename cef_internal::FunctorTraits::RunType RunType; - - // Use RunnableType::RunType instead of RunType above because our - // checks should below for bound references need to know what the actual - // functor is going to interpret the argument as. - typedef cef_internal::FunctionTraits - BoundFunctorTraits; - - // Do not allow binding a non-const reference parameter. Non-const reference - // parameters are disallowed by the Google style guide. Also, binding a - // non-const reference parameter can make for subtle bugs because the - // invoked function will receive a reference to the stored copy of the - // argument and not the original. - COMPILE_ASSERT( - !(is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value), - do_not_bind_functions_with_nonconst_ref); - - // For methods, we need to be careful for parameter 1. We do not require - // a scoped_refptr because BindState<> itself takes care of AddRef() for - // methods. We also disallow binding of an array as the method's target - // object. - COMPILE_ASSERT(cef_internal::HasIsMethodTag::value || - !cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::HasIsMethodTag::value || - !is_array::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p2_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p3_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p4_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p5_is_refcounted_type_and_needs_scoped_refptr); - typedef cef_internal::BindState< - RunnableType, RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)> - BindState; - - return Callback( - new BindState(cef_internal::MakeRunnable(functor), p1, p2, p3, p4, p5)); +/// +/// Unretained() allows binding a non-refcounted class, and to disable +/// refcounting on arguments that are refcounted objects. +/// +/// EXAMPLE OF Unretained(): +/// +///
+///   class Foo {
+///    public:
+///     void func() { cout << "Foo:f" << endl; }
+///   };
+///
+///   // In some function somewhere.
+///   Foo foo;
+///   OnceClosure foo_callback =
+///       BindOnce(&Foo::func, Unretained(&foo));
+///   std::move(foo_callback).Run();  // Prints "Foo:f".
+/// 
+/// +/// Without the Unretained() wrapper on |&foo|, the above call would fail +/// to compile because Foo does not support the AddRef() and Release() methods. +/// +template +inline cef_internal::UnretainedWrapper Unretained(T* o) { + return cef_internal::UnretainedWrapper(o); } -template -base::Callback::RunnableType, - typename cef_internal::FunctorTraits::RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)>:: - UnboundRunType> -Bind(Functor functor, - const P1& p1, - const P2& p2, - const P3& p3, - const P4& p4, - const P5& p5, - const P6& p6) { - // Typedefs for how to store and run the functor. - typedef - typename cef_internal::FunctorTraits::RunnableType RunnableType; - typedef typename cef_internal::FunctorTraits::RunType RunType; - - // Use RunnableType::RunType instead of RunType above because our - // checks should below for bound references need to know what the actual - // functor is going to interpret the argument as. - typedef cef_internal::FunctionTraits - BoundFunctorTraits; - - // Do not allow binding a non-const reference parameter. Non-const reference - // parameters are disallowed by the Google style guide. Also, binding a - // non-const reference parameter can make for subtle bugs because the - // invoked function will receive a reference to the stored copy of the - // argument and not the original. - COMPILE_ASSERT( - !(is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value), - do_not_bind_functions_with_nonconst_ref); - - // For methods, we need to be careful for parameter 1. We do not require - // a scoped_refptr because BindState<> itself takes care of AddRef() for - // methods. We also disallow binding of an array as the method's target - // object. - COMPILE_ASSERT(cef_internal::HasIsMethodTag::value || - !cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::HasIsMethodTag::value || - !is_array::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p2_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p3_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p4_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p5_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p6_is_refcounted_type_and_needs_scoped_refptr); - typedef cef_internal::BindState< - RunnableType, RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)> - BindState; +/// +/// RetainedRef() accepts a ref counted object and retains a reference to it. +/// When the callback is called, the object is passed as a raw pointer. +/// +/// EXAMPLE OF RetainedRef(): +/// +///
+///    void foo(RefCountedBytes* bytes) {}
+///
+///    scoped_refptr bytes = ...;
+///    OnceClosure callback = BindOnce(&foo, base::RetainedRef(bytes));
+///    std::move(callback).Run();
+/// 
+/// +/// Without RetainedRef, the scoped_refptr would try to implicitly convert to +/// a raw pointer and fail compilation: +/// +///
+///    OnceClosure callback = BindOnce(&foo, bytes); // ERROR!
+/// 
+/// +template +inline cef_internal::RetainedRefWrapper RetainedRef(T* o) { + return cef_internal::RetainedRefWrapper(o); +} +template +inline cef_internal::RetainedRefWrapper RetainedRef(scoped_refptr o) { + return cef_internal::RetainedRefWrapper(std::move(o)); +} - return Callback(new BindState( - cef_internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6)); +/// +/// Owned() transfers ownership of an object to the callback resulting from +/// bind; the object will be deleted when the callback is deleted. +/// +/// EXAMPLE OF Owned(): +/// +///
+///   void foo(int* arg) { cout << *arg << endl }
+///
+///   int* pn = new int(1);
+///   RepeatingClosure foo_callback = BindRepeating(&foo, Owned(pn));
+///
+///   foo_callback.Run();  // Prints "1"
+///   foo_callback.Run();  // Prints "1"
+///   *pn = 2;
+///   foo_callback.Run();  // Prints "2"
+///
+///   foo_callback.Reset();  // |pn| is deleted.  Also will happen when
+///                          // |foo_callback| goes out of scope.
+/// 
+/// +/// Without Owned(), someone would have to know to delete |pn| when the last +/// reference to the callback is deleted. +/// +template +inline cef_internal::OwnedWrapper Owned(T* o) { + return cef_internal::OwnedWrapper(o); } -template -base::Callback::RunnableType, - typename cef_internal::FunctorTraits::RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)>:: - UnboundRunType> -Bind(Functor functor, - const P1& p1, - const P2& p2, - const P3& p3, - const P4& p4, - const P5& p5, - const P6& p6, - const P7& p7) { - // Typedefs for how to store and run the functor. - typedef - typename cef_internal::FunctorTraits::RunnableType RunnableType; - typedef typename cef_internal::FunctorTraits::RunType RunType; +template +inline cef_internal::OwnedWrapper Owned( + std::unique_ptr&& ptr) { + return cef_internal::OwnedWrapper(std::move(ptr)); +} - // Use RunnableType::RunType instead of RunType above because our - // checks should below for bound references need to know what the actual - // functor is going to interpret the argument as. - typedef cef_internal::FunctionTraits - BoundFunctorTraits; +/// +/// OwnedRef() stores an object in the callback resulting from +/// bind and passes a reference to the object to the bound function. +/// +/// EXAMPLE OF OwnedRef(): +/// +///
+///   void foo(int& arg) { cout << ++arg << endl }
+///
+///   int counter = 0;
+///   RepeatingClosure foo_callback = BindRepeating(&foo, OwnedRef(counter));
+///
+///   foo_callback.Run();  // Prints "1"
+///   foo_callback.Run();  // Prints "2"
+///   foo_callback.Run();  // Prints "3"
+///
+///   cout << counter;     // Prints "0", OwnedRef creates a copy of counter.
+/// 
+/// +/// Supports OnceCallbacks as well, useful to pass placeholder arguments: +/// +///
+///   void bar(int& ignore, const std::string& s) { cout << s << endl }
+///
+///   OnceClosure bar_callback = BindOnce(&bar, OwnedRef(0), "Hello");
+///
+///   std::move(bar_callback).Run(); // Prints "Hello"
+/// 
+/// +/// Without OwnedRef() it would not be possible to pass a mutable reference to +/// an object owned by the callback. +/// +template +cef_internal::OwnedRefWrapper> OwnedRef(T&& t) { + return cef_internal::OwnedRefWrapper>(std::forward(t)); +} - // Do not allow binding a non-const reference parameter. Non-const reference - // parameters are disallowed by the Google style guide. Also, binding a - // non-const reference parameter can make for subtle bugs because the - // invoked function will receive a reference to the stored copy of the - // argument and not the original. - COMPILE_ASSERT( - !(is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value), - do_not_bind_functions_with_nonconst_ref); +/// +/// Passed() is for transferring movable-but-not-copyable types (eg. unique_ptr) +/// through a RepeatingCallback. Logically, this signifies a destructive +/// transfer of the state of the argument into the target function. Invoking +/// RepeatingCallback::Run() twice on a callback that was created with a +/// Passed() argument will CHECK() because the first invocation would have +/// already transferred ownership to the target function. +/// +/// Note that Passed() is not necessary with BindOnce(), as std::move() does the +/// same thing. Avoid Passed() in favor of std::move() with BindOnce(). +/// +/// EXAMPLE OF Passed(): +/// +///
+///   void TakesOwnership(std::unique_ptr arg) { }
+///   std::unique_ptr CreateFoo() { return std::make_unique();
+///   }
+///
+///   auto f = std::make_unique();
+///
+///   // |cb| is given ownership of Foo(). |f| is now NULL.
+///   // You can use std::move(f) in place of &f, but it's more verbose.
+///   RepeatingClosure cb = BindRepeating(&TakesOwnership, Passed(&f));
+///
+///   // Run was never called so |cb| still owns Foo() and deletes
+///   // it on Reset().
+///   cb.Reset();
+///
+///   // |cb| is given a new Foo created by CreateFoo().
+///   cb = BindRepeating(&TakesOwnership, Passed(CreateFoo()));
+///
+///   // |arg| in TakesOwnership() is given ownership of Foo(). |cb|
+///   // no longer owns Foo() and, if reset, would not delete Foo().
+///   cb.Run();  // Foo() is now transferred to |arg| and deleted.
+///   cb.Run();  // This CHECK()s since Foo() already been used once.
+/// 
+/// +/// We offer 2 syntaxes for calling Passed(). The first takes an rvalue and is +/// best suited for use with the return value of a function or other temporary +/// rvalues. The second takes a pointer to the scoper and is just syntactic +/// sugar to avoid having to write Passed(std::move(scoper)). +/// +/// Both versions of Passed() prevent T from being an lvalue reference. The +/// first via use of enable_if, and the second takes a T* which will not bind to +/// T&. +/// +template ::value>* = nullptr> +inline cef_internal::PassedWrapper Passed(T&& scoper) { + return cef_internal::PassedWrapper(std::move(scoper)); +} +template +inline cef_internal::PassedWrapper Passed(T* scoper) { + return cef_internal::PassedWrapper(std::move(*scoper)); +} - // For methods, we need to be careful for parameter 1. We do not require - // a scoped_refptr because BindState<> itself takes care of AddRef() for - // methods. We also disallow binding of an array as the method's target - // object. - COMPILE_ASSERT(cef_internal::HasIsMethodTag::value || - !cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::HasIsMethodTag::value || - !is_array::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p2_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p3_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p4_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p5_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p6_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p7_is_refcounted_type_and_needs_scoped_refptr); - typedef cef_internal::BindState< - RunnableType, RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)> - BindState; +/// +/// IgnoreResult() is used to adapt a function or callback with a return type to +/// one with a void return. This is most useful if you have a function with, +/// say, a pesky ignorable bool return that you want to use with PostTask or +/// something else that expect a callback with a void return. +/// +/// EXAMPLE OF IgnoreResult(): +/// +///
+///   int DoSomething(int arg) { cout << arg << endl; }
+///
+///   // Assign to a callback with a void return type.
+///   OnceCallback cb = BindOnce(IgnoreResult(&DoSomething));
+///   std::move(cb).Run(1);  // Prints "1".
+///
+///   // Prints "2" on |ml|.
+///   ml->PostTask(FROM_HERE, BindOnce(IgnoreResult(&DoSomething), 2);
+/// 
+/// +template +inline cef_internal::IgnoreResultHelper IgnoreResult(T data) { + return cef_internal::IgnoreResultHelper(std::move(data)); +} - return Callback(new BindState( - cef_internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6, p7)); +#if defined(OS_APPLE) && !HAS_FEATURE(objc_arc) + +/// +/// RetainBlock() is used to adapt an Objective-C block when Automated Reference +/// Counting (ARC) is disabled. This is unnecessary when ARC is enabled, as the +/// BindOnce and BindRepeating already support blocks then. +/// +/// EXAMPLE OF RetainBlock(): +/// +///
+///   // Wrap the block and bind it to a callback.
+///   OnceCallback cb =
+///       BindOnce(RetainBlock(^(int n) { NSLog(@"%d", n); }));
+///   std::move(cb).Run(1);  // Logs "1".
+/// 
+/// +template +base::mac::ScopedBlock RetainBlock(R (^block)(Args...)) { + return base::mac::ScopedBlock(block, + base::scoped_policy::RETAIN); } +#endif // defined(OS_APPLE) && !HAS_FEATURE(objc_arc) + } // namespace base #endif // !USING_CHROMIUM_INCLUDES diff --git a/src/include/base/cef_bind_helpers.h b/src/include/base/cef_bind_helpers.h deleted file mode 100644 index 2b4798b2c..000000000 --- a/src/include/base/cef_bind_helpers.h +++ /dev/null @@ -1,579 +0,0 @@ -// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011 -// Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This defines a set of argument wrappers and related factory methods that -// can be used specify the refcounting and reference semantics of arguments -// that are bound by the Bind() function in base/bind.h. -// -// It also defines a set of simple functions and utilities that people want -// when using Callback<> and Bind(). -// -// -// ARGUMENT BINDING WRAPPERS -// -// The wrapper functions are base::Unretained(), base::Owned(), base::Passed(), -// base::ConstRef(), and base::IgnoreResult(). -// -// Unretained() allows Bind() to bind a non-refcounted class, and to disable -// refcounting on arguments that are refcounted objects. -// -// Owned() transfers ownership of an object to the Callback resulting from -// bind; the object will be deleted when the Callback is deleted. -// -// Passed() is for transferring movable-but-not-copyable types (eg. scoped_ptr) -// through a Callback. Logically, this signifies a destructive transfer of -// the state of the argument into the target function. Invoking -// Callback::Run() twice on a Callback that was created with a Passed() -// argument will CHECK() because the first invocation would have already -// transferred ownership to the target function. -// -// ConstRef() allows binding a constant reference to an argument rather -// than a copy. -// -// IgnoreResult() is used to adapt a function or Callback with a return type to -// one with a void return. This is most useful if you have a function with, -// say, a pesky ignorable bool return that you want to use with PostTask or -// something else that expect a Callback with a void return. -// -// EXAMPLE OF Unretained(): -// -// class Foo { -// public: -// void func() { cout << "Foo:f" << endl; } -// }; -// -// // In some function somewhere. -// Foo foo; -// Closure foo_callback = -// Bind(&Foo::func, Unretained(&foo)); -// foo_callback.Run(); // Prints "Foo:f". -// -// Without the Unretained() wrapper on |&foo|, the above call would fail -// to compile because Foo does not support the AddRef() and Release() methods. -// -// -// EXAMPLE OF Owned(): -// -// void foo(int* arg) { cout << *arg << endl } -// -// int* pn = new int(1); -// Closure foo_callback = Bind(&foo, Owned(pn)); -// -// foo_callback.Run(); // Prints "1" -// foo_callback.Run(); // Prints "1" -// *n = 2; -// foo_callback.Run(); // Prints "2" -// -// foo_callback.Reset(); // |pn| is deleted. Also will happen when -// // |foo_callback| goes out of scope. -// -// Without Owned(), someone would have to know to delete |pn| when the last -// reference to the Callback is deleted. -// -// -// EXAMPLE OF ConstRef(): -// -// void foo(int arg) { cout << arg << endl } -// -// int n = 1; -// Closure no_ref = Bind(&foo, n); -// Closure has_ref = Bind(&foo, ConstRef(n)); -// -// no_ref.Run(); // Prints "1" -// has_ref.Run(); // Prints "1" -// -// n = 2; -// no_ref.Run(); // Prints "1" -// has_ref.Run(); // Prints "2" -// -// Note that because ConstRef() takes a reference on |n|, |n| must outlive all -// its bound callbacks. -// -// -// EXAMPLE OF IgnoreResult(): -// -// int DoSomething(int arg) { cout << arg << endl; } -// -// // Assign to a Callback with a void return type. -// Callback cb = Bind(IgnoreResult(&DoSomething)); -// cb->Run(1); // Prints "1". -// -// // Prints "1" on |ml|. -// ml->PostTask(FROM_HERE, Bind(IgnoreResult(&DoSomething), 1); -// -// -// EXAMPLE OF Passed(): -// -// void TakesOwnership(scoped_ptr arg) { } -// scoped_ptr CreateFoo() { return scoped_ptr(new Foo()); } -// -// scoped_ptr f(new Foo()); -// -// // |cb| is given ownership of Foo(). |f| is now NULL. -// // You can use f.Pass() in place of &f, but it's more verbose. -// Closure cb = Bind(&TakesOwnership, Passed(&f)); -// -// // Run was never called so |cb| still owns Foo() and deletes -// // it on Reset(). -// cb.Reset(); -// -// // |cb| is given a new Foo created by CreateFoo(). -// cb = Bind(&TakesOwnership, Passed(CreateFoo())); -// -// // |arg| in TakesOwnership() is given ownership of Foo(). |cb| -// // no longer owns Foo() and, if reset, would not delete Foo(). -// cb.Run(); // Foo() is now transferred to |arg| and deleted. -// cb.Run(); // This CHECK()s since Foo() already been used once. -// -// Passed() is particularly useful with PostTask() when you are transferring -// ownership of an argument into a task, but don't necessarily know if the -// task will always be executed. This can happen if the task is cancellable -// or if it is posted to a MessageLoopProxy. -// -// -// SIMPLE FUNCTIONS AND UTILITIES. -// -// DoNothing() - Useful for creating a Closure that does nothing when called. -// DeletePointer() - Useful for creating a Closure that will delete a -// pointer when invoked. Only use this when necessary. -// In most cases MessageLoop::DeleteSoon() is a better -// fit. - -#ifndef CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_ -#define CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_ -#pragma once - -#if defined(BASE_BIND_HELPERS_H_) -// Do nothing if the Chromium header has already been included. -// This can happen in cases where Chromium code is used directly by the -// client application. When using Chromium code directly always include -// the Chromium header first to avoid type conflicts. -#elif defined(USING_CHROMIUM_INCLUDES) -// When building CEF include the Chromium header directly. -#include "base/bind_helpers.h" -#else // !USING_CHROMIUM_INCLUDES -// The following is substantially similar to the Chromium implementation. -// If the Chromium implementation diverges the below implementation should be -// updated to match. - -#include "include/base/cef_basictypes.h" -#include "include/base/cef_callback.h" -#include "include/base/cef_template_util.h" -#include "include/base/cef_weak_ptr.h" - -namespace base { -namespace cef_internal { - -// Use the Substitution Failure Is Not An Error (SFINAE) trick to inspect T -// for the existence of AddRef() and Release() functions of the correct -// signature. -// -// http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error -// http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence -// http://stackoverflow.com/questions/4358584/sfinae-approach-comparison -// http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions -// -// The last link in particular show the method used below. -// -// For SFINAE to work with inherited methods, we need to pull some extra tricks -// with multiple inheritance. In the more standard formulation, the overloads -// of Check would be: -// -// template -// Yes NotTheCheckWeWant(Helper<&C::TargetFunc>*); -// -// template -// No NotTheCheckWeWant(...); -// -// static const bool value = sizeof(NotTheCheckWeWant(0)) == sizeof(Yes); -// -// The problem here is that template resolution will not match -// C::TargetFunc if TargetFunc does not exist directly in C. That is, if -// TargetFunc in inherited from an ancestor, &C::TargetFunc will not match, -// |value| will be false. This formulation only checks for whether or -// not TargetFunc exist directly in the class being introspected. -// -// To get around this, we play a dirty trick with multiple inheritance. -// First, We create a class BaseMixin that declares each function that we -// want to probe for. Then we create a class Base that inherits from both T -// (the class we wish to probe) and BaseMixin. Note that the function -// signature in BaseMixin does not need to match the signature of the function -// we are probing for; thus it's easiest to just use void(void). -// -// Now, if TargetFunc exists somewhere in T, then &Base::TargetFunc has an -// ambiguous resolution between BaseMixin and T. This lets us write the -// following: -// -// template -// No GoodCheck(Helper<&C::TargetFunc>*); -// -// template -// Yes GoodCheck(...); -// -// static const bool value = sizeof(GoodCheck(0)) == sizeof(Yes); -// -// Notice here that the variadic version of GoodCheck() returns Yes here -// instead of No like the previous one. Also notice that we calculate |value| -// by specializing GoodCheck() on Base instead of T. -// -// We've reversed the roles of the variadic, and Helper overloads. -// GoodCheck(Helper<&C::TargetFunc>*), when C = Base, fails to be a valid -// substitution if T::TargetFunc exists. Thus GoodCheck(0) will resolve -// to the variadic version if T has TargetFunc. If T::TargetFunc does not -// exist, then &C::TargetFunc is not ambiguous, and the overload resolution -// will prefer GoodCheck(Helper<&C::TargetFunc>*). -// -// This method of SFINAE will correctly probe for inherited names, but it cannot -// typecheck those names. It's still a good enough sanity check though. -// -// Works on gcc-4.2, gcc-4.4, and Visual Studio 2008. -// -// TODO(ajwong): Move to ref_counted.h or template_util.h when we've vetted -// this works well. -// -// TODO(ajwong): Make this check for Release() as well. -// See http://crbug.com/82038. -template -class SupportsAddRefAndRelease { - typedef char Yes[1]; - typedef char No[2]; - - struct BaseMixin { - void AddRef(); - }; - -// MSVC warns when you try to use Base if T has a private destructor, the -// common pattern for refcounted types. It does this even though no attempt to -// instantiate Base is made. We disable the warning for this definition. -#if defined(OS_WIN) -#pragma warning(push) -#pragma warning(disable : 4624) -#endif - struct Base : public T, public BaseMixin {}; -#if defined(OS_WIN) -#pragma warning(pop) -#endif - - template - struct Helper {}; - - template - static No& Check(Helper<&C::AddRef>*); - - template - static Yes& Check(...); - - public: - static const bool value = sizeof(Check(0)) == sizeof(Yes); -}; - -// Helpers to assert that arguments of a recounted type are bound with a -// scoped_refptr. -template -struct UnsafeBindtoRefCountedArgHelper : false_type {}; - -template -struct UnsafeBindtoRefCountedArgHelper - : integral_constant::value> {}; - -template -struct UnsafeBindtoRefCountedArg : false_type {}; - -template -struct UnsafeBindtoRefCountedArg - : UnsafeBindtoRefCountedArgHelper::value, T> {}; - -template -class HasIsMethodTag { - typedef char Yes[1]; - typedef char No[2]; - - template - static Yes& Check(typename U::IsMethod*); - - template - static No& Check(...); - - public: - static const bool value = sizeof(Check(0)) == sizeof(Yes); -}; - -template -class UnretainedWrapper { - public: - explicit UnretainedWrapper(T* o) : ptr_(o) {} - T* get() const { return ptr_; } - - private: - T* ptr_; -}; - -template -class ConstRefWrapper { - public: - explicit ConstRefWrapper(const T& o) : ptr_(&o) {} - const T& get() const { return *ptr_; } - - private: - const T* ptr_; -}; - -template -struct IgnoreResultHelper { - explicit IgnoreResultHelper(T functor) : functor_(functor) {} - - T functor_; -}; - -template -struct IgnoreResultHelper> { - explicit IgnoreResultHelper(const Callback& functor) : functor_(functor) {} - - const Callback& functor_; -}; - -// An alternate implementation is to avoid the destructive copy, and instead -// specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to -// a class that is essentially a scoped_ptr<>. -// -// The current implementation has the benefit though of leaving ParamTraits<> -// fully in callback_internal.h as well as avoiding type conversions during -// storage. -template -class OwnedWrapper { - public: - explicit OwnedWrapper(T* o) : ptr_(o) {} - ~OwnedWrapper() { delete ptr_; } - T* get() const { return ptr_; } - OwnedWrapper(const OwnedWrapper& other) { - ptr_ = other.ptr_; - other.ptr_ = NULL; - } - - private: - mutable T* ptr_; -}; - -// PassedWrapper is a copyable adapter for a scoper that ignores const. -// -// It is needed to get around the fact that Bind() takes a const reference to -// all its arguments. Because Bind() takes a const reference to avoid -// unnecessary copies, it is incompatible with movable-but-not-copyable -// types; doing a destructive "move" of the type into Bind() would violate -// the const correctness. -// -// This conundrum cannot be solved without either C++11 rvalue references or -// a O(2^n) blowup of Bind() templates to handle each combination of regular -// types and movable-but-not-copyable types. Thus we introduce a wrapper type -// that is copyable to transmit the correct type information down into -// BindState<>. Ignoring const in this type makes sense because it is only -// created when we are explicitly trying to do a destructive move. -// -// Two notes: -// 1) PassedWrapper supports any type that has a "Pass()" function. -// This is intentional. The whitelisting of which specific types we -// support is maintained by CallbackParamTraits<>. -// 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL" -// scoper to a Callback and allow the Callback to execute once. -template -class PassedWrapper { - public: - explicit PassedWrapper(T scoper) : is_valid_(true), scoper_(scoper.Pass()) {} - PassedWrapper(const PassedWrapper& other) - : is_valid_(other.is_valid_), scoper_(other.scoper_.Pass()) {} - T Pass() const { - CHECK(is_valid_); - is_valid_ = false; - return scoper_.Pass(); - } - - private: - mutable bool is_valid_; - mutable T scoper_; -}; - -// Unwrap the stored parameters for the wrappers above. -template -struct UnwrapTraits { - typedef const T& ForwardType; - static ForwardType Unwrap(const T& o) { return o; } -}; - -template -struct UnwrapTraits> { - typedef T* ForwardType; - static ForwardType Unwrap(UnretainedWrapper unretained) { - return unretained.get(); - } -}; - -template -struct UnwrapTraits> { - typedef const T& ForwardType; - static ForwardType Unwrap(ConstRefWrapper const_ref) { - return const_ref.get(); - } -}; - -template -struct UnwrapTraits> { - typedef T* ForwardType; - static ForwardType Unwrap(const scoped_refptr& o) { return o.get(); } -}; - -template -struct UnwrapTraits> { - typedef const WeakPtr& ForwardType; - static ForwardType Unwrap(const WeakPtr& o) { return o; } -}; - -template -struct UnwrapTraits> { - typedef T* ForwardType; - static ForwardType Unwrap(const OwnedWrapper& o) { return o.get(); } -}; - -template -struct UnwrapTraits> { - typedef T ForwardType; - static T Unwrap(PassedWrapper& o) { return o.Pass(); } -}; - -// Utility for handling different refcounting semantics in the Bind() -// function. -template -struct MaybeRefcount; - -template -struct MaybeRefcount { - static void AddRef(const T&) {} - static void Release(const T&) {} -}; - -template -struct MaybeRefcount { - static void AddRef(const T*) {} - static void Release(const T*) {} -}; - -template -struct MaybeRefcount { - static void AddRef(const T&) {} - static void Release(const T&) {} -}; - -template -struct MaybeRefcount { - static void AddRef(T* o) { o->AddRef(); } - static void Release(T* o) { o->Release(); } -}; - -// No need to additionally AddRef() and Release() since we are storing a -// scoped_refptr<> inside the storage object already. -template -struct MaybeRefcount> { - static void AddRef(const scoped_refptr& o) {} - static void Release(const scoped_refptr& o) {} -}; - -template -struct MaybeRefcount { - static void AddRef(const T* o) { o->AddRef(); } - static void Release(const T* o) { o->Release(); } -}; - -// IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a -// method. It is used internally by Bind() to select the correct -// InvokeHelper that will no-op itself in the event the WeakPtr<> for -// the target object is invalidated. -// -// P1 should be the type of the object that will be received of the method. -template -struct IsWeakMethod : public false_type {}; - -template -struct IsWeakMethod> : public true_type {}; - -template -struct IsWeakMethod>> : public true_type {}; - -} // namespace cef_internal - -template -static inline cef_internal::UnretainedWrapper Unretained(T* o) { - return cef_internal::UnretainedWrapper(o); -} - -template -static inline cef_internal::ConstRefWrapper ConstRef(const T& o) { - return cef_internal::ConstRefWrapper(o); -} - -template -static inline cef_internal::OwnedWrapper Owned(T* o) { - return cef_internal::OwnedWrapper(o); -} - -// We offer 2 syntaxes for calling Passed(). The first takes a temporary and -// is best suited for use with the return value of a function. The second -// takes a pointer to the scoper and is just syntactic sugar to avoid having -// to write Passed(scoper.Pass()). -template -static inline cef_internal::PassedWrapper Passed(T scoper) { - return cef_internal::PassedWrapper(scoper.Pass()); -} -template -static inline cef_internal::PassedWrapper Passed(T* scoper) { - return cef_internal::PassedWrapper(scoper->Pass()); -} - -template -static inline cef_internal::IgnoreResultHelper IgnoreResult(T data) { - return cef_internal::IgnoreResultHelper(data); -} - -template -static inline cef_internal::IgnoreResultHelper> IgnoreResult( - const Callback& data) { - return cef_internal::IgnoreResultHelper>(data); -} - -void DoNothing(); - -template -void DeletePointer(T* obj) { - delete obj; -} - -} // namespace base - -#endif // !USING_CHROMIUM_INCLUDES - -#endif // CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_ diff --git a/src/include/base/cef_build.h b/src/include/base/cef_build.h index 1e2065ce3..717f05df1 100644 --- a/src/include/base/cef_build.h +++ b/src/include/base/cef_build.h @@ -27,53 +27,132 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/// \file +/// This file adds defines about the platform we're currently building on. +/// +///
+///  Operating System:
+///    OS_AIX / OS_ANDROID / OS_ASMJS / OS_FREEBSD / OS_FUCHSIA / OS_IOS /
+///    OS_LINUX / OS_MAC / OS_NACL (SFI or NONSFI) / OS_NETBSD / OS_OPENBSD /
+///    OS_QNX / OS_SOLARIS / OS_WIN
+///  Operating System family:
+///    OS_APPLE: IOS or MAC
+///    OS_BSD: FREEBSD or NETBSD or OPENBSD
+///    OS_POSIX: AIX or ANDROID or ASMJS or CHROMEOS or FREEBSD or IOS or LINUX
+///              or MAC or NACL or NETBSD or OPENBSD or QNX or SOLARIS
+///
+///  /!\ Note: OS_CHROMEOS is set by the build system, not this file
+///
+///  Compiler:
+///    COMPILER_MSVC / COMPILER_GCC
+///
+///  Processor:
+///    ARCH_CPU_ARM64 / ARCH_CPU_ARMEL / ARCH_CPU_MIPS / ARCH_CPU_MIPS64 /
+///    ARCH_CPU_MIPS64EL / ARCH_CPU_MIPSEL / ARCH_CPU_PPC64 / ARCH_CPU_S390 /
+///    ARCH_CPU_S390X / ARCH_CPU_X86 / ARCH_CPU_X86_64
+///  Processor family:
+///    ARCH_CPU_ARM_FAMILY: ARMEL or ARM64
+///    ARCH_CPU_MIPS_FAMILY: MIPS64EL or MIPSEL or MIPS64 or MIPS
+///    ARCH_CPU_PPC64_FAMILY: PPC64
+///    ARCH_CPU_S390_FAMILY: S390 or S390X
+///    ARCH_CPU_X86_FAMILY: X86 or X86_64
+///  Processor features:
+///    ARCH_CPU_31_BITS / ARCH_CPU_32_BITS / ARCH_CPU_64_BITS
+///    ARCH_CPU_BIG_ENDIAN / ARCH_CPU_LITTLE_ENDIAN
+/// 
+/// + #ifndef CEF_INCLUDE_BASE_CEF_BUILD_H_ #define CEF_INCLUDE_BASE_CEF_BUILD_H_ #pragma once #if defined(USING_CHROMIUM_INCLUDES) // When building CEF include the Chromium header directly. -#include "base/compiler_specific.h" +#include "build/build_config.h" #else // !USING_CHROMIUM_INCLUDES // The following is substantially similar to the Chromium implementation. // If the Chromium implementation diverges the below implementation should be // updated to match. -#if defined(_WIN32) -#ifndef OS_WIN -#define OS_WIN 1 -#endif +// A set of macros to use for platform detection. +#if defined(ANDROID) +#define OS_ANDROID 1 #elif defined(__APPLE__) -#ifndef OS_MACOSX +// Only include TargetConditionals after testing ANDROID as some Android builds +// on the Mac have this header available and it's not needed unless the target +// is really an Apple platform. +#include +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +#define OS_IOS 1 +#else +#define OS_MAC 1 +// For backwards compatibility. #define OS_MACOSX 1 -#endif +#endif // defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE #elif defined(__linux__) -#ifndef OS_LINUX +#if !defined(OS_CHROMEOS) +// Do not define OS_LINUX on Chrome OS build. +// The OS_CHROMEOS macro is defined in GN. #define OS_LINUX 1 +#endif // !defined(OS_CHROMEOS) +// Include a system header to pull in features.h for glibc/uclibc macros. +#include +#if defined(__GLIBC__) && !defined(__UCLIBC__) +// We really are using glibc, not uClibc pretending to be glibc. +#define LIBC_GLIBC 1 #endif +#elif defined(_WIN32) +#define OS_WIN 1 +#elif defined(__Fuchsia__) +#define OS_FUCHSIA 1 +#elif defined(__FreeBSD__) +#define OS_FREEBSD 1 +#elif defined(__NetBSD__) +#define OS_NETBSD 1 +#elif defined(__OpenBSD__) +#define OS_OPENBSD 1 +#elif defined(__sun) +#define OS_SOLARIS 1 +#elif defined(__QNXNTO__) +#define OS_QNX 1 +#elif defined(_AIX) +#define OS_AIX 1 +#elif defined(__asmjs__) || defined(__wasm__) +#define OS_ASMJS 1 #else -#error Please add support for your platform in cef_build.h +#error Please add support for your platform in include/base/cef_build.h +#endif +// NOTE: Adding a new port? Please follow +// https://chromium.googlesource.com/chromium/src/+/master/docs/new_port_policy.md + +#if defined(OS_MAC) || defined(OS_IOS) +#define OS_APPLE 1 +#endif + +// For access to standard BSD features, use OS_BSD instead of a +// more specific macro. +#if defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_OPENBSD) +#define OS_BSD 1 #endif // For access to standard POSIXish features, use OS_POSIX instead of a // more specific macro. -#if defined(OS_MACOSX) || defined(OS_LINUX) -#ifndef OS_POSIX +#if defined(OS_AIX) || defined(OS_ANDROID) || defined(OS_ASMJS) || \ + defined(OS_FREEBSD) || defined(OS_IOS) || defined(OS_LINUX) || \ + defined(OS_CHROMEOS) || defined(OS_MAC) || defined(OS_NACL) || \ + defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_QNX) || \ + defined(OS_SOLARIS) #define OS_POSIX 1 #endif -#endif -// Compiler detection. +// Compiler detection. Note: clang masquerades as GCC on POSIX and as MSVC on +// Windows. #if defined(__GNUC__) -#ifndef COMPILER_GCC #define COMPILER_GCC 1 -#endif #elif defined(_MSC_VER) -#ifndef COMPILER_MSVC #define COMPILER_MSVC 1 -#endif #else -#error Please add support for your compiler in cef_build.h +#error Please add support for your compiler in build/build_config.h #endif // Processor architecture detection. For more info on what's defined, see: @@ -90,108 +169,95 @@ #define ARCH_CPU_X86 1 #define ARCH_CPU_32_BITS 1 #define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__s390x__) +#define ARCH_CPU_S390_FAMILY 1 +#define ARCH_CPU_S390X 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#elif defined(__s390__) +#define ARCH_CPU_S390_FAMILY 1 +#define ARCH_CPU_S390 1 +#define ARCH_CPU_31_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#elif (defined(__PPC64__) || defined(__PPC__)) && defined(__BIG_ENDIAN__) +#define ARCH_CPU_PPC64_FAMILY 1 +#define ARCH_CPU_PPC64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#elif defined(__PPC64__) +#define ARCH_CPU_PPC64_FAMILY 1 +#define ARCH_CPU_PPC64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 #elif defined(__ARMEL__) #define ARCH_CPU_ARM_FAMILY 1 #define ARCH_CPU_ARMEL 1 #define ARCH_CPU_32_BITS 1 #define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(__aarch64__) +#elif defined(__aarch64__) || defined(_M_ARM64) #define ARCH_CPU_ARM_FAMILY 1 #define ARCH_CPU_ARM64 1 #define ARCH_CPU_64_BITS 1 #define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(__pnacl__) +#elif defined(__pnacl__) || defined(__asmjs__) || defined(__wasm__) #define ARCH_CPU_32_BITS 1 #define ARCH_CPU_LITTLE_ENDIAN 1 #elif defined(__MIPSEL__) +#if defined(__LP64__) +#define ARCH_CPU_MIPS_FAMILY 1 +#define ARCH_CPU_MIPS64EL 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#else #define ARCH_CPU_MIPS_FAMILY 1 #define ARCH_CPU_MIPSEL 1 #define ARCH_CPU_32_BITS 1 #define ARCH_CPU_LITTLE_ENDIAN 1 +#endif +#elif defined(__MIPSEB__) +#if defined(__LP64__) +#define ARCH_CPU_MIPS_FAMILY 1 +#define ARCH_CPU_MIPS64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 #else -#error Please add support for your architecture in cef_build.h +#define ARCH_CPU_MIPS_FAMILY 1 +#define ARCH_CPU_MIPS 1 +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#endif +#else +#error Please add support for your architecture in include/base/cef_build.h #endif // Type detection for wchar_t. #if defined(OS_WIN) -#define WCHAR_T_IS_UTF16 +#define WCHAR_T_IS_16_BIT +#elif defined(OS_FUCHSIA) +#define WCHAR_T_IS_32_BIT #elif defined(OS_POSIX) && defined(COMPILER_GCC) && defined(__WCHAR_MAX__) && \ (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff) -#define WCHAR_T_IS_UTF32 +#define WCHAR_T_IS_32_BIT #elif defined(OS_POSIX) && defined(COMPILER_GCC) && defined(__WCHAR_MAX__) && \ (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff) // On Posix, we'll detect short wchar_t, but projects aren't guaranteed to // compile in this mode (in particular, Chrome doesn't). This is intended for // other projects using base who manage their own dependencies and make sure // short wchar works for them. -#define WCHAR_T_IS_UTF16 -#else -#error Please add support for your compiler in cef_build.h -#endif - -// Annotate a function indicating the caller must examine the return value. -// Use like: -// int foo() WARN_UNUSED_RESULT; -// To explicitly ignore a result, see |ignore_result()| in . -#ifndef WARN_UNUSED_RESULT -#if defined(COMPILER_GCC) -#define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) -#else -#define WARN_UNUSED_RESULT -#endif -#endif // WARN_UNUSED_RESULT - -// Annotate a typedef or function indicating it's ok if it's not used. -// Use like: -// typedef Foo Bar ALLOW_UNUSED_TYPE; -#ifndef ALLOW_UNUSED_TYPE -#if defined(COMPILER_GCC) -#define ALLOW_UNUSED_TYPE __attribute__((unused)) +#define WCHAR_T_IS_16_BIT #else -#define ALLOW_UNUSED_TYPE +#error Please add support for your compiler in include/base/cef_build.h #endif -#endif // ALLOW_UNUSED_TYPE -// Annotate a variable indicating it's ok if the variable is not used. -// (Typically used to silence a compiler warning when the assignment -// is important for some other reason.) -// Use like: -// int x = ...; -// ALLOW_UNUSED_LOCAL(x); -#ifndef ALLOW_UNUSED_LOCAL -#define ALLOW_UNUSED_LOCAL(x) false ? (void)x : (void)0 +#if defined(OS_ANDROID) +// The compiler thinks std::string::const_iterator and "const char*" are +// equivalent types. +#define STD_STRING_ITERATOR_IS_CHAR_POINTER +// The compiler thinks std::u16string::const_iterator and "char16_t*" are +// equivalent types. +#define BASE_STRING16_ITERATOR_IS_CHAR16_POINTER #endif #endif // !USING_CHROMIUM_INCLUDES -// Annotate a virtual method indicating it must be overriding a virtual method -// in the parent class. -// Use like: -// void foo() OVERRIDE; -// NOTE: This define should only be used in classes exposed to the client since -// C++11 support may not be enabled in client applications. CEF internal classes -// should use the `override` keyword directly. -#ifndef OVERRIDE -#if defined(__clang__) -#define OVERRIDE override -#elif defined(COMPILER_MSVC) && _MSC_VER >= 1600 -// Visual Studio 2010 and later support override. -#define OVERRIDE override -#elif defined(COMPILER_GCC) && __cplusplus >= 201103 && \ - (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40700 -// GCC 4.7 supports explicit virtual overrides when C++11 support is enabled. -#define OVERRIDE override -#else -#define OVERRIDE -#endif -#endif // OVERRIDE - -// Check for C++11 template alias support which was added in VS2013 and GCC4.7. -// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf -#if __cplusplus > 199711L || (defined(_MSC_VER) && _MSC_VER >= 1800) || \ - (defined(__GNUC__) && \ - (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ >= 40700)) -#define HAS_CPP11_TEMPLATE_ALIAS_SUPPORT -#endif - #endif // CEF_INCLUDE_BASE_CEF_BUILD_H_ diff --git a/src/include/base/cef_callback.h b/src/include/base/cef_callback.h index 16e238a97..bcfe4992a 100644 --- a/src/include/base/cef_callback.h +++ b/src/include/base/cef_callback.h @@ -28,772 +28,221 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/// \file +/// A callback is similar in concept to a function pointer: it wraps a runnable +/// object such as a function, method, lambda, or even another callback, +/// allowing the runnable object to be invoked later via the callback object. +/// +/// Unlike function pointers, callbacks are created with base::BindOnce() or +/// base::BindRepeating() and support partial function application. +/// +/// A base::OnceCallback may be Run() at most once; a base::RepeatingCallback +/// may be Run() any number of times. |is_null()| is guaranteed to return true +/// for a moved-from callback. +/// +///
+///   // The lambda takes two arguments, but the first argument |x| is bound at
+///   // callback creation.
+///   base::OnceCallback cb = base::BindOnce([] (int x, int y) {
+///     return x + y;
+///   }, 1);
+///   // Run() only needs the remaining unbound argument |y|.
+///   printf("1 + 2 = %d\n", std::move(cb).Run(2));  // Prints 3
+///   printf("cb is null? %s\n",
+///          cb.is_null() ? "true" : "false");  // Prints true
+///   std::move(cb).Run(2);  // Crashes since |cb| has already run.
+/// 
+/// +/// Callbacks also support cancellation. A common use is binding the receiver +/// object as a WeakPtr. If that weak pointer is invalidated, calling Run() +/// will be a no-op. Note that |IsCancelled()| and |is_null()| are distinct: +/// simply cancelling a callback will not also make it null. +/// +/// See https://chromium.googlesource.com/chromium/src/+/lkgr/docs/callback.md +/// for the full documentation. + #ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_H_ #define CEF_INCLUDE_BASE_CEF_CALLBACK_H_ #pragma once -#if defined(BASE_CALLBACK_H_) -// Do nothing if the Chromium header has already been included. -// This can happen in cases where Chromium code is used directly by the -// client application. When using Chromium code directly always include -// the Chromium header first to avoid type conflicts. -#elif defined(USING_CHROMIUM_INCLUDES) +#if defined(USING_CHROMIUM_INCLUDES) // When building CEF include the Chromium header directly. -#include "base/callback.h" +#include "base/functional/callback.h" #else // !USING_CHROMIUM_INCLUDES // The following is substantially similar to the Chromium implementation. // If the Chromium implementation diverges the below implementation should be // updated to match. +#include + +#include "include/base/cef_bind.h" #include "include/base/cef_callback_forward.h" -#include "include/base/cef_template_util.h" +#include "include/base/cef_logging.h" #include "include/base/internal/cef_callback_internal.h" -// NOTE: Header files that do not require the full definition of Callback or -// Closure should #include "base/cef_callback_forward.h" instead of this file. - -// ----------------------------------------------------------------------------- -// Introduction -// ----------------------------------------------------------------------------- -// -// The templated Callback class is a generalized function object. Together -// with the Bind() function in bind.h, they provide a type-safe method for -// performing partial application of functions. -// -// Partial application (or "currying") is the process of binding a subset of -// a function's arguments to produce another function that takes fewer -// arguments. This can be used to pass around a unit of delayed execution, -// much like lexical closures are used in other languages. For example, it -// is used in Chromium code to schedule tasks on different MessageLoops. -// -// A callback with no unbound input parameters (base::Callback) -// is called a base::Closure. Note that this is NOT the same as what other -// languages refer to as a closure -- it does not retain a reference to its -// enclosing environment. -// -// MEMORY MANAGEMENT AND PASSING -// -// The Callback objects themselves should be passed by const-reference, and -// stored by copy. They internally store their state via a refcounted class -// and thus do not need to be deleted. -// -// The reason to pass via a const-reference is to avoid unnecessary -// AddRef/Release pairs to the internal state. -// -// -// ----------------------------------------------------------------------------- -// Quick reference for basic stuff -// ----------------------------------------------------------------------------- -// -// BINDING A BARE FUNCTION -// -// int Return5() { return 5; } -// base::Callback func_cb = base::Bind(&Return5); -// LOG(INFO) << func_cb.Run(); // Prints 5. -// -// BINDING A CLASS METHOD -// -// The first argument to bind is the member function to call, the second is -// the object on which to call it. -// -// class Ref : public base::RefCountedThreadSafe { -// public: -// int Foo() { return 3; } -// void PrintBye() { LOG(INFO) << "bye."; } -// }; -// scoped_refptr ref = new Ref(); -// base::Callback ref_cb = base::Bind(&Ref::Foo, ref); -// LOG(INFO) << ref_cb.Run(); // Prints out 3. -// -// By default the object must support RefCounted or you will get a compiler -// error. If you're passing between threads, be sure it's -// RefCountedThreadSafe! See "Advanced binding of member functions" below if -// you don't want to use reference counting. -// -// RUNNING A CALLBACK -// -// Callbacks can be run with their "Run" method, which has the same -// signature as the template argument to the callback. -// -// void DoSomething(const base::Callback& callback) { -// callback.Run(5, "hello"); -// } -// -// Callbacks can be run more than once (they don't get deleted or marked when -// run). However, this precludes using base::Passed (see below). -// -// void DoSomething(const base::Callback& callback) { -// double myresult = callback.Run(3.14159); -// myresult += callback.Run(2.71828); -// } -// -// PASSING UNBOUND INPUT PARAMETERS -// -// Unbound parameters are specified at the time a callback is Run(). They are -// specified in the Callback template type: -// -// void MyFunc(int i, const std::string& str) {} -// base::Callback cb = base::Bind(&MyFunc); -// cb.Run(23, "hello, world"); -// -// PASSING BOUND INPUT PARAMETERS -// -// Bound parameters are specified when you create thee callback as arguments -// to Bind(). They will be passed to the function and the Run()ner of the -// callback doesn't see those values or even know that the function it's -// calling. -// -// void MyFunc(int i, const std::string& str) {} -// base::Callback cb = base::Bind(&MyFunc, 23, "hello world"); -// cb.Run(); -// -// A callback with no unbound input parameters (base::Callback) -// is called a base::Closure. So we could have also written: -// -// base::Closure cb = base::Bind(&MyFunc, 23, "hello world"); -// -// When calling member functions, bound parameters just go after the object -// pointer. -// -// base::Closure cb = base::Bind(&MyClass::MyFunc, this, 23, "hello world"); -// -// PARTIAL BINDING OF PARAMETERS -// -// You can specify some parameters when you create the callback, and specify -// the rest when you execute the callback. -// -// void MyFunc(int i, const std::string& str) {} -// base::Callback cb = base::Bind(&MyFunc, 23); -// cb.Run("hello world"); -// -// When calling a function bound parameters are first, followed by unbound -// parameters. -// -// -// ----------------------------------------------------------------------------- -// Quick reference for advanced binding -// ----------------------------------------------------------------------------- -// -// BINDING A CLASS METHOD WITH WEAK POINTERS -// -// base::Bind(&MyClass::Foo, GetWeakPtr()); -// -// The callback will not be run if the object has already been destroyed. -// DANGER: weak pointers are not threadsafe, so don't use this -// when passing between threads! -// -// BINDING A CLASS METHOD WITH MANUAL LIFETIME MANAGEMENT -// -// base::Bind(&MyClass::Foo, base::Unretained(this)); -// -// This disables all lifetime management on the object. You're responsible -// for making sure the object is alive at the time of the call. You break it, -// you own it! -// -// BINDING A CLASS METHOD AND HAVING THE CALLBACK OWN THE CLASS -// -// MyClass* myclass = new MyClass; -// base::Bind(&MyClass::Foo, base::Owned(myclass)); -// -// The object will be deleted when the callback is destroyed, even if it's -// not run (like if you post a task during shutdown). Potentially useful for -// "fire and forget" cases. -// -// IGNORING RETURN VALUES -// -// Sometimes you want to call a function that returns a value in a callback -// that doesn't expect a return value. -// -// int DoSomething(int arg) { cout << arg << endl; } -// base::Callback) cb = -// base::Bind(base::IgnoreResult(&DoSomething)); -// -// -// ----------------------------------------------------------------------------- -// Quick reference for binding parameters to Bind() -// ----------------------------------------------------------------------------- -// -// Bound parameters are specified as arguments to Bind() and are passed to the -// function. A callback with no parameters or no unbound parameters is called a -// Closure (base::Callback and base::Closure are the same thing). -// -// PASSING PARAMETERS OWNED BY THE CALLBACK -// -// void Foo(int* arg) { cout << *arg << endl; } -// int* pn = new int(1); -// base::Closure foo_callback = base::Bind(&foo, base::Owned(pn)); -// -// The parameter will be deleted when the callback is destroyed, even if it's -// not run (like if you post a task during shutdown). -// -// PASSING PARAMETERS AS A scoped_ptr -// -// void TakesOwnership(scoped_ptr arg) {} -// scoped_ptr f(new Foo); -// // f becomes null during the following call. -// base::Closure cb = base::Bind(&TakesOwnership, base::Passed(&f)); -// -// Ownership of the parameter will be with the callback until the it is run, -// when ownership is passed to the callback function. This means the callback -// can only be run once. If the callback is never run, it will delete the -// object when it's destroyed. -// -// PASSING PARAMETERS AS A scoped_refptr -// -// void TakesOneRef(scoped_refptr arg) {} -// scoped_refptr f(new Foo) -// base::Closure cb = base::Bind(&TakesOneRef, f); -// -// This should "just work." The closure will take a reference as long as it -// is alive, and another reference will be taken for the called function. -// -// PASSING PARAMETERS BY REFERENCE -// -// Const references are *copied* unless ConstRef is used. Example: -// -// void foo(const int& arg) { printf("%d %p\n", arg, &arg); } -// int n = 1; -// base::Closure has_copy = base::Bind(&foo, n); -// base::Closure has_ref = base::Bind(&foo, base::ConstRef(n)); -// n = 2; -// foo(n); // Prints "2 0xaaaaaaaaaaaa" -// has_copy.Run(); // Prints "1 0xbbbbbbbbbbbb" -// has_ref.Run(); // Prints "2 0xaaaaaaaaaaaa" -// -// Normally parameters are copied in the closure. DANGER: ConstRef stores a -// const reference instead, referencing the original parameter. This means -// that you must ensure the object outlives the callback! -// -// -// ----------------------------------------------------------------------------- -// Implementation notes -// ----------------------------------------------------------------------------- -// -// WHERE IS THIS DESIGN FROM: -// -// The design Callback and Bind is heavily influenced by C++'s -// tr1::function/tr1::bind, and by the "Google Callback" system used inside -// Google. -// -// -// HOW THE IMPLEMENTATION WORKS: -// -// There are three main components to the system: -// 1) The Callback classes. -// 2) The Bind() functions. -// 3) The arguments wrappers (e.g., Unretained() and ConstRef()). -// -// The Callback classes represent a generic function pointer. Internally, -// it stores a refcounted piece of state that represents the target function -// and all its bound parameters. Each Callback specialization has a templated -// constructor that takes an BindState<>*. In the context of the constructor, -// the static type of this BindState<> pointer uniquely identifies the -// function it is representing, all its bound parameters, and a Run() method -// that is capable of invoking the target. -// -// Callback's constructor takes the BindState<>* that has the full static type -// and erases the target function type as well as the types of the bound -// parameters. It does this by storing a pointer to the specific Run() -// function, and upcasting the state of BindState<>* to a -// BindStateBase*. This is safe as long as this BindStateBase pointer -// is only used with the stored Run() pointer. -// -// To BindState<> objects are created inside the Bind() functions. -// These functions, along with a set of internal templates, are responsible for -// -// - Unwrapping the function signature into return type, and parameters -// - Determining the number of parameters that are bound -// - Creating the BindState storing the bound parameters -// - Performing compile-time asserts to avoid error-prone behavior -// - Returning an Callback<> with an arity matching the number of unbound -// parameters and that knows the correct refcounting semantics for the -// target object if we are binding a method. -// -// The Bind functions do the above using type-inference, and template -// specializations. -// -// By default Bind() will store copies of all bound parameters, and attempt -// to refcount a target object if the function being bound is a class method. -// These copies are created even if the function takes parameters as const -// references. (Binding to non-const references is forbidden, see bind.h.) -// -// To change this behavior, we introduce a set of argument wrappers -// (e.g., Unretained(), and ConstRef()). These are simple container templates -// that are passed by value, and wrap a pointer to argument. See the -// file-level comment in base/bind_helpers.h for more info. -// -// These types are passed to the Unwrap() functions, and the MaybeRefcount() -// functions respectively to modify the behavior of Bind(). The Unwrap() -// and MaybeRefcount() functions change behavior by doing partial -// specialization based on whether or not a parameter is a wrapper type. -// -// ConstRef() is similar to tr1::cref. Unretained() is specific to Chromium. -// -// -// WHY NOT TR1 FUNCTION/BIND? -// -// Direct use of tr1::function and tr1::bind was considered, but ultimately -// rejected because of the number of copy constructors invocations involved -// in the binding of arguments during construction, and the forwarding of -// arguments during invocation. These copies will no longer be an issue in -// C++0x because C++0x will support rvalue reference allowing for the compiler -// to avoid these copies. However, waiting for C++0x is not an option. -// -// Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the -// tr1::bind call itself will invoke a non-trivial copy constructor three times -// for each bound parameter. Also, each when passing a tr1::function, each -// bound argument will be copied again. -// -// In addition to the copies taken at binding and invocation, copying a -// tr1::function causes a copy to be made of all the bound parameters and -// state. -// -// Furthermore, in Chromium, it is desirable for the Callback to take a -// reference on a target object when representing a class method call. This -// is not supported by tr1. -// -// Lastly, tr1::function and tr1::bind has a more general and flexible API. -// This includes things like argument reordering by use of -// tr1::bind::placeholder, support for non-const reference parameters, and some -// limited amount of subtyping of the tr1::function object (e.g., -// tr1::function is convertible to tr1::function). -// -// These are not features that are required in Chromium. Some of them, such as -// allowing for reference parameters, and subtyping of functions, may actually -// become a source of errors. Removing support for these features actually -// allows for a simpler implementation, and a terser Currying API. -// -// -// WHY NOT GOOGLE CALLBACKS? -// -// The Google callback system also does not support refcounting. Furthermore, -// its implementation has a number of strange edge cases with respect to type -// conversion of its arguments. In particular, the argument's constness must -// at times match exactly the function signature, or the type-inference might -// break. Given the above, writing a custom solution was easier. -// -// -// MISSING FUNCTIONALITY -// - Invoking the return of Bind. Bind(&foo).Run() does not work; -// - Binding arrays to functions that take a non-const pointer. -// Example: -// void Foo(const char* ptr); -// void Bar(char* ptr); -// Bind(&Foo, "test"); -// Bind(&Bar, "test"); // This fails because ptr is not const. - namespace base { -// First, we forward declare the Callback class template. This informs the -// compiler that the template only has 1 type parameter which is the function -// signature that the Callback is representing. -// -// After this, create template specializations for 0-7 parameters. Note that -// even though the template typelist grows, the specialization still -// only has one type: the function signature. -// -// If you are thinking of forward declaring Callback in your own header file, -// please include "base/callback_forward.h" instead. -template -class Callback; - -namespace cef_internal { -template -struct BindState; -} // namespace cef_internal - -template -class Callback : public cef_internal::CallbackBase { +template +class OnceCallback : public cef_internal::CallbackBase { public: - typedef R(RunType)(); - - Callback() : CallbackBase(NULL) {} + using ResultType = R; + using RunType = R(Args...); + using PolymorphicInvoke = R (*)(cef_internal::BindStateBase*, + cef_internal::PassingType...); - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template - Callback( - cef_internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &cef_internal::BindState::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); - } + constexpr OnceCallback() = default; + OnceCallback(std::nullptr_t) = delete; - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); - } + explicit OnceCallback(cef_internal::BindStateBase* bind_state) + : cef_internal::CallbackBase(bind_state) {} - R Run() const { - PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); + OnceCallback(const OnceCallback&) = delete; + OnceCallback& operator=(const OnceCallback&) = delete; - return f(bind_state_.get()); - } - - private: - typedef R (*PolymorphicInvoke)(cef_internal::BindStateBase*); -}; - -template -class Callback : public cef_internal::CallbackBase { - public: - typedef R(RunType)(A1); + OnceCallback(OnceCallback&&) noexcept = default; + OnceCallback& operator=(OnceCallback&&) noexcept = default; - Callback() : CallbackBase(NULL) {} + OnceCallback(RepeatingCallback other) + : cef_internal::CallbackBase(std::move(other)) {} - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template - Callback( - cef_internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &cef_internal::BindState::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); + OnceCallback& operator=(RepeatingCallback other) { + static_cast(*this) = std::move(other); + return *this; } - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); + R Run(Args... args) const& { + static_assert(!sizeof(*this), + "OnceCallback::Run() may only be invoked on a non-const " + "rvalue, i.e. std::move(callback).Run()."); + NOTREACHED(); } - R Run(typename cef_internal::CallbackParamTraits::ForwardType a1) const { + R Run(Args... args) && { + // Move the callback instance into a local variable before the invocation, + // that ensures the internal state is cleared after the invocation. + // It's not safe to touch |this| after the invocation, since running the + // bound function may destroy |this|. + OnceCallback cb = std::move(*this); PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); - - return f(bind_state_.get(), cef_internal::CallbackForward(a1)); + reinterpret_cast(cb.polymorphic_invoke()); + return f(cb.bind_state_.get(), std::forward(args)...); + } + + // Then() returns a new OnceCallback that receives the same arguments as + // |this|, and with the return type of |then|. The returned callback will: + // 1) Run the functor currently bound to |this| callback. + // 2) Run the |then| callback with the result from step 1 as its single + // argument. + // 3) Return the value from running the |then| callback. + // + // Since this method generates a callback that is a replacement for `this`, + // `this` will be consumed and reset to a null callback to ensure the + // originally-bound functor can be run at most once. + template + OnceCallback Then(OnceCallback then) && { + CHECK(then); + return BindOnce( + cef_internal::ThenHelper< + OnceCallback, OnceCallback>::CreateTrampoline(), + std::move(*this), std::move(then)); + } + + // This overload is required; even though RepeatingCallback is implicitly + // convertible to OnceCallback, that conversion will not used when matching + // for template argument deduction. + template + OnceCallback Then( + RepeatingCallback then) && { + CHECK(then); + return BindOnce( + cef_internal::ThenHelper< + OnceCallback, + RepeatingCallback>::CreateTrampoline(), + std::move(*this), std::move(then)); } - - private: - typedef R (*PolymorphicInvoke)( - cef_internal::BindStateBase*, - typename cef_internal::CallbackParamTraits::ForwardType); }; -template -class Callback : public cef_internal::CallbackBase { +template +class RepeatingCallback + : public cef_internal::CallbackBaseCopyable { public: - typedef R(RunType)(A1, A2); - - Callback() : CallbackBase(NULL) {} - - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template - Callback( - cef_internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &cef_internal::BindState::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); - } - - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); - } - - R Run(typename cef_internal::CallbackParamTraits::ForwardType a1, - typename cef_internal::CallbackParamTraits::ForwardType a2) const { - PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); - - return f(bind_state_.get(), cef_internal::CallbackForward(a1), - cef_internal::CallbackForward(a2)); - } + using ResultType = R; + using RunType = R(Args...); + using PolymorphicInvoke = R (*)(cef_internal::BindStateBase*, + cef_internal::PassingType...); - private: - typedef R (*PolymorphicInvoke)( - cef_internal::BindStateBase*, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType); -}; + constexpr RepeatingCallback() = default; + RepeatingCallback(std::nullptr_t) = delete; -template -class Callback : public cef_internal::CallbackBase { - public: - typedef R(RunType)(A1, A2, A3); + explicit RepeatingCallback(cef_internal::BindStateBase* bind_state) + : cef_internal::CallbackBaseCopyable(bind_state) {} - Callback() : CallbackBase(NULL) {} + // Copyable and movable. + RepeatingCallback(const RepeatingCallback&) = default; + RepeatingCallback& operator=(const RepeatingCallback&) = default; + RepeatingCallback(RepeatingCallback&&) noexcept = default; + RepeatingCallback& operator=(RepeatingCallback&&) noexcept = default; - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template - Callback( - cef_internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &cef_internal::BindState::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); + bool operator==(const RepeatingCallback& other) const { + return EqualsInternal(other); } - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); + bool operator!=(const RepeatingCallback& other) const { + return !operator==(other); } - R Run(typename cef_internal::CallbackParamTraits::ForwardType a1, - typename cef_internal::CallbackParamTraits::ForwardType a2, - typename cef_internal::CallbackParamTraits::ForwardType a3) const { + R Run(Args... args) const& { PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); - - return f(bind_state_.get(), cef_internal::CallbackForward(a1), - cef_internal::CallbackForward(a2), - cef_internal::CallbackForward(a3)); + reinterpret_cast(this->polymorphic_invoke()); + return f(this->bind_state_.get(), std::forward(args)...); } - private: - typedef R (*PolymorphicInvoke)( - cef_internal::BindStateBase*, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType); -}; - -template -class Callback : public cef_internal::CallbackBase { - public: - typedef R(RunType)(A1, A2, A3, A4); - - Callback() : CallbackBase(NULL) {} - - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template - Callback( - cef_internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &cef_internal::BindState::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); - } - - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); - } - - R Run(typename cef_internal::CallbackParamTraits::ForwardType a1, - typename cef_internal::CallbackParamTraits::ForwardType a2, - typename cef_internal::CallbackParamTraits::ForwardType a3, - typename cef_internal::CallbackParamTraits::ForwardType a4) const { - PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); - - return f(bind_state_.get(), cef_internal::CallbackForward(a1), - cef_internal::CallbackForward(a2), - cef_internal::CallbackForward(a3), - cef_internal::CallbackForward(a4)); - } - - private: - typedef R (*PolymorphicInvoke)( - cef_internal::BindStateBase*, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType); -}; - -template -class Callback : public cef_internal::CallbackBase { - public: - typedef R(RunType)(A1, A2, A3, A4, A5); - - Callback() : CallbackBase(NULL) {} - - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template - Callback( - cef_internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &cef_internal::BindState::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); - } - - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); - } - - R Run(typename cef_internal::CallbackParamTraits::ForwardType a1, - typename cef_internal::CallbackParamTraits::ForwardType a2, - typename cef_internal::CallbackParamTraits::ForwardType a3, - typename cef_internal::CallbackParamTraits::ForwardType a4, - typename cef_internal::CallbackParamTraits::ForwardType a5) const { + R Run(Args... args) && { + // Move the callback instance into a local variable before the invocation, + // that ensures the internal state is cleared after the invocation. + // It's not safe to touch |this| after the invocation, since running the + // bound function may destroy |this|. + RepeatingCallback cb = std::move(*this); PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); - - return f( - bind_state_.get(), cef_internal::CallbackForward(a1), - cef_internal::CallbackForward(a2), cef_internal::CallbackForward(a3), - cef_internal::CallbackForward(a4), cef_internal::CallbackForward(a5)); + reinterpret_cast(cb.polymorphic_invoke()); + return f(std::move(cb).bind_state_.get(), std::forward(args)...); + } + + // Then() returns a new RepeatingCallback that receives the same arguments as + // |this|, and with the return type of |then|. The + // returned callback will: + // 1) Run the functor currently bound to |this| callback. + // 2) Run the |then| callback with the result from step 1 as its single + // argument. + // 3) Return the value from running the |then| callback. + // + // If called on an rvalue (e.g. std::move(cb).Then(...)), this method + // generates a callback that is a replacement for `this`. Therefore, `this` + // will be consumed and reset to a null callback to ensure the + // originally-bound functor will be run at most once. + template + RepeatingCallback Then( + RepeatingCallback then) const& { + CHECK(then); + return BindRepeating( + cef_internal::ThenHelper< + RepeatingCallback, + RepeatingCallback>::CreateTrampoline(), + *this, std::move(then)); + } + + template + RepeatingCallback Then( + RepeatingCallback then) && { + CHECK(then); + return BindRepeating( + cef_internal::ThenHelper< + RepeatingCallback, + RepeatingCallback>::CreateTrampoline(), + std::move(*this), std::move(then)); } - - private: - typedef R (*PolymorphicInvoke)( - cef_internal::BindStateBase*, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType); }; -template -class Callback : public cef_internal::CallbackBase { - public: - typedef R(RunType)(A1, A2, A3, A4, A5, A6); - - Callback() : CallbackBase(NULL) {} - - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template - Callback( - cef_internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &cef_internal::BindState::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); - } - - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); - } - - R Run(typename cef_internal::CallbackParamTraits::ForwardType a1, - typename cef_internal::CallbackParamTraits::ForwardType a2, - typename cef_internal::CallbackParamTraits::ForwardType a3, - typename cef_internal::CallbackParamTraits::ForwardType a4, - typename cef_internal::CallbackParamTraits::ForwardType a5, - typename cef_internal::CallbackParamTraits::ForwardType a6) const { - PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); - - return f( - bind_state_.get(), cef_internal::CallbackForward(a1), - cef_internal::CallbackForward(a2), cef_internal::CallbackForward(a3), - cef_internal::CallbackForward(a4), cef_internal::CallbackForward(a5), - cef_internal::CallbackForward(a6)); - } - - private: - typedef R (*PolymorphicInvoke)( - cef_internal::BindStateBase*, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType); -}; - -template -class Callback - : public cef_internal::CallbackBase { - public: - typedef R(RunType)(A1, A2, A3, A4, A5, A6, A7); - - Callback() : CallbackBase(NULL) {} - - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template - Callback( - cef_internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &cef_internal::BindState::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); - } - - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); - } - - R Run(typename cef_internal::CallbackParamTraits::ForwardType a1, - typename cef_internal::CallbackParamTraits::ForwardType a2, - typename cef_internal::CallbackParamTraits::ForwardType a3, - typename cef_internal::CallbackParamTraits::ForwardType a4, - typename cef_internal::CallbackParamTraits::ForwardType a5, - typename cef_internal::CallbackParamTraits::ForwardType a6, - typename cef_internal::CallbackParamTraits::ForwardType a7) const { - PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); - - return f( - bind_state_.get(), cef_internal::CallbackForward(a1), - cef_internal::CallbackForward(a2), cef_internal::CallbackForward(a3), - cef_internal::CallbackForward(a4), cef_internal::CallbackForward(a5), - cef_internal::CallbackForward(a6), cef_internal::CallbackForward(a7)); - } - - private: - typedef R (*PolymorphicInvoke)( - cef_internal::BindStateBase*, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType); -}; - -// Syntactic sugar to make Callbacks easier to declare since it -// will be used in a lot of APIs with delayed execution. -typedef Callback Closure; - } // namespace base #endif // !USING_CHROMIUM_INCLUDES diff --git a/src/include/base/cef_callback_forward.h b/src/include/base/cef_callback_forward.h index d604d7cfa..2d2277433 100644 --- a/src/include/base/cef_callback_forward.h +++ b/src/include/base/cef_callback_forward.h @@ -32,14 +32,9 @@ #define INCLUDE_BASE_CEF_CALLBACK_FORWARD_H_ #pragma once -#if defined(BASE_CALLBACK_FORWARD_H_) -// Do nothing if the Chromium header has already been included. -// This can happen in cases where Chromium code is used directly by the -// client application. When using Chromium code directly always include -// the Chromium header first to avoid type conflicts. -#elif defined(USING_CHROMIUM_INCLUDES) +#if defined(USING_CHROMIUM_INCLUDES) // When building CEF include the Chromium header directly. -#include "base/callback_forward.h" +#include "base/functional/callback_forward.h" #else // !USING_CHROMIUM_INCLUDES // The following is substantially similar to the Chromium implementation. // If the Chromium implementation diverges the below implementation should be @@ -47,10 +42,19 @@ namespace base { -template -class Callback; +template +class OnceCallback; -typedef Callback Closure; +template +class RepeatingCallback; + +/// +/// Syntactic sugar to make OnceClosure and RepeatingClosure +/// easier to declare since they will be used in a lot of APIs with delayed +/// execution. +/// +using OnceClosure = OnceCallback; +using RepeatingClosure = RepeatingCallback; } // namespace base diff --git a/src/include/base/cef_callback_helpers.h b/src/include/base/cef_callback_helpers.h index ebe074a1f..5e3864405 100644 --- a/src/include/base/cef_callback_helpers.h +++ b/src/include/base/cef_callback_helpers.h @@ -32,60 +32,228 @@ // are implemented using templates, with a class per callback signature, adding // methods to Callback<> itself is unattractive (lots of extra code gets // generated). Instead, consider adding methods here. -// -// ResetAndReturn(&cb) is like cb.Reset() but allows executing a callback (via a -// copy) after the original callback is Reset(). This can be handy if Run() -// reads/writes the variable holding the Callback. #ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_HELPERS_H_ #define CEF_INCLUDE_BASE_CEF_CALLBACK_HELPERS_H_ #pragma once -#if defined(BASE_CALLBACK_HELPERS_H_) -// Do nothing if the Chromium header has already been included. -// This can happen in cases where Chromium code is used directly by the -// client application. When using Chromium code directly always include -// the Chromium header first to avoid type conflicts. -#elif defined(USING_CHROMIUM_INCLUDES) +#if defined(USING_CHROMIUM_INCLUDES) // When building CEF include the Chromium header directly. -#include "base/callback_helpers.h" +#include "base/functional/callback_helpers.h" #else // !USING_CHROMIUM_INCLUDES // The following is substantially similar to the Chromium implementation. // If the Chromium implementation diverges the below implementation should be // updated to match. -#include "include/base/cef_basictypes.h" -#include "include/base/cef_build.h" +#include +#include +#include +#include + +#include "include/base/cef_bind.h" #include "include/base/cef_callback.h" -#include "include/base/cef_macros.h" +#include "include/base/cef_logging.h" namespace base { -template -base::Callback ResetAndReturn(base::Callback* cb) { - base::Callback ret(*cb); - cb->Reset(); - return ret; +namespace internal { + +template +struct IsBaseCallbackImpl : std::false_type {}; + +template +struct IsBaseCallbackImpl> : std::true_type {}; + +template +struct IsBaseCallbackImpl> : std::true_type {}; + +template +struct IsOnceCallbackImpl : std::false_type {}; + +template +struct IsOnceCallbackImpl> : std::true_type {}; + +} // namespace internal + +/// +/// IsBaseCallback::value is true when T is any of the Closure or Callback +/// family of types. +/// +template +using IsBaseCallback = internal::IsBaseCallbackImpl>; + +/// +/// IsOnceCallback::value is true when T is a OnceClosure or OnceCallback +/// type. +/// +template +using IsOnceCallback = internal::IsOnceCallbackImpl>; + +/// +/// SFINAE friendly enabler allowing to overload methods for both Repeating and +/// OnceCallbacks. +/// +/// Usage: +///
+///   template