From 73c84b20106699db2a15bcc2b46e4b7b51d9131c Mon Sep 17 00:00:00 2001
From: cztomczak
Date: Tue, 11 Apr 2017 20:35:40 +0200
Subject: [PATCH 001/356] Update docs
---
README.md | 2 +-
api/Browser.md | 22 +++++++++++-----------
api/JavascriptCallback.md | 6 +++---
docs/Build-instructions.md | 3 +--
docs/Tutorial.md | 6 ++----
5 files changed, 18 insertions(+), 21 deletions(-)
diff --git a/README.md b/README.md
index bcf0ec45..626e25b1 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ There are many use cases for CEF. You can embed a web browser control
based on Chromium with great HTML 5 support. You can use it to create
a HTML 5 based GUI in an application, this can act as a replacement for
standard GUI toolkits such as wxWidgets, Qt or GTK. In such case to
-communicate between Python<>Javascript use [javascript bindings](api/JavascriptBindings.md)
+communicate between Python<>Javascript use [javascript bindings](docs/Tutorial.md#javascript-integration)
or embed an internal web server and talk using http requests. You
can render web content off-screen in applications that use custom
drawing frameworks. You can use it for automated testing of existing
diff --git a/api/Browser.md b/api/Browser.md
index 58e56698..623e5c53 100644
--- a/api/Browser.md
+++ b/api/Browser.md
@@ -3,20 +3,14 @@
# Browser (object)
-Remember to free all browser references for the browser to shut down cleanly.
+Remember to free all browser references when closing app
+for the browser to shut down cleanly.
Otherwise data such as cookies or other storage might not be flushed to disk
-when closing app, and other issues might occur as well. If you store
-a reference to Frame somewhere in your code then to free it just assign
-a None value to the variable.
+when closing app, and other issues might occur as well. To free a reference
+just assign a None value to a browser variable.
To compare browser objects always use [GetIdentifier()](#getidentifier)
-method. Do not compare two Browser objects variables directly. There
-are some edge cases when after the OnBeforeClose event browser objects
-are no more globally referenced thus a new instance is created that
-wraps upstream CefBrowser object. Browser objects that were globally
-unreferenced do not have properties of the original Browser object,
-for example they do not have client callbacks, javascript bindings
-or user data set.
+method. Do not compare two Browser objects variables directly.
Table of contents:
@@ -107,6 +101,12 @@ Methods available in upstream CEF which were not yet exposed in CEF Python
* ImeFinishComposingText
* ImeCancelComposition
+There are some edge cases when after the OnBeforeClose event browser objects
+are no more globally referenced thus a new instance is created that
+wraps upstream CefBrowser object. Browser objects that were globally
+unreferenced do not have properties of the original Browser object,
+for example they do not have client callbacks, javascript bindings
+or user data set.
## Methods
diff --git a/api/JavascriptCallback.md b/api/JavascriptCallback.md
index 97b3bc06..9f98f272 100644
--- a/api/JavascriptCallback.md
+++ b/api/JavascriptCallback.md
@@ -27,10 +27,10 @@ Table of contents:
| Parameter | Type |
| --- | --- |
-| [params..] | mixed |
-| __Return__ | mixed |
+| [params..] (optional) | mixed |
+| __Return__ | void |
-Call the javascript callback function.
+Call the javascript callback function. Pass arguments optionally.
For a list of allowed types for `mixed` see JavascriptBindings.[IsValueAllowed()](JavascriptBindings.md#isvalueallowed).
diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md
index c35ac91a..1b1811f2 100644
--- a/docs/Build-instructions.md
+++ b/docs/Build-instructions.md
@@ -22,8 +22,7 @@ Table of contents:
## Preface
These instructions are for the new releases of CEF Python v50+.
-For the old v31 release that is supported on all platforms, see
-the build instructions on the wiki pages.
+For the old v31 release see the build instructions on Wiki pages.
If you would like to quickly build cefpython then see the
[Quick build instructions for Windows](#quick-build-instructions-for-windows)
diff --git a/docs/Tutorial.md b/docs/Tutorial.md
index 9abd7c13..f7875782 100644
--- a/docs/Tutorial.md
+++ b/docs/Tutorial.md
@@ -268,7 +268,8 @@ Examples switches:
- "proxy-server" - to set proxy server
- "disable-gpu" - use only CPU software rendering
-Example code:
+Note that when setting switch that doesn't accept value then
+must pass an empty string as value. Example code:
```python
switches = {
@@ -279,9 +280,6 @@ switches = {
cef.Initialize(switches=switches)
```
-Note that when setting switch that doesn't accept value then
-must pass an empty string as value.
-
**Chromium preferences**
From 8afe4c2ecb8cd3c0d1ae5ad09d61ba503d943ece Mon Sep 17 00:00:00 2001
From: cztomczak
Date: Fri, 14 Apr 2017 08:37:29 +0200
Subject: [PATCH 002/356] Update docs
---
README.md | 18 ++++++++++--------
api/API-index.md | 4 +++-
api/Browser.md | 8 ++++----
api/cefpython.md | 14 ++++++--------
docs/Knowledge-Base.md | 6 ++++--
5 files changed, 27 insertions(+), 23 deletions(-)
diff --git a/README.md b/README.md
index 626e25b1..be05b9e2 100644
--- a/README.md
+++ b/README.md
@@ -68,7 +68,7 @@ See the [Examples-README.md](examples/Examples-README.md) file.
- API reference is in the [api/](api) directory:
- [API categories](api/API-categories.md#api-categories)
- [API index](api/API-index.md#api-index)
-- Additional documentation is in issues labelled [Knowledge Base](../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22)
+- Additional documentation is available in [Issues labelled Knowledge Base](../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22)
- To search documentation use GitHub "This repository" search
at the top. To narrow results to documentation only select
"Markdown" in the right pane.
@@ -155,8 +155,8 @@ directly.
- [Tutorial](docs/Tutorial.md)
-### API categories
-
+### API categories
+
#### Modules
* [cefpython](api/cefpython.md#cefpython) module
@@ -190,7 +190,7 @@ directly.
* [WindowUtils](api/WindowUtils.md#windowutils-class) class
-#### Handlers (interfaces)
+#### Client handlers (interfaces)
* [DisplayHandler](api/DisplayHandler.md#displayhandler-interface)
* [DownloadHandler](api/DownloadHandler.md#downloadhandler)
@@ -211,9 +211,9 @@ directly.
* [StringVisitor](api/StringVisitor.md#stringvisitor-interface) interface
* [WebRequestClient](api/WebRequestClient.md#webrequestclient-interface) interface
-
-### API index
-
+
+### API index
+
* [Application settings](api/ApplicationSettings.md#application-settings)
* [accept_language_list](api/ApplicationSettings.md#accept_language_list)
* [auto_zooming](api/ApplicationSettings.md#auto_zooming)
@@ -475,7 +475,9 @@ directly.
* [SetProperty](api/JavascriptBindings.md#setproperty)
* [JavascriptCallback (object)](api/JavascriptCallback.md#javascriptcallback-object)
* [Call](api/JavascriptCallback.md#call)
- * [GetName](api/JavascriptCallback.md#getname)
+ * [GetFrame](api/JavascriptCallback.md#getframe)
+ * [GetId](api/JavascriptCallback.md#getid)
+ * [GetFunctionName](api/JavascriptCallback.md#getfunctionname)
* [JavascriptDialogHandler (interface)](api/JavascriptDialogHandler.md#javascriptdialoghandler-interface)
* [Continue](api/JavascriptDialogHandler.md#continue)
* [OnJavascriptDialog](api/JavascriptDialogHandler.md#onjavascriptdialog)
diff --git a/api/API-index.md b/api/API-index.md
index df2dc4bd..a1ab99c2 100644
--- a/api/API-index.md
+++ b/api/API-index.md
@@ -263,7 +263,9 @@
* [SetProperty](JavascriptBindings.md#setproperty)
* [JavascriptCallback (object)](JavascriptCallback.md#javascriptcallback-object)
* [Call](JavascriptCallback.md#call)
- * [GetName](JavascriptCallback.md#getname)
+ * [GetFrame](JavascriptCallback.md#getframe)
+ * [GetId](JavascriptCallback.md#getid)
+ * [GetFunctionName](JavascriptCallback.md#getfunctionname)
* [JavascriptDialogHandler (interface)](JavascriptDialogHandler.md#javascriptdialoghandler-interface)
* [Continue](JavascriptDialogHandler.md#continue)
* [OnJavascriptDialog](JavascriptDialogHandler.md#onjavascriptdialog)
diff --git a/api/Browser.md b/api/Browser.md
index 623e5c53..807b0cd1 100644
--- a/api/Browser.md
+++ b/api/Browser.md
@@ -169,7 +169,7 @@ Explicitly close the associated DevTools browser, if any.
### DragTargetDragEnter
-| | |
+| Parameter | Type |
| --- | --- |
| drag_data | [DragData](DragData.md) |
| x | int |
@@ -189,7 +189,7 @@ Description from upstream CEF:
### DragTargetDragOver
-| | |
+| Parameter | Type |
| --- | --- |
| x | int |
| y | int |
@@ -217,7 +217,7 @@ Description from upstream CEF:
### DragTargetDrop
-| | |
+| Parameter | Type |
| --- | --- |
| x | int |
| y | int |
@@ -233,7 +233,7 @@ Description from upstream CEF:
### DragSourceEndedAt
-| | |
+| Parameter | Type |
| --- | --- |
| x | int |
| y | int |
diff --git a/api/cefpython.md b/api/cefpython.md
index 3409d8b4..d93a16e3 100644
--- a/api/cefpython.md
+++ b/api/cefpython.md
@@ -34,11 +34,10 @@ Table of contents:
### CreateBrowser
-Create browser asynchronously (does not return Browser object).
-See `CreateBrowserSync()` for params list.
-
-NOTE: currently this is just an alias and actually creates browser
-synchronously. The async call to CefCreateBrowser is yet TODO.
+Not yet implemented - currently this method just calls [CreateBrowserSync](#createbrowsersync).
+In upstream CEF this method creates browser asynchronously. Currently
+CEF Python depends on browser being created synchronously in a few parts
+of code.
### CreateBrowserSync
@@ -82,8 +81,7 @@ This hook does the following: in case of exception write it to
the "error.log" file, display it to the console, shutdown CEF
and exit application immediately by ignoring "finally" (_exit()).
-If you would like to implement a custom hook take a look at the
-source code of ExceptHook in the cefpython/src/helpers.pyx file.
+See also Tutorial: [Handling Python exceptions](../docs/Tutorial.md#handling-python-exceptions).
### GetAppSetting
@@ -233,7 +231,7 @@ Description from upstream CEF:
| --- | --- |
| threadId | int |
| func | object |
-| ... | *args |
+| [args..] | mixed |
| __Return__ | void |
Post a task for execution on the thread associated with this task runner. Execution will occur asynchronously. Only Browser process threads are allowed.
diff --git a/docs/Knowledge-Base.md b/docs/Knowledge-Base.md
index fb9ea865..83d4b679 100644
--- a/docs/Knowledge-Base.md
+++ b/docs/Knowledge-Base.md
@@ -1,7 +1,7 @@
# Knowledge Base
Table of contents:
-* [Notifications on new releases](#notifications-on-new-releases)
+* [Notifications about new releases / commits](#notifications-about-new-releases-commits)
* [Changes in API after CEF updates](#changes-in-api-after-cef-updates)
* [Differences between Python 2 and Python 3](#differences-between-python-2-and-python-3)
* [Location of CEF framework in Mac apps](#location-of-cef-framework-in-mac-apps)
@@ -17,7 +17,7 @@ Table of contents:
* [Security](#security)
-## Notifications on new releases
+## Notifications about new releases / commits
To be notified of new releases subscribe to this [RSS/Atom feed](../../../releases.atom).
@@ -25,6 +25,8 @@ Announcements are also made on the [Forum](https://groups.google.com/d/forum/cef
To be notified of these via email set your Membership and Email settings
and change delivery preference to Daily summaries.
+To be notified on new commits subscribe to this [RSS/Atom feed](../../commits/master.atom).
+
## Changes in API after CEF updates
From 7a418c4b3f1f2560c87bac1b97ec1a4b12941bf9 Mon Sep 17 00:00:00 2001
From: cztomczak
Date: Fri, 14 Apr 2017 08:41:34 +0200
Subject: [PATCH 003/356] Update toc.py
---
docs/Knowledge-Base.md | 2 +-
tools/toc.py | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/docs/Knowledge-Base.md b/docs/Knowledge-Base.md
index 83d4b679..93733cd3 100644
--- a/docs/Knowledge-Base.md
+++ b/docs/Knowledge-Base.md
@@ -1,7 +1,7 @@
# Knowledge Base
Table of contents:
-* [Notifications about new releases / commits](#notifications-about-new-releases-commits)
+* [Notifications about new releases / commits](#notifications-about-new-releases--commits)
* [Changes in API after CEF updates](#changes-in-api-after-cef-updates)
* [Differences between Python 2 and Python 3](#differences-between-python-2-and-python-3)
* [Location of CEF framework in Mac apps](#location-of-cef-framework-in-mac-apps)
diff --git a/tools/toc.py b/tools/toc.py
index a9749d35..e00754c1 100644
--- a/tools/toc.py
+++ b/tools/toc.py
@@ -168,11 +168,13 @@ def headinghash(title):
"""Get a link hash for a heading H1,H2,H3."""
hash_ = title.lower()
hash_ = hash_.replace(" - ", "specialcase1")
+ hash_ = hash_.replace(" / ", "specialcase2")
hash_ = re.sub(r"[^a-z0-9_\- ]+", r"", hash_)
hash_ = hash_.replace(" ", "-")
hash_ = re.sub(r"[-]+", r"-", hash_)
hash_ = re.sub(r"-$", r"", hash_)
hash_ = hash_.replace("specialcase1", "---")
+ hash_ = hash_.replace("specialcase2", "--")
return hash_
From e96ae89e1091f5326a121d7bc2c1825686ca67eb Mon Sep 17 00:00:00 2001
From: cztomczak
Date: Fri, 14 Apr 2017 08:42:47 +0200
Subject: [PATCH 004/356] Fix link
---
docs/Knowledge-Base.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/Knowledge-Base.md b/docs/Knowledge-Base.md
index 93733cd3..5361122d 100644
--- a/docs/Knowledge-Base.md
+++ b/docs/Knowledge-Base.md
@@ -25,7 +25,7 @@ Announcements are also made on the [Forum](https://groups.google.com/d/forum/cef
To be notified of these via email set your Membership and Email settings
and change delivery preference to Daily summaries.
-To be notified on new commits subscribe to this [RSS/Atom feed](../../commits/master.atom).
+To be notified on new commits subscribe to this [RSS/Atom feed](../../../commits/master.atom).
## Changes in API after CEF updates
From a529208618eb2e6eaae2bb39ec4f383712192c83 Mon Sep 17 00:00:00 2001
From: cztomczak
Date: Fri, 14 Apr 2017 11:14:06 +0100
Subject: [PATCH 005/356] Update comment regarding msvc9_query_vcvarsall
(pypa/setuptools/issues/992)
---
tools/automate.py | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/tools/automate.py b/tools/automate.py
index cb97d8d2..741242b8 100644
--- a/tools/automate.py
+++ b/tools/automate.py
@@ -492,8 +492,9 @@ def build_wrapper_library_windows(runtime_library, msvs, vcvars):
# When Using WinSDK 7.1 vcvarsall.bat doesn't work. Use
# setuptools.msvc.msvc9_query_vcvarsall to query env vars.
env.update(msvc9_query_vcvarsall(10.0, arch=VS_PLATFORM_ARG))
- # On Python 2.7 64-bit env values returned by setuptools
- # are unicode. On 32-bit they are strings.
+ # On Python 2.7 env values returned by both distutils
+ # and setuptools are unicode, but Python expects env
+ # dict values as strings.
for env_key in env:
env_value = env[env_key]
if type(env_value) != str:
From f7398c2c51d74c211a174db07dce174846e5812a Mon Sep 17 00:00:00 2001
From: cztomczak
Date: Fri, 14 Apr 2017 11:26:41 +0100
Subject: [PATCH 006/356] Fix error WindowInfo.windowName == NoneType when
running unit tests on Windows
---
src/window_info.pyx | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/window_info.pyx b/src/window_info.pyx
index 2ac24df7..a2e0f251 100644
--- a/src/window_info.pyx
+++ b/src/window_info.pyx
@@ -78,6 +78,7 @@ cdef class WindowInfo:
def __init__(self, title=""):
self.transparentPainting = False
+ self.windowName = ""
if title:
self.windowName = title
From 5caa06123764d3f18ee85c3443430c961de4d3f2 Mon Sep 17 00:00:00 2001
From: cztomczak
Date: Fri, 14 Apr 2017 13:14:30 +0100
Subject: [PATCH 007/356] Use VS2008 to build subprocess.exe to avoid false
positives by AVs (#342)
---
README.md | 12 +++----
src/compile_time_constants.pxi | 4 +--
tools/build.py | 7 +++-
tools/build_distrib.py | 62 ++++++++++++++++++++++++++++++----
tools/run_examples.py | 1 +
5 files changed, 71 insertions(+), 15 deletions(-)
diff --git a/README.md b/README.md
index be05b9e2..114d2d35 100644
--- a/README.md
+++ b/README.md
@@ -62,7 +62,7 @@ See the [Examples-README.md](examples/Examples-README.md) file.
- Supported examples are listed in the [Examples-README.md](examples/Examples-README.md) file
- Documentation is in the [docs/](docs) directory:
- [Build instructions](docs/Build-instructions.md)
- - [Knowledge base](docs/Knowledge-Base.md)
+ - [Knowledge Base](docs/Knowledge-Base.md)
- [Migration guide](docs/Migration-guide.md)
- [Tutorial](docs/Tutorial.md)
- API reference is in the [api/](api) directory:
@@ -155,8 +155,8 @@ directly.
- [Tutorial](docs/Tutorial.md)
-### API categories
-
+### API categories
+
#### Modules
* [cefpython](api/cefpython.md#cefpython) module
@@ -211,9 +211,9 @@ directly.
* [StringVisitor](api/StringVisitor.md#stringvisitor-interface) interface
* [WebRequestClient](api/WebRequestClient.md#webrequestclient-interface) interface
-
-### API index
-
+
+### API index
+
* [Application settings](api/ApplicationSettings.md#application-settings)
* [accept_language_list](api/ApplicationSettings.md#accept_language_list)
* [auto_zooming](api/ApplicationSettings.md#auto_zooming)
diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi
index 35f85002..632aab59 100644
--- a/src/compile_time_constants.pxi
+++ b/src/compile_time_constants.pxi
@@ -1,3 +1,3 @@
# This file was generated by setup.py
-DEF UNAME_SYSNAME = "Linux"
-DEF PY_MAJOR_VERSION = 2
+DEF UNAME_SYSNAME = "Windows"
+DEF PY_MAJOR_VERSION = 3
diff --git a/tools/build.py b/tools/build.py
index 1d32dcf1..3e4f0f8b 100644
--- a/tools/build.py
+++ b/tools/build.py
@@ -879,7 +879,12 @@ def delete_directory_reliably(adir):
print("[build.py] Delete directory: {dir}"
.format(dir=adir.replace(ROOT_DIR, "")))
if WINDOWS:
- shutil.rmtree(adir)
+ # rmtree is vulnerable to race conditions. Sometimes
+ # deleting directory fails with error:
+ # >> OSError: [WinError 145] The directory is not empty:
+ # >> 'C:\\github\\cefpython\\build\\cefpython3_56.2_win64\\build\\
+ # >> lib\\cefpython3'
+ shutil.rmtree(adir, ignore_errors=True)
else:
# On Linux sudo might be required to delete directory, as this
# might be a setup installer directory with package installed
diff --git a/tools/build_distrib.py b/tools/build_distrib.py
index 7466caf8..f2635df2 100644
--- a/tools/build_distrib.py
+++ b/tools/build_distrib.py
@@ -44,7 +44,8 @@
7. Reduce packages size (Issue #321). After packing prebuilt binaries,
reduce its size so that packages will use the reduced prebuilt binaries.
8. Build cefpython modules for all supported Python versions on both
- 32-bit and 64-bit
+ 32-bit and 64-bit. Backup and restore subprocess executable on Windows
+ built with Python 2.7 (Issue #342).
9. Make setup installers and pack them to zip (Win/Mac) or .tar.gz (Linux)
10. Make wheel packages
11. Move setup and wheel packages to the build/distrib/ directory
@@ -129,7 +130,8 @@ def main():
reduce_package_size_issue_262("64bit")
remove_unnecessary_package_files("64bit")
if not NO_REBUILD:
- build_cefpython_modules(pythons_32bit + pythons_64bit)
+ build_cefpython_modules(pythons_32bit, "32bit")
+ build_cefpython_modules(pythons_64bit, "64bit")
if pythons_32bit:
make_packages(pythons_32bit[0], "32bit")
if pythons_64bit:
@@ -439,7 +441,7 @@ def remove_unnecessary_package_files(arch):
delete_cef_sample_apps(caller_script=__file__, bin_dir=bin_dir)
-def build_cefpython_modules(pythons):
+def build_cefpython_modules(pythons, arch):
for python in pythons:
print("[build_distrib.py] Build cefpython module for {python_name}"
.format(python_name=python["name"]))
@@ -461,14 +463,62 @@ def build_cefpython_modules(pythons):
sys.exit(1)
print("[build_distrib.py] Built successfully cefpython module for"
" {python_name}".format(python_name=python["name"]))
- print("[build_distrib.py] Successfully built cefpython modules for"
- " all Python versions")
+ # Issue #342
+ backup_subprocess_executable_issue342(python)
+
+ # Issue #342
+ restore_subprocess_executable_issue342(arch)
+
+ print("[build_distrib.py] Successfully built cefpython modules for {arch}"
+ .format(arch=arch))
+
+
+def backup_subprocess_executable_issue342(python):
+ """Use subprocess executable build by Python 2.7 to avoid
+ false-positives by AVs when building subprocess with Python 3.
+ Windows-only issue."""
+ if not WINDOWS:
+ return
+ if python["version2"] == (2, 7):
+ print("[build_distrib.py] Backup subprocess executable built"
+ " with Python 2.7 (Issue #342)")
+ cefpython_binary_basename = get_cefpython_binary_basename(
+ get_os_postfix2_for_arch(python["arch"]))
+ cefpython_binary = os.path.join(BUILD_DIR, cefpython_binary_basename)
+ assert os.path.isdir(cefpython_binary)
+ src = os.path.join(cefpython_binary, "subprocess.exe")
+ dst = os.path.join(BUILD_CEFPYTHON,
+ "subprocess_py27_{arch}_issue342.exe"
+ .format(arch=python["arch"]))
+ shutil.copy(src, dst)
+
+
+def restore_subprocess_executable_issue342(arch):
+ """Use subprocess executable build by Python 2.7 to avoid
+ false-positives by AVs when building subprocess with Python 3.
+ Windows-only issue."""
+ if not WINDOWS:
+ return
+ print("[build_distrib.py] Restore subprocess executable built"
+ " with Python 2.7 (Issue #342)")
+ cefpython_binary_basename = get_cefpython_binary_basename(
+ get_os_postfix2_for_arch(arch))
+ cefpython_binary = os.path.join(BUILD_DIR, cefpython_binary_basename)
+ assert os.path.isdir(cefpython_binary)
+ src = os.path.join(BUILD_CEFPYTHON,
+ "subprocess_py27_{arch}_issue342.exe"
+ .format(arch=arch))
+ assert os.path.isfile(src)
+ dst = os.path.join(cefpython_binary, "subprocess.exe")
+ shutil.copy(src, dst)
def make_packages(python, arch):
- # Make setup package
+ """Make setup and wheel packages."""
print("[build_distrib.py] Make setup package for {arch}..."
.format(arch=arch))
+
+ # Call make_installer.py
make_installer_py = os.path.join(TOOLS_DIR, "make_installer.py")
installer_command = ("\"{python}\" {make_installer_py} {version}"
.format(python=python["executable"],
diff --git a/tools/run_examples.py b/tools/run_examples.py
index a4a1f0bb..241a9417 100644
--- a/tools/run_examples.py
+++ b/tools/run_examples.py
@@ -36,6 +36,7 @@ def main():
packages = check_installed_packages()
examples = list()
examples.append("hello_world.py")
+ examples.append("tutorial.py")
succeeded = list()
failed = list()
passed = list()
From 15231195385407305d9517563b21809fd5912fc5 Mon Sep 17 00:00:00 2001
From: cztomczak
Date: Tue, 18 Apr 2017 07:41:19 +0200
Subject: [PATCH 008/356] Update wxpython.py example for wxPython 4.0 (#348).
Thanks to Andrew Leech for the patch.
---
docs/Tutorial.md | 7 +++----
examples/wxpython.py | 5 +++--
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/docs/Tutorial.md b/docs/Tutorial.md
index f7875782..bbd3054b 100644
--- a/docs/Tutorial.md
+++ b/docs/Tutorial.md
@@ -7,8 +7,8 @@ a replacement for standard GUI toolkits such as wxWidgets,
Qt or GTK. With this tutorial you will learn CEF Python
basics. This tutorial will discuss the two basic examples:
[hello_world.py](../examples/hello_world.py)
-and [tutorial.py](../examples/tutorial.py). There are more
-many more examples that you can find in the [Examples-README.md](../examples/Examples-README.md)
+and [tutorial.py](../examples/tutorial.py). There are many
+more examples that you can find in the [Examples-README.md](../examples/Examples-README.md)
file, but these examples are out of scope for this tutorial.
@@ -33,8 +33,7 @@ You can install with pip. On Linux pip 8.1+ is required. Alternatively
you can download packages for offline installation from [GitHub Releases](../../../releases).
Run the commands below to install the cefpython3 package, clone
-the github repository, enter the examples/ directory and run the
-Hello World example:
+the repository and run the Hello World example:
```commandline
pip install cefpython3==56.1
diff --git a/examples/wxpython.py b/examples/wxpython.py
index bc5ccf49..4dc733b4 100644
--- a/examples/wxpython.py
+++ b/examples/wxpython.py
@@ -109,7 +109,7 @@ def create_menu(self):
def embed_browser(self):
window_info = cef.WindowInfo()
- (width, height) = self.browser_panel.GetClientSizeTuple()
+ (width, height) = self.browser_panel.GetClientSize().Get()
window_info.SetAsChild(self.browser_panel.GetHandle(),
[0, 0, width, height])
self.browser = cef.CreateBrowserSync(window_info,
@@ -197,14 +197,15 @@ def create_timer(self):
# http://wiki.wxwidgets.org/Making_a_render_loop
# Another way would be to use EVT_IDLE in MainFrame.
self.timer = wx.Timer(self, self.timer_id)
+ self.Bind(wx.EVT_TIMER, self.on_timer, self.timer)
self.timer.Start(10) # 10ms timer
- wx.EVT_TIMER(self, self.timer_id, self.on_timer)
def on_timer(self, _):
cef.MessageLoopWork()
def OnExit(self):
self.timer.Stop()
+ return 0
if __name__ == '__main__':
From e74777a6b2b6c9f98dc70a7d1a58dc5027129c32 Mon Sep 17 00:00:00 2001
From: cztomczak
Date: Tue, 18 Apr 2017 08:14:48 +0200
Subject: [PATCH 009/356] On Linux it is required to show window before
embedding browser (#347)
---
examples/gtk2.py | 6 ++++--
examples/wxpython.py | 2 +-
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/examples/gtk2.py b/examples/gtk2.py
index 99d7cc14..981c422e 100644
--- a/examples/gtk2.py
+++ b/examples/gtk2.py
@@ -96,10 +96,12 @@ def __init__(self):
self.vbox.pack_start(self.menubar, False, False, 0)
self.main_window.add(self.vbox)
- self.embed_browser()
-
+ # On Linux must show window first before embedding browser
+ # (Issue #347).
self.vbox.show()
self.main_window.show()
+ self.embed_browser()
+
self.vbox.get_window().focus()
self.main_window.get_window().focus()
if g_message_loop == MESSAGE_LOOP_TIMER:
diff --git a/examples/wxpython.py b/examples/wxpython.py
index 4dc733b4..069a312b 100644
--- a/examples/wxpython.py
+++ b/examples/wxpython.py
@@ -84,7 +84,7 @@ def __init__(self):
self.browser_panel.Bind(wx.EVT_SIZE, self.OnSize)
# On Linux must show before embedding browser, so that handle
- # is available.
+ # is available (Issue #347).
if LINUX:
self.Show()
self.embed_browser()
From b3591290715dd87606c1dfc12400bc2d492de91d Mon Sep 17 00:00:00 2001
From: cztomczak
Date: Tue, 18 Apr 2017 09:00:20 +0200
Subject: [PATCH 010/356] Fix wxpython.py example on Linux for wxPython 3.0/4.0
(#349)
wx.IconFromBitmap is not available on Linux.
---
examples/wxpython.py | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/examples/wxpython.py b/examples/wxpython.py
index 069a312b..416805ce 100644
--- a/examples/wxpython.py
+++ b/examples/wxpython.py
@@ -87,7 +87,14 @@ def __init__(self):
# is available (Issue #347).
if LINUX:
self.Show()
- self.embed_browser()
+ # In wxPython 3.0 and wxPython 4.0 handle is still
+ # not yet available, must delay embedding browser
+ # (Issue #349).
+ if wx.version().startswith("3.") or wx.version().startswith("4."):
+ wx.CallLater(20, self.embed_browser)
+ else:
+ # This works fine in wxPython 2.8
+ self.embed_browser()
else:
self.embed_browser()
self.Show()
@@ -95,7 +102,8 @@ def __init__(self):
def setup_icon(self):
icon_file = os.path.join(os.path.abspath(os.path.dirname(__file__)),
"resources", "wxpython.png")
- if os.path.exists(icon_file):
+ # wx.IconFromBitmap is not available on Linux in wxPython 3.0/4.0
+ if os.path.exists(icon_file) and hasattr(wx, "IconFromBitmap"):
icon = wx.IconFromBitmap(wx.Bitmap(icon_file, wx.BITMAP_TYPE_PNG))
self.SetIcon(icon)
@@ -132,7 +140,7 @@ def OnSize(self, _):
0, 0, 0)
elif LINUX:
(x, y) = (0, 0)
- (width, height) = self.browser_panel.GetSizeTuple()
+ (width, height) = self.browser_panel.GetSize().Get()
self.browser.SetBounds(x, y, width, height)
self.browser.NotifyMoveOrResizeStarted()
From 7c3ffb5dbf59c3c3b9e92cbcc31759075d19b2dd Mon Sep 17 00:00:00 2001
From: cztomczak
Date: Tue, 18 Apr 2017 15:11:11 +0200
Subject: [PATCH 011/356] Fix wxpython.py example running wxPython 4.0 on Mac
(#350).
Fix searching for Python.h include file when building with
system Python 3 on Mac.
---
examples/wxpython.py | 19 ++++++++++++++++++-
src/compile_time_constants.pxi | 2 +-
tools/common.py | 2 ++
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/examples/wxpython.py b/examples/wxpython.py
index 416805ce..2a5fbafe 100644
--- a/examples/wxpython.py
+++ b/examples/wxpython.py
@@ -191,14 +191,31 @@ class CefApp(wx.App):
def __init__(self, redirect):
self.timer = None
self.timer_id = 1
+ self.is_initialized = False
super(CefApp, self).__init__(redirect=redirect)
+ def OnPreInit(self):
+ super(CefApp, self).OnPreInit()
+ # On Mac with wxPython 4.0 the OnInit() event never gets
+ # called. Doing wx window creation in OnPreInit() seems to
+ # resolve the problem (Issue #350).
+ if MAC and wx.version().startswith("4."):
+ print("[wxpython.py] OnPreInit: initialize here"
+ " (wxPython 4.0 fix)")
+ self.initialize()
+
def OnInit(self):
+ self.initialize()
+ return True
+
+ def initialize(self):
+ if self.is_initialized:
+ return
self.create_timer()
frame = MainFrame()
self.SetTopWindow(frame)
frame.Show()
- return True
+ self.initialized = True
def create_timer(self):
# See also "Making a render loop":
diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi
index 632aab59..457e4a58 100644
--- a/src/compile_time_constants.pxi
+++ b/src/compile_time_constants.pxi
@@ -1,3 +1,3 @@
# This file was generated by setup.py
-DEF UNAME_SYSNAME = "Windows"
+DEF UNAME_SYSNAME = "Darwin"
DEF PY_MAJOR_VERSION = 3
diff --git a/tools/common.py b/tools/common.py
index c6b88648..386979c9 100644
--- a/tools/common.py
+++ b/tools/common.py
@@ -242,6 +242,8 @@ def get_python_include_path():
try_dirs = ["{base_dir}/include",
"{base_dir}/../include/python{ver}",
"{base_dir}/../include/python{ver}*",
+ ("{base_dir}/../Frameworks/Python.framework/Versions/{ver}"
+ "/include/python{ver}*"),
"/usr/include/python{ver}"]
ver_tuple = sys.version_info[:2]
ver = "{major}.{minor}".format(major=ver_tuple[0], minor=ver_tuple[1])
From b438b3edeb6a069e022bcc217cefdb6e0c9b85b8 Mon Sep 17 00:00:00 2001
From: cztomczak
Date: Tue, 18 Apr 2017 15:14:03 +0200
Subject: [PATCH 012/356] Add comment on new tested configurations in
wxpython.py example
---
examples/wxpython.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/examples/wxpython.py b/examples/wxpython.py
index 2a5fbafe..01536a87 100644
--- a/examples/wxpython.py
+++ b/examples/wxpython.py
@@ -4,6 +4,7 @@
# To install wxPython on Linux type "sudo apt-get install python-wxtools".
# Tested configurations:
+# - wxPython 4.0 on Windows/Mac/Linux
# - wxPython 3.0 on Windows/Mac
# - wxPython 2.8 on Linux
# - CEF Python v55.4+
From 8c5904a1c7ee0b78e074572c2cf0fff2b43a766c Mon Sep 17 00:00:00 2001
From: cztomczak
Date: Tue, 18 Apr 2017 15:26:30 +0200
Subject: [PATCH 013/356] Fix typo in wxpython.py example
---
examples/wxpython.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/examples/wxpython.py b/examples/wxpython.py
index 01536a87..f03da5e0 100644
--- a/examples/wxpython.py
+++ b/examples/wxpython.py
@@ -212,11 +212,11 @@ def OnInit(self):
def initialize(self):
if self.is_initialized:
return
+ self.is_initialized = True
self.create_timer()
frame = MainFrame()
self.SetTopWindow(frame)
frame.Show()
- self.initialized = True
def create_timer(self):
# See also "Making a render loop":
From 896b0dfdf2e99dde094221828976d1f8d43325f8 Mon Sep 17 00:00:00 2001
From: cztomczak
Date: Wed, 19 Apr 2017 15:20:10 +0200
Subject: [PATCH 014/356] Use CEF logging functions (#352) and others (#351,
#277)...
Fix logging command line string for sub-processes (#351).
Remove CefExecuteProcess call in cef.Initialize. This call should
happen only in subprocess main.cpp.
---
api/ApplicationSettings.md | 4 +-
docs/Knowledge-Base.md | 8 +-
docs/Tutorial.md | 2 +-
examples/wxpython.py | 6 +-
src/cefpython.pyx | 30 +--
src/client_handler/Makefile | 1 +
src/client_handler/cef_log.cpp | 17 ++
src/client_handler/cef_log.h | 9 +
src/client_handler/client_handler.cpp | 29 +--
src/client_handler/context_menu_handler.cpp | 9 +-
...eprecated_client_handler_py27_64bit.vcproj | 0
...precated_client_handler_py27_win32.vcproj} | 0
...eprecated_client_handler_py34_32bit.vcproj | 0
src/client_handler/dialog_handler_gtk.cpp | 4 +-
src/client_handler/download_handler.cpp | 15 +-
src/client_handler/dpi_aware.cpp | 49 ++--
src/client_handler/lifespan_handler.cpp | 6 +-
.../request_context_handler.cpp | 1 -
src/client_handler/request_handler.cpp | 4 +-
src/client_handler/x11.cpp | 4 +-
src/common/DebugLog.h | 24 --
src/common/LOG_DEBUG.h | 211 ------------------
src/compile_time_constants.pxi | 4 +-
src/extern/cef_log.pxd | 8 +
src/handlers/browser_process_handler.pyx | 2 -
src/linux/binaries_64bit/kivy_.py | 3 -
src/subprocess/cefpython_app.cpp | 160 ++++++-------
src/subprocess/cefpython_app.h | 7 +-
...precated_libcefpythonapp_py27_64bit.vcproj | 0
...recated_libcefpythonapp_py27_win32.vcproj} | 0
...precated_libcefpythonapp_py34_32bit.vcproj | 0
.../deprecated_subprocess_64bit.vcproj | 0
.../deprecated_subprocess_win32.vcproj} | 0
src/subprocess/javascript_callback.cpp | 22 +-
src/subprocess/v8function_handler.cpp | 12 +-
src/subprocess/v8utils.cpp | 85 +++----
src/utils.pyx | 28 +--
tools/cython_setup.py | 18 +-
38 files changed, 293 insertions(+), 489 deletions(-)
create mode 100644 src/client_handler/cef_log.cpp
create mode 100644 src/client_handler/cef_log.h
rename src/client_handler/{ => deprecated}/deprecated_client_handler_py27_64bit.vcproj (100%)
rename src/client_handler/{client_handler_py27_win32.vcproj => deprecated/deprecated_client_handler_py27_win32.vcproj} (100%)
rename src/client_handler/{ => deprecated}/deprecated_client_handler_py34_32bit.vcproj (100%)
delete mode 100644 src/common/DebugLog.h
delete mode 100644 src/common/LOG_DEBUG.h
create mode 100644 src/extern/cef_log.pxd
rename src/subprocess/{ => deprecated}/deprecated_libcefpythonapp_py27_64bit.vcproj (100%)
rename src/subprocess/{libcefpythonapp_py27_win32.vcproj => deprecated/deprecated_libcefpythonapp_py27_win32.vcproj} (100%)
rename src/subprocess/{ => deprecated}/deprecated_libcefpythonapp_py34_32bit.vcproj (100%)
rename src/subprocess/{ => deprecated}/deprecated_subprocess_64bit.vcproj (100%)
rename src/subprocess/{subprocess_win32.vcproj => deprecated/deprecated_subprocess_win32.vcproj} (100%)
diff --git a/api/ApplicationSettings.md b/api/ApplicationSettings.md
index 390b3905..4dc0ff11 100644
--- a/api/ApplicationSettings.md
+++ b/api/ApplicationSettings.md
@@ -287,9 +287,9 @@ a value of "verbose", "info", "warning", "error", "error-report" or
Accepted values - constants available in the cefpython module:
* LOGSEVERITY_VERBOSE
-* LOGSEVERITY_INFO (default)
+* LOGSEVERITY_INFO
* LOGSEVERITY_WARNING
-* LOGSEVERITY_ERROR
+* LOGSEVERITY_ERROR (default)
* LOGSEVERITY_ERROR_REPORT
* LOGSEVERITY_DISABLE
diff --git a/docs/Knowledge-Base.md b/docs/Knowledge-Base.md
index 5361122d..af38bd94 100644
--- a/docs/Knowledge-Base.md
+++ b/docs/Knowledge-Base.md
@@ -167,8 +167,12 @@ You can pass "--debug" command line flag to any of CEF Python
examples and unit tests. It will also work with your app, as
this feature is enabled in CEF Python's core. When this flag is
passed the following settings will be set:
-```
-settings = {"debug": True, "log_severity": cef.LOGSEVERITY_WARNING}
+```python
+settings = {
+ "debug": True,
+ "log_severity": cef.LOGSEVERITY_INFO,
+ "log_file": "debug.log",
+}
cef.Initialize(settings=settings)
```
diff --git a/docs/Tutorial.md b/docs/Tutorial.md
index bbd3054b..91cc029a 100644
--- a/docs/Tutorial.md
+++ b/docs/Tutorial.md
@@ -244,7 +244,7 @@ To enable debugging set these settings:
```python
settings = {
"debug": True,
- "log_severity": cef.LOGSEVERITY_WARNING,
+ "log_severity": cef.LOGSEVERITY_INFO,
"log_file": "debug.log",
}
cef.Initialize(settings=settings)
diff --git a/examples/wxpython.py b/examples/wxpython.py
index 416805ce..b3b5f0f6 100644
--- a/examples/wxpython.py
+++ b/examples/wxpython.py
@@ -1,9 +1,8 @@
# Example of embedding CEF Python browser using wxPython library.
# This example has a top menu and a browser widget without navigation bar.
-# To install wxPython on Linux type "sudo apt-get install python-wxtools".
-
# Tested configurations:
+# - wxPython 4.0 on Windows/Linux
# - wxPython 3.0 on Windows/Mac
# - wxPython 2.8 on Linux
# - CEF Python v55.4+
@@ -35,8 +34,7 @@ def main():
sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error
settings = {}
if WINDOWS:
- # High DPI support
- settings["auto_zooming"] = "system_dpi"
+ settings["auto_zooming"] = "system_dpi" # High DPI support
# noinspection PyUnresolvedReferences, PyArgumentList
cef.DpiAware.SetProcessDpiAware() # Alternative is to embed manifest
cef.Initialize(settings=settings)
diff --git a/src/cefpython.pyx b/src/cefpython.pyx
index dc7a672e..7b5755eb 100644
--- a/src/cefpython.pyx
+++ b/src/cefpython.pyx
@@ -438,12 +438,12 @@ from cef_image cimport *
from main_message_loop cimport *
# noinspection PyUnresolvedReferences
from cef_views cimport *
+from cef_log cimport *
# -----------------------------------------------------------------------------
# GLOBAL VARIABLES
g_debug = False
-g_debugFile = "debug.log"
# When put None here and assigned a local dictionary in Initialize(), later
# while running app this global variable was garbage collected, see topic:
@@ -462,6 +462,7 @@ cdef scoped_ptr[MainMessageLoopExternalPump] g_external_message_pump
cdef py_bool g_MessageLoop_called = False
cdef py_bool g_MessageLoopWork_called = False
+cdef py_bool g_cef_initialized = False
cdef dict g_globalClientCallbacks = {}
@@ -530,14 +531,11 @@ include "handlers/v8function_handler.pyx"
# Utility functions to provide settings to the C++ browser process code.
cdef public void cefpython_GetDebugOptions(
- cpp_bool* debug,
- cpp_string* debugFile
+ cpp_bool* debug
) except * with gil:
# Called from subprocess/cefpython_app.cpp -> CefPythonApp constructor.
- cdef cpp_string cppString = PyStringToChar(g_debugFile)
try:
debug[0] = bool(g_debug)
- debugFile.assign(cppString)
except:
(exc_type, exc_value, exc_trace) = sys.exc_info()
sys.excepthook(exc_type, exc_value, exc_trace)
@@ -618,16 +616,17 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs):
# Debug settings need to be set before Debug() is called
# and before the CefPythonApp class is instantiated.
global g_debug
- global g_debugFile
if "--debug" in sys.argv:
application_settings["debug"] = True
- application_settings["log_file"] = "debug.log"
- application_settings["log_severity"] = LOGSEVERITY_WARNING
+ application_settings["log_file"] = os.path.join(os.getcwd(),
+ "debug.log")
+ application_settings["log_severity"] = LOGSEVERITY_INFO
sys.argv.remove("--debug")
if "debug" in application_settings:
g_debug = bool(application_settings["debug"])
- if "log_file" in application_settings:
- g_debugFile = application_settings["log_file"]
+ if "log_severity" in application_settings:
+ if application_settings["log_severity"] <= LOGSEVERITY_INFO:
+ g_debug = True
Debug("Initialize() called")
@@ -719,11 +718,9 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs):
# TODO: use the CefMainArgs(int argc, char** argv) constructor.
cdef CefMainArgs cefMainArgs
cdef int exitCode = 1
- with nogil:
- exitCode = CefExecuteProcess(cefMainArgs, cefApp, NULL)
- Debug("CefExecuteProcess(): exitCode = %s" % exitCode)
- if exitCode >= 0:
- sys.exit(exitCode)
+
+ # NOTE: CefExecuteProcess shall not be called here. It should
+ # be called only in the subprocess main.cpp.
# Make a copy as applicationSettings is a reference only
# that might get destroyed later.
@@ -755,6 +752,9 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs):
with nogil:
ret = CefInitialize(cefMainArgs, cefApplicationSettings, cefApp, NULL)
+ global g_cef_initialized
+ g_cef_initialized = True
+
if not ret:
Debug("CefInitialize() failed")
diff --git a/src/client_handler/Makefile b/src/client_handler/Makefile
index 13586c8e..bdb2ee72 100644
--- a/src/client_handler/Makefile
+++ b/src/client_handler/Makefile
@@ -23,6 +23,7 @@ SRC = client_handler.cpp cookie_visitor.cpp resource_handler.cpp \
download_handler.cpp focus_handler.cpp js_dialog_handler.cpp \
keyboard_handler.cpp lifespan_handler.cpp load_handler.cpp \
render_handler.cpp request_handler.cpp dialog_handler.cpp \
+ cef_log.cpp \
$(SRC_MORE)
OBJ = $(filter %.o, $(SRC:.cpp=.o) $(SRC:.mm=.o))
diff --git a/src/client_handler/cef_log.cpp b/src/client_handler/cef_log.cpp
new file mode 100644
index 00000000..62ef9ba8
--- /dev/null
+++ b/src/client_handler/cef_log.cpp
@@ -0,0 +1,17 @@
+// Copyright (c) 2017 CEF Python, see the Authors file.
+// All rights reserved. Licensed under BSD 3-clause license.
+// Project website: https://github.com/cztomczak/cefpython
+
+#include "include/base/cef_logging.h"
+
+void cef_log_info(char* msg) {
+ LOG(INFO) << msg;
+}
+
+void cef_log_warning(char* msg) {
+ LOG(WARNING) << msg;
+}
+
+void cef_log_error(char* msg) {
+ LOG(ERROR) << msg;
+}
diff --git a/src/client_handler/cef_log.h b/src/client_handler/cef_log.h
new file mode 100644
index 00000000..094bc719
--- /dev/null
+++ b/src/client_handler/cef_log.h
@@ -0,0 +1,9 @@
+// Copyright (c) 2017 CEF Python, see the Authors file.
+// All rights reserved. Licensed under BSD 3-clause license.
+// Project website: https://github.com/cztomczak/cefpython
+
+#pragma once
+
+void cef_log_info(char* msg);
+void cef_log_warning(char* msg);
+void cef_log_error(char* msg);
diff --git a/src/client_handler/client_handler.cpp b/src/client_handler/client_handler.cpp
index f14fbaf8..f55da812 100644
--- a/src/client_handler/client_handler.cpp
+++ b/src/client_handler/client_handler.cpp
@@ -8,7 +8,7 @@
#include "client_handler.h"
#include "common/cefpython_public_api.h"
-#include "common/DebugLog.h"
+#include "include/base/cef_logging.h"
#if defined(OS_WIN)
#include
@@ -34,9 +34,9 @@ bool ClientHandler::OnProcessMessageReceived(
return false;
}
std::string messageName = message->GetName().ToString();
- std::string logMessage = "Browser: OnProcessMessageReceived(): ";
+ std::string logMessage = "[Browser process] OnProcessMessageReceived(): ";
logMessage.append(messageName.c_str());
- DebugLog(logMessage.c_str());
+ LOG(INFO) << logMessage.c_str();
if (messageName == "OnContextCreated") {
CefRefPtr arguments = message->GetArgumentList();
if (arguments->GetSize() == 1 && arguments->GetType(0) == VTYPE_INT) {
@@ -45,8 +45,8 @@ bool ClientHandler::OnProcessMessageReceived(
V8ContextHandler_OnContextCreated(browser, frame);
return true;
} else {
- DebugLog("Browser: OnProcessMessageReceived(): invalid arguments" \
- ", messageName = OnContextCreated");
+ LOG(ERROR) << "[Browser process] OnProcessMessageReceived():"
+ " invalid arguments, messageName=OnContextCreated";
return false;
}
} else if (messageName == "OnContextReleased") {
@@ -59,8 +59,8 @@ bool ClientHandler::OnProcessMessageReceived(
V8ContextHandler_OnContextReleased(browserId, frameId);
return true;
} else {
- DebugLog("Browser: OnProcessMessageReceived(): invalid arguments" \
- ", messageName = OnContextReleased");
+ LOG(ERROR) << "[Browser process] OnProcessMessageReceived():"
+ " invalid arguments, messageName=OnContextReleased";
return false;
}
} else if (messageName == "V8FunctionHandler::Execute") {
@@ -80,8 +80,9 @@ bool ClientHandler::OnProcessMessageReceived(
functionArguments);
return true;
} else {
- DebugLog("Browser: OnProcessMessageReceived(): invalid arguments" \
- ", messageName = V8FunctionHandler::Execute");
+ LOG(ERROR) << "[Browser process] OnProcessMessageReceived():"
+ " invalid arguments,"
+ " messageName=V8FunctionHandler::Execute";
return false;
}
} else if (messageName == "ExecutePythonCallback") {
@@ -94,8 +95,9 @@ bool ClientHandler::OnProcessMessageReceived(
ExecutePythonCallback(browser, callbackId, functionArguments);
return true;
} else {
- DebugLog("Browser: OnProcessMessageReceived(): invalid arguments" \
- ", messageName = ExecutePythonCallback");
+ LOG(ERROR) << "[Browser process] OnProcessMessageReceived():"
+ " invalid arguments,"
+ " messageName=ExecutePythonCallback";
return false;
}
} else if (messageName == "RemovePythonCallbacksForFrame") {
@@ -105,8 +107,9 @@ bool ClientHandler::OnProcessMessageReceived(
RemovePythonCallbacksForFrame(frameId);
return true;
} else {
- DebugLog("Browser: OnProcessMessageReceived(): invalid arguments" \
- ", messageName = ExecutePythonCallback");
+ LOG(ERROR) << "[Browser process] OnProcessMessageReceived():"
+ " invalid arguments,"
+ " messageName=ExecutePythonCallback";
return false;
}
}
diff --git a/src/client_handler/context_menu_handler.cpp b/src/client_handler/context_menu_handler.cpp
index 1304e803..e6be3986 100644
--- a/src/client_handler/context_menu_handler.cpp
+++ b/src/client_handler/context_menu_handler.cpp
@@ -3,7 +3,7 @@
// Project website: https://github.com/cztomczak/cefpython
#include "context_menu_handler.h"
-#include "common/DebugLog.h"
+#include "include/base/cef_logging.h"
#define _MENU_ID_DEVTOOLS MENU_ID_USER_FIRST + 1
#define _MENU_ID_RELOAD_PAGE MENU_ID_USER_FIRST + 2
@@ -127,12 +127,13 @@ void OpenInExternalBrowser(const std::string& url)
// Linux equivalent of ShellExecute
if (url.empty()) {
- DebugLog("Browser: OpenInExternalBrowser() FAILED: url is empty");
+ LOG(ERROR) << "[Browser process] OpenInExternalBrowser():"
+ " url is empty";
return;
}
- std::string msg = "Browser: OpenInExternalBrowser(): url=";
+ std::string msg = "[Browser process] OpenInExternalBrowser(): url=";
msg.append(url.c_str());
- DebugLog(msg.c_str());
+ LOG(INFO) << msg.c_str();
// xdg-open is a desktop-independent tool for running
// default applications. Installed by default on Ubuntu.
diff --git a/src/client_handler/deprecated_client_handler_py27_64bit.vcproj b/src/client_handler/deprecated/deprecated_client_handler_py27_64bit.vcproj
similarity index 100%
rename from src/client_handler/deprecated_client_handler_py27_64bit.vcproj
rename to src/client_handler/deprecated/deprecated_client_handler_py27_64bit.vcproj
diff --git a/src/client_handler/client_handler_py27_win32.vcproj b/src/client_handler/deprecated/deprecated_client_handler_py27_win32.vcproj
similarity index 100%
rename from src/client_handler/client_handler_py27_win32.vcproj
rename to src/client_handler/deprecated/deprecated_client_handler_py27_win32.vcproj
diff --git a/src/client_handler/deprecated_client_handler_py34_32bit.vcproj b/src/client_handler/deprecated/deprecated_client_handler_py34_32bit.vcproj
similarity index 100%
rename from src/client_handler/deprecated_client_handler_py34_32bit.vcproj
rename to src/client_handler/deprecated/deprecated_client_handler_py34_32bit.vcproj
diff --git a/src/client_handler/dialog_handler_gtk.cpp b/src/client_handler/dialog_handler_gtk.cpp
index 76bf1851..3d53e78a 100644
--- a/src/client_handler/dialog_handler_gtk.cpp
+++ b/src/client_handler/dialog_handler_gtk.cpp
@@ -18,7 +18,7 @@
#include "include/cef_parser.h"
#include "include/wrapper/cef_helpers.h"
-#include "LOG_DEBUG.h"
+#include "include/base/cef_logging.h"
#include "dialog_handler_gtk.h"
#include "x11.h"
@@ -159,7 +159,7 @@ GtkWindow* GetWindow(CefRefPtr browser) {
// internally, so GTK wasn't yet initialized and must do it
// now, so that display is available. Also must install X11
// error handlers to avoid 'BadWindow' errors.
- LOG_DEBUG << "Initialize GTK";
+ LOG(INFO) << "[Browser process] Initialize GTK";
gtk_init(0, NULL);
InstallX11ErrorHandlers();
// Now the display is available
diff --git a/src/client_handler/download_handler.cpp b/src/client_handler/download_handler.cpp
index fae9b313..9e887e46 100644
--- a/src/client_handler/download_handler.cpp
+++ b/src/client_handler/download_handler.cpp
@@ -3,7 +3,7 @@
// Project website: https://github.com/cztomczak/cefpython
#include "download_handler.h"
-#include "common/DebugLog.h"
+#include "include/base/cef_logging.h"
void DownloadHandler::OnBeforeDownload(
@@ -15,12 +15,13 @@ void DownloadHandler::OnBeforeDownload(
REQUIRE_UI_THREAD();
bool downloads_enabled = ApplicationSettings_GetBool("downloads_enabled");
if (downloads_enabled) {
- std::string msg = "Browser: About to download file: ";
+ std::string msg = "[Browser process] About to download file: ";
msg.append(suggested_name.ToString().c_str());
- DebugLog(msg.c_str());
+ LOG(INFO) << msg.c_str();
callback->Continue(suggested_name, true);
} else {
- DebugLog("Browser: Tried to download file, but downloads are disabled");
+ LOG(INFO) << "[Browser process] Tried to download file,"
+ " but downloads are disabled";
}
}
@@ -32,10 +33,10 @@ void DownloadHandler::OnDownloadUpdated(
{
REQUIRE_UI_THREAD();
if (download_item->IsComplete()) {
- std::string msg = "Browser: Download completed, saved to: ";
+ std::string msg = "[Browser process] Download completed, saved to: ";
msg.append(download_item->GetFullPath().ToString().c_str());
- DebugLog(msg.c_str());
+ LOG(INFO) << msg.c_str();
} else if (download_item->IsCanceled()) {
- DebugLog("Browser: Download was cancelled");
+ LOG(INFO) << "[Browser process] Download was cancelled";
}
}
diff --git a/src/client_handler/dpi_aware.cpp b/src/client_handler/dpi_aware.cpp
index 6c8a9213..48e2a13f 100644
--- a/src/client_handler/dpi_aware.cpp
+++ b/src/client_handler/dpi_aware.cpp
@@ -10,7 +10,7 @@
#include "dpi_aware.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/base/cef_bind.h"
-#include "LOG_DEBUG.h"
+#include "include/base/cef_logging.h"
const int DEFAULT_DPIX = 96;
@@ -56,7 +56,8 @@ PROCESS_DPI_AWARENESS GetProcessDpiAwareness() {
return result;
}
// Possible failures include E_INVALIDARG or E_ACCESSDENIED.
- LOG_DEBUG << "Browser: GetProcessDpiAwareness failed with HR=" << hr;
+ LOG(INFO) << "[Browser process] GetProcessDpiAwareness():"
+ " hr=" << hr;
}
return PROCESS_DPI_UNAWARE;
}
@@ -88,23 +89,23 @@ void SetProcessDpiAware() {
GetProcAddress(GetModuleHandleA("user32.dll"),
"SetProcessDpiAwarenessInternal"));
if (set_process_dpi_awareness_func) {
- LOG_DEBUG << "Browser: SetProcessDpiAware: "
- << "calling user32.dll SetProcessDpiAwareness";
+ LOG(INFO) << "[Browser process] SetProcessDpiAware():"
+ " calling user32.dll SetProcessDpiAwareness";
HRESULT hr = set_process_dpi_awareness_func(PROCESS_SYSTEM_DPI_AWARE);
if (SUCCEEDED(hr)) {
- LOG_DEBUG << "Browser: SetBrowserDpiAware: "
- "SetProcessDpiAwareness succeeded";
+ LOG(INFO) << "[Browser process]: SetBrowserDpiAware():"
+ " SetProcessDpiAwareness succeeded";
return;
} else if (hr == E_ACCESSDENIED) {
- LOG_DEBUG << "Browser: SetBrowserDpiAware: "
- "SetProcessDpiAwareness FAILED: "
- "The DPI awareness is already set, either by calling "
- "this API previously or through the application (.exe) "
- "manifest.";
+ LOG(ERROR) << "[Browser process] SetBrowserDpiAware():"
+ " SetProcessDpiAwareness failed:"
+ " The DPI awareness is already set, either by calling"
+ " this API previously or through the application"
+ " (.exe) manifest.";
// Do not return here, let's try to call SetProcessDPIAware.
} else {
- LOG_DEBUG << "Browser: SetBrowserDpiAware: "
- "SetProcessDpiAwareness FAILED";
+ LOG(ERROR) << "[Browser process] SetBrowserDpiAware():"
+ " SetProcessDpiAwareness failed";
// Do not return here, let's try to call SetProcessDPIAware.
}
}
@@ -119,8 +120,8 @@ void SetProcessDpiAware() {
// If cefpython.Initialize() wasn't yet called, then
// this log message won't be written, as g_debug is
// is set during CEF initialization.
- LOG_DEBUG << "Browser: SetProcessDpiAware: "
- << "calling user32.dll SetProcessDPIAware";
+ LOG(INFO) << "[Browser process] SetProcessDpiAware():"
+ " calling user32.dll SetProcessDPIAware";
set_process_dpi_aware_func();
}
}
@@ -153,9 +154,9 @@ void GetDpiAwareWindowSize(int* width, int* height) {
if (newZoomLevel > 0.0) {
*width = *width + (int)ceil(newZoomLevel * 0.25 * (*width));
*height = *height + (int)ceil(newZoomLevel * 0.25 * (*height));
- LOG_DEBUG << "Browser: GetDpiAwareWindowSize: "
- << "enlarged by " << ceil(newZoomLevel * 0.25 * 100) << "% "
- << "new size = " << *width << "/" << *height;
+ LOG(INFO) << "[Browser process] GetDpiAwareWindowSize():"
+ " enlarged by " << ceil(newZoomLevel * 0.25 * 100) << "%"
+ " new size = " << *width << "/" << *height;
}
}
@@ -191,9 +192,9 @@ void SetBrowserDpiSettings(CefRefPtr cefBrowser,
cefBrowser->GetHost()->SetZoomLevel(newZoomLevel);
if (cefBrowser->GetHost()->GetZoomLevel() != oldZoomLevel) {
// OK succes.
- LOG_DEBUG << "Browser: SetBrowserDpiSettings: "
- << "DPI=" << dpix << " "
- << "zoom=" << cefBrowser->GetHost()->GetZoomLevel();
+ LOG(INFO) << "[Browser process] SetBrowserDpiSettings():"
+ " DPI=" << dpix << ""
+ " zoom=" << cefBrowser->GetHost()->GetZoomLevel();
}
} else {
// This code block running can also be a result of executing
@@ -206,9 +207,9 @@ void SetBrowserDpiSettings(CefRefPtr cefBrowser,
if (!already_logged) {
already_logged = true;
// OK success.
- LOG_DEBUG << "Browser: SetBrowserDpiSettings: "
- << "DPI=" << dpix << " "
- << "zoom=" << cefBrowser->GetHost()->GetZoomLevel();
+ LOG(INFO) << "[Browser process] SetBrowserDpiSettings():"
+ " DPI=" << dpix << ""
+ " zoom=" << cefBrowser->GetHost()->GetZoomLevel();
}
}
// We need to check zooming constantly, during loading of pages.
diff --git a/src/client_handler/lifespan_handler.cpp b/src/client_handler/lifespan_handler.cpp
index 0cfd2d1b..d54f5f0a 100644
--- a/src/client_handler/lifespan_handler.cpp
+++ b/src/client_handler/lifespan_handler.cpp
@@ -6,7 +6,7 @@
#if defined(OS_WIN)
#include "dpi_aware.h"
#endif
-#include "LOG_DEBUG.h"
+#include "include/base/cef_logging.h"
bool LifespanHandler::OnBeforePopup(CefRefPtr browser,
@@ -38,8 +38,8 @@ void LifespanHandler::OnAfterCreated(CefRefPtr browser)
// High DPI support.
CefString auto_zooming = ApplicationSettings_GetString("auto_zooming");
if (!auto_zooming.empty()) {
- LOG_DEBUG << "Browser: OnAfterCreated(): auto_zooming = "
- << auto_zooming.ToString();
+ LOG(INFO) << "[Browser process] OnAfterCreated(): auto_zooming = "
+ << auto_zooming.ToString();
SetBrowserDpiSettings(browser, auto_zooming);
}
#endif // OS_WIN
diff --git a/src/client_handler/request_context_handler.cpp b/src/client_handler/request_context_handler.cpp
index ef7cc8b9..bf816cf5 100644
--- a/src/client_handler/request_context_handler.cpp
+++ b/src/client_handler/request_context_handler.cpp
@@ -4,7 +4,6 @@
#include "request_context_handler.h"
#include "common/cefpython_public_api.h"
-#include "DebugLog.h"
// --------------------------------------------------------------------------
// CefRequestContextHandler
diff --git a/src/client_handler/request_handler.cpp b/src/client_handler/request_handler.cpp
index 69904377..c06e098d 100644
--- a/src/client_handler/request_handler.cpp
+++ b/src/client_handler/request_handler.cpp
@@ -3,7 +3,7 @@
// Project website: https://github.com/cztomczak/cefpython
#include "request_handler.h"
-#include "common/DebugLog.h"
+#include "include/base/cef_logging.h"
bool RequestHandler::OnBeforeBrowse(CefRefPtr browser,
@@ -104,7 +104,7 @@ void RequestHandler::OnRenderProcessTerminated(CefRefPtr browser,
cef_termination_status_t status)
{
REQUIRE_UI_THREAD();
- DebugLog("Browser: OnRenderProcessTerminated()");
+ LOG(ERROR) << "[Browser process] OnRenderProcessTerminated()";
RequestHandler_OnRendererProcessTerminated(browser, status);
}
diff --git a/src/client_handler/x11.cpp b/src/client_handler/x11.cpp
index 0c37bff4..18f7ce03 100644
--- a/src/client_handler/x11.cpp
+++ b/src/client_handler/x11.cpp
@@ -3,10 +3,10 @@
// Project website: https://github.com/cztomczak/cefpython
#include "x11.h"
-#include "LOG_DEBUG.h"
+#include "include/base/cef_logging.h"
int XErrorHandlerImpl(Display *display, XErrorEvent *event) {
- LOG_DEBUG
+ LOG(INFO) << "[Browser process] "
<< "X error received: "
<< "type " << event->type << ", "
<< "serial " << event->serial << ", "
diff --git a/src/common/DebugLog.h b/src/common/DebugLog.h
deleted file mode 100644
index 4c5419a6..00000000
--- a/src/common/DebugLog.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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
-
-#pragma once
-#include
-
-extern bool g_debug;
-extern std::string g_logFile;
-
-// Defined as "inline" to get rid of the "already defined" errors
-// when linking.
-inline void DebugLog(const char* szString)
-{
- if (!g_debug)
- return;
- // TODO: get the log_file option from CefSettings.
- printf("[CEF Python] %s\n", szString);
- if (g_logFile.length()) {
- FILE* pFile = fopen(g_logFile.c_str(), "a");
- fprintf(pFile, "[CEF Python] App: %s\n", szString);
- fclose(pFile);
- }
-}
diff --git a/src/common/LOG_DEBUG.h b/src/common/LOG_DEBUG.h
deleted file mode 100644
index 672ad25e..00000000
--- a/src/common/LOG_DEBUG.h
+++ /dev/null
@@ -1,211 +0,0 @@
-// Taken from here: http://www.drdobbs.com/cpp/logging-in-c/201804215
-// Original author: Petru Marginean
-// Modified by: Czarek Tomczak
-
-// Usage:
-// LOG_DEBUG << "Browser: someVar = " << someVar;
-// Warning:
-// Log is written when ~Log() destructor is called, which
-// occurs when outside of scope. This could result in log
-// not being written if program crashes before code goes
-// outside of current scope. You could embrace LOG_DEBUG
-// statements with braces {} to guarantee the log to be
-// written immediately.
-
-#ifndef __LOG_DEBUG_H__
-#define __LOG_DEBUG_H__
-
-#include
-#include
-#include
-#include "DebugLog.h"
-
-inline std::string NowTime();
-
-enum TLogLevel {logERROR, logWARNING, logINFO, logDEBUG,
- logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4};
-
-template
-class Log
-{
-public:
- Log();
- virtual ~Log();
- std::ostringstream& Get(TLogLevel level = logINFO);
-public:
- static TLogLevel& ReportingLevel();
- static std::string ToString(TLogLevel level);
- static TLogLevel FromString(const std::string& level);
-protected:
- std::ostringstream os;
-private:
- Log(const Log&);
- Log& operator =(const Log&);
-};
-
-template
-Log::Log()
-{
-}
-
-template
-std::ostringstream& Log::Get(TLogLevel level)
-{
- // os << "- " << NowTime();
- // os << " " << ToString(level) << ": ";
- // os << std::string(level > logDEBUG ? level - logDEBUG : 0, '\t');
- return os;
-}
-
-template
-Log::~Log()
-{
- os << std::endl;
- /*
- if (T::Stream() != stderr) {
- fprintf(stderr, "%s", os.str().c_str());
- fflush(stderr);
- }
- T::Output(os.str());
- */
- DebugLog(os.str().c_str());
-}
-
-template
-TLogLevel& Log::ReportingLevel()
-{
- static TLogLevel reportingLevel = logDEBUG4;
- return reportingLevel;
-}
-
-template
-std::string Log::ToString(TLogLevel level)
-{
- static const char* const buffer[] = {"ERROR", "WARNING", "INFO", "DEBUG",
- "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4"};
- return buffer[level];
-}
-
-template
-TLogLevel Log::FromString(const std::string& level)
-{
- if (level == "DEBUG4")
- return logDEBUG4;
- if (level == "DEBUG3")
- return logDEBUG3;
- if (level == "DEBUG2")
- return logDEBUG2;
- if (level == "DEBUG1")
- return logDEBUG1;
- if (level == "DEBUG")
- return logDEBUG;
- if (level == "INFO")
- return logINFO;
- if (level == "WARNING")
- return logWARNING;
- if (level == "ERROR")
- return logERROR;
- Log().Get(logWARNING) << "Unknown logging level '" << level
- << "'. Using INFO level as default.";
- return logINFO;
-}
-
-class Output2FILE
-{
-public:
- static FILE*& Stream();
- static void Output(const std::string& msg);
-};
-
-inline FILE*& Output2FILE::Stream()
-{
- static FILE* pStream = stderr;
- return pStream;
-}
-
-inline void Output2FILE::Output(const std::string& msg)
-{
- /*
- FILE* pStream = Stream();
- if (!pStream)
- return;
- fprintf(pStream, "%s", msg.c_str());
- fflush(pStream);
- */
-}
-
-#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
-# if defined (BUILDING_FILELOG_DLL)
-# define FILELOG_DECLSPEC __declspec (dllexport)
-# elif defined (USING_FILELOG_DLL)
-# define FILELOG_DECLSPEC __declspec (dllimport)
-# else
-# define FILELOG_DECLSPEC
-# endif // BUILDING_DBSIMPLE_DLL
-#else
-# define FILELOG_DECLSPEC
-#endif // _WIN32
-
-class FILELOG_DECLSPEC FILELog : public Log {};
-//typedef Log FILELog;
-
-#ifndef FILELOG_MAX_LEVEL
-#define FILELOG_MAX_LEVEL logDEBUG4
-#endif
-
-// Name conflits with cef_logging.h, see:
-// https://bitbucket.org/chromiumembedded/cef/issues/1830
-// LOG, LOG_ERROR, LOG_WARNING and LOG_INFO are already defined
-// in cef_logging.h and must not be used here. So far we've only
-// used LOG_DEBUG in code.
-
-#define CEFPYTHON_LOG(level) \
- if (level > FILELOG_MAX_LEVEL) ;\
- else if (level > FILELog::ReportingLevel() || !Output2FILE::Stream()) ; \
- else FILELog().Get(level) \
-
-// #define LOG_ERROR LOG(logERROR)
-// #define LOG_WARNING LOG(logWARNING)
-// #define LOG_INFO LOG(logINFO)
-#define LOG_DEBUG CEFPYTHON_LOG(logDEBUG)
-
-#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
-
-#include
-
-inline std::string NowTime()
-{
- const int MAX_LEN = 200;
- char buffer[MAX_LEN];
- if (GetTimeFormatA(LOCALE_USER_DEFAULT, 0, 0,
- "HH':'mm':'ss", buffer, MAX_LEN) == 0)
- return "Error in NowTime()";
-
- char result[100] = {0};
- static DWORD first = GetTickCount();
- #pragma warning(suppress: 4996)
- sprintf(result, "%s.%03ld", buffer, (long)(GetTickCount() - first) % 1000);
- return result;
-}
-
-#else
-
-#include
-
-inline std::string NowTime()
-{
- char buffer[11];
- time_t t;
- time(&t);
- tm r = {0};
- strftime(buffer, sizeof(buffer), "%X", localtime_r(&t, &r));
- struct timeval tv;
- gettimeofday(&tv, 0);
- char result[100] = {0};
- sprintf(result, "%s.%03ld", buffer, (long)tv.tv_usec / 1000);
- return result;
-}
-
-#endif //WIN32
-
-#endif //__LOG_DEBUG_H__
diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi
index 632aab59..35f85002 100644
--- a/src/compile_time_constants.pxi
+++ b/src/compile_time_constants.pxi
@@ -1,3 +1,3 @@
# This file was generated by setup.py
-DEF UNAME_SYSNAME = "Windows"
-DEF PY_MAJOR_VERSION = 3
+DEF UNAME_SYSNAME = "Linux"
+DEF PY_MAJOR_VERSION = 2
diff --git a/src/extern/cef_log.pxd b/src/extern/cef_log.pxd
new file mode 100644
index 00000000..04a32cfb
--- /dev/null
+++ b/src/extern/cef_log.pxd
@@ -0,0 +1,8 @@
+# Copyright (c) 2017 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 "client_handler/cef_log.h":
+ void cef_log_info(char* msg)
+ void cef_log_warning(char* msg)
+ void cef_log_error(char* msg)
diff --git a/src/handlers/browser_process_handler.pyx b/src/handlers/browser_process_handler.pyx
index 5847d670..09463b0e 100644
--- a/src/handlers/browser_process_handler.pyx
+++ b/src/handlers/browser_process_handler.pyx
@@ -8,7 +8,6 @@ cdef public void BrowserProcessHandler_OnRenderProcessThreadCreated(
CefRefPtr[CefListValue] extra_info
) except * with gil:
try:
- # Keys 0 and 1 are already set in C++ code - to pass debug options.
pass
except:
(exc_type, exc_value, exc_trace) = sys.exc_info()
@@ -19,7 +18,6 @@ cdef public void BrowserProcessHandler_OnBeforeChildProcessLaunch(
) except * with gil:
try:
AppendSwitchesToCommandLine(cefCommandLine, g_commandLineSwitches)
- Debug("BrowserProcessHandler_OnBeforeChildProcessLaunch()")
except:
(exc_type, exc_value, exc_trace) = sys.exc_info()
sys.excepthook(exc_type, exc_value, exc_trace)
diff --git a/src/linux/binaries_64bit/kivy_.py b/src/linux/binaries_64bit/kivy_.py
index 7d7ef4cc..c980aa9f 100644
--- a/src/linux/binaries_64bit/kivy_.py
+++ b/src/linux/binaries_64bit/kivy_.py
@@ -148,9 +148,6 @@ def start_cef(self):
# Configure CEF
settings = {
- "debug": True, # debug messages in console and in log_file
- "log_severity": cef.LOGSEVERITY_INFO,
- "log_file": "debug.log",
# This directories must be set on Linux
"locales_dir_path": cef.GetModuleDirectory()+"/locales",
"resources_dir_path": cef.GetModuleDirectory(),
diff --git a/src/subprocess/cefpython_app.cpp b/src/subprocess/cefpython_app.cpp
index 1f51ba27..95077702 100644
--- a/src/subprocess/cefpython_app.cpp
+++ b/src/subprocess/cefpython_app.cpp
@@ -22,8 +22,7 @@
#include "util.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/base/cef_bind.h"
-#include "DebugLog.h"
-#include "LOG_DEBUG.h"
+#include "include/base/cef_logging.h"
#include
#include
#include "v8utils.h"
@@ -34,12 +33,12 @@
#include "main_message_loop/main_message_loop_external_pump.h"
#endif
+// GLOBALS
bool g_debug = false;
-std::string g_logFile = "debug.log";
CefPythonApp::CefPythonApp() {
#ifdef BROWSER_PROCESS
- cefpython_GetDebugOptions(&g_debug, &g_logFile);
+ cefpython_GetDebugOptions(&g_debug);
#endif
}
@@ -62,21 +61,26 @@ void CefPythonApp::OnBeforeCommandLineProcessing(
if (process_name.empty()) {
process_name = "browser";
}
- std::string logMessage = "Command line string for the ";
+#ifdef BROWSER_PROCESS
+ std::string logMessage = "[Browser process] ";
+#else
+ std::string logMessage = "[Non-browser process] ";
+#endif
+ logMessage.append("Command line string for the ");
logMessage.append(process_name);
logMessage.append(" process: ");
std::string clString = command_line->GetCommandLineString().ToString();
logMessage.append(clString.c_str());
- // OnBeforeCommandLineProcessing() is called before
- // CefRenderHandler::OnRenderThreadCreated() which sets
- // the debug options. Thus debugging will always be Off
- // at the time this method is called. The fix for that
- // is to keep the command line string somewhere and call
- // DebugLog later in OnRenderThreadCreated().
+ // There is a bug in upstream CEF, log settings are initialized
+ // after OnBeforeCommandLineProcessing. So if g_debug is not
+ // checked it would always log msg even though logging info is
+ // disabled. However this issue does not matter, because command
+ // line is also logged in OnBeforeChildProcessLaunch().
+ // In OnBeforeCommandLineProcessing() command line for browser
+ // process is logged and in OnBeforeChildProcessLaunch() command
+ // line for other processes is logged.
if (g_debug) {
- DebugLog(logMessage.c_str());
- } else {
- commandLineString_ = logMessage;
+ LOG(INFO) << logMessage.c_str();
}
}
@@ -116,6 +120,16 @@ void CefPythonApp::OnBeforeChildProcessLaunch(
// the libcefpythonapp library.
BrowserProcessHandler_OnBeforeChildProcessLaunch(command_line);
#endif // BROWSER_PROCESS
+
+#ifdef BROWSER_PROCESS
+ std::string logMessage = "[Browser process] ";
+#else
+ std::string logMessage = "[Non-browser process] ";
+#endif // BROWSER_PROCESS
+ logMessage.append("OnBeforeChildProcessLaunch() command line: ");
+ std::string clString = command_line->GetCommandLineString().ToString();
+ logMessage.append(clString.c_str());
+ LOG(INFO) << logMessage.c_str();
}
void CefPythonApp::OnRenderProcessThreadCreated(
@@ -127,8 +141,9 @@ void CefPythonApp::OnRenderProcessThreadCreated(
// The equivalent in Cython is:
// | extra_info.Assign(mylist.get())
REQUIRE_IO_THREAD();
- extra_info->SetBool(0, g_debug);
- extra_info->SetString(1, g_logFile);
+ // Eg.:
+ // | extra_info->SetBool(0, false);
+ // | extra_info->SetString(1, "test");
// This is included only in the Browser process, when building
// the libcefpythonapp library.
BrowserProcessHandler_OnRenderProcessThreadCreated(extra_info);
@@ -142,7 +157,7 @@ CefRefPtr CefPythonApp::GetPrintHandler() {
// required for some of the examples.
GdkDisplay* gdk_display = gdk_display_get_default();
if (!gdk_display) {
- LOG_DEBUG << "Initialize GTK";
+ LOG(INFO) << "[Browser process] Initialize GTK";
gtk_init(0, NULL);
}
#endif
@@ -165,24 +180,6 @@ void CefPythonApp::OnScheduleMessagePumpWork(int64 delay_ms) {
// -----------------------------------------------------------------------------
void CefPythonApp::OnRenderThreadCreated(CefRefPtr extra_info) {
- if (extra_info->GetType(0) == VTYPE_BOOL) {
- g_debug = extra_info->GetBool(0);
- if (g_debug) {
- FILELog::ReportingLevel() = logDEBUG;
- } else {
- // In reality this disables logging in LOG_DEBUG.h, as
- // we're using only LOG_DEBUG macro.
- FILELog::ReportingLevel() = logERROR;
- }
- }
- if (extra_info->GetType(1) == VTYPE_STRING) {
- g_logFile = extra_info->GetString(1).ToString();
- }
- if (!commandLineString_.empty()) {
- // See comment in OnBeforeCommandLineProcessing().
- DebugLog(commandLineString_.c_str());
- commandLineString_ = "";
- }
}
void CefPythonApp::OnWebKitInitialized() {
@@ -192,7 +189,7 @@ void CefPythonApp::OnBrowserCreated(CefRefPtr browser) {
}
void CefPythonApp::OnBrowserDestroyed(CefRefPtr browser) {
- DebugLog("Renderer: OnBrowserDestroyed()");
+ LOG(INFO) << "[Renderer process] OnBrowserDestroyed()";
RemoveJavascriptBindings(browser);
}
@@ -207,7 +204,7 @@ bool CefPythonApp::OnBeforeNavigation(CefRefPtr browser,
void CefPythonApp::OnContextCreated(CefRefPtr browser,
CefRefPtr frame,
CefRefPtr context) {
- DebugLog("Renderer: OnContextCreated()");
+ LOG(INFO) << "[Renderer process] OnContextCreated()";
CefRefPtr message = CefProcessMessage::Create(
"OnContextCreated");
CefRefPtr arguments = message->GetArgumentList();
@@ -220,12 +217,12 @@ void CefPythonApp::OnContextCreated(CefRefPtr browser,
/*
// Example of converting int64 to string. Still need an
// example of converting it back from string.
- std::string logMessage = "OnContextCreated(): frameId=";
+ std::string logMessage = "[Renderer process] OnContextCreated(): frameId=";
stringstream stream;
int64 value = frame->GetIdentifier();
stream << value;
logMessage.append(stream.str());
- DebugLog(logMessage.c_str());
+ LOG(INFO) << logMessage.c_str();
*/
// TODO: losing int64 precision, the solution is to convert
// it to string and then in the Browser process back
@@ -255,7 +252,7 @@ void CefPythonApp::OnContextCreated(CefRefPtr browser,
void CefPythonApp::OnContextReleased(CefRefPtr browser,
CefRefPtr frame,
CefRefPtr context) {
- DebugLog("Renderer: OnContextReleased()");
+ LOG(INFO) << "[Renderer process] OnContextReleased()";
CefRefPtr message;
CefRefPtr arguments;
// ------------------------------------------------------------------------
@@ -308,9 +305,9 @@ bool CefPythonApp::OnProcessMessageReceived(CefRefPtr browser,
CefProcessId source_process,
CefRefPtr message) {
std::string messageName = message->GetName().ToString();
- std::string logMessage = "Renderer: OnProcessMessageReceived(): ";
+ std::string logMessage = "[Renderer process] OnProcessMessageReceived(): ";
logMessage.append(messageName.c_str());
- DebugLog(logMessage.c_str());
+ LOG(INFO) << logMessage.c_str();
CefRefPtr args = message->GetArgumentList();
if (messageName == "DoJavascriptBindings") {
if (args->GetSize() == 1
@@ -321,8 +318,9 @@ bool CefPythonApp::OnProcessMessageReceived(CefRefPtr browser,
args->GetDictionary(0)->Copy(false));
DoJavascriptBindingsForBrowser(browser);
} else {
- DebugLog("Renderer: OnProcessMessageReceived(): invalid arguments,"\
- " messageName=DoJavascriptBindings");
+ LOG(ERROR) << "[Renderer process] OnProcessMessageReceived():"
+ " invalid arguments,"
+ " messageName=DoJavascriptBindings";
return false;
}
} else if (messageName == "ExecuteJavascriptCallback") {
@@ -338,9 +336,9 @@ bool CefPythonApp::OnProcessMessageReceived(CefRefPtr browser,
jsArgs->Remove(0);
ExecuteJavascriptCallback(jsCallbackId, jsArgs);
} else {
- DebugLog("Renderer: OnProcessMessageReceived: invalid arguments," \
- "expected first argument to be a javascript callback " \
- "(int)");
+ LOG(ERROR) << "[Renderer process] OnProcessMessageReceived:"
+ " invalid arguments, expected first argument to be"
+ " a javascript callback (int)";
return false;
}
}
@@ -383,16 +381,16 @@ bool CefPythonApp::BindedFunctionExists(CefRefPtr browser,
std::string::npos));
if (!(jsBindings->HasKey("objects")
&& jsBindings->GetType("objects") == VTYPE_DICTIONARY)) {
- DebugLog("Renderer: BindedFunctionExists() FAILED: "\
- "objects dictionary not found");
+ LOG(ERROR) << "[Renderer process] BindedFunctionExists():"
+ " objects dictionary not found";
return false;
}
CefRefPtr objects = \
jsBindings->GetDictionary("objects");
if (objects->HasKey(objectName)) {
if (!(objects->GetType(objectName) == VTYPE_DICTIONARY)) {
- DebugLog("Renderer: BindedFunctionExists() FAILED: "\
- "objects dictionary has invalid type");
+ LOG(ERROR) << "[Renderer process] BindedFunctionExists():"
+ " objects dictionary has invalid type";
return false;
}
CefRefPtr methods = \
@@ -405,8 +403,8 @@ bool CefPythonApp::BindedFunctionExists(CefRefPtr browser,
// This is a function call.
if (!(jsBindings->HasKey("functions")
&& jsBindings->GetType("functions") == VTYPE_DICTIONARY)) {
- DebugLog("Renderer: BindedFunctionExists() FAILED: "\
- "functions dictionary not found");
+ LOG(ERROR) << "[Renderer process] BindedFunctionExists():"
+ " functions dictionary not found";
return false;
}
CefRefPtr functions = \
@@ -425,8 +423,8 @@ void CefPythonApp::DoJavascriptBindingsForBrowser(
CefRefPtr jsBindings = GetJavascriptBindings(browser);
if (!jsBindings.get()) {
// Bindings must be set before this function is called.
- DebugLog("Renderer: DoJavascriptBindingsForBrowser() FAILED: " \
- "bindings not set");
+ LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForBrowser():"
+ " bindings not set";
return;
}
std::vector frameIds;
@@ -461,8 +459,8 @@ void CefPythonApp::DoJavascriptBindingsForBrowser(
frameIds.push_back(browser->GetMainFrame()->GetIdentifier());
}
if (!frameIds.size()) {
- DebugLog("Renderer: DoJavascriptBindingsForBrowser() FAILED: " \
- "frameIds.size() == 0");
+ LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForBrowser():"
+ " frameIds.size() == 0";
return;
}
for (std::vector::iterator it = frameIds.begin(); \
@@ -472,15 +470,15 @@ void CefPythonApp::DoJavascriptBindingsForBrowser(
// filled with zeros. This problem was fixed by using'
// GetFrameNames() so this block of code should not
// be executed anymore.
- DebugLog("Renderer: DoJavascriptBindingsForBrowser() WARNING: " \
- "frameId <= 0");
+ LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForBrowser():"
+ " frameId <= 0";
// printf("[CEF Python] Renderer: frameId = %lli\n", *it);
continue;
}
CefRefPtr frame = browser->GetFrame(*it);
if (!frame.get()) {
- DebugLog("Renderer: DoJavascriptBindingsForBrowser() WARNING: " \
- "GetFrame() failed");
+ LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForBrowser():"
+ " GetFrame() failed";
continue;
}
CefRefPtr context = frame->GetV8Context();
@@ -498,10 +496,12 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser,
CefRefPtr jsBindings = GetJavascriptBindings(browser);
if (!jsBindings.get()) {
// Bindings may not yet be set, it's okay.
- DebugLog("Renderer: DoJavascriptBindingsForFrame(): bindings not set");
+ LOG(INFO) << "[Renderer process] DoJavascriptBindingsForFrame():"
+ " bindings not set yet";
return;
}
- DebugLog("Renderer: DoJavascriptBindingsForFrame(): bindings are set");
+ LOG(INFO) << "[Renderer process] DoJavascriptBindingsForFrame():"
+ " bindings are set";
if (!(jsBindings->HasKey("functions")
&& jsBindings->GetType("functions") == VTYPE_DICTIONARY
&& jsBindings->HasKey("properties")
@@ -510,8 +510,8 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser,
&& jsBindings->GetType("objects") == VTYPE_DICTIONARY
&& jsBindings->HasKey("bindToFrames")
&& jsBindings->GetType("bindToFrames") == VTYPE_BOOL)) {
- DebugLog("Renderer: DoJavascriptBindingsForFrame() FAILED: " \
- "invalid data [1]");
+ LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForFrame():"
+ " invalid data [1]";
return;
}
@@ -527,8 +527,10 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser,
// not be valid. May be a timing issue. Or may be caused by
// a redirect to a different origin and that creates a new
// renderer process.
- DebugLog("Renderer: DoJavascriptBindingsForFrame() FAILED:"\
- " V8 context provided by CEF is invalid");
+ // This message is logged in the tutorial.py example which
+ // uses data uri created from html string.
+ LOG(INFO) << "[Renderer process] DoJavascriptBindingsForFrame():"
+ " V8 context provided by CEF is invalid";
return;
}
context->Enter();
@@ -544,8 +546,8 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser,
// | bool bindToFrames = jsBindings->GetBool("bindToFrames");
if (!(functions->IsValid() && properties->IsValid()
&& objects->IsValid())) {
- DebugLog("Renderer: DoJavascriptBindingsForFrame() FAILED: " \
- "invalid data [2]");
+ LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForFrame():"
+ " invalid data [2]";
if (didEnterContext)
context->Exit();
return;
@@ -556,8 +558,8 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser,
// FUNCTIONS.
std::vector functionsVector;
if (!functions->GetKeys(functionsVector)) {
- DebugLog("Renderer: DoJavascriptBindingsForFrame(): " \
- "functions->GetKeys() FAILED");
+ LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForFrame():"
+ " functions->GetKeys() failed";
if (didEnterContext)
context->Exit();
return;
@@ -575,8 +577,8 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser,
properties);
std::vector v8Keys;
if (!v8Properties->GetKeys(v8Keys)) {
- DebugLog("DoJavascriptBindingsForFrame() FAILED: " \
- "v8Properties->GetKeys() failed");
+ LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForFrame():"
+ " v8Properties->GetKeys() failed";
if (didEnterContext)
context->Exit();
return;
@@ -590,8 +592,8 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser,
// OBJECTS AND ITS METHODS.
std::vector objectsVector;
if (!objects->GetKeys(objectsVector)) {
- DebugLog("Renderer: DoJavascriptBindingsForFrame() FAILED: " \
- "objects->GetKeys() failed");
+ LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForFrame():"
+ " objects->GetKeys() failed";
if (didEnterContext)
context->Exit();
return;
@@ -603,8 +605,8 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser,
v8Window->SetValue(objectName, v8Object, V8_PROPERTY_ATTRIBUTE_NONE);
// METHODS.
if (!(objects->GetType(objectName) == VTYPE_DICTIONARY)) {
- DebugLog("Renderer: DoJavascriptBindingsForFrame() FAILED: " \
- "objects->GetType() != VTYPE_DICTIONARY");
+ LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForFrame():"
+ " objects->GetType() != VTYPE_DICTIONARY";
if (didEnterContext)
context->Exit();
return;
@@ -613,8 +615,8 @@ void CefPythonApp::DoJavascriptBindingsForFrame(CefRefPtr browser,
objects->GetDictionary(objectName);
std::vector methodsVector;
if (!(methods->IsValid() && methods->GetKeys(methodsVector))) {
- DebugLog("Renderer: DoJavascriptBindingsForFrame() FAILED: " \
- "methods->GetKeys() failed");
+ LOG(ERROR) << "[Renderer process] DoJavascriptBindingsForFrame():"
+ " methods->GetKeys() failed";
if (didEnterContext)
context->Exit();
return;
diff --git a/src/subprocess/cefpython_app.h b/src/subprocess/cefpython_app.h
index e76b2691..f9336ba3 100644
--- a/src/subprocess/cefpython_app.h
+++ b/src/subprocess/cefpython_app.h
@@ -10,9 +10,9 @@
// CefPythonApp class is instantiated in subprocess and in
// cefpython.pyx for the browser process, so the code is shared.
-// Using printf() in CefRenderProcessHandler won't work, use
-// the DebugLog() function instead, it will write the message
-// to the "debug.log" file.
+// Using printf() in CefRenderProcessHandler won't work on some
+// operating systems, use LOG(INFO) macro instead, it will write
+// the message to the "debug.log" file.
class CefPythonApp :
public CefApp,
@@ -20,7 +20,6 @@ class CefPythonApp :
public CefRenderProcessHandler {
protected:
std::map > javascriptBindings_;
- std::string commandLineString_;
CefRefPtr print_handler_;
public:
diff --git a/src/subprocess/deprecated_libcefpythonapp_py27_64bit.vcproj b/src/subprocess/deprecated/deprecated_libcefpythonapp_py27_64bit.vcproj
similarity index 100%
rename from src/subprocess/deprecated_libcefpythonapp_py27_64bit.vcproj
rename to src/subprocess/deprecated/deprecated_libcefpythonapp_py27_64bit.vcproj
diff --git a/src/subprocess/libcefpythonapp_py27_win32.vcproj b/src/subprocess/deprecated/deprecated_libcefpythonapp_py27_win32.vcproj
similarity index 100%
rename from src/subprocess/libcefpythonapp_py27_win32.vcproj
rename to src/subprocess/deprecated/deprecated_libcefpythonapp_py27_win32.vcproj
diff --git a/src/subprocess/deprecated_libcefpythonapp_py34_32bit.vcproj b/src/subprocess/deprecated/deprecated_libcefpythonapp_py34_32bit.vcproj
similarity index 100%
rename from src/subprocess/deprecated_libcefpythonapp_py34_32bit.vcproj
rename to src/subprocess/deprecated/deprecated_libcefpythonapp_py34_32bit.vcproj
diff --git a/src/subprocess/deprecated_subprocess_64bit.vcproj b/src/subprocess/deprecated/deprecated_subprocess_64bit.vcproj
similarity index 100%
rename from src/subprocess/deprecated_subprocess_64bit.vcproj
rename to src/subprocess/deprecated/deprecated_subprocess_64bit.vcproj
diff --git a/src/subprocess/subprocess_win32.vcproj b/src/subprocess/deprecated/deprecated_subprocess_win32.vcproj
similarity index 100%
rename from src/subprocess/subprocess_win32.vcproj
rename to src/subprocess/deprecated/deprecated_subprocess_win32.vcproj
diff --git a/src/subprocess/javascript_callback.cpp b/src/subprocess/javascript_callback.cpp
index fd9f55e5..9aeaf80c 100644
--- a/src/subprocess/javascript_callback.cpp
+++ b/src/subprocess/javascript_callback.cpp
@@ -5,9 +5,9 @@
#include "javascript_callback.h"
#include
///
+#if defined(HAS_CPP11_TEMPLATE_ALIAS_SUPPORT)
+template
+using CefRefPtr = scoped_refptr;
+#else
+// When template aliases are not supported use a define instead of subclassing
+// because it's otherwise hard to get the constructors to behave correctly.
+#define CefRefPtr scoped_refptr
+#endif
+
+
+///
+// A CefOwnPtr is like a T*, except that the destructor of CefOwnPtr
+// automatically deletes the pointer it holds (if any). That is, CefOwnPtr
+// owns the T object that it points to. Like a T*, a CefOwnPtr may hold
+// either NULL or a pointer to a T object. Also like T*, CefOwnPtr is
+// thread-compatible, and once you dereference it, you get the thread safety
+// guarantees of T.
+///
+#if defined(USING_CHROMIUM_INCLUDES)
+// Implementation-side code uses std::unique_ptr instead of scoped_ptr.
+template >
+using CefOwnPtr = std::unique_ptr;
+#elif defined(HAS_CPP11_TEMPLATE_ALIAS_SUPPORT)
+template >
+using CefOwnPtr = scoped_ptr;
+#else
+// When template aliases are not supported use a define instead of subclassing
+// because it's otherwise hard to get the constructors to behave correctly.
+#define CefOwnPtr scoped_ptr
+#endif
+
+
+///
+// A CefRawPtr is the same as T*
+///
+#if defined(HAS_CPP11_TEMPLATE_ALIAS_SUPPORT)
template
-class CefRefPtr : public scoped_refptr {
+using CefRawPtr = T*;
+#else
+// Simple wrapper implementation that behaves as much like T* as possible.
+template
+class CefRawPtr {
public:
- typedef scoped_refptr parent;
+ CefRawPtr() : ptr_(nullptr) {}
+ CefRawPtr(T* p) : ptr_(p) {}
+ CefRawPtr(const CefRawPtr& r) : ptr_(r.ptr_) {}
+
+ template
+ CefRawPtr(const CefRawPtr& r) : ptr_(r.get()) {}
+
+ T* get() const { return ptr_; }
- CefRefPtr() : parent() {}
+ // Allow CefRawPtr to be used in boolean expression and comparison operations.
+ operator T*() const { return ptr_; }
- CefRefPtr(T* p) : parent(p) {}
+ T* operator->() const {
+ assert(ptr_ != NULL);
+ return ptr_;
+ }
- CefRefPtr(const scoped_refptr& r) : parent(r) {}
+ CefRawPtr& operator=(T* p) {
+ ptr_ = p;
+ return *this;
+ }
+
+ CefRawPtr& operator=(const CefRawPtr& r) {
+ return *this = r.ptr_;
+ }
template
- CefRefPtr(const scoped_refptr& r) : parent(r) {}
+ CefRawPtr& operator=(const CefRawPtr& r) {
+ return *this = r.get();
+ }
+
+ private:
+ T* ptr_;
};
+#endif
#endif // CEF_INCLUDE_INTERNAL_CEF_PTR_H_
diff --git a/src/include/internal/cef_string_types.h b/src/include/internal/cef_string_types.h
index ab21fe84..06206570 100644
--- a/src/include/internal/cef_string_types.h
+++ b/src/include/internal/cef_string_types.h
@@ -185,6 +185,17 @@ CEF_EXPORT void cef_string_userfree_utf8_free(cef_string_userfree_utf8_t str);
CEF_EXPORT void cef_string_userfree_utf16_free(cef_string_userfree_utf16_t str);
+///
+// These functions convert utf16 string case using the current ICU locale. This
+// may change the length of the string in some cases.
+///
+
+CEF_EXPORT int cef_string_utf16_to_lower(const char16* src, size_t src_len,
+ cef_string_utf16_t* output);
+CEF_EXPORT int cef_string_utf16_to_upper(const char16* src, size_t src_len,
+ cef_string_utf16_t* output);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/src/include/internal/cef_types.h b/src/include/internal/cef_types.h
index 01ef7d1a..b275079d 100644
--- a/src/include/internal/cef_types.h
+++ b/src/include/internal/cef_types.h
@@ -2396,6 +2396,13 @@ typedef struct _cef_pdf_print_settings_t {
int page_width;
int page_height;
+ ///
+ // The percentage to scale the PDF by before printing (e.g. 50 is 50%).
+ // If this value is less than or equal to zero the default value of 100
+ // will be used.
+ ///
+ int scale_factor;
+
///
// Margins in millimeters. Only used if |margin_type| is set to
// PDF_PRINT_MARGIN_CUSTOM.
@@ -2732,6 +2739,19 @@ typedef enum {
CEF_MENU_ANCHOR_BOTTOMCENTER,
} cef_menu_anchor_position_t;
+///
+// Supported color types for menu items.
+///
+typedef enum {
+ CEF_MENU_COLOR_TEXT,
+ CEF_MENU_COLOR_TEXT_HOVERED,
+ CEF_MENU_COLOR_TEXT_ACCELERATOR,
+ CEF_MENU_COLOR_TEXT_ACCELERATOR_HOVERED,
+ CEF_MENU_COLOR_BACKGROUND,
+ CEF_MENU_COLOR_BACKGROUND_HOVERED,
+ CEF_MENU_COLOR_COUNT,
+} cef_menu_color_type_t;
+
// Supported SSL version values. See net/ssl/ssl_connection_status_flags.h
// for more information.
typedef enum {
diff --git a/src/include/internal/cef_types_wrappers.h b/src/include/internal/cef_types_wrappers.h
index 0c125c96..da41f8d3 100644
--- a/src/include/internal/cef_types_wrappers.h
+++ b/src/include/internal/cef_types_wrappers.h
@@ -945,6 +945,8 @@ struct CefPdfPrintSettingsTraits {
target->page_width = src->page_width;
target->page_height = src->page_height;
+ target->scale_factor = src->scale_factor;
+
target->margin_top = src->margin_top;
target->margin_right = src->margin_right;
target->margin_bottom = src->margin_bottom;
diff --git a/src/include/test/cef_translator_test.h b/src/include/test/cef_translator_test.h
index c9398dad..29d1da26 100644
--- a/src/include/test/cef_translator_test.h
+++ b/src/include/test/cef_translator_test.h
@@ -53,10 +53,14 @@
#include "include/cef_base.h"
-class CefTranslatorTestHandler;
-class CefTranslatorTestHandlerChild;
-class CefTranslatorTestObject;
-class CefTranslatorTestObjectChild;
+class CefTranslatorTestRefPtrClient;
+class CefTranslatorTestRefPtrClientChild;
+class CefTranslatorTestRefPtrLibrary;
+class CefTranslatorTestRefPtrLibraryChild;
+class CefTranslatorTestScopedClient;
+class CefTranslatorTestScopedClientChild;
+class CefTranslatorTestScopedLibrary;
+class CefTranslatorTestScopedLibraryChild;
// Test values.
#define TEST_INT_VAL 5
@@ -79,8 +83,8 @@ class CefTranslatorTestObjectChild;
///
// Class for testing all of the possible data transfer types.
///
-/*--cef(source=library,no_debugct_check)--*/
-class CefTranslatorTest : public CefBase {
+/*--cef(source=library)--*/
+class CefTranslatorTest : public CefBaseRefCounted {
public:
///
// Create the test object.
@@ -309,146 +313,311 @@ class CefTranslatorTest : public CefBase {
virtual size_t GetPointListSize() = 0;
- // LIBRARY-SIDE OBJECT VALUES
+ // LIBRARY-SIDE REFPTR VALUES
///
// Return an new library-side object.
///
/*--cef()--*/
- virtual CefRefPtr GetObject(int val) =0;
+ virtual CefRefPtr GetRefPtrLibrary(
+ int val) =0;
///
- // Set an object. Returns the value from CefTranslatorTestObject::GetValue().
+ // Set an object. Returns the value from
+ // CefTranslatorTestRefPtrLibrary::GetValue().
// This tests input and execution of a library-side object type.
///
/*--cef()--*/
- virtual int SetObject(CefRefPtr val) =0;
+ virtual int SetRefPtrLibrary(
+ CefRefPtr val) =0;
///
// Set an object. Returns the object passed in. This tests input and output
// of a library-side object type.
///
/*--cef()--*/
- virtual CefRefPtr SetObjectAndReturn(
- CefRefPtr val) =0;
+ virtual CefRefPtr SetRefPtrLibraryAndReturn(
+ CefRefPtr val) =0;
///
// Set a child object. Returns the value from
- // CefTranslatorTestObject::GetValue(). This tests input of a library-side
- // child object type and execution as the parent type.
+ // CefTranslatorTestRefPtrLibrary::GetValue(). This tests input of a library-
+ // side child object type and execution as the parent type.
///
/*--cef()--*/
- virtual int SetChildObject(CefRefPtr val) =0;
+ virtual int SetChildRefPtrLibrary(
+ CefRefPtr val) =0;
///
// Set a child object. Returns the object as the parent type. This tests input
// of a library-side child object type and return as the parent type.
///
/*--cef()--*/
- virtual CefRefPtr SetChildObjectAndReturnParent(
- CefRefPtr val) =0;
+ virtual CefRefPtr
+ SetChildRefPtrLibraryAndReturnParent(
+ CefRefPtr val) =0;
- // LIBRARY-SIDE OBJECT LIST VALUES
+ // LIBRARY-SIDE REFPTR LIST VALUES
// Test both with and without a typedef.
- typedef std::vector > ObjectList;
+ typedef std::vector >
+ RefPtrLibraryList;
///
// Set an object list vlaue.
///
/*--cef()--*/
- virtual bool SetObjectList(
- const std::vector >& val,
+ virtual bool SetRefPtrLibraryList(
+ const std::vector >& val,
int val1, int val2) =0;
///
// Return an object list value by out-param.
///
- /*--cef(count_func=val:GetObjectListSize)--*/
- virtual bool GetObjectListByRef(ObjectList& val, int val1, int val2) =0;
+ /*--cef(count_func=val:GetRefPtrLibraryListSize)--*/
+ virtual bool GetRefPtrLibraryListByRef(RefPtrLibraryList& val, int val1,
+ int val2) =0;
///
// Return the number of object that will be output above.
///
/*--cef()--*/
- virtual size_t GetObjectListSize() = 0;
+ virtual size_t GetRefPtrLibraryListSize() = 0;
- // CLIENT-SIDE OBJECT VALUES
+ // CLIENT-SIDE REFPTR VALUES
///
- // Set an object. Returns the value from CefTranslatorTestHandler::GetValue().
+ // Set an object. Returns the value from
+ // CefTranslatorTestRefPtrClient::GetValue().
// This tests input and execution of a client-side object type.
///
/*--cef()--*/
- virtual int SetHandler(CefRefPtr val) =0;
+ virtual int SetRefPtrClient(CefRefPtr val) =0;
///
// Set an object. Returns the handler passed in. This tests input and output
// of a client-side object type.
///
/*--cef()--*/
- virtual CefRefPtr SetHandlerAndReturn(
- CefRefPtr val) =0;
+ virtual CefRefPtr SetRefPtrClientAndReturn(
+ CefRefPtr val) =0;
///
// Set a child object. Returns the value from
- // CefTranslatorTestHandler::GetValue(). This tests input of a client-side
- // child object type and execution as the parent type.
+ // CefTranslatorTestRefPtrClient::GetValue(). This tests input of a client-
+ // side child object type and execution as the parent type.
///
/*--cef()--*/
- virtual int SetChildHandler(CefRefPtr val) =0;
+ virtual int SetChildRefPtrClient(
+ CefRefPtr val) =0;
///
// Set a child object. Returns the object as the parent type. This tests
// input of a client-side child object type and return as the parent type.
///
/*--cef()--*/
- virtual CefRefPtr SetChildHandlerAndReturnParent(
- CefRefPtr val) =0;
+ virtual CefRefPtr
+ SetChildRefPtrClientAndReturnParent(
+ CefRefPtr val) =0;
- // CLIENT-SIDE OBJECT LIST VALUES
+ // CLIENT-SIDE REFPTR LIST VALUES
// Test both with and without a typedef.
- typedef std::vector > HandlerList;
+ typedef std::vector >
+ RefPtrClientList;
///
// Set an object list vlaue.
///
/*--cef()--*/
- virtual bool SetHandlerList(
- const std::vector >& val,
+ virtual bool SetRefPtrClientList(
+ const std::vector >& val,
int val1, int val2) =0;
///
// Return an object list value by out-param.
///
- /*--cef(count_func=val:GetObjectListSize)--*/
- virtual bool GetHandlerListByRef(
- HandlerList& val,
- CefRefPtr val1,
- CefRefPtr val2) =0;
+ /*--cef(count_func=val:GetRefPtrLibraryListSize)--*/
+ virtual bool GetRefPtrClientListByRef(
+ RefPtrClientList& val,
+ CefRefPtr val1,
+ CefRefPtr val2) =0;
///
// Return the number of object that will be output above.
///
/*--cef()--*/
- virtual size_t GetHandlerListSize() = 0;
+ virtual size_t GetRefPtrClientListSize() = 0;
+
+
+ // LIBRARY-SIDE OWNPTR VALUES
+
+ ///
+ // Return an new library-side object.
+ ///
+ /*--cef()--*/
+ virtual CefOwnPtr GetOwnPtrLibrary(
+ int val) =0;
+
+ ///
+ // Set an object. Returns the value from
+ // CefTranslatorTestScopedLibrary::GetValue().
+ // This tests input and execution of a library-side object type.
+ ///
+ /*--cef()--*/
+ virtual int SetOwnPtrLibrary(
+ CefOwnPtr val) =0;
+
+ ///
+ // Set an object. Returns the object passed in. This tests input and output
+ // of a library-side object type.
+ ///
+ /*--cef()--*/
+ virtual CefOwnPtr SetOwnPtrLibraryAndReturn(
+ CefOwnPtr val) =0;
+
+ ///
+ // Set a child object. Returns the value from
+ // CefTranslatorTestScopedLibrary::GetValue(). This tests input of a library-
+ // side child object type and execution as the parent type.
+ ///
+ /*--cef()--*/
+ virtual int SetChildOwnPtrLibrary(
+ CefOwnPtr val) =0;
+
+ ///
+ // Set a child object. Returns the object as the parent type. This tests input
+ // of a library-side child object type and return as the parent type.
+ ///
+ /*--cef()--*/
+ virtual CefOwnPtr
+ SetChildOwnPtrLibraryAndReturnParent(
+ CefOwnPtr val) =0;
+
+
+ // CLIENT-SIDE OWNPTR VALUES
+
+ ///
+ // Set an object. Returns the value from
+ // CefTranslatorTestScopedClient::GetValue().
+ // This tests input and execution of a client-side object type.
+ ///
+ /*--cef()--*/
+ virtual int SetOwnPtrClient(CefOwnPtr val) =0;
+
+ ///
+ // Set an object. Returns the handler passed in. This tests input and output
+ // of a client-side object type.
+ ///
+ /*--cef()--*/
+ virtual CefOwnPtr SetOwnPtrClientAndReturn(
+ CefOwnPtr val) =0;
+
+ ///
+ // Set a child object. Returns the value from
+ // CefTranslatorTestScopedClient::GetValue(). This tests input of a client-
+ // side child object type and execution as the parent type.
+ ///
+ /*--cef()--*/
+ virtual int SetChildOwnPtrClient(
+ CefOwnPtr val) =0;
+
+ ///
+ // Set a child object. Returns the object as the parent type. This tests
+ // input of a client-side child object type and return as the parent type.
+ ///
+ /*--cef()--*/
+ virtual CefOwnPtr
+ SetChildOwnPtrClientAndReturnParent(
+ CefOwnPtr val) =0;
+
+
+ // LIBRARY-SIDE RAWPTR VALUES
+
+ ///
+ // Set an object. Returns the value from
+ // CefTranslatorTestScopedLibrary::GetValue().
+ // This tests input and execution of a library-side object type.
+ ///
+ /*--cef()--*/
+ virtual int SetRawPtrLibrary(
+ CefRawPtr val) =0;
+
+ ///
+ // Set a child object. Returns the value from
+ // CefTranslatorTestScopedLibrary::GetValue(). This tests input of a library-
+ // side child object type and execution as the parent type.
+ ///
+ /*--cef()--*/
+ virtual int SetChildRawPtrLibrary(
+ CefRawPtr val) =0;
+
+
+ // LIBRARY-SIDE RAWPTR LIST VALUES
+
+ // Test both with and without a typedef.
+ typedef std::vector >
+ RawPtrLibraryList;
+
+ ///
+ // Set an object list vlaue.
+ ///
+ /*--cef()--*/
+ virtual bool SetRawPtrLibraryList(
+ const std::vector >& val,
+ int val1, int val2) =0;
+
+
+ // CLIENT-SIDE RAWPTR VALUES
+
+ ///
+ // Set an object. Returns the value from
+ // CefTranslatorTestScopedClient::GetValue().
+ // This tests input and execution of a client-side object type.
+ ///
+ /*--cef()--*/
+ virtual int SetRawPtrClient(CefRawPtr val) =0;
+
+ ///
+ // Set a child object. Returns the value from
+ // CefTranslatorTestScopedClient::GetValue(). This tests input of a client-
+ // side child object type and execution as the parent type.
+ ///
+ /*--cef()--*/
+ virtual int SetChildRawPtrClient(
+ CefRawPtr val) =0;
+
+
+ // CLIENT-SIDE RAWPTR LIST VALUES
+
+ // Test both with and without a typedef.
+ typedef std::vector >
+ RawPtrClientList;
+
+ ///
+ // Set an object list vlaue.
+ ///
+ /*--cef()--*/
+ virtual bool SetRawPtrClientList(
+ const std::vector >& val,
+ int val1, int val2) =0;
};
+
///
-// Library-side test object.
+// Library-side test object for RefPtr.
///
-/*--cef(source=library,no_debugct_check)--*/
-class CefTranslatorTestObject : public CefBase {
+/*--cef(source=library)--*/
+class CefTranslatorTestRefPtrLibrary : public CefBaseRefCounted {
public:
///
// Create the test object.
///
/*--cef()--*/
- static CefRefPtr Create(int value);
+ static CefRefPtr Create(int value);
///
// Return a value.
@@ -464,17 +633,129 @@ class CefTranslatorTestObject : public CefBase {
};
///
-// Library-side child test object.
+// Library-side child test object for RefPtr.
///
-/*--cef(source=library,no_debugct_check)--*/
-class CefTranslatorTestObjectChild : public CefTranslatorTestObject {
+/*--cef(source=library)--*/
+class CefTranslatorTestRefPtrLibraryChild :
+ public CefTranslatorTestRefPtrLibrary {
public:
///
// Create the test object.
///
/*--cef()--*/
- static CefRefPtr Create(int value,
- int other_value);
+ static CefRefPtr Create(
+ int value,
+ int other_value);
+
+ ///
+ // Return a value.
+ ///
+ /*--cef()--*/
+ virtual int GetOtherValue() =0;
+
+ ///
+ // Set a value.
+ ///
+ /*--cef()--*/
+ virtual void SetOtherValue(int value) =0;
+};
+
+///
+// Another library-side child test object for RefPtr.
+///
+/*--cef(source=library)--*/
+class CefTranslatorTestRefPtrLibraryChildChild :
+ public CefTranslatorTestRefPtrLibraryChild {
+ public:
+ ///
+ // Create the test object.
+ ///
+ /*--cef()--*/
+ static CefRefPtr Create(
+ int value,
+ int other_value,
+ int other_other_value);
+
+ ///
+ // Return a value.
+ ///
+ /*--cef()--*/
+ virtual int GetOtherOtherValue() =0;
+
+ ///
+ // Set a value.
+ ///
+ /*--cef()--*/
+ virtual void SetOtherOtherValue(int value) =0;
+};
+
+///
+// Client-side test object for RefPtr.
+///
+/*--cef(source=client)--*/
+class CefTranslatorTestRefPtrClient : public virtual CefBaseRefCounted {
+ public:
+ ///
+ // Return a value.
+ ///
+ /*--cef()--*/
+ virtual int GetValue() =0;
+};
+
+///
+// Client-side child test object for RefPtr.
+///
+/*--cef(source=client)--*/
+class CefTranslatorTestRefPtrClientChild :
+ public CefTranslatorTestRefPtrClient {
+ public:
+ ///
+ // Return a value.
+ ///
+ /*--cef()--*/
+ virtual int GetOtherValue() =0;
+};
+
+
+///
+// Library-side test object for OwnPtr/RawPtr.
+///
+/*--cef(source=library)--*/
+class CefTranslatorTestScopedLibrary : public CefBaseScoped {
+ public:
+ ///
+ // Create the test object.
+ ///
+ /*--cef()--*/
+ static CefOwnPtr Create(int value);
+
+ ///
+ // Return a value.
+ ///
+ /*--cef()--*/
+ virtual int GetValue() =0;
+
+ ///
+ // Set a value.
+ ///
+ /*--cef()--*/
+ virtual void SetValue(int value) =0;
+};
+
+///
+// Library-side child test object for OwnPtr/RawPtr.
+///
+/*--cef(source=library)--*/
+class CefTranslatorTestScopedLibraryChild :
+ public CefTranslatorTestScopedLibrary {
+ public:
+ ///
+ // Create the test object.
+ ///
+ /*--cef()--*/
+ static CefOwnPtr Create(
+ int value,
+ int other_value);
///
// Return a value.
@@ -490,16 +771,17 @@ class CefTranslatorTestObjectChild : public CefTranslatorTestObject {
};
///
-// Another library-side child test object.
+// Another library-side child test object for OwnPtr/RawPtr.
///
-/*--cef(source=library,no_debugct_check)--*/
-class CefTranslatorTestObjectChildChild : public CefTranslatorTestObjectChild {
+/*--cef(source=library)--*/
+class CefTranslatorTestScopedLibraryChildChild :
+ public CefTranslatorTestScopedLibraryChild {
public:
///
// Create the test object.
///
/*--cef()--*/
- static CefRefPtr Create(
+ static CefOwnPtr Create(
int value,
int other_value,
int other_other_value);
@@ -518,10 +800,10 @@ class CefTranslatorTestObjectChildChild : public CefTranslatorTestObjectChild {
};
///
-// Client-side test object.
+// Client-side test object for OwnPtr/RawPtr.
///
-/*--cef(source=client,no_debugct_check)--*/
-class CefTranslatorTestHandler : public virtual CefBase {
+/*--cef(source=client)--*/
+class CefTranslatorTestScopedClient : public virtual CefBaseScoped {
public:
///
// Return a value.
@@ -531,10 +813,11 @@ class CefTranslatorTestHandler : public virtual CefBase {
};
///
-// Client-side child test object.
+// Client-side child test object for OwnPtr/RawPtr.
///
-/*--cef(source=client,no_debugct_check)--*/
-class CefTranslatorTestHandlerChild : public CefTranslatorTestHandler {
+/*--cef(source=client)--*/
+class CefTranslatorTestScopedClientChild :
+ public CefTranslatorTestScopedClient {
public:
///
// Return a value.
diff --git a/src/include/views/cef_browser_view.h b/src/include/views/cef_browser_view.h
index 2ae068d9..db622d4d 100644
--- a/src/include/views/cef_browser_view.h
+++ b/src/include/views/cef_browser_view.h
@@ -74,6 +74,18 @@ class CefBrowserView : public CefView {
///
/*--cef()--*/
virtual CefRefPtr GetBrowser() =0;
+
+ ///
+ // Sets whether accelerators registered with CefWindow::SetAccelerator are
+ // triggered before or after the event is sent to the CefBrowser. If
+ // |prefer_accelerators| is true then the matching accelerator will be
+ // triggered immediately and the event will not be sent to the CefBrowser. If
+ // |prefer_accelerators| is false then the matching accelerator will only be
+ // triggered if the event is not handled by web content or by
+ // CefKeyboardHandler. The default value is false.
+ ///
+ /*--cef()--*/
+ virtual void SetPreferAccelerators(bool prefer_accelerators) =0;
};
#endif // CEF_INCLUDE_VIEWS_CEF_BROWSER_VIEW_H_
diff --git a/src/include/views/cef_button.h b/src/include/views/cef_button.h
index 2feda9a6..db3db7d6 100644
--- a/src/include/views/cef_button.h
+++ b/src/include/views/cef_button.h
@@ -68,6 +68,12 @@ class CefButton : public CefView {
/*--cef(default_retval=CEF_BUTTON_STATE_NORMAL)--*/
virtual cef_button_state_t GetState() =0;
+ ///
+ // Sets the Button will use an ink drop effect for displaying state changes.
+ ///
+ /*--cef()--*/
+ virtual void SetInkDropEnabled(bool enabled) =0;
+
///
// Sets the tooltip text that will be displayed when the user hovers the mouse
// cursor over the Button.
diff --git a/src/include/views/cef_button_delegate.h b/src/include/views/cef_button_delegate.h
index 99bd126e..ec33d9be 100644
--- a/src/include/views/cef_button_delegate.h
+++ b/src/include/views/cef_button_delegate.h
@@ -54,6 +54,12 @@ class CefButtonDelegate : public CefViewDelegate {
///
/*--cef()--*/
virtual void OnButtonPressed(CefRefPtr button) =0;
+
+ ///
+ // Called when the state of |button| changes.
+ ///
+ /*--cef()--*/
+ virtual void OnButtonStateChanged(CefRefPtr button) {};
};
#endif // CEF_INCLUDE_VIEWS_CEF_BUTTON_DELEGATE_H_
diff --git a/src/include/views/cef_display.h b/src/include/views/cef_display.h
index d9da0602..e3a84561 100644
--- a/src/include/views/cef_display.h
+++ b/src/include/views/cef_display.h
@@ -51,7 +51,7 @@
// indicated.
///
/*--cef(source=library)--*/
-class CefDisplay : public CefBase {
+class CefDisplay : public CefBaseRefCounted {
public:
///
// Returns the primary Display.
diff --git a/src/include/views/cef_layout.h b/src/include/views/cef_layout.h
index d820a275..5f1fcf4e 100644
--- a/src/include/views/cef_layout.h
+++ b/src/include/views/cef_layout.h
@@ -49,7 +49,7 @@ class CefFillLayout;
// process UI thread unless otherwise indicated.
///
/*--cef(source=library)--*/
-class CefLayout : public CefBase {
+class CefLayout : public CefBaseRefCounted {
public:
///
// Returns this Layout as a BoxLayout or NULL if this is not a BoxLayout.
diff --git a/src/include/views/cef_menu_button.h b/src/include/views/cef_menu_button.h
index 4ae8c4f3..60f803c4 100644
--- a/src/include/views/cef_menu_button.h
+++ b/src/include/views/cef_menu_button.h
@@ -78,6 +78,13 @@ class CefMenuButton : public CefLabelButton {
virtual void ShowMenu(CefRefPtr menu_model,
const CefPoint& screen_point,
cef_menu_anchor_position_t anchor_position) =0;
+
+ ///
+ // Show the menu for this button. Results in a call to
+ // CefMenuButtonDelegate::OnMenuButtonPressed().
+ ///
+ /*--cef()--*/
+ virtual void TriggerMenu() =0;
};
#endif // CEF_INCLUDE_VIEWS_CEF_MENU_BUTTON_H_
diff --git a/src/include/views/cef_view.h b/src/include/views/cef_view.h
index b6f321e0..78422fec 100644
--- a/src/include/views/cef_view.h
+++ b/src/include/views/cef_view.h
@@ -54,7 +54,7 @@ class CefWindow;
// process UI thread unless otherwise indicated.
///
/*--cef(source=library)--*/
-class CefView : public CefBase {
+class CefView : public CefBaseRefCounted {
public:
///
// Returns this View as a BrowserView or NULL if this is not a BrowserView.
@@ -145,6 +145,20 @@ class CefView : public CefBase {
/*--cef()--*/
virtual void SetID(int id) =0;
+ ///
+ // Returns the group id of this View, or -1 if not set.
+ ///
+ /*--cef()--*/
+ virtual int GetGroupID() =0;
+
+ ///
+ // A group id is used to tag Views which are part of the same logical group.
+ // Focus can be moved between views with the same group using the arrow keys.
+ // The group id is immutable once it's set.
+ ///
+ /*--cef()--*/
+ virtual void SetGroupID(int group_id) =0;
+
///
// Returns the View that contains this View, if any.
///
diff --git a/src/include/views/cef_view_delegate.h b/src/include/views/cef_view_delegate.h
index 70fd176c..523b0528 100644
--- a/src/include/views/cef_view_delegate.h
+++ b/src/include/views/cef_view_delegate.h
@@ -47,7 +47,7 @@ class CefView;
// will be called on the browser process UI thread unless otherwise indicated.
///
/*--cef(source=client)--*/
-class CefViewDelegate : public virtual CefBase {
+class CefViewDelegate : public virtual CefBaseRefCounted {
public:
///
// Return the preferred size for |view|. The Layout will use this information
@@ -108,6 +108,18 @@ class CefViewDelegate : public virtual CefBase {
virtual void OnChildViewChanged(CefRefPtr view,
bool added,
CefRefPtr child) {}
+
+ ///
+ // Called when |view| gains focus.
+ ///
+ /*--cef()--*/
+ virtual void OnFocus(CefRefPtr view) {}
+
+ ///
+ // Called when |view| loses focus.
+ ///
+ /*--cef()--*/
+ virtual void OnBlur(CefRefPtr view) {}
};
#endif // CEF_INCLUDE_VIEWS_CEF_WINDOW_DELEGATE_H_
diff --git a/src/include/views/cef_window.h b/src/include/views/cef_window.h
index b6ec638e..a89ab63a 100644
--- a/src/include/views/cef_window.h
+++ b/src/include/views/cef_window.h
@@ -289,6 +289,30 @@ class CefWindow : public CefPanel {
virtual void SendMouseEvents(cef_mouse_button_type_t button,
bool mouse_down,
bool mouse_up) =0;
+ ///
+ // Set the keyboard accelerator for the specified |command_id|. |key_code| can
+ // be any virtual key or character value. CefWindowDelegate::OnAccelerator
+ // will be called if the keyboard combination is triggered while this window
+ // has focus.
+ ///
+ /*--cef()--*/
+ virtual void SetAccelerator(int command_id,
+ int key_code,
+ bool shift_pressed,
+ bool ctrl_pressed,
+ bool alt_pressed) =0;
+
+ ///
+ // Remove the keyboard accelerator for the specified |command_id|.
+ ///
+ /*--cef()--*/
+ virtual void RemoveAccelerator(int command_id) =0;
+
+ ///
+ // Remove all keyboard accelerators.
+ ///
+ /*--cef()--*/
+ virtual void RemoveAllAccelerators() =0;
};
#endif // CEF_INCLUDE_VIEWS_CEF_WINDOW_H_
diff --git a/src/include/views/cef_window_delegate.h b/src/include/views/cef_window_delegate.h
index 19deae72..a50e1fc4 100644
--- a/src/include/views/cef_window_delegate.h
+++ b/src/include/views/cef_window_delegate.h
@@ -95,6 +95,25 @@ class CefWindowDelegate : public CefPanelDelegate {
///
/*--cef()--*/
virtual bool CanClose(CefRefPtr window) { return true; }
+
+ ///
+ // Called when a keyboard accelerator registered with
+ // CefWindow::SetAccelerator is triggered. Return true if the accelerator was
+ // handled or false otherwise.
+ ///
+ /*--cef()--*/
+ virtual bool OnAccelerator(CefRefPtr window,
+ int command_id) { return false; }
+
+ ///
+ // Called after all other controls in the window have had a chance to
+ // handle the event. |event| contains information about the keyboard event.
+ // Return true if the keyboard event was handled or false otherwise.
+ ///
+ /*--cef()--*/
+ virtual bool OnKeyEvent(CefRefPtr window,
+ const CefKeyEvent& event) { return false; }
+
};
#endif // CEF_INCLUDE_VIEWS_CEF_WINDOW_DELEGATE_H_
diff --git a/src/include/wrapper/cef_byte_read_handler.h b/src/include/wrapper/cef_byte_read_handler.h
index 559cdd81..bf593d0a 100644
--- a/src/include/wrapper/cef_byte_read_handler.h
+++ b/src/include/wrapper/cef_byte_read_handler.h
@@ -55,7 +55,7 @@ class CefByteReadHandler : public CefReadHandler {
///
CefByteReadHandler(const unsigned char* bytes,
size_t size,
- CefRefPtr source);
+ CefRefPtr source);
// CefReadHandler methods.
virtual size_t Read(void* ptr, size_t size, size_t n) OVERRIDE;
@@ -68,7 +68,7 @@ class CefByteReadHandler : public CefReadHandler {
const unsigned char* bytes_;
int64 size_;
int64 offset_;
- CefRefPtr source_;
+ CefRefPtr source_;
base::Lock lock_;
diff --git a/src/include/wrapper/cef_closure_task.h b/src/include/wrapper/cef_closure_task.h
index 8828c656..d9b559b6 100644
--- a/src/include/wrapper/cef_closure_task.h
+++ b/src/include/wrapper/cef_closure_task.h
@@ -64,7 +64,7 @@
// Example of executing a bound method:
//
// // Define a class.
-// class MyClass : public CefBase {
+// class MyClass : public CefBaseRefCounted {
// public:
// MyClass() {}
// void MyMethod(int arg) { /* do something with |arg| on the UI thread */ }
diff --git a/src/include/wrapper/cef_message_router.h b/src/include/wrapper/cef_message_router.h
index 2a6fcfe6..23510ddc 100644
--- a/src/include/wrapper/cef_message_router.h
+++ b/src/include/wrapper/cef_message_router.h
@@ -223,7 +223,7 @@ class CefMessageRouterBrowserSide :
// the callback methods. The methods of this class may be called on any
// browser process thread.
///
- class Callback : public CefBase {
+ class Callback : public CefBaseRefCounted {
public:
///
// Notify the associated JavaScript onSuccess callback that the query has
diff --git a/src/include/wrapper/cef_zip_archive.h b/src/include/wrapper/cef_zip_archive.h
index 7ad10bda..5de0960f 100644
--- a/src/include/wrapper/cef_zip_archive.h
+++ b/src/include/wrapper/cef_zip_archive.h
@@ -62,7 +62,7 @@ class CefZipArchive : public base::RefCountedThreadSafe {
// Class representing a file in the archive. Accessing the file data from
// multiple threads is safe provided a reference to the File object is kept.
///
- class File : public CefBase {
+ class File : public CefBaseRefCounted {
public:
///
// Returns the read-only data contained in the file.
From 9930aa87f180165b9b0f22be83d6896b2f9ab19a Mon Sep 17 00:00:00 2001
From: cztomczak
Date: Thu, 20 Apr 2017 15:18:24 +0200
Subject: [PATCH 018/356] Support Qt 5 in qt4.py example (type: qt4.py pyqt5)
(#325).
Tested on Linux.
---
examples/qt4.py | 72 ++++++++++++---------
examples/resources/{pyqt.png => pyqt4.png} | Bin
examples/resources/pyqt5.png | Bin 0 -> 20781 bytes
3 files changed, 43 insertions(+), 29 deletions(-)
rename examples/resources/{pyqt.png => pyqt4.png} (100%)
create mode 100644 examples/resources/pyqt5.png
diff --git a/examples/qt4.py b/examples/qt4.py
index 7b3516a2..fe591eed 100644
--- a/examples/qt4.py
+++ b/examples/qt4.py
@@ -1,12 +1,14 @@
-# Example of embedding CEF browser using PyQt/PySide libraries.
-# This example has two widgets: a navigation bar and a browser.
+# Example of embedding CEF browser using PyQt4, PyQt5 and
+# PySide libraries. This example has two widgets: a navigation
+# bar and a browser.
#
# Tested configurations:
+# - PyQt 5.8.2 on Linux
# - PyQt 4.11 (qt 4.8) on Windows/Linux
# - PySide 1.2 (qt 4.8) on Windows/Linux/Mac
# - CEF Python v55.4+
#
-# Issues on Mac (tested with PySide):
+# Issues with PySide 1.2 on Mac:
# - Keyboard focus issues when switching between controls (Issue #284)
# - Mouse cursor never changes when hovering over links (Issue #311)
# - Sometimes process hangs when quitting app
@@ -17,25 +19,32 @@
import platform
import sys
+# GLOBALS
+PYQT4 = False
+PYQT5 = False
+PYSIDE = False
+
# PyQt imports
-if "pyqt" in sys.argv:
- # noinspection PyUnresolvedReferences
+if "pyqt4" in sys.argv:
+ PYQT4 = True
from PyQt4.QtGui import *
- # noinspection PyUnresolvedReferences
from PyQt4.QtCore import *
+elif "pyqt5" in sys.argv:
+ PYQT5 = True
+ from PyQt5.QtGui import *
+ from PyQt5.QtCore import *
+ from PyQt5.QtWidgets import *
# PySide imports
elif "pyside" in sys.argv:
- # noinspection PyUnresolvedReferences
+ PYSIDE = True
import PySide
- # noinspection PyUnresolvedReferences
from PySide import QtCore
- # noinspection PyUnresolvedReferences
from PySide.QtGui import *
- # noinspection PyUnresolvedReferences
from PySide.QtCore import *
else:
print("USAGE:")
- print(" qt4.py pyqt")
+ print(" qt4.py pyqt4")
+ print(" qt4.py pyqt5")
print(" qt4.py pyside")
sys.exit(1)
@@ -53,8 +62,7 @@
# OS differences
CefWidgetParent = QWidget
-if LINUX:
- # noinspection PyUnresolvedReferences
+if LINUX and (PYQT4 or PYSIDE):
CefWidgetParent = QX11EmbedContainer
@@ -78,17 +86,14 @@ def check_versions():
print("[qt4.py] CEF Python {ver}".format(ver=cef.__version__))
print("[qt4.py] Python {ver} {arch}".format(
ver=platform.python_version(), arch=platform.architecture()[0]))
- # PyQt version
- if "pyqt" in sys.argv:
- # noinspection PyUnresolvedReferences
+ if PYQT4 or PYQT5:
print("[qt4.py] PyQt {v1} (qt {v2})".format(
v1=PYQT_VERSION_STR, v2=qVersion()))
- # PySide version
- elif "pyside" in sys.argv:
+ elif PYSIDE:
print("[qt4.py] PySide {v1} (qt {v2})".format(
v1=PySide.__version__, v2=QtCore.__version__))
# CEF Python version requirement
- assert cef.__version__ >= "55.4", "CEF Python v55.+ required to run this"
+ assert cef.__version__ >= "55.4", "CEF Python v55.4+ required to run this"
class MainWindow(QMainWindow):
@@ -96,9 +101,11 @@ def __init__(self):
super(MainWindow, self).__init__(None)
self.cef_widget = None
self.navigation_bar = None
- if "pyqt" in sys.argv:
- self.setWindowTitle("PyQt example")
- elif "pyside" in sys.argv:
+ if PYQT4:
+ self.setWindowTitle("PyQt4 example")
+ elif PYQT5:
+ self.setWindowTitle("PyQt5 example")
+ elif PYSIDE:
self.setWindowTitle("PySide example")
self.setFocusPolicy(Qt.StrongFocus)
self.setupLayout()
@@ -119,6 +126,10 @@ def setupLayout(self):
self.setCentralWidget(frame)
# Browser can be embedded only after layout was set up
self.cef_widget.embedBrowser()
+ if LINUX and PYQT5:
+ self.container = QWidget.createWindowContainer(
+ self.cef_widget.hidden_window, parent=self)
+ layout.addWidget(self.container, 1, 0)
def closeEvent(self, event):
# Close browser (force=True) and free CEF reference
@@ -137,6 +148,7 @@ def __init__(self, parent=None):
super(CefWidget, self).__init__(parent)
self.parent = parent
self.browser = None
+ self.hidden_window = None # Required for PyQt5 on Linux
self.show()
def focusInEvent(self, event):
@@ -154,6 +166,8 @@ def focusOutEvent(self, event):
self.browser.SetFocus(False)
def embedBrowser(self):
+ if LINUX and PYQT5:
+ self.hidden_window = QWindow()
window_info = cef.WindowInfo()
rect = [0, 0, self.width(), self.height()]
window_info.SetAsChild(self.getHandle(), rect)
@@ -163,11 +177,16 @@ def embedBrowser(self):
self.browser.SetClientHandler(FocusHandler(self))
def getHandle(self):
- # PySide bug: QWidget.winId() returns
- # There is no easy way to convert it to int.
+ # PyQt5 on Linux
+ if self.hidden_window:
+ return int(self.hidden_window.winId())
try:
+ # PyQt4 and PyQt5
return int(self.winId())
except:
+ # PySide:
+ # | QWidget.winId() returns
+ # | Converting it to int using ctypes.
if sys.version_info[0] == 2:
# Python 2
ctypes.pythonapi.PyCObject_AsVoidPtr.restype = (
@@ -214,7 +233,6 @@ def __init__(self, args):
def createTimer(self):
timer = QTimer()
- # noinspection PyUnresolvedReferences
timer.timeout.connect(self.onTimer)
timer.start(10)
return timer
@@ -280,25 +298,21 @@ def __init__(self, cef_widget):
# Back button
self.back = self.createButton("back")
- # noinspection PyUnresolvedReferences
self.back.clicked.connect(self.onBack)
layout.addWidget(self.back, 0, 0)
# Forward button
self.forward = self.createButton("forward")
- # noinspection PyUnresolvedReferences
self.forward.clicked.connect(self.onForward)
layout.addWidget(self.forward, 0, 1)
# Reload button
self.reload = self.createButton("reload")
- # noinspection PyUnresolvedReferences
self.reload.clicked.connect(self.onReload)
layout.addWidget(self.reload, 0, 2)
# Url input
self.url = QLineEdit("")
- # noinspection PyUnresolvedReferences
self.url.returnPressed.connect(self.onGoUrl)
layout.addWidget(self.url, 0, 3)
diff --git a/examples/resources/pyqt.png b/examples/resources/pyqt4.png
similarity index 100%
rename from examples/resources/pyqt.png
rename to examples/resources/pyqt4.png
diff --git a/examples/resources/pyqt5.png b/examples/resources/pyqt5.png
new file mode 100644
index 0000000000000000000000000000000000000000..a41981951b57be5fe10d2fee9562aba5a04ade37
GIT binary patch
literal 20781
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