From 27b4a4cb341d94943bf75a69837cff7b89d09511 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 24 Feb 2016 13:15:14 +0100 Subject: [PATCH 001/557] Code and documentation cleanup PART 2. Issues: #211, #208, #150, #106. --- .gitignore | 6 +- AUTHORS.txt | 29 +- cefpython/LICENSE.txt => LICENSE.txt | 9 +- README.md | 7 + cefpython/cef1/BUILD_COMPATIBILITY.txt | 16 - cefpython/cef1/cefpython_public_api.h | 30 - cefpython/cef1/client_handler/.gitignore | 2 - cefpython/cef1/client_handler/Makefile | 20 - .../cef1/client_handler/client_handler.cpp | 347 ----- .../cef1/client_handler/client_handler.h | 304 ----- .../cef1/client_handler/client_handler.sln | 25 - .../client_handler/client_handler_py27.vcproj | 205 --- .../client_handler/client_handler_py32.vcproj | 204 --- .../client_handler/content_filter_handler.cpp | 17 - .../client_handler/content_filter_handler.h | 31 - .../cef1/client_handler/cookie_visitor.cpp | 16 - .../cef1/client_handler/cookie_visitor.h | 32 - .../cef1/client_handler/download_handler.cpp | 25 - .../cef1/client_handler/download_handler.h | 30 - .../client_handler/web_request_client.cpp | 47 - .../cef1/client_handler/web_request_client.h | 44 - .../http_authentication/AuthCredentials.cpp | 3 - .../http_authentication/AuthCredentials.h | 32 - .../cef1/http_authentication/AuthDialog.cpp | 87 -- .../cef1/http_authentication/AuthDialog.h | 13 - .../http_authentication/DialogTemplate.cpp | 236 ---- .../cef1/http_authentication/DialogTemplate.h | 68 - .../http_authentication.sln | 20 - .../http_authentication.vcproj | 187 --- cefpython/cef1/include/cef_app.h | 139 -- cefpython/cef1/include/cef_application_mac.h | 120 -- cefpython/cef1/include/cef_base.h | 154 --- cefpython/cef1/include/cef_browser.h | 344 ----- cefpython/cef1/include/cef_client.h | 196 --- cefpython/cef1/include/cef_command_line.h | 160 --- cefpython/cef1/include/cef_content_filter.h | 68 - cefpython/cef1/include/cef_cookie.h | 147 -- cefpython/cef1/include/cef_display_handler.h | 124 -- cefpython/cef1/include/cef_dom.h | 429 ------ cefpython/cef1/include/cef_download_handler.h | 65 - cefpython/cef1/include/cef_drag_data.h | 120 -- cefpython/cef1/include/cef_drag_handler.h | 77 -- cefpython/cef1/include/cef_find_handler.h | 68 - cefpython/cef1/include/cef_focus_handler.h | 88 -- cefpython/cef1/include/cef_frame.h | 220 --- cefpython/cef1/include/cef_geolocation.h | 66 - .../cef1/include/cef_geolocation_handler.h | 94 -- cefpython/cef1/include/cef_jsdialog_handler.h | 87 -- cefpython/cef1/include/cef_keyboard_handler.h | 76 -- .../cef1/include/cef_life_span_handler.h | 105 -- cefpython/cef1/include/cef_load_handler.h | 94 -- cefpython/cef1/include/cef_menu_handler.h | 80 -- cefpython/cef1/include/cef_nplugin.h | 119 -- cefpython/cef1/include/cef_origin_whitelist.h | 102 -- .../cef1/include/cef_permission_handler.h | 64 - cefpython/cef1/include/cef_print_handler.h | 91 -- cefpython/cef1/include/cef_proxy_handler.h | 57 - cefpython/cef1/include/cef_render_handler.h | 121 -- cefpython/cef1/include/cef_request.h | 255 ---- cefpython/cef1/include/cef_request_handler.h | 171 --- .../include/cef_resource_bundle_handler.h | 82 -- cefpython/cef1/include/cef_response.h | 104 -- cefpython/cef1/include/cef_runnable.h | 346 ----- cefpython/cef1/include/cef_scheme.h | 231 ---- cefpython/cef1/include/cef_stream.h | 210 --- cefpython/cef1/include/cef_task.h | 89 -- cefpython/cef1/include/cef_url.h | 60 - cefpython/cef1/include/cef_v8.h | 851 ------------ .../cef1/include/cef_v8context_handler.h | 85 -- cefpython/cef1/include/cef_version.h | 68 - cefpython/cef1/include/cef_web_plugin.h | 97 -- cefpython/cef1/include/cef_web_urlrequest.h | 135 -- cefpython/cef1/include/cef_xml_reader.h | 268 ---- cefpython/cef1/include/cef_zip_reader.h | 141 -- cefpython/cef1/include/cef_zoom_handler.h | 72 - cefpython/cef1/include/internal/cef_build.h | 129 -- cefpython/cef1/include/internal/cef_export.h | 55 - cefpython/cef1/include/internal/cef_linux.h | 149 -- cefpython/cef1/include/internal/cef_mac.h | 178 --- .../cef1/include/internal/cef_nplugin_types.h | 90 -- cefpython/cef1/include/internal/cef_ptr.h | 199 --- cefpython/cef1/include/internal/cef_string.h | 113 -- .../cef1/include/internal/cef_string_list.h | 88 -- .../cef1/include/internal/cef_string_map.h | 97 -- .../include/internal/cef_string_multimap.h | 105 -- .../cef1/include/internal/cef_string_types.h | 204 --- .../include/internal/cef_string_wrappers.h | 712 ---------- cefpython/cef1/include/internal/cef_time.h | 88 -- cefpython/cef1/include/internal/cef_tuple.h | 1082 --------------- cefpython/cef1/include/internal/cef_types.h | 1212 ----------------- .../cef1/include/internal/cef_types_linux.h | 88 -- .../cef1/include/internal/cef_types_mac.h | 116 -- .../cef1/include/internal/cef_types_win.h | 110 -- .../include/internal/cef_types_wrappers.h | 687 ---------- cefpython/cef1/include/internal/cef_win.h | 186 --- .../include/wrapper/cef_byte_read_handler.h | 88 -- .../cef1/include/wrapper/cef_xml_object.h | 188 --- .../cef1/include/wrapper/cef_zip_archive.h | 132 -- cefpython/cef1/linux/CEF-GTK-patch.txt | 54 - .../cef1/linux/binaries_32bit/LICENSE.txt | 36 - .../linux/binaries_32bit/cefpython_py27.py | 815 ----------- .../cef1/linux/binaries_32bit/cefsimple.html | 37 - cefpython/cef1/linux/binaries_32bit/pygtk_.py | 191 --- .../cef1/linux/binaries_32bit/wxpython.html | 172 --- .../cef1/linux/binaries_32bit/wxpython.py | 528 ------- .../cef1/linux/binaries_64bit/LICENSE.txt | 36 - .../linux/binaries_64bit/cefpython_py27.py | 815 ----------- .../cef1/linux/binaries_64bit/cefsimple.html | 37 - cefpython/cef1/linux/binaries_64bit/pygtk_.py | 191 --- .../cef1/linux/binaries_64bit/wxpython.html | 172 --- .../cef1/linux/binaries_64bit/wxpython.py | 529 ------- cefpython/cef1/linux/compile.py | 127 -- cefpython/cef1/linux/example.py | 11 - .../cef1/linux/installer/README.txt.template | 23 - .../cef1/linux/installer/__init__.py.template | 12 - cefpython/cef1/linux/installer/make-setup.py | 119 -- .../cef1/linux/installer/setup.py.template | 26 - cefpython/cef1/linux/setup/.gitignore | 5 - cefpython/cef1/linux/setup/cefpython.h | 64 - cefpython/cef1/linux/setup/fix_includes.py | 109 -- cefpython/cef1/linux/setup/setup.py | 105 -- cefpython/cef1/util.h | 37 - cefpython/cef1/v8function_handler/.gitignore | 2 - cefpython/cef1/v8function_handler/Makefile | 20 - .../v8function_handler/v8function_handler.cpp | 15 - .../v8function_handler/v8function_handler.h | 66 - .../v8function_handler/v8function_handler.sln | 25 - .../v8function_handler_py27.vcproj | 172 --- .../v8function_handler_py32.vcproj | 172 --- cefpython/cef1/windows/.gitignore | 10 - cefpython/cef1/windows/binaries/LICENSE.txt | 36 - .../binaries/Microsoft.VC90.CRT.manifest | 6 - cefpython/cef1/windows/binaries/README.txt | 112 -- .../cef1/windows/binaries/cefadvanced.html | 306 ----- .../cef1/windows/binaries/cefadvanced.py | 505 ------- .../windows/binaries/cefclient_dcheck.bat | 2 - .../cef1/windows/binaries/cefpython_py27.py | 815 ----------- .../cef1/windows/binaries/cefpython_py32.py | 815 ----------- .../cef1/windows/binaries/cefsimple.html | 37 - cefpython/cef1/windows/binaries/cefsimple.py | 109 -- cefpython/cef1/windows/binaries/cefwindow.py | 205 --- cefpython/cef1/windows/binaries/cefwxpanel.py | 147 -- .../windows/binaries/cefwxpanel_sample1.py | 33 - .../windows/binaries/cefwxpanel_sample2.py | 70 - cefpython/cef1/windows/binaries/debug_gdb.bat | 7 - cefpython/cef1/windows/binaries/debug_pdb.bat | 3 - cefpython/cef1/windows/binaries/icon.ico | Bin 198275 -> 0 bytes cefpython/cef1/windows/binaries/panda3d_.py | 417 ------ cefpython/cef1/windows/binaries/pygtk_.py | 193 --- cefpython/cef1/windows/binaries/pyqt.py | 167 --- cefpython/cef1/windows/binaries/pyside.py | 184 --- cefpython/cef1/windows/binaries/wxpython.html | 172 --- cefpython/cef1/windows/binaries/wxpython.py | 526 ------- cefpython/cef1/windows/cefadvanced.bat | 1 - cefpython/cef1/windows/cefpython.pyd.manifest | 15 - cefpython/cef1/windows/compile.bat | 50 - .../windows/installer/__init__.py.template | 11 - .../cef1/windows/installer/innosetup.template | 181 --- .../cef1/windows/installer/make-installer.py | 73 - cefpython/cef1/windows/setup/.gitignore | 3 - cefpython/cef1/windows/setup/cefpython.h | 71 - .../cef1/windows/setup/delete_pyx_files.bat | 2 - cefpython/cef1/windows/setup/fix_includes.py | 109 -- cefpython/cef1/windows/setup/setup.py | 108 -- cefpython/cef1/windows/stdint.h | 247 ---- cefpython/cef1/wx-subpackage/README.txt | 6 - cefpython/cef1/wx-subpackage/__init__.py | 0 cefpython/cef1/wx-subpackage/chromectrl.py | 314 ----- .../cef1/wx-subpackage/examples/back.png | Bin 1348 -> 0 bytes .../cef1/wx-subpackage/examples/forward.png | Bin 1311 -> 0 bytes .../wx-subpackage/examples/reload_page.png | Bin 1420 -> 0 bytes .../cef1/wx-subpackage/examples/sample1.html | 33 - .../cef1/wx-subpackage/examples/sample1.py | 34 - .../cef1/wx-subpackage/examples/sample2.py | 74 - .../cef1/wx-subpackage/examples/sample3.py | 79 -- .../cef1/wx-subpackage/images/Arrow Left.png | Bin 3798 -> 0 bytes .../cef1/wx-subpackage/images/Arrow Right.png | Bin 3824 -> 0 bytes .../cef1/wx-subpackage/images/Button Load.png | Bin 4880 -> 0 bytes cefpython/cef1/wx-subpackage/utils.py | 19 - cefpython/cef1_api.py | 815 ----------- cefpython/cefpython.pyx | 4 - cefpython/content_filter.pyx | 117 -- cefpython/ctags.bat | 10 - .../cython_includes/cef_content_filter.pxd | 9 - cefpython/cython_includes/cef_drag.pxd | 16 - cefpython/cython_includes/cef_drag_data.pxd | 21 - cefpython/cython_includes/cef_frame.pxd | 76 +- cefpython/cython_includes/cef_stream.pxd | 10 - .../cython_includes/cef_stream_static.pxd | 11 - .../content_filter_handler.pxd | 7 - cefpython/drag_data.pyx | 57 - cefpython/drag_handler.pyx | 61 - cefpython/imports.pyx | 7 - cefpython/stream.pyx | 35 - docs/API.md | 91 +- docs/handlers/KeyboardHandler.md | 173 +-- docs/objects/NetworkError.md | 254 ++-- docs/objects/WindowUtils.md | 105 +- docs/settings/BrowserSettings.md | 2 +- tools/apidocs.py | 22 + tools/build.py | 5 + .../issue131-stress-test.sh | 2 +- tools/requirements.txt | 1 + 203 files changed, 410 insertions(+), 27659 deletions(-) rename cefpython/LICENSE.txt => LICENSE.txt (83%) delete mode 100644 cefpython/cef1/BUILD_COMPATIBILITY.txt delete mode 100644 cefpython/cef1/cefpython_public_api.h delete mode 100644 cefpython/cef1/client_handler/.gitignore delete mode 100644 cefpython/cef1/client_handler/Makefile delete mode 100644 cefpython/cef1/client_handler/client_handler.cpp delete mode 100644 cefpython/cef1/client_handler/client_handler.h delete mode 100644 cefpython/cef1/client_handler/client_handler.sln delete mode 100644 cefpython/cef1/client_handler/client_handler_py27.vcproj delete mode 100644 cefpython/cef1/client_handler/client_handler_py32.vcproj delete mode 100644 cefpython/cef1/client_handler/content_filter_handler.cpp delete mode 100644 cefpython/cef1/client_handler/content_filter_handler.h delete mode 100644 cefpython/cef1/client_handler/cookie_visitor.cpp delete mode 100644 cefpython/cef1/client_handler/cookie_visitor.h delete mode 100644 cefpython/cef1/client_handler/download_handler.cpp delete mode 100644 cefpython/cef1/client_handler/download_handler.h delete mode 100644 cefpython/cef1/client_handler/web_request_client.cpp delete mode 100644 cefpython/cef1/client_handler/web_request_client.h delete mode 100644 cefpython/cef1/http_authentication/AuthCredentials.cpp delete mode 100644 cefpython/cef1/http_authentication/AuthCredentials.h delete mode 100644 cefpython/cef1/http_authentication/AuthDialog.cpp delete mode 100644 cefpython/cef1/http_authentication/AuthDialog.h delete mode 100644 cefpython/cef1/http_authentication/DialogTemplate.cpp delete mode 100644 cefpython/cef1/http_authentication/DialogTemplate.h delete mode 100644 cefpython/cef1/http_authentication/http_authentication.sln delete mode 100644 cefpython/cef1/http_authentication/http_authentication.vcproj delete mode 100644 cefpython/cef1/include/cef_app.h delete mode 100644 cefpython/cef1/include/cef_application_mac.h delete mode 100644 cefpython/cef1/include/cef_base.h delete mode 100644 cefpython/cef1/include/cef_browser.h delete mode 100644 cefpython/cef1/include/cef_client.h delete mode 100644 cefpython/cef1/include/cef_command_line.h delete mode 100644 cefpython/cef1/include/cef_content_filter.h delete mode 100644 cefpython/cef1/include/cef_cookie.h delete mode 100644 cefpython/cef1/include/cef_display_handler.h delete mode 100644 cefpython/cef1/include/cef_dom.h delete mode 100644 cefpython/cef1/include/cef_download_handler.h delete mode 100644 cefpython/cef1/include/cef_drag_data.h delete mode 100644 cefpython/cef1/include/cef_drag_handler.h delete mode 100644 cefpython/cef1/include/cef_find_handler.h delete mode 100644 cefpython/cef1/include/cef_focus_handler.h delete mode 100644 cefpython/cef1/include/cef_frame.h delete mode 100644 cefpython/cef1/include/cef_geolocation.h delete mode 100644 cefpython/cef1/include/cef_geolocation_handler.h delete mode 100644 cefpython/cef1/include/cef_jsdialog_handler.h delete mode 100644 cefpython/cef1/include/cef_keyboard_handler.h delete mode 100644 cefpython/cef1/include/cef_life_span_handler.h delete mode 100644 cefpython/cef1/include/cef_load_handler.h delete mode 100644 cefpython/cef1/include/cef_menu_handler.h delete mode 100644 cefpython/cef1/include/cef_nplugin.h delete mode 100644 cefpython/cef1/include/cef_origin_whitelist.h delete mode 100644 cefpython/cef1/include/cef_permission_handler.h delete mode 100644 cefpython/cef1/include/cef_print_handler.h delete mode 100644 cefpython/cef1/include/cef_proxy_handler.h delete mode 100644 cefpython/cef1/include/cef_render_handler.h delete mode 100644 cefpython/cef1/include/cef_request.h delete mode 100644 cefpython/cef1/include/cef_request_handler.h delete mode 100644 cefpython/cef1/include/cef_resource_bundle_handler.h delete mode 100644 cefpython/cef1/include/cef_response.h delete mode 100644 cefpython/cef1/include/cef_runnable.h delete mode 100644 cefpython/cef1/include/cef_scheme.h delete mode 100644 cefpython/cef1/include/cef_stream.h delete mode 100644 cefpython/cef1/include/cef_task.h delete mode 100644 cefpython/cef1/include/cef_url.h delete mode 100644 cefpython/cef1/include/cef_v8.h delete mode 100644 cefpython/cef1/include/cef_v8context_handler.h delete mode 100644 cefpython/cef1/include/cef_version.h delete mode 100644 cefpython/cef1/include/cef_web_plugin.h delete mode 100644 cefpython/cef1/include/cef_web_urlrequest.h delete mode 100644 cefpython/cef1/include/cef_xml_reader.h delete mode 100644 cefpython/cef1/include/cef_zip_reader.h delete mode 100644 cefpython/cef1/include/cef_zoom_handler.h delete mode 100644 cefpython/cef1/include/internal/cef_build.h delete mode 100644 cefpython/cef1/include/internal/cef_export.h delete mode 100644 cefpython/cef1/include/internal/cef_linux.h delete mode 100644 cefpython/cef1/include/internal/cef_mac.h delete mode 100644 cefpython/cef1/include/internal/cef_nplugin_types.h delete mode 100644 cefpython/cef1/include/internal/cef_ptr.h delete mode 100644 cefpython/cef1/include/internal/cef_string.h delete mode 100644 cefpython/cef1/include/internal/cef_string_list.h delete mode 100644 cefpython/cef1/include/internal/cef_string_map.h delete mode 100644 cefpython/cef1/include/internal/cef_string_multimap.h delete mode 100644 cefpython/cef1/include/internal/cef_string_types.h delete mode 100644 cefpython/cef1/include/internal/cef_string_wrappers.h delete mode 100644 cefpython/cef1/include/internal/cef_time.h delete mode 100644 cefpython/cef1/include/internal/cef_tuple.h delete mode 100644 cefpython/cef1/include/internal/cef_types.h delete mode 100644 cefpython/cef1/include/internal/cef_types_linux.h delete mode 100644 cefpython/cef1/include/internal/cef_types_mac.h delete mode 100644 cefpython/cef1/include/internal/cef_types_win.h delete mode 100644 cefpython/cef1/include/internal/cef_types_wrappers.h delete mode 100644 cefpython/cef1/include/internal/cef_win.h delete mode 100644 cefpython/cef1/include/wrapper/cef_byte_read_handler.h delete mode 100644 cefpython/cef1/include/wrapper/cef_xml_object.h delete mode 100644 cefpython/cef1/include/wrapper/cef_zip_archive.h delete mode 100644 cefpython/cef1/linux/CEF-GTK-patch.txt delete mode 100644 cefpython/cef1/linux/binaries_32bit/LICENSE.txt delete mode 100644 cefpython/cef1/linux/binaries_32bit/cefpython_py27.py delete mode 100644 cefpython/cef1/linux/binaries_32bit/cefsimple.html delete mode 100644 cefpython/cef1/linux/binaries_32bit/pygtk_.py delete mode 100644 cefpython/cef1/linux/binaries_32bit/wxpython.html delete mode 100644 cefpython/cef1/linux/binaries_32bit/wxpython.py delete mode 100644 cefpython/cef1/linux/binaries_64bit/LICENSE.txt delete mode 100644 cefpython/cef1/linux/binaries_64bit/cefpython_py27.py delete mode 100644 cefpython/cef1/linux/binaries_64bit/cefsimple.html delete mode 100644 cefpython/cef1/linux/binaries_64bit/pygtk_.py delete mode 100644 cefpython/cef1/linux/binaries_64bit/wxpython.html delete mode 100644 cefpython/cef1/linux/binaries_64bit/wxpython.py delete mode 100755 cefpython/cef1/linux/compile.py delete mode 100644 cefpython/cef1/linux/example.py delete mode 100644 cefpython/cef1/linux/installer/README.txt.template delete mode 100644 cefpython/cef1/linux/installer/__init__.py.template delete mode 100644 cefpython/cef1/linux/installer/make-setup.py delete mode 100644 cefpython/cef1/linux/installer/setup.py.template delete mode 100644 cefpython/cef1/linux/setup/.gitignore delete mode 100644 cefpython/cef1/linux/setup/cefpython.h delete mode 100755 cefpython/cef1/linux/setup/fix_includes.py delete mode 100755 cefpython/cef1/linux/setup/setup.py delete mode 100644 cefpython/cef1/util.h delete mode 100644 cefpython/cef1/v8function_handler/.gitignore delete mode 100644 cefpython/cef1/v8function_handler/Makefile delete mode 100644 cefpython/cef1/v8function_handler/v8function_handler.cpp delete mode 100644 cefpython/cef1/v8function_handler/v8function_handler.h delete mode 100644 cefpython/cef1/v8function_handler/v8function_handler.sln delete mode 100644 cefpython/cef1/v8function_handler/v8function_handler_py27.vcproj delete mode 100644 cefpython/cef1/v8function_handler/v8function_handler_py32.vcproj delete mode 100644 cefpython/cef1/windows/.gitignore delete mode 100644 cefpython/cef1/windows/binaries/LICENSE.txt delete mode 100644 cefpython/cef1/windows/binaries/Microsoft.VC90.CRT.manifest delete mode 100644 cefpython/cef1/windows/binaries/README.txt delete mode 100644 cefpython/cef1/windows/binaries/cefadvanced.html delete mode 100644 cefpython/cef1/windows/binaries/cefadvanced.py delete mode 100644 cefpython/cef1/windows/binaries/cefclient_dcheck.bat delete mode 100644 cefpython/cef1/windows/binaries/cefpython_py27.py delete mode 100644 cefpython/cef1/windows/binaries/cefpython_py32.py delete mode 100644 cefpython/cef1/windows/binaries/cefsimple.html delete mode 100644 cefpython/cef1/windows/binaries/cefsimple.py delete mode 100644 cefpython/cef1/windows/binaries/cefwindow.py delete mode 100644 cefpython/cef1/windows/binaries/cefwxpanel.py delete mode 100644 cefpython/cef1/windows/binaries/cefwxpanel_sample1.py delete mode 100644 cefpython/cef1/windows/binaries/cefwxpanel_sample2.py delete mode 100644 cefpython/cef1/windows/binaries/debug_gdb.bat delete mode 100644 cefpython/cef1/windows/binaries/debug_pdb.bat delete mode 100644 cefpython/cef1/windows/binaries/icon.ico delete mode 100644 cefpython/cef1/windows/binaries/panda3d_.py delete mode 100644 cefpython/cef1/windows/binaries/pygtk_.py delete mode 100644 cefpython/cef1/windows/binaries/pyqt.py delete mode 100644 cefpython/cef1/windows/binaries/pyside.py delete mode 100644 cefpython/cef1/windows/binaries/wxpython.html delete mode 100644 cefpython/cef1/windows/binaries/wxpython.py delete mode 100644 cefpython/cef1/windows/cefadvanced.bat delete mode 100644 cefpython/cef1/windows/cefpython.pyd.manifest delete mode 100644 cefpython/cef1/windows/compile.bat delete mode 100644 cefpython/cef1/windows/installer/__init__.py.template delete mode 100644 cefpython/cef1/windows/installer/innosetup.template delete mode 100644 cefpython/cef1/windows/installer/make-installer.py delete mode 100644 cefpython/cef1/windows/setup/.gitignore delete mode 100644 cefpython/cef1/windows/setup/cefpython.h delete mode 100644 cefpython/cef1/windows/setup/delete_pyx_files.bat delete mode 100644 cefpython/cef1/windows/setup/fix_includes.py delete mode 100644 cefpython/cef1/windows/setup/setup.py delete mode 100644 cefpython/cef1/windows/stdint.h delete mode 100644 cefpython/cef1/wx-subpackage/README.txt delete mode 100644 cefpython/cef1/wx-subpackage/__init__.py delete mode 100644 cefpython/cef1/wx-subpackage/chromectrl.py delete mode 100644 cefpython/cef1/wx-subpackage/examples/back.png delete mode 100644 cefpython/cef1/wx-subpackage/examples/forward.png delete mode 100644 cefpython/cef1/wx-subpackage/examples/reload_page.png delete mode 100644 cefpython/cef1/wx-subpackage/examples/sample1.html delete mode 100644 cefpython/cef1/wx-subpackage/examples/sample1.py delete mode 100644 cefpython/cef1/wx-subpackage/examples/sample2.py delete mode 100644 cefpython/cef1/wx-subpackage/examples/sample3.py delete mode 100644 cefpython/cef1/wx-subpackage/images/Arrow Left.png delete mode 100644 cefpython/cef1/wx-subpackage/images/Arrow Right.png delete mode 100644 cefpython/cef1/wx-subpackage/images/Button Load.png delete mode 100644 cefpython/cef1/wx-subpackage/utils.py delete mode 100644 cefpython/cef1_api.py delete mode 100644 cefpython/content_filter.pyx delete mode 100644 cefpython/ctags.bat delete mode 100644 cefpython/cython_includes/cef_content_filter.pxd delete mode 100644 cefpython/cython_includes/cef_drag.pxd delete mode 100644 cefpython/cython_includes/cef_drag_data.pxd delete mode 100644 cefpython/cython_includes/cef_stream.pxd delete mode 100644 cefpython/cython_includes/cef_stream_static.pxd delete mode 100644 cefpython/cython_includes/content_filter_handler.pxd delete mode 100644 cefpython/drag_data.pyx delete mode 100644 cefpython/drag_handler.pyx delete mode 100644 cefpython/stream.pyx rename cefpython/tests/test-launch.sh => tools/issue131-stress-test.sh (97%) mode change 100755 => 100644 diff --git a/.gitignore b/.gitignore index 5e89247a4..41f7f34f0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,2 @@ -cef3-trunk -svn-win32-1.8.5 -cefpython.wiki -.tags* -/cython-version.* .idea/ +build/ diff --git a/AUTHORS.txt b/AUTHORS.txt index ac6d79e22..f7fad18d8 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -1,17 +1,12 @@ -Core developers: - - Czarek Tomczak - -Contributors (in order of first commit): - - 老农 cjjer - Richard Rodriguez - Roman Plášil - Rokas Stupuras - Greg Kacy - Thomas Dähling - Dominique Burnand - Greg Farrell - Finn Hughes - Marcelo Fernandez - Simon Hatt <9hatt2@@gmail.com> +Czarek Tomczak +老农 cjjer +Richard Rodriguez +Roman Plášil +Rokas Stupuras +Greg Kacy +Thomas Dähling +Dominique Burnand +Greg Farrell +Finn Hughes +Marcelo Fernandez +Simon Hatt <9hatt2@@gmail.com> diff --git a/cefpython/LICENSE.txt b/LICENSE.txt similarity index 83% rename from cefpython/LICENSE.txt rename to LICENSE.txt index ba1b96ff8..2b6aad16d 100644 --- a/cefpython/LICENSE.txt +++ b/LICENSE.txt @@ -1,9 +1,10 @@ -Copyright (c) 2012-2014 The CEF Python authors. All rights -reserved. Website: http://code.google.com/p/cefpython/ +Copyright (c) 2012 The CEF Python authors - see the AUTHORS.txt file. +All rights reserved. Licensed under the BSD 3-clause license. +See project website: https://github.com/cztomczak/cefpython This product includes the following third party libraries: -* Chromium Embedded Framework licensed under the BSD 3-clause - license. Website: http://code.google.com/p/chromiumembedded/ +* Chromium Embedded Framework licensed under the BSD 3-clause + license. Website: https://bitbucket.org/chromiumembedded/cef Redistribution and use in source and binary forms, with or without modification, are permitted provided that the diff --git a/README.md b/README.md index fa5a73ab9..68439def0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ +__Notes__: +* Repository rewritten on 2016-02-15 to reduce its size. + Please clone it again. Issue #103. +* There is an ongoing big refactoring with code and documentation + cleanup. The last stable code is in the cefpython31 branch. + Issue #208. + # CEF Python Table of contents: diff --git a/cefpython/cef1/BUILD_COMPATIBILITY.txt b/cefpython/cef1/BUILD_COMPATIBILITY.txt deleted file mode 100644 index edc159a6b..000000000 --- a/cefpython/cef1/BUILD_COMPATIBILITY.txt +++ /dev/null @@ -1,16 +0,0 @@ -Chromium/CEF branch: - 1453 -Chromium release url: - http://src.chromium.org/svn/releases/27.0.1453.110 -CEF revision: - 1273 -CEF repository url: - http://chromiumembedded.googlecode.com/svn/branches/1453/cef1@1273 - ----- - -To convert chromium revision back to version string use this url: -http://src.chromium.org/viewvc/chrome/branches/xxxx/src/chrome/VERSION?revision=xxxx - -The latest chromium version in given branch: -http://src.chromium.org/viewvc/chrome/branches/xxxx/src/chrome/VERSION diff --git a/cefpython/cef1/cefpython_public_api.h b/cefpython/cef1/cefpython_public_api.h deleted file mode 100644 index f55df41f3..000000000 --- a/cefpython/cef1/cefpython_public_api.h +++ /dev/null @@ -1,30 +0,0 @@ -// d:\cefpython\src\setup/cefpython.h(22) : warning C4190: 'RequestHandler_GetCookieManager' -// has C-linkage specified, but returns UDT 'CefRefPtr' which is incompatible with C -#if defined(OS_WIN) -#pragma warning(disable:4190) -#endif - -// All the imports that are required when including "cefpython.h". -#include "include/cef_client.h" -#include "include/cef_web_urlrequest.h" -#include "include/cef_cookie.h" -#include "util.h" - -// To be able to use 'public' declarations you need to include Python.h and cefpython.h. -#include "Python.h" - -// Python 3.2 fix - DL_IMPORT is not defined in Python.h -#ifndef DL_IMPORT /* declarations for DLL import/export */ -#define DL_IMPORT(RTYPE) RTYPE -#endif -#ifndef DL_EXPORT /* declarations for DLL import/export */ -#define DL_EXPORT(RTYPE) RTYPE -#endif - -#if defined(OS_WIN) -#include "windows/setup/cefpython.h" -#endif - -#if defined(OS_LINUX) -#include "linux/setup/cefpython.h" -#endif diff --git a/cefpython/cef1/client_handler/.gitignore b/cefpython/cef1/client_handler/.gitignore deleted file mode 100644 index 151a620fe..000000000 --- a/cefpython/cef1/client_handler/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.o -*.a \ No newline at end of file diff --git a/cefpython/cef1/client_handler/Makefile b/cefpython/cef1/client_handler/Makefile deleted file mode 100644 index 9baf4a885..000000000 --- a/cefpython/cef1/client_handler/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# -g - extra debug information -# -O1 - more precise backtraces -# -fPIC - required when using -shared option -# -Wall - show important warnings -# -Werror - treat warnings as errors - -CC = g++ -CCFLAGS = -g - -SRC = client_handler.cpp web_request_client.cpp content_filter_handler.cpp cookie_visitor.cpp download_handler.cpp -OBJ = $(SRC:.cpp=.o) -OUT = libclient_handler.a - -INC = -I./../ -I/usr/include/python2.7 -I/usr/include/gtk-2.0 -I/usr/include/glib-2.0 -I/usr/lib/i386-linux-gnu/gtk-2.0/include -I/usr/lib/i386-linux-gnu/glib-2.0/include -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/atk-1.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include - -.cpp.o: - $(CC) -fPIC $(INC) $(CCFLAGS) -c $< -o $@ - -$(OUT): $(OBJ) - ar rcs $(OUT) $(OBJ) diff --git a/cefpython/cef1/client_handler/client_handler.cpp b/cefpython/cef1/client_handler/client_handler.cpp deleted file mode 100644 index b2884fccc..000000000 --- a/cefpython/cef1/client_handler/client_handler.cpp +++ /dev/null @@ -1,347 +0,0 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ - -#include "client_handler.h" -#include - -// The const_cast<> were required in Cython <= 0.17.4, -// TODO: get rid of it. - -// ----------------------------------------------------------------------------- -// CefLoadHandler -// ----------------------------------------------------------------------------- - -void ClientHandler::OnLoadEnd( - CefRefPtr browser, - CefRefPtr frame, - int httpStatusCode) { - REQUIRE_UI_THREAD(); - LoadHandler_OnLoadEnd(browser, frame, httpStatusCode); -} - -void ClientHandler::OnLoadStart( - CefRefPtr browser, - CefRefPtr frame) { - REQUIRE_UI_THREAD(); - LoadHandler_OnLoadStart(browser, frame); -} - -bool ClientHandler::OnLoadError( - CefRefPtr browser, - CefRefPtr frame, - cef_handler_errorcode_t errorCode, - const CefString& failedUrl, - CefString& errorText - ) { - REQUIRE_UI_THREAD(); - return LoadHandler_OnLoadError( - browser, frame, errorCode, const_cast(failedUrl), errorText); -} - -// ----------------------------------------------------------------------------- -// CefKeyboardHandler -// ----------------------------------------------------------------------------- - -bool ClientHandler::OnKeyEvent( - CefRefPtr browser, - cef_handler_keyevent_type_t eventType, - int keyCode, - int modifiers, - bool isSystemKey, - bool isAfterJavascript) { - REQUIRE_UI_THREAD(); - return KeyboardHandler_OnKeyEvent( - browser, eventType, keyCode, modifiers, isSystemKey, isAfterJavascript); -} - -// ----------------------------------------------------------------------------- -// CefV8ContextHandler -// ----------------------------------------------------------------------------- - -void ClientHandler::OnContextCreated( - CefRefPtr cefBrowser, - CefRefPtr cefFrame, - CefRefPtr v8Context) { - REQUIRE_UI_THREAD(); - V8ContextHandler_OnContextCreated(cefBrowser, cefFrame, v8Context); -} - -void ClientHandler::OnContextReleased( - CefRefPtr cefBrowser, - CefRefPtr cefFrame, - CefRefPtr v8Context) { - REQUIRE_UI_THREAD(); - V8ContextHandler_OnContextReleased(cefBrowser, cefFrame, v8Context); -} - -void ClientHandler::OnUncaughtException( - CefRefPtr browser, - CefRefPtr frame, - CefRefPtr context, - CefRefPtr exception, - CefRefPtr stackTrace) { - REQUIRE_UI_THREAD(); - V8ContextHandler_OnUncaughtException( - browser, frame, context, exception, stackTrace); -} - -// ----------------------------------------------------------------------------- -// CefRequestHandler -// ----------------------------------------------------------------------------- - -bool ClientHandler::OnBeforeBrowse( - CefRefPtr browser, - CefRefPtr frame, - CefRefPtr request, - cef_handler_navtype_t navType, - bool isRedirect) { - REQUIRE_UI_THREAD(); - return RequestHandler_OnBeforeBrowse( - browser, frame, request, navType, isRedirect); -} - -bool ClientHandler::OnBeforeResourceLoad( - CefRefPtr browser, - CefRefPtr request, - CefString& redirectUrl, - CefRefPtr& resourceStream, - CefRefPtr response, - int loadFlags) { - REQUIRE_IO_THREAD(); - return RequestHandler_OnBeforeResourceLoad( - browser, request, redirectUrl, resourceStream, response, loadFlags); -} - -void ClientHandler::OnResourceRedirect( - CefRefPtr browser, - const CefString& old_url, - CefString& new_url) { - REQUIRE_IO_THREAD(); - RequestHandler_OnResourceRedirect( - browser, const_cast(old_url), new_url); -} - -void ClientHandler::OnResourceResponse( - CefRefPtr browser, - const CefString& url, - CefRefPtr response, - CefRefPtr& filter) { - REQUIRE_UI_THREAD(); - RequestHandler_OnResourceResponse( - browser, const_cast(url), response, filter); -} - -bool ClientHandler::OnProtocolExecution( - CefRefPtr browser, - const CefString& url, - bool& allowOSExecution) { - REQUIRE_IO_THREAD(); - return RequestHandler_OnProtocolExecution( - browser, const_cast(url), allowOSExecution); -} - -bool ClientHandler::GetDownloadHandler( - CefRefPtr browser, - const CefString& mimeType, - const CefString& fileName, - int64 contentLength, - CefRefPtr& handler) { - // Multiple downloads at the same time? - AutoLock lock_scope(this); - REQUIRE_UI_THREAD(); - return RequestHandler_GetDownloadHandler(browser, mimeType, fileName, - contentLength, handler); -} - -bool ClientHandler::GetAuthCredentials( - CefRefPtr browser, - bool isProxy, - const CefString& host, - int port, - const CefString& realm, - const CefString& scheme, - CefString& username, - CefString& password) { - REQUIRE_IO_THREAD(); - return RequestHandler_GetAuthCredentials( - browser, isProxy, const_cast(host), port, - const_cast(realm), const_cast(scheme), - username, password); -} - -CefRefPtr ClientHandler::GetCookieManager( - CefRefPtr browser, - const CefString& main_url) { - REQUIRE_IO_THREAD(); - return RequestHandler_GetCookieManager( - browser, const_cast(main_url)); -} - -// ----------------------------------------------------------------------------- -// CefDisplayHandler -// ----------------------------------------------------------------------------- - -void ClientHandler::OnAddressChange(CefRefPtr browser, - CefRefPtr frame, - const CefString& url) { - REQUIRE_UI_THREAD(); - DisplayHandler_OnAddressChange(browser, frame, const_cast(url)); -} - -bool ClientHandler::OnConsoleMessage(CefRefPtr browser, - const CefString& message, - const CefString& source, - int line) { - REQUIRE_UI_THREAD(); - return DisplayHandler_OnConsoleMessage( - browser, const_cast(message), - const_cast(source), line); -} - -void ClientHandler::OnContentsSizeChange(CefRefPtr browser, - CefRefPtr frame, - int width, - int height) { - REQUIRE_UI_THREAD(); - DisplayHandler_OnContentsSizeChange(browser, frame, width, height); -} - -void ClientHandler::OnNavStateChange(CefRefPtr browser, - bool canGoBack, - bool canGoForward) { - REQUIRE_UI_THREAD(); - DisplayHandler_OnNavStateChange(browser, canGoBack, canGoForward); -} - -void ClientHandler::OnStatusMessage(CefRefPtr browser, - const CefString& value, - StatusType type) { - REQUIRE_UI_THREAD(); - DisplayHandler_OnStatusMessage(browser, const_cast(value), type); -} - - -void ClientHandler::OnTitleChange(CefRefPtr browser, - const CefString& title) { - REQUIRE_UI_THREAD(); - DisplayHandler_OnTitleChange(browser, const_cast(title)); -} - -bool ClientHandler::OnTooltip(CefRefPtr browser, - CefString& text) { - REQUIRE_UI_THREAD(); - return DisplayHandler_OnTooltip(browser, text); -} - -// ----------------------------------------------------------------------------- -// CefLifeSpanHandler -// ----------------------------------------------------------------------------- - -bool ClientHandler::DoClose(CefRefPtr browser) { - REQUIRE_UI_THREAD(); - return LifespanHandler_DoClose(browser); -} - -void ClientHandler::OnAfterCreated(CefRefPtr browser) { - REQUIRE_UI_THREAD(); - LifespanHandler_OnAfterCreated(browser); -} - -void ClientHandler::OnBeforeClose(CefRefPtr browser) { - REQUIRE_UI_THREAD(); - LifespanHandler_OnBeforeClose(browser); -} - -bool ClientHandler::OnBeforePopup(CefRefPtr parentBrowser, - const CefPopupFeatures& popupFeatures, - CefWindowInfo& windowInfo, - const CefString& url, - CefRefPtr& client, - CefBrowserSettings& settings) { - REQUIRE_UI_THREAD(); - // @TODO - return false; -} - -bool ClientHandler::RunModal(CefRefPtr browser) { - REQUIRE_UI_THREAD(); - return LifespanHandler_RunModal(browser); -} - -// ----------------------------------------------------------------------------- -// CefRenderHandler -// ----------------------------------------------------------------------------- - -#if defined(OS_WIN) - -bool ClientHandler::GetViewRect(CefRefPtr browser, - CefRect& rect) { - REQUIRE_UI_THREAD(); - return RenderHandler_GetViewRect(browser, rect); -} - -bool ClientHandler::GetScreenRect(CefRefPtr browser, - CefRect& rect) { - REQUIRE_UI_THREAD(); - return RenderHandler_GetScreenRect(browser, rect); -} - -bool ClientHandler::GetScreenPoint(CefRefPtr browser, - int viewX, - int viewY, - int& screenX, - int& screenY) { - REQUIRE_UI_THREAD(); - return RenderHandler_GetScreenPoint( - browser, viewX, viewY, screenX, screenY); -} - -void ClientHandler::OnPopupShow(CefRefPtr browser, - bool show) { - REQUIRE_UI_THREAD(); - RenderHandler_OnPopupShow(browser, show); -} - -void ClientHandler::OnPopupSize(CefRefPtr browser, - const CefRect& rect) { - REQUIRE_UI_THREAD(); - RenderHandler_OnPopupSize(browser, const_cast(rect)); -} - -void ClientHandler::OnPaint(CefRefPtr browser, - PaintElementType type, - const RectList& dirtyRects, - const void* buffer) { - REQUIRE_UI_THREAD(); - RenderHandler_OnPaint(browser, type, - const_cast(dirtyRects), - const_cast(buffer)); -} - -void ClientHandler::OnCursorChange(CefRefPtr browser, - CefCursorHandle cursor) { - REQUIRE_UI_THREAD(); - RenderHandler_OnCursorChange(browser, cursor); -} - -// #if defined(OS_WIN) - CefRenderHandler -#endif - -// ----------------------------------------------------------------------------- -// CefDragHandler -// ----------------------------------------------------------------------------- - -bool ClientHandler::OnDragStart(CefRefPtr browser, - CefRefPtr dragData, - DragOperationsMask mask) { - REQUIRE_UI_THREAD(); - return DragHandler_OnDragStart(browser, dragData, mask); -} - -bool ClientHandler::OnDragEnter(CefRefPtr browser, - CefRefPtr dragData, - DragOperationsMask mask) { - REQUIRE_UI_THREAD(); - return DragHandler_OnDragEnter(browser, dragData, mask); -} diff --git a/cefpython/cef1/client_handler/client_handler.h b/cefpython/cef1/client_handler/client_handler.h deleted file mode 100644 index 689a00ef3..000000000 --- a/cefpython/cef1/client_handler/client_handler.h +++ /dev/null @@ -1,304 +0,0 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ - -#pragma once - -#if defined(_WIN32) -#include "../windows/stdint.h" -#endif - -#include "cefpython_public_api.h" - -class ClientHandler : public CefClient, - public CefLoadHandler, - public CefKeyboardHandler, - public CefV8ContextHandler, - public CefRequestHandler, - public CefDisplayHandler, - public CefLifeSpanHandler, - public CefRenderHandler, - public CefDragHandler -/* - public CefFocusHandler, - public CefMenuHandler, - public CefPrintHandler, - public CefPermissionHandler, - public CefFindHandler, - public CefJSDialogHandler, -*/ -{ -public: - ClientHandler(){} - virtual ~ClientHandler(){} - - // --------------------------------------------------------------------------- - // Handlers that are already implemented - // --------------------------------------------------------------------------- - - virtual CefRefPtr GetLoadHandler() OVERRIDE - { return this; } - - virtual CefRefPtr GetRequestHandler() OVERRIDE - { return this; } - - virtual CefRefPtr GetDisplayHandler() OVERRIDE - { return this; } - - virtual CefRefPtr GetKeyboardHandler() OVERRIDE - { return this; } - - virtual CefRefPtr GetV8ContextHandler() OVERRIDE - { return this; } - - virtual CefRefPtr GetLifeSpanHandler() OVERRIDE - { return this; } - - virtual CefRefPtr GetRenderHandler() OVERRIDE - { return this; } - - virtual CefRefPtr GetDragHandler() OVERRIDE - { return this; } - - // --------------------------------------------------------------------------- - // NOT yet implemented handlers - // --------------------------------------------------------------------------- - - virtual CefRefPtr GetFocusHandler() OVERRIDE - { return NULL; } - - virtual CefRefPtr GetMenuHandler() OVERRIDE - { return NULL; } - - virtual CefRefPtr GetPermissionHandler() OVERRIDE - { return NULL; } - - virtual CefRefPtr GetPrintHandler() OVERRIDE - { return NULL; } - - virtual CefRefPtr GetFindHandler() OVERRIDE - { return NULL; } - - virtual CefRefPtr GetJSDialogHandler() OVERRIDE - { return NULL; } - - // --------------------------------------------------------------------------- - // CefLoadHandler methods. - // --------------------------------------------------------------------------- - - virtual void OnLoadEnd( - CefRefPtr browser, - CefRefPtr frame, - int httpStatusCode - ) OVERRIDE; - - - virtual void OnLoadStart( - CefRefPtr browser, - CefRefPtr frame - ) OVERRIDE; - - virtual bool OnLoadError( - CefRefPtr browser, - CefRefPtr frame, - cef_handler_errorcode_t errorCode, - const CefString& failedUrl, - CefString& errorText - ) OVERRIDE; - - // --------------------------------------------------------------------------- - // CefKeyboardHandler methods. - // --------------------------------------------------------------------------- - - virtual bool OnKeyEvent( - CefRefPtr browser, - cef_handler_keyevent_type_t eventType, - int keyCode, - int modifiers, - bool isSystemKey, - bool isAfterJavascript - ) OVERRIDE; - - // --------------------------------------------------------------------------- - // CefV8ContextHandler methods. - // --------------------------------------------------------------------------- - - virtual void OnContextCreated( - CefRefPtr cefBrowser, - CefRefPtr cefFrame, - CefRefPtr v8Context) OVERRIDE; - - virtual void OnContextReleased( - CefRefPtr cefBrowser, - CefRefPtr cefFrame, - CefRefPtr v8Context) OVERRIDE; - - virtual void OnUncaughtException( - CefRefPtr browser, - CefRefPtr frame, - CefRefPtr context, - CefRefPtr exception, - CefRefPtr stackTrace) OVERRIDE; - - // --------------------------------------------------------------------------- - // CefRequestHandler methods. - // --------------------------------------------------------------------------- - - virtual bool OnBeforeBrowse( - CefRefPtr browser, - CefRefPtr frame, - CefRefPtr request, - cef_handler_navtype_t navType, - bool isRedirect) OVERRIDE; - - virtual bool OnBeforeResourceLoad( - CefRefPtr browser, - CefRefPtr request, - CefString& redirectUrl, - CefRefPtr& resourceStream, - CefRefPtr response, - int loadFlags) OVERRIDE; - - virtual void OnResourceRedirect( - CefRefPtr browser, - const CefString& old_url, - CefString& new_url) OVERRIDE; - - virtual void OnResourceResponse( - CefRefPtr browser, - const CefString& url, - CefRefPtr response, - CefRefPtr& filter) OVERRIDE; - - virtual bool OnProtocolExecution( - CefRefPtr browser, - const CefString& url, - bool& allowOSExecution) OVERRIDE; - - virtual bool GetDownloadHandler( - CefRefPtr browser, - const CefString& mimeType, - const CefString& fileName, - int64 contentLength, - CefRefPtr& handler) OVERRIDE; - - virtual bool GetAuthCredentials( - CefRefPtr browser, - bool isProxy, - const CefString& host, - int port, - const CefString& realm, - const CefString& scheme, - CefString& username, - CefString& password) OVERRIDE; - - virtual CefRefPtr GetCookieManager( - CefRefPtr browser, - const CefString& main_url) OVERRIDE; - - // --------------------------------------------------------------------------- - // CefDisplayHandler - // --------------------------------------------------------------------------- - - virtual void OnAddressChange(CefRefPtr browser, - CefRefPtr frame, - const CefString& url) OVERRIDE; - - virtual bool OnConsoleMessage(CefRefPtr browser, - const CefString& message, - const CefString& source, - int line) OVERRIDE; - - virtual void OnContentsSizeChange(CefRefPtr browser, - CefRefPtr frame, - int width, - int height) OVERRIDE; - - virtual void OnNavStateChange(CefRefPtr browser, - bool canGoBack, - bool canGoForward) OVERRIDE; - - virtual void OnStatusMessage(CefRefPtr browser, - const CefString& value, - StatusType type) OVERRIDE; - - virtual void OnTitleChange(CefRefPtr browser, - const CefString& title) OVERRIDE; - - virtual bool OnTooltip(CefRefPtr browser, - CefString& text) OVERRIDE; - - // --------------------------------------------------------------------------- - // CefLifeSpanHandler - // --------------------------------------------------------------------------- - - virtual bool DoClose(CefRefPtr browser) OVERRIDE; - - virtual void OnAfterCreated(CefRefPtr browser) OVERRIDE; - - virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE; - - virtual bool OnBeforePopup(CefRefPtr parentBrowser, - const CefPopupFeatures& popupFeatures, - CefWindowInfo& windowInfo, - const CefString& url, - CefRefPtr& client, - CefBrowserSettings& settings) OVERRIDE; - - virtual bool RunModal(CefRefPtr browser) OVERRIDE; - - // --------------------------------------------------------------------------- - // CefRenderHandler - // --------------------------------------------------------------------------- - -#if defined(OS_WIN) - - virtual bool GetViewRect(CefRefPtr browser, - CefRect& rect) OVERRIDE; - - virtual bool GetScreenRect(CefRefPtr browser, - CefRect& rect) OVERRIDE; - - virtual bool GetScreenPoint(CefRefPtr browser, - int viewX, - int viewY, - int& screenX, - int& screenY) OVERRIDE; - - virtual void OnPopupShow(CefRefPtr browser, - bool show) OVERRIDE; - - virtual void OnPopupSize(CefRefPtr browser, - const CefRect& rect) OVERRIDE; - - virtual void OnPaint(CefRefPtr browser, - PaintElementType type, - const RectList& dirtyRects, - const void* buffer) OVERRIDE; - - virtual void OnCursorChange(CefRefPtr browser, - CefCursorHandle cursor) OVERRIDE; - -#endif - - // --------------------------------------------------------------------------- - // CefDragHandler - // --------------------------------------------------------------------------- - - virtual bool OnDragStart(CefRefPtr browser, - CefRefPtr dragData, - DragOperationsMask mask) OVERRIDE; - - virtual bool OnDragEnter(CefRefPtr browser, - CefRefPtr dragData, - DragOperationsMask mask) OVERRIDE; - -protected: - - // Include the default reference counting implementation. - IMPLEMENT_REFCOUNTING(ClientHandler); - - // Include the default locking implementation. - IMPLEMENT_LOCKING(ClientHandler); - -}; diff --git a/cefpython/cef1/client_handler/client_handler.sln b/cefpython/cef1/client_handler/client_handler.sln deleted file mode 100644 index b3dd2d2a1..000000000 --- a/cefpython/cef1/client_handler/client_handler.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client_handler_py27", "client_handler_py27.vcproj", "{15AD928F-FFD0-4FA5-B469-E42ABB0B4196}" -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC943}") = "client_handler_py32", "client_handler_py32.vcproj", "{37AA7CD9-67AD-40B1-ADC0-D62173764BCA}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {15AD928F-FFD0-4FA5-B469-E42ABB0B4196}.Debug|Win32.ActiveCfg = Debug|Win32 - {15AD928F-FFD0-4FA5-B469-E42ABB0B4196}.Debug|Win32.Build.0 = Debug|Win32 - {15AD928F-FFD0-4FA5-B469-E42ABB0B4196}.Release|Win32.ActiveCfg = Release|Win32 - {15AD928F-FFD0-4FA5-B469-E42ABB0B4196}.Release|Win32.Build.0 = Release|Win32 - {37AA7CD9-67AD-40B1-ADC0-D62173764BCA}.Debug|Win32.ActiveCfg = Debug|Win32 - {37AA7CD9-67AD-40B1-ADC0-D62173764BCA}.Debug|Win32.Build.0 = Debug|Win32 - {37AA7CD9-67AD-40B1-ADC0-D62173764BCA}.Release|Win32.ActiveCfg = Release|Win32 - {37AA7CD9-67AD-40B1-ADC0-D62173764BCA}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/cefpython/cef1/client_handler/client_handler_py27.vcproj b/cefpython/cef1/client_handler/client_handler_py27.vcproj deleted file mode 100644 index 3f45e736a..000000000 --- a/cefpython/cef1/client_handler/client_handler_py27.vcproj +++ /dev/null @@ -1,205 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cefpython/cef1/client_handler/client_handler_py32.vcproj b/cefpython/cef1/client_handler/client_handler_py32.vcproj deleted file mode 100644 index 643a67510..000000000 --- a/cefpython/cef1/client_handler/client_handler_py32.vcproj +++ /dev/null @@ -1,204 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cefpython/cef1/client_handler/content_filter_handler.cpp b/cefpython/cef1/client_handler/content_filter_handler.cpp deleted file mode 100644 index 0578bf5db..000000000 --- a/cefpython/cef1/client_handler/content_filter_handler.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ - -#include "content_filter_handler.h" - -void ContentFilterHandler::ProcessData(const void* data, int data_size, - CefRefPtr& substitute_data) { - REQUIRE_UI_THREAD(); - ContentFilterHandler_ProcessData(contentFilterId_, data, data_size, - substitute_data); -} - -void ContentFilterHandler::Drain(CefRefPtr& remainder) { - REQUIRE_UI_THREAD(); - ContentFilterHandler_Drain(contentFilterId_, remainder); -} \ No newline at end of file diff --git a/cefpython/cef1/client_handler/content_filter_handler.h b/cefpython/cef1/client_handler/content_filter_handler.h deleted file mode 100644 index ee267ac49..000000000 --- a/cefpython/cef1/client_handler/content_filter_handler.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ - -#pragma once - -#if defined(_WIN32) -#include "../windows/stdint.h" -#endif - -#include "cefpython_public_api.h" - -class ContentFilterHandler : public CefContentFilter -{ -public: - int contentFilterId_; -public: - ContentFilterHandler(int contentFilterId) : - contentFilterId_(contentFilterId) { - } - virtual ~ContentFilterHandler(){} - - virtual void ProcessData(const void* data, int data_size, - CefRefPtr& substitute_data) OVERRIDE; - - virtual void Drain(CefRefPtr& remainder) OVERRIDE; - -protected: - // Include the default reference counting implementation. - IMPLEMENT_REFCOUNTING(ContentFilterHandler); -}; diff --git a/cefpython/cef1/client_handler/cookie_visitor.cpp b/cefpython/cef1/client_handler/cookie_visitor.cpp deleted file mode 100644 index f1e362da3..000000000 --- a/cefpython/cef1/client_handler/cookie_visitor.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ - -#include "cookie_visitor.h" -#include - -bool CookieVisitor::Visit( - const CefCookie& cookie, - int count, - int total, - bool& deleteCookie - ) { - REQUIRE_IO_THREAD(); - return CookieVisitor_Visit(cookieVisitorId_, cookie, count, total, deleteCookie); -} diff --git a/cefpython/cef1/client_handler/cookie_visitor.h b/cefpython/cef1/client_handler/cookie_visitor.h deleted file mode 100644 index b33a8f6e2..000000000 --- a/cefpython/cef1/client_handler/cookie_visitor.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ - -#pragma once - -#if defined(_WIN32) -#include "../windows/stdint.h" -#endif - -#include "cefpython_public_api.h" - -class CookieVisitor : public CefCookieVisitor -{ -public: - int cookieVisitorId_; -public: - CookieVisitor(int cookieVisitorId) - : cookieVisitorId_(cookieVisitorId) { - } - - virtual bool Visit( - const CefCookie& cookie, - int count, - int total, - bool& deleteCookie - ) OVERRIDE; - -protected: - // Include the default reference counting implementation. - IMPLEMENT_REFCOUNTING(CookieVisitor); -}; diff --git a/cefpython/cef1/client_handler/download_handler.cpp b/cefpython/cef1/client_handler/download_handler.cpp deleted file mode 100644 index 7f8b60aa3..000000000 --- a/cefpython/cef1/client_handler/download_handler.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ - -#include "download_handler.h" -#include - -bool DownloadHandler::ReceivedData( - void* data, - int data_size - ) { - // Multiple downloads at the same time? - AutoLock lock_scope(this); - REQUIRE_UI_THREAD(); - if (data_size == 0) - return true; - return DownloadHandler_ReceivedData(downloadHandlerId_, data, data_size); -} - -void DownloadHandler::Complete() { - // Multiple downloads at the same time? - AutoLock lock_scope(this); - REQUIRE_UI_THREAD(); - DownloadHandler_Complete(downloadHandlerId_); -} diff --git a/cefpython/cef1/client_handler/download_handler.h b/cefpython/cef1/client_handler/download_handler.h deleted file mode 100644 index ad8029658..000000000 --- a/cefpython/cef1/client_handler/download_handler.h +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ - -#pragma once - -#if defined(_WIN32) -#include "../windows/stdint.h" -#endif - -#include "cefpython_public_api.h" - -class DownloadHandler : public CefDownloadHandler -{ -public: - int downloadHandlerId_; -public: - DownloadHandler(int downloadHandlerId) - : downloadHandlerId_(downloadHandlerId) { - } - - virtual bool ReceivedData(void* data, int data_size) OVERRIDE; - virtual void Complete() OVERRIDE; - -protected: - // Include the default reference counting implementation. - IMPLEMENT_REFCOUNTING(DownloadHandler); - // Include the default locking implementation. - IMPLEMENT_LOCKING(DownloadHandler); -}; diff --git a/cefpython/cef1/client_handler/web_request_client.cpp b/cefpython/cef1/client_handler/web_request_client.cpp deleted file mode 100644 index 2f5039f10..000000000 --- a/cefpython/cef1/client_handler/web_request_client.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ - -#include "web_request_client.h" - -// Cython doesn't know nothing about 'const' so we need to remove it, -// otherwise you get compile error. - -void WebRequestClient::OnStateChange(CefRefPtr requester, - RequestState state) { - REQUIRE_UI_THREAD(); - WebRequestClient_OnStateChange(webRequestId_, requester, state); -} - -void WebRequestClient::OnRedirect(CefRefPtr requester, - CefRefPtr request, - CefRefPtr response) { - REQUIRE_UI_THREAD(); - WebRequestClient_OnRedirect(webRequestId_, requester, request, response); -} - -void WebRequestClient::OnHeadersReceived(CefRefPtr requester, - CefRefPtr response) { - REQUIRE_UI_THREAD(); - WebRequestClient_OnHeadersReceived(webRequestId_, requester, response); -} - -void WebRequestClient::OnProgress(CefRefPtr requester, - uint64 bytesSent, uint64 totalBytesToBeSent) { - REQUIRE_UI_THREAD(); - WebRequestClient_OnProgress(webRequestId_, requester, bytesSent, - totalBytesToBeSent); -} - -void WebRequestClient::OnData(CefRefPtr requester, - const void* data, int dataLength) { - REQUIRE_UI_THREAD(); - WebRequestClient_OnData(webRequestId_, requester, const_cast(data), - dataLength); -} - -void WebRequestClient::OnError(CefRefPtr requester, - ErrorCode errorCode) { - REQUIRE_UI_THREAD(); - WebRequestClient_OnError(webRequestId_, requester, errorCode); -} diff --git a/cefpython/cef1/client_handler/web_request_client.h b/cefpython/cef1/client_handler/web_request_client.h deleted file mode 100644 index 0a8eb996f..000000000 --- a/cefpython/cef1/client_handler/web_request_client.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ - -#pragma once - -#if defined(_WIN32) -#include "../windows/stdint.h" -#endif - -#include "cefpython_public_api.h" - -class WebRequestClient : public CefWebURLRequestClient -{ -public: - int webRequestId_; -public: - WebRequestClient(int webRequestId) : - webRequestId_(webRequestId) { - } - virtual ~WebRequestClient(){} - - virtual void OnStateChange(CefRefPtr requester, - RequestState state) OVERRIDE; - - virtual void OnRedirect(CefRefPtr requester, - CefRefPtr request, - CefRefPtr response) OVERRIDE; - - virtual void OnHeadersReceived(CefRefPtr requester, - CefRefPtr response) OVERRIDE; - - virtual void OnProgress(CefRefPtr requester, - uint64 bytesSent, uint64 totalBytesToBeSent) OVERRIDE; - - virtual void OnData(CefRefPtr requester, - const void* data, int dataLength) OVERRIDE; - - virtual void OnError(CefRefPtr requester, - ErrorCode errorCode) OVERRIDE; -protected: - // Include the default reference counting implementation. - IMPLEMENT_REFCOUNTING(WebRequestClient); -}; diff --git a/cefpython/cef1/http_authentication/AuthCredentials.cpp b/cefpython/cef1/http_authentication/AuthCredentials.cpp deleted file mode 100644 index 054f0006b..000000000 --- a/cefpython/cef1/http_authentication/AuthCredentials.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "AuthCredentials.h" - -AuthCredentialsDataMap AuthCredentials::data; diff --git a/cefpython/cef1/http_authentication/AuthCredentials.h b/cefpython/cef1/http_authentication/AuthCredentials.h deleted file mode 100644 index 909c4b8b4..000000000 --- a/cefpython/cef1/http_authentication/AuthCredentials.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -typedef struct -{ - std::string username; - std::string password; -} AuthCredentialsData; - -typedef std::map AuthCredentialsDataMap; - -class AuthCredentials -{ -public: - static void SetData(HWND hwnd, AuthCredentialsData* newData) - { - data[hwnd] = newData; - } - static AuthCredentialsData* GetData(HWND hwnd) - { - if (data.find(hwnd) == data.end()) { - return NULL; - } - return data[hwnd]; - } -protected: - static AuthCredentialsDataMap data; -}; diff --git a/cefpython/cef1/http_authentication/AuthDialog.cpp b/cefpython/cef1/http_authentication/AuthDialog.cpp deleted file mode 100644 index 7e18aeb15..000000000 --- a/cefpython/cef1/http_authentication/AuthDialog.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "AuthDialog.h" -#include "DialogTemplate.h" -#include - -AuthCredentialsData* AuthDialog(HWND parent) -{ - // We want close button, but no sysmenu. - DialogTemplate dialogTemplate("Http Authentication", WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | DS_CENTER, - WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE, 10, 10, 257, 80, "Tahoma", 8); - dialogTemplate.AddStatic("Username:", WS_VISIBLE, 0, 2 + 3, 7, 37, 8, -1); - dialogTemplate.AddStatic("Password:", WS_VISIBLE, 0, 2 + 3, 24, 37, 8, -1); - dialogTemplate.AddEditBox("", WS_VISIBLE | WS_TABSTOP, WS_EX_STATICEDGE, 45 + 3, 7, 80, 10, HTTP_AUTHENTICATION_USERNAME); - dialogTemplate.AddEditBox("", WS_VISIBLE | WS_TABSTOP | ES_PASSWORD, WS_EX_STATICEDGE, 45 + 3, 24, 80, 10, HTTP_AUTHENTICATION_PASSWORD); - dialogTemplate.AddButton("OK", WS_VISIBLE | WS_TABSTOP, 0, 2 + 3, 41, 48, 13, HTTP_AUTHENTICATION_OK); - dialogTemplate.AddButton("Cancel", WS_VISIBLE | WS_TABSTOP, 0, 55 + 3, 41, 48, 13, HTTP_AUTHENTICATION_CANCEL); - - INT_PTR ret = DialogBoxIndirect(GetModuleHandle(0), dialogTemplate, parent, (DLGPROC)AuthDialogProc); - if (1 == ret) { - // OK. - AuthCredentialsData* credentialsData = AuthCredentials::GetData(parent); - if (credentialsData == NULL) { - // Wrong HWND, parent == innerWindowID, - // but in AuthDialogProc() > GetWindow(hDlg, GW_OWNER) returned topWindowID. - HWND tryParent = GetParent(parent); - if (!tryParent) { - // GetParent() works fine, calling GW_OWNER just in case. - // Yes, the order is the reversed compared to what is in AuthDialogProc(). - tryParent = GetWindow(parent, GW_OWNER); - } - credentialsData = AuthCredentials::GetData(tryParent); - } - return credentialsData; - } else { - // Cancel. - return NULL; - } -} - -INT_PTR CALLBACK AuthDialogProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) -{ - HWND parent; - AuthCredentialsData* credentialsData; - TCHAR text[128]; - - switch (msg) - { - case WM_INITDIALOG: - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case HTTP_AUTHENTICATION_OK: // OK button. - case IDOK: // Enter. - - parent = GetWindow(hDlg, GW_OWNER); - if (!parent) { - // GW_OWNER works fine, calling GetParent just in case. - // Yes, the order is reversed compared to what is in AuthDialog(). - parent = GetParent(hDlg); - } - - credentialsData = AuthCredentials::GetData(parent); - if (credentialsData == NULL) { - credentialsData = new AuthCredentialsData(); - } - - GetDlgItemText(hDlg, HTTP_AUTHENTICATION_USERNAME, text, 128); - credentialsData->username.assign(text, 128); - - GetDlgItemText(hDlg, HTTP_AUTHENTICATION_PASSWORD, text, 128); - credentialsData->password.assign(text, 128); - - AuthCredentials::SetData(parent, credentialsData); - - EndDialog(hDlg, 1); - return TRUE; - - case HTTP_AUTHENTICATION_CANCEL: // Cancel button. - case IDCANCEL: // Close Button or Escape key. - EndDialog(hDlg, 2); - return TRUE; - } - break; - } - return FALSE; -} diff --git a/cefpython/cef1/http_authentication/AuthDialog.h b/cefpython/cef1/http_authentication/AuthDialog.h deleted file mode 100644 index 9c55ed48d..000000000 --- a/cefpython/cef1/http_authentication/AuthDialog.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include -#include "AuthCredentials.h" - -#define HTTP_AUTHENTICATION_USERNAME 1001 -#define HTTP_AUTHENTICATION_PASSWORD 1002 -#define HTTP_AUTHENTICATION_OK 1003 -#define HTTP_AUTHENTICATION_CANCEL 1004 - -AuthCredentialsData* AuthDialog(HWND parent); -INT_PTR CALLBACK AuthDialogProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); - diff --git a/cefpython/cef1/http_authentication/DialogTemplate.cpp b/cefpython/cef1/http_authentication/DialogTemplate.cpp deleted file mode 100644 index b9236d301..000000000 --- a/cefpython/cef1/http_authentication/DialogTemplate.cpp +++ /dev/null @@ -1,236 +0,0 @@ -// DialogTemplate - taken from here: -// http://www.flipcode.com/archives/Dialog_Template.shtml -// http://www.flipcode.com/archives/An_assert_Replacement.shtml - -#include "DialogTemplate.h" - -DialogTemplate::DialogTemplate(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, - LPCSTR font, WORD fontSize) - { - - usedBufferLength = sizeof(DLGTEMPLATE ); - totalBufferLength = usedBufferLength; - - dialogTemplate = (DLGTEMPLATE*)malloc(totalBufferLength); - - dialogTemplate->style = style; - - if (font != NULL) - { - dialogTemplate->style |= DS_SETFONT; - } - - dialogTemplate->x = x; - dialogTemplate->y = y; - dialogTemplate->cx = w; - dialogTemplate->cy = h; - dialogTemplate->cdit = 0; - - dialogTemplate->dwExtendedStyle = exStyle; - - // The dialog box doesn't have a menu or a special class - - AppendData("\0", 2); - AppendData("\0", 2); - - // Add the dialog's caption to the template - - AppendString(caption); - - if (font != NULL) - { - AppendData(&fontSize, sizeof(WORD)); - AppendString(font); - } - - } - -void DialogTemplate::AddComponent(LPCSTR type, LPCSTR caption, DWORD style, DWORD exStyle, - int x, int y, int w, int h, WORD id) - { - - DLGITEMTEMPLATE item; - - item.style = style; - item.x = x; - item.y = y; - item.cx = w; - item.cy = h; - item.id = id; - - item.dwExtendedStyle = exStyle; - - AppendData(&item, sizeof(DLGITEMTEMPLATE)); - - AppendString(type); - AppendString(caption); - - WORD creationDataLength = 0; - AppendData(&creationDataLength, sizeof(WORD)); - - // Increment the component count - - dialogTemplate->cdit++; - - } - -void DialogTemplate::AddButton(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, - int w, int h, WORD id) - { - - AddStandardComponent(0x0080, caption, style, exStyle, x, y, w, h, id); - - WORD creationDataLength = 0; - AppendData(&creationDataLength, sizeof(WORD)); - - } - -void DialogTemplate::AddEditBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, - int w, int h, WORD id) - { - - AddStandardComponent(0x0081, caption, style, exStyle, x, y, w, h, id); - - WORD creationDataLength = 0; - AppendData(&creationDataLength, sizeof(WORD)); - - } - -void DialogTemplate::AddStatic(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, - int w, int h, WORD id) - { - - AddStandardComponent(0x0082, caption, style, exStyle, x, y, w, h, id); - - WORD creationDataLength = 0; - AppendData(&creationDataLength, sizeof(WORD)); - - } - -void DialogTemplate::AddListBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, - int w, int h, WORD id) - { - - AddStandardComponent(0x0083, caption, style, exStyle, x, y, w, h, id); - - WORD creationDataLength = 0; - AppendData(&creationDataLength, sizeof(WORD)); - - } - -void DialogTemplate::AddScrollBar(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, - int w, int h, WORD id) - { - - AddStandardComponent(0x0084, caption, style, exStyle, x, y, w, h, id); - - WORD creationDataLength = 0; - AppendData(&creationDataLength, sizeof(WORD)); - - } - -void DialogTemplate::AddComboBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, - int w, int h, WORD id) - { - - AddStandardComponent(0x0085, caption, style, exStyle, x, y, w, h, id); - - WORD creationDataLength = 0; - AppendData(&creationDataLength, sizeof(WORD)); - - } - - /** - * Returns a pointer to the Win32 dialog template which the object - * represents. This pointer may become invalid if additional - * components are added to the template. - */ - - -void DialogTemplate::AddStandardComponent(WORD type, LPCSTR caption, DWORD style, - DWORD exStyle, int x, int y, int w, int h, WORD id) - { - - DLGITEMTEMPLATE item; - - // DWORD algin the beginning of the component data - - AlignData(sizeof(DWORD)); - - item.style = style; - item.x = x; - item.y = y; - item.cx = w; - item.cy = h; - item.id = id; - - item.dwExtendedStyle = exStyle; - - AppendData(&item, sizeof(DLGITEMTEMPLATE)); - - WORD preType = 0xFFFF; - - AppendData(&preType, sizeof(WORD)); - AppendData(&type, sizeof(WORD)); - - AppendString(caption); - - // Increment the component count - - dialogTemplate->cdit++; - - } - -void DialogTemplate::AlignData(int size) - { - - int paddingSize = usedBufferLength % size; - - if (paddingSize != 0) - { - EnsureSpace(paddingSize); - usedBufferLength += paddingSize; - } - - } - -void DialogTemplate::AppendString(LPCSTR string) - { - - int length = MultiByteToWideChar(CP_ACP, 0, string, -1, NULL, 0); - - WCHAR* wideString = (WCHAR*)malloc(sizeof(WCHAR) * length); - MultiByteToWideChar(CP_ACP, 0, string, -1, wideString, length); - - AppendData(wideString, length * sizeof(WCHAR)); - free(wideString); - - } - -void DialogTemplate::AppendData(void* data, int dataLength) - { - - EnsureSpace(dataLength); - - memcpy((char*)dialogTemplate + usedBufferLength, data, dataLength); - usedBufferLength += dataLength; - - } - -void DialogTemplate::EnsureSpace(int length) - { - - if (length + usedBufferLength > totalBufferLength) - { - - totalBufferLength += length * 2; - - void* newBuffer = malloc(totalBufferLength); - memcpy(newBuffer, dialogTemplate, usedBufferLength); - - free(dialogTemplate); - dialogTemplate = (DLGTEMPLATE*)newBuffer; - - } - - } diff --git a/cefpython/cef1/http_authentication/DialogTemplate.h b/cefpython/cef1/http_authentication/DialogTemplate.h deleted file mode 100644 index f7b8ae52b..000000000 --- a/cefpython/cef1/http_authentication/DialogTemplate.h +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -// DialogTemplate - taken from here: -// http://www.flipcode.com/archives/Dialog_Template.shtml -// http://www.flipcode.com/archives/An_assert_Replacement.shtml - -#include - -class DialogTemplate -{ - -public: - - DialogTemplate(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, - LPCSTR font, WORD fontSize); - - void AddComponent(LPCSTR type, LPCSTR caption, DWORD style, DWORD exStyle, - int x, int y, int w, int h, WORD id); - - void AddButton(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, - int w, int h, WORD id); - - void AddEditBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, - int w, int h, WORD id); - - void AddStatic(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, - int w, int h, WORD id); - - void AddListBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, - int w, int h, WORD id); - - void AddScrollBar(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, - int w, int h, WORD id); - - void AddComboBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, - int w, int h, WORD id); - - operator const DLGTEMPLATE*() const - { - return dialogTemplate; - } - - virtual ~DialogTemplate() - { - free(dialogTemplate); - } - -protected: - - void AddStandardComponent(WORD type, LPCSTR caption, DWORD style, - DWORD exStyle, int x, int y, int w, int h, WORD id); - - void AlignData(int size); - - void AppendString(LPCSTR string); - - void AppendData(void* data, int dataLength); - - void EnsureSpace(int length); - -private: - - DLGTEMPLATE* dialogTemplate; - - int totalBufferLength; - int usedBufferLength; - -}; \ No newline at end of file diff --git a/cefpython/cef1/http_authentication/http_authentication.sln b/cefpython/cef1/http_authentication/http_authentication.sln deleted file mode 100644 index d8ff60555..000000000 --- a/cefpython/cef1/http_authentication/http_authentication.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "http_authentication", "http_authentication.vcproj", "{25F1A352-E0AA-4F1A-8134-CB5409953AE9}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {25F1A352-E0AA-4F1A-8134-CB5409953AE9}.Debug|Win32.ActiveCfg = Debug|Win32 - {25F1A352-E0AA-4F1A-8134-CB5409953AE9}.Debug|Win32.Build.0 = Debug|Win32 - {25F1A352-E0AA-4F1A-8134-CB5409953AE9}.Release|Win32.ActiveCfg = Release|Win32 - {25F1A352-E0AA-4F1A-8134-CB5409953AE9}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/cefpython/cef1/http_authentication/http_authentication.vcproj b/cefpython/cef1/http_authentication/http_authentication.vcproj deleted file mode 100644 index bd610b43f..000000000 --- a/cefpython/cef1/http_authentication/http_authentication.vcproj +++ /dev/null @@ -1,187 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cefpython/cef1/include/cef_app.h b/cefpython/cef1/include/cef_app.h deleted file mode 100644 index e352ebbac..000000000 --- a/cefpython/cef1/include/cef_app.h +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) 2013 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - - -#ifndef CEF_INCLUDE_CEF_APP_H_ -#define CEF_INCLUDE_CEF_APP_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_proxy_handler.h" -#include "include/cef_resource_bundle_handler.h" -#include "include/cef_scheme.h" - -class CefApp; - -/// -// This function should be called on the main application thread to initialize -// CEF when the application is started. The |application| parameter may be -// empty. A return value of true indicates that it succeeded and false indicates -// that it failed. -/// -/*--cef(revision_check,optional_param=application)--*/ -bool CefInitialize(const CefSettings& settings, CefRefPtr application); - -/// -// This function should be called on the main application thread to shut down -// CEF before the application exits. -/// -/*--cef()--*/ -void CefShutdown(); - -/// -// Perform a single iteration of CEF message loop processing. This function is -// used to integrate the CEF message loop into an existing application message -// loop. Care must be taken to balance performance against excessive CPU usage. -// This function should only be called on the main application thread and only -// if CefInitialize() is called with a CefSettings.multi_threaded_message_loop -// value of false. This function will not block. -/// -/*--cef()--*/ -void CefDoMessageLoopWork(); - -/// -// Run the CEF message loop. Use this function instead of an application- -// provided message loop to get the best balance between performance and CPU -// usage. This function should only be called on the main application thread and -// only if CefInitialize() is called with a -// CefSettings.multi_threaded_message_loop value of false. This function will -// block until a quit message is received by the system. -/// -/*--cef()--*/ -void CefRunMessageLoop(); - -/// -// Quit the CEF message loop that was started by calling CefRunMessageLoop(). -// This function should only be called on the main application thread and only -// if CefRunMessageLoop() was used. -/// -/*--cef()--*/ -void CefQuitMessageLoop(); - -/// -// Set to true before calling Windows APIs like TrackPopupMenu that enter a -// modal message loop. Set to false after exiting the modal message loop. -/// -/*--cef()--*/ -void CefSetOSModalLoop(bool osModalLoop); - -/// -// Implement this interface to provide handler implementations. Methods will be -// called on the thread indicated. -/// -/*--cef(source=client,no_debugct_check)--*/ -class CefApp : public virtual CefBase { - public: - /// - // Provides an opportunity to register custom schemes. Do not keep a reference - // to the |registrar| object. This method is called on the UI thread. - /// - /*--cef()--*/ - virtual void OnRegisterCustomSchemes( - CefRefPtr registrar) { - } - - /// - // Return the handler for resource bundle events. If - // CefSettings.pack_loading_disabled is true a handler must be returned. If no - // handler is returned resources will be loaded from pack files. This method - // is called on multiple threads. - /// - /*--cef()--*/ - virtual CefRefPtr GetResourceBundleHandler() { - return NULL; - } - - /// - // Return the handler for proxy events. If not handler is returned the default - // system handler will be used. This method is called on the IO thread. - /// - /*--cef()--*/ - virtual CefRefPtr GetProxyHandler() { - return NULL; - } -}; - -#endif // CEF_INCLUDE_CEF_APP_H_ diff --git a/cefpython/cef1/include/cef_application_mac.h b/cefpython/cef1/include/cef_application_mac.h deleted file mode 100644 index 33042478c..000000000 --- a/cefpython/cef1/include/cef_application_mac.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CEF_INCLUDE_CEF_APPLICATION_MAC_H_ -#define CEF_INCLUDE_CEF_APPLICATION_MAC_H_ -#pragma once - -#include "include/cef_base.h" - -#if defined(OS_MACOSX) && defined(__OBJC__) - -#ifdef BUILDING_CEF_SHARED - -// Use the existing CrAppProtocol definition. -#include "base/message_pump_mac.h" - -// Use the existing empty protocol definitions. -#import "base/mac/cocoa_protocols.h" - -#else // BUILDING_CEF_SHARED - -#import -#import - -// Copy of CrAppProtocol definition from base/message_pump_mac.h. -@protocol CrAppProtocol -// Must return true if -[NSApplication sendEvent:] is currently on the stack. -- (BOOL)isHandlingSendEvent; -@end - -// The Mac OS X 10.6 SDK introduced new protocols used for delegates. These -// protocol defintions were not present in earlier releases of the Mac OS X -// SDK. In order to support building against the new SDK, which requires -// delegates to conform to these protocols, and earlier SDKs, which do not -// define these protocols at all, this file will provide empty protocol -// definitions when used with earlier SDK versions. - -#if !defined(MAC_OS_X_VERSION_10_6) || \ -MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 - -#define DEFINE_EMPTY_PROTOCOL(p) \ -@protocol p \ -@end - -DEFINE_EMPTY_PROTOCOL(NSAlertDelegate) -DEFINE_EMPTY_PROTOCOL(NSApplicationDelegate) -DEFINE_EMPTY_PROTOCOL(NSControlTextEditingDelegate) -DEFINE_EMPTY_PROTOCOL(NSMatrixDelegate) -DEFINE_EMPTY_PROTOCOL(NSMenuDelegate) -DEFINE_EMPTY_PROTOCOL(NSOpenSavePanelDelegate) -DEFINE_EMPTY_PROTOCOL(NSOutlineViewDataSource) -DEFINE_EMPTY_PROTOCOL(NSOutlineViewDelegate) -DEFINE_EMPTY_PROTOCOL(NSSpeechSynthesizerDelegate) -DEFINE_EMPTY_PROTOCOL(NSSplitViewDelegate) -DEFINE_EMPTY_PROTOCOL(NSTableViewDataSource) -DEFINE_EMPTY_PROTOCOL(NSTableViewDelegate) -DEFINE_EMPTY_PROTOCOL(NSTextFieldDelegate) -DEFINE_EMPTY_PROTOCOL(NSTextViewDelegate) -DEFINE_EMPTY_PROTOCOL(NSWindowDelegate) - -#undef DEFINE_EMPTY_PROTOCOL - -#endif - -#endif // BUILDING_CEF_SHARED - -// All CEF client applications must subclass NSApplication and implement this -// protocol. -@protocol CefAppProtocol -- (void)setHandlingSendEvent:(BOOL)handlingSendEvent; -@end - -// Controls the state of |isHandlingSendEvent| in the event loop so that it is -// reset properly. -class CefScopedSendingEvent { - public: - CefScopedSendingEvent() - : app_(static_cast*>( - [NSApplication sharedApplication])), - handling_([app_ isHandlingSendEvent]) { - [app_ setHandlingSendEvent:YES]; - } - ~CefScopedSendingEvent() { - [app_ setHandlingSendEvent:handling_]; - } - - private: - NSApplication* app_; - BOOL handling_; -}; - -#endif // defined(OS_MACOSX) && defined(__OBJC__) - -#endif // CEF_INCLUDE_CEF_APPLICATION_MAC_H_ diff --git a/cefpython/cef1/include/cef_base.h b/cefpython/cef1/include/cef_base.h deleted file mode 100644 index 5fc964fa3..000000000 --- a/cefpython/cef1/include/cef_base.h +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - - -#ifndef CEF_INCLUDE_CEF_BASE_H_ -#define CEF_INCLUDE_CEF_BASE_H_ -#pragma once - -#include "include/internal/cef_build.h" -#include "include/internal/cef_ptr.h" -#include "include/internal/cef_types_wrappers.h" - -// Bring in platform-specific definitions. -#if defined(OS_WIN) -#include "include/internal/cef_win.h" -#elif defined(OS_MACOSX) -#include "include/internal/cef_mac.h" -#elif defined(OS_LINUX) -#include "include/internal/cef_linux.h" -#endif - -/// -// Interface defining the reference count implementation methods. All framework -// classes must extend the CefBase class. -/// -class CefBase { - public: - /// - // The AddRef method increments the reference count for the object. It should - // be called for every new copy of a pointer to a given object. The resulting - // reference count value is returned and should be used for diagnostic/testing - // purposes only. - /// - virtual int AddRef() =0; - - /// - // The Release method decrements the reference count for the object. If the - // reference count on the object falls to 0, then the object should free - // itself from memory. The resulting reference count value is returned and - // should be used for diagnostic/testing purposes only. - /// - virtual int Release() =0; - - /// - // Return the current number of references. - /// - virtual int GetRefCt() =0; - - protected: - virtual ~CefBase() {} -}; - - -/// -// Class that implements atomic reference counting. -/// -class CefRefCount { - public: - CefRefCount() : refct_(0) {} - - /// - // Atomic reference increment. - /// - int AddRef() { - return CefAtomicIncrement(&refct_); - } - - /// - // Atomic reference decrement. Delete the object when no references remain. - /// - int Release() { - return CefAtomicDecrement(&refct_); - } - - /// - // Return the current number of references. - /// - int GetRefCt() { return refct_; } - - private: - long refct_; // NOLINT(runtime/int) -}; - -/// -// Macro that provides a reference counting implementation for classes extending -// CefBase. -/// -#define IMPLEMENT_REFCOUNTING(ClassName) \ - public: \ - int AddRef() { return refct_.AddRef(); } \ - int Release() { \ - int retval = refct_.Release(); \ - if (retval == 0) \ - delete this; \ - return retval; \ - } \ - int GetRefCt() { return refct_.GetRefCt(); } \ - private: \ - CefRefCount refct_; - -/// -// Macro that provides a locking implementation. Use the Lock() and Unlock() -// methods to protect a section of code from simultaneous access by multiple -// threads. The AutoLock class is a helper that will hold the lock while in -// scope. -/// -#define IMPLEMENT_LOCKING(ClassName) \ - public: \ - class AutoLock { \ - public: \ - explicit AutoLock(ClassName* base) : base_(base) { base_->Lock(); } \ - ~AutoLock() { base_->Unlock(); } \ - private: \ - ClassName* base_; \ - }; \ - void Lock() { critsec_.Lock(); } \ - void Unlock() { critsec_.Unlock(); } \ - private: \ - CefCriticalSection critsec_; - -#endif // CEF_INCLUDE_CEF_BASE_H_ diff --git a/cefpython/cef1/include/cef_browser.h b/cefpython/cef1/include/cef_browser.h deleted file mode 100644 index 4f3508f3d..000000000 --- a/cefpython/cef1/include/cef_browser.h +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_BROWSER_H_ -#define CEF_INCLUDE_CEF_BROWSER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_frame.h" -#include - -class CefClient; - -/// -// Class used to represent a browser window. The methods of this class may be -// called on any thread unless otherwise indicated in the comments. -/// -/*--cef(source=library)--*/ -class CefBrowser : public virtual CefBase { - public: - typedef cef_key_type_t KeyType; - typedef cef_mouse_button_type_t MouseButtonType; - typedef cef_paint_element_type_t PaintElementType; - - /// - // Create a new browser window using the window parameters specified by - // |windowInfo|. All values will be copied internally and the actual window - // will be created on the UI thread. This method call will not block. - /// - /*--cef(optional_param=url)--*/ - static bool CreateBrowser(CefWindowInfo& windowInfo, - CefRefPtr client, - const CefString& url, - const CefBrowserSettings& settings); - - /// - // Create a new browser window using the window parameters specified by - // |windowInfo|. This method should only be called on the UI thread. - /// - /*--cef(optional_param=url)--*/ - static CefRefPtr CreateBrowserSync(CefWindowInfo& windowInfo, - CefRefPtr client, - const CefString& url, - const CefBrowserSettings& settings); - - /// - // Call this method before destroying a contained browser window. This method - // performs any internal cleanup that may be needed before the browser window - // is destroyed. - /// - /*--cef()--*/ - virtual void ParentWindowWillClose() =0; - - /// - // Closes this browser window. - /// - /*--cef()--*/ - virtual void CloseBrowser() =0; - - /// - // Returns true if the browser can navigate backwards. - /// - /*--cef()--*/ - virtual bool CanGoBack() =0; - /// - // Navigate backwards. - /// - /*--cef()--*/ - virtual void GoBack() =0; - /// - // Returns true if the browser can navigate forwards. - /// - /*--cef()--*/ - virtual bool CanGoForward() =0; - /// - // Navigate forwards. - /// - /*--cef()--*/ - virtual void GoForward() =0; - /// - // Reload the current page. - /// - /*--cef()--*/ - virtual void Reload() =0; - /// - // Reload the current page ignoring any cached data. - /// - /*--cef()--*/ - virtual void ReloadIgnoreCache() =0; - /// - // Stop loading the page. - /// - /*--cef()--*/ - virtual void StopLoad() =0; - - /// - // Set focus for the browser window. If |enable| is true focus will be set to - // the window. Otherwise, focus will be removed. - /// - /*--cef()--*/ - virtual void SetFocus(bool enable) =0; - - /// - // Retrieve the window handle for this browser. - /// - /*--cef()--*/ - virtual CefWindowHandle GetWindowHandle() =0; - - /// - // Retrieve the window handle of the browser that opened this browser. Will - // return NULL for non-popup windows. This method can be used in combination - // with custom handling of modal windows. - /// - /*--cef()--*/ - virtual CefWindowHandle GetOpenerWindowHandle() =0; - - /// - // Returns the globally unique identifier for this browser. - /// - /*--cef()--*/ - virtual int GetIdentifier() =0; - - /// - // Returns true if the window is a popup window. - /// - /*--cef()--*/ - virtual bool IsPopup() =0; - - // Returns true if a document has been loaded in the browser. - /*--cef()--*/ - virtual bool HasDocument() =0; - - /// - // Returns the client for this browser. - /// - /*--cef()--*/ - virtual CefRefPtr GetClient() =0; - - /// - // Returns the main (top-level) frame for the browser window. - /// - /*--cef()--*/ - virtual CefRefPtr GetMainFrame() =0; - - /// - // Returns the focused frame for the browser window. This method should only - // be called on the UI thread. - /// - /*--cef()--*/ - virtual CefRefPtr GetFocusedFrame() =0; - - /// - // Returns the frame with the specified name, or NULL if not found. This - // method should only be called on the UI thread. - /// - /*--cef()--*/ - virtual CefRefPtr GetFrame(const CefString& name) =0; - - /// - // Returns the names of all existing frames. This method should only be called - // on the UI thread. - /// - /*--cef()--*/ - virtual void GetFrameNames(std::vector& names) =0; - - /// - // Search for |searchText|. |identifier| can be used to have multiple searches - // running simultaniously. |forward| indicates whether to search forward or - // backward within the page. |matchCase| indicates whether the search should - // be case-sensitive. |findNext| indicates whether this is the first request - // or a follow-up. - /// - /*--cef()--*/ - virtual void Find(int identifier, const CefString& searchText, - bool forward, bool matchCase, bool findNext) =0; - - /// - // Cancel all searches that are currently going on. - /// - /*--cef()--*/ - virtual void StopFinding(bool clearSelection) =0; - - /// - // Get the current zoom level. The default zoom level is 0.0. This method can - // only be called on the UI thread. - /// - /*--cef()--*/ - virtual double GetZoomLevel() =0; - - /// - // Change the zoom level to the specified value. Specify 0.0 to reset the - // zoom level. The change will be applied asynchronously on the UI thread. - /// - /*--cef()--*/ - virtual void SetZoomLevel(double zoomLevel) =0; - - /// - // Clear the back/forward browsing history. - /// - /*--cef()--*/ - virtual void ClearHistory() =0; - - /// - // Open developer tools in its own window. - /// - /*--cef()--*/ - virtual void ShowDevTools() =0; - - /// - // Explicitly close the developer tools window if one exists for this browser - // instance. - /// - /*--cef()--*/ - virtual void CloseDevTools() =0; - - /// - // Returns true if window rendering is disabled. - /// - /*--cef()--*/ - virtual bool IsWindowRenderingDisabled() =0; - - /// - // Get the size of the specified element. This method should only be called on - // the UI thread. - /// - /*--cef()--*/ - virtual bool GetSize(PaintElementType type, int& width, int& height) =0; - - /// - // Set the size of the specified element. This method is only used when window - // rendering is disabled. - /// - /*--cef()--*/ - virtual void SetSize(PaintElementType type, int width, int height) =0; - - /// - // Returns true if a popup is currently visible. This method should only be - // called on the UI thread. - /// - /*--cef()--*/ - virtual bool IsPopupVisible() =0; - - /// - // Hide the currently visible popup, if any. - /// - /*--cef()--*/ - virtual void HidePopup() =0; - - /// - // Invalidate the |dirtyRect| region of the view. This method is only used - // when window rendering is disabled and will result in a call to - // HandlePaint(). - /// - /*--cef()--*/ - virtual void Invalidate(const CefRect& dirtyRect) =0; - - /// - // Get the raw image data contained in the specified element without - // performing validation. The specified |width| and |height| dimensions must - // match the current element size. On Windows |buffer| must be width*height*4 - // bytes in size and represents a BGRA image with an upper-left origin. This - // method should only be called on the UI thread. - /// - /*--cef()--*/ - virtual bool GetImage(PaintElementType type, int width, int height, - void* buffer) =0; - - /// - // Send a key event to the browser. - /// - /*--cef()--*/ - virtual void SendKeyEvent(KeyType type, const CefKeyInfo& keyInfo, - int modifiers) =0; - - /// - // Send a mouse click event to the browser. The |x| and |y| coordinates are - // relative to the upper-left corner of the view. - /// - /*--cef()--*/ - virtual void SendMouseClickEvent(int x, int y, MouseButtonType type, - bool mouseUp, int clickCount) =0; - - /// - // Send a mouse move event to the browser. The |x| and |y| coordinates are - // relative to the upper-left corner of the view. - /// - /*--cef()--*/ - virtual void SendMouseMoveEvent(int x, int y, bool mouseLeave) =0; - - /// - // Send a mouse wheel event to the browser. The |x| and |y| coordinates are - // relative to the upper-left corner of the view. The |deltaX| and |deltaY| - // values represent the movement delta in the X and Y directions respectively. - /// - /*--cef()--*/ - virtual void SendMouseWheelEvent(int x, int y, int deltaX, int deltaY) =0; - - /// - // Send a focus event to the browser. - /// - /*--cef()--*/ - virtual void SendFocusEvent(bool setFocus) =0; - - /// - // Send a capture lost event to the browser. - /// - /*--cef()--*/ - virtual void SendCaptureLostEvent() =0; -}; - -#endif // CEF_INCLUDE_CEF_BROWSER_H_ diff --git a/cefpython/cef1/include/cef_client.h b/cefpython/cef1/include/cef_client.h deleted file mode 100644 index 0a93a3c1c..000000000 --- a/cefpython/cef1/include/cef_client.h +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_CLIENT_H_ -#define CEF_INCLUDE_CEF_CLIENT_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_display_handler.h" -#include "include/cef_drag_handler.h" -#include "include/cef_find_handler.h" -#include "include/cef_focus_handler.h" -#include "include/cef_geolocation_handler.h" -#include "include/cef_jsdialog_handler.h" -#include "include/cef_keyboard_handler.h" -#include "include/cef_life_span_handler.h" -#include "include/cef_load_handler.h" -#include "include/cef_menu_handler.h" -#include "include/cef_permission_handler.h" -#include "include/cef_print_handler.h" -#include "include/cef_render_handler.h" -#include "include/cef_request_handler.h" -#include "include/cef_v8context_handler.h" -#include "include/cef_zoom_handler.h" - -/// -// Implement this interface to provide handler implementations. -/// -/*--cef(source=client,no_debugct_check)--*/ -class CefClient : public virtual CefBase { - public: - /// - // Return the handler for browser life span events. - /// - /*--cef()--*/ - virtual CefRefPtr GetLifeSpanHandler() { - return NULL; - } - - /// - // Return the handler for browser load status events. - /// - /*--cef()--*/ - virtual CefRefPtr GetLoadHandler() { - return NULL; - } - - /// - // Return the handler for browser request events. - /// - /*--cef()--*/ - virtual CefRefPtr GetRequestHandler() { - return NULL; - } - - /// - // Return the handler for browser display state events. - /// - /*--cef()--*/ - virtual CefRefPtr GetDisplayHandler() { - return NULL; - } - - /// - // Return the handler for focus events. - /// - /*--cef()--*/ - virtual CefRefPtr GetFocusHandler() { - return NULL; - } - - /// - // Return the handler for keyboard events. - /// - /*--cef()--*/ - virtual CefRefPtr GetKeyboardHandler() { - return NULL; - } - - /// - // Return the handler for context menu events. - /// - /*--cef()--*/ - virtual CefRefPtr GetMenuHandler() { - return NULL; - } - - /// - // Return the handler for browser permission events. - /// - /*--cef()--*/ - virtual CefRefPtr GetPermissionHandler() { - return NULL; - } - - /// - // Return the handler for printing events. - /// - /*--cef()--*/ - virtual CefRefPtr GetPrintHandler() { - return NULL; - } - - /// - // Return the handler for find result events. - /// - /*--cef()--*/ - virtual CefRefPtr GetFindHandler() { - return NULL; - } - - /// - // Return the handler for JavaScript dialog events. - /// - /*--cef()--*/ - virtual CefRefPtr GetJSDialogHandler() { - return NULL; - } - - /// - // Return the handler for V8 context events. - /// - /*--cef()--*/ - virtual CefRefPtr GetV8ContextHandler() { - return NULL; - } - - /// - // Return the handler for off-screen rendering events. - /// - /*--cef()--*/ - virtual CefRefPtr GetRenderHandler() { - return NULL; - } - - /// - // Return the handler for drag events. - /// - /*--cef()--*/ - virtual CefRefPtr GetDragHandler() { - return NULL; - } - - /// - // Return the handler for geolocation permissions requests. If no handler is - // provided geolocation access will be denied by default. - /// - /*--cef()--*/ - virtual CefRefPtr GetGeolocationHandler() { - return NULL; - } - - /// - // Return the handler for zoom events. If no handler is provided the default - // zoom behavior will be used. - /// - /*--cef()--*/ - virtual CefRefPtr GetZoomHandler() { - return NULL; - } -}; - -#endif // CEF_INCLUDE_CEF_CLIENT_H_ diff --git a/cefpython/cef1/include/cef_command_line.h b/cefpython/cef1/include/cef_command_line.h deleted file mode 100644 index a698187ee..000000000 --- a/cefpython/cef1/include/cef_command_line.h +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_COMMAND_LINE_H_ -#define CEF_INCLUDE_CEF_COMMAND_LINE_H_ -#pragma once - -#include "include/cef_base.h" -#include -#include - -/// -// Class used to create and/or parse command line arguments. Arguments with -// '--', '-' and, on Windows, '/' prefixes are considered switches. Switches -// will always precede any arguments without switch prefixes. Switches can -// optionally have a value specified using the '=' delimiter (e.g. -// "-switch=value"). An argument of "--" will terminate switch parsing with all -// subsequent tokens, regardless of prefix, being interpreted as non-switch -// arguments. Switch names are considered case-insensitive. This class can be -// used before CefInitialize() is called. -/// -/*--cef(source=library,no_debugct_check)--*/ -class CefCommandLine : public virtual CefBase { - public: - typedef std::vector ArgumentList; - typedef std::map SwitchMap; - - /// - // Create a new CefCommandLine instance. - /// - /*--cef(revision_check)--*/ - static CefRefPtr CreateCommandLine(); - - /// - // Initialize the command line with the specified |argc| and |argv| values. - // The first argument must be the name of the program. This method is only - // supported on non-Windows platforms. - /// - /*--cef()--*/ - virtual void InitFromArgv(int argc, const char* const* argv) =0; - - /// - // Initialize the command line with the string returned by calling - // GetCommandLineW(). This method is only supported on Windows. - /// - /*--cef()--*/ - virtual void InitFromString(const CefString& command_line) =0; - - /// - // Constructs and returns the represented command line string. Use this method - // cautiously because quoting behavior is unclear. - /// - /*--cef()--*/ - virtual CefString GetCommandLineString() =0; - - /// - // Get the program part of the command line string (the first item). - /// - /*--cef()--*/ - virtual CefString GetProgram() =0; - - /// - // Set the program part of the command line string (the first item). - /// - /*--cef()--*/ - virtual void SetProgram(const CefString& program) =0; - - /// - // Returns true if the command line has switches. - /// - /*--cef()--*/ - virtual bool HasSwitches() =0; - - /// - // Returns true if the command line contains the given switch. - /// - /*--cef()--*/ - virtual bool HasSwitch(const CefString& name) =0; - - /// - // Returns the value associated with the given switch. If the switch has no - // value or isn't present this method returns the empty string. - /// - /*--cef()--*/ - virtual CefString GetSwitchValue(const CefString& name) =0; - - /// - // Returns the map of switch names and values. If a switch has no value an - // empty string is returned. - /// - /*--cef()--*/ - virtual void GetSwitches(SwitchMap& switches) =0; - - /// - // Add a switch to the end of the command line. If the switch has no value - // pass an empty value string. - /// - /*--cef()--*/ - virtual void AppendSwitch(const CefString& name) =0; - - /// - // Add a switch with the specified value to the end of the command line. - /// - /*--cef()--*/ - virtual void AppendSwitchWithValue(const CefString& name, - const CefString& value) =0; - - /// - // True if there are remaining command line arguments. - /// - /*--cef()--*/ - virtual bool HasArguments() =0; - - /// - // Get the remaining command line arguments. - /// - /*--cef()--*/ - virtual void GetArguments(ArgumentList& arguments) =0; - - /// - // Add an argument to the end of the command line. - /// - /*--cef()--*/ - virtual void AppendArgument(const CefString& argument) =0; -}; - -#endif // CEF_INCLUDE_CEF_COMMAND_LINE_H_ diff --git a/cefpython/cef1/include/cef_content_filter.h b/cefpython/cef1/include/cef_content_filter.h deleted file mode 100644 index af5cf1755..000000000 --- a/cefpython/cef1/include/cef_content_filter.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_CONTENT_FILTER_H_ -#define CEF_INCLUDE_CEF_CONTENT_FILTER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_stream.h" - -/// -// Interface to implement for filtering response content. The methods of this -// class will always be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefContentFilter : public virtual CefBase { - public: - /// - // Set |substitute_data| to the replacement for the data in |data| if data - // should be modified. - /// - /*--cef()--*/ - virtual void ProcessData(const void* data, int data_size, - CefRefPtr& substitute_data) {} - - /// - // Called when there is no more data to be processed. It is expected that - // whatever data was retained in the last ProcessData() call, it should be - // returned now by setting |remainder| if appropriate. - /// - /*--cef()--*/ - virtual void Drain(CefRefPtr& remainder) {} -}; - -#endif // CEF_INCLUDE_CEF_CONTENT_FILTER_H_ diff --git a/cefpython/cef1/include/cef_cookie.h b/cefpython/cef1/include/cef_cookie.h deleted file mode 100644 index d24325c39..000000000 --- a/cefpython/cef1/include/cef_cookie.h +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_COOKIE_H_ -#define CEF_INCLUDE_CEF_COOKIE_H_ -#pragma once - -#include "include/cef_base.h" -#include - -class CefCookieVisitor; - - -/// -// Class used for managing cookies. The methods of this class may be called on -// any thread unless otherwise indicated. -/// -/*--cef(source=library)--*/ -class CefCookieManager : public virtual CefBase { - public: - /// - // Returns the global cookie manager. By default data will be stored at - // CefSettings.cache_path if specified or in memory otherwise. - /// - /*--cef()--*/ - static CefRefPtr GetGlobalManager(); - - /// - // Creates a new cookie manager. If |path| is empty data will be stored in - // memory only. Returns NULL if creation fails. - /// - /*--cef(optional_param=path)--*/ - static CefRefPtr CreateManager(const CefString& path); - - /// - // Set the schemes supported by this manager. By default only "http" and - // "https" schemes are supported. Must be called before any cookies are - // accessed. - /// - /*--cef()--*/ - virtual void SetSupportedSchemes(const std::vector& schemes) =0; - - /// - // Visit all cookies. The returned cookies are ordered by longest path, then - // by earliest creation date. Returns false if cookies cannot be accessed. - /// - /*--cef()--*/ - virtual bool VisitAllCookies(CefRefPtr visitor) =0; - - /// - // Visit a subset of cookies. The results are filtered by the given url - // scheme, host, domain and path. If |includeHttpOnly| is true HTTP-only - // cookies will also be included in the results. The returned cookies are - // ordered by longest path, then by earliest creation date. Returns false if - // cookies cannot be accessed. - /// - /*--cef()--*/ - virtual bool VisitUrlCookies(const CefString& url, bool includeHttpOnly, - CefRefPtr visitor) =0; - - /// - // Sets a cookie given a valid URL and explicit user-provided cookie - // attributes. This function expects each attribute to be well-formed. It will - // check for disallowed characters (e.g. the ';' character is disallowed - // within the cookie value attribute) and will return false without setting - // the cookie if such characters are found. This method must be called on the - // IO thread. - /// - /*--cef()--*/ - virtual bool SetCookie(const CefString& url, const CefCookie& cookie) =0; - - /// - // Delete all cookies that match the specified parameters. If both |url| and - // values |cookie_name| are specified all host and domain cookies matching - // both will be deleted. If only |url| is specified all host cookies (but not - // domain cookies) irrespective of path will be deleted. If |url| is empty all - // cookies for all hosts and domains will be deleted. Returns false if a non- - // empty invalid URL is specified or if cookies cannot be accessed. This - // method must be called on the IO thread. - /// - /*--cef(optional_param=url,optional_param=cookie_name)--*/ - virtual bool DeleteCookies(const CefString& url, - const CefString& cookie_name) =0; - - /// - // Sets the directory path that will be used for storing cookie data. If - // |path| is empty data will be stored in memory only. Returns false if - // cookies cannot be accessed. - /// - /*--cef(optional_param=path)--*/ - virtual bool SetStoragePath(const CefString& path) =0; -}; - - -/// -// Interface to implement for visiting cookie values. The methods of this class -// will always be called on the IO thread. -/// -/*--cef(source=client)--*/ -class CefCookieVisitor : public virtual CefBase { - public: - /// - // Method that will be called once for each cookie. |count| is the 0-based - // index for the current cookie. |total| is the total number of cookies. - // Set |deleteCookie| to true to delete the cookie currently being visited. - // Return false to stop visiting cookies. This method may never be called if - // no cookies are found. - /// - /*--cef()--*/ - virtual bool Visit(const CefCookie& cookie, int count, int total, - bool& deleteCookie) =0; -}; - -#endif // CEF_INCLUDE_CEF_COOKIE_H_ diff --git a/cefpython/cef1/include/cef_display_handler.h b/cefpython/cef1/include/cef_display_handler.h deleted file mode 100644 index 1558da24a..000000000 --- a/cefpython/cef1/include/cef_display_handler.h +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_DISPLAY_HANDLER_H_ -#define CEF_INCLUDE_CEF_DISPLAY_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" -#include "include/cef_frame.h" - -/// -// Implement this interface to handle events related to browser display state. -// The methods of this class will be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefDisplayHandler : public virtual CefBase { - public: - typedef cef_handler_statustype_t StatusType; - - /// - // Called when the navigation state has changed. - /// - /*--cef()--*/ - virtual void OnNavStateChange(CefRefPtr browser, - bool canGoBack, - bool canGoForward) {} - - /// - // Called when a frame's address has changed. - /// - /*--cef()--*/ - virtual void OnAddressChange(CefRefPtr browser, - CefRefPtr frame, - const CefString& url) {} - - /// - // Called when the size of the content area has changed. - /// - /*--cef()--*/ - virtual void OnContentsSizeChange(CefRefPtr browser, - CefRefPtr frame, - int width, - int height) {} - - /// - // Called when the page title changes. - /// - /*--cef(optional_param=title)--*/ - virtual void OnTitleChange(CefRefPtr browser, - const CefString& title) {} - - /// - // Called when the Favicon URL for a page changes. - /// - /*--cef()--*/ - virtual void OnFaviconURLChange(CefRefPtr browser, - const std::vector& icon_urls) {} - - /// - // Called when the browser is about to display a tooltip. |text| contains the - // text that will be displayed in the tooltip. To handle the display of the - // tooltip yourself return true. Otherwise, you can optionally modify |text| - // and then return false to allow the browser to display the tooltip. - /// - /*--cef(optional_param=text)--*/ - virtual bool OnTooltip(CefRefPtr browser, - CefString& text) { return false; } - - /// - // Called when the browser receives a status message. |text| contains the text - // that will be displayed in the status message and |type| indicates the - // status message type. - /// - /*--cef(optional_param=value)--*/ - virtual void OnStatusMessage(CefRefPtr browser, - const CefString& value, - StatusType type) {} - - /// - // Called to display a console message. Return true to stop the message from - // being output to the console. - /// - /*--cef(optional_param=message,optional_param=source)--*/ - virtual bool OnConsoleMessage(CefRefPtr browser, - const CefString& message, - const CefString& source, - int line) { return false; } -}; - -#endif // CEF_INCLUDE_CEF_DISPLAY_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_dom.h b/cefpython/cef1/include/cef_dom.h deleted file mode 100644 index b56050d87..000000000 --- a/cefpython/cef1/include/cef_dom.h +++ /dev/null @@ -1,429 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_DOM_H_ -#define CEF_INCLUDE_CEF_DOM_H_ -#pragma once - -#include "include/cef_base.h" -#include - -class CefDOMDocument; -class CefDOMEventListener; -class CefDOMNode; - -/// -// Interface to implement for visiting the DOM. The methods of this class will -// be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefDOMVisitor : public virtual CefBase { - public: - /// - // Method executed for visiting the DOM. The document object passed to this - // method represents a snapshot of the DOM at the time this method is - // executed. DOM objects are only valid for the scope of this method. Do not - // keep references to or attempt to access any DOM objects outside the scope - // of this method. - /// - /*--cef()--*/ - virtual void Visit(CefRefPtr document) =0; -}; - - -/// -// Class used to represent a DOM document. The methods of this class should only -// be called on the UI thread. -/// -/*--cef(source=library)--*/ -class CefDOMDocument : public virtual CefBase { - public: - typedef cef_dom_document_type_t Type; - - /// - // Returns the document type. - /// - /*--cef(default_retval=DOM_DOCUMENT_TYPE_UNKNOWN)--*/ - virtual Type GetType() =0; - - /// - // Returns the root document node. - /// - /*--cef()--*/ - virtual CefRefPtr GetDocument() =0; - - /// - // Returns the BODY node of an HTML document. - /// - /*--cef()--*/ - virtual CefRefPtr GetBody() =0; - - /// - // Returns the HEAD node of an HTML document. - /// - /*--cef()--*/ - virtual CefRefPtr GetHead() =0; - - /// - // Returns the title of an HTML document. - /// - /*--cef()--*/ - virtual CefString GetTitle() =0; - - /// - // Returns the document element with the specified ID value. - /// - /*--cef()--*/ - virtual CefRefPtr GetElementById(const CefString& id) =0; - - /// - // Returns the node that currently has keyboard focus. - /// - /*--cef()--*/ - virtual CefRefPtr GetFocusedNode() =0; - - /// - // Returns true if a portion of the document is selected. - /// - /*--cef()--*/ - virtual bool HasSelection() =0; - - /// - // Returns the selection start node. - /// - /*--cef()--*/ - virtual CefRefPtr GetSelectionStartNode() =0; - - /// - // Returns the selection offset within the start node. - /// - /*--cef()--*/ - virtual int GetSelectionStartOffset() =0; - - /// - // Returns the selection end node. - /// - /*--cef()--*/ - virtual CefRefPtr GetSelectionEndNode() =0; - - /// - // Returns the selection offset within the end node. - /// - /*--cef()--*/ - virtual int GetSelectionEndOffset() =0; - - /// - // Returns the contents of this selection as markup. - /// - /*--cef()--*/ - virtual CefString GetSelectionAsMarkup() =0; - - /// - // Returns the contents of this selection as text. - /// - /*--cef()--*/ - virtual CefString GetSelectionAsText() =0; - - /// - // Returns the base URL for the document. - /// - /*--cef()--*/ - virtual CefString GetBaseURL() =0; - - /// - // Returns a complete URL based on the document base URL and the specified - // partial URL. - /// - /*--cef()--*/ - virtual CefString GetCompleteURL(const CefString& partialURL) =0; -}; - - -/// -// Class used to represent a DOM node. The methods of this class should only be -// called on the UI thread. -/// -/*--cef(source=library)--*/ -class CefDOMNode : public virtual CefBase { - public: - typedef std::map AttributeMap; - typedef cef_dom_node_type_t Type; - - /// - // Returns the type for this node. - /// - /*--cef(default_retval=DOM_NODE_TYPE_UNSUPPORTED)--*/ - virtual Type GetType() =0; - - /// - // Returns true if this is a text node. - /// - /*--cef()--*/ - virtual bool IsText() =0; - - /// - // Returns true if this is an element node. - /// - /*--cef()--*/ - virtual bool IsElement() =0; - - /// - // Returns true if this is a form control element node. - /// - /*--cef()--*/ - virtual bool IsFormControlElement() =0; - - /// - // Returns the type of this form control element node. - /// - /*--cef()--*/ - virtual CefString GetFormControlElementType() =0; - - /// - // Returns true if this object is pointing to the same handle as |that| - // object. - /// - /*--cef()--*/ - virtual bool IsSame(CefRefPtr that) =0; - - /// - // Returns the name of this node. - /// - /*--cef()--*/ - virtual CefString GetName() =0; - - /// - // Returns the value of this node. - /// - /*--cef()--*/ - virtual CefString GetValue() =0; - - /// - // Set the value of this node. Returns true on success. - /// - /*--cef()--*/ - virtual bool SetValue(const CefString& value) =0; - - /// - // Returns the contents of this node as markup. - /// - /*--cef()--*/ - virtual CefString GetAsMarkup() =0; - - /// - // Returns the document associated with this node. - /// - /*--cef()--*/ - virtual CefRefPtr GetDocument() =0; - - /// - // Returns the parent node. - /// - /*--cef()--*/ - virtual CefRefPtr GetParent() =0; - - /// - // Returns the previous sibling node. - /// - /*--cef()--*/ - virtual CefRefPtr GetPreviousSibling() =0; - - /// - // Returns the next sibling node. - /// - /*--cef()--*/ - virtual CefRefPtr GetNextSibling() =0; - - /// - // Returns true if this node has child nodes. - /// - /*--cef()--*/ - virtual bool HasChildren() =0; - - /// - // Return the first child node. - /// - /*--cef()--*/ - virtual CefRefPtr GetFirstChild() =0; - - /// - // Returns the last child node. - /// - /*--cef()--*/ - virtual CefRefPtr GetLastChild() =0; - - /// - // Add an event listener to this node for the specified event type. If - // |useCapture| is true then this listener will be considered a capturing - // listener. Capturing listeners will recieve all events of the specified - // type before the events are dispatched to any other event targets beneath - // the current node in the tree. Events which are bubbling upwards through - // the tree will not trigger a capturing listener. Separate calls to this - // method can be used to register the same listener with and without capture. - // See WebCore/dom/EventNames.h for the list of supported event types. - /// - /*--cef()--*/ - virtual void AddEventListener(const CefString& eventType, - CefRefPtr listener, - bool useCapture) =0; - - - // The following methods are valid only for element nodes. - - /// - // Returns the tag name of this element. - /// - /*--cef()--*/ - virtual CefString GetElementTagName() =0; - - /// - // Returns true if this element has attributes. - /// - /*--cef()--*/ - virtual bool HasElementAttributes() =0; - - /// - // Returns true if this element has an attribute named |attrName|. - /// - /*--cef()--*/ - virtual bool HasElementAttribute(const CefString& attrName) =0; - - /// - // Returns the element attribute named |attrName|. - /// - /*--cef()--*/ - virtual CefString GetElementAttribute(const CefString& attrName) =0; - - /// - // Returns a map of all element attributes. - /// - /*--cef()--*/ - virtual void GetElementAttributes(AttributeMap& attrMap) =0; - - /// - // Set the value for the element attribute named |attrName|. Returns true on - // success. - /// - /*--cef()--*/ - virtual bool SetElementAttribute(const CefString& attrName, - const CefString& value) =0; - - /// - // Returns the inner text of the element. - /// - /*--cef()--*/ - virtual CefString GetElementInnerText() =0; -}; - - -/// -// Class used to represent a DOM event. The methods of this class should only -// be called on the UI thread. -/// -/*--cef(source=library)--*/ -class CefDOMEvent : public virtual CefBase { - public: - typedef cef_dom_event_category_t Category; - typedef cef_dom_event_phase_t Phase; - - /// - // Returns the event type. - /// - /*--cef()--*/ - virtual CefString GetType() =0; - - /// - // Returns the event category. - /// - /*--cef(default_retval=DOM_EVENT_CATEGORY_UNKNOWN)--*/ - virtual Category GetCategory() =0; - - /// - // Returns the event processing phase. - /// - /*--cef(default_retval=DOM_EVENT_PHASE_UNKNOWN)--*/ - virtual Phase GetPhase() =0; - - /// - // Returns true if the event can bubble up the tree. - /// - /*--cef()--*/ - virtual bool CanBubble() =0; - - /// - // Returns true if the event can be canceled. - /// - /*--cef()--*/ - virtual bool CanCancel() =0; - - /// - // Returns the document associated with this event. - /// - /*--cef()--*/ - virtual CefRefPtr GetDocument() =0; - - /// - // Returns the target of the event. - /// - /*--cef()--*/ - virtual CefRefPtr GetTarget() =0; - - /// - // Returns the current target of the event. - /// - /*--cef()--*/ - virtual CefRefPtr GetCurrentTarget() =0; -}; - - -/// -// Interface to implement for handling DOM events. The methods of this class -// will be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefDOMEventListener : public virtual CefBase { - public: - /// - // Called when an event is received. The event object passed to this method - // contains a snapshot of the DOM at the time this method is executed. DOM - // objects are only valid for the scope of this method. Do not keep references - // to or attempt to access any DOM objects outside the scope of this method. - /// - /*--cef()--*/ - virtual void HandleEvent(CefRefPtr event) =0; -}; - -#endif // CEF_INCLUDE_CEF_DOM_H_ diff --git a/cefpython/cef1/include/cef_download_handler.h b/cefpython/cef1/include/cef_download_handler.h deleted file mode 100644 index 8fd209447..000000000 --- a/cefpython/cef1/include/cef_download_handler.h +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_DOWNLOAD_HANDLER_H_ -#define CEF_INCLUDE_CEF_DOWNLOAD_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" - -/// -// Class used to handle file downloads. The methods of this class will always be -// called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefDownloadHandler : public virtual CefBase { - public: - /// - // A portion of the file contents have been received. This method will be - // called multiple times until the download is complete. Return |true| to - // continue receiving data and |false| to cancel. - /// - /*--cef()--*/ - virtual bool ReceivedData(void* data, int data_size) =0; - - /// - // The download is complete. - /// - /*--cef()--*/ - virtual void Complete() =0; -}; - -#endif // CEF_INCLUDE_CEF_DOWNLOAD_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_drag_data.h b/cefpython/cef1/include/cef_drag_data.h deleted file mode 100644 index 54400cdd8..000000000 --- a/cefpython/cef1/include/cef_drag_data.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_DRAG_DATA_H_ -#define CEF_INCLUDE_CEF_DRAG_DATA_H_ -#pragma once - -#include "include/cef_base.h" -#include - -/// -// Class used to represent drag data. The methods of this class may be called -// on any thread. -/// -/*--cef(source=library)--*/ -class CefDragData : public virtual CefBase { - public: - /// - // Returns true if the drag data is a link. - /// - /*--cef()--*/ - virtual bool IsLink() =0; - - /// - // Returns true if the drag data is a text or html fragment. - /// - /*--cef()--*/ - virtual bool IsFragment() =0; - - /// - // Returns true if the drag data is a file. - /// - /*--cef()--*/ - virtual bool IsFile() =0; - - /// - // Return the link URL that is being dragged. - /// - /*--cef()--*/ - virtual CefString GetLinkURL() =0; - - /// - // Return the title associated with the link being dragged. - /// - /*--cef()--*/ - virtual CefString GetLinkTitle() =0; - - /// - // Return the metadata, if any, associated with the link being dragged. - /// - /*--cef()--*/ - virtual CefString GetLinkMetadata() =0; - - /// - // Return the plain text fragment that is being dragged. - /// - /*--cef()--*/ - virtual CefString GetFragmentText() =0; - - /// - // Return the text/html fragment that is being dragged. - /// - /*--cef()--*/ - virtual CefString GetFragmentHtml() =0; - - /// - // Return the base URL that the fragment came from. This value is used for - // resolving relative URLs and may be empty. - /// - /*--cef()--*/ - virtual CefString GetFragmentBaseURL() =0; - - /// - // Return the name of the file being dragged out of the browser window. - /// - /*--cef()--*/ - virtual CefString GetFileName() =0; - - /// - // Retrieve the list of file names that are being dragged into the browser - // window. - /// - /*--cef()--*/ - virtual bool GetFileNames(std::vector& names) =0; -}; - -#endif // CEF_INCLUDE_CEF_DRAG_DATA_H_ diff --git a/cefpython/cef1/include/cef_drag_handler.h b/cefpython/cef1/include/cef_drag_handler.h deleted file mode 100644 index 79d90e57e..000000000 --- a/cefpython/cef1/include/cef_drag_handler.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_DRAG_HANDLER_H_ -#define CEF_INCLUDE_CEF_DRAG_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_drag_data.h" -#include "include/cef_browser.h" - -/// -// Implement this interface to handle events related to dragging. The methods of -// this class will be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefDragHandler : public virtual CefBase { - public: - typedef cef_drag_operations_mask_t DragOperationsMask; - - /// - // Called when the browser window initiates a drag event. |dragData| - // contains the drag event data and |mask| represents the type of drag - // operation. Return false for default drag handling behavior or true to - // cancel the drag event. - /// - /*--cef()--*/ - virtual bool OnDragStart(CefRefPtr browser, - CefRefPtr dragData, - DragOperationsMask mask) { return false; } - - /// - // Called when an external drag event enters the browser window. |dragData| - // contains the drag event data and |mask| represents the type of drag - // operation. Return false for default drag handling behavior or true to - // cancel the drag event. - /// - /*--cef()--*/ - virtual bool OnDragEnter(CefRefPtr browser, - CefRefPtr dragData, - DragOperationsMask mask) { return false; } -}; - -#endif // CEF_INCLUDE_CEF_DRAG_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_find_handler.h b/cefpython/cef1/include/cef_find_handler.h deleted file mode 100644 index bead6feeb..000000000 --- a/cefpython/cef1/include/cef_find_handler.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_FIND_HANDLER_H_ -#define CEF_INCLUDE_CEF_FIND_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" - -/// -// Implement this interface to handle events related to find results. The -// methods of this class will be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefFindHandler : public virtual CefBase { - public: - /// - // Called to report find results returned by CefBrowser::Find(). |identifer| - // is the identifier passed to CefBrowser::Find(), |count| is the number of - // matches currently identified, |selectionRect| is the location of where the - // match was found (in window coordinates), |activeMatchOrdinal| is the - // current position in the search results, and |finalUpdate| is true if this - // is the last find notification. - /// - /*--cef()--*/ - virtual void OnFindResult(CefRefPtr browser, - int identifier, - int count, - const CefRect& selectionRect, - int activeMatchOrdinal, - bool finalUpdate) {} -}; - -#endif // CEF_INCLUDE_CEF_FIND_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_focus_handler.h b/cefpython/cef1/include/cef_focus_handler.h deleted file mode 100644 index a45b6f52e..000000000 --- a/cefpython/cef1/include/cef_focus_handler.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_FOCUS_HANDLER_H_ -#define CEF_INCLUDE_CEF_FOCUS_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" -#include "include/cef_dom.h" -#include "include/cef_frame.h" - -/// -// Implement this interface to handle events related to focus. The methods of -// this class will be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefFocusHandler : public virtual CefBase { - public: - typedef cef_handler_focus_source_t FocusSource; - - /// - // Called when the browser component is about to loose focus. For instance, if - // focus was on the last HTML element and the user pressed the TAB key. |next| - // will be true if the browser is giving focus to the next component and false - // if the browser is giving focus to the previous component. - /// - /*--cef()--*/ - virtual void OnTakeFocus(CefRefPtr browser, - bool next) {} - - /// - // Called when the browser component is requesting focus. |source| indicates - // where the focus request is originating from. Return false to allow the - // focus to be set or true to cancel setting the focus. - /// - /*--cef()--*/ - virtual bool OnSetFocus(CefRefPtr browser, - FocusSource source) { return false; } - - /// - // Called when a new node in the the browser gets focus. The |node| value may - // be empty if no specific node has gained focus. The node object passed to - // this method represents a snapshot of the DOM at the time this method is - // executed. DOM objects are only valid for the scope of this method. Do not - // keep references to or attempt to access any DOM objects outside the scope - // of this method. - /// - /*--cef(optional_param=frame,optional_param=node)--*/ - virtual void OnFocusedNodeChanged(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr node) {} -}; - -#endif // CEF_INCLUDE_CEF_FOCUS_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_frame.h b/cefpython/cef1/include/cef_frame.h deleted file mode 100644 index f0ac6ef7a..000000000 --- a/cefpython/cef1/include/cef_frame.h +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_FRAME_H_ -#define CEF_INCLUDE_CEF_FRAME_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_dom.h" -#include "include/cef_request.h" -#include "include/cef_stream.h" - -class CefBrowser; -class CefV8Context; - -/// -// Class used to represent a frame in the browser window. The methods of this -// class may be called on any thread unless otherwise indicated in the comments. -/// -/*--cef(source=library)--*/ -class CefFrame : public virtual CefBase { - public: - /// - // Execute undo in this frame. - /// - /*--cef()--*/ - virtual void Undo() =0; - /// - // Execute redo in this frame. - /// - /*--cef()--*/ - virtual void Redo() =0; - /// - // Execute cut in this frame. - /// - /*--cef()--*/ - virtual void Cut() =0; - /// - // Execute copy in this frame. - /// - /*--cef()--*/ - virtual void Copy() =0; - /// - // Execute paste in this frame. - /// - /*--cef()--*/ - virtual void Paste() =0; - /// - // Execute delete in this frame. - /// - /*--cef(capi_name=del)--*/ - virtual void Delete() =0; - /// - // Execute select all in this frame. - /// - /*--cef()--*/ - virtual void SelectAll() =0; - - /// - // Execute printing in the this frame. The user will be prompted with the - // print dialog appropriate to the operating system. - /// - /*--cef()--*/ - virtual void Print() =0; - - /// - // Save this frame's HTML source to a temporary file and open it in the - // default text viewing application. - /// - /*--cef()--*/ - virtual void ViewSource() =0; - - /// - // Returns this frame's HTML source as a string. This method should only be - // called on the UI thread. - /// - /*--cef()--*/ - virtual CefString GetSource() =0; - - /// - // Returns this frame's display text as a string. This method should only be - // called on the UI thread. - /// - /*--cef()--*/ - virtual CefString GetText() =0; - - /// - // Load the request represented by the |request| object. - /// - /*--cef()--*/ - virtual void LoadRequest(CefRefPtr request) =0; - - /// - // Load the specified |url|. - /// - /*--cef()--*/ - virtual void LoadURL(const CefString& url) =0; - - /// - // Load the contents of |string_val| with the optional dummy target |url|. - /// - /*--cef()--*/ - virtual void LoadString(const CefString& string_val, - const CefString& url) =0; - - /// - // Load the contents of |stream| with the optional dummy target |url|. - /// - /*--cef()--*/ - virtual void LoadStream(CefRefPtr stream, - const CefString& url) =0; - - /// - // Execute a string of JavaScript code in this frame. The |script_url| - // parameter is the URL where the script in question can be found, if any. - // The renderer may request this URL to show the developer the source of the - // error. The |start_line| parameter is the base line number to use for error - // reporting. - /// - /*--cef(optional_param=scriptUrl)--*/ - virtual void ExecuteJavaScript(const CefString& jsCode, - const CefString& scriptUrl, - int startLine) =0; - - /// - // Returns true if this is the main (top-level) frame. - /// - /*--cef()--*/ - virtual bool IsMain() =0; - - /// - // Returns true if this is the focused frame. This method should only be - // called on the UI thread. - /// - /*--cef()--*/ - virtual bool IsFocused() =0; - - /// - // Returns the name for this frame. If the frame has an assigned name (for - // example, set via the iframe "name" attribute) then that value will be - // returned. Otherwise a unique name will be constructed based on the frame - // parent hierarchy. The main (top-level) frame will always have an empty name - // value. - /// - /*--cef()--*/ - virtual CefString GetName() =0; - - /// - // Returns the globally unique identifier for this frame. - /// - /*--cef()--*/ - virtual int64 GetIdentifier() =0; - - /// - // Returns the parent of this frame or NULL if this is the main (top-level) - // frame. This method should only be called on the UI thread. - /// - /*--cef()--*/ - virtual CefRefPtr GetParent() =0; - - /// - // Returns the URL currently loaded in this frame. - /// - /*--cef()--*/ - virtual CefString GetURL() =0; - - /// - // Returns the browser that this frame belongs to. - /// - /*--cef()--*/ - virtual CefRefPtr GetBrowser() =0; - - /// - // Visit the DOM document. - /// - /*--cef()--*/ - virtual void VisitDOM(CefRefPtr visitor) =0; - - /// - // Get the V8 context associated with the frame. This method should only be - // called on the UI thread. - /// - /*--cef()--*/ - virtual CefRefPtr GetV8Context() =0; -}; - -#endif // CEF_INCLUDE_CEF_FRAME_H_ diff --git a/cefpython/cef1/include/cef_geolocation.h b/cefpython/cef1/include/cef_geolocation.h deleted file mode 100644 index 69c08779c..000000000 --- a/cefpython/cef1/include/cef_geolocation.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_GEOLOCATION_H_ -#define CEF_INCLUDE_CEF_GEOLOCATION_H_ -#pragma once - -#include "include/cef_base.h" - -/// -// Implement this interface to receive geolocation updates. The methods of this -// class will be called on the browser process UI thread. -/// -/*--cef(source=client)--*/ -class CefGetGeolocationCallback : public virtual CefBase { - public: - /// - // Called with the 'best available' location information or, if the location - // update failed, with error information. - /// - /*--cef()--*/ - virtual void OnLocationUpdate(const CefGeoposition& position) =0; -}; - -/// -// Request a one-time geolocation update. This function bypasses any user -// permission checks so should only be used by code that is allowed to access -// location information. -/// -/*--cef()--*/ -bool CefGetGeolocation(CefRefPtr callback); - -#endif // CEF_INCLUDE_CEF_GEOLOCATION_H_ diff --git a/cefpython/cef1/include/cef_geolocation_handler.h b/cefpython/cef1/include/cef_geolocation_handler.h deleted file mode 100644 index 4b732b482..000000000 --- a/cefpython/cef1/include/cef_geolocation_handler.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_GEOLOCATION_HANDLER_H_ -#define CEF_INCLUDE_CEF_GEOLOCATION_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" - -/// -// Callback interface used for asynchronous continuation of geolocation -// permission requests. -/// -/*--cef(source=library)--*/ -class CefGeolocationCallback : public virtual CefBase { - public: - /// - // Call to allow or deny geolocation access. - /// - /*--cef(capi_name=cont)--*/ - virtual void Continue(bool allow) =0; -}; - - -/// -// Implement this interface to handle events related to geolocation permission -// requests. The methods of this class will be called on the browser process UI -// thread. -/// -/*--cef(source=client)--*/ -class CefGeolocationHandler : public virtual CefBase { - public: - /// - // Called when a page requests permission to access geolocation information. - // |requesting_url| is the URL requesting permission and |request_id| is the - // unique ID for the permission request. Call CefGeolocationCallback::Continue - // to allow or deny the permission request. - /// - /*--cef()--*/ - virtual void OnRequestGeolocationPermission( - CefRefPtr browser, - const CefString& requesting_url, - int request_id, - CefRefPtr callback) { - } - - /// - // Called when a geolocation access request is canceled. |requesting_url| is - // the URL that originally requested permission and |request_id| is the unique - // ID for the permission request. - /// - /*--cef()--*/ - virtual void OnCancelGeolocationPermission( - CefRefPtr browser, - const CefString& requesting_url, - int request_id) { - } -}; - -#endif // CEF_INCLUDE_CEF_GEOLOCATION_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_jsdialog_handler.h b/cefpython/cef1/include/cef_jsdialog_handler.h deleted file mode 100644 index d3067f3c0..000000000 --- a/cefpython/cef1/include/cef_jsdialog_handler.h +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_JSDIALOG_HANDLER_H_ -#define CEF_INCLUDE_CEF_JSDIALOG_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" -#include "include/cef_frame.h" - -/// -// Implement this interface to handle events related to JavaScript dialogs. The -// methods of this class will be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefJSDialogHandler : public virtual CefBase { - public: - /// - // Called to run a JavaScript alert message. Return false to display the - // default alert or true if you displayed a custom alert. - /// - /*--cef(optional_param=message)--*/ - virtual bool OnJSAlert(CefRefPtr browser, - CefRefPtr frame, - const CefString& message) { return false; } - - /// - // Called to run a JavaScript confirm request. Return false to display the - // default alert or true if you displayed a custom alert. If you handled the - // alert set |retval| to true if the user accepted the confirmation. - /// - /*--cef(optional_param=message)--*/ - virtual bool OnJSConfirm(CefRefPtr browser, - CefRefPtr frame, - const CefString& message, - bool& retval) { return false; } - - /// - // Called to run a JavaScript prompt request. Return false to display the - // default prompt or true if you displayed a custom prompt. If you handled - // the prompt set |retval| to true if the user accepted the prompt and request - // and |result| to the resulting value. - /// - /*--cef(optional_param=message,optional_param=defaultValue)--*/ - virtual bool OnJSPrompt(CefRefPtr browser, - CefRefPtr frame, - const CefString& message, - const CefString& defaultValue, - bool& retval, - CefString& result) { return false; } -}; - -#endif // CEF_INCLUDE_CEF_JSDIALOG_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_keyboard_handler.h b/cefpython/cef1/include/cef_keyboard_handler.h deleted file mode 100644 index a8133e91f..000000000 --- a/cefpython/cef1/include/cef_keyboard_handler.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_KEYBOARD_HANDLER_H_ -#define CEF_INCLUDE_CEF_KEYBOARD_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" - -/// -// Implement this interface to handle events related to keyboard input. The -// methods of this class will be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefKeyboardHandler : public virtual CefBase { - public: - typedef cef_handler_keyevent_type_t KeyEventType; - - /// - // Called when the browser component receives a keyboard event. This method - // is called both before the event is passed to the renderer and after - // JavaScript in the page has had a chance to handle the event. |type| is the - // type of keyboard event, |code| is the windows scan-code for the event, - // |modifiers| is a set of bit- flags describing any pressed modifier keys and - // |isSystemKey| is true if Windows considers this a 'system key' message (see - // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx). If - // |isAfterJavaScript| is true then JavaScript in the page has had a chance - // to handle the event and has chosen not to. Only RAWKEYDOWN, KEYDOWN and - // CHAR events will be sent with |isAfterJavaScript| set to true. Return - // true if the keyboard event was handled or false to allow continued handling - // of the event by the renderer. - /// - /*--cef()--*/ - virtual bool OnKeyEvent(CefRefPtr browser, - KeyEventType type, - int code, - int modifiers, - bool isSystemKey, - bool isAfterJavaScript) { return false; } -}; - -#endif // CEF_INCLUDE_CEF_KEYBOARD_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_life_span_handler.h b/cefpython/cef1/include/cef_life_span_handler.h deleted file mode 100644 index 907d755a8..000000000 --- a/cefpython/cef1/include/cef_life_span_handler.h +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_LIFE_SPAN_HANDLER_H_ -#define CEF_INCLUDE_CEF_LIFE_SPAN_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" - -class CefClient; - -/// -// Implement this interface to handle events related to browser life span. The -// methods of this class will be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefLifeSpanHandler : public virtual CefBase { - public: - /// - // Called before a new popup window is created. The |parentBrowser| parameter - // will point to the parent browser window. The |popupFeatures| parameter will - // contain information about the style of popup window requested. Return false - // to have the framework create the new popup window based on the parameters - // in |windowInfo|. Return true to cancel creation of the popup window. By - // default, a newly created popup window will have the same client and - // settings as the parent window. To change the client for the new window - // modify the object that |client| points to. To change the settings for the - // new window modify the |settings| structure. - /// - /*--cef(optional_param=url)--*/ - virtual bool OnBeforePopup(CefRefPtr parentBrowser, - const CefPopupFeatures& popupFeatures, - CefWindowInfo& windowInfo, - const CefString& url, - CefRefPtr& client, - CefBrowserSettings& settings) { return false; } - - /// - // Called after a new window is created. - /// - /*--cef()--*/ - virtual void OnAfterCreated(CefRefPtr browser) {} - - /// - // Called when a modal window is about to display and the modal loop should - // begin running. Return false to use the default modal loop implementation or - // true to use a custom implementation. - /// - /*--cef()--*/ - virtual bool RunModal(CefRefPtr browser) { return false; } - - /// - // Called when a window has recieved a request to close. Return false to - // proceed with the window close or true to cancel the window close. If this - // is a modal window and a custom modal loop implementation was provided in - // RunModal() this callback should be used to restore the opener window to a - // usable state. - /// - /*--cef()--*/ - virtual bool DoClose(CefRefPtr browser) { return false; } - - /// - // Called just before a window is closed. If this is a modal window and a - // custom modal loop implementation was provided in RunModal() this callback - // should be used to exit the custom modal loop. - /// - /*--cef()--*/ - virtual void OnBeforeClose(CefRefPtr browser) {} -}; - -#endif // CEF_INCLUDE_CEF_LIFE_SPAN_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_load_handler.h b/cefpython/cef1/include/cef_load_handler.h deleted file mode 100644 index bfa01df25..000000000 --- a/cefpython/cef1/include/cef_load_handler.h +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_LOAD_HANDLER_H_ -#define CEF_INCLUDE_CEF_LOAD_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" -#include "include/cef_frame.h" - -/// -// Implement this interface to handle events related to browser load status. The -// methods of this class will be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefLoadHandler : public virtual CefBase { - public: - typedef cef_handler_errorcode_t ErrorCode; - - /// - // Called when the browser begins loading a frame. The |frame| value will - // never be empty -- call the IsMain() method to check if this frame is the - // main frame. Multiple frames may be loading at the same time. Sub-frames may - // start or continue loading after the main frame load has ended. This method - // may not be called for a particular frame if the load request for that frame - // fails. - /// - /*--cef()--*/ - virtual void OnLoadStart(CefRefPtr browser, - CefRefPtr frame) {} - - /// - // Called when the browser is done loading a frame. The |frame| value will - // never be empty -- call the IsMain() method to check if this frame is the - // main frame. Multiple frames may be loading at the same time. Sub-frames may - // start or continue loading after the main frame load has ended. This method - // will always be called for all frames irrespective of whether the request - // completes successfully. - /// - /*--cef()--*/ - virtual void OnLoadEnd(CefRefPtr browser, - CefRefPtr frame, - int httpStatusCode) {} - - /// - // Called when the browser fails to load a resource. |errorCode| is the error - // code number and |failedUrl| is the URL that failed to load. To provide - // custom error text assign the text to |errorText| and return true. - // Otherwise, return false for the default error text. See - // net\base\net_error_list.h for complete descriptions of the error codes. - /// - /*--cef()--*/ - virtual bool OnLoadError(CefRefPtr browser, - CefRefPtr frame, - ErrorCode errorCode, - const CefString& failedUrl, - CefString& errorText) { return false; } -}; - -#endif // CEF_INCLUDE_CEF_LOAD_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_menu_handler.h b/cefpython/cef1/include/cef_menu_handler.h deleted file mode 100644 index 81fe115b1..000000000 --- a/cefpython/cef1/include/cef_menu_handler.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_MENU_HANDLER_H_ -#define CEF_INCLUDE_CEF_MENU_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" - -/// -// Implement this interface to handle events related to browser context menus. -// The methods of this class will be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefMenuHandler : public virtual CefBase { - public: - typedef cef_menu_id_t MenuId; - - /// - // Called before a context menu is displayed. Return false to display the - // default context menu or true to cancel the display. - /// - /*--cef()--*/ - virtual bool OnBeforeMenu(CefRefPtr browser, - const CefMenuInfo& menuInfo) { return false; } - - /// - // Called to optionally override the default text for a context menu item. - // |label| contains the default text and may be modified to substitute - // alternate text. - /// - /*--cef()--*/ - virtual void GetMenuLabel(CefRefPtr browser, - MenuId menuId, - CefString& label) {} - - /// - // Called when an option is selected from the default context menu. Return - // false to execute the default action or true to cancel the action. - /// - /*--cef()--*/ - virtual bool OnMenuAction(CefRefPtr browser, - MenuId menuId) { return false; } -}; - -#endif // CEF_INCLUDE_CEF_MENU_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_nplugin.h b/cefpython/cef1/include/cef_nplugin.h deleted file mode 100644 index 4b16fe91f..000000000 --- a/cefpython/cef1/include/cef_nplugin.h +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -#ifndef CEF_INCLUDE_CEF_NPLUGIN_H_ -#define CEF_INCLUDE_CEF_NPLUGIN_H_ -#pragma once - -#include "internal/cef_nplugin_types.h" - -/// -// Netscape plugins are normally built at separate DLLs that are loaded by the -// browser when needed. This interface supports the creation of plugins that -// are an embedded component of the application. Embedded plugins built using -// this interface use the same Netscape Plugin API as DLL-based plugins. -// See https://developer.mozilla.org/En/Gecko_Plugin_API_Reference for complete -// documentation on how to use the Netscape Plugin API. -// -// This class provides attribute information and entry point functions for a -// plugin. -/// -class CefPluginInfo : public cef_plugin_info_t { - public: - CefPluginInfo() { - Init(); - } - virtual ~CefPluginInfo() { - Reset(); - } - - CefPluginInfo(const CefPluginInfo& r) { // NOLINT(runtime/explicit) - Init(); - *this = r; - } - CefPluginInfo(const cef_plugin_info_t& r) { // NOLINT(runtime/explicit) - Init(); - *this = r; - } - - void Reset() { - cef_string_clear(&unique_name); - cef_string_clear(&display_name); - cef_string_clear(&version); - cef_string_clear(&description); - cef_string_clear(&mime_types); - cef_string_clear(&file_extensions); - cef_string_clear(&type_descriptions); - Init(); - } - - void Attach(const cef_plugin_info_t& r) { - Reset(); - *static_cast(this) = r; - } - - void Detach() { - Init(); - } - - CefPluginInfo& operator=(const CefPluginInfo& r) { - return operator=(static_cast(r)); - } - - CefPluginInfo& operator=(const cef_plugin_info_t& r) { - cef_string_copy(r.unique_name.str, r.unique_name.length, &unique_name); - cef_string_copy(r.display_name.str, r.display_name.length, &display_name); - cef_string_copy(r.version.str, r.version.length, &version); - cef_string_copy(r.description.str, r.description.length, &description); - cef_string_copy(r.mime_types.str, r.mime_types.length, &mime_types); - cef_string_copy(r.file_extensions.str, r.file_extensions.length, - &file_extensions); - cef_string_copy(r.type_descriptions.str, r.type_descriptions.length, - &type_descriptions); -#if !defined(OS_POSIX) || defined(OS_MACOSX) - np_getentrypoints = r.np_getentrypoints; -#endif - np_initialize = r.np_initialize; - np_shutdown = r.np_shutdown; - return *this; - } - - protected: - void Init() { - memset(static_cast(this), 0, sizeof(cef_plugin_info_t)); - } -}; - -/// -// Register a plugin with the system. -/// -bool CefRegisterPlugin(const CefPluginInfo& plugin_info); - -#endif // CEF_INCLUDE_CEF_NPLUGIN_H_ diff --git a/cefpython/cef1/include/cef_origin_whitelist.h b/cefpython/cef1/include/cef_origin_whitelist.h deleted file mode 100644 index fd434460e..000000000 --- a/cefpython/cef1/include/cef_origin_whitelist.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_ORIGIN_WHITELIST_H_ -#define CEF_INCLUDE_CEF_ORIGIN_WHITELIST_H_ -#pragma once - -#include "include/cef_base.h" - - -/// -// Add an entry to the cross-origin access whitelist. -// -// The same-origin policy restricts how scripts hosted from different origins -// (scheme + domain + port) can communicate. By default, scripts can only access -// resources with the same origin. Scripts hosted on the HTTP and HTTPS schemes -// (but no other schemes) can use the "Access-Control-Allow-Origin" header to -// allow cross-origin requests. For example, https://source.example.com can make -// XMLHttpRequest requests on http://target.example.com if the -// http://target.example.com request returns an "Access-Control-Allow-Origin: -// https://source.example.com" response header. -// -// Scripts in separate frames or iframes and hosted from the same protocol and -// domain suffix can execute cross-origin JavaScript if both pages set the -// document.domain value to the same domain suffix. For example, -// scheme://foo.example.com and scheme://bar.example.com can communicate using -// JavaScript if both domains set document.domain="example.com". -// -// This method is used to allow access to origins that would otherwise violate -// the same-origin policy. Scripts hosted underneath the fully qualified -// |source_origin| URL (like http://www.example.com) will be allowed access to -// all resources hosted on the specified |target_protocol| and |target_domain|. -// If |target_domain| is non-empty and |allow_target_subdomains| if false only -// exact domain matches will be allowed. If |target_domain| is non-empty and -// |allow_target_subdomains| is true sub-domain matches will be allowed. If -// |target_domain| is empty and |allow_target_subdomains| if true all domains -// and IP addresses will be allowed. -// -// This method cannot be used to bypass the restrictions on local or display -// isolated schemes. See the comments on CefRegisterCustomScheme for more -// information. -// -// This function may be called on any thread. Returns false if |source_origin| -// is invalid or the whitelist cannot be accessed. -/// -/*--cef(optional_param=target_domain)--*/ -bool CefAddCrossOriginWhitelistEntry(const CefString& source_origin, - const CefString& target_protocol, - const CefString& target_domain, - bool allow_target_subdomains); - -/// -// Remove an entry from the cross-origin access whitelist. Returns false if -// |source_origin| is invalid or the whitelist cannot be accessed. -/// -/*--cef(optional_param=target_domain)--*/ -bool CefRemoveCrossOriginWhitelistEntry(const CefString& source_origin, - const CefString& target_protocol, - const CefString& target_domain, - bool allow_target_subdomains); - -/// -// Remove all entries from the cross-origin access whitelist. Returns false if -// the whitelist cannot be accessed. -/// -/*--cef()--*/ -bool CefClearCrossOriginWhitelist(); - -#endif // CEF_INCLUDE_CEF_ORIGIN_WHITELIST_H_ diff --git a/cefpython/cef1/include/cef_permission_handler.h b/cefpython/cef1/include/cef_permission_handler.h deleted file mode 100644 index aea8e46bb..000000000 --- a/cefpython/cef1/include/cef_permission_handler.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_PERMISSION_HANDLER_H_ -#define CEF_INCLUDE_CEF_PERMISSION_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" -#include "include/cef_frame.h" - -/// -// Implement this interface to handle events related to browser permissions. -// The methods of this class will be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefPermissionHandler : public virtual CefBase { - public: - /// - // Called on the UI thread before a script extension is loaded. - // Return false to let the extension load normally. - /// - /*--cef()--*/ - virtual bool OnBeforeScriptExtensionLoad(CefRefPtr browser, - CefRefPtr frame, - const CefString& extensionName) { - return false; - } -}; - -#endif // CEF_INCLUDE_CEF_PERMISSION_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_print_handler.h b/cefpython/cef1/include/cef_print_handler.h deleted file mode 100644 index d47fbf632..000000000 --- a/cefpython/cef1/include/cef_print_handler.h +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_PRINT_HANDLER_H_ -#define CEF_INCLUDE_CEF_PRINT_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" -#include "include/cef_frame.h" - -/// -// Implement this interface to handle events related to printing. The methods of -// this class will be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefPrintHandler : public virtual CefBase { - public: - /// - // Called to allow customization of standard print options before the print - // dialog is displayed. |printOptions| allows specification of paper size, - // orientation and margins. Note that the specified margins may be adjusted if - // they are outside the range supported by the printer. All units are in - // inches. Return false to display the default print options or true to - // display the modified |printOptions|. - /// - /*--cef()--*/ - virtual bool GetPrintOptions(CefRefPtr browser, - CefPrintOptions& printOptions) { return false; } - - /// - // Called to format print headers and footers. |printInfo| contains platform- - // specific information about the printer context. |url| is the URL if the - // currently printing page, |title| is the title of the currently printing - // page, |currentPage| is the current page number and |maxPages| is the total - // number of pages. Six default header locations are provided by the - // implementation: top left, top center, top right, bottom left, bottom center - // and bottom right. To use one of these default locations just assign a - // string to the appropriate variable. To draw the header and footer yourself - // return true. Otherwise, populate the approprate variables and return false. - /// - /*--cef()--*/ - virtual bool GetPrintHeaderFooter(CefRefPtr browser, - CefRefPtr frame, - const CefPrintInfo& printInfo, - const CefString& url, - const CefString& title, - int currentPage, - int maxPages, - CefString& topLeft, - CefString& topCenter, - CefString& topRight, - CefString& bottomLeft, - CefString& bottomCenter, - CefString& bottomRight) { return false; } -}; - -#endif // CEF_INCLUDE_CEF_PRINT_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_proxy_handler.h b/cefpython/cef1/include/cef_proxy_handler.h deleted file mode 100644 index d40c67d7c..000000000 --- a/cefpython/cef1/include/cef_proxy_handler.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_PROXY_HANDLER_H_ -#define CEF_INCLUDE_CEF_PROXY_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" - -/// -// Implement this interface to handle proxy resolution events. -/// -/*--cef(source=client)--*/ -class CefProxyHandler : public virtual CefBase { - public: - /// - // Called to retrieve proxy information for the specified |url|. - /// - /*--cef()--*/ - virtual void GetProxyForUrl(const CefString& url, - CefProxyInfo& proxy_info) {} -}; - -#endif // CEF_INCLUDE_CEF_PROXY_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_render_handler.h b/cefpython/cef1/include/cef_render_handler.h deleted file mode 100644 index 643fbbf56..000000000 --- a/cefpython/cef1/include/cef_render_handler.h +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_RENDER_HANDLER_H_ -#define CEF_INCLUDE_CEF_RENDER_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" -#include - -/// -// Implement this interface to handle events when window rendering is disabled. -// The methods of this class will be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefRenderHandler : public virtual CefBase { - public: - typedef cef_paint_element_type_t PaintElementType; - typedef std::vector RectList; - - /// - // Called to retrieve the view rectangle which is relative to screen - // coordinates. Return true if the rectangle was provided. - /// - /*--cef()--*/ - virtual bool GetViewRect(CefRefPtr browser, - CefRect& rect) { return false; } - - /// - // Called to retrieve the simulated screen rectangle. Return true if the - // rectangle was provided. - /// - /*--cef()--*/ - virtual bool GetScreenRect(CefRefPtr browser, - CefRect& rect) { return false; } - - /// - // Called to retrieve the translation from view coordinates to actual screen - // coordinates. Return true if the screen coordinates were provided. - /// - /*--cef()--*/ - virtual bool GetScreenPoint(CefRefPtr browser, - int viewX, - int viewY, - int& screenX, - int& screenY) { return false; } - - /// - // Called when the browser wants to show or hide the popup widget. The popup - // should be shown if |show| is true and hidden if |show| is false. - /// - /*--cef()--*/ - virtual void OnPopupShow(CefRefPtr browser, - bool show) {} - - /// - // Called when the browser wants to move or resize the popup widget. |rect| - // contains the new location and size. - /// - /*--cef()--*/ - virtual void OnPopupSize(CefRefPtr browser, - const CefRect& rect) {} - - /// - // Called when an element should be painted. |type| indicates whether the - // element is the view or the popup widget. |buffer| contains the pixel data - // for the whole image. |dirtyRects| contains the set of rectangles that need - // to be repainted. On Windows |buffer| will be width*height*4 bytes in size - // and represents a BGRA image with an upper-left origin. The - // CefBrowserSettings.animation_frame_rate value controls the rate at which - // this method is called. - /// - /*--cef()--*/ - virtual void OnPaint(CefRefPtr browser, - PaintElementType type, - const RectList& dirtyRects, - const void* buffer) {} - - /// - // Called when the browser window's cursor has changed. - /// - /*--cef()--*/ - virtual void OnCursorChange(CefRefPtr browser, - CefCursorHandle cursor) {} -}; - -#endif // CEF_INCLUDE_CEF_RENDER_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_request.h b/cefpython/cef1/include/cef_request.h deleted file mode 100644 index 95ade79b1..000000000 --- a/cefpython/cef1/include/cef_request.h +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_REQUEST_H_ -#define CEF_INCLUDE_CEF_REQUEST_H_ -#pragma once - -#include "include/cef_base.h" -#include -#include - -class CefPostData; -class CefPostDataElement; - -/// -// Class used to represent a web request. The methods of this class may be -// called on any thread. -/// -/*--cef(source=library)--*/ -class CefRequest : public virtual CefBase { - public: - typedef std::multimap HeaderMap; - typedef cef_weburlrequest_flags_t RequestFlags; - - /// - // Create a new CefRequest object. - /// - /*--cef()--*/ - static CefRefPtr CreateRequest(); - - /// - // Get the fully qualified URL. - /// - /*--cef()--*/ - virtual CefString GetURL() =0; - /// - // Set the fully qualified URL. - /// - /*--cef()--*/ - virtual void SetURL(const CefString& url) =0; - - /// - // Get the request method type. The value will default to POST if post data - // is provided and GET otherwise. - /// - /*--cef()--*/ - virtual CefString GetMethod() =0; - /// - // Set the request method type. - /// - /*--cef()--*/ - virtual void SetMethod(const CefString& method) =0; - - /// - // Get the post data. - /// - /*--cef()--*/ - virtual CefRefPtr GetPostData() =0; - /// - // Set the post data. - /// - /*--cef()--*/ - virtual void SetPostData(CefRefPtr postData) =0; - - /// - // Get the header values. - /// - /*--cef()--*/ - virtual void GetHeaderMap(HeaderMap& headerMap) =0; - /// - // Set the header values. - /// - /*--cef()--*/ - virtual void SetHeaderMap(const HeaderMap& headerMap) =0; - - /// - // Set all values at one time. - /// - /*--cef(optional_param=postData)--*/ - virtual void Set(const CefString& url, - const CefString& method, - CefRefPtr postData, - const HeaderMap& headerMap) =0; - - /// - // Get the flags used in combination with CefWebURLRequest. - /// - /*--cef(default_retval=WUR_FLAG_NONE)--*/ - virtual RequestFlags GetFlags() =0; - /// - // Set the flags used in combination with CefWebURLRequest. - /// - /*--cef()--*/ - virtual void SetFlags(RequestFlags flags) =0; - - /// - // Set the URL to the first party for cookies used in combination with - // CefWebURLRequest. - /// - /*--cef()--*/ - virtual CefString GetFirstPartyForCookies() =0; - /// - // Get the URL to the first party for cookies used in combination with - // CefWebURLRequest. - /// - /*--cef()--*/ - virtual void SetFirstPartyForCookies(const CefString& url) =0; -}; - - -/// -// Class used to represent post data for a web request. The methods of this -// class may be called on any thread. -/// -/*--cef(source=library)--*/ -class CefPostData : public virtual CefBase { - public: - typedef std::vector > ElementVector; - - /// - // Create a new CefPostData object. - /// - /*--cef()--*/ - static CefRefPtr CreatePostData(); - - /// - // Returns the number of existing post data elements. - /// - /*--cef()--*/ - virtual size_t GetElementCount() =0; - - /// - // Retrieve the post data elements. - /// - /*--cef(count_func=elements:GetElementCount)--*/ - virtual void GetElements(ElementVector& elements) =0; - - /// - // Remove the specified post data element. Returns true if the removal - // succeeds. - /// - /*--cef()--*/ - virtual bool RemoveElement(CefRefPtr element) =0; - - /// - // Add the specified post data element. Returns true if the add succeeds. - /// - /*--cef()--*/ - virtual bool AddElement(CefRefPtr element) =0; - - /// - // Remove all existing post data elements. - /// - /*--cef()--*/ - virtual void RemoveElements() =0; -}; - - -/// -// Class used to represent a single element in the request post data. The -// methods of this class may be called on any thread. -/// -/*--cef(source=library)--*/ -class CefPostDataElement : public virtual CefBase { - public: - /// - // Post data elements may represent either bytes or files. - /// - typedef cef_postdataelement_type_t Type; - - /// - // Create a new CefPostDataElement object. - /// - /*--cef()--*/ - static CefRefPtr CreatePostDataElement(); - - /// - // Remove all contents from the post data element. - /// - /*--cef()--*/ - virtual void SetToEmpty() =0; - - /// - // The post data element will represent a file. - /// - /*--cef()--*/ - virtual void SetToFile(const CefString& fileName) =0; - - /// - // The post data element will represent bytes. The bytes passed - // in will be copied. - /// - /*--cef()--*/ - virtual void SetToBytes(size_t size, const void* bytes) =0; - - /// - // Return the type of this post data element. - /// - /*--cef(default_retval=PDE_TYPE_EMPTY)--*/ - virtual Type GetType() =0; - - /// - // Return the file name. - /// - /*--cef()--*/ - virtual CefString GetFile() =0; - - /// - // Return the number of bytes. - /// - /*--cef()--*/ - virtual size_t GetBytesCount() =0; - - /// - // Read up to |size| bytes into |bytes| and return the number of bytes - // actually read. - /// - /*--cef()--*/ - virtual size_t GetBytes(size_t size, void* bytes) =0; -}; - -#endif // CEF_INCLUDE_CEF_REQUEST_H_ diff --git a/cefpython/cef1/include/cef_request_handler.h b/cefpython/cef1/include/cef_request_handler.h deleted file mode 100644 index a9c7f1d66..000000000 --- a/cefpython/cef1/include/cef_request_handler.h +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_REQUEST_HANDLER_H_ -#define CEF_INCLUDE_CEF_REQUEST_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" -#include "include/cef_cookie.h" -#include "include/cef_download_handler.h" -#include "include/cef_frame.h" -#include "include/cef_content_filter.h" -#include "include/cef_response.h" -#include "include/cef_request.h" -#include "include/cef_stream.h" - -/// -// Implement this interface to handle events related to browser requests. The -// methods of this class will be called on the thread indicated. -/// -/*--cef(source=client)--*/ -class CefRequestHandler : public virtual CefBase { - public: - typedef cef_handler_navtype_t NavType; - - /// - // Called on the UI thread before browser navigation. Return true to cancel - // the navigation or false to allow the navigation to proceed. - /// - /*--cef()--*/ - virtual bool OnBeforeBrowse(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr request, - NavType navType, - bool isRedirect) { return false; } - - /// - // Called on the IO thread before a resource is loaded. To allow the resource - // to load normally return false. To redirect the resource to a new url - // populate the |redirectUrl| value and return false. To specify data for the - // resource return a CefStream object in |resourceStream|, use the |response| - // object to set mime type, HTTP status code and optional header values, and - // return false. To cancel loading of the resource return true. Any - // modifications to |request| will be observed. If the URL in |request| is - // changed and |redirectUrl| is also set, the URL in |request| will be used. - /// - /*--cef()--*/ - virtual bool OnBeforeResourceLoad(CefRefPtr browser, - CefRefPtr request, - CefString& redirectUrl, - CefRefPtr& resourceStream, - CefRefPtr response, - int loadFlags) { return false; } - - /// - // Called on the IO thread when a resource load is redirected. The |old_url| - // parameter will contain the old URL. The |new_url| parameter will contain - // the new URL and can be changed if desired. - /// - /*--cef()--*/ - virtual void OnResourceRedirect(CefRefPtr browser, - const CefString& old_url, - CefString& new_url) {} - - /// - // Called on the UI thread after a response to the resource request is - // received. Set |filter| if response content needs to be monitored and/or - // modified as it arrives. - /// - /*--cef()--*/ - virtual void OnResourceResponse(CefRefPtr browser, - const CefString& url, - CefRefPtr response, - CefRefPtr& filter) {} - - /// - // Called on the IO thread to handle requests for URLs with an unknown - // protocol component. Return true to indicate that the request should - // succeed because it was handled externally. Set |allowOSExecution| to true - // and return false to attempt execution via the registered OS protocol - // handler, if any. If false is returned and either |allow_os_execution| - // is false or OS protocol handler execution fails then the request will fail - // with an error condition. - // SECURITY WARNING: YOU SHOULD USE THIS METHOD TO ENFORCE RESTRICTIONS BASED - // ON SCHEME, HOST OR OTHER URL ANALYSIS BEFORE ALLOWING OS EXECUTION. - /// - /*--cef()--*/ - virtual bool OnProtocolExecution(CefRefPtr browser, - const CefString& url, - bool& allowOSExecution) { return false; } - - /// - // Called on the UI thread when a server indicates via the - // 'Content-Disposition' header that a response represents a file to download. - // |mimeType| is the mime type for the download, |fileName| is the suggested - // target file name and |contentLength| is either the value of the - // 'Content-Size' header or -1 if no size was provided. Set |handler| to the - // CefDownloadHandler instance that will recieve the file contents. Return - // true to download the file or false to cancel the file download. - /// - /*--cef(optional_param=mimeType)--*/ - virtual bool GetDownloadHandler(CefRefPtr browser, - const CefString& mimeType, - const CefString& fileName, - int64 contentLength, - CefRefPtr& handler) - { return false; } - - /// - // Called on the IO thread when the browser needs credentials from the user. - // |isProxy| indicates whether the host is a proxy server. |host| contains the - // hostname and port number. Set |username| and |password| and return - // true to handle the request. Return false to cancel the request. - /// - /*--cef(optional_param=realm)--*/ - virtual bool GetAuthCredentials(CefRefPtr browser, - bool isProxy, - const CefString& host, - int port, - const CefString& realm, - const CefString& scheme, - CefString& username, - CefString& password) { return false; } - - /// - // Called on the IO thread to retrieve the cookie manager. |main_url| is the - // URL of the top-level frame. Cookies managers can be unique per browser or - // shared across multiple browsers. The global cookie manager will be used if - // this method returns NULL. - /// - /*--cef()--*/ - virtual CefRefPtr GetCookieManager( - CefRefPtr browser, - const CefString& main_url) { return NULL; } -}; - -#endif // CEF_INCLUDE_CEF_REQUEST_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_resource_bundle_handler.h b/cefpython/cef1/include/cef_resource_bundle_handler.h deleted file mode 100644 index e7a37d1b5..000000000 --- a/cefpython/cef1/include/cef_resource_bundle_handler.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_RESOURCE_BUNDLE_HANDLER_H_ -#define CEF_INCLUDE_CEF_RESOURCE_BUNDLE_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" - -/// -// Class used to implement a custom resource bundle interface. The methods of -// this class may be called on multiple threads. -/// -/*--cef(source=client)--*/ -class CefResourceBundleHandler : public virtual CefBase { - public: - /// - // Called to retrieve a localized translation for the string specified by - // |message_id|. To provide the translation set |string| to the translation - // string and return true. To use the default translation return false. - // - // WARNING: Be cautious when implementing this method. ID values are auto- - // generated when CEF is built and may change between versions. Existing ID - // values can be discovered by searching for *_strings.h in the - // "obj/global_intermediate" build output directory. - /// - /*--cef()--*/ - virtual bool GetLocalizedString(int message_id, - CefString& string) =0; - - /// - // Called to retrieve data for the resource specified by |resource_id|. To - // provide the resource data set |data| and |data_size| to the data pointer - // and size respectively and return true. To use the default resource data - // return false. The resource data will not be copied and must remain resident - // in memory. - // - // WARNING: Be cautious when implementing this method. ID values are auto- - // generated when CEF is built and may change between versions. Existing ID - // values can be discovered by searching for *_resources.h in the - // "obj/global_intermediate" build output directory. - /// - /*--cef()--*/ - virtual bool GetDataResource(int resource_id, - void*& data, - size_t& data_size) =0; -}; - -#endif // CEF_INCLUDE_CEF_RESOURCE_BUNDLE_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_response.h b/cefpython/cef1/include/cef_response.h deleted file mode 100644 index 5448cd71c..000000000 --- a/cefpython/cef1/include/cef_response.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_RESPONSE_H_ -#define CEF_INCLUDE_CEF_RESPONSE_H_ -#pragma once - -#include "include/cef_base.h" -#include - -/// -// Class used to represent a web response. The methods of this class may be -// called on any thread. -/// -/*--cef(source=library)--*/ -class CefResponse : public virtual CefBase { - public: - typedef std::multimap HeaderMap; - - /// - // Get the response status code. - /// - /*--cef()--*/ - virtual int GetStatus() =0; - /// - // Set the response status code. - /// - /*--cef()--*/ - virtual void SetStatus(int status) = 0; - - /// - // Get the response status text. - /// - /*--cef()--*/ - virtual CefString GetStatusText() =0; - /// - // Set the response status text. - /// - /*--cef()--*/ - virtual void SetStatusText(const CefString& statusText) = 0; - - /// - // Get the response mime type. - /// - /*--cef()--*/ - virtual CefString GetMimeType() = 0; - /// - // Set the response mime type. - /// - /*--cef()--*/ - virtual void SetMimeType(const CefString& mimeType) = 0; - - /// - // Get the value for the specified response header field. - /// - /*--cef()--*/ - virtual CefString GetHeader(const CefString& name) =0; - - /// - // Get all response header fields. - /// - /*--cef()--*/ - virtual void GetHeaderMap(HeaderMap& headerMap) =0; - /// - // Set all response header fields. - /// - /*--cef()--*/ - virtual void SetHeaderMap(const HeaderMap& headerMap) =0; -}; - -#endif // CEF_INCLUDE_CEF_RESPONSE_H_ diff --git a/cefpython/cef1/include/cef_runnable.h b/cefpython/cef1/include/cef_runnable.h deleted file mode 100644 index 826ddaa46..000000000 --- a/cefpython/cef1/include/cef_runnable.h +++ /dev/null @@ -1,346 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. Portions Copyright (c) -// 2006-2011 Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The contents of this file are a modified extract of base/task.h - -#ifndef CEF_INCLUDE_CEF_RUNNABLE_H_ -#define CEF_INCLUDE_CEF_RUNNABLE_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_task.h" -#ifdef BUILDING_CEF_SHARED -#include "base/tuple.h" -#else -#include "internal/cef_tuple.h" -#endif - -// CefRunnableMethodTraits ----------------------------------------------------- -// -// This traits-class is used by CefRunnableMethod to manage the lifetime of the -// callee object. By default, it is assumed that the callee supports AddRef -// and Release methods. A particular class can specialize this template to -// define other lifetime management. For example, if the callee is known to -// live longer than the CefRunnableMethod object, then a CefRunnableMethodTraits -// struct could be defined with empty RetainCallee and ReleaseCallee methods. -// -// The DISABLE_RUNNABLE_METHOD_REFCOUNT macro is provided as a convenient way -// for declaring a CefRunnableMethodTraits that disables refcounting. - -template -struct CefRunnableMethodTraits { - CefRunnableMethodTraits() { - } - - ~CefRunnableMethodTraits() { - } - - void RetainCallee(T* obj) { -#ifndef NDEBUG - // Catch NewCefRunnableMethod being called in an object's constructor. - // This isn't safe since the method can be invoked before the constructor - // completes, causing the object to be deleted. - obj->AddRef(); - obj->Release(); -#endif - obj->AddRef(); - } - - void ReleaseCallee(T* obj) { - obj->Release(); - } -}; - -// Convenience macro for declaring a CefRunnableMethodTraits that disables -// refcounting of a class. This is useful if you know that the callee -// will outlive the CefRunnableMethod object and thus do not need the ref -// counts. -// -// The invocation of DISABLE_RUNNABLE_METHOD_REFCOUNT should be done at the -// global namespace scope. Example: -// -// namespace foo { -// class Bar { -// ... -// }; -// } // namespace foo -// -// DISABLE_RUNNABLE_METHOD_REFCOUNT(foo::Bar); -// -// This is different from DISALLOW_COPY_AND_ASSIGN which is declared inside the -// class. -#define DISABLE_RUNNABLE_METHOD_REFCOUNT(TypeName) \ - template <> \ - struct CefRunnableMethodTraits { \ - void RetainCallee(TypeName* manager) {} \ - void ReleaseCallee(TypeName* manager) {} \ - } - -// CefRunnableMethod and CefRunnableFunction ---------------------------------- -// -// CefRunnable methods are a type of task that call a function on an object -// when they are run. We implement both an object and a set of -// NewCefRunnableMethod and NewCefRunnableFunction functions for convenience. -// These functions are overloaded and will infer the template types, -// simplifying calling code. -// -// The template definitions all use the following names: -// T - the class type of the object you're supplying -// this is not needed for the Static version of the call -// Method/Function - the signature of a pointer to the method or function you -// want to call -// Param - the parameter(s) to the method, possibly packed as a Tuple -// A - the first parameter (if any) to the method -// B - the second parameter (if any) to the method -// -// Put these all together and you get an object that can call a method whose -// signature is: -// R T::MyFunction([A[, B]]) -// -// Usage: -// CefPostTask(TID_UI, NewCefRunnableMethod(object, &Object::method[, a[, b]]) -// CefPostTask(TID_UI, NewCefRunnableFunction(&function[, a[, b]]) - -// CefRunnableMethod and NewCefRunnableMethod implementation ------------------ - -template -class CefRunnableMethod : public CefTask { - public: - CefRunnableMethod(T* obj, Method meth, const Params& params) - : obj_(obj), meth_(meth), params_(params) { - traits_.RetainCallee(obj_); - } - - ~CefRunnableMethod() { - T* obj = obj_; - obj_ = NULL; - if (obj) - traits_.ReleaseCallee(obj); - } - - virtual void Execute(CefThreadId threadId) { - if (obj_) - DispatchToMethod(obj_, meth_, params_); - } - - private: - T* obj_; - Method meth_; - Params params_; - CefRunnableMethodTraits traits_; - - IMPLEMENT_REFCOUNTING(CefRunnableMethod); -}; - -template -inline CefRefPtr NewCefRunnableMethod(T* object, Method method) { - return new CefRunnableMethod(object, method, MakeTuple()); -} - -template -inline CefRefPtr NewCefRunnableMethod(T* object, Method method, - const A& a) { - return new CefRunnableMethod >(object, - method, - MakeTuple(a)); -} - -template -inline CefRefPtr NewCefRunnableMethod(T* object, Method method, - const A& a, const B& b) { - return new CefRunnableMethod >(object, method, - MakeTuple(a, b)); -} - -template -inline CefRefPtr NewCefRunnableMethod(T* object, Method method, - const A& a, const B& b, - const C& c) { - return new CefRunnableMethod >(object, method, - MakeTuple(a, b, - c)); -} - -template -inline CefRefPtr NewCefRunnableMethod(T* object, Method method, - const A& a, const B& b, - const C& c, const D& d) { - return new CefRunnableMethod >(object, method, - MakeTuple(a, b, - c, - d)); -} - -template -inline CefRefPtr NewCefRunnableMethod(T* object, Method method, - const A& a, const B& b, - const C& c, const D& d, - const E& e) { - return new CefRunnableMethod >(object, - method, - MakeTuple(a, b, c, d, - e)); -} - -template -inline CefRefPtr NewCefRunnableMethod(T* object, Method method, - const A& a, const B& b, - const C& c, const D& d, - const E& e, const F& f) { - return new CefRunnableMethod >(object, - method, - MakeTuple(a, b, c, d, - e, f)); -} - -template -inline CefRefPtr NewCefRunnableMethod(T* object, Method method, - const A& a, const B& b, - const C& c, const D& d, - const E& e, const F& f, - const G& g) { - return new CefRunnableMethod >(object, - method, - MakeTuple(a, b, c, - d, e, f, - g)); -} - -// CefRunnableFunction and NewCefRunnableFunction implementation -------------- - -template -class CefRunnableFunction : public CefTask { - public: - CefRunnableFunction(Function function, const Params& params) - : function_(function), params_(params) { - } - - ~CefRunnableFunction() { - } - - virtual void Execute(CefThreadId threadId) { - if (function_) - DispatchToFunction(function_, params_); - } - - private: - Function function_; - Params params_; - - IMPLEMENT_REFCOUNTING(CefRunnableFunction); -}; - -template -inline CefRefPtr NewCefRunnableFunction(Function function) { - return new CefRunnableFunction(function, MakeTuple()); -} - -template -inline CefRefPtr NewCefRunnableFunction(Function function, - const A& a) { - return new CefRunnableFunction >(function, MakeTuple(a)); -} - -template -inline CefRefPtr NewCefRunnableFunction(Function function, - const A& a, const B& b) { - return new CefRunnableFunction >(function, - MakeTuple(a, b)); -} - -template -inline CefRefPtr NewCefRunnableFunction(Function function, - const A& a, const B& b, - const C& c) { - return new CefRunnableFunction >(function, - MakeTuple(a, b, - c)); -} - -template -inline CefRefPtr NewCefRunnableFunction(Function function, - const A& a, const B& b, - const C& c, const D& d) { - return new CefRunnableFunction >(function, - MakeTuple(a, b, - c, - d)); -} - -template -inline CefRefPtr NewCefRunnableFunction(Function function, - const A& a, const B& b, - const C& c, const D& d, - const E& e) { - return new CefRunnableFunction >(function, - MakeTuple(a, b, c, d, e)); -} - -template -inline CefRefPtr NewCefRunnableFunction(Function function, - const A& a, const B& b, - const C& c, const D& d, - const E& e, const F& f) { - return new CefRunnableFunction >(function, - MakeTuple(a, b, c, d, e, f)); -} - -template -inline CefRefPtr NewCefRunnableFunction(Function function, - const A& a, const B& b, - const C& c, const D& d, - const E& e, const F& f, - const G& g) { - return new CefRunnableFunction >( - function, MakeTuple(a, b, c, d, e, f, g)); -} - -template -inline CefRefPtr NewCefRunnableFunction(Function function, - const A& a, const B& b, - const C& c, const D& d, - const E& e, const F& f, - const G& g, const H& h) { - return new CefRunnableFunction >( - function, MakeTuple(a, b, c, d, e, f, g, h)); -} - -#endif // CEF_INCLUDE_CEF_RUNNABLE_H_ diff --git a/cefpython/cef1/include/cef_scheme.h b/cefpython/cef1/include/cef_scheme.h deleted file mode 100644 index 97786590b..000000000 --- a/cefpython/cef1/include/cef_scheme.h +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_SCHEME_H_ -#define CEF_INCLUDE_CEF_SCHEME_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" -#include "include/cef_response.h" -#include "include/cef_request.h" - -class CefSchemeHandler; -class CefSchemeHandlerFactory; - -/// -// Register a scheme handler factory for the specified |scheme_name| and -// optional |domain_name|. An empty |domain_name| value for a standard scheme -// will cause the factory to match all domain names. The |domain_name| value -// will be ignored for non-standard schemes. If |scheme_name| is a built-in -// scheme and no handler is returned by |factory| then the built-in scheme -// handler factory will be called. If |scheme_name| is a custom scheme the -// CefRegisterCustomScheme() function should be called for that scheme. -// This function may be called multiple times to change or remove the factory -// that matches the specified |scheme_name| and optional |domain_name|. -// Returns false if an error occurs. This function may be called on any thread. -/// -/*--cef(optional_param=domain_name,optional_param=factory)--*/ -bool CefRegisterSchemeHandlerFactory(const CefString& scheme_name, - const CefString& domain_name, - CefRefPtr factory); - -/// -// Clear all registered scheme handler factories. Returns false on error. This -// function may be called on any thread. -/// -/*--cef()--*/ -bool CefClearSchemeHandlerFactories(); - - -/// -// Class that manages custom scheme registrations. -/// -/*--cef(source=library)--*/ -class CefSchemeRegistrar : public virtual CefBase { - public: - /// - // Register a custom scheme. This method should not be called for the built-in - // HTTP, HTTPS, FILE, FTP, ABOUT and DATA schemes. - // - // If |is_standard| is true the scheme will be treated as a standard scheme. - // Standard schemes are subject to URL canonicalization and parsing rules as - // defined in the Common Internet Scheme Syntax RFC 1738 Section 3.1 available - // at http://www.ietf.org/rfc/rfc1738.txt - // - // In particular, the syntax for standard scheme URLs must be of the form: - //
-  //  [scheme]://[username]:[password]@[host]:[port]/[url-path]
-  // 
- // Standard scheme URLs must have a host component that is a fully qualified - // domain name as defined in Section 3.5 of RFC 1034 [13] and Section 2.1 of - // RFC 1123. These URLs will be canonicalized to "scheme://host/path" in the - // simplest case and "scheme://username:password@host:port/path" in the most - // explicit case. For example, "scheme:host/path" and "scheme:///host/path" - // will both be canonicalized to "scheme://host/path". The origin of a - // standard scheme URL is the combination of scheme, host and port (i.e., - // "scheme://host:port" in the most explicit case). - // - // For non-standard scheme URLs only the "scheme:" component is parsed and - // canonicalized. The remainder of the URL will be passed to the handler - // as-is. For example, "scheme:///some%20text" will remain the same. - // Non-standard scheme URLs cannot be used as a target for form submission. - // - // If |is_local| is true the scheme will be treated as local (i.e., with the - // same security rules as those applied to "file" URLs). Normal pages cannot - // link to or access local URLs. Also, by default, local URLs can only perform - // XMLHttpRequest calls to the same URL (origin + path) that originated the - // request. To allow XMLHttpRequest calls from a local URL to other URLs with - // the same origin set the CefSettings.file_access_from_file_urls_allowed - // value to true. To allow XMLHttpRequest calls from a local URL to all - // origins set the CefSettings.universal_access_from_file_urls_allowed value - // to true. - // - // If |is_display_isolated| is true the scheme will be treated as display- - // isolated. This means that pages cannot display these URLs unless they are - // from the same scheme. For example, pages in another origin cannot create - // iframes or hyperlinks to URLs with this scheme. - // - // This function may be called on any thread. It should only be called once - // per unique |scheme_name| value. If |scheme_name| is already registered or - // if an error occurs this method will return false. - /// - /*--cef()--*/ - virtual bool AddCustomScheme(const CefString& scheme_name, - bool is_standard, - bool is_local, - bool is_display_isolated) =0; -}; - - -/// -// Class that creates CefSchemeHandler instances. The methods of this class will -// always be called on the IO thread. -/// -/*--cef(source=client)--*/ -class CefSchemeHandlerFactory : public virtual CefBase { - public: - /// - // Return a new scheme handler instance to handle the request. |browser| will - // be the browser window that initiated the request. If the request was - // initiated using the CefWebURLRequest API |browser| will be NULL. The - // |request| object passed to this method will not contain cookie data. - /// - /*--cef(optional_param=browser)--*/ - virtual CefRefPtr Create(CefRefPtr browser, - const CefString& scheme_name, - CefRefPtr request) =0; -}; - -/// -// Class used to facilitate asynchronous responses to custom scheme handler -// requests. The methods of this class may be called on any thread. -/// -/*--cef(source=library)--*/ -class CefSchemeHandlerCallback : public virtual CefBase { - public: - /// - // Notify that header information is now available for retrieval. - /// - /*--cef()--*/ - virtual void HeadersAvailable() =0; - - /// - // Notify that response data is now available for reading. - /// - /*--cef()--*/ - virtual void BytesAvailable() =0; - - /// - // Cancel processing of the request. - /// - /*--cef()--*/ - virtual void Cancel() =0; -}; - -/// -// Class used to implement a custom scheme handler interface. The methods of -// this class will always be called on the IO thread. -/// -/*--cef(source=client)--*/ -class CefSchemeHandler : public virtual CefBase { - public: - /// - // Begin processing the request. To handle the request return true and call - // HeadersAvailable() once the response header information is available - // (HeadersAvailable() can also be called from inside this method if header - // information is available immediately). To cancel the request return false. - /// - /*--cef()--*/ - virtual bool ProcessRequest(CefRefPtr request, - CefRefPtr callback) =0; - - /// - // Retrieve response header information. If the response length is not known - // set |response_length| to -1 and ReadResponse() will be called until it - // returns false. If the response length is known set |response_length| - // to a positive value and ReadResponse() will be called until it returns - // false or the specified number of bytes have been read. Use the |response| - // object to set the mime type, http status code and other optional header - // values. To redirect the request to a new URL set |redirectUrl| to the new - // URL. - /// - /*--cef()--*/ - virtual void GetResponseHeaders(CefRefPtr response, - int64& response_length, - CefString& redirectUrl) =0; - - /// - // Read response data. If data is available immediately copy up to - // |bytes_to_read| bytes into |data_out|, set |bytes_read| to the number of - // bytes copied, and return true. To read the data at a later time set - // |bytes_read| to 0, return true and call BytesAvailable() when the data is - // available. To indicate response completion return false. - /// - /*--cef()--*/ - virtual bool ReadResponse(void* data_out, - int bytes_to_read, - int& bytes_read, - CefRefPtr callback) =0; - - /// - // Request processing has been canceled. - /// - /*--cef()--*/ - virtual void Cancel() =0; -}; - -#endif // CEF_INCLUDE_CEF_SCHEME_H_ diff --git a/cefpython/cef1/include/cef_stream.h b/cefpython/cef1/include/cef_stream.h deleted file mode 100644 index 8daae1708..000000000 --- a/cefpython/cef1/include/cef_stream.h +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_STREAM_H_ -#define CEF_INCLUDE_CEF_STREAM_H_ - -#include "include/cef_base.h" - -/// -// Interface the client can implement to provide a custom stream reader. The -// methods of this class may be called on any thread. -/// -/*--cef(source=client)--*/ -class CefReadHandler : public virtual CefBase { - public: - /// - // Read raw binary data. - /// - /*--cef()--*/ - virtual size_t Read(void* ptr, size_t size, size_t n) =0; - - /// - // Seek to the specified offset position. |whence| may be any one of - // SEEK_CUR, SEEK_END or SEEK_SET. Return zero on success and non-zero on - // failure. - /// - /*--cef()--*/ - virtual int Seek(int64 offset, int whence) =0; - - /// - // Return the current offset position. - /// - /*--cef()--*/ - virtual int64 Tell() =0; - - /// - // Return non-zero if at end of file. - /// - /*--cef()--*/ - virtual int Eof() =0; -}; - - -/// -// Class used to read data from a stream. The methods of this class may be -// called on any thread. -/// -/*--cef(source=library)--*/ -class CefStreamReader : public virtual CefBase { - public: - /// - // Create a new CefStreamReader object from a file. - /// - /*--cef()--*/ - static CefRefPtr CreateForFile(const CefString& fileName); - /// - // Create a new CefStreamReader object from data. - /// - /*--cef()--*/ - static CefRefPtr CreateForData(void* data, size_t size); - /// - // Create a new CefStreamReader object from a custom handler. - /// - /*--cef()--*/ - static CefRefPtr CreateForHandler( - CefRefPtr handler); - - /// - // Read raw binary data. - /// - /*--cef()--*/ - virtual size_t Read(void* ptr, size_t size, size_t n) =0; - - /// - // Seek to the specified offset position. |whence| may be any one of - // SEEK_CUR, SEEK_END or SEEK_SET. Returns zero on success and non-zero on - // failure. - /// - /*--cef()--*/ - virtual int Seek(int64 offset, int whence) =0; - - /// - // Return the current offset position. - /// - /*--cef()--*/ - virtual int64 Tell() =0; - - /// - // Return non-zero if at end of file. - /// - /*--cef()--*/ - virtual int Eof() =0; -}; - - -/// -// Interface the client can implement to provide a custom stream writer. The -// methods of this class may be called on any thread. -/// -/*--cef(source=client)--*/ -class CefWriteHandler : public virtual CefBase { - public: - /// - // Write raw binary data. - /// - /*--cef()--*/ - virtual size_t Write(const void* ptr, size_t size, size_t n) =0; - - /// - // Seek to the specified offset position. |whence| may be any one of - // SEEK_CUR, SEEK_END or SEEK_SET. Return zero on success and non-zero on - // failure. - /// - /*--cef()--*/ - virtual int Seek(int64 offset, int whence) =0; - - /// - // Return the current offset position. - /// - /*--cef()--*/ - virtual int64 Tell() =0; - - /// - // Flush the stream. - /// - /*--cef()--*/ - virtual int Flush() =0; -}; - - -/// -// Class used to write data to a stream. The methods of this class may be called -// on any thread. -/// -/*--cef(source=library)--*/ -class CefStreamWriter : public virtual CefBase { - public: - /// - // Create a new CefStreamWriter object for a file. - /// - /*--cef()--*/ - static CefRefPtr CreateForFile(const CefString& fileName); - /// - // Create a new CefStreamWriter object for a custom handler. - /// - /*--cef()--*/ - static CefRefPtr CreateForHandler( - CefRefPtr handler); - - /// - // Write raw binary data. - /// - /*--cef()--*/ - virtual size_t Write(const void* ptr, size_t size, size_t n) =0; - - /// - // Seek to the specified offset position. |whence| may be any one of - // SEEK_CUR, SEEK_END or SEEK_SET. Returns zero on success and non-zero on - // failure. - /// - /*--cef()--*/ - virtual int Seek(int64 offset, int whence) =0; - - /// - // Return the current offset position. - /// - /*--cef()--*/ - virtual int64 Tell() =0; - - /// - // Flush the stream. - /// - /*--cef()--*/ - virtual int Flush() =0; -}; - -#endif // CEF_INCLUDE_CEF_STREAM_H_ diff --git a/cefpython/cef1/include/cef_task.h b/cefpython/cef1/include/cef_task.h deleted file mode 100644 index 86550f6a0..000000000 --- a/cefpython/cef1/include/cef_task.h +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_TASK_H_ -#define CEF_INCLUDE_CEF_TASK_H_ - -#include "include/cef_base.h" - -class CefTask; - -typedef cef_thread_id_t CefThreadId; - -/// -// CEF maintains multiple internal threads that are used for handling different -// types of tasks. The UI thread creates the browser window and is used for all -// interaction with the WebKit rendering engine and V8 JavaScript engine (The -// UI thread will be the same as the main application thread if CefInitialize() -// is called with a CefSettings.multi_threaded_message_loop value of false.) The -// IO thread is used for handling schema and network requests. The FILE thread -// is used for the application cache and other miscellaneous activities. This -// function will return true if called on the specified thread. -/// -/*--cef()--*/ -bool CefCurrentlyOn(CefThreadId threadId); - -/// -// Post a task for execution on the specified thread. This function may be -// called on any thread. -/// -/*--cef()--*/ -bool CefPostTask(CefThreadId threadId, CefRefPtr task); - -/// -// Post a task for delayed execution on the specified thread. This function may -// be called on any thread. -/// -/*--cef()--*/ -bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr task, - int64 delay_ms); - - -/// -// Implement this interface for task execution. The methods of this class may -// be called on any thread. -/// -/*--cef(source=client)--*/ -class CefTask : public virtual CefBase { - public: - /// - // Method that will be executed. |threadId| is the thread executing the call. - /// - /*--cef()--*/ - virtual void Execute(CefThreadId threadId) =0; -}; - -#endif // CEF_INCLUDE_CEF_TASK_H_ diff --git a/cefpython/cef1/include/cef_url.h b/cefpython/cef1/include/cef_url.h deleted file mode 100644 index 6caa1e229..000000000 --- a/cefpython/cef1/include/cef_url.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_URL_H_ -#define CEF_INCLUDE_CEF_URL_H_ -#pragma once - -#include "include/cef_base.h" - -/// -// Parse the specified |url| into its component parts. -// Returns false if the URL is empty or invalid. -/// -/*--cef()--*/ -bool CefParseURL(const CefString& url, - CefURLParts& parts); - -/// -// Creates a URL from the specified |parts|, which must contain a non-empty -// spec or a non-empty host and path (at a minimum), but not both. -// Returns false if |parts| isn't initialized as described. -/// -/*--cef()--*/ -bool CefCreateURL(const CefURLParts& parts, - CefString& url); - -#endif // CEF_INCLUDE_CEF_URL_H_ diff --git a/cefpython/cef1/include/cef_v8.h b/cefpython/cef1/include/cef_v8.h deleted file mode 100644 index 03a16b09f..000000000 --- a/cefpython/cef1/include/cef_v8.h +++ /dev/null @@ -1,851 +0,0 @@ -// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - - -#ifndef CEF_INCLUDE_CEF_V8_H_ -#define CEF_INCLUDE_CEF_V8_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" -#include "include/cef_frame.h" -#include - -class CefV8Exception; -class CefV8Handler; -class CefV8StackFrame; -class CefV8Value; - - -/// -// Register a new V8 extension with the specified JavaScript extension code and -// handler. Functions implemented by the handler are prototyped using the -// keyword 'native'. The calling of a native function is restricted to the scope -// in which the prototype of the native function is defined. This function may -// be called on any thread. -// -// Example JavaScript extension code: -//
-//   // create the 'example' global object if it doesn't already exist.
-//   if (!example)
-//     example = {};
-//   // create the 'example.test' global object if it doesn't already exist.
-//   if (!example.test)
-//     example.test = {};
-//   (function() {
-//     // Define the function 'example.test.myfunction'.
-//     example.test.myfunction = function() {
-//       // Call CefV8Handler::Execute() with the function name 'MyFunction'
-//       // and no arguments.
-//       native function MyFunction();
-//       return MyFunction();
-//     };
-//     // Define the getter function for parameter 'example.test.myparam'.
-//     example.test.__defineGetter__('myparam', function() {
-//       // Call CefV8Handler::Execute() with the function name 'GetMyParam'
-//       // and no arguments.
-//       native function GetMyParam();
-//       return GetMyParam();
-//     });
-//     // Define the setter function for parameter 'example.test.myparam'.
-//     example.test.__defineSetter__('myparam', function(b) {
-//       // Call CefV8Handler::Execute() with the function name 'SetMyParam'
-//       // and a single argument.
-//       native function SetMyParam();
-//       if(b) SetMyParam(b);
-//     });
-//
-//     // Extension definitions can also contain normal JavaScript variables
-//     // and functions.
-//     var myint = 0;
-//     example.test.increment = function() {
-//       myint += 1;
-//       return myint;
-//     };
-//   })();
-// 
-// Example usage in the page: -//
-//   // Call the function.
-//   example.test.myfunction();
-//   // Set the parameter.
-//   example.test.myparam = value;
-//   // Get the parameter.
-//   value = example.test.myparam;
-//   // Call another function.
-//   example.test.increment();
-// 
-/// -/*--cef(optional_param=handler)--*/ -bool CefRegisterExtension(const CefString& extension_name, - const CefString& javascript_code, - CefRefPtr handler); - - -/// -// Class that encapsulates a V8 context handle. The methods of this class may -// only be called on the UI thread. -/// -/*--cef(source=library)--*/ -class CefV8Context : public virtual CefBase { - public: - /// - // Returns the current (top) context object in the V8 context stack. - /// - /*--cef()--*/ - static CefRefPtr GetCurrentContext(); - - /// - // Returns the entered (bottom) context object in the V8 context stack. - /// - /*--cef()--*/ - static CefRefPtr GetEnteredContext(); - - /// - // Returns true if V8 is currently inside a context. - /// - /*--cef()--*/ - static bool InContext(); - - /// - // Returns true if this object is valid. Do not call any other methods if this - // method returns false. - /// - /*--cef()--*/ - virtual bool IsValid() =0; - - /// - // Returns the browser for this context. - /// - /*--cef()--*/ - virtual CefRefPtr GetBrowser() =0; - - /// - // Returns the frame for this context. - /// - /*--cef()--*/ - virtual CefRefPtr GetFrame() =0; - - /// - // Returns the global object for this context. The context must be entered - // before calling this method. - /// - /*--cef()--*/ - virtual CefRefPtr GetGlobal() =0; - - /// - // Enter this context. A context must be explicitly entered before creating a - // V8 Object, Array, Function or Date asynchronously. Exit() must be called - // the same number of times as Enter() before releasing this context. V8 - // objects belong to the context in which they are created. Returns true if - // the scope was entered successfully. - /// - /*--cef()--*/ - virtual bool Enter() =0; - - /// - // Exit this context. Call this method only after calling Enter(). Returns - // true if the scope was exited successfully. - /// - /*--cef()--*/ - virtual bool Exit() =0; - - /// - // Returns true if this object is pointing to the same handle as |that| - // object. - /// - /*--cef()--*/ - virtual bool IsSame(CefRefPtr that) =0; - - /// - // Evaluates the specified JavaScript code using this context's global object. - // On success |retval| will be set to the return value, if any, and the - // function will return true. On failure |exception| will be set to the - // exception, if any, and the function will return false. - /// - /*--cef()--*/ - virtual bool Eval(const CefString& code, - CefRefPtr& retval, - CefRefPtr& exception) =0; -}; - - -typedef std::vector > CefV8ValueList; - -/// -// Interface that should be implemented to handle V8 function calls. The methods -// of this class will always be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefV8Handler : public virtual CefBase { - public: - /// - // Handle execution of the function identified by |name|. |object| is the - // receiver ('this' object) of the function. |arguments| is the list of - // arguments passed to the function. If execution succeeds set |retval| to the - // function return value. If execution fails set |exception| to the exception - // that will be thrown. Return true if execution was handled. - /// - /*--cef()--*/ - virtual bool Execute(const CefString& name, - CefRefPtr object, - const CefV8ValueList& arguments, - CefRefPtr& retval, - CefString& exception) =0; -}; - -/// -// Interface that should be implemented to handle V8 accessor calls. Accessor -// identifiers are registered by calling CefV8Value::SetValue(). The methods -// of this class will always be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefV8Accessor : public virtual CefBase { - public: - /// - // Handle retrieval the accessor value identified by |name|. |object| is the - // receiver ('this' object) of the accessor. If retrieval succeeds set - // |retval| to the return value. If retrieval fails set |exception| to the - // exception that will be thrown. Return true if accessor retrieval was - // handled. - /// - /*--cef()--*/ - virtual bool Get(const CefString& name, - const CefRefPtr object, - CefRefPtr& retval, - CefString& exception) =0; - - /// - // Handle assignment of the accessor value identified by |name|. |object| is - // the receiver ('this' object) of the accessor. |value| is the new value - // being assigned to the accessor. If assignment fails set |exception| to the - // exception that will be thrown. Return true if accessor assignment was - // handled. - /// - /*--cef()--*/ - virtual bool Set(const CefString& name, - const CefRefPtr object, - const CefRefPtr value, - CefString& exception) =0; -}; - -/// -// Class representing a V8 exception. -/// -/*--cef(source=library)--*/ -class CefV8Exception : public virtual CefBase { - public: - /// - // Returns the exception message. - /// - /*--cef()--*/ - virtual CefString GetMessage() =0; - - /// - // Returns the line of source code that the exception occurred within. - /// - /*--cef()--*/ - virtual CefString GetSourceLine() =0; - - /// - // Returns the resource name for the script from where the function causing - // the error originates. - /// - /*--cef()--*/ - virtual CefString GetScriptResourceName() =0; - - /// - // Returns the 1-based number of the line where the error occurred or 0 if the - // line number is unknown. - /// - /*--cef()--*/ - virtual int GetLineNumber() =0; - - /// - // Returns the index within the script of the first character where the error - // occurred. - /// - /*--cef()--*/ - virtual int GetStartPosition() =0; - - /// - // Returns the index within the script of the last character where the error - // occurred. - /// - /*--cef()--*/ - virtual int GetEndPosition() =0; - - /// - // Returns the index within the line of the first character where the error - // occurred. - /// - /*--cef()--*/ - virtual int GetStartColumn() =0; - - /// - // Returns the index within the line of the last character where the error - // occurred. - /// - /*--cef()--*/ - virtual int GetEndColumn() =0; -}; - -/// -// Class representing a V8 value. The methods of this class may only be called -// on the UI thread. -/// -/*--cef(source=library)--*/ -class CefV8Value : public virtual CefBase { - public: - typedef cef_v8_accesscontrol_t AccessControl; - typedef cef_v8_propertyattribute_t PropertyAttribute; - - /// - // Create a new CefV8Value object of type undefined. - /// - /*--cef()--*/ - static CefRefPtr CreateUndefined(); - - /// - // Create a new CefV8Value object of type null. - /// - /*--cef()--*/ - static CefRefPtr CreateNull(); - - /// - // Create a new CefV8Value object of type bool. - /// - /*--cef()--*/ - static CefRefPtr CreateBool(bool value); - - /// - // Create a new CefV8Value object of type int. - /// - /*--cef()--*/ - static CefRefPtr CreateInt(int32 value); - - /// - // Create a new CefV8Value object of type unsigned int. - /// - /*--cef()--*/ - static CefRefPtr CreateUInt(uint32 value); - - /// - // Create a new CefV8Value object of type double. - /// - /*--cef()--*/ - static CefRefPtr CreateDouble(double value); - - /// - // Create a new CefV8Value object of type Date. This method should only be - // called from within the scope of a CefV8ContextHandler, CefV8Handler or - // CefV8Accessor callback, or in combination with calling Enter() and Exit() - // on a stored CefV8Context reference. - /// - /*--cef()--*/ - static CefRefPtr CreateDate(const CefTime& date); - - /// - // Create a new CefV8Value object of type string. - /// - /*--cef(optional_param=value)--*/ - static CefRefPtr CreateString(const CefString& value); - - /// - // Create a new CefV8Value object of type object with optional accessor. This - // method should only be called from within the scope of a - // CefV8ContextHandler, CefV8Handler or CefV8Accessor callback, or in - // combination with calling Enter() and Exit() on a stored CefV8Context - // reference. - /// - /*--cef(optional_param=accessor)--*/ - static CefRefPtr CreateObject(CefRefPtr accessor); - - /// - // Create a new CefV8Value object of type array with the specified |length|. - // If |length| is negative the returned array will have length 0. This method - // should only be called from within the scope of a CefV8ContextHandler, - // CefV8Handler or CefV8Accessor callback, or in combination with calling - // Enter() and Exit() on a stored CefV8Context reference. - /// - /*--cef()--*/ - static CefRefPtr CreateArray(int length); - - /// - // Create a new CefV8Value object of type function. This method should only be - // called from within the scope of a CefV8ContextHandler, CefV8Handler or - // CefV8Accessor callback, or in combination with calling Enter() and Exit() - // on a stored CefV8Context reference. - /// - /*--cef()--*/ - static CefRefPtr CreateFunction(const CefString& name, - CefRefPtr handler); - - /// - // Returns true if this object is valid. Do not call any other methods if this - // method returns false. - /// - /*--cef()--*/ - virtual bool IsValid() =0; - - /// - // True if the value type is undefined. - /// - /*--cef()--*/ - virtual bool IsUndefined() =0; - - /// - // True if the value type is null. - /// - /*--cef()--*/ - virtual bool IsNull() =0; - - /// - // True if the value type is bool. - /// - /*--cef()--*/ - virtual bool IsBool() =0; - - /// - // True if the value type is int. - /// - /*--cef()--*/ - virtual bool IsInt() =0; - - /// - // True if the value type is unsigned int. - /// - /*--cef()--*/ - virtual bool IsUInt() =0; - - /// - // True if the value type is double. - /// - /*--cef()--*/ - virtual bool IsDouble() =0; - - /// - // True if the value type is Date. - /// - /*--cef()--*/ - virtual bool IsDate() =0; - - /// - // True if the value type is string. - /// - /*--cef()--*/ - virtual bool IsString() =0; - - /// - // True if the value type is object. - /// - /*--cef()--*/ - virtual bool IsObject() =0; - - /// - // True if the value type is array. - /// - /*--cef()--*/ - virtual bool IsArray() =0; - - /// - // True if the value type is function. - /// - /*--cef()--*/ - virtual bool IsFunction() =0; - - /// - // Returns true if this object is pointing to the same handle as |that| - // object. - /// - /*--cef()--*/ - virtual bool IsSame(CefRefPtr that) =0; - - /// - // Return a bool value. The underlying data will be converted to if - // necessary. - /// - /*--cef()--*/ - virtual bool GetBoolValue() =0; - - /// - // Return an int value. The underlying data will be converted to if - // necessary. - /// - /*--cef()--*/ - virtual int32 GetIntValue() =0; - - /// - // Return an unisgned int value. The underlying data will be converted to if - // necessary. - /// - /*--cef()--*/ - virtual uint32 GetUIntValue() =0; - - /// - // Return a double value. The underlying data will be converted to if - // necessary. - /// - /*--cef()--*/ - virtual double GetDoubleValue() =0; - - /// - // Return a Date value. The underlying data will be converted to if - // necessary. - /// - /*--cef()--*/ - virtual CefTime GetDateValue() =0; - - /// - // Return a string value. The underlying data will be converted to if - // necessary. - /// - /*--cef()--*/ - virtual CefString GetStringValue() =0; - - - // OBJECT METHODS - These methods are only available on objects. Arrays and - // functions are also objects. String- and integer-based keys can be used - // interchangably with the framework converting between them as necessary. - - /// - // Returns true if this is a user created object. - /// - /*--cef()--*/ - virtual bool IsUserCreated() =0; - - /// - // Returns true if the last method call resulted in an exception. This - // attribute exists only in the scope of the current CEF value object. - /// - /*--cef()--*/ - virtual bool HasException() =0; - - /// - // Returns the exception resulting from the last method call. This attribute - // exists only in the scope of the current CEF value object. - /// - /*--cef()--*/ - virtual CefRefPtr GetException() =0; - - /// - // Clears the last exception and returns true on success. - /// - /*--cef()--*/ - virtual bool ClearException() =0; - - /// - // Returns true if this object will re-throw future exceptions. This attribute - // exists only in the scope of the current CEF value object. - /// - /*--cef()--*/ - virtual bool WillRethrowExceptions() =0; - - /// - // Set whether this object will re-throw future exceptions. By default - // exceptions are not re-thrown. If a exception is re-thrown the current - // context should not be accessed again until after the exception has been - // caught and not re-thrown. Returns true on success. This attribute exists - // only in the scope of the current CEF value object. - /// - /*--cef()--*/ - virtual bool SetRethrowExceptions(bool rethrow) =0; - - /// - // Returns true if the object has a value with the specified identifier. - /// - /*--cef(capi_name=has_value_bykey,optional_param=key)--*/ - virtual bool HasValue(const CefString& key) =0; - - /// - // Returns true if the object has a value with the specified identifier. - /// - /*--cef(capi_name=has_value_byindex,index_param=index)--*/ - virtual bool HasValue(int index) =0; - - /// - // Deletes the value with the specified identifier and returns true on - // success. Returns false if this method is called incorrectly or an exception - // is thrown. For read-only and don't-delete values this method will return - // true even though deletion failed. - /// - /*--cef(capi_name=delete_value_bykey,optional_param=key)--*/ - virtual bool DeleteValue(const CefString& key) =0; - - /// - // Deletes the value with the specified identifier and returns true on - // success. Returns false if this method is called incorrectly, deletion fails - // or an exception is thrown. For read-only and don't-delete values this - // method will return true even though deletion failed. - /// - /*--cef(capi_name=delete_value_byindex,index_param=index)--*/ - virtual bool DeleteValue(int index) =0; - - /// - // Returns the value with the specified identifier on success. Returns NULL - // if this method is called incorrectly or an exception is thrown. - /// - /*--cef(capi_name=get_value_bykey,optional_param=key)--*/ - virtual CefRefPtr GetValue(const CefString& key) =0; - - /// - // Returns the value with the specified identifier on success. Returns NULL - // if this method is called incorrectly or an exception is thrown. - /// - /*--cef(capi_name=get_value_byindex,index_param=index)--*/ - virtual CefRefPtr GetValue(int index) =0; - - /// - // Associates a value with the specified identifier and returns true on - // success. Returns false if this method is called incorrectly or an exception - // is thrown. For read-only values this method will return true even though - // assignment failed. - /// - /*--cef(capi_name=set_value_bykey,optional_param=key)--*/ - virtual bool SetValue(const CefString& key, CefRefPtr value, - PropertyAttribute attribute) =0; - - /// - // Associates a value with the specified identifier and returns true on - // success. Returns false if this method is called incorrectly or an exception - // is thrown. For read-only values this method will return true even though - // assignment failed. - /// - /*--cef(capi_name=set_value_byindex,index_param=index)--*/ - virtual bool SetValue(int index, CefRefPtr value) =0; - - /// - // Registers an identifier and returns true on success. Access to the - // identifier will be forwarded to the CefV8Accessor instance passed to - // CefV8Value::CreateObject(). Returns false if this method is called - // incorrectly or an exception is thrown. For read-only values this method - // will return true even though assignment failed. - /// - /*--cef(capi_name=set_value_byaccessor,optional_param=key)--*/ - virtual bool SetValue(const CefString& key, AccessControl settings, - PropertyAttribute attribute) =0; - - /// - // Read the keys for the object's values into the specified vector. Integer- - // based keys will also be returned as strings. - /// - /*--cef()--*/ - virtual bool GetKeys(std::vector& keys) =0; - - /// - // Sets the user data for this object and returns true on success. Returns - // false if this method is called incorrectly. This method can only be called - // on user created objects. - /// - /*--cef(optional_param=user_data)--*/ - virtual bool SetUserData(CefRefPtr user_data) =0; - - /// - // Returns the user data, if any, assigned to this object. - /// - /*--cef()--*/ - virtual CefRefPtr GetUserData() =0; - - /// - // Returns the amount of externally allocated memory registered for the - // object. - /// - /*--cef()--*/ - virtual int GetExternallyAllocatedMemory() =0; - - /// - // Adjusts the amount of registered external memory for the object. Used to - // give V8 an indication of the amount of externally allocated memory that is - // kept alive by JavaScript objects. V8 uses this information to decide when - // to perform global garbage collection. Each CefV8Value tracks the amount of - // external memory associated with it and automatically decreases the global - // total by the appropriate amount on its destruction. |change_in_bytes| - // specifies the number of bytes to adjust by. This method returns the number - // of bytes associated with the object after the adjustment. This method can - // only be called on user created objects. - /// - /*--cef()--*/ - virtual int AdjustExternallyAllocatedMemory(int change_in_bytes) =0; - - - // ARRAY METHODS - These methods are only available on arrays. - - /// - // Returns the number of elements in the array. - /// - /*--cef()--*/ - virtual int GetArrayLength() =0; - - - // FUNCTION METHODS - These methods are only available on functions. - - /// - // Returns the function name. - /// - /*--cef()--*/ - virtual CefString GetFunctionName() =0; - - /// - // Returns the function handler or NULL if not a CEF-created function. - /// - /*--cef()--*/ - virtual CefRefPtr GetFunctionHandler() =0; - - /// - // Execute the function using the current V8 context. This method should only - // be called from within the scope of a CefV8Handler or CefV8Accessor - // callback, or in combination with calling Enter() and Exit() on a stored - // CefV8Context reference. |object| is the receiver ('this' object) of the - // function. If |object| is empty the current context's global object will be - // used. |arguments| is the list of arguments that will be passed to the - // function. Returns the function return value on success. Returns NULL if - // this method is called incorrectly or an exception is thrown. - /// - /*--cef(optional_param=object)--*/ - virtual CefRefPtr ExecuteFunction( - CefRefPtr object, - const CefV8ValueList& arguments) =0; - - /// - // Execute the function using the specified V8 context. |object| is the - // receiver ('this' object) of the function. If |object| is empty the - // specified context's global object will be used. |arguments| is the list of - // arguments that will be passed to the function. Returns the function return - // value on success. Returns NULL if this method is called incorrectly or an - // exception is thrown. - /// - /*--cef(optional_param=object)--*/ - virtual CefRefPtr ExecuteFunctionWithContext( - CefRefPtr context, - CefRefPtr object, - const CefV8ValueList& arguments) =0; -}; - -/// -// Class representing a V8 stack trace. The methods of this class may only be -// called on the UI thread. -/// -/*--cef(source=library)--*/ -class CefV8StackTrace : public virtual CefBase { - public: - /// - // Returns the stack trace for the currently active context. |frame_limit| is - // the maximum number of frames that will be captured. - /// - /*--cef()--*/ - static CefRefPtr GetCurrent(int frame_limit); - - /// - // Returns true if this object is valid. Do not call any other methods if this - // method returns false. - /// - /*--cef()--*/ - virtual bool IsValid() =0; - - /// - // Returns the number of stack frames. - /// - /*--cef()--*/ - virtual int GetFrameCount() =0; - - /// - // Returns the stack frame at the specified 0-based index. - /// - /*--cef()--*/ - virtual CefRefPtr GetFrame(int index) =0; -}; - -/// -// Class representing a V8 stack frame. The methods of this class may only be -// called on the UI thread. -/// -/*--cef(source=library)--*/ -class CefV8StackFrame : public virtual CefBase { - public: - /// - // Returns true if this object is valid. Do not call any other methods if this - // method returns false. - /// - /*--cef()--*/ - virtual bool IsValid() =0; - - /// - // Returns the name of the resource script that contains the function. - /// - /*--cef()--*/ - virtual CefString GetScriptName() =0; - - /// - // Returns the name of the resource script that contains the function or the - // sourceURL value if the script name is undefined and its source ends with - // a "//@ sourceURL=..." string. - /// - /*--cef()--*/ - virtual CefString GetScriptNameOrSourceURL() =0; - - /// - // Returns the name of the function. - /// - /*--cef()--*/ - virtual CefString GetFunctionName() =0; - - /// - // Returns the 1-based line number for the function call or 0 if unknown. - /// - /*--cef()--*/ - virtual int GetLineNumber() =0; - - /// - // Returns the 1-based column offset on the line for the function call or 0 if - // unknown. - /// - /*--cef()--*/ - virtual int GetColumn() =0; - - /// - // Returns true if the function was compiled using eval(). - /// - /*--cef()--*/ - virtual bool IsEval() =0; - - /// - // Returns true if the function was called as a constructor via "new". - /// - /*--cef()--*/ - virtual bool IsConstructor() =0; -}; - -#endif // CEF_INCLUDE_CEF_V8_H_ diff --git a/cefpython/cef1/include/cef_v8context_handler.h b/cefpython/cef1/include/cef_v8context_handler.h deleted file mode 100644 index 0483f3f3e..000000000 --- a/cefpython/cef1/include/cef_v8context_handler.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_V8CONTEXT_HANDLER_H_ -#define CEF_INCLUDE_CEF_V8CONTEXT_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" -#include "include/cef_frame.h" -#include "include/cef_v8.h" - -/// -// Implement this interface to handle V8 context events. The methods of this -// class will be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefV8ContextHandler : public virtual CefBase { - public: - /// - // Called immediately after the V8 context for a frame has been created. To - // retrieve the JavaScript 'window' object use the CefV8Context::GetGlobal() - // method. - /// - /*--cef()--*/ - virtual void OnContextCreated(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr context) {} - - /// - // Called immediately before the V8 context for a frame is released. No - // references to the context should be kept after this method is called. - /// - /*--cef()--*/ - virtual void OnContextReleased(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr context) {} - - /// - // Called for global uncaught exceptions. Execution of this callback is - // disabled by default. To enable set - // CefSettings.uncaught_exception_stack_size > 0. - /// - /*--cef()--*/ - virtual void OnUncaughtException(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr context, - CefRefPtr exception, - CefRefPtr stackTrace) {} -}; - -#endif // CEF_INCLUDE_CEF_V8CONTEXT_HANDLER_H_ diff --git a/cefpython/cef1/include/cef_version.h b/cefpython/cef1/include/cef_version.h deleted file mode 100644 index 63db08d2e..000000000 --- a/cefpython/cef1/include/cef_version.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2013 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// This file is generated by the make_version_header.py tool. -// - -#ifndef CEF_INCLUDE_CEF_VERSION_H_ -#define CEF_INCLUDE_CEF_VERSION_H_ - -#define CEF_REVISION 1268 -#define COPYRIGHT_YEAR 2013 - -#define CHROME_VERSION_MAJOR 27 -#define CHROME_VERSION_MINOR 0 -#define CHROME_VERSION_BUILD 1453 -#define CHROME_VERSION_PATCH 93 - -#define DO_MAKE_STRING(p) #p -#define MAKE_STRING(p) DO_MAKE_STRING(p) - -#ifndef APSTUDIO_HIDDEN_SYMBOLS - -#ifdef __cplusplus -extern "C" { -#endif - -#include "internal/cef_export.h" - -/// -// Returns the CEF build revision of the libcef library. -/// -CEF_EXPORT int cef_build_revision(); - -#ifdef __cplusplus -} -#endif - -#endif // APSTUDIO_HIDDEN_SYMBOLS - -#endif // CEF_INCLUDE_CEF_VERSION_H_ diff --git a/cefpython/cef1/include/cef_web_plugin.h b/cefpython/cef1/include/cef_web_plugin.h deleted file mode 100644 index e00b2349b..000000000 --- a/cefpython/cef1/include/cef_web_plugin.h +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_WEB_PLUGIN_H_ -#define CEF_INCLUDE_CEF_WEB_PLUGIN_H_ - -#include "include/cef_base.h" - -class CefWebPluginInfo; - -/// -// Returns the number of installed web plugins. This method must be called on -// the UI thread. -/// -/*--cef()--*/ -size_t CefGetWebPluginCount(); - -/// -// Returns information for web plugin at the specified zero-based index. This -// method must be called on the UI thread. -/// -/*--cef()--*/ -CefRefPtr CefGetWebPluginInfo(int index); - -/// -// Returns information for web plugin with the specified name. This method must -// be called on the UI thread. -/// -/*--cef(capi_name=cef_get_web_plugin_info_byname)--*/ -CefRefPtr CefGetWebPluginInfo(const CefString& name); - - -/// -// Information about a specific web plugin. -/// -/*--cef(source=library)--*/ -class CefWebPluginInfo : public virtual CefBase { - public: - /// - // Returns the plugin name (i.e. Flash). - /// - /*--cef()--*/ - virtual CefString GetName() =0; - - /// - // Returns the plugin file path (DLL/bundle/library). - /// - /*--cef()--*/ - virtual CefString GetPath() =0; - - /// - // Returns the version of the plugin (may be OS-specific). - /// - /*--cef()--*/ - virtual CefString GetVersion() =0; - - /// - // Returns a description of the plugin from the version information. - /// - /*--cef()--*/ - virtual CefString GetDescription() =0; -}; - -#endif // CEF_INCLUDE_CEF_WEB_PLUGIN_H_ diff --git a/cefpython/cef1/include/cef_web_urlrequest.h b/cefpython/cef1/include/cef_web_urlrequest.h deleted file mode 100644 index c5f471f9a..000000000 --- a/cefpython/cef1/include/cef_web_urlrequest.h +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_WEB_URLREQUEST_H_ -#define CEF_INCLUDE_CEF_WEB_URLREQUEST_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_request.h" -#include "include/cef_response.h" - -class CefWebURLRequestClient; - -/// -// Class used to make a Web URL request. Web URL requests are not associated -// with a browser instance so no CefClient callbacks will be executed. The -// methods of this class may be called on any thread. -/// -/*--cef(source=library)--*/ -class CefWebURLRequest : public virtual CefBase { - public: - typedef cef_weburlrequest_state_t RequestState; - - /// - // Create a new CefWebUrlRequest object. - /// - /*--cef()--*/ - static CefRefPtr CreateWebURLRequest( - CefRefPtr request, - CefRefPtr client); - - /// - // Cancels the request. - /// - /*--cef()--*/ - virtual void Cancel() =0; - - /// - // Returns the current ready state of the request. - /// - /*--cef(default_retval=WUR_STATE_UNSENT)--*/ - virtual RequestState GetState() =0; -}; - -/// -// Interface that should be implemented by the CefWebURLRequest client. The -// methods of this class will always be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefWebURLRequestClient : public virtual CefBase { - public: - typedef cef_weburlrequest_state_t RequestState; - typedef cef_handler_errorcode_t ErrorCode; - - /// - // Notifies the client that the request state has changed. State change - // notifications will always be sent before the below notification methods - // are called. - /// - /*--cef()--*/ - virtual void OnStateChange(CefRefPtr requester, - RequestState state) =0; - - /// - // Notifies the client that the request has been redirected and provides a - // chance to change the request parameters. - /// - /*--cef()--*/ - virtual void OnRedirect(CefRefPtr requester, - CefRefPtr request, - CefRefPtr response) =0; - - /// - // Notifies the client of the response data. - /// - /*--cef()--*/ - virtual void OnHeadersReceived(CefRefPtr requester, - CefRefPtr response) =0; - - /// - // Notifies the client of the upload progress. - /// - /*--cef()--*/ - virtual void OnProgress(CefRefPtr requester, - uint64 bytesSent, uint64 totalBytesToBeSent) =0; - - /// - // Notifies the client that content has been received. - /// - /*--cef()--*/ - virtual void OnData(CefRefPtr requester, - const void* data, int dataLength) =0; - - /// - // Notifies the client that the request ended with an error. - /// - /*--cef()--*/ - virtual void OnError(CefRefPtr requester, - ErrorCode errorCode) =0; -}; - -#endif // CEF_INCLUDE_CEF_WEB_URLREQUEST_H_ diff --git a/cefpython/cef1/include/cef_xml_reader.h b/cefpython/cef1/include/cef_xml_reader.h deleted file mode 100644 index e457e0d8d..000000000 --- a/cefpython/cef1/include/cef_xml_reader.h +++ /dev/null @@ -1,268 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_XML_READER_H_ -#define CEF_INCLUDE_CEF_XML_READER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_stream.h" - -/// -// Class that supports the reading of XML data via the libxml streaming API. -// The methods of this class should only be called on the thread that creates -// the object. -/// -/*--cef(source=library)--*/ -class CefXmlReader : public virtual CefBase { - public: - typedef cef_xml_encoding_type_t EncodingType; - typedef cef_xml_node_type_t NodeType; - - /// - // Create a new CefXmlReader object. The returned object's methods can only - // be called from the thread that created the object. - /// - /*--cef()--*/ - static CefRefPtr Create(CefRefPtr stream, - EncodingType encodingType, - const CefString& URI); - - /// - // Moves the cursor to the next node in the document. This method must be - // called at least once to set the current cursor position. Returns true if - // the cursor position was set successfully. - /// - /*--cef()--*/ - virtual bool MoveToNextNode() =0; - - /// - // Close the document. This should be called directly to ensure that cleanup - // occurs on the correct thread. - /// - /*--cef()--*/ - virtual bool Close() =0; - - /// - // Returns true if an error has been reported by the XML parser. - /// - /*--cef()--*/ - virtual bool HasError() =0; - - /// - // Returns the error string. - /// - /*--cef()--*/ - virtual CefString GetError() =0; - - - // The below methods retrieve data for the node at the current cursor - // position. - - /// - // Returns the node type. - /// - /*--cef(default_retval=XML_NODE_UNSUPPORTED)--*/ - virtual NodeType GetType() =0; - - /// - // Returns the node depth. Depth starts at 0 for the root node. - /// - /*--cef()--*/ - virtual int GetDepth() =0; - - /// - // Returns the local name. See - // http://www.w3.org/TR/REC-xml-names/#NT-LocalPart for additional details. - /// - /*--cef()--*/ - virtual CefString GetLocalName() =0; - - /// - // Returns the namespace prefix. See http://www.w3.org/TR/REC-xml-names/ for - // additional details. - /// - /*--cef()--*/ - virtual CefString GetPrefix() =0; - - /// - // Returns the qualified name, equal to (Prefix:)LocalName. See - // http://www.w3.org/TR/REC-xml-names/#ns-qualnames for additional details. - /// - /*--cef()--*/ - virtual CefString GetQualifiedName() =0; - - /// - // Returns the URI defining the namespace associated with the node. See - // http://www.w3.org/TR/REC-xml-names/ for additional details. - /// - /*--cef()--*/ - virtual CefString GetNamespaceURI() =0; - - /// - // Returns the base URI of the node. See http://www.w3.org/TR/xmlbase/ for - // additional details. - /// - /*--cef()--*/ - virtual CefString GetBaseURI() =0; - - /// - // Returns the xml:lang scope within which the node resides. See - // http://www.w3.org/TR/REC-xml/#sec-lang-tag for additional details. - /// - /*--cef()--*/ - virtual CefString GetXmlLang() =0; - - /// - // Returns true if the node represents an empty element. is considered - // empty but is not. - /// - /*--cef()--*/ - virtual bool IsEmptyElement() =0; - - /// - // Returns true if the node has a text value. - /// - /*--cef()--*/ - virtual bool HasValue() =0; - - /// - // Returns the text value. - /// - /*--cef()--*/ - virtual CefString GetValue() =0; - - /// - // Returns true if the node has attributes. - /// - /*--cef()--*/ - virtual bool HasAttributes() =0; - - /// - // Returns the number of attributes. - /// - /*--cef()--*/ - virtual size_t GetAttributeCount() =0; - - /// - // Returns the value of the attribute at the specified 0-based index. - /// - /*--cef(capi_name=get_attribute_byindex,index_param=index)--*/ - virtual CefString GetAttribute(int index) =0; - - /// - // Returns the value of the attribute with the specified qualified name. - /// - /*--cef(capi_name=get_attribute_byqname)--*/ - virtual CefString GetAttribute(const CefString& qualifiedName) =0; - - /// - // Returns the value of the attribute with the specified local name and - // namespace URI. - /// - /*--cef(capi_name=get_attribute_bylname)--*/ - virtual CefString GetAttribute(const CefString& localName, - const CefString& namespaceURI) =0; - - /// - // Returns an XML representation of the current node's children. - /// - /*--cef()--*/ - virtual CefString GetInnerXml() =0; - - /// - // Returns an XML representation of the current node including its children. - /// - /*--cef()--*/ - virtual CefString GetOuterXml() =0; - - /// - // Returns the line number for the current node. - /// - /*--cef()--*/ - virtual int GetLineNumber() =0; - - - // Attribute nodes are not traversed by default. The below methods can be - // used to move the cursor to an attribute node. MoveToCarryingElement() can - // be called afterwards to return the cursor to the carrying element. The - // depth of an attribute node will be 1 + the depth of the carrying element. - - /// - // Moves the cursor to the attribute at the specified 0-based index. Returns - // true if the cursor position was set successfully. - /// - /*--cef(capi_name=move_to_attribute_byindex,index_param=index)--*/ - virtual bool MoveToAttribute(int index) =0; - - /// - // Moves the cursor to the attribute with the specified qualified name. - // Returns true if the cursor position was set successfully. - /// - /*--cef(capi_name=move_to_attribute_byqname)--*/ - virtual bool MoveToAttribute(const CefString& qualifiedName) =0; - - /// - // Moves the cursor to the attribute with the specified local name and - // namespace URI. Returns true if the cursor position was set successfully. - /// - /*--cef(capi_name=move_to_attribute_bylname)--*/ - virtual bool MoveToAttribute(const CefString& localName, - const CefString& namespaceURI) =0; - - /// - // Moves the cursor to the first attribute in the current element. Returns - // true if the cursor position was set successfully. - /// - /*--cef()--*/ - virtual bool MoveToFirstAttribute() =0; - - /// - // Moves the cursor to the next attribute in the current element. Returns - // true if the cursor position was set successfully. - /// - /*--cef()--*/ - virtual bool MoveToNextAttribute() =0; - - /// - // Moves the cursor back to the carrying element. Returns true if the cursor - // position was set successfully. - /// - /*--cef()--*/ - virtual bool MoveToCarryingElement() =0; -}; - -#endif // CEF_INCLUDE_CEF_XML_READER_H_ diff --git a/cefpython/cef1/include/cef_zip_reader.h b/cefpython/cef1/include/cef_zip_reader.h deleted file mode 100644 index 9498f06ed..000000000 --- a/cefpython/cef1/include/cef_zip_reader.h +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_ZIP_READER_H_ -#define CEF_INCLUDE_CEF_ZIP_READER_H_ - -#include "include/cef_base.h" -#include "include/cef_stream.h" - -/// -// Class that supports the reading of zip archives via the zlib unzip API. -// The methods of this class should only be called on the thread that creates -// the object. -/// -/*--cef(source=library)--*/ -class CefZipReader : public virtual CefBase { - public: - /// - // Create a new CefZipReader object. The returned object's methods can only - // be called from the thread that created the object. - /// - /*--cef()--*/ - static CefRefPtr Create(CefRefPtr stream); - - /// - // Moves the cursor to the first file in the archive. Returns true if the - // cursor position was set successfully. - /// - /*--cef()--*/ - virtual bool MoveToFirstFile() =0; - - /// - // Moves the cursor to the next file in the archive. Returns true if the - // cursor position was set successfully. - /// - /*--cef()--*/ - virtual bool MoveToNextFile() =0; - - /// - // Moves the cursor to the specified file in the archive. If |caseSensitive| - // is true then the search will be case sensitive. Returns true if the cursor - // position was set successfully. - /// - /*--cef()--*/ - virtual bool MoveToFile(const CefString& fileName, bool caseSensitive) =0; - - /// - // Closes the archive. This should be called directly to ensure that cleanup - // occurs on the correct thread. - /// - /*--cef()--*/ - virtual bool Close() =0; - - - // The below methods act on the file at the current cursor position. - - /// - // Returns the name of the file. - /// - /*--cef()--*/ - virtual CefString GetFileName() =0; - - /// - // Returns the uncompressed size of the file. - /// - /*--cef()--*/ - virtual int64 GetFileSize() =0; - - /// - // Returns the last modified timestamp for the file. - /// - /*--cef()--*/ - virtual time_t GetFileLastModified() =0; - - /// - // Opens the file for reading of uncompressed data. A read password may - // optionally be specified. - /// - /*--cef(optional_param=password)--*/ - virtual bool OpenFile(const CefString& password) =0; - - /// - // Closes the file. - /// - /*--cef()--*/ - virtual bool CloseFile() =0; - - /// - // Read uncompressed file contents into the specified buffer. Returns < 0 if - // an error occurred, 0 if at the end of file, or the number of bytes read. - /// - /*--cef()--*/ - virtual int ReadFile(void* buffer, size_t bufferSize) =0; - - /// - // Returns the current offset in the uncompressed file contents. - /// - /*--cef()--*/ - virtual int64 Tell() =0; - - /// - // Returns true if at end of the file contents. - /// - /*--cef()--*/ - virtual bool Eof() =0; -}; - -#endif // CEF_INCLUDE_CEF_ZIP_READER_H_ diff --git a/cefpython/cef1/include/cef_zoom_handler.h b/cefpython/cef1/include/cef_zoom_handler.h deleted file mode 100644 index 7062b64b7..000000000 --- a/cefpython/cef1/include/cef_zoom_handler.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file must follow a specific format in order to -// support the CEF translator tool. See the translator.README.txt file in the -// tools directory for more information. -// - -#ifndef CEF_INCLUDE_CEF_ZOOM_HANDLER_H_ -#define CEF_INCLUDE_CEF_ZOOM_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_browser.h" - -/// -// Implement this interface to customize zoom handling. The methods of this -// class will be called on the UI thread. -/// -/*--cef(source=client)--*/ -class CefZoomHandler : public virtual CefBase { - public: - /// - // Called when the browser wants to retrieve the zoom level for the given - // |url|. Return true if |zoomLevel| has been set to the custom zoom level. - // Return false for the browser's default zoom handling behavior. - /// - /*--cef()--*/ - virtual bool OnGetZoomLevel(CefRefPtr browser, - const CefString& url, - double& zoomLevel) { return false; } - - /// - // Called when the browser's zoom level has been set to |zoomLevel| for the - // given |url|. Return true to indicate that the new setting has been handled. - // Return false to use the browser's default zoom handling behavior. - /// - /*--cef()--*/ - virtual bool OnSetZoomLevel(CefRefPtr browser, - const CefString& url, - double zoomLevel) { return false; } -}; - -#endif // CEF_INCLUDE_CEF_ZOOM_HANDLER_H_ diff --git a/cefpython/cef1/include/internal/cef_build.h b/cefpython/cef1/include/internal/cef_build.h deleted file mode 100644 index 4b8c54546..000000000 --- a/cefpython/cef1/include/internal/cef_build.h +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -#ifndef CEF_INCLUDE_INTERNAL_CEF_BUILD_H_ -#define CEF_INCLUDE_INTERNAL_CEF_BUILD_H_ -#pragma once - -#if defined(BUILDING_CEF_SHARED) - -#include "base/compiler_specific.h" - -#else // !BUILDING_CEF_SHARED - -#if defined(_WIN32) -#ifndef OS_WIN -#define OS_WIN 1 -#endif -#elif defined(__APPLE__) -#ifndef OS_MACOSX -#define OS_MACOSX 1 -#endif -#elif defined(__linux__) -#ifndef OS_LINUX -#define OS_LINUX 1 -#endif -#else -#error Please add support for your platform in cef_build.h -#endif - -// For access to standard POSIXish features, use OS_POSIX instead of a -// more specific macro. -#if defined(OS_MACOSX) || defined(OS_LINUX) -#ifndef OS_POSIX -#define OS_POSIX 1 -#endif -#endif - -// Compiler detection. -#if defined(__GNUC__) -#ifndef COMPILER_GCC -#define COMPILER_GCC 1 -#endif -#elif defined(_MSC_VER) -#ifndef COMPILER_MSVC -#define COMPILER_MSVC 1 -#endif -#else -#error Please add support for your compiler in cef_build.h -#endif - -// Annotate a virtual method indicating it must be overriding a virtual -// method in the parent class. -// Use like: -// virtual void foo() OVERRIDE; -#ifndef OVERRIDE -#if defined(COMPILER_MSVC) -#define OVERRIDE override -#elif defined(__clang__) -#define OVERRIDE override -#else -#define OVERRIDE -#endif -#endif - -#ifndef ALLOW_THIS_IN_INITIALIZER_LIST -#if defined(COMPILER_MSVC) - -// MSVC_PUSH_DISABLE_WARNING pushes |n| onto a stack of warnings to be disabled. -// The warning remains disabled until popped by MSVC_POP_WARNING. -#define MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \ - __pragma(warning(disable:n)) - -// MSVC_PUSH_WARNING_LEVEL pushes |n| as the global warning level. The level -// remains in effect until popped by MSVC_POP_WARNING(). Use 0 to disable all -// warnings. -#define MSVC_PUSH_WARNING_LEVEL(n) __pragma(warning(push, n)) - -// Pop effects of innermost MSVC_PUSH_* macro. -#define MSVC_POP_WARNING() __pragma(warning(pop)) - -// Allows |this| to be passed as an argument in constructor initializer lists. -// This uses push/pop instead of the seemingly simpler suppress feature to avoid -// having the warning be disabled for more than just |code|. -// -// Example usage: -// Foo::Foo() : x(NULL), ALLOW_THIS_IN_INITIALIZER_LIST(y(this)), z(3) {} -// -// Compiler warning C4355: 'this': used in base member initializer list: -// http://msdn.microsoft.com/en-us/library/3c594ae3(VS.80).aspx -#define ALLOW_THIS_IN_INITIALIZER_LIST(code) MSVC_PUSH_DISABLE_WARNING(4355) \ - code \ - MSVC_POP_WARNING() -#else // !COMPILER_MSVC - -#define ALLOW_THIS_IN_INITIALIZER_LIST(code) code - -#endif // !COMPILER_MSVC -#endif - -#endif // !BUILDING_CEF_SHARED - -#endif // CEF_INCLUDE_INTERNAL_CEF_BUILD_H_ diff --git a/cefpython/cef1/include/internal/cef_export.h b/cefpython/cef1/include/internal/cef_export.h deleted file mode 100644 index d333a5db8..000000000 --- a/cefpython/cef1/include/internal/cef_export.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2009 The Chromium Embedded Framework Authors. All rights -// reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CEF_INCLUDE_INTERNAL_CEF_EXPORT_H_ -#define CEF_INCLUDE_INTERNAL_CEF_EXPORT_H_ -#pragma once - -#include "include/internal/cef_build.h" - -#if defined(COMPILER_MSVC) - -#ifdef BUILDING_CEF_SHARED -#define CEF_EXPORT __declspec(dllexport) -#elif USING_CEF_SHARED -#define CEF_EXPORT __declspec(dllimport) -#else -#define CEF_EXPORT -#endif -#define CEF_CALLBACK __stdcall - -#elif defined(COMPILER_GCC) - -#define CEF_EXPORT __attribute__ ((visibility("default"))) -#define CEF_CALLBACK - -#endif // COMPILER_GCC - -#endif // CEF_INCLUDE_INTERNAL_CEF_EXPORT_H_ diff --git a/cefpython/cef1/include/internal/cef_linux.h b/cefpython/cef1/include/internal/cef_linux.h deleted file mode 100644 index 0c9003b06..000000000 --- a/cefpython/cef1/include/internal/cef_linux.h +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (c) 2010 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -#ifndef CEF_INCLUDE_INTERNAL_CEF_LINUX_H_ -#define CEF_INCLUDE_INTERNAL_CEF_LINUX_H_ -#pragma once - -#if defined(OS_LINUX) -#include -#include "include/internal/cef_types_linux.h" -#include "include/internal/cef_types_wrappers.h" - -/// -// Atomic increment and decrement. -/// -inline long CefAtomicIncrement(long volatile *pDest) { // NOLINT(runtime/int) - return __sync_add_and_fetch(pDest, 1); -} -inline long CefAtomicDecrement(long volatile *pDest) { // NOLINT(runtime/int) - return __sync_sub_and_fetch(pDest, 1); -} - -/// -// Critical section wrapper. -/// -class CefCriticalSection { - public: - CefCriticalSection() { - pthread_mutexattr_init(&attr_); - pthread_mutexattr_settype(&attr_, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&lock_, &attr_); - } - virtual ~CefCriticalSection() { - pthread_mutex_destroy(&lock_); - pthread_mutexattr_destroy(&attr_); - } - void Lock() { - pthread_mutex_lock(&lock_); - } - void Unlock() { - pthread_mutex_unlock(&lock_); - } - - pthread_mutex_t lock_; - pthread_mutexattr_t attr_; -}; - -/// -// Handle types. -/// -#define CefWindowHandle cef_window_handle_t -#define CefCursorHandle cef_cursor_handle_t - - -struct CefWindowInfoTraits { - typedef cef_window_info_t struct_type; - - static inline void init(struct_type* s) {} - static inline void clear(struct_type* s) {} - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - target->m_Widget = src->m_Widget; - target->m_ParentWidget = src->m_ParentWidget; - } -}; - -/// -// Class representing window information. -/// -class CefWindowInfo : public CefStructBase { - public: - typedef CefStructBase parent; - - CefWindowInfo() : parent() {} - explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {} - explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {} - - void SetAsChild(CefWindowHandle ParentWidget) { - m_ParentWidget = ParentWidget; - } -}; - - -struct CefPrintInfoTraits { - typedef cef_print_info_t struct_type; - - static inline void init(struct_type* s) {} - static inline void clear(struct_type* s) {} - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - target->m_Scale = src->m_Scale; - } -}; - -/// -// Class representing print context information. -/// -typedef CefStructBase CefPrintInfo; - - -struct CefKeyInfoTraits { - typedef cef_key_info_t struct_type; - - static inline void init(struct_type* s) {} - static inline void clear(struct_type* s) {} - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - target->key = src->key; - } -}; - -/// -// Class representing key information. -/// -typedef CefStructBase CefKeyInfo; - -#endif // OS_LINUX - -#endif // CEF_INCLUDE_INTERNAL_CEF_LINUX_H_ diff --git a/cefpython/cef1/include/internal/cef_mac.h b/cefpython/cef1/include/internal/cef_mac.h deleted file mode 100644 index d979e80fe..000000000 --- a/cefpython/cef1/include/internal/cef_mac.h +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright (c) 2010 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -#ifndef CEF_INCLUDE_INTERNAL_CEF_MAC_H_ -#define CEF_INCLUDE_INTERNAL_CEF_MAC_H_ -#pragma once - -#if defined(OS_MACOSX) -#include -#include "include/internal/cef_types_mac.h" -#include "include/internal/cef_types_wrappers.h" - -/// -// Atomic increment and decrement. -/// -inline long CefAtomicIncrement(long volatile *pDest) { // NOLINT(runtime/int) - return __sync_add_and_fetch(pDest, 1); -} -inline long CefAtomicDecrement(long volatile *pDest) { // NOLINT(runtime/int) - return __sync_sub_and_fetch(pDest, 1); -} - -/// -// Handle types. -/// -#define CefWindowHandle cef_window_handle_t -#define CefCursorHandle cef_cursor_handle_t - -/// -// Critical section wrapper. -/// -class CefCriticalSection { - public: - CefCriticalSection() { - pthread_mutexattr_init(&attr_); - pthread_mutexattr_settype(&attr_, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&lock_, &attr_); - } - virtual ~CefCriticalSection() { - pthread_mutex_destroy(&lock_); - pthread_mutexattr_destroy(&attr_); - } - void Lock() { - pthread_mutex_lock(&lock_); - } - void Unlock() { - pthread_mutex_unlock(&lock_); - } - - pthread_mutex_t lock_; - pthread_mutexattr_t attr_; -}; - - -struct CefWindowInfoTraits { - typedef cef_window_info_t struct_type; - - static inline void init(struct_type* s) {} - - static inline void clear(struct_type* s) { - cef_string_clear(&s->m_windowName); - } - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - target->m_View = src->m_View; - target->m_ParentView = src->m_ParentView; - cef_string_set(src->m_windowName.str, src->m_windowName.length, - &target->m_windowName, copy); - target->m_x = src->m_x; - target->m_y = src->m_y; - target->m_nWidth = src->m_nWidth; - target->m_nHeight = src->m_nHeight; - target->m_bHidden = src->m_bHidden; - target->m_bWindowRenderingDisabled = src->m_bWindowRenderingDisabled; - target->m_bTransparentPainting = src->m_bTransparentPainting; - } -}; - -/// -// Class representing window information. -/// -class CefWindowInfo : public CefStructBase { - public: - typedef CefStructBase parent; - - CefWindowInfo() : parent() {} - explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {} - explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {} - - void SetAsChild(CefWindowHandle ParentView, int x, int y, int width, - int height) { - m_ParentView = ParentView; - m_x = x; - m_y = y; - m_nWidth = width; - m_nHeight = height; - m_bHidden = false; - } - - void SetAsOffScreen(NSView* parent) { - m_bWindowRenderingDisabled = true; - m_ParentView = parent; - } - - void SetTransparentPainting(int transparentPainting) { - m_bTransparentPainting = transparentPainting; - } -}; - - -struct CefPrintInfoTraits { - typedef cef_print_info_t struct_type; - - static inline void init(struct_type* s) {} - static inline void clear(struct_type* s) {} - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - target->m_Scale = src->m_Scale; - } -}; - -/// -// Class representing print context information. -/// -typedef CefStructBase CefPrintInfo; - -struct CefKeyInfoTraits { - typedef cef_key_info_t struct_type; - - static inline void init(struct_type* s) {} - static inline void clear(struct_type* s) {} - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - target->keyCode = src->keyCode; - target->character = src->character; - target->characterNoModifiers = src->characterNoModifiers; - } -}; - -/// -// Class representing key information. -/// -typedef CefStructBase CefKeyInfo; - - -#endif // OS_MACOSX - -#endif // CEF_INCLUDE_INTERNAL_CEF_MAC_H_ diff --git a/cefpython/cef1/include/internal/cef_nplugin_types.h b/cefpython/cef1/include/internal/cef_nplugin_types.h deleted file mode 100644 index 0113f72fb..000000000 --- a/cefpython/cef1/include/internal/cef_nplugin_types.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -#ifndef CEF_INCLUDE_INTERNAL_CEF_NPLUGIN_TYPES_H_ -#define CEF_INCLUDE_INTERNAL_CEF_NPLUGIN_TYPES_H_ -#pragma once - -#include "include/internal/cef_export.h" -#include "include/internal/cef_string.h" -#include "third_party/npapi/bindings/npapi.h" -#include "third_party/npapi/bindings/nphostapi.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Netscape plugins are normally built at separate DLLs that are loaded by the -// browser when needed. This interface supports the creation of plugins that -// are an embedded component of the application. Embedded plugins built using -// this interface use the same Netscape Plugin API as DLL-based plugins. -// See https://developer.mozilla.org/En/Gecko_Plugin_API_Reference for complete -// documentation on how to use the Netscape Plugin API. - -// This structure provides attribute information and entry point functions for -// a plugin. -typedef struct _cef_plugin_info_t { - // The unique name that identifies the plugin. - cef_string_t unique_name; - - // The friendly display name of the plugin. - cef_string_t display_name; - - // The version string of the plugin. - cef_string_t version; - - // A description of the plugin. - cef_string_t description; - - // A pipe (|) delimited list of mime type values that the plugin supports. - cef_string_t mime_types; - - // A pipe (|) delimited list of extension values. Each value is associated - // with the mime type value at the same position. Multiple file extensions - // for the same mime type may be delimited with commas (,). - cef_string_t file_extensions; - - // A pipe (|) delimited list of description values. Each value is associated - // with the mime type value at the same position. - cef_string_t type_descriptions; - - // Entry point function pointers. -#if !defined(OS_POSIX) || defined(OS_MACOSX) - NP_GetEntryPointsFunc np_getentrypoints; -#endif - NP_InitializeFunc np_initialize; - NP_ShutdownFunc np_shutdown; -} cef_plugin_info_t; - -#ifdef __cplusplus -} -#endif - -#endif // CEF_INCLUDE_INTERNAL_CEF_NPLUGIN_TYPES_H_ diff --git a/cefpython/cef1/include/internal/cef_ptr.h b/cefpython/cef1/include/internal/cef_ptr.h deleted file mode 100644 index fcbe69e5c..000000000 --- a/cefpython/cef1/include/internal/cef_ptr.h +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) 2008 Marshall A. Greenblatt. Portions Copyright (c) -// 2006-2008 Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -#ifndef CEF_INCLUDE_INTERNAL_CEF_PTR_H_ -#define CEF_INCLUDE_INTERNAL_CEF_PTR_H_ -#pragma once - -#include - -/// -// Smart pointer implementation borrowed from base/ref_counted.h -//

-// A smart pointer class for reference counted objects. Use this class instead -// of calling AddRef and Release manually on a reference counted object to -// avoid common memory leaks caused by forgetting to Release an object -// reference. Sample usage: -//

-//   class MyFoo : public CefBase {
-//    ...
-//   };
-//
-//   void some_function() {
-//     // The MyFoo object that |foo| represents starts with a single
-//     // reference.
-//     CefRefPtr<MyFoo> foo = new MyFoo();
-//     foo->Method(param);
-//     // |foo| is released when this function returns
-//   }
-//
-//   void some_other_function() {
-//     CefRefPtr<MyFoo> foo = new MyFoo();
-//     ...
-//     foo = NULL;  // explicitly releases |foo|
-//     ...
-//     if (foo)
-//       foo->Method(param);
-//   }
-// 
-// The above examples show how CefRefPtr<T> acts like a pointer to T. -// Given two CefRefPtr<T> classes, it is also possible to exchange -// references between the two objects, like so: -//
-//   {
-//     CefRefPtr<MyFoo> a = new MyFoo();
-//     CefRefPtr<MyFoo> b;
-//
-//     b.swap(a);
-//     // now, |b| references the MyFoo object, and |a| references NULL.
-//   }
-// 
-// To make both |a| and |b| in the above example reference the same MyFoo -// object, simply use the assignment operator: -//
-//   {
-//     CefRefPtr<MyFoo> a = new MyFoo();
-//     CefRefPtr<MyFoo> b;
-//
-//     b = a;
-//     // now, |a| and |b| each own a reference to the same MyFoo object.
-//     // the reference count of the underlying MyFoo object will be 2.
-//   }
-// 
-// Reference counted objects can also be passed as function parameters and -// used as function return values: -//
-//   void some_func_with_param(CefRefPtr<MyFoo> param) {
-//     // A reference is added to the MyFoo object that |param| represents
-//     // during the scope of some_func_with_param() and released when
-//     // some_func_with_param() goes out of scope.
-//   }
-//
-//   CefRefPtr<MyFoo> some_func_with_retval() {
-//     // The MyFoo object that |foox| represents starts with a single
-//     // reference.
-//     CefRefPtr<MyFoo> foox = new MyFoo();
-//
-//     // Creating the return value adds an additional reference.
-//     return foox;
-//
-//     // When some_func_with_retval() goes out of scope the original |foox|
-//     // reference is released.
-//   }
-//
-//   void and_another_function() {
-//     CefRefPtr<MyFoo> foo = new MyFoo();
-//
-//     // pass |foo| as a parameter.
-//     some_function(foo);
-//
-//     CefRefPtr<MyFoo> foo2 = some_func_with_retval();
-//     // Now, since we kept a reference to the some_func_with_retval() return
-//     // value, |foo2| is the only class pointing to the MyFoo object created
-//     in some_func_with_retval(), and it has a reference count of 1.
-//
-//     some_func_with_retval();
-//     // Now, since we didn't keep a reference to the some_func_with_retval()
-//     // return value, the MyFoo object created in some_func_with_retval()
-//     // will automatically be released.
-//   }
-// 
-// And in standard containers: -//
-//   {
-//      // Create a vector that holds MyFoo objects.
-//      std::vector<CefRefPtr<MyFoo> > MyFooVec;
-//
-//     // The MyFoo object that |foo| represents starts with a single
-//     // reference.
-//     CefRefPtr<MyFoo> foo = new MyFoo();
-//
-//     // When the MyFoo object is added to |MyFooVec| the reference count
-//     // is increased to 2.
-//     MyFooVec.push_back(foo);
-//   }
-// 
-//

-/// -template -class CefRefPtr { - public: - CefRefPtr() : ptr_(NULL) { - } - - CefRefPtr(T* p) : ptr_(p) { // NOLINT(runtime/explicit) - if (ptr_) - ptr_->AddRef(); - } - - CefRefPtr(const CefRefPtr& r) : ptr_(r.ptr_) { - if (ptr_) - ptr_->AddRef(); - } - - ~CefRefPtr() { - if (ptr_) - ptr_->Release(); - } - - T* get() const { return ptr_; } - operator T*() const { return ptr_; } - T* operator->() const { return ptr_; } - - CefRefPtr& operator=(T* p) { - // AddRef first so that self assignment should work - if (p) - p->AddRef(); - if (ptr_ ) - ptr_ ->Release(); - ptr_ = p; - return *this; - } - - CefRefPtr& operator=(const CefRefPtr& r) { - return *this = r.ptr_; - } - - void swap(T** pp) { - T* p = ptr_; - ptr_ = *pp; - *pp = p; - } - - void swap(CefRefPtr& r) { - swap(&r.ptr_); // NOLINT(build/include_what_you_use) - } - - private: - T* ptr_; -}; - -#endif // CEF_INCLUDE_INTERNAL_CEF_PTR_H_ diff --git a/cefpython/cef1/include/internal/cef_string.h b/cefpython/cef1/include/internal/cef_string.h deleted file mode 100644 index a7876fe56..000000000 --- a/cefpython/cef1/include/internal/cef_string.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2010 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CEF_INCLUDE_INTERNAL_CEF_STRING_H_ -#define CEF_INCLUDE_INTERNAL_CEF_STRING_H_ -#pragma once - -// The CEF interface is built with one string type as the default. Comment out -// all but one of the CEF_STRING_TYPE_* defines below to specify the default. -// If you change the default you MUST recompile all of CEF. - -// Build with the UTF8 string type as default. -// #define CEF_STRING_TYPE_UTF8 1 - -// Build with the UTF16 string type as default. -#define CEF_STRING_TYPE_UTF16 1 - -// Build with the wide string type as default. -// #define CEF_STRING_TYPE_WIDE 1 - - -#include "include/internal/cef_string_types.h" - -#ifdef __cplusplus -#include "include/internal/cef_string_wrappers.h" -#if defined(CEF_STRING_TYPE_UTF16) -typedef CefStringUTF16 CefString; -#elif defined(CEF_STRING_TYPE_UTF8) -typedef CefStringUTF8 CefString; -#elif defined(CEF_STRING_TYPE_WIDE) -typedef CefStringWide CefString; -#endif -#endif // __cplusplus - -#if defined(CEF_STRING_TYPE_UTF8) -typedef char cef_char_t; -typedef cef_string_utf8_t cef_string_t; -typedef cef_string_userfree_utf8_t cef_string_userfree_t; -#define cef_string_set cef_string_utf8_set -#define cef_string_copy cef_string_utf8_copy -#define cef_string_clear cef_string_utf8_clear -#define cef_string_userfree_alloc cef_string_userfree_utf8_alloc -#define cef_string_userfree_free cef_string_userfree_utf8_free -#define cef_string_from_ascii cef_string_utf8_copy -#define cef_string_to_utf8 cef_string_utf8_copy -#define cef_string_from_utf8 cef_string_utf8_copy -#define cef_string_to_utf16 cef_string_utf8_to_utf16 -#define cef_string_from_utf16 cef_string_utf16_to_utf8 -#define cef_string_to_wide cef_string_utf8_to_wide -#define cef_string_from_wide cef_string_wide_to_utf8 -#elif defined(CEF_STRING_TYPE_UTF16) -typedef char16 cef_char_t; -typedef cef_string_userfree_utf16_t cef_string_userfree_t; -typedef cef_string_utf16_t cef_string_t; -#define cef_string_set cef_string_utf16_set -#define cef_string_copy cef_string_utf16_copy -#define cef_string_clear cef_string_utf16_clear -#define cef_string_userfree_alloc cef_string_userfree_utf16_alloc -#define cef_string_userfree_free cef_string_userfree_utf16_free -#define cef_string_from_ascii cef_string_ascii_to_utf16 -#define cef_string_to_utf8 cef_string_utf16_to_utf8 -#define cef_string_from_utf8 cef_string_utf8_to_utf16 -#define cef_string_to_utf16 cef_string_utf16_copy -#define cef_string_from_utf16 cef_string_utf16_copy -#define cef_string_to_wide cef_string_utf16_to_wide -#define cef_string_from_wide cef_string_wide_to_utf16 -#elif defined(CEF_STRING_TYPE_WIDE) -typedef wchar_t cef_char_t; -typedef cef_string_wide_t cef_string_t; -typedef cef_string_userfree_wide_t cef_string_userfree_t; -#define cef_string_set cef_string_wide_set -#define cef_string_copy cef_string_wide_copy -#define cef_string_clear cef_string_wide_clear -#define cef_string_userfree_alloc cef_string_userfree_wide_alloc -#define cef_string_userfree_free cef_string_userfree_wide_free -#define cef_string_from_ascii cef_string_ascii_to_wide -#define cef_string_to_utf8 cef_string_wide_to_utf8 -#define cef_string_from_utf8 cef_string_utf8_to_wide -#define cef_string_to_utf16 cef_string_wide_to_utf16 -#define cef_string_from_utf16 cef_string_utf16_to_wide -#define cef_string_to_wide cef_string_wide_copy -#define cef_string_from_wide cef_string_wide_copy -#else -#error Please choose a string type. -#endif - -#endif // CEF_INCLUDE_INTERNAL_CEF_STRING_H_ diff --git a/cefpython/cef1/include/internal/cef_string_list.h b/cefpython/cef1/include/internal/cef_string_list.h deleted file mode 100644 index 52a0abf2f..000000000 --- a/cefpython/cef1/include/internal/cef_string_list.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2009 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CEF_INCLUDE_INTERNAL_CEF_STRING_LIST_H_ -#define CEF_INCLUDE_INTERNAL_CEF_STRING_LIST_H_ -#pragma once - -#include "include/internal/cef_export.h" -#include "include/internal/cef_string.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/// -// CEF string maps are a set of key/value string pairs. -/// -typedef void* cef_string_list_t; - -/// -// Allocate a new string map. -/// -CEF_EXPORT cef_string_list_t cef_string_list_alloc(); - -/// -// Return the number of elements in the string list. -/// -CEF_EXPORT int cef_string_list_size(cef_string_list_t list); - -/// -// Retrieve the value at the specified zero-based string list index. Returns -// true (1) if the value was successfully retrieved. -/// -CEF_EXPORT int cef_string_list_value(cef_string_list_t list, - int index, cef_string_t* value); - -/// -// Append a new value at the end of the string list. -/// -CEF_EXPORT void cef_string_list_append(cef_string_list_t list, - const cef_string_t* value); - -/// -// Clear the string list. -/// -CEF_EXPORT void cef_string_list_clear(cef_string_list_t list); - -/// -// Free the string list. -/// -CEF_EXPORT void cef_string_list_free(cef_string_list_t list); - -/// -// Creates a copy of an existing string list. -/// -CEF_EXPORT cef_string_list_t cef_string_list_copy(cef_string_list_t list); - -#ifdef __cplusplus -} -#endif - -#endif // CEF_INCLUDE_INTERNAL_CEF_STRING_LIST_H_ diff --git a/cefpython/cef1/include/internal/cef_string_map.h b/cefpython/cef1/include/internal/cef_string_map.h deleted file mode 100644 index 93eea2a55..000000000 --- a/cefpython/cef1/include/internal/cef_string_map.h +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) 2009 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CEF_INCLUDE_INTERNAL_CEF_STRING_MAP_H_ -#define CEF_INCLUDE_INTERNAL_CEF_STRING_MAP_H_ -#pragma once - -#include "include/internal/cef_export.h" -#include "include/internal/cef_string.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/// -// CEF string maps are a set of key/value string pairs. -/// -typedef void* cef_string_map_t; - -/// -// Allocate a new string map. -/// -CEF_EXPORT cef_string_map_t cef_string_map_alloc(); - -/// -// Return the number of elements in the string map. -/// -CEF_EXPORT int cef_string_map_size(cef_string_map_t map); - -/// -// Return the value assigned to the specified key. -/// -CEF_EXPORT int cef_string_map_find(cef_string_map_t map, - const cef_string_t* key, - cef_string_t* value); - -/// -// Return the key at the specified zero-based string map index. -/// -CEF_EXPORT int cef_string_map_key(cef_string_map_t map, int index, - cef_string_t* key); - -/// -// Return the value at the specified zero-based string map index. -/// -CEF_EXPORT int cef_string_map_value(cef_string_map_t map, int index, - cef_string_t* value); - -/// -// Append a new key/value pair at the end of the string map. -/// -CEF_EXPORT int cef_string_map_append(cef_string_map_t map, - const cef_string_t* key, - const cef_string_t* value); - -/// -// Clear the string map. -/// -CEF_EXPORT void cef_string_map_clear(cef_string_map_t map); - -/// -// Free the string map. -/// -CEF_EXPORT void cef_string_map_free(cef_string_map_t map); - - -#ifdef __cplusplus -} -#endif - -#endif // CEF_INCLUDE_INTERNAL_CEF_STRING_MAP_H_ diff --git a/cefpython/cef1/include/internal/cef_string_multimap.h b/cefpython/cef1/include/internal/cef_string_multimap.h deleted file mode 100644 index cd3904244..000000000 --- a/cefpython/cef1/include/internal/cef_string_multimap.h +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CEF_INCLUDE_INTERNAL_CEF_STRING_MULTIMAP_H_ -#define CEF_INCLUDE_INTERNAL_CEF_STRING_MULTIMAP_H_ -#pragma once - -#include "include/internal/cef_export.h" -#include "include/internal/cef_string.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/// -// CEF string multimaps are a set of key/value string pairs. -// More than one value can be assigned to a single key. -/// -typedef void* cef_string_multimap_t; - -/// -// Allocate a new string multimap. -/// -CEF_EXPORT cef_string_multimap_t cef_string_multimap_alloc(); - -/// -// Return the number of elements in the string multimap. -/// -CEF_EXPORT int cef_string_multimap_size(cef_string_multimap_t map); - -/// -// Return the number of values with the specified key. -/// -CEF_EXPORT int cef_string_multimap_find_count(cef_string_multimap_t map, - const cef_string_t* key); - -/// -// Return the value_index-th value with the specified key. -/// -CEF_EXPORT int cef_string_multimap_enumerate(cef_string_multimap_t map, - const cef_string_t* key, - int value_index, - cef_string_t* value); - -/// -// Return the key at the specified zero-based string multimap index. -/// -CEF_EXPORT int cef_string_multimap_key(cef_string_multimap_t map, int index, - cef_string_t* key); - -/// -// Return the value at the specified zero-based string multimap index. -/// -CEF_EXPORT int cef_string_multimap_value(cef_string_multimap_t map, int index, - cef_string_t* value); - -/// -// Append a new key/value pair at the end of the string multimap. -/// -CEF_EXPORT int cef_string_multimap_append(cef_string_multimap_t map, - const cef_string_t* key, - const cef_string_t* value); - -/// -// Clear the string multimap. -/// -CEF_EXPORT void cef_string_multimap_clear(cef_string_multimap_t map); - -/// -// Free the string multimap. -/// -CEF_EXPORT void cef_string_multimap_free(cef_string_multimap_t map); - - -#ifdef __cplusplus -} -#endif - -#endif // CEF_INCLUDE_INTERNAL_CEF_STRING_MULTIMAP_H_ diff --git a/cefpython/cef1/include/internal/cef_string_types.h b/cefpython/cef1/include/internal/cef_string_types.h deleted file mode 100644 index 7ab6671cb..000000000 --- a/cefpython/cef1/include/internal/cef_string_types.h +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright (c) 2010 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CEF_INCLUDE_INTERNAL_CEF_STRING_TYPES_H_ -#define CEF_INCLUDE_INTERNAL_CEF_STRING_TYPES_H_ -#pragma once - -// CEF provides functions for converting between UTF-8, -16 and -32 strings. -// CEF string types are safe for reading from multiple threads but not for -// modification. It is the user's responsibility to provide synchronization if -// modifying CEF strings from multiple threads. - -#ifdef __cplusplus -extern "C" { -#endif - -#include "include/internal/cef_build.h" -#include "include/internal/cef_export.h" -#include - -// CEF character type definitions. wchar_t is 2 bytes on Windows and 4 bytes on -// most other platforms. - -#if defined(OS_WIN) -typedef wchar_t char16; -#else // !OS_WIN -typedef unsigned short char16; // NOLINT (runtime/int) -#ifndef WCHAR_T_IS_UTF32 -#define WCHAR_T_IS_UTF32 -#endif // WCHAR_T_IS_UTF32 -#endif // !OS_WIN - - -// CEF string type definitions. Whomever allocates |str| is responsible for -// providing an appropriate |dtor| implementation that will free the string in -// the same memory space. When reusing an existing string structure make sure -// to call |dtor| for the old value before assigning new |str| and |dtor| -// values. Static strings will have a NULL |dtor| value. Using the below -// functions if you want this managed for you. - -typedef struct _cef_string_wide_t { - wchar_t* str; - size_t length; - void (*dtor)(wchar_t* str); -} cef_string_wide_t; - -typedef struct _cef_string_utf8_t { - char* str; - size_t length; - void (*dtor)(char* str); -} cef_string_utf8_t; - -typedef struct _cef_string_utf16_t { - char16* str; - size_t length; - void (*dtor)(char16* str); -} cef_string_utf16_t; - - -/// -// These functions set string values. If |copy| is true (1) the value will be -// copied instead of referenced. It is up to the user to properly manage -// the lifespan of references. -/// - -CEF_EXPORT int cef_string_wide_set(const wchar_t* src, size_t src_len, - cef_string_wide_t* output, int copy); -CEF_EXPORT int cef_string_utf8_set(const char* src, size_t src_len, - cef_string_utf8_t* output, int copy); -CEF_EXPORT int cef_string_utf16_set(const char16* src, size_t src_len, - cef_string_utf16_t* output, int copy); - - -/// -// Convenience macros for copying values. -/// - -#define cef_string_wide_copy(src, src_len, output) \ - cef_string_wide_set(src, src_len, output, true) -#define cef_string_utf8_copy(src, src_len, output) \ - cef_string_utf8_set(src, src_len, output, true) -#define cef_string_utf16_copy(src, src_len, output) \ - cef_string_utf16_set(src, src_len, output, true) - - -/// -// These functions clear string values. The structure itself is not freed. -/// - -CEF_EXPORT void cef_string_wide_clear(cef_string_wide_t* str); -CEF_EXPORT void cef_string_utf8_clear(cef_string_utf8_t* str); -CEF_EXPORT void cef_string_utf16_clear(cef_string_utf16_t* str); - - -/// -// These functions compare two string values with the same results as strcmp(). -/// - -CEF_EXPORT int cef_string_wide_cmp(const cef_string_wide_t* str1, - const cef_string_wide_t* str2); -CEF_EXPORT int cef_string_utf8_cmp(const cef_string_utf8_t* str1, - const cef_string_utf8_t* str2); -CEF_EXPORT int cef_string_utf16_cmp(const cef_string_utf16_t* str1, - const cef_string_utf16_t* str2); - - -/// -// These functions convert between UTF-8, -16, and -32 strings. They are -// potentially slow so unnecessary conversions should be avoided. The best -// possible result will always be written to |output| with the boolean return -// value indicating whether the conversion is 100% valid. -/// - -CEF_EXPORT int cef_string_wide_to_utf8(const wchar_t* src, size_t src_len, - cef_string_utf8_t* output); -CEF_EXPORT int cef_string_utf8_to_wide(const char* src, size_t src_len, - cef_string_wide_t* output); - -CEF_EXPORT int cef_string_wide_to_utf16(const wchar_t* src, size_t src_len, - cef_string_utf16_t* output); -CEF_EXPORT int cef_string_utf16_to_wide(const char16* src, size_t src_len, - cef_string_wide_t* output); - -CEF_EXPORT int cef_string_utf8_to_utf16(const char* src, size_t src_len, - cef_string_utf16_t* output); -CEF_EXPORT int cef_string_utf16_to_utf8(const char16* src, size_t src_len, - cef_string_utf8_t* output); - - -/// -// These functions convert an ASCII string, typically a hardcoded constant, to a -// Wide/UTF16 string. Use instead of the UTF8 conversion routines if you know -// the string is ASCII. -/// - -CEF_EXPORT int cef_string_ascii_to_wide(const char* src, size_t src_len, - cef_string_wide_t* output); -CEF_EXPORT int cef_string_ascii_to_utf16(const char* src, size_t src_len, - cef_string_utf16_t* output); - - - -/// -// It is sometimes necessary for the system to allocate string structures with -// the expectation that the user will free them. The userfree types act as a -// hint that the user is responsible for freeing the structure. -/// - -typedef cef_string_wide_t* cef_string_userfree_wide_t; -typedef cef_string_utf8_t* cef_string_userfree_utf8_t; -typedef cef_string_utf16_t* cef_string_userfree_utf16_t; - - -/// -// These functions allocate a new string structure. They must be freed by -// calling the associated free function. -/// - -CEF_EXPORT cef_string_userfree_wide_t cef_string_userfree_wide_alloc(); -CEF_EXPORT cef_string_userfree_utf8_t cef_string_userfree_utf8_alloc(); -CEF_EXPORT cef_string_userfree_utf16_t cef_string_userfree_utf16_alloc(); - - -/// -// These functions free the string structure allocated by the associated -// alloc function. Any string contents will first be cleared. -/// - -CEF_EXPORT void cef_string_userfree_wide_free(cef_string_userfree_wide_t str); -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); - - -#ifdef __cplusplus -} -#endif - -#endif // CEF_INCLUDE_INTERNAL_CEF_STRING_TYPES_H_ diff --git a/cefpython/cef1/include/internal/cef_string_wrappers.h b/cefpython/cef1/include/internal/cef_string_wrappers.h deleted file mode 100644 index b3012331b..000000000 --- a/cefpython/cef1/include/internal/cef_string_wrappers.h +++ /dev/null @@ -1,712 +0,0 @@ -// Copyright (c) 2010 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CEF_INCLUDE_INTERNAL_CEF_STRING_WRAPPERS_H_ -#define CEF_INCLUDE_INTERNAL_CEF_STRING_WRAPPERS_H_ -#pragma once - -#include -#include -#include "include/internal/cef_string_types.h" - -#ifdef BUILDING_CEF_SHARED -#include "base/string16.h" -#endif - - -/// -// Traits implementation for wide character strings. -/// -struct CefStringTraitsWide { - typedef wchar_t char_type; - typedef cef_string_wide_t struct_type; - typedef cef_string_userfree_wide_t userfree_struct_type; - - static inline void clear(struct_type *s) { cef_string_wide_clear(s); } - static inline int set(const char_type* src, size_t src_size, - struct_type* output, int copy) { - return cef_string_wide_set(src, src_size, output, copy); - } - static inline int compare(const struct_type* s1, const struct_type* s2) { - return cef_string_wide_cmp(s1, s2); - } - static inline userfree_struct_type userfree_alloc() { - return cef_string_userfree_wide_alloc(); - } - static inline void userfree_free(userfree_struct_type ufs) { - return cef_string_userfree_wide_free(ufs); - } - - // Conversion methods. - static inline bool from_ascii(const char* str, size_t len, struct_type *s) { - return cef_string_ascii_to_wide(str, len, s) ? true : false; - } - static inline std::string to_string(const struct_type *s) { - cef_string_utf8_t cstr; - memset(&cstr, 0, sizeof(cstr)); - cef_string_wide_to_utf8(s->str, s->length, &cstr); - std::string str; - if (cstr.length > 0) - str = std::string(cstr.str, cstr.length); - cef_string_utf8_clear(&cstr); - return str; - } - static inline bool from_string(const std::string& str, struct_type *s) { - return cef_string_utf8_to_wide(str.c_str(), str.length(), s) ? true : false; - } - static inline std::wstring to_wstring(const struct_type *s) { - return std::wstring(s->str, s->length); - } - static inline bool from_wstring(const std::wstring& str, struct_type *s) { - return cef_string_wide_set(str.c_str(), str.length(), s, true) ? - true : false; - } -#if defined(BUILDING_CEF_SHARED) -#if defined(WCHAR_T_IS_UTF32) - static inline string16 to_string16(const struct_type *s) { - cef_string_utf16_t cstr; - memset(&cstr, 0, sizeof(cstr)); - cef_string_wide_to_utf16(s->str, s->length, &cstr); - string16 str; - if (cstr.length > 0) - str = string16(cstr.str, cstr.length); - cef_string_utf16_clear(&cstr); - return str; - } - static inline bool from_string16(const string16& str, struct_type *s) { - return cef_string_utf16_to_wide(str.c_str(), str.length(), s) ? - true : false; - } -#else // WCHAR_T_IS_UTF32 - static inline string16 to_string16(const struct_type *s) { - return string16(s->str, s->length); - } - static inline bool from_string16(const string16& str, struct_type *s) { - return cef_string_wide_set(str.c_str(), str.length(), s, true) ? - true : false; - } -#endif // WCHAR_T_IS_UTF32 -#endif // BUILDING_CEF_SHARED -}; - -/// -// Traits implementation for utf8 character strings. -/// -struct CefStringTraitsUTF8 { - typedef char char_type; - typedef cef_string_utf8_t struct_type; - typedef cef_string_userfree_utf8_t userfree_struct_type; - - static inline void clear(struct_type *s) { cef_string_utf8_clear(s); } - static inline int set(const char_type* src, size_t src_size, - struct_type* output, int copy) { - return cef_string_utf8_set(src, src_size, output, copy); - } - static inline int compare(const struct_type* s1, const struct_type* s2) { - return cef_string_utf8_cmp(s1, s2); - } - static inline userfree_struct_type userfree_alloc() { - return cef_string_userfree_utf8_alloc(); - } - static inline void userfree_free(userfree_struct_type ufs) { - return cef_string_userfree_utf8_free(ufs); - } - - // Conversion methods. - static inline bool from_ascii(const char* str, size_t len, struct_type* s) { - return cef_string_utf8_copy(str, len, s) ? true : false; - } - static inline std::string to_string(const struct_type* s) { - return std::string(s->str, s->length); - } - static inline bool from_string(const std::string& str, struct_type* s) { - return cef_string_utf8_copy(str.c_str(), str.length(), s) ? true : false; - } - static inline std::wstring to_wstring(const struct_type* s) { - cef_string_wide_t cstr; - memset(&cstr, 0, sizeof(cstr)); - cef_string_utf8_to_wide(s->str, s->length, &cstr); - std::wstring str; - if (cstr.length > 0) - str = std::wstring(cstr.str, cstr.length); - cef_string_wide_clear(&cstr); - return str; - } - static inline bool from_wstring(const std::wstring& str, struct_type* s) { - return cef_string_wide_to_utf8(str.c_str(), str.length(), s) ? true : false; - } -#if defined(BUILDING_CEF_SHARED) - static inline string16 to_string16(const struct_type* s) { - cef_string_utf16_t cstr; - memset(&cstr, 0, sizeof(cstr)); - cef_string_utf8_to_utf16(s->str, s->length, &cstr); - string16 str; - if (cstr.length > 0) - str = string16(cstr.str, cstr.length); - cef_string_utf16_clear(&cstr); - return str; - } - static inline bool from_string16(const string16& str, struct_type* s) { - return cef_string_utf16_to_utf8(str.c_str(), str.length(), s) ? - true : false; - } -#endif // BUILDING_CEF_SHARED -}; - -/// -// Traits implementation for utf16 character strings. -/// -struct CefStringTraitsUTF16 { - typedef char16 char_type; - typedef cef_string_utf16_t struct_type; - typedef cef_string_userfree_utf16_t userfree_struct_type; - - static inline void clear(struct_type *s) { cef_string_utf16_clear(s); } - static inline int set(const char_type* src, size_t src_size, - struct_type* output, int copy) { - return cef_string_utf16_set(src, src_size, output, copy); - } - static inline int compare(const struct_type* s1, const struct_type* s2) { - return cef_string_utf16_cmp(s1, s2); - } - static inline userfree_struct_type userfree_alloc() { - return cef_string_userfree_utf16_alloc(); - } - static inline void userfree_free(userfree_struct_type ufs) { - return cef_string_userfree_utf16_free(ufs); - } - - // Conversion methods. - static inline bool from_ascii(const char* str, size_t len, struct_type* s) { - return cef_string_ascii_to_utf16(str, len, s) ? true : false; - } - static inline std::string to_string(const struct_type* s) { - cef_string_utf8_t cstr; - memset(&cstr, 0, sizeof(cstr)); - cef_string_utf16_to_utf8(s->str, s->length, &cstr); - std::string str; - if (cstr.length > 0) - str = std::string(cstr.str, cstr.length); - cef_string_utf8_clear(&cstr); - return str; - } - static inline bool from_string(const std::string& str, struct_type* s) { - return cef_string_utf8_to_utf16(str.c_str(), str.length(), s) ? - true : false; - } -#if defined(WCHAR_T_IS_UTF32) - static inline std::wstring to_wstring(const struct_type* s) { - cef_string_wide_t cstr; - memset(&cstr, 0, sizeof(cstr)); - cef_string_utf16_to_wide(s->str, s->length, &cstr); - std::wstring str; - if (cstr.length > 0) - str = std::wstring(cstr.str, cstr.length); - cef_string_wide_clear(&cstr); - return str; - } - static inline bool from_wstring(const std::wstring& str, struct_type* s) { - return cef_string_wide_to_utf16(str.c_str(), str.length(), s) ? - true : false; - } -#else // WCHAR_T_IS_UTF32 - static inline std::wstring to_wstring(const struct_type* s) { - return std::wstring(s->str, s->length); - } - static inline bool from_wstring(const std::wstring& str, struct_type* s) { - return cef_string_utf16_set(str.c_str(), str.length(), s, true) ? - true : false; - } -#endif // WCHAR_T_IS_UTF32 -#if defined(BUILDING_CEF_SHARED) - static inline string16 to_string16(const struct_type* s) { - return string16(s->str, s->length); - } - static inline bool from_string16(const string16& str, struct_type* s) { - return cef_string_utf16_set(str.c_str(), str.length(), s, true) ? - true : false; - } -#endif // BUILDING_CEF_SHARED -}; - -/// -// CEF string classes can convert between all supported string types. For -// example, the CefStringWide class uses wchar_t as the underlying character -// type and provides two approaches for converting data to/from a UTF8 string -// (std::string). -//

-// 1. Implicit conversion using the assignment operator overload. -//

-//   CefStringWide aCefString;
-//   std::string aUTF8String;
-//   aCefString = aUTF8String; // Assign std::string to CefStringWide
-//   aUTF8String = aCefString; // Assign CefStringWide to std::string
-// 
-// 2. Explicit conversion using the FromString/ToString methods. -//
-//   CefStringWide aCefString;
-//   std::string aUTF8String;
-//   aCefString.FromString(aUTF8String); // Assign std::string to CefStringWide
-//   aUTF8String = aCefString.ToString(); // Assign CefStringWide to std::string
-// 
-// Conversion will only occur if the assigned value is a different string type. -// Assigning a std::string to a CefStringUTF8, for example, will copy the data -// without performing a conversion. -//

-// CEF string classes are safe for reading from multiple threads but not for -// modification. It is the user's responsibility to provide synchronization if -// modifying CEF strings from multiple threads. -/// -template -class CefStringBase { - public: - typedef typename traits::char_type char_type; - typedef typename traits::struct_type struct_type; - typedef typename traits::userfree_struct_type userfree_struct_type; - - /// - // Default constructor. - /// - CefStringBase() : string_(NULL), owner_(false) {} - - /// - // Create a new string from an existing string. Data will always be copied. - /// - CefStringBase(const CefStringBase& str) - : string_(NULL), owner_(false) { - FromString(str.c_str(), str.length(), true); - } - - /// - // Create a new string from an existing std::string. Data will be always - // copied. Translation will occur if necessary based on the underlying string - // type. - /// - CefStringBase(const std::string& src) // NOLINT(runtime/explicit) - : string_(NULL), owner_(false) { - FromString(src); - } - CefStringBase(const char* src) // NOLINT(runtime/explicit) - : string_(NULL), owner_(false) { - if (src) - FromString(std::string(src)); - } - - /// - // Create a new string from an existing std::wstring. Data will be always - // copied. Translation will occur if necessary based on the underlying string - // type. - /// - CefStringBase(const std::wstring& src) // NOLINT(runtime/explicit) - : string_(NULL), owner_(false) { - FromWString(src); - } - CefStringBase(const wchar_t* src) // NOLINT(runtime/explicit) - : string_(NULL), owner_(false) { - if (src) - FromWString(std::wstring(src)); - } - -#if (defined(BUILDING_CEF_SHARED) && defined(WCHAR_T_IS_UTF32)) - /// - // Create a new string from an existing string16. Data will be always - // copied. Translation will occur if necessary based on the underlying string - // type. - /// - CefStringBase(const string16& src) // NOLINT(runtime/explicit) - : string_(NULL), owner_(false) { - FromString16(src); - } - CefStringBase(const char16* src) // NOLINT(runtime/explicit) - : string_(NULL), owner_(false) { - if (src) - FromString16(string16(src)); - } -#endif // BUILDING_CEF_SHARED && WCHAR_T_IS_UTF32 - - /// - // Create a new string from an existing character array. If |copy| is true - // this class will copy the data. Otherwise, this class will reference the - // existing data. Referenced data must exist for the lifetime of this class - // and will not be freed by this class. - /// - CefStringBase(const char_type* src, size_t src_len, bool copy) - : string_(NULL), owner_(false) { - if (src && src_len > 0) - FromString(src, src_len, copy); - } - - /// - // Create a new string referencing an existing string structure without taking - // ownership. Referenced structures must exist for the lifetime of this class - // and will not be freed by this class. - /// - CefStringBase(const struct_type* src) // NOLINT(runtime/explicit) - : string_(NULL), owner_(false) { - if (!src) - return; - // Reference the existing structure without taking ownership. - Attach(const_cast(src), false); - } - - virtual ~CefStringBase() { ClearAndFree(); } - - - // The following methods are named for compatibility with the standard library - // string template types. - - /// - // Return a read-only pointer to the string data. - /// - const char_type* c_str() const { return (string_ ? string_->str : NULL); } - - /// - // Return the length of the string data. - /// - size_t length() const { return (string_ ? string_->length : 0); } - - /// - // Return the length of the string data. - /// - inline size_t size() const { return length(); } - - /// - // Returns true if the string is empty. - /// - bool empty() const { return (string_ == NULL || string_->length == 0); } - - /// - // Compare this string to the specified string. - /// - int compare(const CefStringBase& str) const { - if (empty() && str.empty()) - return 0; - if (empty()) - return -1; - if (str.empty()) - return 1; - return traits::compare(string_, str.GetStruct()); - } - - /// - // Clear the string data. - /// - void clear() { - if (string_) - traits::clear(string_); - } - - - // The following methods are unique to CEF string template types. - - /// - // Returns true if this class owns the underlying string structure. - /// - bool IsOwner() const { return owner_; } - - /// - // Returns a read-only pointer to the underlying string structure. May return - // NULL if no structure is currently allocated. - /// - const struct_type* GetStruct() const { return string_; } - - /// - // Returns a writable pointer to the underlying string structure. Will never - // return NULL. - /// - struct_type* GetWritableStruct() { - AllocIfNeeded(); - return string_; - } - - /// - // Clear the state of this class. The underlying string structure and data - // will be freed if this class owns the structure. - /// - void ClearAndFree() { - if (!string_) - return; - if (owner_) { - clear(); - delete string_; - } - string_ = NULL; - owner_ = false; - } - - /// - // Attach to the specified string structure. If |owner| is true this class - // will take ownership of the structure. - /// - void Attach(struct_type* str, bool owner) { - // Free the previous structure and data, if any. - ClearAndFree(); - - string_ = str; - owner_ = owner; - } - - /// - // Take ownership of the specified userfree structure's string data. The - // userfree structure itself will be freed. Only use this method with userfree - // structures. - /// - void AttachToUserFree(userfree_struct_type str) { - // Free the previous structure and data, if any. - ClearAndFree(); - - if (!str) - return; - - AllocIfNeeded(); - owner_ = true; - memcpy(string_, str, sizeof(struct_type)); - - // Free the |str| structure but not the data. - memset(str, 0, sizeof(struct_type)); - traits::userfree_free(str); - } - - /// - // Detach from the underlying string structure. To avoid memory leaks only use - // this method if you already hold a pointer to the underlying string - // structure. - /// - void Detach() { - string_ = NULL; - owner_ = false; - } - - /// - // Create a userfree structure and give it ownership of this class' string - // data. This class will be disassociated from the data. May return NULL if - // this string class currently contains no data. - /// - userfree_struct_type DetachToUserFree() { - if (empty()) - return NULL; - - userfree_struct_type str = traits::userfree_alloc(); - memcpy(str, string_, sizeof(struct_type)); - - // Free this class' structure but not the data. - memset(string_, 0, sizeof(struct_type)); - ClearAndFree(); - - return str; - } - - /// - // Set this string's data to the specified character array. If |copy| is true - // this class will copy the data. Otherwise, this class will reference the - // existing data. Referenced data must exist for the lifetime of this class - // and will not be freed by this class. - /// - bool FromString(const char_type* src, size_t src_len, bool copy) { - if (src == NULL || src_len == 0) { - clear(); - return true; - } - AllocIfNeeded(); - return traits::set(src, src_len, string_, copy) ? true : false; - } - - /// - // Set this string's data from an existing ASCII string. Data will be always - // copied. Translation will occur if necessary based on the underlying string - // type. - /// - bool FromASCII(const char* str) { - size_t len = str ? strlen(str) : 0; - if (len == 0) { - clear(); - return true; - } - AllocIfNeeded(); - return traits::from_ascii(str, len, string_); - } - - /// - // Return this string's data as a std::string. Translation will occur if - // necessary based on the underlying string type. - /// - std::string ToString() const { - if (empty()) - return std::string(); - return traits::to_string(string_); - } - - /// - // Set this string's data from an existing std::string. Data will be always - // copied. Translation will occur if necessary based on the underlying string - // type. - /// - bool FromString(const std::string& str) { - if (str.empty()) { - clear(); - return true; - } - AllocIfNeeded(); - return traits::from_string(str, string_); - } - - /// - // Return this string's data as a std::wstring. Translation will occur if - // necessary based on the underlying string type. - /// - std::wstring ToWString() const { - if (empty()) - return std::wstring(); - return traits::to_wstring(string_); - } - - /// - // Set this string's data from an existing std::wstring. Data will be always - // copied. Translation will occur if necessary based on the underlying string - // type. - /// - bool FromWString(const std::wstring& str) { - if (str.empty()) { - clear(); - return true; - } - AllocIfNeeded(); - return traits::from_wstring(str, string_); - } -#if defined(BUILDING_CEF_SHARED) - /// - // Return this string's data as a string16. Translation will occur if - // necessary based on the underlying string type. - /// - string16 ToString16() const { - if (empty()) - return string16(); - return traits::to_string16(string_); - } - - /// - // Set this string's data from an existing string16. Data will be always - // copied. Translation will occur if necessary based on the underlying string - // type. - /// - bool FromString16(const string16& str) { - if (str.empty()) { - clear(); - return true; - } - AllocIfNeeded(); - return traits::from_string16(str, string_); - } -#endif // BUILDING_CEF_SHARED - - /// - // Comparison operator overloads. - /// - bool operator<(const CefStringBase& str) const { - return (compare(str) < 0); - } - bool operator<=(const CefStringBase& str) const { - return (compare(str) <= 0); - } - bool operator>(const CefStringBase& str) const { - return (compare(str) > 0); - } - bool operator>=(const CefStringBase& str) const { - return (compare(str) >= 0); - } - bool operator==(const CefStringBase& str) const { - return (compare(str) == 0); - } - bool operator!=(const CefStringBase& str) const { - return (compare(str) != 0); - } - - /// - // Assignment operator overloads. - /// - CefStringBase& operator=(const CefStringBase& str) { - FromString(str.c_str(), str.length(), true); - return *this; - } - operator std::string() const { - return ToString(); - } - CefStringBase& operator=(const std::string& str) { - FromString(str); - return *this; - } - CefStringBase& operator=(const char* str) { - FromString(std::string(str)); - return *this; - } - operator std::wstring() const { - return ToWString(); - } - CefStringBase& operator=(const std::wstring& str) { - FromWString(str); - return *this; - } - CefStringBase& operator=(const wchar_t* str) { - FromWString(std::wstring(str)); - return *this; - } -#if (defined(BUILDING_CEF_SHARED) && defined(WCHAR_T_IS_UTF32)) - operator string16() const { - return ToString16(); - } - CefStringBase& operator=(const string16& str) { - FromString16(str); - return *this; - } - CefStringBase& operator=(const char16* str) { - FromString16(string16(str)); - return *this; - } -#endif // BUILDING_CEF_SHARED && WCHAR_T_IS_UTF32 - - private: - // Allocate the string structure if it doesn't already exist. - void AllocIfNeeded() { - if (string_ == NULL) { - string_ = new struct_type; - memset(string_, 0, sizeof(struct_type)); - owner_ = true; - } - } - - struct_type* string_; - bool owner_; -}; - - -typedef CefStringBase CefStringWide; -typedef CefStringBase CefStringUTF8; -typedef CefStringBase CefStringUTF16; - -#endif // CEF_INCLUDE_INTERNAL_CEF_STRING_WRAPPERS_H_ diff --git a/cefpython/cef1/include/internal/cef_time.h b/cefpython/cef1/include/internal/cef_time.h deleted file mode 100644 index 64e601fe0..000000000 --- a/cefpython/cef1/include/internal/cef_time.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CEF_INCLUDE_INTERNAL_CEF_TIME_H_ -#define CEF_INCLUDE_INTERNAL_CEF_TIME_H_ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include "include/internal/cef_export.h" -#include - -/// -// Time information. Values should always be in UTC. -/// -typedef struct _cef_time_t { - int year; // Four digit year "2007" - int month; // 1-based month (values 1 = January, etc.) - int day_of_week; // 0-based day of week (0 = Sunday, etc.) - int day_of_month; // 1-based day of month (1-31) - int hour; // Hour within the current day (0-23) - int minute; // Minute within the current hour (0-59) - int second; // Second within the current minute (0-59 plus leap - // seconds which may take it up to 60). - int millisecond; // Milliseconds within the current second (0-999) -} cef_time_t; - -/// -// Converts cef_time_t to/from time_t. Returns true (1) on success and false (0) -// on failure. -/// -CEF_EXPORT int cef_time_to_timet(const cef_time_t* cef_time, time_t* time); -CEF_EXPORT int cef_time_from_timet(time_t time, cef_time_t* cef_time); - -/// -// Converts cef_time_t to/from a double which is the number of seconds since -// epoch (Jan 1, 1970). Webkit uses this format to represent time. A value of 0 -// means "not initialized". Returns true (1) on success and false (0) on -// failure. -/// -CEF_EXPORT int cef_time_to_doublet(const cef_time_t* cef_time, double* time); -CEF_EXPORT int cef_time_from_doublet(double time, cef_time_t* cef_time); - -/// -// Retrieve the current system time. -// -CEF_EXPORT int cef_time_now(cef_time_t* cef_time); - -/// -// Retrieve the delta in milliseconds between two time values. -// -CEF_EXPORT int cef_time_delta(const cef_time_t* cef_time1, - const cef_time_t* cef_time2, - long long* delta); - -#ifdef __cplusplus -} -#endif - -#endif // CEF_INCLUDE_INTERNAL_CEF_TIME_H_ diff --git a/cefpython/cef1/include/internal/cef_tuple.h b/cefpython/cef1/include/internal/cef_tuple.h deleted file mode 100644 index d9a1a2c96..000000000 --- a/cefpython/cef1/include/internal/cef_tuple.h +++ /dev/null @@ -1,1082 +0,0 @@ -// Copyright (c) 2006-2011 Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// The contents of this file are identical to base/tuple.h - -// A Tuple is a generic templatized container, similar in concept to std::pair. -// There are classes Tuple0 to Tuple6, cooresponding to the number of elements -// it contains. The convenient MakeTuple() function takes 0 to 6 arguments, -// and will construct and return the appropriate Tuple object. The functions -// DispatchToMethod and DispatchToFunction take a function pointer or instance -// and method pointer, and unpack a tuple into arguments to the call. -// -// Tuple elements are copied by value, and stored in the tuple. See the unit -// tests for more details of how/when the values are copied. -// -// Example usage: -// // These two methods of creating a Tuple are identical. -// Tuple2 tuple_a(1, "wee"); -// Tuple2 tuple_b = MakeTuple(1, "wee"); -// -// void SomeFunc(int a, const char* b) { } -// DispatchToFunction(&SomeFunc, tuple_a); // SomeFunc(1, "wee") -// DispatchToFunction( -// &SomeFunc, MakeTuple(10, "foo")); // SomeFunc(10, "foo") -// -// struct { void SomeMeth(int a, int b, int c) { } } foo; -// DispatchToMethod(&foo, &Foo::SomeMeth, MakeTuple(1, 2, 3)); -// // foo->SomeMeth(1, 2, 3); - -#ifndef CEF_INCLUDE_INTERNAL_CEF_TUPLE_H_ -#define CEF_INCLUDE_INTERNAL_CEF_TUPLE_H_ -#pragma once - -#if defined(OS_CHROMEOS) -// To troubleshoot crosbug.com/7327. -#include "base/logging.h" -#endif -// Traits ---------------------------------------------------------------------- -// -// A simple traits class for tuple arguments. -// -// ValueType: the bare, nonref version of a type (same as the type for nonrefs). -// RefType: the ref version of a type (same as the type for refs). -// ParamType: what type to pass to functions (refs should not be constified). - -template -struct TupleTraits { - typedef P ValueType; - typedef P& RefType; - typedef const P& ParamType; -}; - -template -struct TupleTraits { - typedef P ValueType; - typedef P& RefType; - typedef P& ParamType; -}; - -template -struct TupleTypes { }; - -// Tuple ----------------------------------------------------------------------- -// -// This set of classes is useful for bundling 0 or more heterogeneous data types -// into a single variable. The advantage of this is that it greatly simplifies -// function objects that need to take an arbitrary number of parameters; see -// RunnableMethod and IPC::MessageWithTuple. -// -// Tuple0 is supplied to act as a 'void' type. It can be used, for example, -// when dispatching to a function that accepts no arguments (see the -// Dispatchers below). -// Tuple1 is rarely useful. One such use is when A is non-const ref that you -// want filled by the dispatchee, and the tuple is merely a container for that -// output (a "tier"). See MakeRefTuple and its usages. - -struct Tuple0 { - typedef Tuple0 ValueTuple; - typedef Tuple0 RefTuple; - typedef Tuple0 ParamTuple; -}; - -template -struct Tuple1 { - public: - typedef A TypeA; - - Tuple1() {} - explicit Tuple1(typename TupleTraits::ParamType a) : a(a) {} - - A a; -}; - -template -struct Tuple2 { - public: - typedef A TypeA; - typedef B TypeB; - - Tuple2() {} - Tuple2(typename TupleTraits::ParamType a, - typename TupleTraits::ParamType b) - : a(a), b(b) { - } - - A a; - B b; -}; - -template -struct Tuple3 { - public: - typedef A TypeA; - typedef B TypeB; - typedef C TypeC; - - Tuple3() {} - Tuple3(typename TupleTraits::ParamType a, - typename TupleTraits::ParamType b, - typename TupleTraits::ParamType c) - : a(a), b(b), c(c) { - } - - A a; - B b; - C c; -}; - -template -struct Tuple4 { - public: - typedef A TypeA; - typedef B TypeB; - typedef C TypeC; - typedef D TypeD; - - Tuple4() {} - Tuple4(typename TupleTraits::ParamType a, - typename TupleTraits::ParamType b, - typename TupleTraits::ParamType c, - typename TupleTraits::ParamType d) - : a(a), b(b), c(c), d(d) { - } - - A a; - B b; - C c; - D d; -}; - -template -struct Tuple5 { - public: - typedef A TypeA; - typedef B TypeB; - typedef C TypeC; - typedef D TypeD; - typedef E TypeE; - - Tuple5() {} - Tuple5(typename TupleTraits::ParamType a, - typename TupleTraits::ParamType b, - typename TupleTraits::ParamType c, - typename TupleTraits::ParamType d, - typename TupleTraits::ParamType e) - : a(a), b(b), c(c), d(d), e(e) { - } - - A a; - B b; - C c; - D d; - E e; -}; - -template -struct Tuple6 { - public: - typedef A TypeA; - typedef B TypeB; - typedef C TypeC; - typedef D TypeD; - typedef E TypeE; - typedef F TypeF; - - Tuple6() {} - Tuple6(typename TupleTraits::ParamType a, - typename TupleTraits::ParamType b, - typename TupleTraits::ParamType c, - typename TupleTraits::ParamType d, - typename TupleTraits::ParamType e, - typename TupleTraits::ParamType f) - : a(a), b(b), c(c), d(d), e(e), f(f) { - } - - A a; - B b; - C c; - D d; - E e; - F f; -}; - -template -struct Tuple7 { - public: - typedef A TypeA; - typedef B TypeB; - typedef C TypeC; - typedef D TypeD; - typedef E TypeE; - typedef F TypeF; - typedef G TypeG; - - Tuple7() {} - Tuple7(typename TupleTraits::ParamType a, - typename TupleTraits::ParamType b, - typename TupleTraits::ParamType c, - typename TupleTraits::ParamType d, - typename TupleTraits::ParamType e, - typename TupleTraits::ParamType f, - typename TupleTraits::ParamType g) - : a(a), b(b), c(c), d(d), e(e), f(f), g(g) { - } - - A a; - B b; - C c; - D d; - E e; - F f; - G g; -}; - -template -struct Tuple8 { - public: - typedef A TypeA; - typedef B TypeB; - typedef C TypeC; - typedef D TypeD; - typedef E TypeE; - typedef F TypeF; - typedef G TypeG; - typedef H TypeH; - - Tuple8() {} - Tuple8(typename TupleTraits::ParamType a, - typename TupleTraits::ParamType b, - typename TupleTraits::ParamType c, - typename TupleTraits::ParamType d, - typename TupleTraits::ParamType e, - typename TupleTraits::ParamType f, - typename TupleTraits::ParamType g, - typename TupleTraits::ParamType h) - : a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h) { - } - - A a; - B b; - C c; - D d; - E e; - F f; - G g; - H h; -}; - -// Tuple types ---------------------------------------------------------------- -// -// Allows for selection of ValueTuple/RefTuple/ParamTuple without needing the -// definitions of class types the tuple takes as parameters. - -template <> -struct TupleTypes< Tuple0 > { - typedef Tuple0 ValueTuple; - typedef Tuple0 RefTuple; - typedef Tuple0 ParamTuple; -}; - -template -struct TupleTypes< Tuple1 > { - typedef Tuple1::ValueType> ValueTuple; - typedef Tuple1::RefType> RefTuple; - typedef Tuple1::ParamType> ParamTuple; -}; - -template -struct TupleTypes< Tuple2 > { - typedef Tuple2::ValueType, - typename TupleTraits::ValueType> ValueTuple; -typedef Tuple2::RefType, - typename TupleTraits::RefType> RefTuple; - typedef Tuple2::ParamType, - typename TupleTraits::ParamType> ParamTuple; -}; - -template -struct TupleTypes< Tuple3 > { - typedef Tuple3::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType> ValueTuple; -typedef Tuple3::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType> RefTuple; - typedef Tuple3::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType> ParamTuple; -}; - -template -struct TupleTypes< Tuple4 > { - typedef Tuple4::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType> ValueTuple; -typedef Tuple4::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType> RefTuple; - typedef Tuple4::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType> ParamTuple; -}; - -template -struct TupleTypes< Tuple5 > { - typedef Tuple5::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType> ValueTuple; -typedef Tuple5::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType> RefTuple; - typedef Tuple5::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType> ParamTuple; -}; - -template -struct TupleTypes< Tuple6 > { - typedef Tuple6::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType> ValueTuple; -typedef Tuple6::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType> RefTuple; - typedef Tuple6::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType> ParamTuple; -}; - -template -struct TupleTypes< Tuple7 > { - typedef Tuple7::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType> ValueTuple; -typedef Tuple7::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType> RefTuple; - typedef Tuple7::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType> ParamTuple; -}; - -template -struct TupleTypes< Tuple8 > { - typedef Tuple8::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType, - typename TupleTraits::ValueType> ValueTuple; -typedef Tuple8::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType, - typename TupleTraits::RefType> RefTuple; - typedef Tuple8::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType, - typename TupleTraits::ParamType> ParamTuple; -}; - -// Tuple creators ------------------------------------------------------------- -// -// Helper functions for constructing tuples while inferring the template -// argument types. - -inline Tuple0 MakeTuple() { - return Tuple0(); -} - -template -inline Tuple1 MakeTuple(const A& a) { - return Tuple1(a); -} - -template -inline Tuple2 MakeTuple(const A& a, const B& b) { - return Tuple2(a, b); -} - -template -inline Tuple3 MakeTuple(const A& a, const B& b, const C& c) { - return Tuple3(a, b, c); -} - -template -inline Tuple4 MakeTuple(const A& a, const B& b, const C& c, - const D& d) { - return Tuple4(a, b, c, d); -} - -template -inline Tuple5 MakeTuple(const A& a, const B& b, const C& c, - const D& d, const E& e) { - return Tuple5(a, b, c, d, e); -} - -template -inline Tuple6 MakeTuple(const A& a, const B& b, const C& c, - const D& d, const E& e, const F& f) { - return Tuple6(a, b, c, d, e, f); -} - -template -inline Tuple7 MakeTuple(const A& a, const B& b, const C& c, - const D& d, const E& e, const F& f, - const G& g) { - return Tuple7(a, b, c, d, e, f, g); -} - -template -inline Tuple8 MakeTuple(const A& a, const B& b, - const C& c, const D& d, - const E& e, const F& f, - const G& g, const H& h) { - return Tuple8(a, b, c, d, e, f, g, h); -} - -// The following set of helpers make what Boost refers to as "Tiers" - a tuple -// of references. - -template -inline Tuple1 MakeRefTuple(A& a) { - return Tuple1(a); -} - -template -inline Tuple2 MakeRefTuple(A& a, B& b) { - return Tuple2(a, b); -} - -template -inline Tuple3 MakeRefTuple(A& a, B& b, C& c) { - return Tuple3(a, b, c); -} - -template -inline Tuple4 MakeRefTuple(A& a, B& b, C& c, D& d) { - return Tuple4(a, b, c, d); -} - -template -inline Tuple5 MakeRefTuple(A& a, B& b, C& c, D& d, E& e) { - return Tuple5(a, b, c, d, e); -} - -template -inline Tuple6 MakeRefTuple(A& a, B& b, C& c, D& d, E& e, - F& f) { - return Tuple6(a, b, c, d, e, f); -} - -template -inline Tuple7 MakeRefTuple(A& a, B& b, C& c, D& d, - E& e, F& f, G& g) { - return Tuple7(a, b, c, d, e, f, g); -} - -template -inline Tuple8 MakeRefTuple(A& a, B& b, C& c, - D& d, E& e, F& f, - G& g, H& h) { - return Tuple8(a, b, c, d, e, f, g, h); -} - -// Dispatchers ---------------------------------------------------------------- -// -// Helper functions that call the given method on an object, with the unpacked -// tuple arguments. Notice that they all have the same number of arguments, -// so you need only write: -// DispatchToMethod(object, &Object::method, args); -// This is very useful for templated dispatchers, since they don't need to know -// what type |args| is. - -// Non-Static Dispatchers with no out params. - -template -inline void DispatchToMethod(ObjT* obj, Method method, const Tuple0& arg) { - (obj->*method)(); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, const A& arg) { - (obj->*method)(arg); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, const Tuple1& arg) { -#if defined(OS_CHROMEOS) - // To troubleshoot crosbug.com/7327. - CHECK(obj); - CHECK(&arg); - CHECK(method); -#endif - (obj->*method)(arg.a); -} - -template -inline void DispatchToMethod(ObjT* obj, - Method method, - const Tuple2& arg) { - (obj->*method)(arg.a, arg.b); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple3& arg) { - (obj->*method)(arg.a, arg.b, arg.c); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple4& arg) { - (obj->*method)(arg.a, arg.b, arg.c, arg.d); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple5& arg) { - (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple6& arg) { - (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple7& arg) { - (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f, arg.g); -} - -// Static Dispatchers with no out params. - -template -inline void DispatchToFunction(Function function, const Tuple0& arg) { - (*function)(); -} - -template -inline void DispatchToFunction(Function function, const A& arg) { - (*function)(arg); -} - -template -inline void DispatchToFunction(Function function, const Tuple1& arg) { - (*function)(arg.a); -} - -template -inline void DispatchToFunction(Function function, const Tuple2& arg) { - (*function)(arg.a, arg.b); -} - -template -inline void DispatchToFunction(Function function, const Tuple3& arg) { - (*function)(arg.a, arg.b, arg.c); -} - -template -inline void DispatchToFunction(Function function, - const Tuple4& arg) { - (*function)(arg.a, arg.b, arg.c, arg.d); -} - -template -inline void DispatchToFunction(Function function, - const Tuple5& arg) { - (*function)(arg.a, arg.b, arg.c, arg.d, arg.e); -} - -template -inline void DispatchToFunction(Function function, - const Tuple6& arg) { - (*function)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f); -} - -template -inline void DispatchToFunction(Function function, - const Tuple7& arg) { - (*function)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f, arg.g); -} - -template -inline void DispatchToFunction(Function function, - const Tuple8& arg) { - (*function)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f, arg.g, arg.h); -} - -// Dispatchers with 0 out param (as a Tuple0). - -template -inline void DispatchToMethod(ObjT* obj, - Method method, - const Tuple0& arg, Tuple0*) { - (obj->*method)(); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, const A& arg, Tuple0*) { - (obj->*method)(arg); -} - -template -inline void DispatchToMethod(ObjT* obj, - Method method, - const Tuple1& arg, Tuple0*) { - (obj->*method)(arg.a); -} - -template -inline void DispatchToMethod(ObjT* obj, - Method method, - const Tuple2& arg, Tuple0*) { - (obj->*method)(arg.a, arg.b); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple3& arg, Tuple0*) { - (obj->*method)(arg.a, arg.b, arg.c); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple4& arg, Tuple0*) { - (obj->*method)(arg.a, arg.b, arg.c, arg.d); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple5& arg, Tuple0*) { - (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple6& arg, Tuple0*) { - (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f); -} - -// Dispatchers with 1 out param. - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple0& in, - Tuple1* out) { - (obj->*method)(&out->a); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const InA& in, - Tuple1* out) { - (obj->*method)(in, &out->a); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple1& in, - Tuple1* out) { - (obj->*method)(in.a, &out->a); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple2& in, - Tuple1* out) { - (obj->*method)(in.a, in.b, &out->a); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple3& in, - Tuple1* out) { - (obj->*method)(in.a, in.b, in.c, &out->a); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple4& in, - Tuple1* out) { - (obj->*method)(in.a, in.b, in.c, in.d, &out->a); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple5& in, - Tuple1* out) { - (obj->*method)(in.a, in.b, in.c, in.d, in.e, &out->a); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple6& in, - Tuple1* out) { - (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, &out->a); -} - -// Dispatchers with 2 out params. - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple0& in, - Tuple2* out) { - (obj->*method)(&out->a, &out->b); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const InA& in, - Tuple2* out) { - (obj->*method)(in, &out->a, &out->b); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple1& in, - Tuple2* out) { - (obj->*method)(in.a, &out->a, &out->b); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple2& in, - Tuple2* out) { - (obj->*method)(in.a, in.b, &out->a, &out->b); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple3& in, - Tuple2* out) { - (obj->*method)(in.a, in.b, in.c, &out->a, &out->b); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple4& in, - Tuple2* out) { - (obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple5& in, - Tuple2* out) { - (obj->*method)(in.a, in.b, in.c, in.d, in.e, &out->a, &out->b); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple6& in, - Tuple2* out) { - (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, &out->a, &out->b); -} - -// Dispatchers with 3 out params. - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple0& in, - Tuple3* out) { - (obj->*method)(&out->a, &out->b, &out->c); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const InA& in, - Tuple3* out) { - (obj->*method)(in, &out->a, &out->b, &out->c); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple1& in, - Tuple3* out) { - (obj->*method)(in.a, &out->a, &out->b, &out->c); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple2& in, - Tuple3* out) { - (obj->*method)(in.a, in.b, &out->a, &out->b, &out->c); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple3& in, - Tuple3* out) { - (obj->*method)(in.a, in.b, in.c, &out->a, &out->b, &out->c); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple4& in, - Tuple3* out) { - (obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b, &out->c); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple5& in, - Tuple3* out) { - (obj->*method)(in.a, in.b, in.c, in.d, in.e, &out->a, &out->b, &out->c); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple6& in, - Tuple3* out) { - (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, &out->a, &out->b, &out->c); -} - -// Dispatchers with 4 out params. - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple0& in, - Tuple4* out) { - (obj->*method)(&out->a, &out->b, &out->c, &out->d); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const InA& in, - Tuple4* out) { - (obj->*method)(in, &out->a, &out->b, &out->c, &out->d); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple1& in, - Tuple4* out) { - (obj->*method)(in.a, &out->a, &out->b, &out->c, &out->d); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple2& in, - Tuple4* out) { - (obj->*method)(in.a, in.b, &out->a, &out->b, &out->c, &out->d); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple3& in, - Tuple4* out) { - (obj->*method)(in.a, in.b, in.c, &out->a, &out->b, &out->c, &out->d); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple4& in, - Tuple4* out) { - (obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b, &out->c, &out->d); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple5& in, - Tuple4* out) { - (obj->*method)(in.a, in.b, in.c, in.d, in.e, - &out->a, &out->b, &out->c, &out->d); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple6& in, - Tuple4* out) { - (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, - &out->a, &out->b, &out->c, &out->d); -} - -// Dispatchers with 5 out params. - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple0& in, - Tuple5* out) { - (obj->*method)(&out->a, &out->b, &out->c, &out->d, &out->e); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const InA& in, - Tuple5* out) { - (obj->*method)(in, &out->a, &out->b, &out->c, &out->d, &out->e); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple1& in, - Tuple5* out) { - (obj->*method)(in.a, &out->a, &out->b, &out->c, &out->d, &out->e); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple2& in, - Tuple5* out) { - (obj->*method)(in.a, in.b, &out->a, &out->b, &out->c, &out->d, &out->e); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple3& in, - Tuple5* out) { - (obj->*method)(in.a, in.b, in.c, &out->a, &out->b, &out->c, &out->d, &out->e); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple4& in, - Tuple5* out) { - (obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b, &out->c, &out->d, - &out->e); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple5& in, - Tuple5* out) { - (obj->*method)(in.a, in.b, in.c, in.d, in.e, - &out->a, &out->b, &out->c, &out->d, &out->e); -} - -template -inline void DispatchToMethod(ObjT* obj, Method method, - const Tuple6& in, - Tuple5* out) { - (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, - &out->a, &out->b, &out->c, &out->d, &out->e); -} - -#endif // CEF_INCLUDE_INTERNAL_CEF_TUPLE_H_ diff --git a/cefpython/cef1/include/internal/cef_types.h b/cefpython/cef1/include/internal/cef_types.h deleted file mode 100644 index 0726b1dbc..000000000 --- a/cefpython/cef1/include/internal/cef_types.h +++ /dev/null @@ -1,1212 +0,0 @@ -// Copyright (c) 2010 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -#ifndef CEF_INCLUDE_INTERNAL_CEF_TYPES_H_ -#define CEF_INCLUDE_INTERNAL_CEF_TYPES_H_ -#pragma once - -#include "include/internal/cef_build.h" -#include "include/internal/cef_string.h" -#include "include/internal/cef_string_list.h" -#include "include/internal/cef_time.h" - -// Bring in platform-specific definitions. -#if defined(OS_WIN) -#include "include/internal/cef_types_win.h" -#elif defined(OS_MACOSX) -#include "include/internal/cef_types_mac.h" -#elif defined(OS_LINUX) -#include "include/internal/cef_types_linux.h" -#endif - -#include // For size_t - -// The NSPR system headers define 64-bit as |long| when possible, except on -// Mac OS X. In order to not have typedef mismatches, we do the same on LP64. -// -// On Mac OS X, |long long| is used for 64-bit types for compatibility with -// format macros even in the LP64 model. -#if defined(__LP64__) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) -typedef long int64; // NOLINT(runtime/int) -typedef unsigned long uint64; // NOLINT(runtime/int) -#else -typedef long long int64; // NOLINT(runtime/int) -typedef unsigned long long uint64; // NOLINT(runtime/int) -#endif - -// TODO: Remove these type guards. These are to avoid conflicts with -// obsolete/protypes.h in the Gecko SDK. -#ifndef _INT32 -#define _INT32 -typedef int int32; -#endif - -// TODO: Remove these type guards. These are to avoid conflicts with -// obsolete/protypes.h in the Gecko SDK. -#ifndef _UINT32 -#define _UINT32 -typedef unsigned int uint32; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/// -// Log severity levels. -/// -enum cef_log_severity_t { - LOGSEVERITY_VERBOSE = -1, - LOGSEVERITY_INFO, - LOGSEVERITY_WARNING, - LOGSEVERITY_ERROR, - LOGSEVERITY_ERROR_REPORT, - // Disables logging completely. - LOGSEVERITY_DISABLE = 99 -}; - -/// -// Initialization settings. Specify NULL or 0 to get the recommended default -// values. -/// -typedef struct _cef_settings_t { - /// - // Size of this structure. - /// - size_t size; - - /// - // Set to true (1) to have the message loop run in a separate thread. If - // false (0) than the CefDoMessageLoopWork() function must be called from - // your application message loop. - /// - bool multi_threaded_message_loop; - - /// - // The location where cache data will be stored on disk. If empty an - // in-memory cache will be used. HTML5 databases such as localStorage will - // only persist across sessions if a cache path is specified. - /// - cef_string_t cache_path; - - /// - // Value that will be returned as the User-Agent HTTP header. If empty the - // default User-Agent string will be used. - /// - cef_string_t user_agent; - - /// - // Value that will be inserted as the product portion of the default - // User-Agent string. If empty the Chromium product version will be used. If - // |userAgent| is specified this value will be ignored. - /// - cef_string_t product_version; - - /// - // The locale string that will be passed to WebKit. If empty the default - // locale of "en-US" will be used. This value is ignored on Linux where locale - // is determined using environment variable parsing with the precedence order: - // LANGUAGE, LC_ALL, LC_MESSAGES and LANG. - /// - cef_string_t locale; - - /// - // List of fully qualified paths to plugins (including plugin name) that will - // be loaded in addition to any plugins found in the default search paths. - /// - cef_string_list_t extra_plugin_paths; - - /// - // The directory and file name to use for the debug log. If empty, the - // default name of "debug.log" will be used and the file will be written - // to the application directory. - /// - cef_string_t log_file; - - /// - // The log severity. Only messages of this severity level or higher will be - // logged. - /// - cef_log_severity_t log_severity; - - /// - // Enable DCHECK in release mode to ease debugging. - /// - bool release_dcheck_enabled; - - /// - // The graphics implementation that CEF will use for rendering GPU accelerated - // content like WebGL, accelerated layers and 3D CSS. - /// - cef_graphics_implementation_t graphics_implementation; - - /// - // Quota limit for localStorage data across all origins. Default size is 5MB. - /// - unsigned int local_storage_quota; - - /// - // Quota limit for sessionStorage data per namespace. Default size is 5MB. - /// - unsigned int session_storage_quota; - - /// - // Custom flags that will be used when initializing the V8 JavaScript engine. - // The consequences of using custom flags may not be well tested. - /// - cef_string_t javascript_flags; - -#if defined(OS_WIN) - /// - // Set to true (1) to use the system proxy resolver on Windows when - // "Automatically detect settings" is checked. This setting is disabled - // by default for performance reasons. - /// - bool auto_detect_proxy_settings_enabled; -#endif - - /// - // The fully qualified path for the resources directory. If this value is - // empty the chrome.pak and/or devtools_resources.pak files must be located in - // the module directory on Windows/Linux or the app bundle Resources directory - // on Mac OS X. - /// - cef_string_t resources_dir_path; - - /// - // The fully qualified path for the locales directory. If this value is empty - // the locales directory must be located in the module directory. This value - // is ignored on Mac OS X where pack files are always loaded from the app - // bundle Resources directory. - /// - cef_string_t locales_dir_path; - - /// - // Set to true (1) to disable loading of pack files for resources and locales. - // A resource bundle handler must be provided for the browser and renderer - // processes via CefApp::GetResourceBundleHandler() if loading of pack files - // is disabled. - /// - bool pack_loading_disabled; - - /// - // The number of stack trace frames to capture for uncaught exceptions. - // Specify a positive value to enable the CefV8ContextHandler:: - // OnUncaughtException() callback. Specify 0 (default value) and - // OnUncaughtException() will not be called. - /// - int uncaught_exception_stack_size; - - /// - // By default CEF V8 references will be invalidated (the IsValid() method will - // return false) after the owning context has been released. This reduces the - // need for external record keeping and avoids crashes due to the use of V8 - // references after the associated context has been released. - // - // CEF currently offers two context safety implementations with different - // performance characteristics. The default implementation (value of 0) uses a - // map of hash values and should provide better performance in situations with - // a small number contexts. The alternate implementation (value of 1) uses a - // hidden value attached to each context and should provide better performance - // in situations with a large number of contexts. - // - // If you need better performance in the creation of V8 references and you - // plan to manually track context lifespan you can disable context safety by - // specifying a value of -1. - /// - int context_safety_implementation; -} cef_settings_t; - -/// -// Browser initialization settings. Specify NULL or 0 to get the recommended -// default values. The consequences of using custom values may not be well -// tested. -/// -typedef struct _cef_browser_settings_t { - /// - // Size of this structure. - /// - size_t size; - - /// - // Disable drag & drop of URLs from other windows. - /// - bool drag_drop_disabled; - - /// - // Disable default navigation resulting from drag & drop of URLs. - /// - bool load_drops_disabled; - - /// - // Disable history back/forward navigation. - /// - bool history_disabled; - - /// - // The number of frames per second (fps) for animation and windowless - // rendering. When window rendering is enabled and the JavaScript - // requestAnimationFrame method is used the browser client area will be - // invalidated at the rate specified. When window rendering is disabled the - // CefRenderHandler::OnPaint() method will be called at the rate specified. - // This value must be between 0 and 90. Specify a value of zero for the - // default frame rate of 30 fps. Changing this value may affect display - // performance and/or CPU usage. - /// - int animation_frame_rate; - - // The below values map to WebPreferences settings. - - /// - // Font settings. - /// - cef_string_t standard_font_family; - cef_string_t fixed_font_family; - cef_string_t serif_font_family; - cef_string_t sans_serif_font_family; - cef_string_t cursive_font_family; - cef_string_t fantasy_font_family; - int default_font_size; - int default_fixed_font_size; - int minimum_font_size; - int minimum_logical_font_size; - - /// - // Set to true (1) to disable loading of fonts from remote sources. - /// - bool remote_fonts_disabled; - - /// - // Default encoding for Web content. If empty "ISO-8859-1" will be used. - /// - cef_string_t default_encoding; - - /// - // Set to true (1) to attempt automatic detection of content encoding. - /// - bool encoding_detector_enabled; - - /// - // Set to true (1) to disable JavaScript. - /// - bool javascript_disabled; - - /// - // Set to true (1) to disallow JavaScript from opening windows. - /// - bool javascript_open_windows_disallowed; - - /// - // Set to true (1) to disallow JavaScript from closing windows. - /// - bool javascript_close_windows_disallowed; - - /// - // Set to true (1) to disallow JavaScript from accessing the clipboard. - /// - bool javascript_access_clipboard_disallowed; - - /// - // Set to true (1) to disable DOM pasting in the editor. DOM pasting also - // depends on |javascript_cannot_access_clipboard| being false (0). - /// - bool dom_paste_disabled; - - /// - // Set to true (1) to enable drawing of the caret position. - /// - bool caret_browsing_enabled; - - /// - // Set to true (1) to disable Java. - /// - bool java_disabled; - - /// - // Set to true (1) to disable plugins. - /// - bool plugins_disabled; - - /// - // Set to true (1) to allow access to all URLs from file URLs. - /// - bool universal_access_from_file_urls_allowed; - - /// - // Set to true (1) to allow access to file URLs from other file URLs. - /// - bool file_access_from_file_urls_allowed; - - /// - // Set to true (1) to allow risky security behavior such as cross-site - // scripting (XSS). Use with extreme care. - /// - bool web_security_disabled; - - /// - // Set to true (1) to enable console warnings about XSS attempts. - /// - bool xss_auditor_enabled; - - /// - // Set to true (1) to suppress the network load of image URLs. A cached - // image will still be rendered if requested. - /// - bool image_load_disabled; - - /// - // Set to true (1) to shrink standalone images to fit the page. - /// - bool shrink_standalone_images_to_fit; - - /// - // Set to true (1) to disable browser backwards compatibility features. - /// - bool site_specific_quirks_disabled; - - /// - // Set to true (1) to disable resize of text areas. - /// - bool text_area_resize_disabled; - - /// - // Set to true (1) to disable use of the page cache. - /// - bool page_cache_disabled; - - /// - // Set to true (1) to not have the tab key advance focus to links. - /// - bool tab_to_links_disabled; - - /// - // Set to true (1) to disable hyperlink pings ( and window.sendPing). - /// - bool hyperlink_auditing_disabled; - - /// - // Set to true (1) to enable the user style sheet for all pages. - /// - bool user_style_sheet_enabled; - - /// - // Location of the user style sheet. This must be a data URL of the form - // "data:text/css;charset=utf-8;base64,csscontent" where "csscontent" is the - // base64 encoded contents of the CSS file. - /// - cef_string_t user_style_sheet_location; - - /// - // Set to true (1) to disable style sheets. - /// - bool author_and_user_styles_disabled; - - /// - // Set to true (1) to disable local storage. - /// - bool local_storage_disabled; - - /// - // Set to true (1) to disable databases. - /// - bool databases_disabled; - - /// - // Set to true (1) to disable application cache. - /// - bool application_cache_disabled; - - /// - // Set to true (1) to disable WebGL. - /// - bool webgl_disabled; - - /// - // Set to true (1) to enable accelerated compositing. This is turned off by - // default because the current in-process GPU implementation does not - // support it correctly. - /// - bool accelerated_compositing_enabled; - - /// - // Set to true (1) to disable accelerated layers. This affects features like - // 3D CSS transforms. - /// - bool accelerated_layers_disabled; - - /// - // Set to true (1) to disable accelerated video. - /// - bool accelerated_video_disabled; - - /// - // Set to true (1) to disable accelerated 2d canvas. - /// - bool accelerated_2d_canvas_disabled; - - /// - // Set to true (1) to disable accelerated filters. - /// - bool accelerated_filters_disabled; - - /// - // Set to true (1) to disable accelerated plugins. - /// - bool accelerated_plugins_disabled; - - /// - // Set to true (1) to disable developer tools (WebKit inspector). - /// - bool developer_tools_disabled; - - /// - // Set to true (1) to enable fullscreen mode. - /// - bool fullscreen_enabled; -} cef_browser_settings_t; - -/// -// URL component parts. -/// -typedef struct _cef_urlparts_t { - /// - // The complete URL specification. - /// - cef_string_t spec; - - /// - // Scheme component not including the colon (e.g., "http"). - /// - cef_string_t scheme; - - /// - // User name component. - /// - cef_string_t username; - - /// - // Password component. - /// - cef_string_t password; - - /// - // Host component. This may be a hostname, an IPv4 address or an IPv6 literal - // surrounded by square brackets (e.g., "[2001:db8::1]"). - /// - cef_string_t host; - - /// - // Port number component. - /// - cef_string_t port; - - /// - // Path component including the first slash following the host. - /// - cef_string_t path; - - /// - // Query string component (i.e., everything following the '?'). - /// - cef_string_t query; -} cef_urlparts_t; - -/// -// Cookie information. -/// -typedef struct _cef_cookie_t { - /// - // The cookie name. - /// - cef_string_t name; - - /// - // The cookie value. - /// - cef_string_t value; - - /// - // If |domain| is empty a host cookie will be created instead of a domain - // cookie. Domain cookies are stored with a leading "." and are visible to - // sub-domains whereas host cookies are not. - /// - cef_string_t domain; - - /// - // If |path| is non-empty only URLs at or below the path will get the cookie - // value. - /// - cef_string_t path; - - /// - // If |secure| is true the cookie will only be sent for HTTPS requests. - /// - bool secure; - - /// - // If |httponly| is true the cookie will only be sent for HTTP requests. - /// - bool httponly; - - /// - // The cookie creation date. This is automatically populated by the system on - // cookie creation. - /// - cef_time_t creation; - - /// - // The cookie last access date. This is automatically populated by the system - // on access. - /// - cef_time_t last_access; - - /// - // The cookie expiration date is only valid if |has_expires| is true. - /// - bool has_expires; - cef_time_t expires; -} cef_cookie_t; - -/// -// Storage types. -/// -enum cef_storage_type_t { - ST_LOCALSTORAGE = 0, - ST_SESSIONSTORAGE, -}; - -/// -// Mouse button types. -/// -enum cef_mouse_button_type_t { - MBT_LEFT = 0, - MBT_MIDDLE, - MBT_RIGHT, -}; - -/// -// Key types. -/// -enum cef_key_type_t { - KT_KEYUP = 0, - KT_KEYDOWN, - KT_CHAR, -}; - -/// -// Various browser navigation types supported by chrome. -/// -enum cef_handler_navtype_t { - NAVTYPE_LINKCLICKED = 0, - NAVTYPE_FORMSUBMITTED, - NAVTYPE_BACKFORWARD, - NAVTYPE_RELOAD, - NAVTYPE_FORMRESUBMITTED, - NAVTYPE_OTHER, - NAVTYPE_LINKDROPPED, -}; - -/// -// Supported error code values. See net\base\net_error_list.h for complete -// descriptions of the error codes. -/// -enum cef_handler_errorcode_t { - ERR_FAILED = -2, - ERR_ABORTED = -3, - ERR_INVALID_ARGUMENT = -4, - ERR_INVALID_HANDLE = -5, - ERR_FILE_NOT_FOUND = -6, - ERR_TIMED_OUT = -7, - ERR_FILE_TOO_BIG = -8, - ERR_UNEXPECTED = -9, - ERR_ACCESS_DENIED = -10, - ERR_NOT_IMPLEMENTED = -11, - ERR_CONNECTION_CLOSED = -100, - ERR_CONNECTION_RESET = -101, - ERR_CONNECTION_REFUSED = -102, - ERR_CONNECTION_ABORTED = -103, - ERR_CONNECTION_FAILED = -104, - ERR_NAME_NOT_RESOLVED = -105, - ERR_INTERNET_DISCONNECTED = -106, - ERR_SSL_PROTOCOL_ERROR = -107, - ERR_ADDRESS_INVALID = -108, - ERR_ADDRESS_UNREACHABLE = -109, - ERR_SSL_CLIENT_AUTH_CERT_NEEDED = -110, - ERR_TUNNEL_CONNECTION_FAILED = -111, - ERR_NO_SSL_VERSIONS_ENABLED = -112, - ERR_SSL_VERSION_OR_CIPHER_MISMATCH = -113, - ERR_SSL_RENEGOTIATION_REQUESTED = -114, - ERR_CERT_COMMON_NAME_INVALID = -200, - ERR_CERT_DATE_INVALID = -201, - ERR_CERT_AUTHORITY_INVALID = -202, - ERR_CERT_CONTAINS_ERRORS = -203, - ERR_CERT_NO_REVOCATION_MECHANISM = -204, - ERR_CERT_UNABLE_TO_CHECK_REVOCATION = -205, - ERR_CERT_REVOKED = -206, - ERR_CERT_INVALID = -207, - ERR_CERT_END = -208, - ERR_INVALID_URL = -300, - ERR_DISALLOWED_URL_SCHEME = -301, - ERR_UNKNOWN_URL_SCHEME = -302, - ERR_TOO_MANY_REDIRECTS = -310, - ERR_UNSAFE_REDIRECT = -311, - ERR_UNSAFE_PORT = -312, - ERR_INVALID_RESPONSE = -320, - ERR_INVALID_CHUNKED_ENCODING = -321, - ERR_METHOD_NOT_SUPPORTED = -322, - ERR_UNEXPECTED_PROXY_AUTH = -323, - ERR_EMPTY_RESPONSE = -324, - ERR_RESPONSE_HEADERS_TOO_BIG = -325, - ERR_CACHE_MISS = -400, - ERR_INSECURE_RESPONSE = -501, -}; - -/// -// "Verb" of a drag-and-drop operation as negotiated between the source and -// destination. These constants match their equivalents in WebCore's -// DragActions.h and should not be renumbered. -/// -enum cef_drag_operations_mask_t { - DRAG_OPERATION_NONE = 0, - DRAG_OPERATION_COPY = 1, - DRAG_OPERATION_LINK = 2, - DRAG_OPERATION_GENERIC = 4, - DRAG_OPERATION_PRIVATE = 8, - DRAG_OPERATION_MOVE = 16, - DRAG_OPERATION_DELETE = 32, - DRAG_OPERATION_EVERY = UINT_MAX -}; - -/// -// V8 access control values. -/// -enum cef_v8_accesscontrol_t { - V8_ACCESS_CONTROL_DEFAULT = 0, - V8_ACCESS_CONTROL_ALL_CAN_READ = 1, - V8_ACCESS_CONTROL_ALL_CAN_WRITE = 1 << 1, - V8_ACCESS_CONTROL_PROHIBITS_OVERWRITING = 1 << 2 -}; - -/// -// V8 property attribute values. -/// -enum cef_v8_propertyattribute_t { - V8_PROPERTY_ATTRIBUTE_NONE = 0, // Writeable, Enumerable, - // Configurable - V8_PROPERTY_ATTRIBUTE_READONLY = 1 << 0, // Not writeable - V8_PROPERTY_ATTRIBUTE_DONTENUM = 1 << 1, // Not enumerable - V8_PROPERTY_ATTRIBUTE_DONTDELETE = 1 << 2 // Not configurable -}; - -/// -// Structure representing menu information. -/// -typedef struct _cef_menu_info_t { - /// - // Values from the cef_handler_menutypebits_t enumeration. - /// - int typeFlags; - - /// - // If window rendering is enabled |x| and |y| will be in screen coordinates. - // Otherwise, |x| and |y| will be in view coordinates. - /// - int x; - int y; - - cef_string_t linkUrl; - cef_string_t imageUrl; - cef_string_t pageUrl; - cef_string_t frameUrl; - cef_string_t selectionText; - cef_string_t misspelledWord; - - /// - // Values from the cef_handler_menucapabilitybits_t enumeration. - /// - int editFlags; - - cef_string_t securityInfo; -} cef_menu_info_t; - -/// -// The cef_menu_info_t typeFlags value will be a combination of the -// following values. -/// -enum cef_menu_typebits_t { - /// - // No node is selected - /// - MENUTYPE_NONE = 0x0, - /// - // The top page is selected - /// - MENUTYPE_PAGE = 0x1, - /// - // A subframe page is selected - /// - MENUTYPE_FRAME = 0x2, - /// - // A link is selected - /// - MENUTYPE_LINK = 0x4, - /// - // An image is selected - /// - MENUTYPE_IMAGE = 0x8, - /// - // There is a textual or mixed selection that is selected - /// - MENUTYPE_SELECTION = 0x10, - /// - // An editable element is selected - /// - MENUTYPE_EDITABLE = 0x20, - /// - // A misspelled word is selected - /// - MENUTYPE_MISSPELLED_WORD = 0x40, - /// - // A video node is selected - /// - MENUTYPE_VIDEO = 0x80, - /// - // A video node is selected - /// - MENUTYPE_AUDIO = 0x100, -}; - -/// -// The cef_menu_info_t editFlags value will be a combination of the -// following values. -/// -enum cef_menu_capabilitybits_t { - // Values from WebContextMenuData::EditFlags in WebContextMenuData.h - MENU_CAN_DO_NONE = 0x0, - MENU_CAN_UNDO = 0x1, - MENU_CAN_REDO = 0x2, - MENU_CAN_CUT = 0x4, - MENU_CAN_COPY = 0x8, - MENU_CAN_PASTE = 0x10, - MENU_CAN_DELETE = 0x20, - MENU_CAN_SELECT_ALL = 0x40, - MENU_CAN_TRANSLATE = 0x80, - // Values unique to CEF - MENU_CAN_GO_FORWARD = 0x10000000, - MENU_CAN_GO_BACK = 0x20000000, -}; - -/// -// Supported menu ID values. -/// -enum cef_menu_id_t { - MENU_ID_NAV_BACK = 10, - MENU_ID_NAV_FORWARD = 11, - MENU_ID_NAV_RELOAD = 12, - MENU_ID_NAV_RELOAD_NOCACHE = 13, - MENU_ID_NAV_STOP = 14, - MENU_ID_UNDO = 20, - MENU_ID_REDO = 21, - MENU_ID_CUT = 22, - MENU_ID_COPY = 23, - MENU_ID_PASTE = 24, - MENU_ID_DELETE = 25, - MENU_ID_SELECTALL = 26, - MENU_ID_PRINT = 30, - MENU_ID_VIEWSOURCE = 31, -}; - -enum cef_paint_element_type_t { - PET_VIEW = 0, - PET_POPUP, -}; - -/// -// Post data elements may represent either bytes or files. -/// -enum cef_postdataelement_type_t { - PDE_TYPE_EMPTY = 0, - PDE_TYPE_BYTES, - PDE_TYPE_FILE, -}; - -enum cef_weburlrequest_flags_t { - WUR_FLAG_NONE = 0, - WUR_FLAG_SKIP_CACHE = 0x1, - WUR_FLAG_ALLOW_CACHED_CREDENTIALS = 0x2, - WUR_FLAG_ALLOW_COOKIES = 0x4, - WUR_FLAG_REPORT_UPLOAD_PROGRESS = 0x8, - WUR_FLAG_REPORT_LOAD_TIMING = 0x10, - WUR_FLAG_REPORT_RAW_HEADERS = 0x20 -}; - -enum cef_weburlrequest_state_t { - WUR_STATE_UNSENT = 0, - WUR_STATE_STARTED = 1, - WUR_STATE_HEADERS_RECEIVED = 2, - WUR_STATE_LOADING = 3, - WUR_STATE_DONE = 4, - WUR_STATE_ERROR = 5, - WUR_STATE_ABORT = 6, -}; - -/// -// Focus sources. -/// -enum cef_handler_focus_source_t { - /// - // The source is explicit navigation via the API (LoadURL(), etc). - /// - FOCUS_SOURCE_NAVIGATION = 0, - /// - // The source is a system-generated focus event. - /// - FOCUS_SOURCE_SYSTEM, - /// - // The source is a child widget of the browser window requesting focus. - /// - FOCUS_SOURCE_WIDGET, -}; - -/// -// Key event types. -/// -enum cef_handler_keyevent_type_t { - KEYEVENT_RAWKEYDOWN = 0, - KEYEVENT_KEYDOWN, - KEYEVENT_KEYUP, - KEYEVENT_CHAR -}; - -/// -// Key event modifiers. -/// -enum cef_handler_keyevent_modifiers_t { - KEY_SHIFT = 1 << 0, - KEY_CTRL = 1 << 1, - KEY_ALT = 1 << 2, - KEY_META = 1 << 3, - KEY_KEYPAD = 1 << 4, // Only used on Mac OS-X -}; - -/// -// Structure representing a rectangle. -/// -typedef struct _cef_rect_t { - int x; - int y; - int width; - int height; -} cef_rect_t; - -/// -// Existing thread IDs. -/// -enum cef_thread_id_t { - TID_UI = 0, - TID_IO = 1, - TID_FILE = 2, -}; - -/// -// Paper type for printing. -/// -enum cef_paper_type_t { - PT_LETTER = 0, - PT_LEGAL, - PT_EXECUTIVE, - PT_A3, - PT_A4, - PT_CUSTOM -}; - -/// -// Paper metric information for printing. -/// -struct cef_paper_metrics { - enum cef_paper_type_t paper_type; - // Length and width needed if paper_type is custom_size - // Units are in inches. - double length; - double width; -}; - -/// -// Paper print margins. -/// -struct cef_print_margins { - // Margin size in inches for left/right/top/bottom (this is content margins). - double left; - double right; - double top; - double bottom; - // Margin size (top/bottom) in inches for header/footer. - double header; - double footer; -}; - -/// -// Page orientation for printing. -/// -enum cef_page_orientation { - PORTRAIT = 0, - LANDSCAPE -}; - -/// -// Printing options. -/// -typedef struct _cef_print_options_t { - enum cef_page_orientation page_orientation; - struct cef_paper_metrics paper_metrics; - struct cef_print_margins paper_margins; -} cef_print_options_t; - -/// -// Supported XML encoding types. The parser supports ASCII, ISO-8859-1, and -// UTF16 (LE and BE) by default. All other types must be translated to UTF8 -// before being passed to the parser. If a BOM is detected and the correct -// decoder is available then that decoder will be used automatically. -/// -enum cef_xml_encoding_type_t { - XML_ENCODING_NONE = 0, - XML_ENCODING_UTF8, - XML_ENCODING_UTF16LE, - XML_ENCODING_UTF16BE, - XML_ENCODING_ASCII, -}; - -/// -// XML node types. -/// -enum cef_xml_node_type_t { - XML_NODE_UNSUPPORTED = 0, - XML_NODE_PROCESSING_INSTRUCTION, - XML_NODE_DOCUMENT_TYPE, - XML_NODE_ELEMENT_START, - XML_NODE_ELEMENT_END, - XML_NODE_ATTRIBUTE, - XML_NODE_TEXT, - XML_NODE_CDATA, - XML_NODE_ENTITY_REFERENCE, - XML_NODE_WHITESPACE, - XML_NODE_COMMENT, -}; - -/// -// Status message types. -/// -enum cef_handler_statustype_t { - STATUSTYPE_TEXT = 0, - STATUSTYPE_MOUSEOVER_URL, - STATUSTYPE_KEYBOARD_FOCUS_URL, -}; - -/// -// Popup window features. -/// -typedef struct _cef_popup_features_t { - int x; - bool xSet; - int y; - bool ySet; - int width; - bool widthSet; - int height; - bool heightSet; - - bool menuBarVisible; - bool statusBarVisible; - bool toolBarVisible; - bool locationBarVisible; - bool scrollbarsVisible; - bool resizable; - - bool fullscreen; - bool dialog; - cef_string_list_t additionalFeatures; -} cef_popup_features_t; - -/// -// DOM document types. -/// -enum cef_dom_document_type_t { - DOM_DOCUMENT_TYPE_UNKNOWN = 0, - DOM_DOCUMENT_TYPE_HTML, - DOM_DOCUMENT_TYPE_XHTML, - DOM_DOCUMENT_TYPE_PLUGIN, -}; - -/// -// DOM event category flags. -/// -enum cef_dom_event_category_t { - DOM_EVENT_CATEGORY_UNKNOWN = 0x0, - DOM_EVENT_CATEGORY_UI = 0x1, - DOM_EVENT_CATEGORY_MOUSE = 0x2, - DOM_EVENT_CATEGORY_MUTATION = 0x4, - DOM_EVENT_CATEGORY_KEYBOARD = 0x8, - DOM_EVENT_CATEGORY_TEXT = 0x10, - DOM_EVENT_CATEGORY_COMPOSITION = 0x20, - DOM_EVENT_CATEGORY_DRAG = 0x40, - DOM_EVENT_CATEGORY_CLIPBOARD = 0x80, - DOM_EVENT_CATEGORY_MESSAGE = 0x100, - DOM_EVENT_CATEGORY_WHEEL = 0x200, - DOM_EVENT_CATEGORY_BEFORE_TEXT_INSERTED = 0x400, - DOM_EVENT_CATEGORY_OVERFLOW = 0x800, - DOM_EVENT_CATEGORY_PAGE_TRANSITION = 0x1000, - DOM_EVENT_CATEGORY_POPSTATE = 0x2000, - DOM_EVENT_CATEGORY_PROGRESS = 0x4000, - DOM_EVENT_CATEGORY_XMLHTTPREQUEST_PROGRESS = 0x8000, - DOM_EVENT_CATEGORY_WEBKIT_ANIMATION = 0x10000, - DOM_EVENT_CATEGORY_WEBKIT_TRANSITION = 0x20000, - DOM_EVENT_CATEGORY_BEFORE_LOAD = 0x40000, -}; - -/// -// DOM event processing phases. -/// -enum cef_dom_event_phase_t { - DOM_EVENT_PHASE_UNKNOWN = 0, - DOM_EVENT_PHASE_CAPTURING, - DOM_EVENT_PHASE_AT_TARGET, - DOM_EVENT_PHASE_BUBBLING, -}; - -/// -// DOM node types. -/// -enum cef_dom_node_type_t { - DOM_NODE_TYPE_UNSUPPORTED = 0, - DOM_NODE_TYPE_ELEMENT, - DOM_NODE_TYPE_ATTRIBUTE, - DOM_NODE_TYPE_TEXT, - DOM_NODE_TYPE_CDATA_SECTION, - DOM_NODE_TYPE_ENTITY_REFERENCE, - DOM_NODE_TYPE_ENTITY, - DOM_NODE_TYPE_PROCESSING_INSTRUCTIONS, - DOM_NODE_TYPE_COMMENT, - DOM_NODE_TYPE_DOCUMENT, - DOM_NODE_TYPE_DOCUMENT_TYPE, - DOM_NODE_TYPE_DOCUMENT_FRAGMENT, - DOM_NODE_TYPE_NOTATION, - DOM_NODE_TYPE_XPATH_NAMESPACE, -}; - -/// -// Proxy types. -/// -enum cef_proxy_type_t { - CEF_PROXY_TYPE_DIRECT = 0, - CEF_PROXY_TYPE_NAMED, - CEF_PROXY_TYPE_PAC_STRING, -}; - -/// -// Proxy information. -/// -typedef struct _cef_proxy_info_t { - enum cef_proxy_type_t proxyType; - cef_string_t proxyList; -} cef_proxy_info_t; - -/// -// Geoposition error codes. -/// -enum cef_geoposition_error_code_t { - GEOPOSITON_ERROR_NONE = 0, - GEOPOSITON_ERROR_PERMISSION_DENIED, - GEOPOSITON_ERROR_POSITION_UNAVAILABLE, - GEOPOSITON_ERROR_TIMEOUT, -}; - -/// -// Structure representing geoposition information. The properties of this -// structure correspond to those of the JavaScript Position object although -// their types may differ. -/// -typedef struct _cef_geoposition_t { - /// - // Latitude in decimal degrees north (WGS84 coordinate frame). - /// - double latitude; - - /// - // Longitude in decimal degrees west (WGS84 coordinate frame). - /// - double longitude; - - /// - // Altitude in meters (above WGS84 datum). - /// - double altitude; - - /// - // Accuracy of horizontal position in meters. - /// - double accuracy; - - /// - // Accuracy of altitude in meters. - /// - double altitude_accuracy; - - /// - // Heading in decimal degrees clockwise from true north. - /// - double heading; - - /// - // Horizontal component of device velocity in meters per second. - /// - double speed; - - /// - // Time of position measurement in miliseconds since Epoch in UTC time. This - // is taken from the host computer's system clock. - /// - cef_time_t timestamp; - - /// - // Error code, see enum above. - /// - cef_geoposition_error_code_t error_code; - - /// - // Human-readable error message. - /// - cef_string_t error_message; -} cef_geoposition_t; - -#ifdef __cplusplus -} -#endif - -#endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_H_ diff --git a/cefpython/cef1/include/internal/cef_types_linux.h b/cefpython/cef1/include/internal/cef_types_linux.h deleted file mode 100644 index 15966907e..000000000 --- a/cefpython/cef1/include/internal/cef_types_linux.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2010 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -#ifndef CEF_INCLUDE_INTERNAL_CEF_TYPES_LINUX_H_ -#define CEF_INCLUDE_INTERNAL_CEF_TYPES_LINUX_H_ -#pragma once - -#include "include/internal/cef_build.h" - -#if defined(OS_LINUX) -#include -#include "include/internal/cef_string.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Window handle. -#define cef_window_handle_t GtkWidget* -#define cef_cursor_handle_t void* - -/// -// Supported graphics implementations. -/// -enum cef_graphics_implementation_t { - DESKTOP_IN_PROCESS = 0, - DESKTOP_IN_PROCESS_COMMAND_BUFFER, -}; - -/// -// Class representing window information. -/// -typedef struct _cef_window_info_t { - // Pointer for the parent GtkBox widget. - cef_window_handle_t m_ParentWidget; - - // Pointer for the new browser widget. - cef_window_handle_t m_Widget; -} cef_window_info_t; - -/// -// Class representing print context information. -/// -typedef struct _cef_print_info_t { - double m_Scale; -} cef_print_info_t; - -/// -// Class representing key information. -/// -typedef struct _cef_key_info_t { - int key; -} cef_key_info_t; - -#ifdef __cplusplus -} -#endif - -#endif // OS_LINUX - -#endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_LINUX_H_ diff --git a/cefpython/cef1/include/internal/cef_types_mac.h b/cefpython/cef1/include/internal/cef_types_mac.h deleted file mode 100644 index a10c54016..000000000 --- a/cefpython/cef1/include/internal/cef_types_mac.h +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) 2010 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -#ifndef CEF_INCLUDE_INTERNAL_CEF_TYPES_MAC_H_ -#define CEF_INCLUDE_INTERNAL_CEF_TYPES_MAC_H_ -#pragma once - -#include "include/internal/cef_build.h" - -#if defined(OS_MACOSX) -#include "include/internal/cef_string.h" - -// Window handle. -#ifdef __cplusplus -#ifdef __OBJC__ -@class NSCursor; -@class NSView; -#else -class NSCursor; -struct NSView; -#endif -#define cef_window_handle_t NSView* -#define cef_cursor_handle_t NSCursor* -#else -#define cef_window_handle_t void* -#define cef_cursor_handle_t void* -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/// -// Supported graphics implementations. -/// -enum cef_graphics_implementation_t { - DESKTOP_IN_PROCESS = 0, - DESKTOP_IN_PROCESS_COMMAND_BUFFER, -}; - -/// -// Class representing window information. -/// -typedef struct _cef_window_info_t { - cef_string_t m_windowName; - int m_x; - int m_y; - int m_nWidth; - int m_nHeight; - int m_bHidden; - - // NSView pointer for the parent view. - cef_window_handle_t m_ParentView; - - // If window rendering is disabled no browser window will be created. Set - // |m_ParentView| to the window that will act as the parent for popup menus, - // dialog boxes, etc. - int m_bWindowRenderingDisabled; - - // Set to true to enable transparent painting. - int m_bTransparentPainting; - - // NSView pointer for the new browser view. - cef_window_handle_t m_View; -} cef_window_info_t; - -/// -// Class representing print context information. -/// -typedef struct _cef_print_info_t { - double m_Scale; -} cef_print_info_t; - -/// -// Class representing key information. -/// -typedef struct _cef_key_info_t { - int keyCode; - int character; - int characterNoModifiers; -} cef_key_info_t; - -#ifdef __cplusplus -} -#endif - -#endif // OS_MACOSX - -#endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_MAC_H_ diff --git a/cefpython/cef1/include/internal/cef_types_win.h b/cefpython/cef1/include/internal/cef_types_win.h deleted file mode 100644 index 9b5e48e59..000000000 --- a/cefpython/cef1/include/internal/cef_types_win.h +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2009 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -#ifndef CEF_INCLUDE_INTERNAL_CEF_TYPES_WIN_H_ -#define CEF_INCLUDE_INTERNAL_CEF_TYPES_WIN_H_ -#pragma once - -#include "include/internal/cef_build.h" - -#if defined(OS_WIN) -#include -#include "include/internal/cef_string.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Window handle. -#define cef_window_handle_t HWND -#define cef_cursor_handle_t HCURSOR - -/// -// Supported graphics implementations. -/// -enum cef_graphics_implementation_t { - ANGLE_IN_PROCESS = 0, - ANGLE_IN_PROCESS_COMMAND_BUFFER, - DESKTOP_IN_PROCESS, - DESKTOP_IN_PROCESS_COMMAND_BUFFER, -}; - -/// -// Class representing window information. -/// -typedef struct _cef_window_info_t { - // Standard parameters required by CreateWindowEx() - DWORD m_dwExStyle; - cef_string_t m_windowName; - DWORD m_dwStyle; - int m_x; - int m_y; - int m_nWidth; - int m_nHeight; - cef_window_handle_t m_hWndParent; - HMENU m_hMenu; - - // If window rendering is disabled no browser window will be created. Set - // |m_hWndParent| to the window that will act as the parent for popup menus, - // dialog boxes, etc. - BOOL m_bWindowRenderingDisabled; - - // Set to true to enable transparent painting. - BOOL m_bTransparentPainting; - - // Handle for the new browser window. - cef_window_handle_t m_hWnd; -} cef_window_info_t; - -/// -// Class representing print context information. -/// -typedef struct _cef_print_info_t { - HDC m_hDC; - RECT m_Rect; - double m_Scale; -} cef_print_info_t; - -/// -// Class representing key information. -/// -typedef struct _cef_key_info_t { - int key; - BOOL sysChar; - BOOL imeChar; -} cef_key_info_t; - -#ifdef __cplusplus -} -#endif - -#endif // OS_WIN - -#endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_WIN_H_ diff --git a/cefpython/cef1/include/internal/cef_types_wrappers.h b/cefpython/cef1/include/internal/cef_types_wrappers.h deleted file mode 100644 index dd27229a4..000000000 --- a/cefpython/cef1/include/internal/cef_types_wrappers.h +++ /dev/null @@ -1,687 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef CEF_INCLUDE_INTERNAL_CEF_TYPES_WRAPPERS_H_ -#define CEF_INCLUDE_INTERNAL_CEF_TYPES_WRAPPERS_H_ -#pragma once - -#include "include/internal/cef_string.h" -#include "include/internal/cef_string_list.h" -#include "include/internal/cef_types.h" - -/// -// Template class that provides common functionality for CEF structure wrapping. -/// -template -class CefStructBase : public traits::struct_type { - public: - typedef typename traits::struct_type struct_type; - - CefStructBase() : attached_to_(NULL) { - Init(); - } - virtual ~CefStructBase() { - // Only clear this object's data if it isn't currently attached to a - // structure. - if (!attached_to_) - Clear(this); - } - - CefStructBase(const CefStructBase& r) { - Init(); - *this = r; - } - CefStructBase(const struct_type& r) { // NOLINT(runtime/explicit) - Init(); - *this = r; - } - - /// - // Clear this object's values. - /// - void Reset() { - Clear(this); - Init(); - } - - /// - // Attach to the source structure's existing values. DetachTo() can be called - // to insert the values back into the existing structure. - /// - void AttachTo(struct_type& source) { - // Only clear this object's data if it isn't currently attached to a - // structure. - if (!attached_to_) - Clear(this); - - // This object is now attached to the new structure. - attached_to_ = &source; - - // Transfer ownership of the values from the source structure. - memcpy(static_cast(this), &source, sizeof(struct_type)); - } - - /// - // Relinquish ownership of values to the target structure. - /// - void DetachTo(struct_type& target) { - if (attached_to_ != &target) { - // Clear the target structure's values only if we are not currently - // attached to that structure. - Clear(&target); - } - - // Transfer ownership of the values to the target structure. - memcpy(&target, static_cast(this), sizeof(struct_type)); - - // Remove the references from this object. - Init(); - } - - /// - // Set this object's values. If |copy| is true the source structure's values - // will be copied instead of referenced. - /// - void Set(const struct_type& source, bool copy) { - traits::set(&source, this, copy); - } - - CefStructBase& operator=(const CefStructBase& s) { - return operator=(static_cast(s)); - } - - CefStructBase& operator=(const struct_type& s) { - Set(s, true); - return *this; - } - - protected: - void Init() { - memset(static_cast(this), 0, sizeof(struct_type)); - attached_to_ = NULL; - traits::init(this); - } - - static void Clear(struct_type* s) { traits::clear(s); } - - struct_type* attached_to_; -}; - - -struct CefRectTraits { - typedef cef_rect_t struct_type; - - static inline void init(struct_type* s) {} - static inline void clear(struct_type* s) {} - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - *target = *src; - } -}; - -/// -// Class representing a rectangle. -/// -class CefRect : public CefStructBase { - public: - typedef CefStructBase parent; - - CefRect() : parent() {} - CefRect(const cef_rect_t& r) : parent(r) {} // NOLINT(runtime/explicit) - CefRect(const CefRect& r) : parent(r) {} // NOLINT(runtime/explicit) - CefRect(int x, int y, int width, int height) : parent() { - Set(x, y, width, height); - } - - bool IsEmpty() const { return width <= 0 || height <= 0; } - void Set(int x, int y, int width, int height) { - this->x = x, this->y = y, this->width = width, this->height = height; - } -}; - -inline bool operator==(const CefRect& a, const CefRect& b) { - return a.x == b.x && a.y == b.y && a.width == b.width && a.height == b.height; -} - -inline bool operator!=(const CefRect& a, const CefRect& b) { - return !(a == b); -} - - -struct CefPrintOptionsTraits { - typedef cef_print_options_t struct_type; - - static inline void init(struct_type* s) {} - static inline void clear(struct_type* s) {} - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - *target = *src; - } -}; - -/// -// Class representing print options. -/// -typedef CefStructBase CefPrintOptions; - - - -struct CefPopupFeaturesTraits { - typedef cef_popup_features_t struct_type; - - static inline void init(struct_type* s) { - s->menuBarVisible = true; - s->statusBarVisible = true; - s->toolBarVisible = true; - s->locationBarVisible = true; - s->scrollbarsVisible = true; - s->resizable = true; - } - - static inline void clear(struct_type* s) { - if (s->additionalFeatures) - cef_string_list_free(s->additionalFeatures); - } - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - if (target->additionalFeatures) - cef_string_list_free(target->additionalFeatures); - target->additionalFeatures = src->additionalFeatures ? - cef_string_list_copy(src->additionalFeatures) : NULL; - - target->x = src->x; - target->xSet = src->xSet; - target->y = src->y; - target->ySet = src->ySet; - target->width = src->width; - target->widthSet = src->widthSet; - target->height = src->height; - target->heightSet = src->heightSet; - target->menuBarVisible = src->menuBarVisible; - target->statusBarVisible = src->statusBarVisible; - target->toolBarVisible = src->toolBarVisible; - target->locationBarVisible = src->locationBarVisible; - target->scrollbarsVisible = src->scrollbarsVisible; - target->resizable = src->resizable; - target->fullscreen = src->fullscreen; - target->dialog = src->dialog; - } -}; - -/// -// Class representing popup window features. -/// -typedef CefStructBase CefPopupFeatures; - - -struct CefSettingsTraits { - typedef cef_settings_t struct_type; - - static inline void init(struct_type* s) { - s->size = sizeof(struct_type); - } - - static inline void clear(struct_type* s) { - cef_string_clear(&s->cache_path); - cef_string_clear(&s->user_agent); - cef_string_clear(&s->product_version); - cef_string_clear(&s->locale); - if (s->extra_plugin_paths) - cef_string_list_free(s->extra_plugin_paths); - cef_string_clear(&s->log_file); - cef_string_clear(&s->javascript_flags); - cef_string_clear(&s->resources_dir_path); - cef_string_clear(&s->locales_dir_path); - } - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - target->multi_threaded_message_loop = src->multi_threaded_message_loop; - - cef_string_set(src->cache_path.str, src->cache_path.length, - &target->cache_path, copy); - cef_string_set(src->user_agent.str, src->user_agent.length, - &target->user_agent, copy); - cef_string_set(src->product_version.str, src->product_version.length, - &target->product_version, copy); - cef_string_set(src->locale.str, src->locale.length, &target->locale, copy); - - if (target->extra_plugin_paths) - cef_string_list_free(target->extra_plugin_paths); - target->extra_plugin_paths = src->extra_plugin_paths ? - cef_string_list_copy(src->extra_plugin_paths) : NULL; - - cef_string_set(src->log_file.str, src->log_file.length, &target->log_file, - copy); - target->log_severity = src->log_severity; - target->release_dcheck_enabled = src->release_dcheck_enabled; - target->graphics_implementation = src->graphics_implementation; - target->local_storage_quota = src->local_storage_quota; - target->session_storage_quota = src->session_storage_quota; - cef_string_set(src->javascript_flags.str, src->javascript_flags.length, - &target->javascript_flags, copy); - -#if defined(OS_WIN) - target->auto_detect_proxy_settings_enabled = - src->auto_detect_proxy_settings_enabled; -#endif - - cef_string_set(src->resources_dir_path.str, src->resources_dir_path.length, - &target->resources_dir_path, copy); - cef_string_set(src->locales_dir_path.str, src->locales_dir_path.length, - &target->locales_dir_path, copy); - target->pack_loading_disabled = src->pack_loading_disabled; - target->uncaught_exception_stack_size = src->uncaught_exception_stack_size; - target->context_safety_implementation = src->context_safety_implementation; - } -}; - -/// -// Class representing initialization settings. -/// -typedef CefStructBase CefSettings; - - -struct CefBrowserSettingsTraits { - typedef cef_browser_settings_t struct_type; - - static inline void init(struct_type* s) { - s->size = sizeof(struct_type); - } - - static inline void clear(struct_type* s) { - cef_string_clear(&s->standard_font_family); - cef_string_clear(&s->fixed_font_family); - cef_string_clear(&s->serif_font_family); - cef_string_clear(&s->sans_serif_font_family); - cef_string_clear(&s->cursive_font_family); - cef_string_clear(&s->fantasy_font_family); - cef_string_clear(&s->default_encoding); - cef_string_clear(&s->user_style_sheet_location); - } - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - target->drag_drop_disabled = src->drag_drop_disabled; - target->load_drops_disabled = src->load_drops_disabled; - target->history_disabled = src->history_disabled; - target->animation_frame_rate = src->animation_frame_rate; - - cef_string_set(src->standard_font_family.str, - src->standard_font_family.length, &target->standard_font_family, copy); - cef_string_set(src->fixed_font_family.str, src->fixed_font_family.length, - &target->fixed_font_family, copy); - cef_string_set(src->serif_font_family.str, src->serif_font_family.length, - &target->serif_font_family, copy); - cef_string_set(src->sans_serif_font_family.str, - src->sans_serif_font_family.length, &target->sans_serif_font_family, - copy); - cef_string_set(src->cursive_font_family.str, - src->cursive_font_family.length, &target->cursive_font_family, copy); - cef_string_set(src->fantasy_font_family.str, - src->fantasy_font_family.length, &target->fantasy_font_family, copy); - - target->default_font_size = src->default_font_size; - target->default_fixed_font_size = src->default_fixed_font_size; - target->minimum_font_size = src->minimum_font_size; - target->minimum_logical_font_size = src->minimum_logical_font_size; - target->remote_fonts_disabled = src->remote_fonts_disabled; - - cef_string_set(src->default_encoding.str, src->default_encoding.length, - &target->default_encoding, copy); - - target->encoding_detector_enabled = src->encoding_detector_enabled; - target->javascript_disabled = src->javascript_disabled; - target->javascript_open_windows_disallowed = - src->javascript_open_windows_disallowed; - target->javascript_close_windows_disallowed = - src->javascript_close_windows_disallowed; - target->javascript_access_clipboard_disallowed = - src->javascript_access_clipboard_disallowed; - target->dom_paste_disabled = src->dom_paste_disabled; - target->caret_browsing_enabled = src->caret_browsing_enabled; - target->java_disabled = src->java_disabled; - target->plugins_disabled = src->plugins_disabled; - target->universal_access_from_file_urls_allowed = - src->universal_access_from_file_urls_allowed; - target->file_access_from_file_urls_allowed = - src->file_access_from_file_urls_allowed; - target->web_security_disabled = src->web_security_disabled; - target->xss_auditor_enabled = src->xss_auditor_enabled; - target->image_load_disabled = src->image_load_disabled; - target->shrink_standalone_images_to_fit = - src->shrink_standalone_images_to_fit; - target->site_specific_quirks_disabled = src->site_specific_quirks_disabled; - target->text_area_resize_disabled = src->text_area_resize_disabled; - target->page_cache_disabled = src->page_cache_disabled; - target->tab_to_links_disabled = src->tab_to_links_disabled; - target->hyperlink_auditing_disabled = src->hyperlink_auditing_disabled; - target->user_style_sheet_enabled = src->user_style_sheet_enabled; - - cef_string_set(src->user_style_sheet_location.str, - src->user_style_sheet_location.length, - &target->user_style_sheet_location, copy); - - target->author_and_user_styles_disabled = - src->author_and_user_styles_disabled; - target->local_storage_disabled = src->local_storage_disabled; - target->databases_disabled = src->databases_disabled; - target->application_cache_disabled = src->application_cache_disabled; - target->webgl_disabled = src->webgl_disabled; - target->accelerated_compositing_enabled = - src->accelerated_compositing_enabled; - target->accelerated_layers_disabled = src->accelerated_layers_disabled; - target->accelerated_video_disabled = src->accelerated_video_disabled; - target->accelerated_2d_canvas_disabled = - src->accelerated_2d_canvas_disabled; - target->accelerated_filters_disabled = src->accelerated_filters_disabled; - target->accelerated_plugins_disabled = src->accelerated_plugins_disabled; - target->developer_tools_disabled = src->developer_tools_disabled; - target->fullscreen_enabled = src->fullscreen_enabled; - } -}; - -/// -// Class representing browser initialization settings. -/// -typedef CefStructBase CefBrowserSettings; - - -struct CefURLPartsTraits { - typedef cef_urlparts_t struct_type; - - static inline void init(struct_type* s) {} - - static inline void clear(struct_type* s) { - cef_string_clear(&s->spec); - cef_string_clear(&s->scheme); - cef_string_clear(&s->username); - cef_string_clear(&s->password); - cef_string_clear(&s->host); - cef_string_clear(&s->port); - cef_string_clear(&s->path); - cef_string_clear(&s->query); - } - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - cef_string_set(src->spec.str, src->spec.length, &target->spec, copy); - cef_string_set(src->scheme.str, src->scheme.length, &target->scheme, copy); - cef_string_set(src->username.str, src->username.length, &target->username, - copy); - cef_string_set(src->password.str, src->password.length, &target->password, - copy); - cef_string_set(src->host.str, src->host.length, &target->host, copy); - cef_string_set(src->port.str, src->port.length, &target->port, copy); - cef_string_set(src->path.str, src->path.length, &target->path, copy); - cef_string_set(src->query.str, src->query.length, &target->query, copy); - } -}; - -/// -// Class representing a URL's component parts. -/// -typedef CefStructBase CefURLParts; - - -struct CefTimeTraits { - typedef cef_time_t struct_type; - - static inline void init(struct_type* s) {} - - static inline void clear(struct_type* s) {} - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - *target = *src; - } -}; - -/// -// Class representing a time. -/// -class CefTime : public CefStructBase { - public: - typedef CefStructBase parent; - - CefTime() : parent() {} - CefTime(const cef_time_t& r) : parent(r) {} // NOLINT(runtime/explicit) - CefTime(const CefTime& r) : parent(r) {} // NOLINT(runtime/explicit) - explicit CefTime(time_t r) : parent() { SetTimeT(r); } - explicit CefTime(double r) : parent() { SetDoubleT(r); } - - // Converts to/from time_t. - void SetTimeT(time_t r) { - cef_time_from_timet(r, this); - } - time_t GetTimeT() const { - time_t time = 0; - cef_time_to_timet(this, &time); - return time; - } - - // Converts to/from a double which is the number of seconds since epoch - // (Jan 1, 1970). Webkit uses this format to represent time. A value of 0 - // means "not initialized". - void SetDoubleT(double r) { - cef_time_from_doublet(r, this); - } - double GetDoubleT() const { - double time = 0; - cef_time_to_doublet(this, &time); - return time; - } - - // Set this object to now. - void Now() { - cef_time_now(this); - } - - // Return the delta between this object and |other| in milliseconds. - long long Delta(const CefTime& other) { - long long delta = 0; - cef_time_delta(this, &other, &delta); - return delta; - } -}; - - -struct CefCookieTraits { - typedef cef_cookie_t struct_type; - - static inline void init(struct_type* s) {} - - static inline void clear(struct_type* s) { - cef_string_clear(&s->name); - cef_string_clear(&s->value); - cef_string_clear(&s->domain); - cef_string_clear(&s->path); - } - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - cef_string_set(src->name.str, src->name.length, &target->name, copy); - cef_string_set(src->value.str, src->value.length, &target->value, copy); - cef_string_set(src->domain.str, src->domain.length, &target->domain, copy); - cef_string_set(src->path.str, src->path.length, &target->path, copy); - target->secure = src->secure; - target->httponly = src->httponly; - target->creation = src->creation; - target->last_access = src->last_access; - target->has_expires = src->has_expires; - target->expires = src->expires; - } -}; - -/// -// Class representing a cookie. -/// -typedef CefStructBase CefCookie; - - -struct CefMenuInfoTraits { - typedef cef_menu_info_t struct_type; - - static inline void init(struct_type* s) {} - - static inline void clear(struct_type* s) { - cef_string_clear(&s->linkUrl); - cef_string_clear(&s->imageUrl); - cef_string_clear(&s->pageUrl); - cef_string_clear(&s->frameUrl); - cef_string_clear(&s->selectionText); - cef_string_clear(&s->misspelledWord); - cef_string_clear(&s->securityInfo); - } - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - target->typeFlags = src->typeFlags; - target->x = src->x; - target->y = src->y; - - cef_string_set(src->linkUrl.str, src->linkUrl.length, - &target->linkUrl, copy); - cef_string_set(src->imageUrl.str, src->imageUrl.length, - &target->imageUrl, copy); - cef_string_set(src->pageUrl.str, src->pageUrl.length, - &target->pageUrl, copy); - cef_string_set(src->frameUrl.str, src->frameUrl.length, - &target->frameUrl, copy); - cef_string_set(src->selectionText.str, src->selectionText.length, - &target->selectionText, copy); - cef_string_set(src->misspelledWord.str, src->misspelledWord.length, - &target->misspelledWord, copy); - cef_string_set(src->securityInfo.str, src->securityInfo.length, - &target->securityInfo, copy); - - target->editFlags = src->editFlags; - } -}; - -/// -// Class representing menu info. -/// -typedef CefStructBase CefMenuInfo; - - -struct CefProxyInfoTraits { - typedef cef_proxy_info_t struct_type; - - static inline void init(struct_type* s) {} - - static inline void clear(struct_type* s) { - cef_string_clear(&s->proxyList); - } - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - target->proxyType = src->proxyType; - cef_string_set(src->proxyList.str, src->proxyList.length, - &target->proxyList, copy); - } -}; - -/// -// Class representing the results of proxy resolution. -/// -class CefProxyInfo : public CefStructBase { - public: - /// - // Use a direction connection instead of a proxy. - /// - void UseDirect() { - proxyType = CEF_PROXY_TYPE_DIRECT; - } - - /// - // Use one or more named proxy servers specified in WinHTTP format. Each proxy - // server is of the form: - // - // ["://"][":"] - // - // Multiple values may be separated by semicolons or whitespace. For example, - // "foo1:80;foo2:80". - /// - void UseNamedProxy(const CefString& proxy_uri_list) { - proxyType = CEF_PROXY_TYPE_NAMED; - (CefString(&proxyList)) = proxy_uri_list; - } - - /// - // Use one or more named proxy servers specified in PAC script format. For - // example, "PROXY foobar:99; SOCKS fml:2; DIRECT". - /// - void UsePacString(const CefString& pac_string) { - proxyType = CEF_PROXY_TYPE_PAC_STRING; - (CefString(&proxyList)) = pac_string; - } - - bool IsDirect() const { return proxyType == CEF_PROXY_TYPE_DIRECT; } - bool IsNamedProxy() const { return proxyType == CEF_PROXY_TYPE_NAMED; } - bool IsPacString() const { return proxyType == CEF_PROXY_TYPE_PAC_STRING; } - - CefString ProxyList() const { return CefString(&proxyList); } -}; - - -struct CefGeopositionTraits { - typedef cef_geoposition_t struct_type; - - static inline void init(struct_type* s) {} - - static inline void clear(struct_type* s) { - cef_string_clear(&s->error_message); - } - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - target->latitude = src->latitude; - target->longitude = src->longitude; - target->altitude = src->altitude; - target->accuracy = src->accuracy; - target->altitude_accuracy = src->altitude_accuracy; - target->heading = src->heading; - target->speed = src->speed; - target->timestamp = src->timestamp; - target->error_code = src->error_code; - cef_string_set(src->error_message.str, src->error_message.length, - &target->error_message, copy); - } -}; - -/// -// Class representing a geoposition. -/// -typedef CefStructBase CefGeoposition; - -#endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_WRAPPERS_H_ diff --git a/cefpython/cef1/include/internal/cef_win.h b/cefpython/cef1/include/internal/cef_win.h deleted file mode 100644 index 68d91dced..000000000 --- a/cefpython/cef1/include/internal/cef_win.h +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (c) 2008 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -#ifndef CEF_INCLUDE_INTERNAL_CEF_WIN_H_ -#define CEF_INCLUDE_INTERNAL_CEF_WIN_H_ -#pragma once - -#if defined(OS_WIN) -#include -#include "include/internal/cef_types_win.h" -#include "include/internal/cef_types_wrappers.h" - -/// -// Atomic increment and decrement. -/// -#define CefAtomicIncrement(p) InterlockedIncrement(p) -#define CefAtomicDecrement(p) InterlockedDecrement(p) - -/// -// Critical section wrapper. -/// -class CefCriticalSection { - public: - CefCriticalSection() { - memset(&m_sec, 0, sizeof(CRITICAL_SECTION)); - InitializeCriticalSection(&m_sec); - } - virtual ~CefCriticalSection() { - DeleteCriticalSection(&m_sec); - } - void Lock() { - EnterCriticalSection(&m_sec); - } - void Unlock() { - LeaveCriticalSection(&m_sec); - } - - CRITICAL_SECTION m_sec; -}; - -/// -// Handle types. -/// -#define CefWindowHandle cef_window_handle_t -#define CefCursorHandle cef_cursor_handle_t - -struct CefWindowInfoTraits { - typedef cef_window_info_t struct_type; - - static inline void init(struct_type* s) {} - - static inline void clear(struct_type* s) { - cef_string_clear(&s->m_windowName); - } - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - target->m_dwExStyle = src->m_dwExStyle; - cef_string_set(src->m_windowName.str, src->m_windowName.length, - &target->m_windowName, copy); - target->m_dwStyle = src->m_dwStyle; - target->m_x = src->m_x; - target->m_y = src->m_y; - target->m_nWidth = src->m_nWidth; - target->m_nHeight = src->m_nHeight; - target->m_hWndParent = src->m_hWndParent; - target->m_hMenu = src->m_hMenu; - target->m_bWindowRenderingDisabled = src->m_bWindowRenderingDisabled; - target->m_bTransparentPainting = src->m_bTransparentPainting; - target->m_hWnd = src->m_hWnd; - } -}; - -/// -// Class representing window information. -/// -class CefWindowInfo : public CefStructBase { - public: - typedef CefStructBase parent; - - CefWindowInfo() : parent() {} - explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {} - explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {} - - void SetAsChild(HWND hWndParent, RECT windowRect) { - m_dwStyle = WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_TABSTOP | - WS_VISIBLE; - m_hWndParent = hWndParent; - m_x = windowRect.left; - m_y = windowRect.top; - m_nWidth = windowRect.right - windowRect.left; - m_nHeight = windowRect.bottom - windowRect.top; - } - - void SetAsPopup(HWND hWndParent, const CefString& windowName) { - m_dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | - WS_VISIBLE; - m_hWndParent = hWndParent; - m_x = CW_USEDEFAULT; - m_y = CW_USEDEFAULT; - m_nWidth = CW_USEDEFAULT; - m_nHeight = CW_USEDEFAULT; - - cef_string_copy(windowName.c_str(), windowName.length(), &m_windowName); - } - - void SetAsOffScreen(HWND hWndParent) { - m_bWindowRenderingDisabled = TRUE; - m_hWndParent = hWndParent; - } - - void SetTransparentPainting(BOOL transparentPainting) { - m_bTransparentPainting = transparentPainting; - } -}; - - -struct CefPrintInfoTraits { - typedef cef_print_info_t struct_type; - - static inline void init(struct_type* s) {} - static inline void clear(struct_type* s) {} - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - target->m_hDC = src->m_hDC; - target->m_Rect = src->m_Rect; - target->m_Scale = src->m_Scale; - } -}; - -/// -// Class representing print context information. -/// -typedef CefStructBase CefPrintInfo; - - -struct CefKeyInfoTraits { - typedef cef_key_info_t struct_type; - - static inline void init(struct_type* s) {} - static inline void clear(struct_type* s) {} - - static inline void set(const struct_type* src, struct_type* target, - bool copy) { - target->key = src->key; - target->sysChar = src->sysChar; - target->imeChar = src->imeChar; - } -}; - -/// -// Class representing key information. -/// -typedef CefStructBase CefKeyInfo; - -#endif // OS_WIN - -#endif // CEF_INCLUDE_INTERNAL_CEF_WIN_H_ diff --git a/cefpython/cef1/include/wrapper/cef_byte_read_handler.h b/cefpython/cef1/include/wrapper/cef_byte_read_handler.h deleted file mode 100644 index f7ca7a15a..000000000 --- a/cefpython/cef1/include/wrapper/cef_byte_read_handler.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file are only available to applications that link -// against the libcef_dll_wrapper target. -// - -#ifndef CEF_INCLUDE_WRAPPER_CEF_BYTE_READ_HANDLER_H_ -#define CEF_INCLUDE_WRAPPER_CEF_BYTE_READ_HANDLER_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_stream.h" - -/// -// Thread safe implementation of the CefReadHandler class for reading an -// in-memory array of bytes. -/// -class CefByteReadHandler : public CefReadHandler { - public: - /// - // Create a new object for reading an array of bytes. An optional |source| - // reference can be kept to keep the underlying data source from being - // released while the reader exists. - /// - CefByteReadHandler(const unsigned char* bytes, size_t size, - CefRefPtr source); - - /// - // Read raw binary data. - /// - virtual size_t Read(void* ptr, size_t size, size_t n); - - /// - // Seek to the specified offset position. |whence| may be any one of - // SEEK_CUR, SEEK_END or SEEK_SET. - /// - virtual int Seek(int64 offset, int whence); - - /// - // Return the current offset position. - /// - virtual int64 Tell(); - - /// - // Return non-zero if at end of file. - /// - virtual int Eof(); - - private: - const unsigned char* bytes_; - int64 size_; - int64 offset_; - CefRefPtr source_; - - IMPLEMENT_REFCOUNTING(CefByteReadHandler); - IMPLEMENT_LOCKING(CefByteReadHandler); -}; - -#endif // CEF_INCLUDE_WRAPPER_CEF_BYTE_READ_HANDLER_H_ diff --git a/cefpython/cef1/include/wrapper/cef_xml_object.h b/cefpython/cef1/include/wrapper/cef_xml_object.h deleted file mode 100644 index d9f706fde..000000000 --- a/cefpython/cef1/include/wrapper/cef_xml_object.h +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file are only available to applications that link -// against the libcef_dll_wrapper target. -// - -#ifndef CEF_INCLUDE_WRAPPER_CEF_XML_OBJECT_H_ -#define CEF_INCLUDE_WRAPPER_CEF_XML_OBJECT_H_ -#pragma once - -#include "include/cef_base.h" -#include "include/cef_xml_reader.h" -#include -#include - -class CefStreamReader; - -/// -// Thread safe class for representing XML data as a structured object. This -// class should not be used with large XML documents because all data will be -// resident in memory at the same time. This implementation supports a -// restricted set of XML features: -//
-// (1) Processing instructions, whitespace and comments are ignored.
-// (2) Elements and attributes must always be referenced using the fully
-//     qualified name (ie, namespace:localname).
-// (3) Empty elements () and elements with zero-length values ()
-//     are considered the same.
-// (4) Element nodes are considered part of a value if:
-//     (a) The element node follows a non-element node at the same depth
-//         (see 5), or
-//     (b) The element node does not have a namespace and the parent node does.
-// (5) Mixed node types at the same depth are combined into a single element
-//     value as follows:
-//     (a) All node values are concatenated to form a single string value.
-//     (b) Entity reference nodes are resolved to the corresponding entity
-//         value.
-//     (c) Element nodes are represented by their outer XML string.
-// 
-/// -class CefXmlObject : public CefBase { - public: - typedef std::vector > ObjectVector; - typedef std::map AttributeMap; - - /// - // Create a new object with the specified name. An object name must always be - // at least one character long. - /// - explicit CefXmlObject(const CefString& name); - virtual ~CefXmlObject(); - - /// - // Load the contents of the specified XML stream into this object. The - // existing children and attributes, if any, will first be cleared. - /// - bool Load(CefRefPtr stream, - CefXmlReader::EncodingType encodingType, - const CefString& URI, CefString* loadError); - - /// - // Set the name, children and attributes of this object to a duplicate of the - // specified object's contents. The existing children and attributes, if any, - // will first be cleared. - /// - void Set(CefRefPtr object); - - /// - // Append a duplicate of the children and attributes of the specified object - // to this object. If |overwriteAttributes| is true then any attributes in - // this object that also exist in the specified object will be overwritten - // with the new values. The name of this object is not changed. - /// - void Append(CefRefPtr object, bool overwriteAttributes); - - /// - // Return a new object with the same name, children and attributes as this - // object. The parent of the new object will be NULL. - /// - CefRefPtr Duplicate(); - - /// - // Clears this object's children and attributes. The name and parenting of - // this object are not changed. - /// - void Clear(); - - /// - // Access the object's name. An object name must always be at least one - // character long. - /// - CefString GetName(); - bool SetName(const CefString& name); - - /// - // Access the object's parent. The parent can be NULL if this object has not - // been added as the child on another object. - /// - bool HasParent(); - CefRefPtr GetParent(); - - /// - // Access the object's value. An object cannot have a value if it also has - // children. Attempting to set the value while children exist will fail. - /// - bool HasValue(); - CefString GetValue(); - bool SetValue(const CefString& value); - - /// - // Access the object's attributes. Attributes must have unique names. - /// - bool HasAttributes(); - size_t GetAttributeCount(); - bool HasAttribute(const CefString& name); - CefString GetAttributeValue(const CefString& name); - bool SetAttributeValue(const CefString& name, const CefString& value); - size_t GetAttributes(AttributeMap& attributes); - void ClearAttributes(); - - /// - // Access the object's children. Each object can only have one parent so - // attempting to add an object that already has a parent will fail. Removing a - // child will set the child's parent to NULL. Adding a child will set the - // child's parent to this object. This object's value, if any, will be cleared - // if a child is added. - /// - bool HasChildren(); - size_t GetChildCount(); - bool HasChild(CefRefPtr child); - bool AddChild(CefRefPtr child); - bool RemoveChild(CefRefPtr child); - size_t GetChildren(ObjectVector& children); - void ClearChildren(); - - /// - // Find the first child with the specified name. - /// - CefRefPtr FindChild(const CefString& name); - - /// - // Find all children with the specified name. - /// - size_t FindChildren(const CefString& name, ObjectVector& children); - - private: - void SetParent(CefXmlObject* parent); - - CefString name_; - CefXmlObject* parent_; - CefString value_; - AttributeMap attributes_; - ObjectVector children_; - - IMPLEMENT_REFCOUNTING(CefXmlObject); - IMPLEMENT_LOCKING(CefXmlObject); -}; - -#endif // CEF_INCLUDE_WRAPPER_CEF_XML_OBJECT_H_ diff --git a/cefpython/cef1/include/wrapper/cef_zip_archive.h b/cefpython/cef1/include/wrapper/cef_zip_archive.h deleted file mode 100644 index b58dbca01..000000000 --- a/cefpython/cef1/include/wrapper/cef_zip_archive.h +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --------------------------------------------------------------------------- -// -// The contents of this file are only available to applications that link -// against the libcef_dll_wrapper target. -// - -#ifndef CEF_INCLUDE_WRAPPER_CEF_ZIP_ARCHIVE_H_ -#define CEF_INCLUDE_WRAPPER_CEF_ZIP_ARCHIVE_H_ -#pragma once - -#include "include/cef_base.h" -#include - -class CefStreamReader; - -/// -// Thread-safe class for accessing zip archive file contents. This class should -// not be used with large archive files because all data will be resident in -// memory at the same time. This implementation supports a restricted set of zip -// archive features: -// (1) Password-protected files are not supported. -// (2) All file names are stored and compared in lower case. -// (3) File ordering from the original zip archive is not maintained. This -// means that files from the same folder may not be located together in the -// file content map. -/// -class CefZipArchive : public CefBase { - public: - /// - // 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 { - public: - /// - // Returns the read-only data contained in the file. - /// - virtual const unsigned char* GetData() =0; - - /// - // Returns the size of the data in the file. - /// - virtual size_t GetDataSize() =0; - - /// - // Returns a CefStreamReader object for streaming the contents of the file. - /// - virtual CefRefPtr GetStreamReader() =0; - }; - typedef std::map > FileMap; - - /// - // Create a new object. - /// - CefZipArchive(); - virtual ~CefZipArchive(); - - /// - // Load the contents of the specified zip archive stream into this object. - // If |overwriteExisting| is true then any files in this object that also - // exist in the specified archive will be replaced with the new files. - // Returns the number of files successfully loaded. - /// - size_t Load(CefRefPtr stream, bool overwriteExisting); - - /// - // Clears the contents of this object. - /// - void Clear(); - - /// - // Returns the number of files in the archive. - /// - size_t GetFileCount(); - - /// - // Returns true if the specified file exists and has contents. - /// - bool HasFile(const CefString& fileName); - - /// - // Returns the specified file. - /// - CefRefPtr GetFile(const CefString& fileName); - - /// - // Removes the specified file. - /// - bool RemoveFile(const CefString& fileName); - - /// - // Returns the map of all files. - /// - size_t GetFiles(FileMap& map); - - private: - FileMap contents_; - - IMPLEMENT_REFCOUNTING(CefZipArchive); - IMPLEMENT_LOCKING(CefZipArchive); -}; - -#endif // CEF_INCLUDE_WRAPPER_CEF_ZIP_ARCHIVE_H_ diff --git a/cefpython/cef1/linux/CEF-GTK-patch.txt b/cefpython/cef1/linux/CEF-GTK-patch.txt deleted file mode 100644 index fba8f3a13..000000000 --- a/cefpython/cef1/linux/CEF-GTK-patch.txt +++ /dev/null @@ -1,54 +0,0 @@ -See this topic on the CEF C++ forum for more details: -http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=10641 - -Do the following changes in the CEF C++ sources: - -1. In `chromium/src/cef/libcef/browser_impl_gtk.cc`: - - At the end of the CefBrowserImpl::UIT_CreateBrowser() function, - before the return statement add the following code: - - gtk_widget_show_all(GTK_WIDGET(window_info_.m_Widget)); - -2. In `chromium/src/cef/libcef/webwidget_host_gtk.cc`: - - In WebWidgetHostGtkWidget::CreateNewWidget() function replace this line: - - gtk_box_pack_start(GTK_BOX(parent_view), widget, TRUE, TRUE, 0); - - With the following code: - - if (GTK_IS_BOX(parent_view)) { - gtk_box_pack_start(GTK_BOX(parent_view), widget, TRUE, TRUE, 0); - } else { - // Parent view shouldn't contain any children, but in wxWidgets library - // there will be GtkPizza widget for Panel or any other control. - GList *children, *iter; - children = gtk_container_get_children(GTK_CONTAINER(parent_view)); - GtkWidget* child = NULL; - GtkWidget* vbox = gtk_vbox_new(FALSE, 0); - for (iter = children; iter != NULL; iter = g_list_next(iter)) { - child = GTK_WIDGET(iter->data); - // We will have to keep a reference to that child that we remove, - // otherwise we will get lots of warnings like "invalid unclassed - // pointer in cast to `GtkPizza'". First we increase a reference, - // we need to do this for a moment before we add this child to the - // vbox, then we will decrease that reference. - g_object_ref(G_OBJECT(child)); - gtk_container_remove(GTK_CONTAINER(parent_view), child); - } - g_list_free(children); - gtk_box_pack_start(GTK_BOX(vbox), widget, TRUE, TRUE, 0); - if (child != NULL) { - // This child is packed to the box only so that its reference lives, - // as it might be referenced from other code thus resulting in errors. - gtk_box_pack_end(GTK_BOX(vbox), child, FALSE, FALSE, 0); - gtk_widget_hide(GTK_WIDGET(child)); - g_object_unref(G_OBJECT(child)); - } - gtk_widget_show(GTK_WIDGET(vbox)); - if (GTK_IS_SCROLLED_WINDOW(parent_view)) - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(parent_view), vbox); - else - gtk_container_add(GTK_CONTAINER(parent_view), vbox); - } diff --git a/cefpython/cef1/linux/binaries_32bit/LICENSE.txt b/cefpython/cef1/linux/binaries_32bit/LICENSE.txt deleted file mode 100644 index 97f1e9616..000000000 --- a/cefpython/cef1/linux/binaries_32bit/LICENSE.txt +++ /dev/null @@ -1,36 +0,0 @@ -Copyright (c) 2012-2013 Czarek Tomczak. Portions Copyright -(c) 2008-2013 Marshall A.Greenblatt, 2006-2009 Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with -or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of Google Inc. nor the name Chromium - Embedded Framework nor the name of CEF Python nor the - names of its contributors may be used to endorse or - promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/cefpython/cef1/linux/binaries_32bit/cefpython_py27.py b/cefpython/cef1/linux/binaries_32bit/cefpython_py27.py deleted file mode 100644 index 0b0e988ce..000000000 --- a/cefpython/cef1/linux/binaries_32bit/cefpython_py27.py +++ /dev/null @@ -1,815 +0,0 @@ -# This file contains API for the "cefpython.pyd" module, all functions are dummy. -# Use it as a quick reference. Use it for code completion in your IDE. -# This file does NOT need to be distribitued along with binaries. - -raise Exception("A dummy API file was imported instead of the PYD module.") - -""" -Detailed documentation with examples can be found on wiki pages: -http://code.google.com/p/cefpython/w/list -""" - -# Global functions in cefpython module. - -def CreateBrowserSync(windowInfo, browserSettings, navigateUrl): - return Browser() - -def FormatJavascriptStackTrace(stackTrace): - return "" - -def GetBrowserByWindowHandle(windowHandle): - return Browser() - -def GetJavascriptStackTrace(frameLimit=100): - return [] - -def Initialize(applicationSettings={}): - return None - -def IsKeyModifier(key, modifiers): - return False - -def MessageLoop(): - return None - -def MessageLoopWork(): - return None - -def QuitMessageLoop(): - return None - -def Shutdown(): - return None - -def GetModuleDirectory(): - return "" - -# -# Settings -# - -# Values are dummy, these are NOT the defaults. -ApplicationSettings = { - "auto_detect_proxy_settings_enabled": False, - "cache_path": "", - "extra_plugin_paths": [""], - "graphics_implementation": ANGLE_IN_PROCESS, - "javascript_flags": "", - "local_storage_quota": 5*1024*1024, - "locale": "", - "locales_dir_path": "", - "log_file": "", - "log_severity": LOGSEVERITY_INFO, - "release_dcheck_enabled": False, - "multi_threaded_message_loop": False, - "pack_loading_disabled": False, - "product_version": "", - "resources_dir_path": "", - "session_storage_quota": 5*1024*1024, - "string_encoding": "utf-8", - "uncaught_exception_stack_size": 0, - "user_agent": "", -} - -# ApplicationSettings["log_severity"] -LOGSEVERITY_VERBOSE = 0 -LOGSEVERITY_INFO = 0 -LOGSEVERITY_WARNING = 0 -LOGSEVERITY_ERROR = 0 -LOGSEVERITY_ERROR_REPORT = 0 -LOGSEVERITY_DISABLE = 0 - -# ApplicationSettings["graphics_implementation"] -ANGLE_IN_PROCESS = 0 -ANGLE_IN_PROCESS_COMMAND_BUFFER = 0 -DESKTOP_IN_PROCESS = 0 -DESKTOP_IN_PROCESS_COMMAND_BUFFER = 0 - -# Values are dummy, these are NOT the defaults. -BrowserSettings = { - "accelerated_2d_canvas_disabled": False, - "accelerated_compositing_enabled": False, - "accelerated_filters_disabled": False, - "accelerated_layers_disabled": False, - "accelerated_plugins_disabled": False, - "accelerated_video_disabled": False, - "animation_frame_rate": 0, - "application_cache_disabled": False, - "author_and_user_styles_disabled": False, - "caret_browsing_enabled": False, - "cursive_font_family": "", - "databases_disabled": False, - "default_encoding": "iso-8859-1", - "default_fixed_font_size": 0, - "default_font_size": 0, - "developer_tools_disabled": False, - "dom_paste_disabled": False, - "drag_drop_disabled": False, - "encoding_detector_enabled": False, - "fantasy_font_family": "", - "file_access_from_file_urls_allowed": False, - "fixed_font_family": "", - "fullscreen_enabled": False, - "history_disabled": False, - "hyperlink_auditing_disabled": False, - "image_load_disabled": False, - "java_disabled": False, - "javascript_access_clipboard_disallowed": False, - "javascript_close_windows_disallowed": False, - "javascript_disabled": False, - "javascript_open_windows_disallowed": False, - "load_drops_disabled": False, - "local_storage_disabled": False, - "minimum_font_size": 0, - "minimum_logical_font_size": 0, - "page_cache_disabled": False, - "plugins_disabled": False, - "remote_fonts_disabled": False, - "sans_serif_font_family": "", - "serif_font_family": "", - "shrink_standalone_images_to_fit": False, - "site_specific_quirks_disabled": False, - "standard_font_family": "", - "tab_to_links_disabled": False, - "text_area_resize_disabled": False, - "universal_access_from_file_urls_allowed": False, - "user_style_sheet_enabled": False, - "user_style_sheet_location": "", - "web_security_disabled": False, - "webgl_disabled": False, - "xss_auditor_enabled": False, -} - -# -# Browser object. -# - -class Browser: - - def CanGoBack(self): - return False - - def CanGoForward(self): - return False - - def ClearHistory(self): - return None - - def CloseBrowser(self): - return None - - def CloseDevTools(self): - return None - - def Find(self, searchID, searchText, forward, matchCase, findNext): - return None - - def GetClientCallback(self, name): - return callback - - def GetClientCallbacksDict(self): - return {} - - def GetFocusedFrame(self): - return Frame() - - def GetFrame(self): - return Frame() - - def GetFrameNames(self): - return ["", ""] - - def GetIdentifier(self): - return 0 - - def GetImage(self, paintElementType, width, height): - return PaintBuffer() - - def GetJavascriptBindings(self): - return JavascriptBindings() - - def GetMainFrame(self): - return Frame() - - def GetOpenerWindowHandle(self): - return 0 - - def GetOuterWindowHandle(self): - return 0 - - def GetSize(self, paintElementType): - return (0,0,) - - def GetUserData(self, key): - return None - - def GetWindowID(self): - return windowID - - def GetWindowHandle(self): - return 0 - - def GetZoomLevel(self): - return 0.0 - - def GoBack(self): - return None - - def GoForward(self): - return None - - def HasDocument(self): - return False - - def HidePopup(self): - return None - - def Invalidate(self, dirtyRect): - return None - - def IsFullscreen(self): - return False - - def IsPopup(self): - return False - - def IsPopupVisible(self): - return False - - def IsWindowRenderingDisabled(self): - return False - - def Reload(self): - return None - - def ReloadIgnoreCache(self): - return None - - def SendKeyEvent(self, keyType, keyInfo, modifiers): - return None - - def SendMouseClickEvent(self, x, y, mouseButtonType, mouseUp, clickCount): - return None - - def SendMouseMoveEvent(self, x, y, mouseLeave): - return None - - def SendMouseWheelEvent(self, x, y, deltaX, deltaY): - return None - - def SendFocusEvent(self, setFocus): - return None - - def SendCaptureLostEvent(self): - return None - - def SetClientCallback(self, name, callback): - return None - - def SetClientHandler(self, clientHandler): - return None - - def SetFocus(self, enable): - return None - - def SetJavascriptBindings(self, javascriptBindings): - return None - - def SetSize(self, paintElementType, width, height): - return None - - def SetZoomLevel(self, zoomLevel): - return None - - def SetUserData(self, key, value): - return None - - def ShowDevTools(self): - return None - - def StopLoad(self): - return None - - def StopFinding(self, clearSelection): - return None - - def ToggleFullscreen(self): - return None - -# -# Frame object. -# - -class Frame: - - def Copy(self): - return None - - def Cut(self): - return None - - def Delete(self): - return None - - def ExecuteJavascript(self, jsCode, scriptUrl=None, startLine=None): - return None - - def GetIdentifier(self): - return 0 - - def GetName(self): - return "" - - def GetProperty(self, name): - return mixed - - def GetSource(self): - return "" - - def GetText(self): - return "" - - def GetUrl(self): - return "" - - def IsFocused(self): - return False - - def IsMain(self): - return False - - def LoadString(self, value, url): - return None - - def LoadUrl(self, url): - return None - - def Paste(self): - return None - - def Print(self): - return None - - def Redo(self): - return None - - def SelectAll(self): - return None - - def SetProperty(self, name, value): - return None - - def Undo(self): - return None - - def ViewSource(self): - return None - -class Response: - - def GetStatus(self): - return 0 - - def SetStatus(self, status): - return None - - def GetStatusText(self): - return "" - - def SetStatusText(self, statusText): - return None - - def GetMimeType(self): - return "" - - def SetMimeType(self, mimeType): - return None - - def GetHeader(self, name): - return "" - - def GetHeaderMap(self): - return {} - - def GetHeaderMultimap(self): - return [("","")] - - def SetHeaderMap(self, headerMap={}): - return None - - def SetHeaderMultimap(self, headerMultimap=[]): - return None - -class PaintBuffer: - - def GetIntPointer(self): - return 0 - - def GetString(self, mode="bgra", origin="top-left"): - return "" - -class JavascriptBindings: - - def __init__(self, bindToFrames=False, bindToPopups=False): - return None - - def IsValueAllowed(self, value): - return False - - def Rebind(self): - return None - - def SetFunction(self, name, func): - return None - - def SetObject(self, name, obj): - return None - - def SetProperty(self, name, value): - return None - -class JavascriptCallback: - - def Call(self, param1, param2, param3_etc): - return mixed - - def GetName(self): - return name - -class WindowUtils: - - @staticmethod - def OnSetFocus(windowID, msg, wparam, lparam): - return 0 - - @staticmethod - def OnSize(windowID, msg, wparam, lparam): - return 0 - - @staticmethod - def OnEraseBackground(windowID, msg, wparam, lparam): - return 0 - - @staticmethod - def SetTitle(pyBrowser, pyTitle): - return None - - @staticmethod - def SetIcon(pyBrowser, icon="inherit"): - return None - -# -# DisplayHandler. -# - -# statusType constants (OnStatusMessage). -STATUSTYPE_TEXT = 0 -STATUSTYPE_MOUSEOVER_URL = 0 -STATUSTYPE_KEYBOARD_FOCUS_URL = 0 - -def DisplayHandler_OnAddressChange(browser, frame, url): - return None - -def DisplayHandler_OnConsoleMessage(browser, message, source, line): - return False - -def DisplayHandler_OnContentsSizeChange(browser, frame, width, height): - return None - -def DisplayHandler_OnNavStateChange(browser, canGoBack, canGoForward): - return None - -def DisplayHandler_OnStatusMessage(browser, text, statusType): - return None - -def DisplayHandler_OnTitleChange(browser, title): - return None - -def DisplayHandler_OnTooltip(browser, text_out=[""]): - return False - -# -# KeyboardHandler. -# - -def KeyboardHandler_OnKeyEvent( - browser, eventType, keyCode, modifiers, isSystemKey, isAfterJavascript): - return False - -# keyCode constants (OnKeyEvent). -VK_0=0x30 -VK_1=0x31 -VK_2=0x32 -VK_3=0x33 -VK_4=0x34 -VK_5=0x35 -VK_6=0x36 -VK_7=0x37 -VK_8=0x38 -VK_9=0x39 -VK_A=0x041 -VK_B=0x042 -VK_C=0x043 -VK_D=0x044 -VK_E=0x045 -VK_F=0x046 -VK_G=0x047 -VK_H=0x048 -VK_I=0x049 -VK_J=0x04A -VK_K=0x04B -VK_L=0x04C -VK_M=0x04D -VK_N=0x04E -VK_O=0x04F -VK_P=0x050 -VK_Q=0x051 -VK_R=0x052 -VK_S=0x053 -VK_T=0x054 -VK_U=0x055 -VK_V=0x056 -VK_W=0x057 -VK_X=0x058 -VK_Y=0x059 -VK_Z=0x05A -VK_F1=0x70 -VK_F2=0x71 -VK_F3=0x72 -VK_F4=0x73 -VK_F5=0x74 -VK_F6=0x75 -VK_F7=0x76 -VK_F8=0x77 -VK_F9=0x78 -VK_F10=0x79 -VK_F11=0x7A -VK_F12=0x7B -VK_F13=0x7C -VK_F14=0x7D -VK_F15=0x7E -VK_F16=0x7F -VK_F17=0x80 -VK_F18=0x81 -VK_F19=0x82 -VK_F20=0x83 -VK_F21=0x84 -VK_F22=0x85 -VK_F23=0x86 -VK_F24=0x87 -VK_LSHIFT=0xA0 -VK_RSHIFT=0xA1 -VK_LCONTROL=0xA2 -VK_RCONTROL=0xA3 -VK_LMENU=0xA4 -VK_RMENU=0xA5 -VK_BACK=0x08 -VK_TAB=0x09 -VK_SPACE=0x20 -VK_PRIOR=0x21 -VK_NEXT=0x22 -VK_END=0x23 -VK_HOME=0x24 -VK_LEFT=0x25 -VK_UP=0x26 -VK_RIGHT=0x27 -VK_DOWN=0x28 -VK_SELECT=0x29 -VK_PRINT=0x2A -VK_EXECUTE=0x2B -VK_SNAPSHOT=0x2C -VK_INSERT=0x2D -VK_DELETE=0x2E -VK_HELP=0x2F -VK_SHIFT=0x10 -VK_CONTROL=0x11 -VK_MENU=0x12 -VK_PAUSE=0x13 -VK_CAPITAL=0x14 -VK_CLEAR=0x0C -VK_RETURN=0x0D -VK_ESCAPE=0x1B -VK_LWIN=0x5B -VK_RWIN=0x5C -VK_APPS=0x5D -VK_SLEEP=0x5F -VK_NUMPAD0=0x60 -VK_NUMPAD1=0x61 -VK_NUMPAD2=0x62 -VK_NUMPAD3=0x63 -VK_NUMPAD4=0x64 -VK_NUMPAD5=0x65 -VK_NUMPAD6=0x66 -VK_NUMPAD7=0x67 -VK_NUMPAD8=0x68 -VK_NUMPAD9=0x69 -VK_BROWSER_BACK=0xA6 -VK_BROWSER_FORWARD=0xA7 -VK_BROWSER_REFRESH=0xA8 -VK_BROWSER_STOP=0xA9 -VK_BROWSER_SEARCH=0xAA -VK_BROWSER_FAVORITES=0xAB -VK_BROWSER_HOME=0xAC -VK_VOLUME_MUTE=0xAD -VK_VOLUME_DOWN=0xAE -VK_VOLUME_UP=0xAF -VK_MEDIA_NEXT_TRACK=0xB0 -VK_MEDIA_PREV_TRACK=0xB1 -VK_MEDIA_STOP=0xB2 -VK_MEDIA_PLAY_PAUSE=0xB3 -VK_LAUNCH_MAIL=0xB4 -VK_LAUNCH_MEDIA_SELECT=0xB5 -VK_LAUNCH_APP1=0xB6 -VK_LAUNCH_APP2=0xB7 -VK_MULTIPLY=0x6A -VK_ADD=0x6B -VK_SEPARATOR=0x6C -VK_SUBTRACT=0x6D -VK_DECIMAL=0x6E -VK_DIVIDE=0x6F -VK_NUMLOCK=0x90 -VK_SCROLL=0x91 -VK_LBUTTON=0x01 -VK_RBUTTON=0x02 -VK_CANCEL=0x03 -VK_MBUTTON=0x04 -VK_XBUTTON1=0x05 -VK_XBUTTON2=0x06 -VK_KANA=0x15 -VK_HANGEUL=0x15 -VK_HANGUL=0x15 -VK_JUNJA=0x17 -VK_FINAL=0x18 -VK_HANJA=0x19 -VK_KANJI=0x19 -VK_CONVERT=0x1C -VK_NONCONVERT=0x1D -VK_ACCEPT=0x1E -VK_MODECHANGE=0x1F -VK_PROCESSKEY=0xE5 -VK_PACKET=0xE7 -VK_ICO_HELP=0xE3 -VK_ICO_00=0xE4 -VK_ICO_CLEAR=0xE6 - -# eventType constants (OnKeyEvent). -KEYEVENT_RAWKEYDOWN = 0 -KEYEVENT_KEYDOWN = 0 -KEYEVENT_KEYUP = 0 -KEYEVENT_CHAR = 0 - -# Constants for checking modifiers param (OnKeyEvent), for use with IsKeyModifier() function. -KEY_NONE = 0 -KEY_SHIFT = 0 -KEY_CTRL = 0 -KEY_ALT = 0 -KEY_META = 0 -KEY_KEYPAD = 0 - -# -# LoadHandler. -# - -def LoadHandler_OnLoadEnd(browser, frame, httpStatusCode): - return None - -def LoadHandler_OnLoadError(browser, frame, errorCode, failedUrl, errorText_out=[""]): - return False - -def LoadHandler_OnLoadStart(browser, frame): - return None - -# errorCode constants (OnLoadError). -ERR_FAILED = 0 -ERR_ABORTED = 0 -ERR_INVALID_ARGUMENT = 0 -ERR_INVALID_HANDLE = 0 -ERR_FILE_NOT_FOUND = 0 -ERR_TIMED_OUT = 0 -ERR_FILE_TOO_BIG = 0 -ERR_UNEXPECTED = 0 -ERR_ACCESS_DENIED = 0 -ERR_NOT_IMPLEMENTED = 0 -ERR_CONNECTION_CLOSED = 0 -ERR_CONNECTION_RESET = 0 -ERR_CONNECTION_REFUSED = 0 -ERR_CONNECTION_ABORTED = 0 -ERR_CONNECTION_FAILED = 0 -ERR_NAME_NOT_RESOLVED = 0 -ERR_INTERNET_DISCONNECTED = 0 -ERR_SSL_PROTOCOL_ERROR = 0 -ERR_ADDRESS_INVALID = 0 -ERR_ADDRESS_UNREACHABLE = 0 -ERR_SSL_CLIENT_AUTH_CERT_NEEDED = 0 -ERR_TUNNEL_CONNECTION_FAILED = 0 -ERR_NO_SSL_VERSIONS_ENABLED = 0 -ERR_SSL_VERSION_OR_CIPHER_MISMATCH = 0 -ERR_SSL_RENEGOTIATION_REQUESTED = 0 -ERR_CERT_COMMON_NAME_INVALID = 0 -ERR_CERT_DATE_INVALID = 0 -ERR_CERT_AUTHORITY_INVALID = 0 -ERR_CERT_CONTAINS_ERRORS = 0 -ERR_CERT_NO_REVOCATION_MECHANISM = 0 -ERR_CERT_UNABLE_TO_CHECK_REVOCATION = 0 -ERR_CERT_REVOKED = 0 -ERR_CERT_INVALID = 0 -ERR_CERT_END = 0 -ERR_INVALID_URL = 0 -ERR_DISALLOWED_URL_SCHEME = 0 -ERR_UNKNOWN_URL_SCHEME = 0 -ERR_TOO_MANY_REDIRECTS = 0 -ERR_UNSAFE_REDIRECT = 0 -ERR_UNSAFE_PORT = 0 -ERR_INVALID_RESPONSE = 0 -ERR_INVALID_CHUNKED_ENCODING = 0 -ERR_METHOD_NOT_SUPPORTED = 0 -ERR_UNEXPECTED_PROXY_AUTH = 0 -ERR_EMPTY_RESPONSE = 0 -ERR_RESPONSE_HEADERS_TOO_BIG = 0 -ERR_CACHE_MISS = 0 -ERR_INSECURE_RESPONSE = 0 - -# -# RequestHandler. -# - -def RequestHandler_OnResourceRedirect(browser, oldUrl, newUrl_out=[""]): - return None - -def RequestHandler_OnResourceResponse(browser, url, response, filter_out=[None]): - return None - -def RequestHandler_OnProtocolExecution(browser, url, allowOSExecution_out=[False]): - return False - -def RequestHandler_GetAuthCredentials(browser, isProxy, host, port, realm, scheme, username_out=[""], password_out=[""]): - return False - -# navType constants (OnBeforeBrowse). -NAVTYPE_LINKCLICKED = 0 -NAVTYPE_FORMSUBMITTED = 0 -NAVTYPE_BACKFORWARD = 0 -NAVTYPE_RELOAD = 0 -NAVTYPE_FORMRESUBMITTED = 0 -NAVTYPE_OTHER = 0 -NAVTYPE_LINKDROPPED = 0 - -# -# JavascriptContextHandler -# - -def JavascriptContextHandler_OnUncaughtException(browser, frame, exception, stackTrace): - return None - -# -# LifespanHandler -# - -def LifespanHandler_DoClose(browser): - return False - -def LifespanHandler_OnAfterCreated(browser): - return None - -def LifespanHandler_OnBeforeClose(browser): - return None - -def LifespanHandler_RunModal(browser): - return False - -# -# RenderHandler -# - -PET_VIEW = 0 -PET_POPUP = 0 - -KEYTYPE_KEYUP = 0 -KEYTYPE_KEYDOWN = 0 -KEYTYPE_CHAR = 0 - -MOUSEBUTTON_LEFT = 0 -MOUSEBUTTON_MIDDLE = 0 -MOUSEBUTTON_RIGHT = 0 - -def RenderHandler_GetViewRect(browser, out_rect): - return False - -def RenderHandler_GetScreenRect(browser, out_rect): - return False - -def RenderHandler_GetScreenPoint(browser, viewX, viewY, out_screenCoordinates): - return False - -def RenderHandler_OnPopupShow(browser, show): - return None - -def RenderHandler_OnPopupSize(browser, rect): - return None - -def RenderHandler_OnPaint(browser, paintElementType, out_dirtyRects, - paintBuffer): - return None - -def RenderHandler_OnCursorChange(browser, cursor): - return None diff --git a/cefpython/cef1/linux/binaries_32bit/cefsimple.html b/cefpython/cef1/linux/binaries_32bit/cefsimple.html deleted file mode 100644 index f46f773c7..000000000 --- a/cefpython/cef1/linux/binaries_32bit/cefsimple.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - CefSimple (utf-8: ąś) - - - - -Welcome to CEF Python - bindings for the Chromium Embedded Framework.

- -Project's website: http://code.google.com/p/cefpython/
-Wiki documentation: http://code.google.com/p/cefpython/wiki/
-Support forum: https://groups.google.com/group/cefpython?hl=en
- -

Google Search

- -http://www.google.com/ - -

User agent

- - - -

Popup

- - - window.open('cefsimple.html') - -










-










-










- - - diff --git a/cefpython/cef1/linux/binaries_32bit/pygtk_.py b/cefpython/cef1/linux/binaries_32bit/pygtk_.py deleted file mode 100644 index 77141a516..000000000 --- a/cefpython/cef1/linux/binaries_32bit/pygtk_.py +++ /dev/null @@ -1,191 +0,0 @@ -# An example of embedding CEF browser in PyGTK on Linux. - -import ctypes, os, sys -libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'libcef.so') -if os.path.exists(libcef_so): - # Import local module - ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import from package - from cefpython1 import cefpython - -import pygtk -pygtk.require('2.0') -import gtk -import gobject -import re - -def GetApplicationPath(file=None): - import re, os, platform - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - if hasattr(sys, "frozen"): - path = os.path.dirname(sys.executable) - elif "__file__" in globals(): - path = os.path.dirname(os.path.realpath(__file__)) - else: - path = os.getcwd() - path = path + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("cefpython: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class PyGTKExample: - - mainWindow = None - container = None - browser = None - exiting = None - searchEntry = None - vbox = None - - def __init__(self): - - self.mainWindow = gtk.Window(gtk.WINDOW_TOPLEVEL) - self.mainWindow.connect('destroy', self.OnExit) - self.mainWindow.set_size_request(width=600, height=400) - self.mainWindow.set_title('PyGTK CEF example') - self.mainWindow.realize() - - self.vbox = gtk.VBox(False, 0) - self.vbox.pack_start(self.CreateMenu(), False, False, 0) - self.mainWindow.add(self.vbox) - - m = re.search("GtkVBox at 0x(\w+)", str(self.vbox)) - hexID = m.group(1) - windowID = int(hexID, 16) - - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(windowID) - # Linux requires adding "file://" for local files, - # otherwise /home/some will be replaced as http://home/some - self.browser = cefpython.CreateBrowserSync( - windowInfo, - # Flash will crash app in CEF 1 on Linux, setting - # plugins_disabled to True. - browserSettings={"plugins_disabled": True}, - navigateUrl="file://"+GetApplicationPath("cefsimple.html")) - - # Must be show_all() for VBox otherwise browser doesn't - # appear when you just call show(). - self.vbox.show() - - self.mainWindow.show() - gobject.timeout_add(10, self.OnTimer) - - def CreateMenu(self): - - file = gtk.MenuItem('File') - file.show() - filemenu = gtk.Menu() - item = gtk.MenuItem('Open') - filemenu.append(item) - item.show() - item = gtk.MenuItem('Exit') - filemenu.append(item) - item.show() - file.set_submenu(filemenu) - - about = gtk.MenuItem('About') - about.show() - aboutmenu = gtk.Menu() - item = gtk.MenuItem('CEF Python') - aboutmenu.append(item) - item.show() - about.set_submenu(aboutmenu) - - menubar = gtk.MenuBar() - menubar.append(file) - menubar.append(about) - menubar.show() - - return menubar - - def OnWidgetClick(self, widget, data): - - self.mainWindow.get_window().focus() - - def OnTimer(self): - - if self.exiting: - return False - cefpython.MessageLoopWork() - return True - - def OnFocusIn(self, widget, data): - - # This function is currently not called by any of code, - # but if you would like for browser to have automatic focus - # add such line: - # self.mainWindow.connect('focus-in-event', self.OnFocusIn) - self.browser.SetFocus(True) - - def OnExit(self, widget, data=None): - - self.exiting = True - gtk.main_quit() - -if __name__ == '__main__': - - version = '.'.join(map(str, list(gtk.gtk_version))) - print('GTK version: %s' % version) - - sys.excepthook = ExceptHook - cefpython.g_debug = True - cefpython.g_debugFile = GetApplicationPath("debug.log") - settings = { - "log_severity": cefpython.LOGSEVERITY_INFO, - "log_file": GetApplicationPath("debug.log"), - "release_dcheck_enabled": True, # Enable only when debugging. - # This directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory() - } - cefpython.Initialize(settings) - - gobject.threads_init() # timer for messageloop - PyGTKExample() - gtk.main() - - cefpython.Shutdown() diff --git a/cefpython/cef1/linux/binaries_32bit/wxpython.html b/cefpython/cef1/linux/binaries_32bit/wxpython.html deleted file mode 100644 index ff6744439..000000000 --- a/cefpython/cef1/linux/binaries_32bit/wxpython.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - CefSimple (utf-8: ąś) - - - - -Use mouse context menu to go Back/Forward in history navigation. - - - -

Google Search

-http://www.google.com/ - - - -

User agent

- - - - -

Popup

- - window.open('wxpython.html') - - - - -

RequestHandler tests

- -

See messages in the console.

- -OnBeforeBrowse() - navigate to see message: -wxpython.html -

- -OnBeforeBrowse() / OnBeforeResourceLoad() - test request.GetPostData() -and request.SetPostData(): -submit a form: - - https://accounts.google.com/ServiceLogin, -upload a file: - - http://encodable.com/uploaddemo/ -

- -OnBeforeResourceLoad() - try loading nonexistent css file locally: - - LoadCssFile('nonexistent.css') - -

- -OnBeforeResourceLoad() - try replacing a resource on the fly: - - LoadCssFile('replace-on-the-fly.css') -(css content: body { color: red; }) -

- -OnResourceRedirect() - try loading this url: - - http://tinyurl.com/google404redirect -

- -OnResourceResponse() - try loading nonexistent css file via http: - - LoadCssFile('http://www.google.com/404.css') -

- -OnResourceResponse() - try filtering content of the resource: - - LoadCssFile('content-filter/replace-on-the-fly.css') -(new css content: body { color: green; } and body h3 { color: orange; } ) -

- - - - - -

WebRequest test

- -See the console for messages.
- - - external.WebRequest('https://code.google.com/robots.txt') - -

Frame.CallFunction() test

- - - - external.DoCallFunction() - - - - -

Cookie tests

- -See messages in the console. -

- -RequestHandler.GetCookieManager() - an example of having an unique -cookie manager for each browser. Visit - - http://www.html-kit.com/tools/cookietester/ and set some cookie, -then go back to this page using the context menu and open a - - new popup window, the cookie should not appear in the popup browser window. -

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

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

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

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

- - - - -

DragHandler test

- -Try dragging a file, or a text/html fragment to the browser window -and look for the messages in the console. In the wxpython.py script see -ClientHandler.OnDragStart() and OnDragEnter(). - - - - -

DownloadHandler test

- -Try downloading this file (838 KiB):
- - http://cefpython.googlecode.com/files/ubuntu-wallpapers2.zip -
-See messages in the console. -The file will be saved in the ./downloads/ directory. - - - - - - diff --git a/cefpython/cef1/linux/binaries_32bit/wxpython.py b/cefpython/cef1/linux/binaries_32bit/wxpython.py deleted file mode 100644 index 9571f9c6b..000000000 --- a/cefpython/cef1/linux/binaries_32bit/wxpython.py +++ /dev/null @@ -1,528 +0,0 @@ -# An example of embedding CEF browser in wxPython on Linux. - -import ctypes, os, sys -libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'libcef.so') -if os.path.exists(libcef_so): - # Import local module - ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import from package - from cefpython1 import cefpython - -import wx -import time -import re -import uuid - -# Which method to use for message loop processing. -# EVT_IDLE - wx application has priority (default) -# EVT_TIMER - cef browser has priority -# It seems that Flash content behaves better when using a timer. -# IMPORTANT! On Linux EVT_IDLE does not work, the events seems to -# be propagated only when you move your mouse, which is not the -# expected behavior, it is recommended to use EVT_TIMER on Linux, -# so set this value to False. -USE_EVT_IDLE = False - -def GetApplicationPath(file=None): - import re, os, platform - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - if hasattr(sys, "frozen"): - path = os.path.dirname(sys.executable) - elif "__file__" in globals(): - path = os.path.dirname(os.path.realpath(__file__)) - else: - path = os.getcwd() - path = path + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("cefpython: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainFrame(wx.Frame): - browser = None - initialized = False - idleCount = 0 - box = None - - def __init__(self): - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, - title='wxPython example', size=(800,600)) - self.CreateMenu() - - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(self.GetGtkWidget()) - # Linux requires adding "file://" for local files, - # otherwise /home/some will be replaced as http://home/some - self.browser = cefpython.CreateBrowserSync( - windowInfo, - # Flash will crash app in CEF 1 on Linux, setting - # plugins_disabled to True. - browserSettings={"plugins_disabled": True}, - navigateUrl="file://"+GetApplicationPath("wxpython.html")) - - self.browser.SetClientHandler(ClientHandler()) - - jsBindings = cefpython.JavascriptBindings( - bindToFrames=False, bindToPopups=False) - jsBindings.SetObject("external", JavascriptBindings(self.browser)) - self.browser.SetJavascriptBindings(jsBindings) - - self.Bind(wx.EVT_CLOSE, self.OnClose) - if USE_EVT_IDLE: - # Bind EVT_IDLE only for the main application frame. - self.Bind(wx.EVT_IDLE, self.OnIdle) - - def CreateMenu(self): - filemenu = wx.Menu() - filemenu.Append(1, "Open") - exit = filemenu.Append(2, "Exit") - self.Bind(wx.EVT_MENU, self.OnClose, exit) - aboutmenu = wx.Menu() - aboutmenu.Append(1, "CEF Python") - menubar = wx.MenuBar() - menubar.Append(filemenu,"&File") - menubar.Append(aboutmenu, "&About") - self.SetMenuBar(menubar) - - def OnClose(self, event): - self.browser.CloseBrowser() - self.Destroy() - - def OnIdle(self, event): - # self.idleCount += 1 - # print("wxpython.py: OnIdle() %d" % self.idleCount) - cefpython.MessageLoopWork() - -class JavascriptBindings: - mainBrowser = None - webRequest = None - webRequestId = 0 - cookieVisitor = None - - def __init__(self, mainBrowser): - self.mainBrowser = mainBrowser - - def WebRequest(self, url): - request = cefpython.Request.CreateRequest() - request.SetUrl(url) - webRequestClient = WebRequestClient() - # Must keep the reference otherwise WebRequestClient - # callbacks won't be called. - self.webRequest = cefpython.WebRequest.CreateWebRequest(request, - webRequestClient) - - def DoCallFunction(self): - self.mainBrowser.GetMainFrame().CallFunction( - "MyFunction", "abc", 12, [1,2,3], {"qwe": 456, "rty": 789}) - - def VisitAllCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\nCookie manager not yet created! Visit http website first") - return - cookieManager.VisitAllCookies(self.cookieVisitor) - - def VisitUrlCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\nCookie manager not yet created! Visit http website first") - return - cookieManager.VisitUrlCookies( - "http://www.html-kit.com/tools/cookietester/", - False, self.cookieVisitor) - # .www.html-kit.com - - def SetCookie(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\nCookie manager not yet created! Visit http website first") - return - cookie = cefpython.Cookie() - cookie.SetName("Created_Via_Python") - cookie.SetValue("yeah really") - cookieManager.SetCookie("http://www.html-kit.com/tools/cookietester/", - cookie) - print("\nCookie created! Visit html-kit cookietester to see it") - - def DeleteCookies(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\nCookie manager not yet created! Visit http website first") - return - cookieManager.DeleteCookies( - "http://www.html-kit.com/tools/cookietester/", - "Created_Via_Python") - print("\nCookie deleted! Visit html-kit cookietester to see the result") - -class CookieVisitor: - def Visit(self, cookie, count, total, deleteCookie): - if count == 0: - print("\nCookieVisitor.Visit(): total cookies: %s" % total) - print("\nCookieVisitor.Visit(): cookie:") - print(cookie.Get()) - # True to continue visiting cookies - return True - -class WebRequestClient: - def OnStateChange(self, webRequest, state): - stateName = "unknown" - for key, value in cefpython.WebRequest.State.iteritems(): - if value == state: - stateName = key - print("\nWebRequestClient::OnStateChange(): state = %s" % stateName) - - def OnRedirect(self, webRequest, request, response): - print("\nWebRequestClient::OnRedirect(): url = %s" % ( - request.GetUrl()[:80])) - - def OnHeadersReceived(self, webRequest, response): - print("\nWebRequestClient::OnHeadersReceived(): headers = %s" % ( - response.GetHeaderMap())) - - def OnProgress(self, webRequest, bytesSent, totalBytesToBeSent): - print("\nWebRequestClient::OnProgress(): bytesSent = %s, " - "totalBytesToBeSent = %s" % (bytesSent, totalBytesToBeSent)) - - def OnData(self, webRequest, data): - print("\nWebRequestClient::OnData(): data:") - print("-" * 60) - print(data) - print("-" * 60) - - def OnError(self, webRequest, errorCode): - print("\nWebRequestClient::OnError(): errorCode = %s" % errorCode) - -class ContentFilterHandler: - def OnData(self, data, substitute_data): - if data == "body { color: red; }": - substitute_data.SetData("body { color: green; }") - - def OnDrain(self, remainder): - remainder.SetData("body h3 { color: orange; }") - -class ClientHandler: - - # -------------------------------------------------------------------------- - # RequestHandler - # -------------------------------------------------------------------------- - - contentFilter = None - - def OnBeforeBrowse(self, browser, frame, request, navType, isRedirect): - # - frame.GetUrl() returns current url - # - request.GetUrl() returns new url - # - Return true to cancel the navigation or false to allow - # the navigation to proceed. - # - Modifying headers or post data can be done only in - # OnBeforeResourceLoad() - print("\nOnBeforeBrowse(): request.GetUrl() = %s, " - "request.GetHeaderMap(): %s" % ( - request.GetUrl()[:80], request.GetHeaderMap())) - if request.GetMethod() == "POST": - print("\nOnBeforeBrowse(): POST data: %s" % ( - request.GetPostData())) - - def OnBeforeResourceLoad(self, browser, request, redirectUrl, - streamReader, response, loadFlags): - print("\nOnBeforeResourceLoad(): request.GetUrl() = %s" % ( - request.GetUrl()[:80])) - if request.GetMethod() == "POST": - if request.GetUrl().startswith( - "https://accounts.google.com/ServiceLogin"): - postData = request.GetPostData() - postData["Email"] = "--changed via python" - request.SetPostData(postData) - print("\nOnBeforeResourceLoad(): modified POST data: %s" % ( - request.GetPostData())) - if request.GetUrl().endswith("replace-on-the-fly.css"): - print("\nOnBeforeResourceLoad(): replacing css on the fly") - response.SetStatus(200) - response.SetStatusText("OK") - response.SetMimeType("text/css") - streamReader.SetData("body { color: red; }") - - def OnResourceRedirect(self, browser, oldUrl, newUrl): - print("\nOnResourceRedirect(): oldUrl: %s, newUrl: %s" % ( - oldUrl, newUrl[0])) - - def OnResourceResponse(self, browser, url, response, contentFilter): - print("\nOnResourceResponse(): url = %s, headers = %s" % ( - url[:80], response.GetHeaderMap())) - if url.endswith("content-filter/replace-on-the-fly.css"): - print("\nOnResourceResponse(): setting contentFilter handler") - contentFilter.SetHandler(ContentFilterHandler()) - # Must keep the reference to contentFilter otherwise - # ContentFilterHandler callbacks won't be called. - self.contentFilter = contentFilter - - def GetCookieManager(self, browser, mainUrl): - # Create unique cookie manager for each browser. - cookieManager = browser.GetUserData("cookieManager") - if cookieManager: - return cookieManager - else: - cookieManager = cefpython.CookieManager.CreateManager("") - browser.SetUserData("cookieManager", cookieManager) - return cookieManager - - # -------------------------------------------------------------------------- - # DragHandler - # -------------------------------------------------------------------------- - - def OnDragStart(self, browser, dragData, mask): - maskNames = "" - for key, value in cefpython.Drag.Operation.iteritems(): - if value and (value & mask) == value: - maskNames += " "+key - print("\nOnDragStart(): mask=%s" % maskNames) - print(" IsLink(): %s" % dragData.IsLink()) - print(" IsFragment(): %s" % dragData.IsFragment()) - print(" IsFile(): %s" % dragData.IsFile()) - print(" GetLinkUrl(): %s" % dragData.GetLinkUrl()) - print(" GetLinkTitle(): %s" % dragData.GetLinkTitle()) - print(" GetLinkMetadata(): %s" % dragData.GetLinkMetadata()) - print(" GetFragmentText(): %s" % dragData.GetFragmentText()) - print(" GetFragmentHtml(): %s" % dragData.GetFragmentHtml()) - print(" GetFragmentBaseUrl(): %s" % dragData.GetFragmentBaseUrl()) - print(" GetFile(): %s" % dragData.GetFile()) - print(" GetFiles(): %s" % dragData.GetFiles()) - # Returning True on Linux causes segmentation fault, - # reported the bug here: - # http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=10693 - # Not being able to cancel a drag event is a problem - # only when a link or a folder is dragged, as this will - # cause loading the link or the folder in the browser window. - # When dragging text/html or a file it is not a problem, as - # it does not lead to browser navigating. - return False - - def OnDragEnter(self, browser, dragData, mask): - maskNames = "" - for key, value in cefpython.Drag.Operation.iteritems(): - if value and (value & mask) == value: - maskNames += " "+key - print("\nOnDragEnter(): mask=%s" % maskNames) - print(" IsLink(): %s" % dragData.IsLink()) - print(" IsFragment(): %s" % dragData.IsFragment()) - print(" IsFile(): %s" % dragData.IsFile()) - print(" GetLinkUrl(): %s" % dragData.GetLinkUrl()) - print(" GetLinkTitle(): %s" % dragData.GetLinkTitle()) - print(" GetLinkMetadata(): %s" % dragData.GetLinkMetadata()) - print(" GetFragmentText(): %s" % dragData.GetFragmentText()) - print(" GetFragmentHtml(): %s" % dragData.GetFragmentHtml()) - print(" GetFragmentBaseUrl(): %s" % dragData.GetFragmentBaseUrl()) - print(" GetFile(): %s" % dragData.GetFile()) - print(" GetFiles(): %s" % dragData.GetFiles()) - # Returning True on Linux causes segmentation fault, - # reported the bug here: - # http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=10693 - # Not being able to cancel a drag event is a problem - # only when a link or a folder is dragged, as this will - # cause loading the link or the folder in the browser window. - # When dragging text/html or a file it is not a problem, as - # it does not lead to browser navigating. - return False - - # -------------------------------------------------------------------------- - # DownloadHandler - # -------------------------------------------------------------------------- - - downloadHandler = None - - def GetDownloadHandler(self, browser, mimeType, filename, contentLength): - # Close the browser window if it is a popup with - # no other document contents. - if browser.IsPopup() and not browser.HasDocument(): - browser.CloseBrowser() - # The reference to DownloadHandler must be kept alive - # while download proceeds. - if self.downloadHandler and self.downloadHandler.downloading: - print("\nDownload is already in progress") - return False - self.downloadHandler = DownloadHandler(mimeType, filename, - contentLength) - return self.downloadHandler - -class DownloadHandler: - mimeType = "" - filename = "" - contentLength = -1 # -1 means that file size was not provided. - fp = None - downloadsDir = "./downloads" - alreadyDownloaded = 0 - downloading = False - - def __init__(self, mimeType, filename, contentLength): - self.downloading = True - if not os.path.exists(self.downloadsDir): - os.mkdir(self.downloadsDir) - filename = filename.strip() - if not len(filename): - filename = self.GetUniqueFilename() - filename = self.GetSafeFilename(filename) - print("\nDownloadHandler() created") - print("mimeType: %s" % mimeType) - print("filename: %s" % filename) - print("contentLength: %s" % contentLength) - # Append ".downloading" to the filename, in OnComplete() - # when download finishes get rid of this extension. - filename += ".downloading" - if os.path.exists(self.downloadsDir+"/"+filename): - # If the last download did not succeed, the - # "xxx.downloading" might still be there. - os.remove(self.downloadsDir+"/"+filename) - self.mimeType = mimeType - self.filename = filename - self.contentLength = contentLength - self.fp = open(self.downloadsDir+"/"+filename, "wb") - - def GetSafeFilename(self, filename): - # TODO: - # - remove any unsafe characters (".." or "/" or "\" and - # others), the safest way is to have a regexp with a list - # safe characters. The dots ".." is a special case that - # needs to be treated separately. - if os.path.exists(self.downloadsDir+"/"+filename): - filename = self.GetUniqueFilename()[:4]+"_"+filename - assert not os.path.exists(self.downloadsDir+"/"+filename), ( - "File aready exists") - return filename - - def GetUniqueFilename(self): - # The filename may be empty, in that case generate - # an unique name. - # TODO: - # - guess the extension using the mimeType (but mimeType - # may also be empty), "text/css" => ".css". - return str(uuid.uuid4()).replace("-", "")[:16] - - def OnData(self, data): - # TODO: display progress in percentage or/and KiB/MiB. - if self.alreadyDownloaded == 0: - sys.stdout.write("Download progress: ") - sys.stdout.write(".") - sys.stdout.flush() - self.alreadyDownloaded += len(data) - self.fp.write(data) - # time.sleep(1) # Let's make the progress a bit slower (if cached) - # Return True to continue receiving data, False to cancel. - return True - - def OnComplete(self): - sys.stdout.write("\n") - sys.stdout.flush() - self.fp.close() - currentFile = self.downloadsDir+"/"+self.filename - newFilename = re.sub(".downloading$", "", self.filename) - os.rename(self.downloadsDir+"/"+self.filename, - self.downloadsDir+"/"+newFilename) - self.downloading = False - print("\nDownload complete!") - print("Total downloaded: %s" % self.PrettyBytes( - self.alreadyDownloaded)) - print("See the 'downloads' directory.") - - def PrettyBytes(self, bytes): - KiB = 1024 - return "%.3g KiB" % (bytes / KiB) - -class MyApp(wx.App): - timer = None - timerID = 1 - timerCount = 0 - - def OnInit(self): - if not USE_EVT_IDLE: - self.CreateTimer() - frame = MainFrame() - self.SetTopWindow(frame) - frame.Show() - return True - - def CreateTimer(self): - # See "Making a render loop": - # http://wiki.wxwidgets.org/Making_a_render_loop - # Another approach is to use EVT_IDLE in MainFrame, - # see which one fits you better. - self.timer = wx.Timer(self, self.timerID) - self.timer.Start(10) # 10ms - wx.EVT_TIMER(self, self.timerID, self.OnTimer) - - def OnTimer(self, event): - self.timerCount += 1 - # print("wxpython.py: OnTimer() %d" % self.timerCount) - cefpython.MessageLoopWork() - - def OnExit(self): - # When app.MainLoop() returns, MessageLoopWork() should - # not be called anymore. - if not USE_EVT_IDLE: - self.timer.Stop() - -if __name__ == '__main__': - sys.excepthook = ExceptHook - cefpython.g_debug = True - cefpython.g_debugFile = GetApplicationPath("debug.log") - settings = { - "log_severity": cefpython.LOGSEVERITY_INFO, - "log_file": GetApplicationPath("debug.log"), - "release_dcheck_enabled": True, # Enable only when debugging. - # This directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory() - } - cefpython.Initialize(settings) - - print('wx.version=%s' % wx.version()) - app = MyApp(False) - app.MainLoop() - # Let wx.App destructor do the cleanup before calling cefpython.Shutdown(). - del app - - cefpython.Shutdown() diff --git a/cefpython/cef1/linux/binaries_64bit/LICENSE.txt b/cefpython/cef1/linux/binaries_64bit/LICENSE.txt deleted file mode 100644 index 97f1e9616..000000000 --- a/cefpython/cef1/linux/binaries_64bit/LICENSE.txt +++ /dev/null @@ -1,36 +0,0 @@ -Copyright (c) 2012-2013 Czarek Tomczak. Portions Copyright -(c) 2008-2013 Marshall A.Greenblatt, 2006-2009 Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with -or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of Google Inc. nor the name Chromium - Embedded Framework nor the name of CEF Python nor the - names of its contributors may be used to endorse or - promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/cefpython/cef1/linux/binaries_64bit/cefpython_py27.py b/cefpython/cef1/linux/binaries_64bit/cefpython_py27.py deleted file mode 100644 index 0b0e988ce..000000000 --- a/cefpython/cef1/linux/binaries_64bit/cefpython_py27.py +++ /dev/null @@ -1,815 +0,0 @@ -# This file contains API for the "cefpython.pyd" module, all functions are dummy. -# Use it as a quick reference. Use it for code completion in your IDE. -# This file does NOT need to be distribitued along with binaries. - -raise Exception("A dummy API file was imported instead of the PYD module.") - -""" -Detailed documentation with examples can be found on wiki pages: -http://code.google.com/p/cefpython/w/list -""" - -# Global functions in cefpython module. - -def CreateBrowserSync(windowInfo, browserSettings, navigateUrl): - return Browser() - -def FormatJavascriptStackTrace(stackTrace): - return "" - -def GetBrowserByWindowHandle(windowHandle): - return Browser() - -def GetJavascriptStackTrace(frameLimit=100): - return [] - -def Initialize(applicationSettings={}): - return None - -def IsKeyModifier(key, modifiers): - return False - -def MessageLoop(): - return None - -def MessageLoopWork(): - return None - -def QuitMessageLoop(): - return None - -def Shutdown(): - return None - -def GetModuleDirectory(): - return "" - -# -# Settings -# - -# Values are dummy, these are NOT the defaults. -ApplicationSettings = { - "auto_detect_proxy_settings_enabled": False, - "cache_path": "", - "extra_plugin_paths": [""], - "graphics_implementation": ANGLE_IN_PROCESS, - "javascript_flags": "", - "local_storage_quota": 5*1024*1024, - "locale": "", - "locales_dir_path": "", - "log_file": "", - "log_severity": LOGSEVERITY_INFO, - "release_dcheck_enabled": False, - "multi_threaded_message_loop": False, - "pack_loading_disabled": False, - "product_version": "", - "resources_dir_path": "", - "session_storage_quota": 5*1024*1024, - "string_encoding": "utf-8", - "uncaught_exception_stack_size": 0, - "user_agent": "", -} - -# ApplicationSettings["log_severity"] -LOGSEVERITY_VERBOSE = 0 -LOGSEVERITY_INFO = 0 -LOGSEVERITY_WARNING = 0 -LOGSEVERITY_ERROR = 0 -LOGSEVERITY_ERROR_REPORT = 0 -LOGSEVERITY_DISABLE = 0 - -# ApplicationSettings["graphics_implementation"] -ANGLE_IN_PROCESS = 0 -ANGLE_IN_PROCESS_COMMAND_BUFFER = 0 -DESKTOP_IN_PROCESS = 0 -DESKTOP_IN_PROCESS_COMMAND_BUFFER = 0 - -# Values are dummy, these are NOT the defaults. -BrowserSettings = { - "accelerated_2d_canvas_disabled": False, - "accelerated_compositing_enabled": False, - "accelerated_filters_disabled": False, - "accelerated_layers_disabled": False, - "accelerated_plugins_disabled": False, - "accelerated_video_disabled": False, - "animation_frame_rate": 0, - "application_cache_disabled": False, - "author_and_user_styles_disabled": False, - "caret_browsing_enabled": False, - "cursive_font_family": "", - "databases_disabled": False, - "default_encoding": "iso-8859-1", - "default_fixed_font_size": 0, - "default_font_size": 0, - "developer_tools_disabled": False, - "dom_paste_disabled": False, - "drag_drop_disabled": False, - "encoding_detector_enabled": False, - "fantasy_font_family": "", - "file_access_from_file_urls_allowed": False, - "fixed_font_family": "", - "fullscreen_enabled": False, - "history_disabled": False, - "hyperlink_auditing_disabled": False, - "image_load_disabled": False, - "java_disabled": False, - "javascript_access_clipboard_disallowed": False, - "javascript_close_windows_disallowed": False, - "javascript_disabled": False, - "javascript_open_windows_disallowed": False, - "load_drops_disabled": False, - "local_storage_disabled": False, - "minimum_font_size": 0, - "minimum_logical_font_size": 0, - "page_cache_disabled": False, - "plugins_disabled": False, - "remote_fonts_disabled": False, - "sans_serif_font_family": "", - "serif_font_family": "", - "shrink_standalone_images_to_fit": False, - "site_specific_quirks_disabled": False, - "standard_font_family": "", - "tab_to_links_disabled": False, - "text_area_resize_disabled": False, - "universal_access_from_file_urls_allowed": False, - "user_style_sheet_enabled": False, - "user_style_sheet_location": "", - "web_security_disabled": False, - "webgl_disabled": False, - "xss_auditor_enabled": False, -} - -# -# Browser object. -# - -class Browser: - - def CanGoBack(self): - return False - - def CanGoForward(self): - return False - - def ClearHistory(self): - return None - - def CloseBrowser(self): - return None - - def CloseDevTools(self): - return None - - def Find(self, searchID, searchText, forward, matchCase, findNext): - return None - - def GetClientCallback(self, name): - return callback - - def GetClientCallbacksDict(self): - return {} - - def GetFocusedFrame(self): - return Frame() - - def GetFrame(self): - return Frame() - - def GetFrameNames(self): - return ["", ""] - - def GetIdentifier(self): - return 0 - - def GetImage(self, paintElementType, width, height): - return PaintBuffer() - - def GetJavascriptBindings(self): - return JavascriptBindings() - - def GetMainFrame(self): - return Frame() - - def GetOpenerWindowHandle(self): - return 0 - - def GetOuterWindowHandle(self): - return 0 - - def GetSize(self, paintElementType): - return (0,0,) - - def GetUserData(self, key): - return None - - def GetWindowID(self): - return windowID - - def GetWindowHandle(self): - return 0 - - def GetZoomLevel(self): - return 0.0 - - def GoBack(self): - return None - - def GoForward(self): - return None - - def HasDocument(self): - return False - - def HidePopup(self): - return None - - def Invalidate(self, dirtyRect): - return None - - def IsFullscreen(self): - return False - - def IsPopup(self): - return False - - def IsPopupVisible(self): - return False - - def IsWindowRenderingDisabled(self): - return False - - def Reload(self): - return None - - def ReloadIgnoreCache(self): - return None - - def SendKeyEvent(self, keyType, keyInfo, modifiers): - return None - - def SendMouseClickEvent(self, x, y, mouseButtonType, mouseUp, clickCount): - return None - - def SendMouseMoveEvent(self, x, y, mouseLeave): - return None - - def SendMouseWheelEvent(self, x, y, deltaX, deltaY): - return None - - def SendFocusEvent(self, setFocus): - return None - - def SendCaptureLostEvent(self): - return None - - def SetClientCallback(self, name, callback): - return None - - def SetClientHandler(self, clientHandler): - return None - - def SetFocus(self, enable): - return None - - def SetJavascriptBindings(self, javascriptBindings): - return None - - def SetSize(self, paintElementType, width, height): - return None - - def SetZoomLevel(self, zoomLevel): - return None - - def SetUserData(self, key, value): - return None - - def ShowDevTools(self): - return None - - def StopLoad(self): - return None - - def StopFinding(self, clearSelection): - return None - - def ToggleFullscreen(self): - return None - -# -# Frame object. -# - -class Frame: - - def Copy(self): - return None - - def Cut(self): - return None - - def Delete(self): - return None - - def ExecuteJavascript(self, jsCode, scriptUrl=None, startLine=None): - return None - - def GetIdentifier(self): - return 0 - - def GetName(self): - return "" - - def GetProperty(self, name): - return mixed - - def GetSource(self): - return "" - - def GetText(self): - return "" - - def GetUrl(self): - return "" - - def IsFocused(self): - return False - - def IsMain(self): - return False - - def LoadString(self, value, url): - return None - - def LoadUrl(self, url): - return None - - def Paste(self): - return None - - def Print(self): - return None - - def Redo(self): - return None - - def SelectAll(self): - return None - - def SetProperty(self, name, value): - return None - - def Undo(self): - return None - - def ViewSource(self): - return None - -class Response: - - def GetStatus(self): - return 0 - - def SetStatus(self, status): - return None - - def GetStatusText(self): - return "" - - def SetStatusText(self, statusText): - return None - - def GetMimeType(self): - return "" - - def SetMimeType(self, mimeType): - return None - - def GetHeader(self, name): - return "" - - def GetHeaderMap(self): - return {} - - def GetHeaderMultimap(self): - return [("","")] - - def SetHeaderMap(self, headerMap={}): - return None - - def SetHeaderMultimap(self, headerMultimap=[]): - return None - -class PaintBuffer: - - def GetIntPointer(self): - return 0 - - def GetString(self, mode="bgra", origin="top-left"): - return "" - -class JavascriptBindings: - - def __init__(self, bindToFrames=False, bindToPopups=False): - return None - - def IsValueAllowed(self, value): - return False - - def Rebind(self): - return None - - def SetFunction(self, name, func): - return None - - def SetObject(self, name, obj): - return None - - def SetProperty(self, name, value): - return None - -class JavascriptCallback: - - def Call(self, param1, param2, param3_etc): - return mixed - - def GetName(self): - return name - -class WindowUtils: - - @staticmethod - def OnSetFocus(windowID, msg, wparam, lparam): - return 0 - - @staticmethod - def OnSize(windowID, msg, wparam, lparam): - return 0 - - @staticmethod - def OnEraseBackground(windowID, msg, wparam, lparam): - return 0 - - @staticmethod - def SetTitle(pyBrowser, pyTitle): - return None - - @staticmethod - def SetIcon(pyBrowser, icon="inherit"): - return None - -# -# DisplayHandler. -# - -# statusType constants (OnStatusMessage). -STATUSTYPE_TEXT = 0 -STATUSTYPE_MOUSEOVER_URL = 0 -STATUSTYPE_KEYBOARD_FOCUS_URL = 0 - -def DisplayHandler_OnAddressChange(browser, frame, url): - return None - -def DisplayHandler_OnConsoleMessage(browser, message, source, line): - return False - -def DisplayHandler_OnContentsSizeChange(browser, frame, width, height): - return None - -def DisplayHandler_OnNavStateChange(browser, canGoBack, canGoForward): - return None - -def DisplayHandler_OnStatusMessage(browser, text, statusType): - return None - -def DisplayHandler_OnTitleChange(browser, title): - return None - -def DisplayHandler_OnTooltip(browser, text_out=[""]): - return False - -# -# KeyboardHandler. -# - -def KeyboardHandler_OnKeyEvent( - browser, eventType, keyCode, modifiers, isSystemKey, isAfterJavascript): - return False - -# keyCode constants (OnKeyEvent). -VK_0=0x30 -VK_1=0x31 -VK_2=0x32 -VK_3=0x33 -VK_4=0x34 -VK_5=0x35 -VK_6=0x36 -VK_7=0x37 -VK_8=0x38 -VK_9=0x39 -VK_A=0x041 -VK_B=0x042 -VK_C=0x043 -VK_D=0x044 -VK_E=0x045 -VK_F=0x046 -VK_G=0x047 -VK_H=0x048 -VK_I=0x049 -VK_J=0x04A -VK_K=0x04B -VK_L=0x04C -VK_M=0x04D -VK_N=0x04E -VK_O=0x04F -VK_P=0x050 -VK_Q=0x051 -VK_R=0x052 -VK_S=0x053 -VK_T=0x054 -VK_U=0x055 -VK_V=0x056 -VK_W=0x057 -VK_X=0x058 -VK_Y=0x059 -VK_Z=0x05A -VK_F1=0x70 -VK_F2=0x71 -VK_F3=0x72 -VK_F4=0x73 -VK_F5=0x74 -VK_F6=0x75 -VK_F7=0x76 -VK_F8=0x77 -VK_F9=0x78 -VK_F10=0x79 -VK_F11=0x7A -VK_F12=0x7B -VK_F13=0x7C -VK_F14=0x7D -VK_F15=0x7E -VK_F16=0x7F -VK_F17=0x80 -VK_F18=0x81 -VK_F19=0x82 -VK_F20=0x83 -VK_F21=0x84 -VK_F22=0x85 -VK_F23=0x86 -VK_F24=0x87 -VK_LSHIFT=0xA0 -VK_RSHIFT=0xA1 -VK_LCONTROL=0xA2 -VK_RCONTROL=0xA3 -VK_LMENU=0xA4 -VK_RMENU=0xA5 -VK_BACK=0x08 -VK_TAB=0x09 -VK_SPACE=0x20 -VK_PRIOR=0x21 -VK_NEXT=0x22 -VK_END=0x23 -VK_HOME=0x24 -VK_LEFT=0x25 -VK_UP=0x26 -VK_RIGHT=0x27 -VK_DOWN=0x28 -VK_SELECT=0x29 -VK_PRINT=0x2A -VK_EXECUTE=0x2B -VK_SNAPSHOT=0x2C -VK_INSERT=0x2D -VK_DELETE=0x2E -VK_HELP=0x2F -VK_SHIFT=0x10 -VK_CONTROL=0x11 -VK_MENU=0x12 -VK_PAUSE=0x13 -VK_CAPITAL=0x14 -VK_CLEAR=0x0C -VK_RETURN=0x0D -VK_ESCAPE=0x1B -VK_LWIN=0x5B -VK_RWIN=0x5C -VK_APPS=0x5D -VK_SLEEP=0x5F -VK_NUMPAD0=0x60 -VK_NUMPAD1=0x61 -VK_NUMPAD2=0x62 -VK_NUMPAD3=0x63 -VK_NUMPAD4=0x64 -VK_NUMPAD5=0x65 -VK_NUMPAD6=0x66 -VK_NUMPAD7=0x67 -VK_NUMPAD8=0x68 -VK_NUMPAD9=0x69 -VK_BROWSER_BACK=0xA6 -VK_BROWSER_FORWARD=0xA7 -VK_BROWSER_REFRESH=0xA8 -VK_BROWSER_STOP=0xA9 -VK_BROWSER_SEARCH=0xAA -VK_BROWSER_FAVORITES=0xAB -VK_BROWSER_HOME=0xAC -VK_VOLUME_MUTE=0xAD -VK_VOLUME_DOWN=0xAE -VK_VOLUME_UP=0xAF -VK_MEDIA_NEXT_TRACK=0xB0 -VK_MEDIA_PREV_TRACK=0xB1 -VK_MEDIA_STOP=0xB2 -VK_MEDIA_PLAY_PAUSE=0xB3 -VK_LAUNCH_MAIL=0xB4 -VK_LAUNCH_MEDIA_SELECT=0xB5 -VK_LAUNCH_APP1=0xB6 -VK_LAUNCH_APP2=0xB7 -VK_MULTIPLY=0x6A -VK_ADD=0x6B -VK_SEPARATOR=0x6C -VK_SUBTRACT=0x6D -VK_DECIMAL=0x6E -VK_DIVIDE=0x6F -VK_NUMLOCK=0x90 -VK_SCROLL=0x91 -VK_LBUTTON=0x01 -VK_RBUTTON=0x02 -VK_CANCEL=0x03 -VK_MBUTTON=0x04 -VK_XBUTTON1=0x05 -VK_XBUTTON2=0x06 -VK_KANA=0x15 -VK_HANGEUL=0x15 -VK_HANGUL=0x15 -VK_JUNJA=0x17 -VK_FINAL=0x18 -VK_HANJA=0x19 -VK_KANJI=0x19 -VK_CONVERT=0x1C -VK_NONCONVERT=0x1D -VK_ACCEPT=0x1E -VK_MODECHANGE=0x1F -VK_PROCESSKEY=0xE5 -VK_PACKET=0xE7 -VK_ICO_HELP=0xE3 -VK_ICO_00=0xE4 -VK_ICO_CLEAR=0xE6 - -# eventType constants (OnKeyEvent). -KEYEVENT_RAWKEYDOWN = 0 -KEYEVENT_KEYDOWN = 0 -KEYEVENT_KEYUP = 0 -KEYEVENT_CHAR = 0 - -# Constants for checking modifiers param (OnKeyEvent), for use with IsKeyModifier() function. -KEY_NONE = 0 -KEY_SHIFT = 0 -KEY_CTRL = 0 -KEY_ALT = 0 -KEY_META = 0 -KEY_KEYPAD = 0 - -# -# LoadHandler. -# - -def LoadHandler_OnLoadEnd(browser, frame, httpStatusCode): - return None - -def LoadHandler_OnLoadError(browser, frame, errorCode, failedUrl, errorText_out=[""]): - return False - -def LoadHandler_OnLoadStart(browser, frame): - return None - -# errorCode constants (OnLoadError). -ERR_FAILED = 0 -ERR_ABORTED = 0 -ERR_INVALID_ARGUMENT = 0 -ERR_INVALID_HANDLE = 0 -ERR_FILE_NOT_FOUND = 0 -ERR_TIMED_OUT = 0 -ERR_FILE_TOO_BIG = 0 -ERR_UNEXPECTED = 0 -ERR_ACCESS_DENIED = 0 -ERR_NOT_IMPLEMENTED = 0 -ERR_CONNECTION_CLOSED = 0 -ERR_CONNECTION_RESET = 0 -ERR_CONNECTION_REFUSED = 0 -ERR_CONNECTION_ABORTED = 0 -ERR_CONNECTION_FAILED = 0 -ERR_NAME_NOT_RESOLVED = 0 -ERR_INTERNET_DISCONNECTED = 0 -ERR_SSL_PROTOCOL_ERROR = 0 -ERR_ADDRESS_INVALID = 0 -ERR_ADDRESS_UNREACHABLE = 0 -ERR_SSL_CLIENT_AUTH_CERT_NEEDED = 0 -ERR_TUNNEL_CONNECTION_FAILED = 0 -ERR_NO_SSL_VERSIONS_ENABLED = 0 -ERR_SSL_VERSION_OR_CIPHER_MISMATCH = 0 -ERR_SSL_RENEGOTIATION_REQUESTED = 0 -ERR_CERT_COMMON_NAME_INVALID = 0 -ERR_CERT_DATE_INVALID = 0 -ERR_CERT_AUTHORITY_INVALID = 0 -ERR_CERT_CONTAINS_ERRORS = 0 -ERR_CERT_NO_REVOCATION_MECHANISM = 0 -ERR_CERT_UNABLE_TO_CHECK_REVOCATION = 0 -ERR_CERT_REVOKED = 0 -ERR_CERT_INVALID = 0 -ERR_CERT_END = 0 -ERR_INVALID_URL = 0 -ERR_DISALLOWED_URL_SCHEME = 0 -ERR_UNKNOWN_URL_SCHEME = 0 -ERR_TOO_MANY_REDIRECTS = 0 -ERR_UNSAFE_REDIRECT = 0 -ERR_UNSAFE_PORT = 0 -ERR_INVALID_RESPONSE = 0 -ERR_INVALID_CHUNKED_ENCODING = 0 -ERR_METHOD_NOT_SUPPORTED = 0 -ERR_UNEXPECTED_PROXY_AUTH = 0 -ERR_EMPTY_RESPONSE = 0 -ERR_RESPONSE_HEADERS_TOO_BIG = 0 -ERR_CACHE_MISS = 0 -ERR_INSECURE_RESPONSE = 0 - -# -# RequestHandler. -# - -def RequestHandler_OnResourceRedirect(browser, oldUrl, newUrl_out=[""]): - return None - -def RequestHandler_OnResourceResponse(browser, url, response, filter_out=[None]): - return None - -def RequestHandler_OnProtocolExecution(browser, url, allowOSExecution_out=[False]): - return False - -def RequestHandler_GetAuthCredentials(browser, isProxy, host, port, realm, scheme, username_out=[""], password_out=[""]): - return False - -# navType constants (OnBeforeBrowse). -NAVTYPE_LINKCLICKED = 0 -NAVTYPE_FORMSUBMITTED = 0 -NAVTYPE_BACKFORWARD = 0 -NAVTYPE_RELOAD = 0 -NAVTYPE_FORMRESUBMITTED = 0 -NAVTYPE_OTHER = 0 -NAVTYPE_LINKDROPPED = 0 - -# -# JavascriptContextHandler -# - -def JavascriptContextHandler_OnUncaughtException(browser, frame, exception, stackTrace): - return None - -# -# LifespanHandler -# - -def LifespanHandler_DoClose(browser): - return False - -def LifespanHandler_OnAfterCreated(browser): - return None - -def LifespanHandler_OnBeforeClose(browser): - return None - -def LifespanHandler_RunModal(browser): - return False - -# -# RenderHandler -# - -PET_VIEW = 0 -PET_POPUP = 0 - -KEYTYPE_KEYUP = 0 -KEYTYPE_KEYDOWN = 0 -KEYTYPE_CHAR = 0 - -MOUSEBUTTON_LEFT = 0 -MOUSEBUTTON_MIDDLE = 0 -MOUSEBUTTON_RIGHT = 0 - -def RenderHandler_GetViewRect(browser, out_rect): - return False - -def RenderHandler_GetScreenRect(browser, out_rect): - return False - -def RenderHandler_GetScreenPoint(browser, viewX, viewY, out_screenCoordinates): - return False - -def RenderHandler_OnPopupShow(browser, show): - return None - -def RenderHandler_OnPopupSize(browser, rect): - return None - -def RenderHandler_OnPaint(browser, paintElementType, out_dirtyRects, - paintBuffer): - return None - -def RenderHandler_OnCursorChange(browser, cursor): - return None diff --git a/cefpython/cef1/linux/binaries_64bit/cefsimple.html b/cefpython/cef1/linux/binaries_64bit/cefsimple.html deleted file mode 100644 index f46f773c7..000000000 --- a/cefpython/cef1/linux/binaries_64bit/cefsimple.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - CefSimple (utf-8: ąś) - - - - -Welcome to CEF Python - bindings for the Chromium Embedded Framework.

- -Project's website: http://code.google.com/p/cefpython/
-Wiki documentation: http://code.google.com/p/cefpython/wiki/
-Support forum: https://groups.google.com/group/cefpython?hl=en
- -

Google Search

- -http://www.google.com/ - -

User agent

- - - -

Popup

- - - window.open('cefsimple.html') - -










-










-










- - - diff --git a/cefpython/cef1/linux/binaries_64bit/pygtk_.py b/cefpython/cef1/linux/binaries_64bit/pygtk_.py deleted file mode 100644 index 77141a516..000000000 --- a/cefpython/cef1/linux/binaries_64bit/pygtk_.py +++ /dev/null @@ -1,191 +0,0 @@ -# An example of embedding CEF browser in PyGTK on Linux. - -import ctypes, os, sys -libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'libcef.so') -if os.path.exists(libcef_so): - # Import local module - ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import from package - from cefpython1 import cefpython - -import pygtk -pygtk.require('2.0') -import gtk -import gobject -import re - -def GetApplicationPath(file=None): - import re, os, platform - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - if hasattr(sys, "frozen"): - path = os.path.dirname(sys.executable) - elif "__file__" in globals(): - path = os.path.dirname(os.path.realpath(__file__)) - else: - path = os.getcwd() - path = path + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("cefpython: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class PyGTKExample: - - mainWindow = None - container = None - browser = None - exiting = None - searchEntry = None - vbox = None - - def __init__(self): - - self.mainWindow = gtk.Window(gtk.WINDOW_TOPLEVEL) - self.mainWindow.connect('destroy', self.OnExit) - self.mainWindow.set_size_request(width=600, height=400) - self.mainWindow.set_title('PyGTK CEF example') - self.mainWindow.realize() - - self.vbox = gtk.VBox(False, 0) - self.vbox.pack_start(self.CreateMenu(), False, False, 0) - self.mainWindow.add(self.vbox) - - m = re.search("GtkVBox at 0x(\w+)", str(self.vbox)) - hexID = m.group(1) - windowID = int(hexID, 16) - - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(windowID) - # Linux requires adding "file://" for local files, - # otherwise /home/some will be replaced as http://home/some - self.browser = cefpython.CreateBrowserSync( - windowInfo, - # Flash will crash app in CEF 1 on Linux, setting - # plugins_disabled to True. - browserSettings={"plugins_disabled": True}, - navigateUrl="file://"+GetApplicationPath("cefsimple.html")) - - # Must be show_all() for VBox otherwise browser doesn't - # appear when you just call show(). - self.vbox.show() - - self.mainWindow.show() - gobject.timeout_add(10, self.OnTimer) - - def CreateMenu(self): - - file = gtk.MenuItem('File') - file.show() - filemenu = gtk.Menu() - item = gtk.MenuItem('Open') - filemenu.append(item) - item.show() - item = gtk.MenuItem('Exit') - filemenu.append(item) - item.show() - file.set_submenu(filemenu) - - about = gtk.MenuItem('About') - about.show() - aboutmenu = gtk.Menu() - item = gtk.MenuItem('CEF Python') - aboutmenu.append(item) - item.show() - about.set_submenu(aboutmenu) - - menubar = gtk.MenuBar() - menubar.append(file) - menubar.append(about) - menubar.show() - - return menubar - - def OnWidgetClick(self, widget, data): - - self.mainWindow.get_window().focus() - - def OnTimer(self): - - if self.exiting: - return False - cefpython.MessageLoopWork() - return True - - def OnFocusIn(self, widget, data): - - # This function is currently not called by any of code, - # but if you would like for browser to have automatic focus - # add such line: - # self.mainWindow.connect('focus-in-event', self.OnFocusIn) - self.browser.SetFocus(True) - - def OnExit(self, widget, data=None): - - self.exiting = True - gtk.main_quit() - -if __name__ == '__main__': - - version = '.'.join(map(str, list(gtk.gtk_version))) - print('GTK version: %s' % version) - - sys.excepthook = ExceptHook - cefpython.g_debug = True - cefpython.g_debugFile = GetApplicationPath("debug.log") - settings = { - "log_severity": cefpython.LOGSEVERITY_INFO, - "log_file": GetApplicationPath("debug.log"), - "release_dcheck_enabled": True, # Enable only when debugging. - # This directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory() - } - cefpython.Initialize(settings) - - gobject.threads_init() # timer for messageloop - PyGTKExample() - gtk.main() - - cefpython.Shutdown() diff --git a/cefpython/cef1/linux/binaries_64bit/wxpython.html b/cefpython/cef1/linux/binaries_64bit/wxpython.html deleted file mode 100644 index ff6744439..000000000 --- a/cefpython/cef1/linux/binaries_64bit/wxpython.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - CefSimple (utf-8: ąś) - - - - -Use mouse context menu to go Back/Forward in history navigation. - - - -

Google Search

-http://www.google.com/ - - - -

User agent

- - - - -

Popup

- - window.open('wxpython.html') - - - - -

RequestHandler tests

- -

See messages in the console.

- -OnBeforeBrowse() - navigate to see message: -wxpython.html -

- -OnBeforeBrowse() / OnBeforeResourceLoad() - test request.GetPostData() -and request.SetPostData(): -submit a form: - - https://accounts.google.com/ServiceLogin, -upload a file: - - http://encodable.com/uploaddemo/ -

- -OnBeforeResourceLoad() - try loading nonexistent css file locally: - - LoadCssFile('nonexistent.css') - -

- -OnBeforeResourceLoad() - try replacing a resource on the fly: - - LoadCssFile('replace-on-the-fly.css') -(css content: body { color: red; }) -

- -OnResourceRedirect() - try loading this url: - - http://tinyurl.com/google404redirect -

- -OnResourceResponse() - try loading nonexistent css file via http: - - LoadCssFile('http://www.google.com/404.css') -

- -OnResourceResponse() - try filtering content of the resource: - - LoadCssFile('content-filter/replace-on-the-fly.css') -(new css content: body { color: green; } and body h3 { color: orange; } ) -

- - - - - -

WebRequest test

- -See the console for messages.
- - - external.WebRequest('https://code.google.com/robots.txt') - -

Frame.CallFunction() test

- - - - external.DoCallFunction() - - - - -

Cookie tests

- -See messages in the console. -

- -RequestHandler.GetCookieManager() - an example of having an unique -cookie manager for each browser. Visit - - http://www.html-kit.com/tools/cookietester/ and set some cookie, -then go back to this page using the context menu and open a - - new popup window, the cookie should not appear in the popup browser window. -

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

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

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

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

- - - - -

DragHandler test

- -Try dragging a file, or a text/html fragment to the browser window -and look for the messages in the console. In the wxpython.py script see -ClientHandler.OnDragStart() and OnDragEnter(). - - - - -

DownloadHandler test

- -Try downloading this file (838 KiB):
- - http://cefpython.googlecode.com/files/ubuntu-wallpapers2.zip -
-See messages in the console. -The file will be saved in the ./downloads/ directory. - - - - - - diff --git a/cefpython/cef1/linux/binaries_64bit/wxpython.py b/cefpython/cef1/linux/binaries_64bit/wxpython.py deleted file mode 100644 index cac0def2c..000000000 --- a/cefpython/cef1/linux/binaries_64bit/wxpython.py +++ /dev/null @@ -1,529 +0,0 @@ -# An example of embedding CEF browser in wxPython on Linux. - -import ctypes, os, sys -libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'libcef.so') -if os.path.exists(libcef_so): - # Import local module - ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import from package - from cefpython1 import cefpython - -import wx -import time -import re -import uuid - -# Which method to use for message loop processing. -# EVT_IDLE - wx application has priority (default) -# EVT_TIMER - cef browser has priority -# It seems that Flash content behaves better when using a timer. -# IMPORTANT! On Linux EVT_IDLE does not work, the events seems to -# be propagated only when you move your mouse, which is not the -# expected behavior, it is recommended to use EVT_TIMER on Linux, -# so set this value to False. -USE_EVT_IDLE = False - -def GetApplicationPath(file=None): - import re, os, platform - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - if hasattr(sys, "frozen"): - path = os.path.dirname(sys.executable) - elif "__file__" in globals(): - path = os.path.dirname(os.path.realpath(__file__)) - else: - path = os.getcwd() - path = path + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("cefpython: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainFrame(wx.Frame): - browser = None - idleCount = 0 - mainPanel = None - - def __init__(self): - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, - title='wxPython example', size=(800,600)) - self.CreateMenu() - - # Cannot attach browser to the main frame as this will cause - # the menu not to work. - self.mainPanel = wx.Panel(self) - - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(self.mainPanel.GetGtkWidget()) - # Linux requires adding "file://" for local files, - # otherwise /home/some will be replaced as http://home/some - self.browser = cefpython.CreateBrowserSync( - windowInfo, - # Flash will crash app in CEF 1 on Linux, setting - # plugins_disabled to True. - browserSettings={"plugins_disabled": True}, - navigateUrl="file://"+GetApplicationPath("wxpython.html")) - - self.browser.SetClientHandler(ClientHandler()) - - jsBindings = cefpython.JavascriptBindings( - bindToFrames=False, bindToPopups=False) - jsBindings.SetObject("external", JavascriptBindings(self.browser)) - self.browser.SetJavascriptBindings(jsBindings) - - self.Bind(wx.EVT_CLOSE, self.OnClose) - if USE_EVT_IDLE: - # Bind EVT_IDLE only for the main application frame. - self.Bind(wx.EVT_IDLE, self.OnIdle) - - def CreateMenu(self): - filemenu = wx.Menu() - filemenu.Append(1, "Open") - exit = filemenu.Append(2, "Exit") - self.Bind(wx.EVT_MENU, self.OnClose, exit) - aboutmenu = wx.Menu() - aboutmenu.Append(1, "CEF Python") - menubar = wx.MenuBar() - menubar.Append(filemenu,"&File") - menubar.Append(aboutmenu, "&About") - self.SetMenuBar(menubar) - - def OnClose(self, event): - self.browser.CloseBrowser() - self.Destroy() - - def OnIdle(self, event): - # self.idleCount += 1 - # print("wxpython.py: OnIdle() %d" % self.idleCount) - cefpython.MessageLoopWork() - -class JavascriptBindings: - mainBrowser = None - webRequest = None - webRequestId = 0 - cookieVisitor = None - - def __init__(self, mainBrowser): - self.mainBrowser = mainBrowser - - def WebRequest(self, url): - request = cefpython.Request.CreateRequest() - request.SetUrl(url) - webRequestClient = WebRequestClient() - # Must keep the reference otherwise WebRequestClient - # callbacks won't be called. - self.webRequest = cefpython.WebRequest.CreateWebRequest(request, - webRequestClient) - - def DoCallFunction(self): - self.mainBrowser.GetMainFrame().CallFunction( - "MyFunction", "abc", 12, [1,2,3], {"qwe": 456, "rty": 789}) - - def VisitAllCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\nCookie manager not yet created! Visit http website first") - return - cookieManager.VisitAllCookies(self.cookieVisitor) - - def VisitUrlCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\nCookie manager not yet created! Visit http website first") - return - cookieManager.VisitUrlCookies( - "http://www.html-kit.com/tools/cookietester/", - False, self.cookieVisitor) - # .www.html-kit.com - - def SetCookie(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\nCookie manager not yet created! Visit http website first") - return - cookie = cefpython.Cookie() - cookie.SetName("Created_Via_Python") - cookie.SetValue("yeah really") - cookieManager.SetCookie("http://www.html-kit.com/tools/cookietester/", - cookie) - print("\nCookie created! Visit html-kit cookietester to see it") - - def DeleteCookies(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\nCookie manager not yet created! Visit http website first") - return - cookieManager.DeleteCookies( - "http://www.html-kit.com/tools/cookietester/", - "Created_Via_Python") - print("\nCookie deleted! Visit html-kit cookietester to see the result") - -class CookieVisitor: - def Visit(self, cookie, count, total, deleteCookie): - if count == 0: - print("\nCookieVisitor.Visit(): total cookies: %s" % total) - print("\nCookieVisitor.Visit(): cookie:") - print(cookie.Get()) - # True to continue visiting cookies - return True - -class WebRequestClient: - def OnStateChange(self, webRequest, state): - stateName = "unknown" - for key, value in cefpython.WebRequest.State.iteritems(): - if value == state: - stateName = key - print("\nWebRequestClient::OnStateChange(): state = %s" % stateName) - - def OnRedirect(self, webRequest, request, response): - print("\nWebRequestClient::OnRedirect(): url = %s" % ( - request.GetUrl()[:80])) - - def OnHeadersReceived(self, webRequest, response): - print("\nWebRequestClient::OnHeadersReceived(): headers = %s" % ( - response.GetHeaderMap())) - - def OnProgress(self, webRequest, bytesSent, totalBytesToBeSent): - print("\nWebRequestClient::OnProgress(): bytesSent = %s, " - "totalBytesToBeSent = %s" % (bytesSent, totalBytesToBeSent)) - - def OnData(self, webRequest, data): - print("\nWebRequestClient::OnData(): data:") - print("-" * 60) - print(data) - print("-" * 60) - - def OnError(self, webRequest, errorCode): - print("\nWebRequestClient::OnError(): errorCode = %s" % errorCode) - -class ContentFilterHandler: - def OnData(self, data, substitute_data): - if data == "body { color: red; }": - substitute_data.SetData("body { color: green; }") - - def OnDrain(self, remainder): - remainder.SetData("body h3 { color: orange; }") - -class ClientHandler: - # -------------------------------------------------------------------------- - # RequestHandler - # -------------------------------------------------------------------------- - contentFilter = None - - def OnBeforeBrowse(self, browser, frame, request, navType, isRedirect): - # - frame.GetUrl() returns current url - # - request.GetUrl() returns new url - # - Return true to cancel the navigation or false to allow - # the navigation to proceed. - # - Modifying headers or post data can be done only in - # OnBeforeResourceLoad() - print("\nOnBeforeBrowse(): request.GetUrl() = %s, " - "request.GetHeaderMap(): %s" % ( - request.GetUrl()[:80], request.GetHeaderMap())) - if request.GetMethod() == "POST": - print("\nOnBeforeBrowse(): POST data: %s" % ( - request.GetPostData())) - - def OnBeforeResourceLoad(self, browser, request, redirectUrl, - streamReader, response, loadFlags): - print("\nOnBeforeResourceLoad(): request.GetUrl() = %s" % ( - request.GetUrl()[:80])) - if request.GetMethod() == "POST": - if request.GetUrl().startswith( - "https://accounts.google.com/ServiceLogin"): - postData = request.GetPostData() - postData["Email"] = "--changed via python" - request.SetPostData(postData) - print("\nOnBeforeResourceLoad(): modified POST data: %s" % ( - request.GetPostData())) - if request.GetUrl().endswith("replace-on-the-fly.css"): - print("\nOnBeforeResourceLoad(): replacing css on the fly") - response.SetStatus(200) - response.SetStatusText("OK") - response.SetMimeType("text/css") - streamReader.SetData("body { color: red; }") - - def OnResourceRedirect(self, browser, oldUrl, newUrl): - print("\nOnResourceRedirect(): oldUrl: %s, newUrl: %s" % ( - oldUrl, newUrl[0])) - - def OnResourceResponse(self, browser, url, response, contentFilter): - print("\nOnResourceResponse(): url = %s, headers = %s" % ( - url[:80], response.GetHeaderMap())) - if url.endswith("content-filter/replace-on-the-fly.css"): - print("\nOnResourceResponse(): setting contentFilter handler") - contentFilter.SetHandler(ContentFilterHandler()) - # Must keep the reference to contentFilter otherwise - # ContentFilterHandler callbacks won't be called. - self.contentFilter = contentFilter - - def GetCookieManager(self, browser, mainUrl): - # Create unique cookie manager for each browser. - cookieManager = browser.GetUserData("cookieManager") - if cookieManager: - return cookieManager - else: - cookieManager = cefpython.CookieManager.CreateManager("") - browser.SetUserData("cookieManager", cookieManager) - return cookieManager - - # -------------------------------------------------------------------------- - # DragHandler - # -------------------------------------------------------------------------- - - def OnDragStart(self, browser, dragData, mask): - maskNames = "" - for key, value in cefpython.Drag.Operation.iteritems(): - if value and (value & mask) == value: - maskNames += " "+key - print("\nOnDragStart(): mask=%s" % maskNames) - print(" IsLink(): %s" % dragData.IsLink()) - print(" IsFragment(): %s" % dragData.IsFragment()) - print(" IsFile(): %s" % dragData.IsFile()) - print(" GetLinkUrl(): %s" % dragData.GetLinkUrl()) - print(" GetLinkTitle(): %s" % dragData.GetLinkTitle()) - print(" GetLinkMetadata(): %s" % dragData.GetLinkMetadata()) - print(" GetFragmentText(): %s" % dragData.GetFragmentText()) - print(" GetFragmentHtml(): %s" % dragData.GetFragmentHtml()) - print(" GetFragmentBaseUrl(): %s" % dragData.GetFragmentBaseUrl()) - print(" GetFile(): %s" % dragData.GetFile()) - print(" GetFiles(): %s" % dragData.GetFiles()) - # Returning True on Linux causes segmentation fault, - # reported the bug here: - # http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=10693 - # Not being able to cancel a drag event is a problem - # only when a link or a folder is dragged, as this will - # cause loading the link or the folder in the browser window. - # When dragging text/html or a file it is not a problem, as - # it does not lead to browser navigating. - return False - - def OnDragEnter(self, browser, dragData, mask): - maskNames = "" - for key, value in cefpython.Drag.Operation.iteritems(): - if value and (value & mask) == value: - maskNames += " "+key - print("\nOnDragEnter(): mask=%s" % maskNames) - print(" IsLink(): %s" % dragData.IsLink()) - print(" IsFragment(): %s" % dragData.IsFragment()) - print(" IsFile(): %s" % dragData.IsFile()) - print(" GetLinkUrl(): %s" % dragData.GetLinkUrl()) - print(" GetLinkTitle(): %s" % dragData.GetLinkTitle()) - print(" GetLinkMetadata(): %s" % dragData.GetLinkMetadata()) - print(" GetFragmentText(): %s" % dragData.GetFragmentText()) - print(" GetFragmentHtml(): %s" % dragData.GetFragmentHtml()) - print(" GetFragmentBaseUrl(): %s" % dragData.GetFragmentBaseUrl()) - print(" GetFile(): %s" % dragData.GetFile()) - print(" GetFiles(): %s" % dragData.GetFiles()) - # Returning True on Linux causes segmentation fault, - # reported the bug here: - # http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=10693 - # Not being able to cancel a drag event is a problem - # only when a link or a folder is dragged, as this will - # cause loading the link or the folder in the browser window. - # When dragging text/html or a file it is not a problem, as - # it does not lead to browser navigating. - return False - - # -------------------------------------------------------------------------- - # DownloadHandler - # -------------------------------------------------------------------------- - - downloadHandler = None - - def GetDownloadHandler(self, browser, mimeType, filename, contentLength): - # Close the browser window if it is a popup with - # no other document contents. - if browser.IsPopup() and not browser.HasDocument(): - browser.CloseBrowser() - # The reference to DownloadHandler must be kept alive - # while download proceeds. - if self.downloadHandler and self.downloadHandler.downloading: - print("\nDownload is already in progress") - return False - self.downloadHandler = DownloadHandler(mimeType, filename, - contentLength) - return self.downloadHandler - -class DownloadHandler: - mimeType = "" - filename = "" - contentLength = -1 # -1 means that file size was not provided. - fp = None - downloadsDir = "./downloads" - alreadyDownloaded = 0 - downloading = False - - def __init__(self, mimeType, filename, contentLength): - self.downloading = True - if not os.path.exists(self.downloadsDir): - os.mkdir(self.downloadsDir) - filename = filename.strip() - if not len(filename): - filename = self.GetUniqueFilename() - filename = self.GetSafeFilename(filename) - print("\nDownloadHandler() created") - print("mimeType: %s" % mimeType) - print("filename: %s" % filename) - print("contentLength: %s" % contentLength) - # Append ".downloading" to the filename, in OnComplete() - # when download finishes get rid of this extension. - filename += ".downloading" - if os.path.exists(self.downloadsDir+"/"+filename): - # If the last download did not succeed, the - # "xxx.downloading" might still be there. - os.remove(self.downloadsDir+"/"+filename) - self.mimeType = mimeType - self.filename = filename - self.contentLength = contentLength - self.fp = open(self.downloadsDir+"/"+filename, "wb") - - def GetSafeFilename(self, filename): - # TODO: - # - remove any unsafe characters (".." or "/" or "\" and - # others), the safest way is to have a regexp with a list - # safe characters. The dots ".." is a special case that - # needs to be treated separately. - if os.path.exists(self.downloadsDir+"/"+filename): - filename = self.GetUniqueFilename()[:4]+"_"+filename - assert not os.path.exists(self.downloadsDir+"/"+filename), ( - "File aready exists") - return filename - - def GetUniqueFilename(self): - # The filename may be empty, in that case generate - # an unique name. - # TODO: - # - guess the extension using the mimeType (but mimeType - # may also be empty), "text/css" => ".css". - return str(uuid.uuid4()).replace("-", "")[:16] - - def OnData(self, data): - # TODO: display progress in percentage or/and KiB/MiB. - if self.alreadyDownloaded == 0: - sys.stdout.write("Download progress: ") - sys.stdout.write(".") - sys.stdout.flush() - self.alreadyDownloaded += len(data) - self.fp.write(data) - # time.sleep(1) # Let's make the progress a bit slower (if cached) - # Return True to continue receiving data, False to cancel. - return True - - def OnComplete(self): - sys.stdout.write("\n") - sys.stdout.flush() - self.fp.close() - currentFile = self.downloadsDir+"/"+self.filename - newFilename = re.sub(".downloading$", "", self.filename) - os.rename(self.downloadsDir+"/"+self.filename, - self.downloadsDir+"/"+newFilename) - self.downloading = False - print("\nDownload complete!") - print("Total downloaded: %s" % self.PrettyBytes( - self.alreadyDownloaded)) - print("See the 'downloads' directory.") - - def PrettyBytes(self, bytes): - KiB = 1024 - return "%.3g KiB" % (bytes / KiB) - -class MyApp(wx.App): - timer = None - timerID = 1 - timerCount = 0 - - def OnInit(self): - if not USE_EVT_IDLE: - self.CreateTimer() - frame = MainFrame() - self.SetTopWindow(frame) - frame.Show() - return True - - def CreateTimer(self): - # See "Making a render loop": - # http://wiki.wxwidgets.org/Making_a_render_loop - # Another approach is to use EVT_IDLE in MainFrame, - # see which one fits you better. - self.timer = wx.Timer(self, self.timerID) - self.timer.Start(10) # 10ms - wx.EVT_TIMER(self, self.timerID, self.OnTimer) - - def OnTimer(self, event): - self.timerCount += 1 - # print("wxpython.py: OnTimer() %d" % self.timerCount) - cefpython.MessageLoopWork() - - def OnExit(self): - # When app.MainLoop() returns, MessageLoopWork() should - # not be called anymore. - if not USE_EVT_IDLE: - self.timer.Stop() - -if __name__ == '__main__': - sys.excepthook = ExceptHook - cefpython.g_debug = True - cefpython.g_debugFile = GetApplicationPath("debug.log") - settings = { - "log_severity": cefpython.LOGSEVERITY_INFO, - "log_file": GetApplicationPath("debug.log"), - "release_dcheck_enabled": True, # Enable only when debugging. - # This directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory() - } - cefpython.Initialize(settings) - - print('wx.version=%s' % wx.version()) - app = MyApp(False) - app.MainLoop() - # Let wx.App destructor do the cleanup before calling cefpython.Shutdown(). - del app - - cefpython.Shutdown() diff --git a/cefpython/cef1/linux/compile.py b/cefpython/cef1/linux/compile.py deleted file mode 100755 index f7de51fc0..000000000 --- a/cefpython/cef1/linux/compile.py +++ /dev/null @@ -1,127 +0,0 @@ -import sys -import os -import glob -import shutil -import subprocess -import platform - -# This will not show "Segmentation fault" error message: -# | subprocess.call(["python", "./wxpython.py"]) -# You need to call it with shell=True for this kind of -# error message to be shown: -# | subprocess.call("python wxpython.py", shell=True) - -# How to debug: -# 1. Install "python-dbg" package -# 2. Install "python-wxgtk2.8-dbg" package -# 3. Run "python compile.py debug" -# 4. In cygdb type "cy run" -# 5. To display debug backtrace type "cy bt" -# 6. More commands: http://docs.cython.org/src/userguide/debugging.html - -if len(sys.argv) > 1 and sys.argv[1] == "debug": - DEBUG = True - print("DEBUG mode On") -else: - DEBUG = False - -BITS = platform.architecture()[0] -assert (BITS == "32bit" or BITS == "64bit") - -PYVERSION = str(sys.version_info[0])+str(sys.version_info[1]) -print("PYVERSION = %s" % PYVERSION) -print("BITS = %s" % BITS) - -print("Compiling C++ projects") - -# Need to allow continuing even when make fails, as it may -# fail because the "public" function declaration is not yet -# in "cefpython.h", but for it to be generated we need to run -# cython compiling, so in this case you continue even when make -# fails and then run the compile.py script again and this time -# make should succeed. - -os.chdir("./../../cpp_utils/") -ret = subprocess.call("make -f Makefile", shell=True) -if ret != 0: - what = raw_input("make failed, press 'y' to continue, 'n' to stop: ") - if what != "y": - sys.exit() - -os.chdir("./../cef1/client_handler/") -ret = subprocess.call("make -f Makefile", shell=True) -if ret != 0: - what = raw_input("make failed, press 'y' to continue, 'n' to stop: ") - if what != "y": - sys.exit() - -os.chdir("./../v8function_handler/") -ret = subprocess.call("make -f Makefile", shell=True) -if ret != 0: - what = raw_input("make failed, press 'y' to continue, 'n' to stop: ") - if what != "y": - sys.exit() - -os.chdir("./../linux/") - -try: - os.remove("./binaries_%s/cefpython_py%s.so" % (BITS, PYVERSION)) -except OSError: - pass - -try: - os.remove("./setup/cefpython_py%s.so" % PYVERSION) - os.remove("./setup/cefpython_py%s_d.so" % PYVERSION) -except OSError: - pass - -pyx_files = glob.glob("./setup/*.pyx") -for f in pyx_files: - os.remove(f) - -try: - shutil.rmtree("./setup/build") -except OSError: - pass - -os.chdir("./setup") - -ret = subprocess.call("python fix_includes.py", shell=True) -if ret != 0: - sys.exit("ERROR") - -if DEBUG: - ret = subprocess.call("python-dbg setup.py build_ext --inplace" - " --cython-gdb", shell=True) -else: - ret = subprocess.call("python setup.py build_ext --inplace", shell=True) - -if DEBUG: - shutil.rmtree("./../binaries_%s/cython_debug/" % BITS, ignore_errors=True) - shutil.copytree("./cython_debug/", "./../binaries_%s/cython_debug/" % BITS) - -os.chdir("../") - -oldpyxfiles = glob.glob("./setup/*.pyx") -print("Removing old pyx files in /setup/: %s" % oldpyxfiles) -for pyxfile in oldpyxfiles: - if os.path.exists(pyxfile): - os.remove(pyxfile) - -if ret != 0: - sys.exit("ERROR") - -if DEBUG: - os.rename("./setup/cefpython_py%s_d.so" % PYVERSION, "./binaries_%s/cefpython_py%s.so" % (BITS, PYVERSION)) -else: - os.rename("./setup/cefpython_py%s.so" % PYVERSION, "./binaries_%s/cefpython_py%s.so" % (BITS, PYVERSION)) - -shutil.copyfile("./../../cef1_api.py", "./binaries_%s/cefpython_py%s.py" % (BITS, PYVERSION)) - -print("DONE") - -os.chdir("./binaries_%s" % BITS) -if DEBUG: - subprocess.call("cygdb . --args python-dbg wxpython.py", shell=True) -else: - subprocess.call("python wxpython.py", shell=True) diff --git a/cefpython/cef1/linux/example.py b/cefpython/cef1/linux/example.py deleted file mode 100644 index 53d79a624..000000000 --- a/cefpython/cef1/linux/example.py +++ /dev/null @@ -1,11 +0,0 @@ -import os -import platform -import subprocess -import sys - -BITS = platform.architecture()[0] -assert (BITS == "32bit" or BITS == "64bit") - -os.chdir("./binaries_%s" % BITS) - -subprocess.call("python wxpython.py", shell=True) diff --git a/cefpython/cef1/linux/installer/README.txt.template b/cefpython/cef1/linux/installer/README.txt.template deleted file mode 100644 index be6827b68..000000000 --- a/cefpython/cef1/linux/installer/README.txt.template +++ /dev/null @@ -1,23 +0,0 @@ -1. To install CEF Python 1 type: - - sudo python setup.py install - - This will install cefpython1 package to - /usr/local/lib/python2.7/dist-packages/ - -2. In the same directory that setup.py resides there is - an examples/ directory, run some example scripts from there: - - cd examples/ - python wxpython.py - python pygtk_.py - cd wx/ - python sample1.py - python sample2.py - python sample3.py - -Note: - Examples directory can also be found in package's directory: - /usr/local/lib/python2.7/dist-packages/cefpython1/examples/ - But to run examples from there you would have to chmod 0777 - the examples/ directory as it needs permission to create log files. diff --git a/cefpython/cef1/linux/installer/__init__.py.template b/cefpython/cef1/linux/installer/__init__.py.template deleted file mode 100644 index ca81eea9c..000000000 --- a/cefpython/cef1/linux/installer/__init__.py.template +++ /dev/null @@ -1,12 +0,0 @@ -import ctypes, os -libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)), "libcef.so") -ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - -import sys -if 0x02070000 <= sys.hexversion < 0x03000000: - from . import cefpython_py27 as cefpython -else: - raise Exception("Unsupported python version: " + sys.version) - -__version__ = "%(APP_VERSION)s" -__author__ = "The CEF Python authors" diff --git a/cefpython/cef1/linux/installer/make-setup.py b/cefpython/cef1/linux/installer/make-setup.py deleted file mode 100644 index caddb875f..000000000 --- a/cefpython/cef1/linux/installer/make-setup.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -# Create a setup package. - -import sys -import os -import platform -import argparse -import re -import platform -import shutil -import glob - -BITS = platform.architecture()[0] -assert (BITS == "32bit" or BITS == "64bit") - -PACKAGE_NAME = "cefpython1" - -README_TEMPLATE = os.getcwd()+r"/README.txt.template" -INIT_TEMPLATE = os.getcwd()+r"/__init__.py.template" -SETUP_TEMPLATE = os.getcwd()+r"/setup.py.template" - -def main(): - parser = argparse.ArgumentParser(usage="%(prog)s [options]") - parser.add_argument("-v", "--version", help="cefpython version", - required=True) - args = parser.parse_args() - assert re.search(r"^\d+\.\d+$", args.version), ( - "Invalid version string") - - vars = {} - vars["APP_VERSION"] = args.version - - print("Reading template: %s" % README_TEMPLATE) - f = open(README_TEMPLATE) - README_CONTENT = f.read() % vars - f.close() - - print("Reading template: %s" % INIT_TEMPLATE) - f = open(INIT_TEMPLATE) - INIT_CONTENT = f.read() % vars - f.close() - - print("Reading template: %s" % SETUP_TEMPLATE) - f = open(SETUP_TEMPLATE) - SETUP_CONTENT = f.read() % vars - f.close() - - installer_dir = os.path.dirname(os.path.abspath(__file__)) - - setup_dir = installer_dir+"/"+PACKAGE_NAME+"-"+vars["APP_VERSION"]+"-linux-"+BITS+"-setup" - print("Creating setup dir: "+setup_dir) - os.mkdir(setup_dir) - - package_dir = setup_dir+"/"+PACKAGE_NAME - print("Creating package dir") - os.mkdir(package_dir) - - print("Creating README.txt from template") - with open(setup_dir+"/README.txt", "w") as f: - f.write(README_CONTENT) - - print("Creating setup.py from template") - with open(setup_dir+"/setup.py", "w") as f: - f.write(SETUP_CONTENT) - - binaries_dir = os.path.abspath(installer_dir+"/../binaries_"+BITS+"/") - print("Copying binaries to package dir") - ret = os.system("cp -rf "+binaries_dir+"/* "+package_dir) - assert ret == 0 - - os.chdir(package_dir) - print("Removing .log files from the package dir") - ret = os.system("rm *.log") - # assert ret == 0 - if there are no .log files this assert would fail. - os.chdir(installer_dir) - - print("Creating __init__.py from template") - with open(package_dir+"/__init__.py", "w") as f: - f.write(INIT_CONTENT) - - print("Creating examples dir in package dir") - os.mkdir(package_dir+"/examples/") - - print("Creating wx dir in package dir") - os.mkdir(package_dir+"/wx/") - - print("Moving example scripts from package dir to examples dir") - examples = glob.glob(package_dir+"/*.py") - for example in examples: - # Ignore: cefpython_py27.py - dummy API script - if os.path.basename(example).startswith("cefpython_"): - continue - # Ignore: __init__.py - if os.path.basename(example).startswith("__"): - continue - os.rename(example, package_dir+"/examples/"+os.path.basename(example)) - ret = os.system("mv "+package_dir+"/*.html "+package_dir+"/examples/") - assert ret == 0 - - print("Copying wx-subpackage to wx dir in package dir") - wx_subpackage_dir = os.path.abspath(installer_dir+"/../../wx-subpackage/") - ret = os.system("cp -rf "+wx_subpackage_dir+"/* "+package_dir+"/wx/") - assert ret == 0 - - print("Moving wx examples from wx/examples to examples/wx") - shutil.move(package_dir+"/wx/examples", package_dir+"/wx/wx/") - shutil.move(package_dir+"/wx/wx/", package_dir+"/examples/") - - print("Copying package dir examples to setup dir") - ret = os.system("cp -rf "+package_dir+"/examples/ "+setup_dir+"/examples/") - assert ret == 0 - - print("Setup Package created.") - -if __name__ == "__main__": - main() diff --git a/cefpython/cef1/linux/installer/setup.py.template b/cefpython/cef1/linux/installer/setup.py.template deleted file mode 100644 index 1a507843e..000000000 --- a/cefpython/cef1/linux/installer/setup.py.template +++ /dev/null @@ -1,26 +0,0 @@ -from distutils.core import setup - -setup( - name='cefpython1', # No spaces here, so that it works with deb packages. - version='%(APP_VERSION)s', - description='Python bindings for the Chromium Embedded Framework', - license='BSD 3-Clause', - author='Czarek Tomczak', - author_email='czarek.tomczak@gmail.com', - url='http://code.google.com/p/cefpython/', - packages=['cefpython1', 'cefpython1.wx'], - package_data={'cefpython1': [ - 'examples/*.py', - 'examples/*.html', - 'examples/wx/*.py', - 'examples/wx/*.html', - 'examples/wx/*.png', - 'locales/*.pak', - 'wx/*.txt', - 'wx/images/*.png', - '*.txt', - 'cefclient', - '*.so', - '*.pak', - ]} -) diff --git a/cefpython/cef1/linux/setup/.gitignore b/cefpython/cef1/linux/setup/.gitignore deleted file mode 100644 index 0882aaec0..000000000 --- a/cefpython/cef1/linux/setup/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -build/ -cefpython.cpp -cython_debug/ -*.pyx -*.cpp \ No newline at end of file diff --git a/cefpython/cef1/linux/setup/cefpython.h b/cefpython/cef1/linux/setup/cefpython.h deleted file mode 100644 index 3555254b8..000000000 --- a/cefpython/cef1/linux/setup/cefpython.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef __PYX_HAVE__cefpython_py27 -#define __PYX_HAVE__cefpython_py27 - - -#ifndef __PYX_HAVE_API__cefpython_py27 - -#ifndef __PYX_EXTERN_C - #ifdef __cplusplus - #define __PYX_EXTERN_C extern "C" - #else - #define __PYX_EXTERN_C extern - #endif -#endif - -__PYX_EXTERN_C DL_IMPORT(bool) CookieVisitor_Visit(int, CefCookie const &, int, int, bool &); -__PYX_EXTERN_C DL_IMPORT(void) LoadHandler_OnLoadEnd(CefRefPtr, CefRefPtr, int); -__PYX_EXTERN_C DL_IMPORT(void) LoadHandler_OnLoadStart(CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) LoadHandler_OnLoadError(CefRefPtr, CefRefPtr, enum cef_handler_errorcode_t, CefString &, CefString &); -__PYX_EXTERN_C DL_IMPORT(bool) KeyboardHandler_OnKeyEvent(CefRefPtr, enum cef_handler_keyevent_type_t, int, int, bool, bool); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnStateChange(int, CefRefPtr, enum cef_weburlrequest_state_t); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnRedirect(int, CefRefPtr, CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnHeadersReceived(int, CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnProgress(int, CefRefPtr, uint64_t, uint64_t); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnData(int, CefRefPtr, void *, int); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnError(int, CefRefPtr, int); -__PYX_EXTERN_C DL_IMPORT(void) ContentFilterHandler_ProcessData(int, void const *, int, CefRefPtr &); -__PYX_EXTERN_C DL_IMPORT(void) ContentFilterHandler_Drain(int, CefRefPtr &); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnBeforeBrowse(CefRefPtr, CefRefPtr, CefRefPtr, enum cef_handler_navtype_t, bool); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnBeforeResourceLoad(CefRefPtr, CefRefPtr, CefString &, CefRefPtr &, CefRefPtr, int); -__PYX_EXTERN_C DL_IMPORT(void) RequestHandler_OnResourceRedirect(CefRefPtr, CefString &, CefString &); -__PYX_EXTERN_C DL_IMPORT(void) RequestHandler_OnResourceResponse(CefRefPtr, CefString &, CefRefPtr, CefRefPtr &); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnProtocolExecution(CefRefPtr, CefString &, bool &); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_GetDownloadHandler(CefRefPtr, CefString const &, CefString const &, int64, CefRefPtr &); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_GetAuthCredentials(CefRefPtr, bool, CefString &, int, CefString &, CefString &, CefString &, CefString &); -__PYX_EXTERN_C DL_IMPORT(CefRefPtr) RequestHandler_GetCookieManager(CefRefPtr, CefString &); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnAddressChange(CefRefPtr, CefRefPtr, CefString &); -__PYX_EXTERN_C DL_IMPORT(bool) DisplayHandler_OnConsoleMessage(CefRefPtr, CefString &, CefString &, int); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnContentsSizeChange(CefRefPtr, CefRefPtr, int, int); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnNavStateChange(CefRefPtr, bool, bool); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnStatusMessage(CefRefPtr, CefString &, enum cef_handler_statustype_t); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnTitleChange(CefRefPtr, CefString &); -__PYX_EXTERN_C DL_IMPORT(bool) DisplayHandler_OnTooltip(CefRefPtr, CefString &); -__PYX_EXTERN_C DL_IMPORT(bool) LifespanHandler_DoClose(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) LifespanHandler_OnAfterCreated(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) LifespanHandler_OnBeforeClose(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) LifespanHandler_RunModal(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) DragHandler_OnDragStart(CefRefPtr, CefRefPtr, enum cef_drag_operations_mask_t); -__PYX_EXTERN_C DL_IMPORT(bool) DragHandler_OnDragEnter(CefRefPtr, CefRefPtr, enum cef_drag_operations_mask_t); -__PYX_EXTERN_C DL_IMPORT(bool) DownloadHandler_ReceivedData(int, void *, int); -__PYX_EXTERN_C DL_IMPORT(void) DownloadHandler_Complete(int); -__PYX_EXTERN_C DL_IMPORT(void) V8ContextHandler_OnContextCreated(CefRefPtr, CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) V8ContextHandler_OnContextReleased(CefRefPtr, CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) V8ContextHandler_OnUncaughtException(CefRefPtr, CefRefPtr, CefRefPtr, CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) V8FunctionHandler_Execute(CefRefPtr, int, CefString &, CefRefPtr, CefV8ValueList &, CefRefPtr &, CefString &); - -#endif /* !__PYX_HAVE_API__cefpython_py27 */ - -#if PY_MAJOR_VERSION < 3 -PyMODINIT_FUNC initcefpython_py27(void); -#else -PyMODINIT_FUNC PyInit_cefpython_py27(void); -#endif - -#endif /* !__PYX_HAVE__cefpython_py27 */ diff --git a/cefpython/cef1/linux/setup/fix_includes.py b/cefpython/cef1/linux/setup/fix_includes.py deleted file mode 100755 index e25922ba5..000000000 --- a/cefpython/cef1/linux/setup/fix_includes.py +++ /dev/null @@ -1,109 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -# First, it copies all .pyx files from upper directory to setup/. -# Then, fixes repeating of "include" statements in pyx files. - -# Only the mainfile needs to have "include" statements, -# but we're using PyCharm and to get rid of "unresolved references" -# and other errors displayed in pycharm we are adding "include" -# statements in all of the pyx files. - -# I'm not 100% sure how includes work in Cython, but I suspect that -# a few includes of the same file will include the same content more -# than once, it should work, but function and variable definitions are -# duplicated, it is some kind of overhead and it could lead to some -# problems in the future, better to fix it now. - -# It also checks cdef & cpdef functions whether they are not missing "except *", -# it is required to add it when returning non-python type. - -import glob -import os -import re -import shutil -import sys - -def ExceptAllMissing(content): - - # This is not perfect, won't detect C++ custom types, but will find - # the built-in types, templates and pointers. - patterns = [] - patterns.append( - r"\bcp?def\s+" - "((int|short|long|double|char|unsigned|float|double|cpp_bool" - "|cpp_string|cpp_wstring|uint64_t|uintptr_t|void" - "|CefString)\s+)+" - "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") - patterns.append( - r"\bcp?def\s+" - # A template ends with bracket: CefRefPtr[CefBrowser] - # or a pointer ends with asterisk: CefBrowser* - "[^\s]+[\]*]\s+" - "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") - patterns.append( - r"\bcp?def\s+" - # A reference, eg. CefString& - "[^\s]+&\s+" - "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") - - for pattern in patterns: - match = re.search(pattern, content) - if match: break - - if match: - lineNumber = (content.count("\n", 0, match.start()) + 1) - return lineNumber - -print("\n") -mainfile = "cefpython.pyx" - -pyxfiles = glob.glob("../../../*.pyx") -if not len(pyxfiles): - sys.exit(1) -pyxfiles = [file for file in pyxfiles if file.find(mainfile) == -1] -# Now, pyxfiles contains all pyx files except the mainfile (cefpython.pyx), -# we do not fix includes in mainfile. - -# So that this is the right directory we're in. -if os.path.exists("setup"): - print("Wrong directory, we should be inside setup!") - sys.exit(1) - -# Remove old pyx files in setup directory. -oldpyxfiles = glob.glob("./*.pyx") -print("Removing old pyx files in /setup/: %s" % oldpyxfiles) -for pyxfile in oldpyxfiles: - if os.path.exists(pyxfile): - os.remove(pyxfile) - -# Copying pyxfiles and reading its contents. - -print("Copying .pyx files to /setup/: %s" % pyxfiles) -shutil.copy("../../../%s" % mainfile, "./%s" % mainfile) -# Rest of the files will be copied in for loop below. - -print("Fixing includes in .pyx files:") -for pyxfile in pyxfiles: - newfile = "./%s" % os.path.basename(pyxfile) - shutil.copy(pyxfile, newfile) - pyxfile = newfile - with open(pyxfile, "r") as pyxfileopened: - content = pyxfileopened.read() - lineNumber = ExceptAllMissing(content) - if lineNumber: - print("WARNING: 'except *' missing in a cdef/cpdef function, " - "in file %s on line %d" % (os.path.basename(pyxfile), lineNumber)) - sys.exit(1) - # Do not remove the newline - so that line numbers are exact with originals. - (content, subs) = re.subn(r"^include[\t ]+[\"'][^\"'\n\r]+[\"'][\t ]*", "", content, flags=re.MULTILINE) - if subs: - print("%s includes removed in: %s" % (subs, os.path.basename(pyxfile))) - # Reading and writing with the same handle using "r+" mode doesn't work, - # you need to seek(0) and write the same amount of bytes that was in the - # file, otherwise old data from the end of file stays. - with open(pyxfile, "w") as pyxfileopened: - pyxfileopened.write(content) - -print("\n") diff --git a/cefpython/cef1/linux/setup/setup.py b/cefpython/cef1/linux/setup/setup.py deleted file mode 100755 index 7efd4b03d..000000000 --- a/cefpython/cef1/linux/setup/setup.py +++ /dev/null @@ -1,105 +0,0 @@ -from distutils.core import setup -# Use "Extension" from Cython.Distutils so that "cython_directives" works. -# from distutils.extension import Extension -from Cython.Distutils import build_ext, Extension -import sys -import platform -from Cython.Compiler import Options - -BITS = platform.architecture()[0] -assert (BITS == "32bit" or BITS == "64bit") - -# Stop on first error, otherwise hundreds of errors appear in the console. -Options.fast_fail = True - -# Written to cython_includes/compile_time_constants.pxi -CEF_VERSION = 1 - -# Python version string: "27" or "32". -PYTHON_VERSION = str(sys.version_info.major) + str(sys.version_info.minor) - -def CompileTimeConstants(): - - print("Generating: cython_includes/compile_time_constants.pxi") - with open("./../../../cython_includes/compile_time_constants.pxi", "w") as fd: - fd.write('# This file was generated by setup.py\n') - # A way around Python 3.2 bug: UNAME_SYSNAME is not set. - fd.write('DEF UNAME_SYSNAME = "%s"\n' % platform.uname()[0]) - fd.write('DEF CEF_VERSION = %s\n' % CEF_VERSION) - fd.write('DEF PY_MAJOR_VERSION = %s\n' % sys.version_info.major) - -CompileTimeConstants() - -ext_modules = [Extension( - - "cefpython_py%s" % PYTHON_VERSION, - ["cefpython.pyx"], - - # Ignore the warning in the console: - # > C:\Python27\lib\distutils\extension.py:133: UserWarning: - # > Unknown Extension options: 'cython_directives' warnings.warn(msg) - cython_directives={ - # Any conversion to unicode must be explicit using .decode(). - "c_string_type": "bytes", - "c_string_encoding": "utf-8", - }, - - language='c++', - include_dirs=[ - r'./../', - r'./../../', - r'./../../../', - r'./../../../cython_includes/', - '/usr/include/gtk-2.0', - '/usr/include/glib-2.0', - '/usr/lib/i386-linux-gnu/gtk-2.0/include', - '/usr/lib/i386-linux-gnu/glib-2.0/include', - '/usr/include/cairo', - '/usr/include/pango-1.0', - '/usr/include/gdk-pixbuf-2.0', - '/usr/include/atk-1.0', - # 64bit Ubuntu - '/usr/lib/x86_64-linux-gnu/glib-2.0/include', - '/usr/lib/x86_64-linux-gnu/gtk-2.0/include', - ], - - # http_authentication not implemented on Linux. - library_dirs=[ - r'./lib_%s' % BITS, - r'./../../v8function_handler/', - r'./../../client_handler/', - r'./../../../cpp_utils/' - ], - - libraries=[ - 'cef_dll_wrapper', - 'v8function_handler', - 'client_handler', - 'cpp_utils' - ], - - # Loading libcef.so will only work when running scripts from the same - # directory that libcef.so resides in when you put "./" in here. - # runtime_library_dirs=[ - # './' - #], - - # /EHsc - using STL string, multimap and others that use C++ exceptions. - extra_compile_args=[], - - # '/ignore:4217' - silence warnings: "locally defined symbol _V8FunctionHandler_Execute - # imported in function "public: virtual bool __thiscall V8FunctionHandler::Execute". - # client_handler or other vcprojects include setup/cefpython.h, - # this is a list of functions with "public" statement that is - # accessible from c++. - extra_link_args=[], - - # Defining macros: - # define_macros = [("UNICODE","1"), ("_UNICODE","1"), ] -)] - -setup( - name = 'cefpython_py%s' % PYTHON_VERSION, - cmdclass = {'build_ext': build_ext}, - ext_modules = ext_modules -) diff --git a/cefpython/cef1/util.h b/cefpython/cef1/util.h deleted file mode 100644 index ba0305c1c..000000000 --- a/cefpython/cef1/util.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -#ifndef CEF_TESTS_CEFCLIENT_UTIL_H_ -#define CEF_TESTS_CEFCLIENT_UTIL_H_ -#pragma once - -#include "include/cef_task.h" - -#if defined(OS_WIN) - -#include // NOLINT(build/include_order) - -#ifndef NDEBUG -#define ASSERT(condition) if (!(condition)) { DebugBreak(); } -#else -#define ASSERT(condition) ((void)0) -#endif - -#else // !OS_WIN - -#include // NOLINT(build/include_order) - -#ifndef NDEBUG -#define ASSERT(condition) if (!(condition)) { assert(false); } -#else -#define ASSERT(condition) ((void)0) -#endif - -#endif // !OS_WIN - -#define REQUIRE_UI_THREAD() ASSERT(CefCurrentlyOn(TID_UI)); -#define REQUIRE_IO_THREAD() ASSERT(CefCurrentlyOn(TID_IO)); -#define REQUIRE_FILE_THREAD() ASSERT(CefCurrentlyOn(TID_FILE)); - -#endif // CEF_TESTS_CEFCLIENT_UTIL_H_ diff --git a/cefpython/cef1/v8function_handler/.gitignore b/cefpython/cef1/v8function_handler/.gitignore deleted file mode 100644 index 151a620fe..000000000 --- a/cefpython/cef1/v8function_handler/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.o -*.a \ No newline at end of file diff --git a/cefpython/cef1/v8function_handler/Makefile b/cefpython/cef1/v8function_handler/Makefile deleted file mode 100644 index c8d094d4a..000000000 --- a/cefpython/cef1/v8function_handler/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# -g - extra debug information -# -O1 - more precise backtraces -# -fPIC - required when using -shared option -# -Wall - show important warnings -# -Werror - treat warnings as errors - -CC = g++ -CCFLAGS = -g - -SRC = v8function_handler.cpp -OBJ = $(SRC:.cpp=.o) -OUT = libv8function_handler.a - -INC = -I./../ -I/usr/include/python2.7 -I/usr/include/gtk-2.0 -I/usr/include/glib-2.0 -I/usr/lib/i386-linux-gnu/gtk-2.0/include -I/usr/lib/i386-linux-gnu/glib-2.0/include -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/atk-1.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include - -.cpp.o: - $(CC) -fPIC $(INC) $(CCFLAGS) -c $< -o $@ - -$(OUT): $(OBJ) - ar rcs $(OUT) $(OBJ) diff --git a/cefpython/cef1/v8function_handler/v8function_handler.cpp b/cefpython/cef1/v8function_handler/v8function_handler.cpp deleted file mode 100644 index e05a558b9..000000000 --- a/cefpython/cef1/v8function_handler/v8function_handler.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "v8function_handler.h" - -// Implementation cannot be in .h as it is included by cython's setup script and -// V8FunctionHandler_Execute() is not visible at that time. -bool V8FunctionHandler::Execute( - const CefString& name, - CefRefPtr object, - const CefV8ValueList& arguments, - CefRefPtr& retval, - CefString& exception) -{ - // The methods of this class will always be called on the UI thread, no need to call REQUIRE_UI_THREAD(). - return V8FunctionHandler_Execute(this->GetContext(), this->pythonCallbackID, - const_cast(name), object, const_cast(arguments), retval, exception); -} diff --git a/cefpython/cef1/v8function_handler/v8function_handler.h b/cefpython/cef1/v8function_handler/v8function_handler.h deleted file mode 100644 index cc33980e3..000000000 --- a/cefpython/cef1/v8function_handler/v8function_handler.h +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ - -#pragma once - -#if defined(_WIN32) -#include "../windows/stdint.h" -#endif - -#include "cefpython_public_api.h" - -typedef void (*RemovePythonCallback_type)( - int callbackID -); - -class V8FunctionHandler : public CefV8Handler -{ -public: - V8FunctionHandler() - { - this->removePythonCallback = NULL; - this->pythonCallbackID = 0; - } - virtual ~V8FunctionHandler() - { - if (this->removePythonCallback) { - this->removePythonCallback(this->pythonCallbackID); - } - } - - CefRefPtr __context; - - void SetContext(CefRefPtr context) - { - this->__context = context; - } - CefRefPtr GetContext() - { - return this->__context; - } - - - // CefV8Handler methods. - - RemovePythonCallback_type removePythonCallback; - int pythonCallbackID; - - void SetCallback_RemovePythonCallback(RemovePythonCallback_type callback) - { - this->removePythonCallback = callback; - } - void SetPythonCallbackID(int callbackID) - { - this->pythonCallbackID = callbackID; - } - virtual bool Execute( - const CefString& name, - CefRefPtr object, - const CefV8ValueList& arguments, - CefRefPtr& retval, - CefString& exception) OVERRIDE; - -protected: - IMPLEMENT_REFCOUNTING(V8FunctionHandler); -}; diff --git a/cefpython/cef1/v8function_handler/v8function_handler.sln b/cefpython/cef1/v8function_handler/v8function_handler.sln deleted file mode 100644 index 5929d6fc3..000000000 --- a/cefpython/cef1/v8function_handler/v8function_handler.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8function_handler_py27", "v8function_handler_py27.vcproj", "{6CA41D5D-3546-4363-B670-97FFE4B88D4C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8function_handler_py32", "v8function_handler_py32.vcproj", "{9E47F572-3024-4C6E-80E5-4C4BF79EEE8E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6CA41D5D-3546-4363-B670-97FFE4B88D4C}.Debug|Win32.ActiveCfg = Debug|Win32 - {6CA41D5D-3546-4363-B670-97FFE4B88D4C}.Debug|Win32.Build.0 = Debug|Win32 - {6CA41D5D-3546-4363-B670-97FFE4B88D4C}.Release|Win32.ActiveCfg = Release|Win32 - {6CA41D5D-3546-4363-B670-97FFE4B88D4C}.Release|Win32.Build.0 = Release|Win32 - {9E47F572-3024-4C6E-80E5-4C4BF79EEE8E}.Debug|Win32.ActiveCfg = Debug|Win32 - {9E47F572-3024-4C6E-80E5-4C4BF79EEE8E}.Release|Win32.ActiveCfg = Release|Win32 - {9E47F572-3024-4C6E-80E5-4C4BF79EEE8E}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/cefpython/cef1/v8function_handler/v8function_handler_py27.vcproj b/cefpython/cef1/v8function_handler/v8function_handler_py27.vcproj deleted file mode 100644 index 2e0712395..000000000 --- a/cefpython/cef1/v8function_handler/v8function_handler_py27.vcproj +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cefpython/cef1/v8function_handler/v8function_handler_py32.vcproj b/cefpython/cef1/v8function_handler/v8function_handler_py32.vcproj deleted file mode 100644 index 71efefbae..000000000 --- a/cefpython/cef1/v8function_handler/v8function_handler_py32.vcproj +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cefpython/cef1/windows/.gitignore b/cefpython/cef1/windows/.gitignore deleted file mode 100644 index f1e2fe98d..000000000 --- a/cefpython/cef1/windows/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Ignore binary files and static libraries, they can -# be build using the build instructions on the wiki page: -# https://code.google.com/p/cefpython/wiki/BuildOnWindows - -*.pak -*.exe -*.dll - -*.lib -*.pyd diff --git a/cefpython/cef1/windows/binaries/LICENSE.txt b/cefpython/cef1/windows/binaries/LICENSE.txt deleted file mode 100644 index 97f1e9616..000000000 --- a/cefpython/cef1/windows/binaries/LICENSE.txt +++ /dev/null @@ -1,36 +0,0 @@ -Copyright (c) 2012-2013 Czarek Tomczak. Portions Copyright -(c) 2008-2013 Marshall A.Greenblatt, 2006-2009 Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with -or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of Google Inc. nor the name Chromium - Embedded Framework nor the name of CEF Python nor the - names of its contributors may be used to endorse or - promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/cefpython/cef1/windows/binaries/Microsoft.VC90.CRT.manifest b/cefpython/cef1/windows/binaries/Microsoft.VC90.CRT.manifest deleted file mode 100644 index 338438dfe..000000000 --- a/cefpython/cef1/windows/binaries/Microsoft.VC90.CRT.manifest +++ /dev/null @@ -1,6 +0,0 @@ - - - - - KSaO8M0iCtPF6YEr79P1dZsnomY= ojDmTgpYMFRKJYkPcM6ckpYkWUU= tVogb8kezDre2mXShlIqpp8ErIg= - \ No newline at end of file diff --git a/cefpython/cef1/windows/binaries/README.txt b/cefpython/cef1/windows/binaries/README.txt deleted file mode 100644 index b8f84accc..000000000 --- a/cefpython/cef1/windows/binaries/README.txt +++ /dev/null @@ -1,112 +0,0 @@ -Chromium Embedded Framework (CEF) Standard Binary Distribution for Windows -------------------------------------------------------------------------------- - -Date: June 06, 2013 - -CEF Version: 1.1453.1273 -CEF URL: http://chromiumembedded.googlecode.com/svn/branches/1453/cef1@1273 - -Chromium Verison: 27.0.1453.110 -Chromium URL: http://src.chromium.org/svn/branches/1453/src@202711 - -This distribution contains all components necessary to build and distribute an -application using CEF on the Windows platform. Please see the LICENSING -section of this document for licensing terms and conditions. - -CONTENTS --------- - -cefclient Contains the cefclient sample application configured to build - using the files in this distribution. - -Debug Contains libcef.dll, libcef.lib and other components required to - build and run the debug version of CEF-based applications. By - default these files should be placed in the same directory as the - executable and will be copied there as part of the build process. - -include Contains all required CEF header files. - -libcef_dll Contains the source code for the libcef_dll_wrapper static library - that all applications using the CEF C++ API must link against. - -Release Contains libcef.dll, libcef.lib and other components required to - build and run the release version of CEF-based applications. By - default these files should be placed in the same directory as the - executable and will be copied there as part of the build process. - -Resources Contains resources required by libcef.dll. By default these files - should be placed in the same directory as libcef.dll. By default - these files should be placed in the same directory as libcef.dll - and will be copied there as part of the build process. - - -USAGE ------ - -Visual Studio 2012 and Visual Studio 2010: - Open the cefclient2010.sln solution in Visual Studio and build. - -Visual Studio 2008: - Open the cefclient2008.sln solution in Visual Studio and build. - -Visual Studio 2005: - 1. Open the cefclient.vcproj and libcef_dll_wrapper.vcproj files in a text - editor. Change Version="9.00" to Version="8.00". - 2. Open the cefclient2005.sln file in a text editor. Change "Version 9.00" to - "Version 8.00". - 3. Open the cefclient2005.sln solution in Visual Studio and build. - -Please visit the CEF Website for additional usage information. - -http://code.google.com/p/chromiumembedded - -REDISTRIBUTION --------------- - -This binary distribution contains the below components. Components listed under -the "required" section must be redistributed with all applications using CEF. -Components listed under the "optional" section may be excluded if the related -features will not be used. - -Required components: - -* CEF core library - libcef.dll - -* Unicode support - icudt.dll - -Optional components: - -* Localized resources - locales/ - Note: Contains localized strings for WebKit UI controls. A .pak file is loaded - from this folder based on the CefSettings.locale value. Only configured - locales need to be distributed. If no locale is configured the default locale - of "en-US" will be used. Locale file loading can be disabled completely using - CefSettings.pack_loading_disabled. The locales folder path can be customized - using CefSettings.locales_dir_path. - -* Other resources - devtools_resources.pak - Note: Contains WebKit image and inspector resources. Pack file loading can be - disabled completely using CefSettings.pack_loading_disabled. The resources - directory path can be customized using CefSettings.resources_dir_path. - -* Angle and Direct3D support - d3dcompiler_43.dll - d3dx9_43.dll - libEGL.dll - libGLESv2.dll - Note: Without these components the default ANGLE_IN_PROCESS graphics - implementation for HTML5 accelerated content like 2D canvas, 3D CSS and - WebGL will not function. To use the desktop GL graphics implementation which - does not require these components (and does not work on all systems) set - CefSettings.graphics_implementation to DESKTOP_IN_PROCESS. - -LICENSING ---------- - -The CEF project is BSD licensed. Please read the LICENSE.txt file included with -this binary distribution for licensing terms and conditions. Other software -included in this distribution is provided under other licenses. \ No newline at end of file diff --git a/cefpython/cef1/windows/binaries/cefadvanced.html b/cefpython/cef1/windows/binaries/cefadvanced.html deleted file mode 100644 index 9f0805e24..000000000 --- a/cefpython/cef1/windows/binaries/cefadvanced.html +++ /dev/null @@ -1,306 +0,0 @@ - - - - - CefAdvanced - - - - -Welcome to CEF Python - bindings for the Chromium Embedded Framework. -

- -Project website: -http://code.google.com/p/cefpython/
- -Wiki documentation: -http://code.google.com/p/cefpython/wiki/
- -Support forum: -https://groups.google.com/group/cefpython?hl=en
- -

User agent

- - - -

Python version

- - - -

Keyboard and mouse shortcuts

- -
    -
  • Press F5 to refresh & rebind python<>javascript bindings - (does not work for the main module). -
  • Press F11 to go fullscreen, press F11 again to exit fullscreen. -
  • Press F12 key to show developer tools for the main frame. -
  • Press backspace to go Back in history. -
  • Use right mouse button context menu to go Back/Forward or to view the sources. -
  • Press Ctrl(+) to zoom in, Ctrl(-) to zoom out. -
- -

Browse google

- - http://www.google.com/ - -

Transparent window

- - - python.TransparentPopup() - -

Browser object

- - CanGoBack()
- CanGoForward()
- ClearHistory()
- CloseBrowser()
- CloseDevTools()
- Find(searchId=0, searchText='test', forward=true, matchCase=false, findNext=false)
- GetUserData('some')
- GetFocusedFrame() - - throws an error, returning a PyFrame object to to javascript is not yet supported
- GetFrame('simple') - throws an error, returning a PyFrame object to javascript is not yet supported
- GetFrameNames()
- GetMainFrame() - - throws an error, returning a PyFrame object to javascript is not yet supported
- - GetOpenerWindowHandle()
- - GetOuterWindowHandle()
- GetWindowHandle()
- GetZoomLevel()
- GoBack()
- GoForward()
- HasDocument()
- HidePopup()
- IsFullscreen()
- IsPopup()
- IsPopupVisible()
- - IsWindowRenderingDisabled()
- Reload()
- ReloadIgnoreCache()
- SetFocus(false) - - inner window loses focus, check keyboard and mouse wheel scrolling
- - SetUserData('some', 'something') - call GetUserData('some')
- SetZoomLevel(2)
- ShowDevTools()
- StopLoad()
- StopFinding(true) - call Find(), then StopFinding()
- ToggleFullscreen()
- -

Frame object

- - Copy()
- Cut()
- Delete()
- - ExecuteJavascript('alert(1)')
- GetIdentifier()
- - GetName()
- GetProperty('name')
- GetSource()
- GetText()
- GetUrl()
- IsFocused()
- IsMain()
- LoadString('some html source', 'cef://some')
- - LoadUrl('http://www.google.com/')
- Paste()
- Print()
- Redo()
- SelectAll()
- - SetProperty('name', 'noname') - call GetProperty('name')
- Undo()
- ViewSource()
- -

Browser view as an image

- - Browser.GetImage() returns a PaintBuffer object that has the GetString() - method that returns the buffer as a string, that string can be - passed to PIL.Image.fromstring() and saved as a PNG or other - format. This test requires the PIL or pygame library to be installed:
- - python.SaveImage('!cefadvanced.png', 'PNG')
- - TODO: capture image of all the scrollable content on a webpage, - detect the height of the content in javascript and call - Browser.SetSize() using that height. - -

Test unicode string

- - - python.GetUnicodeString()
- You should see a long dash in python 2.7. - -

Test creation of second browser

- - python.CreateSecondBrowser() - -

Test int32, uint, long

- - python.GetType(2147483647)
- python.GetType(2147483648) - here we get UINT from CEF so it is converted to long in Py2, int in Py3.
- python.GetType(4294967295) - uint limit.
- python.GetType(4294967296) - outside of uint limit, converted to float.
- python.GetType(-2147483647)
- python.GetType(-2147483648)
- python.GetType(-2147483649) - here you get a FLOAT value, not long.
-
- TODO: do these tests the other way, from javascript to python. - -
- -

Basic authentication

- - - - -
- -

Frame.ExecuteJavascript()

- -
- python.ExecuteJavascript(jscode.value) - execute javascript from the textarea above. - -

Frames

- - - - -

Javascript bindings

- - See output in the console for the javascript bindings tests.
- Note: "window." is optional, you can just call "python.Test1()".
- -

Passing arguments

- - python.Test1(100)
- python.Test2(100, 'This string was passed from javascript [unicode: ąś]', '') - python.Test2() should return: [1,2, [2.1, {'3': 3, '4': [5,6]}], unicode...] -

- - - python.Test1(array) (var array = [1]; array[100] = 100.01;) - the gap is filled with None values.
- - - python.Test1(object) (var object = {a: 1, '3': 33};)
- -
- - python.Test1(nested) (var nested = [1,2, [3, 4, [5,6, [{7:7, 8: [9,10]}, 11]]]];) - dictionary keys will be in a different order in Python.
- -
- window.PyConfig = - -
- Now change PyConfig: window.PyConfig={'option1': False, 'option2': 40}
- Call __browser.GetMainFrame().GetProperty("PyConfig"): python.PrintPyConfig()
- Try setting PyConfig during runtime using __browser.GetMainFrame().SetProperty(): python.ChangePyConfig() (then call python.PrintPyConfig()) - -

Javasript callbacks

- - - - - python.TestJavascriptCallback(MyJSCallback)
- MyJSCallback alerts arguments. - -

Python callbacks

- -

See the output in the console.

- - - - python.TestPythonCallbackThroughReturn()('some')
- python.TestPythonCallbackThroughJavascriptCallback(JSCallbackForPythonCallback) - -

Errors

- -

Typically when you browse a webpage javascript errors appear in - the developer tools javascript console (in cefadvanced.py there - is a binding to F12 key for the developer tools popup).

- -

Global exception handler

- - - -

You can catch javascript errors programmatically by - using JavascriptContextHandler.OnUncaughtException() callback, - to see the complete stack trace you need to set the - "uncaught_exception_stack_size" ApplicationSettings option to - a value greater than 0, test it:
- - DoSomeError() -

- -

Test error when calling javascript callback from python

- - - - python.TestJavascriptCallback(JsCallbackThrowingError)
- JsCallbackThrowingError throws new Error(). - -

Infinite recursion

- - python.Test1(window)
- You should see a python exception in the console (also in error.log), - as data structures can have maximum 8 levels of nesting. - -

Moving and resizing window

- - python.ResizeWindow() - cefwindow.MoveWindow(__browser.GetWindowID(), width=500, height=500)
- python.MoveWindow() - cefwindow.MoveWindow(__browser.GetWindowID(), xpos=0, ypos=0) - -

Popups

- - window.open('cefsimple.html')
- window.open('cefadvanced.html') - -

Overwriting window.alert()

- -
def Alert(self, msg):
-        print "python.Alert() called instead of window.alert()"
-        win32gui.MessageBox(__browser.GetWindowID(), msg, "python.Alert()")
- - window.alert('SOME ALERT!') -

-
def ChangeAlertDuringRuntime(self):
-        __browser.GetMainFrame().SetProperty("alert", self.Alert2)
- python.ChangeAlertDuringRuntime() - now check window.alert() above, the messagebox style should be changed. - -

Find text on this page

- -
def Find(self, searchText, findNext=False):
-        __browser.Find(1, searchText, forward=True, matchCase=False, findNext=findNext)
- - - - - diff --git a/cefpython/cef1/windows/binaries/cefadvanced.py b/cefpython/cef1/windows/binaries/cefadvanced.py deleted file mode 100644 index b7d3de059..000000000 --- a/cefpython/cef1/windows/binaries/cefadvanced.py +++ /dev/null @@ -1,505 +0,0 @@ -# coding=utf-8 - -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -# Checking whether python architecture and version are valid, -# otherwise an obfuscated error will be thrown when trying -# to load cefpython.pyd with a message "DLL load failed". - -import platform -if platform.architecture()[0] != "32bit": - raise Exception("Only 32bit architecture is supported") - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import the local module. - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - elif 0x03000000 <= sys.hexversion < 0x04000000: - import cefpython_py32 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import the package. - from cefpython1 import cefpython - -import cefwindow - -# pywin32 extension -import win32api -import win32con -import win32gui - -import re -import imp -import inspect -import pprint -import time -import imp - -DEBUG = True - -# TODO: example of creating popup windows from python, -# call WindowInfo.SetAsPopup(). -# TODO: example of creating modal windows from python. - -def GetApplicationPath(file=None): - import re, os - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - if hasattr(sys, "frozen"): - path = os.path.dirname(sys.executable) - elif "__file__" in globals(): - path = os.path.dirname(os.path.realpath(__file__)) - else: - path = os.getcwd() - path = path + os.sep + file - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("cefpython: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -def InitDebugging(): - # Whether to print & log debug messages - if DEBUG: - cefpython.g_debug = True - cefpython.g_debugFile = GetApplicationPath("debug.log") - cefwindow.g_debug = True - -def CefAdvanced(): - sys.excepthook = ExceptHook - InitDebugging() - - appSettings = dict() - appSettings["log_file"] = GetApplicationPath("debug.log") - - # LOGSEVERITY_INFO - less debug oput. - # LOGSEVERITY_DISABLE - will not create "debug.log" file. - appSettings["log_severity"] = cefpython.LOGSEVERITY_VERBOSE - - # Enable only when debugging, otherwise performance might hurt. - appSettings["release_dcheck_enabled"] = True - - # Must be set so that OnUncaughtException() is called. - appSettings["uncaught_exception_stack_size"] = 100 - - cefpython.Initialize(applicationSettings=appSettings) - - # Closing main window quits the application as we define - # WM_DESTOROY message. - wndproc = { - win32con.WM_CLOSE: CloseWindow, - win32con.WM_DESTROY: QuitApplication, - win32con.WM_SIZE: cefpython.WindowUtils.OnSize, - win32con.WM_SETFOCUS: cefpython.WindowUtils.OnSetFocus, - win32con.WM_ERASEBKGND: cefpython.WindowUtils.OnEraseBackground - } - - windowHandle = cefwindow.CreateWindow( - title="CefAdvanced", className="cefadvanced", - width=900, height=710, icon="icon.ico", windowProc=wndproc) - - browserSettings = dict() - browserSettings["history_disabled"] = False - browserSettings["universal_access_from_file_urls_allowed"] = True - browserSettings["file_access_from_file_urls_allowed"] = True - - javascriptBindings = cefpython.JavascriptBindings( - bindToFrames=False, bindToPopups=True) - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(windowHandle) - browser = cefpython.CreateBrowserSync( - windowInfo, browserSettings=browserSettings, - navigateUrl=GetApplicationPath("cefadvanced.html")) - browser.SetUserData("outerWindowHandle", windowInfo.parentWindowHandle) - browser.SetClientHandler(ClientHandler()) - browser.SetJavascriptBindings(javascriptBindings) - - javascriptRebindings = JavascriptRebindings(javascriptBindings, browser) - javascriptRebindings.Bind() - browser.SetUserData("javascriptRebindings", javascriptRebindings) - - cefpython.MessageLoop() - cefpython.Shutdown() - -def CloseWindow(windowHandle, msg, wparam, lparam): - browser = cefpython.GetBrowserByWindowHandle(windowHandle) - browser.CloseBrowser() - return win32gui.DefWindowProc(windowHandle, msg, wparam, lparam) - -def QuitApplication(windowHandle, msg, wparam, lparam): - win32gui.PostQuitMessage(0) - return 0 - -class JavascriptRebindings: - javascriptBindings = None - browser = None - - def __init__(self, javascriptBindings, browser): - self.javascriptBindings = javascriptBindings - self.browser = browser - - def Bind(self): - # These bindings are rebinded when pressing F5. - # It's not useful for the main module as it can't be reloaded. - python = Python() - python.browser = self.browser - - # Overwrite "window.alert". - # self.javascriptBindings.SetFunction("alert", python.Alert) - - self.javascriptBindings.SetObject("python", python) - self.javascriptBindings.SetObject("browser", self.browser) - self.javascriptBindings.SetObject("frame", self.browser.GetMainFrame()) - self.javascriptBindings.SetProperty("PyConfig", - {"option1": True, "option2": 20}) - - def Rebind(self): - # Reload all application modules, next rebind javascript bindings. - # Called from: OnKeyEvent > F5. - - currentDir = GetApplicationPath() - - for mod in sys.modules.values(): - if mod and mod.__name__ != "__main__": - # This module resides in app's directory. - if hasattr(mod, "__file__") and ( - mod.__file__.find(currentDir) != -1): - try: - imp.reload(mod) - if DEBUG: - print("Reloaded module: %s" % mod.__name__) - except (Exception, exc): - print("WARNING: reloading module failed: %s. " - "Exception: %s" % (mod.__name__, exc)) - - # cefpython & cefwindow modules have been reloaded, - # we need to re-initialize debugging. - InitDebugging() - - self.Bind() - self.javascriptBindings.Rebind() - -class ClientHandler: - - def OnLoadStart(self, browser, frame): - # print("OnLoadStart(): frame url: %s" % frame.GetUrl()) - pass - - def OnLoadEnd(self, browser, frame, httpStatusCode): - # print("OnLoadEnd(): frame url: %s" % frame.GetUrl()) - pass - - def OnLoadError(self, browser, frame, errorCode, failedUrl, errorText): - # print("OnLoadError() failedUrl: %s" % (failedUrl)) - errorText[0] = ("Custom error message when loading url fails, " - "see: def OnLoadError()") - return True - - def OnKeyEvent(self, browser, eventType, keyCode, modifiers, isSystemKey, - isAfterJavascript): - - # print("eventType = %s, keyCode=%s, modifiers=%s, isSystemKey=%s" % - # (eventType, keyCode, modifiers, isSystemKey)) - - if eventType != cefpython.KEYEVENT_RAWKEYDOWN or isSystemKey: - return False - - # Bind F12 to developer tools. - if keyCode == cefpython.VK_F12 and ( - cefpython.IsKeyModifier(cefpython.KEY_NONE, modifiers)): - browser.ShowDevTools() - return True - - # Bind F5 to refresh browser window. - # Also reload all modules and rebind javascript bindings. - if keyCode == cefpython.VK_F5 and ( - cefpython.IsKeyModifier(cefpython.KEY_NONE, modifiers)): - # When we press F5 in Developer Tools popup, there are - # no bindings in this window, error would be thrown. - # Pressing F5 in Developer Tools seem to not refresh - # the parent window. - if browser.GetUserData("javascriptRebindings"): - browser.GetUserData("javascriptRebindings").Rebind() - # This is not required, rebinding will work without refreshing page. - browser.ReloadIgnoreCache() - return True - - # Bind Ctrl(+) to increase zoom level - if keyCode in (187, 107) and ( - cefpython.IsKeyModifier(cefpython.KEY_CTRL, modifiers)): - browser.SetZoomLevel(browser.GetZoomLevel() +1) - return True - - # Bind Ctrl(-) to reduce zoom level - if keyCode in (189, 109) and ( - cefpython.IsKeyModifier(cefpython.KEY_CTRL, modifiers)): - browser.SetZoomLevel(browser.GetZoomLevel() -1) - return True - - # Bind F11 to go fullscreen. - if keyCode == cefpython.VK_F11 and ( - cefpython.IsKeyModifier(cefpython.KEY_NONE, modifiers)): - browser.ToggleFullscreen() - return True - - return False - - def OnConsoleMessage(self, browser, message, source, line): - appdir = GetApplicationPath().replace("\\", "/") - if appdir[1] == ":": - appdir = appdir[0].upper() + appdir[1:] - source = source.replace("file:///", "") - source = source.replace(appdir, "") - print("Console message: %s (%s:%s)\n" % (message, source, line)); - return False - - def OnResourceResponse(self, browser, url, response, filter): - # This function does not get called for local disk sources (file:///). - pass - # print("Resource: %s (status=%s)" % (url, response.GetStatus())) - # response.SetHeaderMap( - # {"Content-Length": 123, "Content-Type": "none"}) - # print("response.GetHeaderMap(): %s" % response.GetHeaderMap()) - # print("response.GetHeaderMultimap(): %s" % ( - # response.GetHeaderMultimap())) - - def OnUncaughtException(self, browser, frame, exception, stackTrace): - if not "cefadvanced.html" in frame.GetUrl(): - # Exit application when javascript encountered - # only for the cefadvanced.html example. - return - url = exception["scriptResourceName"] - stackTrace = cefpython.FormatJavascriptStackTrace(stackTrace) - if re.match(r"file:/+", url): - # Get a relative path of the html/js file, - # get rid of the "file://d:/.../cefpython/". - url = re.sub(r"^file:/+", "", url) - url = re.sub(r"[/\\]+", re.escape(os.sep), url) - url = re.sub(r"%s" % re.escape(GetApplicationPath()), - "", url, flags=re.IGNORECASE) - url = re.sub(r"^%s" % re.escape(os.sep), "", url) - raise Exception("%s.\n" - "On line %s in %s.\n" - "Source of that line: %s\nStack trace:\n%s" % ( - exception["message"], exception["lineNumber"], - url, exception["sourceLine"], stackTrace)) - - def OnTitleChange(self, browser, title): - # cefpython.WindowUtils.SetTitle(browser, "ąś") - # return False - return True - -def ModuleExists(module): - try: - imp.find_module(module) - return True - except ImportError: - return False - -class Python: - browser = None - - def SaveImage(self, outfile, format): - outfile = GetApplicationPath(outfile) - (width, height) = self.browser.GetSize(cefpython.PET_VIEW) - buffer = self.browser.GetImage(cefpython.PET_VIEW, width, height) - if ModuleExists("PIL"): - self.__SaveImageWithPil(buffer, width, height, outfile, format) - elif ModuleExists("pygame"): - self.__SaveImageWithPygame(buffer, width, height, outfile) - else: - print("Could not save image, no image library found (PIL, pygame)") - if os.path.exists(outfile): - os.system(outfile) - - def __SaveImageWithPil(self, buffer, width, height, outfile, format): - from PIL import Image - image = Image.fromstring( - "RGBA", (width,height), - buffer.GetString(mode="rgba", origin="top-left"), - "raw", "RGBA", 0, 1) - image.save(outfile, format) - - def __SaveImageWithPygame(self, buffer, width, height, outfile): - import pygame - # Format "PNG" is read from the filename. - surface = pygame.image.frombuffer( - buffer.GetString(mode="rgba", origin="top-left"), - (width, height), "RGBA") - pygame.image.save(surface, outfile) - - def ExecuteJavascript(self, jsCode): - self.browser.GetMainFrame().ExecuteJavascript(jsCode) - - def LoadUrl(self): - self.browser.GetMainFrame().LoadUrl( - GetApplicationPath("cefsimple.html")) - - def Version(self): - return sys.version - - def Test1(self, arg1): - print("python.Test1(%s) called" % arg1) - return ("This string was returned from python function python.Test1()" - " [unicode: ąś]") - - def Test2(self, arg1, arg2, arg3): - # ąś == b"\xc4\x85\xc5\x9b" - # ąś == u"\u0105\u015b" - # Displaying utf-8 characters to the console may result - # in UnicodeDecodeError, thus let's convert it to bytes - # and display the raw b"\xc4\x85\xc5\x9b" characters. - arg2_original = arg2 - if type(arg2) != bytes: - arg2 = arg2.encode(encoding="utf-8") - print("python.Test2(%s, '%s', '%s') called" % (arg1, arg2, arg3)) - # Testing nested return values. - return [1,2, [2.1, {'3': 3, '4': [5,6]}], "[unicode: ąś]", - arg2_original, arg2] - - def PrintPyConfig(self): - print("python.PrintPyConfig(): %s" % ( - self.browser.GetMainFrame().GetProperty("PyConfig"))) - - def ChangePyConfig(self): - self.browser.GetMainFrame().SetProperty("PyConfig", - "Changed in python during runtime in python.ChangePyConfig()") - - def TestJavascriptCallback(self, jsCallback): - if isinstance(jsCallback, cefpython.JavascriptCallback): - print("python.TestJavascriptCallback(): jsCallback.GetName(): " - "%s" % jsCallback.GetName()) - print("jsCallback.Call(1, [2,3], ('tuple', 'tuple'), " - "'unicode string')") - if bytes == str: - # Python 2.7 - jsCallback.Call(1, [2,3], ('tuple', 'tuple'), - unicode('unicode string [ąś]', encoding="utf-8")) - else: - # Python 3.2 - there is no "unicode()" in python 3 - jsCallback.Call(1, [2,3], ('tuple', 'tuple'), - 'unicode string [ąś]', - 'bytes string [ąś]'.encode('utf-8')) - else: - raise Exception("python.TestJavascriptCallback() failed: " - "given argument is not a javascript callback function") - - def TestPythonCallbackThroughReturn(self): - print("python.TestPythonCallbackThroughReturn() called, " - "returning PyCallback.") - return self.PyCallback - - def PyCallback(self, *args): - print("python.PyCallback() called, args: %s" % str(args)) - - def TestPythonCallbackThroughJavascriptCallback(self, jsCallback): - print("python.TestPythonCallbackThroughJavascriptCallback(jsCallback) " - "called") - print("jsCallback.Call(PyCallback)") - jsCallback.Call(self.PyCallback) - - def Alert(self, msg): - print("python.Alert() called instead of window.alert()") - win32gui.MessageBox(self.browser.GetUserData("outerWindowHandle"), - msg, "python.Alert()", win32con.MB_ICONQUESTION) - - def ChangeAlertDuringRuntime(self): - self.browser.GetMainFrame().SetProperty("alert", self.Alert2) - - def Alert2(self, msg): - print("python.Alert2() called instead of window.alert()") - win32gui.MessageBox(self.browser.GetUserData("outerWindowHandle"), - msg, "python.Alert2()", win32con.MB_ICONSTOP) - - def Find(self, searchText, findNext=False): - self.browser.Find(1, searchText, forward=True, matchCase=False, - findNext=findNext) - - def ResizeWindow(self): - cefwindow.MoveWindow(self.browser.GetUserData("outerWindowHandle"), - width=500, height=500) - - def MoveWindow(self): - cefwindow.MoveWindow(self.browser.GetUserData("outerWindowHandle"), - xpos=0, ypos=0) - - def GetType(self, arg1): - return "arg1=%s, type=%s" % (arg1, type(arg1).__name__) - - def CreateSecondBrowser(self): - # Closing second window won't quit application, - # WM_DESTROY not defined here. - wndproc2 = { - win32con.WM_CLOSE: CloseWindow, - win32con.WM_SIZE: cefpython.WindowUtils.OnSize, - win32con.WM_SETFOCUS: cefpython.WindowUtils.OnSetFocus, - win32con.WM_ERASEBKGND: cefpython.WindowUtils.OnEraseBackground - } - windowHandle2 = cefwindow.CreateWindow( - title="SecondBrowser", className="secondbrowser", - width=800, height=600, xpos=0, ypos=0, icon="icon.ico", - windowProc=wndproc2) - windowInfo2 = cefpython.WindowInfo() - windowInfo2.SetAsChild(windowHandle2) - browser2 = cefpython.CreateBrowserSync( - windowInfo2, browserSettings={}, - navigateUrl=GetApplicationPath("cefsimple.html")) - browser2.SetUserData("outerWindowHandle", windowHandle2) - - def GetUnicodeString(self): - if bytes == str: - # Python 2.7. Can't write u"This is unicode string \u2014" - # because Python 3 complains. - return unicode("This is unicode string \xe2\x80\x94".decode("utf-8")) - else: - return "Unicode string can be tested only in python 2.x" - - def TransparentPopup(self): - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsPopup(self.browser.GetWindowHandle(), "transparent") - windowInfo.SetTransparentPainting(True) - cefpython.CreateBrowserSync(windowInfo, browserSettings={}, - navigateUrl=GetApplicationPath("cefsimple.html")) - -if __name__ == "__main__": - CefAdvanced() diff --git a/cefpython/cef1/windows/binaries/cefclient_dcheck.bat b/cefpython/cef1/windows/binaries/cefclient_dcheck.bat deleted file mode 100644 index 0c23b8d5f..000000000 --- a/cefpython/cef1/windows/binaries/cefclient_dcheck.bat +++ /dev/null @@ -1,2 +0,0 @@ -cefclient.exe -release-dcheck-enabled -log-severity=verbose -pause \ No newline at end of file diff --git a/cefpython/cef1/windows/binaries/cefpython_py27.py b/cefpython/cef1/windows/binaries/cefpython_py27.py deleted file mode 100644 index 0b0e988ce..000000000 --- a/cefpython/cef1/windows/binaries/cefpython_py27.py +++ /dev/null @@ -1,815 +0,0 @@ -# This file contains API for the "cefpython.pyd" module, all functions are dummy. -# Use it as a quick reference. Use it for code completion in your IDE. -# This file does NOT need to be distribitued along with binaries. - -raise Exception("A dummy API file was imported instead of the PYD module.") - -""" -Detailed documentation with examples can be found on wiki pages: -http://code.google.com/p/cefpython/w/list -""" - -# Global functions in cefpython module. - -def CreateBrowserSync(windowInfo, browserSettings, navigateUrl): - return Browser() - -def FormatJavascriptStackTrace(stackTrace): - return "" - -def GetBrowserByWindowHandle(windowHandle): - return Browser() - -def GetJavascriptStackTrace(frameLimit=100): - return [] - -def Initialize(applicationSettings={}): - return None - -def IsKeyModifier(key, modifiers): - return False - -def MessageLoop(): - return None - -def MessageLoopWork(): - return None - -def QuitMessageLoop(): - return None - -def Shutdown(): - return None - -def GetModuleDirectory(): - return "" - -# -# Settings -# - -# Values are dummy, these are NOT the defaults. -ApplicationSettings = { - "auto_detect_proxy_settings_enabled": False, - "cache_path": "", - "extra_plugin_paths": [""], - "graphics_implementation": ANGLE_IN_PROCESS, - "javascript_flags": "", - "local_storage_quota": 5*1024*1024, - "locale": "", - "locales_dir_path": "", - "log_file": "", - "log_severity": LOGSEVERITY_INFO, - "release_dcheck_enabled": False, - "multi_threaded_message_loop": False, - "pack_loading_disabled": False, - "product_version": "", - "resources_dir_path": "", - "session_storage_quota": 5*1024*1024, - "string_encoding": "utf-8", - "uncaught_exception_stack_size": 0, - "user_agent": "", -} - -# ApplicationSettings["log_severity"] -LOGSEVERITY_VERBOSE = 0 -LOGSEVERITY_INFO = 0 -LOGSEVERITY_WARNING = 0 -LOGSEVERITY_ERROR = 0 -LOGSEVERITY_ERROR_REPORT = 0 -LOGSEVERITY_DISABLE = 0 - -# ApplicationSettings["graphics_implementation"] -ANGLE_IN_PROCESS = 0 -ANGLE_IN_PROCESS_COMMAND_BUFFER = 0 -DESKTOP_IN_PROCESS = 0 -DESKTOP_IN_PROCESS_COMMAND_BUFFER = 0 - -# Values are dummy, these are NOT the defaults. -BrowserSettings = { - "accelerated_2d_canvas_disabled": False, - "accelerated_compositing_enabled": False, - "accelerated_filters_disabled": False, - "accelerated_layers_disabled": False, - "accelerated_plugins_disabled": False, - "accelerated_video_disabled": False, - "animation_frame_rate": 0, - "application_cache_disabled": False, - "author_and_user_styles_disabled": False, - "caret_browsing_enabled": False, - "cursive_font_family": "", - "databases_disabled": False, - "default_encoding": "iso-8859-1", - "default_fixed_font_size": 0, - "default_font_size": 0, - "developer_tools_disabled": False, - "dom_paste_disabled": False, - "drag_drop_disabled": False, - "encoding_detector_enabled": False, - "fantasy_font_family": "", - "file_access_from_file_urls_allowed": False, - "fixed_font_family": "", - "fullscreen_enabled": False, - "history_disabled": False, - "hyperlink_auditing_disabled": False, - "image_load_disabled": False, - "java_disabled": False, - "javascript_access_clipboard_disallowed": False, - "javascript_close_windows_disallowed": False, - "javascript_disabled": False, - "javascript_open_windows_disallowed": False, - "load_drops_disabled": False, - "local_storage_disabled": False, - "minimum_font_size": 0, - "minimum_logical_font_size": 0, - "page_cache_disabled": False, - "plugins_disabled": False, - "remote_fonts_disabled": False, - "sans_serif_font_family": "", - "serif_font_family": "", - "shrink_standalone_images_to_fit": False, - "site_specific_quirks_disabled": False, - "standard_font_family": "", - "tab_to_links_disabled": False, - "text_area_resize_disabled": False, - "universal_access_from_file_urls_allowed": False, - "user_style_sheet_enabled": False, - "user_style_sheet_location": "", - "web_security_disabled": False, - "webgl_disabled": False, - "xss_auditor_enabled": False, -} - -# -# Browser object. -# - -class Browser: - - def CanGoBack(self): - return False - - def CanGoForward(self): - return False - - def ClearHistory(self): - return None - - def CloseBrowser(self): - return None - - def CloseDevTools(self): - return None - - def Find(self, searchID, searchText, forward, matchCase, findNext): - return None - - def GetClientCallback(self, name): - return callback - - def GetClientCallbacksDict(self): - return {} - - def GetFocusedFrame(self): - return Frame() - - def GetFrame(self): - return Frame() - - def GetFrameNames(self): - return ["", ""] - - def GetIdentifier(self): - return 0 - - def GetImage(self, paintElementType, width, height): - return PaintBuffer() - - def GetJavascriptBindings(self): - return JavascriptBindings() - - def GetMainFrame(self): - return Frame() - - def GetOpenerWindowHandle(self): - return 0 - - def GetOuterWindowHandle(self): - return 0 - - def GetSize(self, paintElementType): - return (0,0,) - - def GetUserData(self, key): - return None - - def GetWindowID(self): - return windowID - - def GetWindowHandle(self): - return 0 - - def GetZoomLevel(self): - return 0.0 - - def GoBack(self): - return None - - def GoForward(self): - return None - - def HasDocument(self): - return False - - def HidePopup(self): - return None - - def Invalidate(self, dirtyRect): - return None - - def IsFullscreen(self): - return False - - def IsPopup(self): - return False - - def IsPopupVisible(self): - return False - - def IsWindowRenderingDisabled(self): - return False - - def Reload(self): - return None - - def ReloadIgnoreCache(self): - return None - - def SendKeyEvent(self, keyType, keyInfo, modifiers): - return None - - def SendMouseClickEvent(self, x, y, mouseButtonType, mouseUp, clickCount): - return None - - def SendMouseMoveEvent(self, x, y, mouseLeave): - return None - - def SendMouseWheelEvent(self, x, y, deltaX, deltaY): - return None - - def SendFocusEvent(self, setFocus): - return None - - def SendCaptureLostEvent(self): - return None - - def SetClientCallback(self, name, callback): - return None - - def SetClientHandler(self, clientHandler): - return None - - def SetFocus(self, enable): - return None - - def SetJavascriptBindings(self, javascriptBindings): - return None - - def SetSize(self, paintElementType, width, height): - return None - - def SetZoomLevel(self, zoomLevel): - return None - - def SetUserData(self, key, value): - return None - - def ShowDevTools(self): - return None - - def StopLoad(self): - return None - - def StopFinding(self, clearSelection): - return None - - def ToggleFullscreen(self): - return None - -# -# Frame object. -# - -class Frame: - - def Copy(self): - return None - - def Cut(self): - return None - - def Delete(self): - return None - - def ExecuteJavascript(self, jsCode, scriptUrl=None, startLine=None): - return None - - def GetIdentifier(self): - return 0 - - def GetName(self): - return "" - - def GetProperty(self, name): - return mixed - - def GetSource(self): - return "" - - def GetText(self): - return "" - - def GetUrl(self): - return "" - - def IsFocused(self): - return False - - def IsMain(self): - return False - - def LoadString(self, value, url): - return None - - def LoadUrl(self, url): - return None - - def Paste(self): - return None - - def Print(self): - return None - - def Redo(self): - return None - - def SelectAll(self): - return None - - def SetProperty(self, name, value): - return None - - def Undo(self): - return None - - def ViewSource(self): - return None - -class Response: - - def GetStatus(self): - return 0 - - def SetStatus(self, status): - return None - - def GetStatusText(self): - return "" - - def SetStatusText(self, statusText): - return None - - def GetMimeType(self): - return "" - - def SetMimeType(self, mimeType): - return None - - def GetHeader(self, name): - return "" - - def GetHeaderMap(self): - return {} - - def GetHeaderMultimap(self): - return [("","")] - - def SetHeaderMap(self, headerMap={}): - return None - - def SetHeaderMultimap(self, headerMultimap=[]): - return None - -class PaintBuffer: - - def GetIntPointer(self): - return 0 - - def GetString(self, mode="bgra", origin="top-left"): - return "" - -class JavascriptBindings: - - def __init__(self, bindToFrames=False, bindToPopups=False): - return None - - def IsValueAllowed(self, value): - return False - - def Rebind(self): - return None - - def SetFunction(self, name, func): - return None - - def SetObject(self, name, obj): - return None - - def SetProperty(self, name, value): - return None - -class JavascriptCallback: - - def Call(self, param1, param2, param3_etc): - return mixed - - def GetName(self): - return name - -class WindowUtils: - - @staticmethod - def OnSetFocus(windowID, msg, wparam, lparam): - return 0 - - @staticmethod - def OnSize(windowID, msg, wparam, lparam): - return 0 - - @staticmethod - def OnEraseBackground(windowID, msg, wparam, lparam): - return 0 - - @staticmethod - def SetTitle(pyBrowser, pyTitle): - return None - - @staticmethod - def SetIcon(pyBrowser, icon="inherit"): - return None - -# -# DisplayHandler. -# - -# statusType constants (OnStatusMessage). -STATUSTYPE_TEXT = 0 -STATUSTYPE_MOUSEOVER_URL = 0 -STATUSTYPE_KEYBOARD_FOCUS_URL = 0 - -def DisplayHandler_OnAddressChange(browser, frame, url): - return None - -def DisplayHandler_OnConsoleMessage(browser, message, source, line): - return False - -def DisplayHandler_OnContentsSizeChange(browser, frame, width, height): - return None - -def DisplayHandler_OnNavStateChange(browser, canGoBack, canGoForward): - return None - -def DisplayHandler_OnStatusMessage(browser, text, statusType): - return None - -def DisplayHandler_OnTitleChange(browser, title): - return None - -def DisplayHandler_OnTooltip(browser, text_out=[""]): - return False - -# -# KeyboardHandler. -# - -def KeyboardHandler_OnKeyEvent( - browser, eventType, keyCode, modifiers, isSystemKey, isAfterJavascript): - return False - -# keyCode constants (OnKeyEvent). -VK_0=0x30 -VK_1=0x31 -VK_2=0x32 -VK_3=0x33 -VK_4=0x34 -VK_5=0x35 -VK_6=0x36 -VK_7=0x37 -VK_8=0x38 -VK_9=0x39 -VK_A=0x041 -VK_B=0x042 -VK_C=0x043 -VK_D=0x044 -VK_E=0x045 -VK_F=0x046 -VK_G=0x047 -VK_H=0x048 -VK_I=0x049 -VK_J=0x04A -VK_K=0x04B -VK_L=0x04C -VK_M=0x04D -VK_N=0x04E -VK_O=0x04F -VK_P=0x050 -VK_Q=0x051 -VK_R=0x052 -VK_S=0x053 -VK_T=0x054 -VK_U=0x055 -VK_V=0x056 -VK_W=0x057 -VK_X=0x058 -VK_Y=0x059 -VK_Z=0x05A -VK_F1=0x70 -VK_F2=0x71 -VK_F3=0x72 -VK_F4=0x73 -VK_F5=0x74 -VK_F6=0x75 -VK_F7=0x76 -VK_F8=0x77 -VK_F9=0x78 -VK_F10=0x79 -VK_F11=0x7A -VK_F12=0x7B -VK_F13=0x7C -VK_F14=0x7D -VK_F15=0x7E -VK_F16=0x7F -VK_F17=0x80 -VK_F18=0x81 -VK_F19=0x82 -VK_F20=0x83 -VK_F21=0x84 -VK_F22=0x85 -VK_F23=0x86 -VK_F24=0x87 -VK_LSHIFT=0xA0 -VK_RSHIFT=0xA1 -VK_LCONTROL=0xA2 -VK_RCONTROL=0xA3 -VK_LMENU=0xA4 -VK_RMENU=0xA5 -VK_BACK=0x08 -VK_TAB=0x09 -VK_SPACE=0x20 -VK_PRIOR=0x21 -VK_NEXT=0x22 -VK_END=0x23 -VK_HOME=0x24 -VK_LEFT=0x25 -VK_UP=0x26 -VK_RIGHT=0x27 -VK_DOWN=0x28 -VK_SELECT=0x29 -VK_PRINT=0x2A -VK_EXECUTE=0x2B -VK_SNAPSHOT=0x2C -VK_INSERT=0x2D -VK_DELETE=0x2E -VK_HELP=0x2F -VK_SHIFT=0x10 -VK_CONTROL=0x11 -VK_MENU=0x12 -VK_PAUSE=0x13 -VK_CAPITAL=0x14 -VK_CLEAR=0x0C -VK_RETURN=0x0D -VK_ESCAPE=0x1B -VK_LWIN=0x5B -VK_RWIN=0x5C -VK_APPS=0x5D -VK_SLEEP=0x5F -VK_NUMPAD0=0x60 -VK_NUMPAD1=0x61 -VK_NUMPAD2=0x62 -VK_NUMPAD3=0x63 -VK_NUMPAD4=0x64 -VK_NUMPAD5=0x65 -VK_NUMPAD6=0x66 -VK_NUMPAD7=0x67 -VK_NUMPAD8=0x68 -VK_NUMPAD9=0x69 -VK_BROWSER_BACK=0xA6 -VK_BROWSER_FORWARD=0xA7 -VK_BROWSER_REFRESH=0xA8 -VK_BROWSER_STOP=0xA9 -VK_BROWSER_SEARCH=0xAA -VK_BROWSER_FAVORITES=0xAB -VK_BROWSER_HOME=0xAC -VK_VOLUME_MUTE=0xAD -VK_VOLUME_DOWN=0xAE -VK_VOLUME_UP=0xAF -VK_MEDIA_NEXT_TRACK=0xB0 -VK_MEDIA_PREV_TRACK=0xB1 -VK_MEDIA_STOP=0xB2 -VK_MEDIA_PLAY_PAUSE=0xB3 -VK_LAUNCH_MAIL=0xB4 -VK_LAUNCH_MEDIA_SELECT=0xB5 -VK_LAUNCH_APP1=0xB6 -VK_LAUNCH_APP2=0xB7 -VK_MULTIPLY=0x6A -VK_ADD=0x6B -VK_SEPARATOR=0x6C -VK_SUBTRACT=0x6D -VK_DECIMAL=0x6E -VK_DIVIDE=0x6F -VK_NUMLOCK=0x90 -VK_SCROLL=0x91 -VK_LBUTTON=0x01 -VK_RBUTTON=0x02 -VK_CANCEL=0x03 -VK_MBUTTON=0x04 -VK_XBUTTON1=0x05 -VK_XBUTTON2=0x06 -VK_KANA=0x15 -VK_HANGEUL=0x15 -VK_HANGUL=0x15 -VK_JUNJA=0x17 -VK_FINAL=0x18 -VK_HANJA=0x19 -VK_KANJI=0x19 -VK_CONVERT=0x1C -VK_NONCONVERT=0x1D -VK_ACCEPT=0x1E -VK_MODECHANGE=0x1F -VK_PROCESSKEY=0xE5 -VK_PACKET=0xE7 -VK_ICO_HELP=0xE3 -VK_ICO_00=0xE4 -VK_ICO_CLEAR=0xE6 - -# eventType constants (OnKeyEvent). -KEYEVENT_RAWKEYDOWN = 0 -KEYEVENT_KEYDOWN = 0 -KEYEVENT_KEYUP = 0 -KEYEVENT_CHAR = 0 - -# Constants for checking modifiers param (OnKeyEvent), for use with IsKeyModifier() function. -KEY_NONE = 0 -KEY_SHIFT = 0 -KEY_CTRL = 0 -KEY_ALT = 0 -KEY_META = 0 -KEY_KEYPAD = 0 - -# -# LoadHandler. -# - -def LoadHandler_OnLoadEnd(browser, frame, httpStatusCode): - return None - -def LoadHandler_OnLoadError(browser, frame, errorCode, failedUrl, errorText_out=[""]): - return False - -def LoadHandler_OnLoadStart(browser, frame): - return None - -# errorCode constants (OnLoadError). -ERR_FAILED = 0 -ERR_ABORTED = 0 -ERR_INVALID_ARGUMENT = 0 -ERR_INVALID_HANDLE = 0 -ERR_FILE_NOT_FOUND = 0 -ERR_TIMED_OUT = 0 -ERR_FILE_TOO_BIG = 0 -ERR_UNEXPECTED = 0 -ERR_ACCESS_DENIED = 0 -ERR_NOT_IMPLEMENTED = 0 -ERR_CONNECTION_CLOSED = 0 -ERR_CONNECTION_RESET = 0 -ERR_CONNECTION_REFUSED = 0 -ERR_CONNECTION_ABORTED = 0 -ERR_CONNECTION_FAILED = 0 -ERR_NAME_NOT_RESOLVED = 0 -ERR_INTERNET_DISCONNECTED = 0 -ERR_SSL_PROTOCOL_ERROR = 0 -ERR_ADDRESS_INVALID = 0 -ERR_ADDRESS_UNREACHABLE = 0 -ERR_SSL_CLIENT_AUTH_CERT_NEEDED = 0 -ERR_TUNNEL_CONNECTION_FAILED = 0 -ERR_NO_SSL_VERSIONS_ENABLED = 0 -ERR_SSL_VERSION_OR_CIPHER_MISMATCH = 0 -ERR_SSL_RENEGOTIATION_REQUESTED = 0 -ERR_CERT_COMMON_NAME_INVALID = 0 -ERR_CERT_DATE_INVALID = 0 -ERR_CERT_AUTHORITY_INVALID = 0 -ERR_CERT_CONTAINS_ERRORS = 0 -ERR_CERT_NO_REVOCATION_MECHANISM = 0 -ERR_CERT_UNABLE_TO_CHECK_REVOCATION = 0 -ERR_CERT_REVOKED = 0 -ERR_CERT_INVALID = 0 -ERR_CERT_END = 0 -ERR_INVALID_URL = 0 -ERR_DISALLOWED_URL_SCHEME = 0 -ERR_UNKNOWN_URL_SCHEME = 0 -ERR_TOO_MANY_REDIRECTS = 0 -ERR_UNSAFE_REDIRECT = 0 -ERR_UNSAFE_PORT = 0 -ERR_INVALID_RESPONSE = 0 -ERR_INVALID_CHUNKED_ENCODING = 0 -ERR_METHOD_NOT_SUPPORTED = 0 -ERR_UNEXPECTED_PROXY_AUTH = 0 -ERR_EMPTY_RESPONSE = 0 -ERR_RESPONSE_HEADERS_TOO_BIG = 0 -ERR_CACHE_MISS = 0 -ERR_INSECURE_RESPONSE = 0 - -# -# RequestHandler. -# - -def RequestHandler_OnResourceRedirect(browser, oldUrl, newUrl_out=[""]): - return None - -def RequestHandler_OnResourceResponse(browser, url, response, filter_out=[None]): - return None - -def RequestHandler_OnProtocolExecution(browser, url, allowOSExecution_out=[False]): - return False - -def RequestHandler_GetAuthCredentials(browser, isProxy, host, port, realm, scheme, username_out=[""], password_out=[""]): - return False - -# navType constants (OnBeforeBrowse). -NAVTYPE_LINKCLICKED = 0 -NAVTYPE_FORMSUBMITTED = 0 -NAVTYPE_BACKFORWARD = 0 -NAVTYPE_RELOAD = 0 -NAVTYPE_FORMRESUBMITTED = 0 -NAVTYPE_OTHER = 0 -NAVTYPE_LINKDROPPED = 0 - -# -# JavascriptContextHandler -# - -def JavascriptContextHandler_OnUncaughtException(browser, frame, exception, stackTrace): - return None - -# -# LifespanHandler -# - -def LifespanHandler_DoClose(browser): - return False - -def LifespanHandler_OnAfterCreated(browser): - return None - -def LifespanHandler_OnBeforeClose(browser): - return None - -def LifespanHandler_RunModal(browser): - return False - -# -# RenderHandler -# - -PET_VIEW = 0 -PET_POPUP = 0 - -KEYTYPE_KEYUP = 0 -KEYTYPE_KEYDOWN = 0 -KEYTYPE_CHAR = 0 - -MOUSEBUTTON_LEFT = 0 -MOUSEBUTTON_MIDDLE = 0 -MOUSEBUTTON_RIGHT = 0 - -def RenderHandler_GetViewRect(browser, out_rect): - return False - -def RenderHandler_GetScreenRect(browser, out_rect): - return False - -def RenderHandler_GetScreenPoint(browser, viewX, viewY, out_screenCoordinates): - return False - -def RenderHandler_OnPopupShow(browser, show): - return None - -def RenderHandler_OnPopupSize(browser, rect): - return None - -def RenderHandler_OnPaint(browser, paintElementType, out_dirtyRects, - paintBuffer): - return None - -def RenderHandler_OnCursorChange(browser, cursor): - return None diff --git a/cefpython/cef1/windows/binaries/cefpython_py32.py b/cefpython/cef1/windows/binaries/cefpython_py32.py deleted file mode 100644 index 0b0e988ce..000000000 --- a/cefpython/cef1/windows/binaries/cefpython_py32.py +++ /dev/null @@ -1,815 +0,0 @@ -# This file contains API for the "cefpython.pyd" module, all functions are dummy. -# Use it as a quick reference. Use it for code completion in your IDE. -# This file does NOT need to be distribitued along with binaries. - -raise Exception("A dummy API file was imported instead of the PYD module.") - -""" -Detailed documentation with examples can be found on wiki pages: -http://code.google.com/p/cefpython/w/list -""" - -# Global functions in cefpython module. - -def CreateBrowserSync(windowInfo, browserSettings, navigateUrl): - return Browser() - -def FormatJavascriptStackTrace(stackTrace): - return "" - -def GetBrowserByWindowHandle(windowHandle): - return Browser() - -def GetJavascriptStackTrace(frameLimit=100): - return [] - -def Initialize(applicationSettings={}): - return None - -def IsKeyModifier(key, modifiers): - return False - -def MessageLoop(): - return None - -def MessageLoopWork(): - return None - -def QuitMessageLoop(): - return None - -def Shutdown(): - return None - -def GetModuleDirectory(): - return "" - -# -# Settings -# - -# Values are dummy, these are NOT the defaults. -ApplicationSettings = { - "auto_detect_proxy_settings_enabled": False, - "cache_path": "", - "extra_plugin_paths": [""], - "graphics_implementation": ANGLE_IN_PROCESS, - "javascript_flags": "", - "local_storage_quota": 5*1024*1024, - "locale": "", - "locales_dir_path": "", - "log_file": "", - "log_severity": LOGSEVERITY_INFO, - "release_dcheck_enabled": False, - "multi_threaded_message_loop": False, - "pack_loading_disabled": False, - "product_version": "", - "resources_dir_path": "", - "session_storage_quota": 5*1024*1024, - "string_encoding": "utf-8", - "uncaught_exception_stack_size": 0, - "user_agent": "", -} - -# ApplicationSettings["log_severity"] -LOGSEVERITY_VERBOSE = 0 -LOGSEVERITY_INFO = 0 -LOGSEVERITY_WARNING = 0 -LOGSEVERITY_ERROR = 0 -LOGSEVERITY_ERROR_REPORT = 0 -LOGSEVERITY_DISABLE = 0 - -# ApplicationSettings["graphics_implementation"] -ANGLE_IN_PROCESS = 0 -ANGLE_IN_PROCESS_COMMAND_BUFFER = 0 -DESKTOP_IN_PROCESS = 0 -DESKTOP_IN_PROCESS_COMMAND_BUFFER = 0 - -# Values are dummy, these are NOT the defaults. -BrowserSettings = { - "accelerated_2d_canvas_disabled": False, - "accelerated_compositing_enabled": False, - "accelerated_filters_disabled": False, - "accelerated_layers_disabled": False, - "accelerated_plugins_disabled": False, - "accelerated_video_disabled": False, - "animation_frame_rate": 0, - "application_cache_disabled": False, - "author_and_user_styles_disabled": False, - "caret_browsing_enabled": False, - "cursive_font_family": "", - "databases_disabled": False, - "default_encoding": "iso-8859-1", - "default_fixed_font_size": 0, - "default_font_size": 0, - "developer_tools_disabled": False, - "dom_paste_disabled": False, - "drag_drop_disabled": False, - "encoding_detector_enabled": False, - "fantasy_font_family": "", - "file_access_from_file_urls_allowed": False, - "fixed_font_family": "", - "fullscreen_enabled": False, - "history_disabled": False, - "hyperlink_auditing_disabled": False, - "image_load_disabled": False, - "java_disabled": False, - "javascript_access_clipboard_disallowed": False, - "javascript_close_windows_disallowed": False, - "javascript_disabled": False, - "javascript_open_windows_disallowed": False, - "load_drops_disabled": False, - "local_storage_disabled": False, - "minimum_font_size": 0, - "minimum_logical_font_size": 0, - "page_cache_disabled": False, - "plugins_disabled": False, - "remote_fonts_disabled": False, - "sans_serif_font_family": "", - "serif_font_family": "", - "shrink_standalone_images_to_fit": False, - "site_specific_quirks_disabled": False, - "standard_font_family": "", - "tab_to_links_disabled": False, - "text_area_resize_disabled": False, - "universal_access_from_file_urls_allowed": False, - "user_style_sheet_enabled": False, - "user_style_sheet_location": "", - "web_security_disabled": False, - "webgl_disabled": False, - "xss_auditor_enabled": False, -} - -# -# Browser object. -# - -class Browser: - - def CanGoBack(self): - return False - - def CanGoForward(self): - return False - - def ClearHistory(self): - return None - - def CloseBrowser(self): - return None - - def CloseDevTools(self): - return None - - def Find(self, searchID, searchText, forward, matchCase, findNext): - return None - - def GetClientCallback(self, name): - return callback - - def GetClientCallbacksDict(self): - return {} - - def GetFocusedFrame(self): - return Frame() - - def GetFrame(self): - return Frame() - - def GetFrameNames(self): - return ["", ""] - - def GetIdentifier(self): - return 0 - - def GetImage(self, paintElementType, width, height): - return PaintBuffer() - - def GetJavascriptBindings(self): - return JavascriptBindings() - - def GetMainFrame(self): - return Frame() - - def GetOpenerWindowHandle(self): - return 0 - - def GetOuterWindowHandle(self): - return 0 - - def GetSize(self, paintElementType): - return (0,0,) - - def GetUserData(self, key): - return None - - def GetWindowID(self): - return windowID - - def GetWindowHandle(self): - return 0 - - def GetZoomLevel(self): - return 0.0 - - def GoBack(self): - return None - - def GoForward(self): - return None - - def HasDocument(self): - return False - - def HidePopup(self): - return None - - def Invalidate(self, dirtyRect): - return None - - def IsFullscreen(self): - return False - - def IsPopup(self): - return False - - def IsPopupVisible(self): - return False - - def IsWindowRenderingDisabled(self): - return False - - def Reload(self): - return None - - def ReloadIgnoreCache(self): - return None - - def SendKeyEvent(self, keyType, keyInfo, modifiers): - return None - - def SendMouseClickEvent(self, x, y, mouseButtonType, mouseUp, clickCount): - return None - - def SendMouseMoveEvent(self, x, y, mouseLeave): - return None - - def SendMouseWheelEvent(self, x, y, deltaX, deltaY): - return None - - def SendFocusEvent(self, setFocus): - return None - - def SendCaptureLostEvent(self): - return None - - def SetClientCallback(self, name, callback): - return None - - def SetClientHandler(self, clientHandler): - return None - - def SetFocus(self, enable): - return None - - def SetJavascriptBindings(self, javascriptBindings): - return None - - def SetSize(self, paintElementType, width, height): - return None - - def SetZoomLevel(self, zoomLevel): - return None - - def SetUserData(self, key, value): - return None - - def ShowDevTools(self): - return None - - def StopLoad(self): - return None - - def StopFinding(self, clearSelection): - return None - - def ToggleFullscreen(self): - return None - -# -# Frame object. -# - -class Frame: - - def Copy(self): - return None - - def Cut(self): - return None - - def Delete(self): - return None - - def ExecuteJavascript(self, jsCode, scriptUrl=None, startLine=None): - return None - - def GetIdentifier(self): - return 0 - - def GetName(self): - return "" - - def GetProperty(self, name): - return mixed - - def GetSource(self): - return "" - - def GetText(self): - return "" - - def GetUrl(self): - return "" - - def IsFocused(self): - return False - - def IsMain(self): - return False - - def LoadString(self, value, url): - return None - - def LoadUrl(self, url): - return None - - def Paste(self): - return None - - def Print(self): - return None - - def Redo(self): - return None - - def SelectAll(self): - return None - - def SetProperty(self, name, value): - return None - - def Undo(self): - return None - - def ViewSource(self): - return None - -class Response: - - def GetStatus(self): - return 0 - - def SetStatus(self, status): - return None - - def GetStatusText(self): - return "" - - def SetStatusText(self, statusText): - return None - - def GetMimeType(self): - return "" - - def SetMimeType(self, mimeType): - return None - - def GetHeader(self, name): - return "" - - def GetHeaderMap(self): - return {} - - def GetHeaderMultimap(self): - return [("","")] - - def SetHeaderMap(self, headerMap={}): - return None - - def SetHeaderMultimap(self, headerMultimap=[]): - return None - -class PaintBuffer: - - def GetIntPointer(self): - return 0 - - def GetString(self, mode="bgra", origin="top-left"): - return "" - -class JavascriptBindings: - - def __init__(self, bindToFrames=False, bindToPopups=False): - return None - - def IsValueAllowed(self, value): - return False - - def Rebind(self): - return None - - def SetFunction(self, name, func): - return None - - def SetObject(self, name, obj): - return None - - def SetProperty(self, name, value): - return None - -class JavascriptCallback: - - def Call(self, param1, param2, param3_etc): - return mixed - - def GetName(self): - return name - -class WindowUtils: - - @staticmethod - def OnSetFocus(windowID, msg, wparam, lparam): - return 0 - - @staticmethod - def OnSize(windowID, msg, wparam, lparam): - return 0 - - @staticmethod - def OnEraseBackground(windowID, msg, wparam, lparam): - return 0 - - @staticmethod - def SetTitle(pyBrowser, pyTitle): - return None - - @staticmethod - def SetIcon(pyBrowser, icon="inherit"): - return None - -# -# DisplayHandler. -# - -# statusType constants (OnStatusMessage). -STATUSTYPE_TEXT = 0 -STATUSTYPE_MOUSEOVER_URL = 0 -STATUSTYPE_KEYBOARD_FOCUS_URL = 0 - -def DisplayHandler_OnAddressChange(browser, frame, url): - return None - -def DisplayHandler_OnConsoleMessage(browser, message, source, line): - return False - -def DisplayHandler_OnContentsSizeChange(browser, frame, width, height): - return None - -def DisplayHandler_OnNavStateChange(browser, canGoBack, canGoForward): - return None - -def DisplayHandler_OnStatusMessage(browser, text, statusType): - return None - -def DisplayHandler_OnTitleChange(browser, title): - return None - -def DisplayHandler_OnTooltip(browser, text_out=[""]): - return False - -# -# KeyboardHandler. -# - -def KeyboardHandler_OnKeyEvent( - browser, eventType, keyCode, modifiers, isSystemKey, isAfterJavascript): - return False - -# keyCode constants (OnKeyEvent). -VK_0=0x30 -VK_1=0x31 -VK_2=0x32 -VK_3=0x33 -VK_4=0x34 -VK_5=0x35 -VK_6=0x36 -VK_7=0x37 -VK_8=0x38 -VK_9=0x39 -VK_A=0x041 -VK_B=0x042 -VK_C=0x043 -VK_D=0x044 -VK_E=0x045 -VK_F=0x046 -VK_G=0x047 -VK_H=0x048 -VK_I=0x049 -VK_J=0x04A -VK_K=0x04B -VK_L=0x04C -VK_M=0x04D -VK_N=0x04E -VK_O=0x04F -VK_P=0x050 -VK_Q=0x051 -VK_R=0x052 -VK_S=0x053 -VK_T=0x054 -VK_U=0x055 -VK_V=0x056 -VK_W=0x057 -VK_X=0x058 -VK_Y=0x059 -VK_Z=0x05A -VK_F1=0x70 -VK_F2=0x71 -VK_F3=0x72 -VK_F4=0x73 -VK_F5=0x74 -VK_F6=0x75 -VK_F7=0x76 -VK_F8=0x77 -VK_F9=0x78 -VK_F10=0x79 -VK_F11=0x7A -VK_F12=0x7B -VK_F13=0x7C -VK_F14=0x7D -VK_F15=0x7E -VK_F16=0x7F -VK_F17=0x80 -VK_F18=0x81 -VK_F19=0x82 -VK_F20=0x83 -VK_F21=0x84 -VK_F22=0x85 -VK_F23=0x86 -VK_F24=0x87 -VK_LSHIFT=0xA0 -VK_RSHIFT=0xA1 -VK_LCONTROL=0xA2 -VK_RCONTROL=0xA3 -VK_LMENU=0xA4 -VK_RMENU=0xA5 -VK_BACK=0x08 -VK_TAB=0x09 -VK_SPACE=0x20 -VK_PRIOR=0x21 -VK_NEXT=0x22 -VK_END=0x23 -VK_HOME=0x24 -VK_LEFT=0x25 -VK_UP=0x26 -VK_RIGHT=0x27 -VK_DOWN=0x28 -VK_SELECT=0x29 -VK_PRINT=0x2A -VK_EXECUTE=0x2B -VK_SNAPSHOT=0x2C -VK_INSERT=0x2D -VK_DELETE=0x2E -VK_HELP=0x2F -VK_SHIFT=0x10 -VK_CONTROL=0x11 -VK_MENU=0x12 -VK_PAUSE=0x13 -VK_CAPITAL=0x14 -VK_CLEAR=0x0C -VK_RETURN=0x0D -VK_ESCAPE=0x1B -VK_LWIN=0x5B -VK_RWIN=0x5C -VK_APPS=0x5D -VK_SLEEP=0x5F -VK_NUMPAD0=0x60 -VK_NUMPAD1=0x61 -VK_NUMPAD2=0x62 -VK_NUMPAD3=0x63 -VK_NUMPAD4=0x64 -VK_NUMPAD5=0x65 -VK_NUMPAD6=0x66 -VK_NUMPAD7=0x67 -VK_NUMPAD8=0x68 -VK_NUMPAD9=0x69 -VK_BROWSER_BACK=0xA6 -VK_BROWSER_FORWARD=0xA7 -VK_BROWSER_REFRESH=0xA8 -VK_BROWSER_STOP=0xA9 -VK_BROWSER_SEARCH=0xAA -VK_BROWSER_FAVORITES=0xAB -VK_BROWSER_HOME=0xAC -VK_VOLUME_MUTE=0xAD -VK_VOLUME_DOWN=0xAE -VK_VOLUME_UP=0xAF -VK_MEDIA_NEXT_TRACK=0xB0 -VK_MEDIA_PREV_TRACK=0xB1 -VK_MEDIA_STOP=0xB2 -VK_MEDIA_PLAY_PAUSE=0xB3 -VK_LAUNCH_MAIL=0xB4 -VK_LAUNCH_MEDIA_SELECT=0xB5 -VK_LAUNCH_APP1=0xB6 -VK_LAUNCH_APP2=0xB7 -VK_MULTIPLY=0x6A -VK_ADD=0x6B -VK_SEPARATOR=0x6C -VK_SUBTRACT=0x6D -VK_DECIMAL=0x6E -VK_DIVIDE=0x6F -VK_NUMLOCK=0x90 -VK_SCROLL=0x91 -VK_LBUTTON=0x01 -VK_RBUTTON=0x02 -VK_CANCEL=0x03 -VK_MBUTTON=0x04 -VK_XBUTTON1=0x05 -VK_XBUTTON2=0x06 -VK_KANA=0x15 -VK_HANGEUL=0x15 -VK_HANGUL=0x15 -VK_JUNJA=0x17 -VK_FINAL=0x18 -VK_HANJA=0x19 -VK_KANJI=0x19 -VK_CONVERT=0x1C -VK_NONCONVERT=0x1D -VK_ACCEPT=0x1E -VK_MODECHANGE=0x1F -VK_PROCESSKEY=0xE5 -VK_PACKET=0xE7 -VK_ICO_HELP=0xE3 -VK_ICO_00=0xE4 -VK_ICO_CLEAR=0xE6 - -# eventType constants (OnKeyEvent). -KEYEVENT_RAWKEYDOWN = 0 -KEYEVENT_KEYDOWN = 0 -KEYEVENT_KEYUP = 0 -KEYEVENT_CHAR = 0 - -# Constants for checking modifiers param (OnKeyEvent), for use with IsKeyModifier() function. -KEY_NONE = 0 -KEY_SHIFT = 0 -KEY_CTRL = 0 -KEY_ALT = 0 -KEY_META = 0 -KEY_KEYPAD = 0 - -# -# LoadHandler. -# - -def LoadHandler_OnLoadEnd(browser, frame, httpStatusCode): - return None - -def LoadHandler_OnLoadError(browser, frame, errorCode, failedUrl, errorText_out=[""]): - return False - -def LoadHandler_OnLoadStart(browser, frame): - return None - -# errorCode constants (OnLoadError). -ERR_FAILED = 0 -ERR_ABORTED = 0 -ERR_INVALID_ARGUMENT = 0 -ERR_INVALID_HANDLE = 0 -ERR_FILE_NOT_FOUND = 0 -ERR_TIMED_OUT = 0 -ERR_FILE_TOO_BIG = 0 -ERR_UNEXPECTED = 0 -ERR_ACCESS_DENIED = 0 -ERR_NOT_IMPLEMENTED = 0 -ERR_CONNECTION_CLOSED = 0 -ERR_CONNECTION_RESET = 0 -ERR_CONNECTION_REFUSED = 0 -ERR_CONNECTION_ABORTED = 0 -ERR_CONNECTION_FAILED = 0 -ERR_NAME_NOT_RESOLVED = 0 -ERR_INTERNET_DISCONNECTED = 0 -ERR_SSL_PROTOCOL_ERROR = 0 -ERR_ADDRESS_INVALID = 0 -ERR_ADDRESS_UNREACHABLE = 0 -ERR_SSL_CLIENT_AUTH_CERT_NEEDED = 0 -ERR_TUNNEL_CONNECTION_FAILED = 0 -ERR_NO_SSL_VERSIONS_ENABLED = 0 -ERR_SSL_VERSION_OR_CIPHER_MISMATCH = 0 -ERR_SSL_RENEGOTIATION_REQUESTED = 0 -ERR_CERT_COMMON_NAME_INVALID = 0 -ERR_CERT_DATE_INVALID = 0 -ERR_CERT_AUTHORITY_INVALID = 0 -ERR_CERT_CONTAINS_ERRORS = 0 -ERR_CERT_NO_REVOCATION_MECHANISM = 0 -ERR_CERT_UNABLE_TO_CHECK_REVOCATION = 0 -ERR_CERT_REVOKED = 0 -ERR_CERT_INVALID = 0 -ERR_CERT_END = 0 -ERR_INVALID_URL = 0 -ERR_DISALLOWED_URL_SCHEME = 0 -ERR_UNKNOWN_URL_SCHEME = 0 -ERR_TOO_MANY_REDIRECTS = 0 -ERR_UNSAFE_REDIRECT = 0 -ERR_UNSAFE_PORT = 0 -ERR_INVALID_RESPONSE = 0 -ERR_INVALID_CHUNKED_ENCODING = 0 -ERR_METHOD_NOT_SUPPORTED = 0 -ERR_UNEXPECTED_PROXY_AUTH = 0 -ERR_EMPTY_RESPONSE = 0 -ERR_RESPONSE_HEADERS_TOO_BIG = 0 -ERR_CACHE_MISS = 0 -ERR_INSECURE_RESPONSE = 0 - -# -# RequestHandler. -# - -def RequestHandler_OnResourceRedirect(browser, oldUrl, newUrl_out=[""]): - return None - -def RequestHandler_OnResourceResponse(browser, url, response, filter_out=[None]): - return None - -def RequestHandler_OnProtocolExecution(browser, url, allowOSExecution_out=[False]): - return False - -def RequestHandler_GetAuthCredentials(browser, isProxy, host, port, realm, scheme, username_out=[""], password_out=[""]): - return False - -# navType constants (OnBeforeBrowse). -NAVTYPE_LINKCLICKED = 0 -NAVTYPE_FORMSUBMITTED = 0 -NAVTYPE_BACKFORWARD = 0 -NAVTYPE_RELOAD = 0 -NAVTYPE_FORMRESUBMITTED = 0 -NAVTYPE_OTHER = 0 -NAVTYPE_LINKDROPPED = 0 - -# -# JavascriptContextHandler -# - -def JavascriptContextHandler_OnUncaughtException(browser, frame, exception, stackTrace): - return None - -# -# LifespanHandler -# - -def LifespanHandler_DoClose(browser): - return False - -def LifespanHandler_OnAfterCreated(browser): - return None - -def LifespanHandler_OnBeforeClose(browser): - return None - -def LifespanHandler_RunModal(browser): - return False - -# -# RenderHandler -# - -PET_VIEW = 0 -PET_POPUP = 0 - -KEYTYPE_KEYUP = 0 -KEYTYPE_KEYDOWN = 0 -KEYTYPE_CHAR = 0 - -MOUSEBUTTON_LEFT = 0 -MOUSEBUTTON_MIDDLE = 0 -MOUSEBUTTON_RIGHT = 0 - -def RenderHandler_GetViewRect(browser, out_rect): - return False - -def RenderHandler_GetScreenRect(browser, out_rect): - return False - -def RenderHandler_GetScreenPoint(browser, viewX, viewY, out_screenCoordinates): - return False - -def RenderHandler_OnPopupShow(browser, show): - return None - -def RenderHandler_OnPopupSize(browser, rect): - return None - -def RenderHandler_OnPaint(browser, paintElementType, out_dirtyRects, - paintBuffer): - return None - -def RenderHandler_OnCursorChange(browser, cursor): - return None diff --git a/cefpython/cef1/windows/binaries/cefsimple.html b/cefpython/cef1/windows/binaries/cefsimple.html deleted file mode 100644 index f46f773c7..000000000 --- a/cefpython/cef1/windows/binaries/cefsimple.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - CefSimple (utf-8: ąś) - - - - -Welcome to CEF Python - bindings for the Chromium Embedded Framework.

- -Project's website: http://code.google.com/p/cefpython/
-Wiki documentation: http://code.google.com/p/cefpython/wiki/
-Support forum: https://groups.google.com/group/cefpython?hl=en
- -

Google Search

- -http://www.google.com/ - -

User agent

- - - -

Popup

- - - window.open('cefsimple.html') - -










-










-










- - - diff --git a/cefpython/cef1/windows/binaries/cefsimple.py b/cefpython/cef1/windows/binaries/cefsimple.py deleted file mode 100644 index 966de180b..000000000 --- a/cefpython/cef1/windows/binaries/cefsimple.py +++ /dev/null @@ -1,109 +0,0 @@ -# Simple CEF Python application, -# for more advanced features see "cefadvanced.py" - -import platform -if platform.architecture()[0] != "32bit": - raise Exception("Only 32bit architecture is supported") - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import the local module. - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - elif 0x03000000 <= sys.hexversion < 0x04000000: - import cefpython_py32 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import the package. - from cefpython1 import cefpython - -import cefwindow -import win32con -import win32gui - -def GetApplicationPath(file=None): - import re, os - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - if hasattr(sys, "frozen"): - path = os.path.dirname(sys.executable) - elif "__file__" in globals(): - path = os.path.dirname(os.path.realpath(__file__)) - else: - path = os.getcwd() - path = path + os.sep + file - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("cefpython: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -def CefSimple(): - sys.excepthook = ExceptHook - cefpython.g_debug = True - cefpython.Initialize() - wndproc = { - win32con.WM_CLOSE: CloseWindow, - win32con.WM_DESTROY: QuitApplication, - win32con.WM_SIZE: cefpython.WindowUtils.OnSize, - win32con.WM_SETFOCUS: cefpython.WindowUtils.OnSetFocus, - win32con.WM_ERASEBKGND: cefpython.WindowUtils.OnEraseBackground } - windowHandle = cefwindow.CreateWindow( - title="CefSimple", className="cefsimple", width=800, height=600, - icon="icon.ico", windowProc=wndproc) - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(windowHandle) - browser = cefpython.CreateBrowserSync( - windowInfo, browserSettings={}, - navigateUrl=GetApplicationPath("cefsimple.html")) - cefpython.MessageLoop() - cefpython.Shutdown() - -def CloseWindow(windowHandle, message, wparam, lparam): - browser = cefpython.GetBrowserByWindowHandle(windowHandle) - browser.CloseBrowser() - return win32gui.DefWindowProc(windowHandle, message, wparam, lparam) - -def QuitApplication(windowHandle, message, wparam, lparam): - win32gui.PostQuitMessage(0) - return 0 - -if __name__ == "__main__": - CefSimple() diff --git a/cefpython/cef1/windows/binaries/cefwindow.py b/cefpython/cef1/windows/binaries/cefwindow.py deleted file mode 100644 index fd0ac73ea..000000000 --- a/cefpython/cef1/windows/binaries/cefwindow.py +++ /dev/null @@ -1,205 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -import win32gui -import win32con -import win32api -import time -import math -import os -import sys -import re - -if sys.version_info.major == 2: - from urllib import pathname2url as urllib_pathname2url -else: - from urllib.request import pathname2url as urllib_pathname2url - -g_debug = False -g_windows = {} # windowID(int): className -g_registeredClasses = {} - -def Debug(msg): - - if not g_debug: - return - msg = "cefwindow: "+str(msg) - print(msg) - with open(GetRealPath("debug.log"), "a") as file: - file.write(msg+"\n") - -def GetRealPath(file=None, encodeURL=False): - - # This function is defined in 2 files: cefpython.pyx and cefwindow.py, if you make changes edit both files. - # If file is None return current directory, without trailing slash. - - # encodeURL param - will call urllib.pathname2url(), only when file is empty (current dir) - # or is relative path ("test.html", "some/test.html"), we need to encode it before passing - # to CreateBrowser(), otherwise it is encoded by CEF internally and becomes (chinese characters): - # >> %EF%BF%97%EF%BF%80%EF%BF%83%EF%BF%A6 - # but should be: - # >> %E6%A1%8C%E9%9D%A2 - - if file is None: file = "" - if file.find("/") != 0 and file.find("\\") != 0 and not re.search(r"^[a-zA-Z]+:[/\\]?", file): - # Execute this block only when relative path ("test.html", "some\test.html") or file is empty (current dir). - # 1. find != 0 >> not starting with / or \ (/ - linux absolute path, \ - just to be sure) - # 2. not re.search >> not (D:\\ or D:/ or D: or http:// or ftp:// or file://), - # "D:" is also valid absolute path ("D:cefpython" in chrome becomes "file:///D:/cefpython/") - if hasattr(sys, "frozen"): path = os.path.dirname(sys.executable) - elif "__file__" in globals(): path = os.path.dirname(os.path.realpath(__file__)) - else: path = os.getcwd() - path = path + os.sep + file - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) # directory without trailing slash. - if encodeURL: - return urllib_pathname2url(path) - else: - return path - return file - -def CreateWindow(title, className, width, height, xpos=None, ypos=None, icon=None, windowProc=None): - - """ - for key in g_windows: - if g_windows[key] == className: - raise Exception("There was already created a window with that className: %s." - "Each created window must have an unique className." % className) - """ - - if not windowProc: - windowProc = {win32con.WM_CLOSE: WM_CLOSE} - - bigIcon = "" - smallIcon = "" - - if icon: - icon = GetRealPath(icon) - - # Load small and big icon. - # WNDCLASSEX (along with hIconSm) is not supported by pywin32, - # we need to use WM_SETICON message after window creation. - - # http://stackoverflow.com/questions/2234988/how-to-set-hicon-on-a-window-ico-with-multiple-sizes - # http://blog.barthe.ph/2009/07/17/wmseticon/ - - bigX = win32api.GetSystemMetrics(win32con.SM_CXICON) - bigY = win32api.GetSystemMetrics(win32con.SM_CYICON) - bigIcon = win32gui.LoadImage(0, icon, win32con.IMAGE_ICON, bigX, bigY, win32con.LR_LOADFROMFILE) - smallX = win32api.GetSystemMetrics(win32con.SM_CXSMICON) - smallY = win32api.GetSystemMetrics(win32con.SM_CYSMICON) - smallIcon = win32gui.LoadImage(0, icon, win32con.IMAGE_ICON, smallX, smallY, win32con.LR_LOADFROMFILE) - - wndclass = win32gui.WNDCLASS() - wndclass.hInstance = win32api.GetModuleHandle(None) - wndclass.lpszClassName = className - wndclass.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW - # win32con.CS_GLOBALCLASS - wndclass.hbrBackground = win32con.COLOR_WINDOW - wndclass.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW) - wndclass.lpfnWndProc = windowProc - - #noinspection PyUnusedLocal - global g_registeredClasses - if not className in g_registeredClasses: - g_registeredClasses[className] = True - atomclass = win32gui.RegisterClass(wndclass) - Debug("win32gui.RegisterClass(%s)" % className) - - if xpos is None or ypos is None: - # Center window on the screen. - Debug("Centering window on the screen.") - screenx = win32api.GetSystemMetrics(win32con.SM_CXSCREEN) - screeny = win32api.GetSystemMetrics(win32con.SM_CYSCREEN) - xpos = int(math.floor((screenx - width) / 2)) - ypos = int(math.floor((screeny - height) / 2)) - if xpos < 0: xpos = 0 - if ypos < 0: ypos = 0 - - windowID = win32gui.CreateWindow(className, title, - win32con.WS_OVERLAPPEDWINDOW | win32con.WS_CLIPCHILDREN | win32con.WS_VISIBLE, - xpos, ypos, width, height, # xpos, ypos, width, height - 0, 0, wndclass.hInstance, None) - g_windows[windowID] = className - - if icon: - if bigIcon: - win32api.SendMessage(windowID, win32con.WM_SETICON, win32con.ICON_BIG, bigIcon) - if smallIcon: - win32api.SendMessage(windowID, win32con.WM_SETICON, win32con.ICON_SMALL, smallIcon) - - Debug("windowID = %s" % windowID) - return windowID - - -# Memory error when calling win32gui.DestroyWindow() -# after we called cefpython.CloseBrowser() - -def DestroyWindow(windowID): - - win32gui.DestroyWindow(windowID) - #className = GetWindowClassName(windowID) - #win32gui.UnregisterClass(className, None) - #del g_windows[windowID] # Let window with this className be created again. - - -def GetWindowClassName(windowID): - - for key in g_windows: - if key == windowID: - return g_windows[key] - -def MoveWindow(windowID, xpos=None, ypos=None, width=None, height=None, center=None): - - (left, top, right, bottom) = win32gui.GetWindowRect(windowID) - if xpos is None and ypos is None: - xpos = left - ypos = top - if width is None and height is None: - width = right - left - height = bottom - top - # Case: only ypos provided - if xpos is None and ypos is not None: - xpos = left - if ypos is None and xpos is not None: - ypos = top - # Case: only height provided - if not width: - width = right - left - if not height: - height = bottom - top - if center: - screenx = win32api.GetSystemMetrics(win32con.SM_CXSCREEN) - screeny = win32api.GetSystemMetrics(win32con.SM_CYSCREEN) - xpos = int(math.floor((screenx - width) / 2)) - ypos = int(math.floor((screeny - height) / 2)) - if xpos < 0: xpos = 0 - if ypos < 0: ypos = 0 - win32gui.MoveWindow(windowID, xpos, ypos, width, height, 1) - - -#noinspection PyUnusedLocal -def WM_CLOSE(windowID, msg, wparam, lparam): - - DestroyWindow(windowID) - win32gui.PostQuitMessage(0) - - -def GetLastError(): - - code = win32api.GetLastError() - return "(%d) %s" % (code, win32api.FormatMessage(code)) - -#noinspection PyUnusedLocal -def MessageLoop(className): - - while not win32gui.PumpWaitingMessages(): - time.sleep(0.001) - - -if __name__ == "__main__": - - g_debug = True - hwnd = CreateWindow("Test window", "testwindow", 800, 600) - MessageLoop("testwindow") \ No newline at end of file diff --git a/cefpython/cef1/windows/binaries/cefwxpanel.py b/cefpython/cef1/windows/binaries/cefwxpanel.py deleted file mode 100644 index e53f52d3f..000000000 --- a/cefpython/cef1/windows/binaries/cefwxpanel.py +++ /dev/null @@ -1,147 +0,0 @@ -# Additional wx specific layer of abstraction for the cefpython -# __author__ = "Greg Kacy " - -#------------------------------------------------------------------------------- - -import platform -if platform.architecture()[0] != "32bit": - raise Exception("Only 32bit architecture is supported") - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import the local module. - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - elif 0x03000000 <= sys.hexversion < 0x04000000: - import cefpython_py32 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import the package. - from cefpython1 import cefpython - -import wx - -def GetApplicationPath(file=None): - import re, os - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - if hasattr(sys, "frozen"): - path = os.path.dirname(sys.executable) - elif "__file__" in globals(): - path = os.path.dirname(os.path.realpath(__file__)) - else: - path = os.getcwd() - path = path + os.sep + file - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("cefpython: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -#------------------------------------------------------------------------------- - -TIMER_MILLIS = 10 - -#------------------------------------------------------------------------------- - -class CEFWindow(wx.Window): - """Standalone CEF component. The class provides facilites for interacting with wx message loop""" - def __init__(self, parent, url="", size=(-1, -1), *args, **kwargs): - wx.Window.__init__(self, parent, id=wx.ID_ANY, size=size, *args, **kwargs) - self.url = url - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(self.GetHandle()) - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings={}, navigateUrl=url) - - self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) - self.Bind(wx.EVT_SIZE, self.OnSize) - - self.timerID = 1 - self._createTimer() - - def GetBrowser(self): - '''Returns the CEF's browser object''' - return self.browser - - def __del__(self): - '''cleanup stuff''' - self.timer.Stop() - self.browser.CloseBrowser() - - def _createTimer(self): - # this timer's events services the SEF message loops - self.timer = wx.Timer(self, self.timerID) - self.timer.Start(TIMER_MILLIS) # - wx.EVT_TIMER(self, self.timerID, self._onTimer) - - def _onTimer(self, event): - """Service CEF message loop""" - cefpython.MessageLoopWork() - - def OnSetFocus(self, event): - cefpython.WindowUtils.OnSetFocus(self.GetHandle(), 0, 0, 0) - - def OnSize(self, event): - cefpython.WindowUtils.OnSize(self.GetHandle(), 0, 0, 0) - - #def Shutdown(self): - #print "CLOSING PAGE %s, YA MAN" % self.url - #self.timer.Stop() - #self.browser.CloseBrowser() - -#------------------------------------------------------------------------------- - -def initCEF(settings=None): - """Initializes CEF, We should do it before initializing wx - If no settings passed a default is used - """ - sys.excepthook = ExceptHook - if not settings: - settings = { - "log_severity": cefpython.LOGSEVERITY_INFO, - "log_file": GetApplicationPath("debug.log"), - "release_dcheck_enabled": True # Enable only when debugging. - } - cefpython.Initialize(settings) - -def shutdownCEF(): - """Shuts down CEF, should be called by app exiting code""" - cefpython.Shutdown() diff --git a/cefpython/cef1/windows/binaries/cefwxpanel_sample1.py b/cefpython/cef1/windows/binaries/cefwxpanel_sample1.py deleted file mode 100644 index 1aff04042..000000000 --- a/cefpython/cef1/windows/binaries/cefwxpanel_sample1.py +++ /dev/null @@ -1,33 +0,0 @@ -# Simple sample ilustrating the usage of CEFWindow class -# __author__ = "Greg Kacy " - -import wx - -from cefwxpanel import initCEF, shutdownCEF, CEFWindow, GetApplicationPath - -class MainFrame(wx.Frame): - def __init__(self): - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, title='wxPython example', size=(600,400)) - - self.cefPanel = CEFWindow(self, - url=GetApplicationPath("cefsimple.html")) - - sizer = wx.BoxSizer() - sizer.Add(self.cefPanel, 1, wx.EXPAND, 0) - self.SetSizer(sizer) - - self.Bind(wx.EVT_CLOSE, self.OnClose) - - def OnClose(self, event): - self.Destroy() - -if __name__ == '__main__': - initCEF() - print('wx.version=%s' % wx.version()) - app = wx.PySimpleApp() - MainFrame().Show() - app.MainLoop() - del app # Let wx.App destructor do the cleanup before calling cefpython.Shutdown(). - shutdownCEF() - - diff --git a/cefpython/cef1/windows/binaries/cefwxpanel_sample2.py b/cefpython/cef1/windows/binaries/cefwxpanel_sample2.py deleted file mode 100644 index c7283e5f3..000000000 --- a/cefpython/cef1/windows/binaries/cefwxpanel_sample2.py +++ /dev/null @@ -1,70 +0,0 @@ -# Slightly more advanced sample illustrating the usage of CEFWindow class -# __author__ = "Greg Kacy " - -import wx -import wx.lib.agw.flatnotebook as fnb - -from cefwxpanel import initCEF, shutdownCEF, CEFWindow, GetApplicationPath - -ROOT_NAME = "My Locations" - -URLS = ["http://google.com", - "http://maps.google.com", - "http://youtube.com", - "http://yahoo.com", - "http://wikipedia.com", - "http://cyaninc.com", - ] - -class MainFrame(wx.Frame): - def __init__(self): - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, title='wxPython example', size=(600,400)) - self.initComponents() - self.layoutComponents() - self.initEventHandlers() - - def initComponents(self): - self.tree = wx.TreeCtrl(self, id=-1, size=(200, -1)) - self.root = self.tree.AddRoot(ROOT_NAME) - for url in URLS: - self.tree.AppendItem(self.root, url) - self.tree.Expand(self.root) - - self.tabs = fnb.FlatNotebook(self, wx.ID_ANY, agwStyle=fnb.FNB_NODRAG|fnb.FNB_X_ON_TAB) - - def layoutComponents(self): - sizer = wx.BoxSizer(wx.HORIZONTAL) - sizer.Add(self.tree, 0, wx.EXPAND) - sizer.Add(self.tabs, 1, wx.EXPAND) - self.SetSizer(sizer) - - def initEventHandlers(self): - self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, self.tree) - self.Bind(fnb.EVT_FLATNOTEBOOK_PAGE_CLOSING, self.OnPageClosing) - self.Bind(wx.EVT_CLOSE, self.OnClose) - - def OnSelChanged(self, event): - self.item = event.GetItem() - url = self.tree.GetItemText(self.item) - if url and url != ROOT_NAME: - cefPanel = CEFWindow(self.tabs, url=str(url)) - self.tabs.AddPage(cefPanel, url) - self.tabs.SetSelection(self.tabs.GetPageCount()-1) - event.Skip() - - def OnPageClosing(self, event): - print "One could place some extra closing stuff here" - event.Skip() - - def OnClose(self, event): - self.Destroy() - -if __name__ == '__main__': - initCEF() - print('wx.version=%s' % wx.version()) - app = wx.PySimpleApp() - MainFrame().Show() - app.MainLoop() - del app # Let wx.App destructor do the cleanup before calling cefpython.Shutdown(). - shutdownCEF() - diff --git a/cefpython/cef1/windows/binaries/debug_gdb.bat b/cefpython/cef1/windows/binaries/debug_gdb.bat deleted file mode 100644 index cde0af227..000000000 --- a/cefpython/cef1/windows/binaries/debug_gdb.bat +++ /dev/null @@ -1,7 +0,0 @@ -setlocal -set PATH=%PATH%;C:\mingw\bin;C:\python27 -C:\mingw\bin\gdb.exe --args C:\python27\python.exe %~dp0cefadvanced.py -REM type "run" -REM if error occurs type "backtrace" -REM type "help" for more commands -pause \ No newline at end of file diff --git a/cefpython/cef1/windows/binaries/debug_pdb.bat b/cefpython/cef1/windows/binaries/debug_pdb.bat deleted file mode 100644 index 9a64357ad..000000000 --- a/cefpython/cef1/windows/binaries/debug_pdb.bat +++ /dev/null @@ -1,3 +0,0 @@ -python -m pdb cefadvanced.py -REM type "continue" or "help" -pause \ No newline at end of file diff --git a/cefpython/cef1/windows/binaries/icon.ico b/cefpython/cef1/windows/binaries/icon.ico deleted file mode 100644 index 435045aec271dc2677d61810be947aa2420cd76d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 198275 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 Jm0$eg{{a!zwfz79 diff --git a/cefpython/cef1/windows/binaries/panda3d_.py b/cefpython/cef1/windows/binaries/panda3d_.py deleted file mode 100644 index d03b64671..000000000 --- a/cefpython/cef1/windows/binaries/panda3d_.py +++ /dev/null @@ -1,417 +0,0 @@ -# CEF off-screen rendering using the Panda3D game engine: -# http://www.panda3d.org/ - -# You need panda3D SDK that is compatible with python 2.7, -# version 1.8.0 comes by default with python 2.7. - -# To use custom python (not the one provided with the SDK) -# create a "panda.pth" file inside your copy of python, in -# this file put paths to panda & bin directory on separate -# lines, for example: -# -# c:\Panda3D-1.8.0 -# c:\Panda3D-1.8.0\bin -# -# This will enable your copy of python to find the panda libraries. - -# TODO: fix the blurriness of the browser when window is resized. - -TEST_TRANSPARENCY = False - -import platform -if platform.architecture()[0] != "32bit": - raise Exception("Only 32bit architecture is supported") - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import the local module. - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - elif 0x03000000 <= sys.hexversion < 0x04000000: - import cefpython_py32 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import the package. - from cefpython1 import cefpython - -from pandac.PandaModules import loadPrcFileData -loadPrcFileData("", "Panda3D example") -loadPrcFileData("", "fullscreen 0") -loadPrcFileData("", "win-size 1024 768") -from pandac.PandaModules import TransparencyAttrib - -import direct.directbase.DirectStart -from panda3d.core import * -from direct.showbase.DirectObject import DirectObject -from direct.task import Task -from math import pi, sin, cos, floor, ceil -import platform -import ctypes - -def GetApplicationPath(file=None): - import re, os - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - if hasattr(sys, "frozen"): - path = os.path.dirname(sys.executable) - elif "__file__" in globals(): - path = os.path.dirname(os.path.realpath(__file__)) - else: - path = os.getcwd() - path = path + os.sep + file - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("cefpython: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class World(DirectObject): - browser = None - texture = None - nodePath = None - lastMouseMove = (-1, -1) - translateKeys = None - keyModifiers = 0 - modifierKeys = None - - def __init__(self): - environ = loader.loadModel("models/environment") - environ.reparentTo(render) - environ.setScale(0.25,0.25,0.25) - environ.setPos(-8,42,0) - taskMgr.add(self.spinCameraTask, "SpinCameraTask") - - self.texture = Texture() - self.texture.setCompression(Texture.CMOff) - self.texture.setComponentType(Texture.TUnsignedByte) - self.texture.setFormat(Texture.FRgba4) - - cardMaker = CardMaker("browser2d") - cardMaker.setFrame(-0.75, 0.75, -0.75, 0.75) - node = cardMaker.generate() - self.nodePath = render2d.attachNewNode(node) - self.nodePath.setTexture(self.texture) - if TEST_TRANSPARENCY: - self.nodePath.setTransparency(TransparencyAttrib.MAlpha) - self.nodePath.setHpr(0, 0, 5) - - windowHandle = base.win.getWindowHandle().getIntHandle() - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsOffscreen(windowHandle) - if TEST_TRANSPARENCY: - windowInfo.SetTransparentPainting(True) - - # By default window rendering is 30 fps, let's change - # it to 60 for better user experience when scrolling. - browserSettings = {"animation_frame_rate": 60} - - self.browser = cefpython.CreateBrowserSync( - windowInfo, browserSettings, - navigateUrl=GetApplicationPath("cefsimple.html")) - self.browser.SetClientHandler( - ClientHandler(self.browser, self.texture)) - - # SetFocus needs to be called after browser creation. - if platform.system() == "Windows": - ctypes.windll.user32.SetFocus(windowHandle) - self.browser.SendFocusEvent(True) - - self.setBrowserSize() - self.accept("window-event", self.setBrowserSize) - - self.initMouseHandlers() - self.initKeyboardHandlers() - - taskMgr.add(self.messageLoop, "CefMessageLoop") - - def setBrowserSize(self, window=None): - width = int(round(base.win.getXSize() * 0.75)) - height = int(round(base.win.getYSize() * 0.75)) - self.texture.setXSize(width) - self.texture.setYSize(height) - self.browser.SetSize(cefpython.PET_VIEW, width, height) - - def initMouseHandlers(self): - # Browser methods for sending mouse/keyboard/focus events: - # SendKeyEvent(), SendMouseClickEvent(), SendMouseMoveEvent(), - # SendMouseWheelEvent(), SendFocusEvent(), SendCaptureLostEvent(). - - taskMgr.add(self.onMouseMove, "onMouseMove") - self.accept("mouse1", self.onMouseDown) - self.accept("mouse1-up", self.onMouseUp) - self.accept("wheel_up", self.onMouseWheelUp) - self.accept("wheel_down", self.onMouseWheelDown) - - def initKeyboardHandlers(self): - self.translateKeys = { - "f1": cefpython.VK_F1, "f2": cefpython.VK_F2, - "f3": cefpython.VK_F3, "f4": cefpython.VK_F4, - "f5": cefpython.VK_F5, "f6": cefpython.VK_F6, - "f7": cefpython.VK_F7, "f8": cefpython.VK_F8, - "f9": cefpython.VK_F9, "f10": cefpython.VK_F10, - "f11": cefpython.VK_F11, "f12": cefpython.VK_F12, - - "arrow_left": cefpython.VK_LEFT, - "arrow_up": cefpython.VK_UP, - "arrow_down": cefpython.VK_DOWN, - "arrow_right": cefpython.VK_RIGHT, - - "enter": cefpython.VK_RETURN, - "tab": cefpython.VK_TAB, - "space": cefpython.VK_SPACE, - "escape": cefpython.VK_ESCAPE, - "backspace": cefpython.VK_BACK, - "insert": cefpython.VK_INSERT, - "delete": cefpython.VK_DELETE, - "home": cefpython.VK_HOME, - "end": cefpython.VK_END, - "page_up": cefpython.VK_PAGEUP, - "page_down": cefpython.VK_PAGEDOWN, - - "num_lock": cefpython.VK_NUMLOCK, - "caps_lock": cefpython.VK_CAPITAL, - "scroll_lock": cefpython.VK_SCROLL, - - "lshift": cefpython.VK_LSHIFT, - "rshift": cefpython.VK_RSHIFT, - "lcontrol": cefpython.VK_LCONTROL, - "rcontrol": cefpython.VK_RCONTROL, - "lalt": cefpython.VK_LMENU, - "ralt": cefpython.VK_RMENU, - } - - base.buttonThrowers[0].node().setKeystrokeEvent('keystroke') - base.buttonThrowers[0].node().setButtonDownEvent('button-down') - base.buttonThrowers[0].node().setButtonUpEvent('button-up') - base.buttonThrowers[0].node().setButtonRepeatEvent('button-repeat') - - self.accept("keystroke", self.onKeystroke) - self.accept("button-down", self.onButtonDown) - self.accept("button-up", self.onButtonUp) - self.accept("button-repeat", self.onButtonDown) - - self.keyModifiers = 0 - self.modifierKeys = { - "shift": cefpython.KEY_SHIFT, - "ctrl": cefpython.KEY_CTRL, - "alt": cefpython.KEY_ALT - } - - def keyInfo(self, key): - if platform.system() == "Windows": - return (key, 0, 0) - elif platform.system() == "Darwin": - return (key, 0, 0) - elif platform.system() == "Linux": - return (key,) - - def onKeystroke(self, key): - self.browser.SendKeyEvent(cefpython.KEYTYPE_CHAR, - self.keyInfo(ord(key)), 0) - - def onButtonDownOrUp(self, keyType, key): - if key in self.modifierKeys: - self.keyModifiers |= self.modifierKeys[key] - else: - if key in self.translateKeys: - self.browser.SendKeyEvent(keyType, - self.keyInfo(self.translateKeys[key]), - self.keyModifiers) - - def onButtonDown(self, key): - self.onButtonDownOrUp(cefpython.KEYTYPE_KEYDOWN, key) - - def onButtonUp(self, key): - self.onButtonDownOrUp(cefpython.KEYTYPE_KEYUP, key) - - def isMouseInsideBrowser(self, mouse): - if mouse.getX() >= -0.75 and mouse.getX() <= 0.75 and ( - mouse.getY() >= -0.75 and mouse.getY() <= 0.75): - return True - else: - return False - - def getMousePixelCoordinates(self, mouse): - # This calculation works only for the browser area. - relX = mouse.getX() - relY = mouse.getY() - relX += 0.75 # 0 .. 1.5 - relY += 0.75 # 0 .. 1.5 - width = self.texture.getXSize() - height = self.texture.getYSize() - width /= 1.5 - height /= 1.5 - pixelX = relX * width - pixelY = relY * height - pixelY = abs(pixelY - self.texture.getYSize()) - pixelX = int(round(pixelX)) - pixelY = int(round(pixelY)) - return (pixelX, pixelY) - - def onMouseMove(self, task): - if base.mouseWatcherNode.hasMouse(): - mouse = base.mouseWatcherNode.getMouse() - - (lastX, lastY) = self.lastMouseMove - if lastX == mouse.getX() and lastY == mouse.getY(): - return Task.cont - else: - self.lastMouseMove = (mouse.getX(), mouse.getY()) - - if self.isMouseInsideBrowser(mouse): - self.nodePath.setHpr(0, 0, 0) - (x,y) = self.getMousePixelCoordinates(mouse) - self.browser.SendMouseMoveEvent(x, y, mouseLeave=False) - else: - self.browser.SendMouseMoveEvent(-1, -1, mouseLeave=True) - self.nodePath.setHpr(0, 0, 5) - else: - self.nodePath.setHpr(0, 0, 5) - return Task.cont - - def onMouseDown(self): - mouse = base.mouseWatcherNode.getMouse() - (x,y) = self.getMousePixelCoordinates(mouse) - self.browser.SendMouseClickEvent(x, y, cefpython.MOUSEBUTTON_LEFT, - mouseUp=False, clickCount=1) - - def onMouseUp(self): - mouse = base.mouseWatcherNode.getMouse() - (x,y) = self.getMousePixelCoordinates(mouse) - self.browser.SendMouseClickEvent(x, y, cefpython.MOUSEBUTTON_LEFT, - mouseUp=True, clickCount=1) - - def onMouseWheelUp(self): - if base.mouseWatcherNode.hasMouse(): - mouse = base.mouseWatcherNode.getMouse() - if self.isMouseInsideBrowser(mouse): - (x,y) = self.getMousePixelCoordinates(mouse) - self.browser.SendMouseWheelEvent(x, y, deltaX=0, deltaY=120) - - def onMouseWheelDown(self): - if base.mouseWatcherNode.hasMouse(): - mouse = base.mouseWatcherNode.getMouse() - if self.isMouseInsideBrowser(mouse): - (x,y) = self.getMousePixelCoordinates(mouse) - self.browser.SendMouseWheelEvent(x, y, deltaX=0, deltaY=-120) - - def messageLoop(self, task): - cefpython.MessageLoopWork() - return Task.cont - - def spinCameraTask(self, task): - angleDegrees = task.time * 6.0 - angleRadians = angleDegrees * (pi / 180.0) - camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3) - camera.setHpr(angleDegrees, 0, 0) - return Task.cont - -class ClientHandler: - browser = None - texture = None - - def __init__(self, browser, texture): - self.browser = browser - self.texture = texture - - def OnPaint(self, browser, paintElementType, dirtyRects, buffer): - (width, height) = self.browser.GetSize(paintElementType) - img = self.texture.modifyRamImage() - if paintElementType == cefpython.PET_POPUP: - print("width=%s, height=%s" % (width, height)) - elif paintElementType == cefpython.PET_VIEW: - img.setData(buffer.GetString(mode="bgra", origin="bottom-left")) - else: - raise Exception("Unknown paintElementType: %s" % paintElementType) - - def GetViewRect(self, browser, rect): - return False - print("GetViewRect()") - width = self.texture.getXSize() - height = self.texture.getYSize() - rect.append(0) - rect.append(0) - rect.append(width) - rect.append(height) - return True - - def GetScreenRect(self, browser, rect): - return False - print("GetScreenRect()") - return self.GetViewRect(browser, rect) - - def GetScreenPoint(self, browser, viewX, viewY, screenCoordinates): - return False - print("GetScreenPoint()") - return False - - def OnLoadEnd(self, browser, frame, httpStatusCode): - return - self._saveImage() - - def _saveImage(self): - try: - from PIL import Image - except: - print("PIL library not available, can't save image") - return - (width, height) = self.browser.GetSize(cefpython.PET_VIEW) - buffer = self.browser.GetImage(cefpython.PET_VIEW, width, height) - image = Image.fromstring( - "RGBA", (width,height), - buffer.GetString(mode="rgba", origin="top-left"), - "raw", "RGBA", 0, 1) - image.save("panda3d_image.png", "PNG") - -if __name__ == "__main__": - sys.excepthook = ExceptHook - settings = { - "log_severity": cefpython.LOGSEVERITY_INFO, - "log_file": GetApplicationPath("debug.log"), - "release_dcheck_enabled": True # Enable only when debugging. - } - cefpython.Initialize(settings) - - print("Panda3D version: %s" % PandaSystem.getVersionString()) - w = World() - run() - del w - - cefpython.Shutdown() diff --git a/cefpython/cef1/windows/binaries/pygtk_.py b/cefpython/cef1/windows/binaries/pygtk_.py deleted file mode 100644 index 230aec090..000000000 --- a/cefpython/cef1/windows/binaries/pygtk_.py +++ /dev/null @@ -1,193 +0,0 @@ -# An example of embedding CEF in PyGTK application. - -import platform -if platform.architecture()[0] != "32bit": - raise Exception("Only 32bit architecture is supported") - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import the local module. - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - elif 0x03000000 <= sys.hexversion < 0x04000000: - import cefpython_py32 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import the package. - from cefpython1 import cefpython - -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -def GetApplicationPath(file=None): - import re, os - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - if hasattr(sys, "frozen"): - path = os.path.dirname(sys.executable) - elif "__file__" in globals(): - path = os.path.dirname(os.path.realpath(__file__)) - else: - path = os.getcwd() - path = path + os.sep + file - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("cefpython: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class PyGTKExample: - - mainWindow = None - container = None - browser = None - exiting = None - searchEntry = None - - def __init__(self): - - gobject.timeout_add(10, self.OnTimer) - - self.mainWindow = gtk.Window(gtk.WINDOW_TOPLEVEL) - self.mainWindow.connect('destroy', self.OnExit) - self.mainWindow.set_size_request(width=600, height=400) - self.mainWindow.set_title('PyGTK CEF example') - self.mainWindow.realize() - - self.container = gtk.DrawingArea() - self.container.set_property('can-focus', True) - self.container.connect('size-allocate', self.OnSize) - self.container.show() - - self.searchEntry = gtk.Entry() - # By default, clicking a GTK widget doesn't grab the focus away from a native Win32 control (browser). - self.searchEntry.connect('button-press-event', self.OnWidgetClick) - self.searchEntry.show() - - table = gtk.Table(3, 1, homogeneous=False) - self.mainWindow.add(table) - table.attach(self.CreateMenu(), 0, 1, 0, 1, yoptions=gtk.SHRINK) - table.attach(self.searchEntry, 0, 1, 1, 2, yoptions=gtk.SHRINK) - table.attach(self.container, 0, 1, 2, 3) - table.show() - - windowID = self.container.get_window().handle - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(windowID) - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings={}, - navigateUrl=GetApplicationPath("cefsimple.html")) - - self.mainWindow.show() - - # Browser took focus, we need to get it back and give to searchEntry. - self.mainWindow.get_window().focus() - self.searchEntry.grab_focus() - - def CreateMenu(self): - - file = gtk.MenuItem('File') - file.show() - filemenu = gtk.Menu() - item = gtk.MenuItem('Open') - filemenu.append(item) - item.show() - item = gtk.MenuItem('Exit') - filemenu.append(item) - item.show() - file.set_submenu(filemenu) - - about = gtk.MenuItem('About') - about.show() - - menubar = gtk.MenuBar() - menubar.append(file) - menubar.append(about) - menubar.show() - - return menubar - - def OnWidgetClick(self, widget, data): - - self.mainWindow.get_window().focus() - - def OnTimer(self): - - if self.exiting: - return False - cefpython.MessageLoopWork() - return True - - def OnFocusIn(self, widget, data): - - # This function is currently not called by any of code, but if you would like - # for browser to have automatic focus add such line: - # self.mainWindow.connect('focus-in-event', self.OnFocusIn) - cefpython.WindowUtils.OnSetFocus(self.container.get_window().handle, 0, 0, 0) - - def OnSize(self, widget, sizeAlloc): - - cefpython.WindowUtils.OnSize(self.container.get_window().handle, 0, 0, 0) - - def OnExit(self, widget, data=None): - - self.exiting = True - gtk.main_quit() - -if __name__ == '__main__': - - version = '.'.join(map(str, list(gtk.gtk_version))) - print('GTK version: %s' % version) - - sys.excepthook = ExceptHook - settings = { - "log_severity": cefpython.LOGSEVERITY_INFO, - "log_file": GetApplicationPath("debug.log"), - "release_dcheck_enabled": True # Enable only when debugging. - } - cefpython.Initialize(settings) - - gobject.threads_init() # timer for messageloop - PyGTKExample() - gtk.main() - - cefpython.Shutdown() diff --git a/cefpython/cef1/windows/binaries/pyqt.py b/cefpython/cef1/windows/binaries/pyqt.py deleted file mode 100644 index c74a6f4e3..000000000 --- a/cefpython/cef1/windows/binaries/pyqt.py +++ /dev/null @@ -1,167 +0,0 @@ -# An example of embedding CEF Python in PyQt4 application. - -import platform -if platform.architecture()[0] != "32bit": - raise Exception("Only 32bit architecture is supported") - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import the local module. - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - elif 0x03000000 <= sys.hexversion < 0x04000000: - import cefpython_py32 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import the package. - from cefpython1 import cefpython - -from PyQt4 import QtGui -from PyQt4 import QtCore - -def GetApplicationPath(file=None): - import re, os - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - if hasattr(sys, "frozen"): - path = os.path.dirname(sys.executable) - elif "__file__" in globals(): - path = os.path.dirname(os.path.realpath(__file__)) - else: - path = os.getcwd() - path = path + os.sep + file - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("cefpython: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainWindow(QtGui.QMainWindow): - mainFrame = None - - def __init__(self): - super(MainWindow, self).__init__(None) - self.createMenu() - self.mainFrame = MainFrame(self) - self.setCentralWidget(self.mainFrame) - self.resize(600, 480) - self.setWindowTitle('PyQT example') - self.setFocusPolicy(QtCore.Qt.StrongFocus) - - def createMenu(self): - menubar = self.menuBar() - filemenu = menubar.addMenu("&File") - filemenu.addAction(QtGui.QAction("Open", self)) - filemenu.addAction(QtGui.QAction("Exit", self)) - aboutmenu = menubar.addMenu("&About") - - def focusInEvent(self, event): - cefpython.WindowUtils.OnSetFocus(int(self.centralWidget().winId()), 0, 0, 0) - - def closeEvent(self, event): - self.mainFrame.browser.CloseBrowser() - -class MainFrame(QtGui.QWidget): - browser = None - - def __init__(self, parent=None): - super(MainFrame, self).__init__(parent) - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(int(self.winId())) - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings={}, - navigateUrl=GetApplicationPath("cefsimple.html")) - self.show() - - def moveEvent(self, event): - cefpython.WindowUtils.OnSize(int(self.winId()), 0, 0, 0) - - def resizeEvent(self, event): - cefpython.WindowUtils.OnSize(int(self.winId()), 0, 0, 0) - -class CefApplication(QtGui.QApplication): - timer = None - - def __init__(self, args): - super(CefApplication, self).__init__(args) - self.createTimer() - - def createTimer(self): - self.timer = QtCore.QTimer() - self.timer.timeout.connect(self.onTimer) - self.timer.start(10) - - def onTimer(self): - # The proper way of doing message loop should be: - # 1. In createTimer() call self.timer.start(0) - # 2. In onTimer() call MessageLoopWork() only when - # QtGui.QApplication.instance()->hasPendingEvents() returns False. - # But... there is a bug in Qt, hasPendingEvents() returns always true. - cefpython.MessageLoopWork() - - def stopTimer(self): - # Stop the timer after Qt message loop ended, calls to MessageLoopWork() - # should not happen anymore. - self.timer.stop() - -if __name__ == '__main__': - print("PyQt version: %s" % QtCore.PYQT_VERSION_STR) - print("QtCore version: %s" % QtCore.qVersion()) - - sys.excepthook = ExceptHook - settings = { - "log_severity": cefpython.LOGSEVERITY_INFO, - "log_file": GetApplicationPath("debug.log"), - "release_dcheck_enabled": True # Enable only when debugging. - } - cefpython.Initialize(settings) - - app = CefApplication(sys.argv) - mainWindow = MainWindow() - mainWindow.show() - app.exec_() - app.stopTimer() - - # Need to destroy QApplication(), otherwise Shutdown() fails. - # Unset main window also just to be safe. - del mainWindow - del app - - cefpython.Shutdown() diff --git a/cefpython/cef1/windows/binaries/pyside.py b/cefpython/cef1/windows/binaries/pyside.py deleted file mode 100644 index 35cc8a8f0..000000000 --- a/cefpython/cef1/windows/binaries/pyside.py +++ /dev/null @@ -1,184 +0,0 @@ -# An example of embedding CEF Python in PySide application. - -import platform -if platform.architecture()[0] != "32bit": - raise Exception("Only 32bit architecture is supported") - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import the local module. - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - elif 0x03000000 <= sys.hexversion < 0x04000000: - import cefpython_py32 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import the package. - from cefpython1 import cefpython - -import PySide -from PySide import QtGui -from PySide import QtCore -import ctypes - -def GetApplicationPath(file=None): - import re, os - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - if hasattr(sys, "frozen"): - path = os.path.dirname(sys.executable) - elif "__file__" in globals(): - path = os.path.dirname(os.path.realpath(__file__)) - else: - path = os.getcwd() - path = path + os.sep + file - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("cefpython: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainWindow(QtGui.QMainWindow): - mainFrame = None - - def __init__(self): - super(MainWindow, self).__init__(None) - self.createMenu() - self.mainFrame = MainFrame(self) - self.setCentralWidget(self.mainFrame) - self.resize(600, 480) - self.setWindowTitle('PySide example') - self.setFocusPolicy(QtCore.Qt.StrongFocus) - - def createMenu(self): - menubar = self.menuBar() - filemenu = menubar.addMenu("&File") - filemenu.addAction(QtGui.QAction("Open", self)) - filemenu.addAction(QtGui.QAction("Exit", self)) - aboutmenu = menubar.addMenu("&About") - - def focusInEvent(self, event): - cefpython.WindowUtils.OnSetFocus(int(self.centralWidget().winIdFixed()), 0, 0, 0) - - def closeEvent(self, event): - self.mainFrame.browser.CloseBrowser() - -class MainFrame(QtGui.QWidget): - browser = None - - def __init__(self, parent=None): - super(MainFrame, self).__init__(parent) - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(int(self.winIdFixed())) - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings={}, - navigateUrl=GetApplicationPath("cefsimple.html")) - self.show() - - def winIdFixed(self): - # PySide bug: QWidget.winId() returns , - # there is no easy way to convert it to int. - try: - return int(self.winId()) - except: - if sys.version_info[0] == 2: - ctypes.pythonapi.PyCObject_AsVoidPtr.restype = ctypes.c_void_p - ctypes.pythonapi.PyCObject_AsVoidPtr.argtypes = [ctypes.py_object] - return ctypes.pythonapi.PyCObject_AsVoidPtr(self.winId()) - elif sys.version_info[0] == 3: - ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p - ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object] - return ctypes.pythonapi.PyCapsule_GetPointer(self.winId(), None) - - def moveEvent(self, event): - cefpython.WindowUtils.OnSize(int(self.winIdFixed()), 0, 0, 0) - - def resizeEvent(self, event): - cefpython.WindowUtils.OnSize(int(self.winIdFixed()), 0, 0, 0) - -class CefApplication(QtGui.QApplication): - timer = None - - def __init__(self, args): - super(CefApplication, self).__init__(args) - self.createTimer() - - def createTimer(self): - self.timer = QtCore.QTimer() - self.timer.timeout.connect(self.onTimer) - self.timer.start(10) - - def onTimer(self): - # The proper way of doing message loop should be: - # 1. In createTimer() call self.timer.start(0) - # 2. In onTimer() call MessageLoopWork() only when - # QtGui.QApplication.instance()->hasPendingEvents() returns False. - # But... there is a bug in Qt, hasPendingEvents() returns always true. - cefpython.MessageLoopWork() - - def stopTimer(self): - # Stop the timer after Qt message loop ended, calls to MessageLoopWork() - # should not happen anymore. - self.timer.stop() - -if __name__ == '__main__': - print("PySide version: %s" % PySide.__version__) - print("QtCore version: %s" % QtCore.__version__) - - sys.excepthook = ExceptHook - settings = { - "log_severity": cefpython.LOGSEVERITY_INFO, - "log_file": GetApplicationPath("debug.log"), - "release_dcheck_enabled": True # Enable only when debugging. - } - cefpython.Initialize(settings) - - app = CefApplication(sys.argv) - mainWindow = MainWindow() - mainWindow.show() - app.exec_() - app.stopTimer() - - # Need to destroy QApplication(), otherwise Shutdown() fails. - # Unset main window also just to be safe. - del mainWindow - del app - - cefpython.Shutdown() diff --git a/cefpython/cef1/windows/binaries/wxpython.html b/cefpython/cef1/windows/binaries/wxpython.html deleted file mode 100644 index ff6744439..000000000 --- a/cefpython/cef1/windows/binaries/wxpython.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - CefSimple (utf-8: ąś) - - - - -Use mouse context menu to go Back/Forward in history navigation. - - - -

Google Search

-http://www.google.com/ - - - -

User agent

- - - - -

Popup

- - window.open('wxpython.html') - - - - -

RequestHandler tests

- -

See messages in the console.

- -OnBeforeBrowse() - navigate to see message: -wxpython.html -

- -OnBeforeBrowse() / OnBeforeResourceLoad() - test request.GetPostData() -and request.SetPostData(): -submit a form: - - https://accounts.google.com/ServiceLogin, -upload a file: - - http://encodable.com/uploaddemo/ -

- -OnBeforeResourceLoad() - try loading nonexistent css file locally: - - LoadCssFile('nonexistent.css') - -

- -OnBeforeResourceLoad() - try replacing a resource on the fly: - - LoadCssFile('replace-on-the-fly.css') -(css content: body { color: red; }) -

- -OnResourceRedirect() - try loading this url: - - http://tinyurl.com/google404redirect -

- -OnResourceResponse() - try loading nonexistent css file via http: - - LoadCssFile('http://www.google.com/404.css') -

- -OnResourceResponse() - try filtering content of the resource: - - LoadCssFile('content-filter/replace-on-the-fly.css') -(new css content: body { color: green; } and body h3 { color: orange; } ) -

- - - - - -

WebRequest test

- -See the console for messages.
- - - external.WebRequest('https://code.google.com/robots.txt') - -

Frame.CallFunction() test

- - - - external.DoCallFunction() - - - - -

Cookie tests

- -See messages in the console. -

- -RequestHandler.GetCookieManager() - an example of having an unique -cookie manager for each browser. Visit - - http://www.html-kit.com/tools/cookietester/ and set some cookie, -then go back to this page using the context menu and open a - - new popup window, the cookie should not appear in the popup browser window. -

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

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

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

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

- - - - -

DragHandler test

- -Try dragging a file, or a text/html fragment to the browser window -and look for the messages in the console. In the wxpython.py script see -ClientHandler.OnDragStart() and OnDragEnter(). - - - - -

DownloadHandler test

- -Try downloading this file (838 KiB):
- - http://cefpython.googlecode.com/files/ubuntu-wallpapers2.zip -
-See messages in the console. -The file will be saved in the ./downloads/ directory. - - - - - - diff --git a/cefpython/cef1/windows/binaries/wxpython.py b/cefpython/cef1/windows/binaries/wxpython.py deleted file mode 100644 index bb4fee5ec..000000000 --- a/cefpython/cef1/windows/binaries/wxpython.py +++ /dev/null @@ -1,526 +0,0 @@ -# An example of embedding CEF in wxPython application. - -import platform -if platform.architecture()[0] != "32bit": - raise Exception("Only 32bit architecture is supported") - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import the local module. - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - elif 0x03000000 <= sys.hexversion < 0x04000000: - import cefpython_py32 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import the package. - from cefpython1 import cefpython - -import wx -import time -import re -import uuid - -# Which method to use for message loop processing. -# EVT_IDLE - wx application has priority (default) -# EVT_TIMER - cef browser has priority -# From the tests it seems that Flash content behaves -# better when using a timer. -USE_EVT_IDLE = True - -def GetApplicationPath(file=None): - import re, os, platform - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - if hasattr(sys, "frozen"): - path = os.path.dirname(sys.executable) - elif "__file__" in globals(): - path = os.path.dirname(os.path.realpath(__file__)) - else: - path = os.getcwd() - path = path + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("cefpython: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainFrame(wx.Frame): - browser = None - - def __init__(self): - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, - title='wxPython example', size=(800,600)) - self.CreateMenu() - - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(self.GetHandle()) - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings={}, - navigateUrl=GetApplicationPath("wxpython.html")) - - self.browser.SetClientHandler(ClientHandler()) - jsBindings = cefpython.JavascriptBindings( - bindToFrames=False, bindToPopups=False) - jsBindings.SetObject("external", JavascriptBindings(self.browser)) - self.browser.SetJavascriptBindings(jsBindings) - - self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) - self.Bind(wx.EVT_SIZE, self.OnSize) - self.Bind(wx.EVT_CLOSE, self.OnClose) - if USE_EVT_IDLE: - # Bind EVT_IDLE only for the main application frame. - self.Bind(wx.EVT_IDLE, self.OnIdle) - - def CreateMenu(self): - filemenu = wx.Menu() - filemenu.Append(1, "Open") - exit = filemenu.Append(2, "Exit") - self.Bind(wx.EVT_MENU, self.OnClose, exit) - aboutmenu = wx.Menu() - aboutmenu.Append(1, "CEF Python") - menubar = wx.MenuBar() - menubar.Append(filemenu,"&File") - menubar.Append(aboutmenu, "&About") - self.SetMenuBar(menubar) - - def OnSetFocus(self, event): - cefpython.WindowUtils.OnSetFocus(self.GetHandle(), 0, 0, 0) - - def OnSize(self, event): - cefpython.WindowUtils.OnSize(self.GetHandle(), 0, 0, 0) - - def OnClose(self, event): - self.browser.CloseBrowser() - self.Destroy() - - def OnIdle(self, event): - cefpython.MessageLoopWork() - -class JavascriptBindings: - mainBrowser = None - webRequest = None - webRequestId = 0 - cookieVisitor = None - - def __init__(self, mainBrowser): - self.mainBrowser = mainBrowser - - def WebRequest(self, url): - request = cefpython.Request.CreateRequest() - request.SetUrl(url) - webRequestClient = WebRequestClient() - # Must keep the reference otherwise WebRequestClient - # callbacks won't be called. - self.webRequest = cefpython.WebRequest.CreateWebRequest(request, - webRequestClient) - - def DoCallFunction(self): - self.mainBrowser.GetMainFrame().CallFunction( - "MyFunction", "abc", 12, [1,2,3], {"qwe": 456, "rty": 789}) - - def VisitAllCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\nCookie manager not yet created! Visit http website first") - return - cookieManager.VisitAllCookies(self.cookieVisitor) - - def VisitUrlCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\nCookie manager not yet created! Visit http website first") - return - cookieManager.VisitUrlCookies( - "http://www.html-kit.com/tools/cookietester/", - False, self.cookieVisitor) - # .www.html-kit.com - - def SetCookie(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\nCookie manager not yet created! Visit http website first") - return - cookie = cefpython.Cookie() - cookie.SetName("Created_Via_Python") - cookie.SetValue("yeah really") - cookieManager.SetCookie("http://www.html-kit.com/tools/cookietester/", - cookie) - print("\nCookie created! Visit html-kit cookietester to see it") - - def DeleteCookies(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\nCookie manager not yet created! Visit http website first") - return - cookieManager.DeleteCookies( - "http://www.html-kit.com/tools/cookietester/", - "Created_Via_Python") - print("\nCookie deleted! Visit html-kit cookietester to see the result") - -class CookieVisitor: - def Visit(self, cookie, count, total, deleteCookie): - if count == 0: - print("\nCookieVisitor.Visit(): total cookies: %s" % total) - print("\nCookieVisitor.Visit(): cookie:") - print(cookie.Get()) - # True to continue visiting cookies - return True - -class WebRequestClient: - def OnStateChange(self, webRequest, state): - stateName = "unknown" - for key, value in cefpython.WebRequest.State.iteritems(): - if value == state: - stateName = key - print("\nWebRequestClient::OnStateChange(): state = %s" % stateName) - - def OnRedirect(self, webRequest, request, response): - print("\nWebRequestClient::OnRedirect(): url = %s" % ( - request.GetUrl()[:80])) - - def OnHeadersReceived(self, webRequest, response): - print("\nWebRequestClient::OnHeadersReceived(): headers = %s" % ( - response.GetHeaderMap())) - - def OnProgress(self, webRequest, bytesSent, totalBytesToBeSent): - print("\nWebRequestClient::OnProgress(): bytesSent = %s, " - "totalBytesToBeSent = %s" % (bytesSent, totalBytesToBeSent)) - - def OnData(self, webRequest, data): - print("\nWebRequestClient::OnData(): data:") - print("-" * 60) - print(data) - print("-" * 60) - - def OnError(self, webRequest, errorCode): - print("\nWebRequestClient::OnError(): errorCode = %s" % errorCode) - -class ContentFilterHandler: - def OnData(self, data, substitute_data): - if data == "body { color: red; }": - substitute_data.SetData("body { color: green; }") - - def OnDrain(self, remainder): - remainder.SetData("body h3 { color: orange; }") - -class ClientHandler: - # -------------------------------------------------------------------------- - # RequestHandler - # -------------------------------------------------------------------------- - contentFilter = None - - def OnBeforeBrowse(self, browser, frame, request, navType, isRedirect): - # - frame.GetUrl() returns current url - # - request.GetUrl() returns new url - # - Return true to cancel the navigation or false to allow - # the navigation to proceed. - # - Modifying headers or post data can be done only in - # OnBeforeResourceLoad() - print("\nOnBeforeBrowse(): request.GetUrl() = %s, " - "request.GetHeaderMap(): %s" % ( - request.GetUrl()[:80], request.GetHeaderMap())) - if request.GetMethod() == "POST": - print("\nOnBeforeBrowse(): POST data: %s" % ( - request.GetPostData())) - - def OnBeforeResourceLoad(self, browser, request, redirectUrl, - streamReader, response, loadFlags): - print("\nOnBeforeResourceLoad(): request.GetUrl() = %s" % ( - request.GetUrl()[:80])) - if request.GetMethod() == "POST": - if request.GetUrl().startswith( - "https://accounts.google.com/ServiceLogin"): - postData = request.GetPostData() - postData["Email"] = "--changed via python" - request.SetPostData(postData) - print("\nOnBeforeResourceLoad(): modified POST data: %s" % ( - request.GetPostData())) - if request.GetUrl().endswith("replace-on-the-fly.css"): - print("\nOnBeforeResourceLoad(): replacing css on the fly") - response.SetStatus(200) - response.SetStatusText("OK") - response.SetMimeType("text/css") - streamReader.SetData("body { color: red; }") - - def OnResourceRedirect(self, browser, oldUrl, newUrl): - print("\nOnResourceRedirect(): oldUrl: %s, newUrl: %s" % ( - oldUrl, newUrl[0])) - - def OnResourceResponse(self, browser, url, response, contentFilter): - print("\nOnResourceResponse(): url = %s, headers = %s" % ( - url[:80], response.GetHeaderMap())) - if url.endswith("content-filter/replace-on-the-fly.css"): - print("\nOnResourceResponse(): setting contentFilter handler") - contentFilter.SetHandler(ContentFilterHandler()) - # Must keep the reference to contentFilter otherwise - # ContentFilterHandler callbacks won't be called. - self.contentFilter = contentFilter - - def GetCookieManager(self, browser, mainUrl): - # Create unique cookie manager for each browser. - cookieManager = browser.GetUserData("cookieManager") - if cookieManager: - return cookieManager - else: - cookieManager = cefpython.CookieManager.CreateManager("") - browser.SetUserData("cookieManager", cookieManager) - return cookieManager - - # -------------------------------------------------------------------------- - # DragHandler - # -------------------------------------------------------------------------- - - def OnDragStart(self, browser, dragData, mask): - maskNames = "" - for key, value in cefpython.Drag.Operation.iteritems(): - if value and (value & mask) == value: - maskNames += " "+key - print("\nOnDragStart(): mask=%s" % maskNames) - print(" IsLink(): %s" % dragData.IsLink()) - print(" IsFragment(): %s" % dragData.IsFragment()) - print(" IsFile(): %s" % dragData.IsFile()) - print(" GetLinkUrl(): %s" % dragData.GetLinkUrl()) - print(" GetLinkTitle(): %s" % dragData.GetLinkTitle()) - print(" GetLinkMetadata(): %s" % dragData.GetLinkMetadata()) - print(" GetFragmentText(): %s" % dragData.GetFragmentText()) - print(" GetFragmentHtml(): %s" % dragData.GetFragmentHtml()) - print(" GetFragmentBaseUrl(): %s" % dragData.GetFragmentBaseUrl()) - print(" GetFile(): %s" % dragData.GetFile()) - print(" GetFiles(): %s" % dragData.GetFiles()) - # Returning True on Linux causes segmentation fault, - # reported the bug here: - # http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=10693 - # Not being able to cancel a drag event is a problem - # only when a link or a folder is dragged, as this will - # cause loading the link or the folder in the browser window. - # When dragging text/html or a file it is not a problem, as - # it does not lead to browser navigating. - if platform.system() == "Windows": - # Return true to cancel the drag event. - return True - else: - return False - - def OnDragEnter(self, browser, dragData, mask): - maskNames = "" - for key, value in cefpython.Drag.Operation.iteritems(): - if value and (value & mask) == value: - maskNames += " "+key - print("\nOnDragEnter(): mask=%s" % maskNames) - print(" IsLink(): %s" % dragData.IsLink()) - print(" IsFragment(): %s" % dragData.IsFragment()) - print(" IsFile(): %s" % dragData.IsFile()) - print(" GetLinkUrl(): %s" % dragData.GetLinkUrl()) - print(" GetLinkTitle(): %s" % dragData.GetLinkTitle()) - print(" GetLinkMetadata(): %s" % dragData.GetLinkMetadata()) - print(" GetFragmentText(): %s" % dragData.GetFragmentText()) - print(" GetFragmentHtml(): %s" % dragData.GetFragmentHtml()) - print(" GetFragmentBaseUrl(): %s" % dragData.GetFragmentBaseUrl()) - print(" GetFile(): %s" % dragData.GetFile()) - print(" GetFiles(): %s" % dragData.GetFiles()) - # Returning True on Linux causes segmentation fault, - # reported the bug here: - # http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=10693 - # Not being able to cancel a drag event is a problem - # only when a link or a folder is dragged, as this will - # cause loading the link or the folder in the browser window. - # When dragging text/html or a file it is not a problem, as - # it does not lead to browser navigating. - if platform.system() == "Windows": - # Return true to cancel the drag event. - return True - else: - return False - - # -------------------------------------------------------------------------- - # DownloadHandler - # -------------------------------------------------------------------------- - - downloadHandler = None - - def GetDownloadHandler(self, browser, mimeType, filename, contentLength): - # Close the browser window if it is a popup with - # no other document contents. - if browser.IsPopup() and not browser.HasDocument(): - browser.CloseBrowser() - # The reference to DownloadHandler must be kept alive - # while download proceeds. - if self.downloadHandler and self.downloadHandler.downloading: - print("\nDownload is already in progress") - return False - self.downloadHandler = DownloadHandler(mimeType, filename, - contentLength) - return self.downloadHandler - -class DownloadHandler: - mimeType = "" - filename = "" - contentLength = -1 # -1 means that file size was not provided. - fp = None - downloadsDir = "./downloads" - alreadyDownloaded = 0 - downloading = False - - def __init__(self, mimeType, filename, contentLength): - self.downloading = True - if not os.path.exists(self.downloadsDir): - os.mkdir(self.downloadsDir) - filename = filename.strip() - if not len(filename): - filename = self.GetUniqueFilename() - filename = self.GetSafeFilename(filename) - print("\nDownloadHandler() created") - print("mimeType: %s" % mimeType) - print("filename: %s" % filename) - print("contentLength: %s" % contentLength) - # Append ".downloading" to the filename, in OnComplete() - # when download finishes get rid of this extension. - filename += ".downloading" - if os.path.exists(self.downloadsDir+"/"+filename): - # If the last download did not succeed, the - # "xxx.downloading" might still be there. - os.remove(self.downloadsDir+"/"+filename) - self.mimeType = mimeType - self.filename = filename - self.contentLength = contentLength - self.fp = open(self.downloadsDir+"/"+filename, "wb") - - def GetSafeFilename(self, filename): - # TODO: - # - remove any unsafe characters (".." or "/" or "\" and - # others), the safest way is to have a regexp with a list - # safe characters. The dots ".." is a special case that - # needs to be treated separately. - if os.path.exists(self.downloadsDir+"/"+filename): - filename = self.GetUniqueFilename()[:4]+"_"+filename - assert not os.path.exists(self.downloadsDir+"/"+filename), ( - "File aready exists") - return filename - - def GetUniqueFilename(self): - # The filename may be empty, in that case generate - # an unique name. - # TODO: - # - guess the extension using the mimeType (but mimeType - # may also be empty), "text/css" => ".css". - return str(uuid.uuid4()).replace("-", "")[:16] - - def OnData(self, data): - # TODO: display progress in percentage or/and KiB/MiB. - if self.alreadyDownloaded == 0: - sys.stdout.write("Download progress: ") - sys.stdout.write(".") - sys.stdout.flush() - self.alreadyDownloaded += len(data) - self.fp.write(data) - # time.sleep(1) # Let's make the progress a bit slower (if cached) - # Return True to continue receiving data, False to cancel. - return True - - def OnComplete(self): - sys.stdout.write("\n") - sys.stdout.flush() - self.fp.close() - currentFile = self.downloadsDir+"/"+self.filename - newFilename = re.sub(".downloading$", "", self.filename) - os.rename(self.downloadsDir+"/"+self.filename, - self.downloadsDir+"/"+newFilename) - self.downloading = False - print("\nDownload complete!") - print("Total downloaded: %s" % self.PrettyBytes( - self.alreadyDownloaded)) - print("See the 'downloads' directory.") - - def PrettyBytes(self, bytes): - KiB = 1024 - return "%.3g KiB" % (bytes / KiB) - -class MyApp(wx.App): - timer = None - timerID = 1 - - def OnInit(self): - if not USE_EVT_IDLE: - self.CreateTimer() - frame = MainFrame() - self.SetTopWindow(frame) - frame.Show() - return True - - def CreateTimer(self): - # See "Making a render loop": - # http://wiki.wxwidgets.org/Making_a_render_loop - # Another approach is to use EVT_IDLE in MainFrame, - # see which one fits you better. - self.timer = wx.Timer(self, self.timerID) - self.timer.Start(10) # 10ms - wx.EVT_TIMER(self, self.timerID, self.OnTimer) - - def OnTimer(self, event): - cefpython.MessageLoopWork() - - def OnExit(self): - # When app.MainLoop() returns, MessageLoopWork() should - # not be called anymore. - if not USE_EVT_IDLE: - self.timer.Stop() - -if __name__ == '__main__': - sys.excepthook = ExceptHook - # cefpython.g_debug = True - # cefpython.g_debugFile = GetApplicationPath("debug.log") - settings = { - "log_severity": cefpython.LOGSEVERITY_INFO, - "log_file": GetApplicationPath("debug.log"), - "release_dcheck_enabled": True # Enable only when debugging. - } - cefpython.Initialize(settings) - print('wx.version=%s' % wx.version()) - app = MyApp(False) - app.MainLoop() - # Let wx.App destructor do the cleanup before calling cefpython.Shutdown(). - del app - cefpython.Shutdown() diff --git a/cefpython/cef1/windows/cefadvanced.bat b/cefpython/cef1/windows/cefadvanced.bat deleted file mode 100644 index 7aa66356b..000000000 --- a/cefpython/cef1/windows/cefadvanced.bat +++ /dev/null @@ -1 +0,0 @@ -start binaries\cefadvanced.py \ No newline at end of file diff --git a/cefpython/cef1/windows/cefpython.pyd.manifest b/cefpython/cef1/windows/cefpython.pyd.manifest deleted file mode 100644 index 725694718..000000000 --- a/cefpython/cef1/windows/cefpython.pyd.manifest +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/cefpython/cef1/windows/compile.bat b/cefpython/cef1/windows/compile.bat deleted file mode 100644 index 9f0733c61..000000000 --- a/cefpython/cef1/windows/compile.bat +++ /dev/null @@ -1,50 +0,0 @@ -for /f %%i in ('python -c "import sys; print(str(sys.version_info[0])+str(sys.version_info[1]));"') do set PYVERSION=%%i - -del "binaries\cefpython_py%PYVERSION%.pyd" -del "setup\cefpython_py%PYVERSION%.pyd" - -for /R %~dp0setup\ %%f in (*.pyx) do @del "%%f" - -rmdir /S /Q "%dp0setup\build\" - -cd "setup" - -call python "fix_includes.py" - -@if %ERRORLEVEL% neq 0 pause -@if %ERRORLEVEL% neq 0 exit - -call python "setup.py" build_ext --inplace - -REM -- the setup above has disabled ECHO for commands, turning it back on. -ECHO ON - -@if %ERRORLEVEL% neq 0 for /R %~dp0setup\ %%f in (*.pyx) do @del "%%f" -@if %ERRORLEVEL% neq 0 pause -@if %ERRORLEVEL% neq 0 exit - -for /R %~dp0setup\ %%f in (*.pyx) do @del "%%f" - -rmdir /S /Q "build\" -@if %ERRORLEVEL% neq 0 pause -@if %ERRORLEVEL% neq 0 exit - -call "C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\mt.exe" -nologo -manifest %~dp0\cefpython.pyd.manifest -outputresource:%~dp0\setup\cefpython_py%PYVERSION%.pyd;2 - -@if %ERRORLEVEL% neq 0 pause -@if %ERRORLEVEL% neq 0 exit - -move "cefpython_py%PYVERSION%.pyd" "../binaries/cefpython_py%PYVERSION%.pyd" -@if %ERRORLEVEL% neq 0 pause -@if %ERRORLEVEL% neq 0 exit - -copy %~dp0..\..\cef1_api.py %~dp0binaries\cefpython_py%PYVERSION%.py -@if %ERRORLEVEL% neq 0 pause -@if %ERRORLEVEL% neq 0 exit - -cd .. -cd binaries - -call python "cefadvanced.py" - -pause \ No newline at end of file diff --git a/cefpython/cef1/windows/installer/__init__.py.template b/cefpython/cef1/windows/installer/__init__.py.template deleted file mode 100644 index 1777ca242..000000000 --- a/cefpython/cef1/windows/installer/__init__.py.template +++ /dev/null @@ -1,11 +0,0 @@ -import sys - -if 0x02070000 <= sys.hexversion < 0x03000000: - from . import cefpython_py27 as cefpython -elif 0x03000000 <= sys.hexversion < 0x04000000: - from . import cefpython_py32 as cefpython -else: - raise Exception("Unsupported python version: " + sys.version) - -__version__ = "%(APP_VERSION)s" -__author__ = "The CEF Python authors" diff --git a/cefpython/cef1/windows/installer/innosetup.template b/cefpython/cef1/windows/installer/innosetup.template deleted file mode 100644 index 1189c01b9..000000000 --- a/cefpython/cef1/windows/installer/innosetup.template +++ /dev/null @@ -1,181 +0,0 @@ -; Parts of this code was taken from wxPython/distrib/make_installer.py - -[Setup] - -AppName = CEF Python 1 for Python %(PYTHON_VERSION)s -AppVersion = %(APP_VERSION)s -AppVerName = CEF Python 1 version %(APP_VERSION)s for Python %(PYTHON_VERSION)s %(PYTHON_ARCHITECTURE)s - -AppPublisher = Czarek Tomczak -AppPublisherURL = http://code.google.com/cefpython/ -AppSupportURL = https://groups.google.com/group/cefpython?hl=en -AppUpdatesURL = http://code.google.com/cefpython/ -AppCopyright = Copyright 2012-2013 Czarek Tomczak - -DefaultDirName = {code:GetInstallDir|c:\Python} - -DefaultGroupName = CEF Python 1 for Python %(PYTHON_VERSION)s -PrivilegesRequired = none -DisableStartupPrompt = yes -Compression = zip -DirExistsWarning = no -DisableReadyMemo = yes -DisableReadyPage = yes -DisableDirPage = no -DisableProgramGroupPage = no -UsePreviousAppDir = yes -UsePreviousGroup = yes - -SourceDir = %(BINARIES_DIR)s -OutputDir = %(INSTALLER_DIR)s\Output -OutputBaseFilename = %(PACKAGE_NAME)s-%(APP_VERSION)s-win32-py%(PYTHON_VERSION_NODOT)s - -UninstallFilesDir = {app}\%(PACKAGE_NAME)s -LicenseFile = %(BINARIES_DIR)s\LICENSE.txt - -[Icons] - -Name: "{group}\Examples"; Filename: "{app}\%(PACKAGE_NAME)s\examples"; -Name: "{group}\Uninstall Package"; Filename: "{uninstallexe}"; - -[Run] - -Filename: "{app}\%(PACKAGE_NAME)s\examples"; Flags: postinstall shellexec; - -[Files] - -Source: "*.dll"; DestDir: "{app}\%(PACKAGE_NAME)s"; Flags: ignoreversion; -Source: "*.pak"; DestDir: "{app}\%(PACKAGE_NAME)s"; Flags: ignoreversion; -Source: "locales\*.pak"; DestDir: "{app}\%(PACKAGE_NAME)s\locales"; Flags: ignoreversion; - -Source: "%(INSTALLER_DIR)s\__init__.py.generated"; DestDir: "{app}\%(PACKAGE_NAME)s"; DestName: "__init__.py"; Flags: ignoreversion; - -Source: "cefclient.exe"; DestDir: "{app}\%(PACKAGE_NAME)s"; Flags: ignoreversion; - -Source: "cefpython_py%(PYTHON_VERSION_NODOT)s.pyd"; DestDir: "{app}\%(PACKAGE_NAME)s"; Flags: ignoreversion; -Source: "cefpython_py%(PYTHON_VERSION_NODOT)s.py"; DestDir: "{app}\%(PACKAGE_NAME)s"; Flags: ignoreversion; - -Source: "LICENSE.txt"; DestDir: "{app}\%(PACKAGE_NAME)s"; Flags: ignoreversion; - -Source: "Microsoft.VC90.CRT.manifest"; DestDir: "{app}\%(PACKAGE_NAME)s"; Flags: ignoreversion; - -Source: "README.txt"; DestDir: "{app}\%(PACKAGE_NAME)s"; Flags: ignoreversion; - -; ------------------------------------------------------------------------------ -; wx subpackage -; ------------------------------------------------------------------------------ - -Source: "%(WX_SUBPACKAGE_DIR)s\*.py"; DestDir: "{app}\%(PACKAGE_NAME)s\wx"; Flags: ignoreversion; -Source: "%(WX_SUBPACKAGE_DIR)s\*.txt"; DestDir: "{app}\%(PACKAGE_NAME)s\wx"; Flags: ignoreversion; -Source: "%(WX_SUBPACKAGE_DIR)s\images\*.png"; DestDir: "{app}\%(PACKAGE_NAME)s\wx\images"; Flags: ignoreversion; - -; ------------------------------------------------------------------------------ -; wx examples -; ------------------------------------------------------------------------------ - -Source: "%(WX_SUBPACKAGE_DIR)s\examples\*.py"; DestDir: "{app}\%(PACKAGE_NAME)s\examples\wx"; Flags: ignoreversion; -Source: "%(WX_SUBPACKAGE_DIR)s\examples\*.html"; DestDir: "{app}\%(PACKAGE_NAME)s\examples\wx"; Flags: ignoreversion; -Source: "%(WX_SUBPACKAGE_DIR)s\examples\*.png"; DestDir: "{app}\%(PACKAGE_NAME)s\examples\wx"; Flags: ignoreversion; - -; ------------------------------------------------------------------------------ -; examples -; ------------------------------------------------------------------------------ - -Source: "*.html"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; - -Source: "cefadvanced.py"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; -Source: "cefsimple.py"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; -Source: "cefwindow.py"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; - -Source: "cefwxpanel.py"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; -Source: "cefwxpanel_sample1.py"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; -Source: "cefwxpanel_sample2.py"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; - -Source: "icon.ico"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; - -Source: "panda3d_.py"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; -Source: "pygtk_.py"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; -Source: "pyqt.py"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; -Source: "pyside.py"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; -Source: "wxpython.py"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; - -[UninstallDelete] - -Type: files; Name: "{app}\%(PACKAGE_NAME)s\*.pyc"; -Type: files; Name: "{app}\%(PACKAGE_NAME)s\examples\*.pyc"; -Type: files; Name: "{app}\%(PACKAGE_NAME)s\examples\*.log"; -Type: files; Name: "{app}\%(PACKAGE_NAME)s\examples\wx\*.pyc"; -Type: files; Name: "{app}\%(PACKAGE_NAME)s\examples\wx\*.log"; -Type: files; Name: "{app}\%(PACKAGE_NAME)s\wx\*.pyc"; -Type: files; Name: "{app}\%(PACKAGE_NAME)s\wx\*.log"; - -[Code] - -program Setup; -var - PythonDir : String; - InstallDir : String; - -function InitializeSetup(): Boolean; -begin - - if not RegQueryStringValue(HKEY_CURRENT_USER, - 'Software\Python\PythonCore\%(PYTHON_VERSION)s\InstallPath', - '', PythonDir) then begin - - if not RegQueryStringValue(HKEY_LOCAL_MACHINE, - 'Software\Python\PythonCore\%(PYTHON_VERSION)s\InstallPath', - '', PythonDir) then begin - - if not RegQueryStringValue(HKEY_CURRENT_USER, - 'Software\Wow6432Node\Python\PythonCore\%(PYTHON_VERSION)s\InstallPath', - '', PythonDir) then begin - - if not RegQueryStringValue(HKEY_LOCAL_MACHINE, - 'Software\Wow6432Node\Python\PythonCore\%(PYTHON_VERSION)s\InstallPath', - '', PythonDir) then begin - - MsgBox('No installation of Python %(PYTHON_VERSION)s ' - + 'found in registry.' + #13 + 'Be sure to enter ' - + 'a pathname that places CEF Python 1 on the ' - + 'PYTHONPATH', - mbConfirmation, MB_OK); - PythonDir := 'C:\Python'; - end; - end; - end; - end; - - InstallDir := PythonDir + '\Lib\site-packages'; - Result := True; -end; - -function GetInstallDir(Default: String): String; -begin - Result := InstallDir; -end; - -function UninstallOld(FileName: String): Boolean; -var - ResultCode: Integer; -begin - Result := False; - if FileExists(FileName) then begin - Result := True; - ResultCode := MsgBox('A prior CEF Python 1 installation was found in ' - + 'this directory. It' + #13 + 'is recommended that it be ' - + 'uninstalled first.' + #13#13 + 'Should I do it?', - mbConfirmation, MB_YESNO); - if ResultCode = IDYES then begin - Exec(FileName, '/SILENT', WizardDirValue(), SW_SHOWNORMAL, - ewWaitUntilTerminated, ResultCode); - end; - end; -end; - -function NextButtonClick(CurPage: Integer): Boolean; -begin - Result := True; - if CurPage <> wpSelectDir then Exit; - UninstallOld(WizardDirValue() + '\%(PACKAGE_NAME)s\unins000.exe') -end; diff --git a/cefpython/cef1/windows/installer/make-installer.py b/cefpython/cef1/windows/installer/make-installer.py deleted file mode 100644 index 6ad2dc467..000000000 --- a/cefpython/cef1/windows/installer/make-installer.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -# Create a Windows package installer. - -import sys -import os -import platform -import argparse -import re - -ISCC = r"c:\Program Files (x86)\Inno Setup 5\ISCC.exe" -if "INNO5" in os.environ: - ISCC = os.environ["INNO5"] - -TEMPLATE_FILE = os.getcwd()+r"\innosetup.template" -ISS_FILE = os.getcwd()+r"\innosetup.generated" - -def main(): - parser = argparse.ArgumentParser(usage="%(prog)s [options]") - parser.add_argument("-v", "--version", help="cefpython version", - required=True) - args = parser.parse_args() - assert re.search(r"^\d+\.\d+$", args.version), ( - "Invalid version string") - - vars = {} - vars["PACKAGE_NAME"] = "cefpython1" - vars["APP_VERSION"] = args.version - vars["PYTHON_VERSION"] = (str(sys.version_info.major) + "." - + str(sys.version_info.minor)) - vars["PYTHON_VERSION_NODOT"] = (str(sys.version_info.major) + "" - + str(sys.version_info.minor)) - vars["PYTHON_ARCHITECTURE"] = platform.architecture()[0] - vars["BINARIES_DIR"] = os.path.realpath(os.getcwd()+r"\..\binaries") - vars["PYD_FILE"] = (vars["BINARIES_DIR"]+r"\cefpython_py" - + str(sys.version_info.major) + str(sys.version_info.minor) - + ".pyd") - vars["INSTALLER_DIR"] = os.getcwd() - vars["WX_SUBPACKAGE_DIR"] = os.path.realpath(os.getcwd()+r"\..\.." - "\wx-subpackage") - - print("Reading template: %s" % TEMPLATE_FILE) - - f = open(TEMPLATE_FILE) - template = f.read() - f.close() - - f = open(ISS_FILE, "w") - f.write(template % vars) - f.close() - - print("Saved: %s" % ISS_FILE) - - initPyTemplate = os.getcwd()+r"\__init__.py.template" - initPyInstall = os.getcwd()+r"\__init__.py.generated" - - f = open(initPyTemplate) - initPyTemplateCode = f.read() - f.close() - - f = open(initPyInstall, "w") - f.write(initPyTemplateCode % vars) - f.close() - print("Saved: %s" % initPyInstall) - - iscc_command = '"'+ ISCC + '" ' + ISS_FILE - print("Running ISCC: %s" % iscc_command) - os.system(iscc_command) - -if __name__ == "__main__": - main() diff --git a/cefpython/cef1/windows/setup/.gitignore b/cefpython/cef1/windows/setup/.gitignore deleted file mode 100644 index d4b2c081e..000000000 --- a/cefpython/cef1/windows/setup/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.cpp -*.pyx - diff --git a/cefpython/cef1/windows/setup/cefpython.h b/cefpython/cef1/windows/setup/cefpython.h deleted file mode 100644 index 2c9c8c9fc..000000000 --- a/cefpython/cef1/windows/setup/cefpython.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef __PYX_HAVE__cefpython_py27 -#define __PYX_HAVE__cefpython_py27 - - -#ifndef __PYX_HAVE_API__cefpython_py27 - -#ifndef __PYX_EXTERN_C - #ifdef __cplusplus - #define __PYX_EXTERN_C extern "C" - #else - #define __PYX_EXTERN_C extern - #endif -#endif - -__PYX_EXTERN_C DL_IMPORT(bool) CookieVisitor_Visit(int, CefCookie const &, int, int, bool &); -__PYX_EXTERN_C DL_IMPORT(void) LoadHandler_OnLoadEnd(CefRefPtr, CefRefPtr, int); -__PYX_EXTERN_C DL_IMPORT(void) LoadHandler_OnLoadStart(CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) LoadHandler_OnLoadError(CefRefPtr, CefRefPtr, enum cef_handler_errorcode_t, CefString &, CefString &); -__PYX_EXTERN_C DL_IMPORT(bool) KeyboardHandler_OnKeyEvent(CefRefPtr, enum cef_handler_keyevent_type_t, int, int, bool, bool); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnStateChange(int, CefRefPtr, enum cef_weburlrequest_state_t); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnRedirect(int, CefRefPtr, CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnHeadersReceived(int, CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnProgress(int, CefRefPtr, uint64_t, uint64_t); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnData(int, CefRefPtr, void *, int); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnError(int, CefRefPtr, int); -__PYX_EXTERN_C DL_IMPORT(void) ContentFilterHandler_ProcessData(int, void const *, int, CefRefPtr &); -__PYX_EXTERN_C DL_IMPORT(void) ContentFilterHandler_Drain(int, CefRefPtr &); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnBeforeBrowse(CefRefPtr, CefRefPtr, CefRefPtr, enum cef_handler_navtype_t, bool); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnBeforeResourceLoad(CefRefPtr, CefRefPtr, CefString &, CefRefPtr &, CefRefPtr, int); -__PYX_EXTERN_C DL_IMPORT(void) RequestHandler_OnResourceRedirect(CefRefPtr, CefString &, CefString &); -__PYX_EXTERN_C DL_IMPORT(void) RequestHandler_OnResourceResponse(CefRefPtr, CefString &, CefRefPtr, CefRefPtr &); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnProtocolExecution(CefRefPtr, CefString &, bool &); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_GetDownloadHandler(CefRefPtr, CefString const &, CefString const &, int64, CefRefPtr &); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_GetAuthCredentials(CefRefPtr, bool, CefString &, int, CefString &, CefString &, CefString &, CefString &); -__PYX_EXTERN_C DL_IMPORT(CefRefPtr) RequestHandler_GetCookieManager(CefRefPtr, CefString &); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnAddressChange(CefRefPtr, CefRefPtr, CefString &); -__PYX_EXTERN_C DL_IMPORT(bool) DisplayHandler_OnConsoleMessage(CefRefPtr, CefString &, CefString &, int); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnContentsSizeChange(CefRefPtr, CefRefPtr, int, int); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnNavStateChange(CefRefPtr, bool, bool); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnStatusMessage(CefRefPtr, CefString &, enum cef_handler_statustype_t); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnTitleChange(CefRefPtr, CefString &); -__PYX_EXTERN_C DL_IMPORT(bool) DisplayHandler_OnTooltip(CefRefPtr, CefString &); -__PYX_EXTERN_C DL_IMPORT(bool) LifespanHandler_DoClose(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) LifespanHandler_OnAfterCreated(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) LifespanHandler_OnBeforeClose(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) LifespanHandler_RunModal(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetViewRect(CefRefPtr, CefRect &); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetScreenRect(CefRefPtr, CefRect &); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetScreenPoint(CefRefPtr, int, int, int &, int &); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnPopupShow(CefRefPtr, bool); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnPopupSize(CefRefPtr, CefRect &); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnPaint(CefRefPtr, cef_paint_element_type_t, std::vector &, void *); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnCursorChange(CefRefPtr, CefCursorHandle); -__PYX_EXTERN_C DL_IMPORT(bool) DragHandler_OnDragStart(CefRefPtr, CefRefPtr, enum cef_drag_operations_mask_t); -__PYX_EXTERN_C DL_IMPORT(bool) DragHandler_OnDragEnter(CefRefPtr, CefRefPtr, enum cef_drag_operations_mask_t); -__PYX_EXTERN_C DL_IMPORT(bool) DownloadHandler_ReceivedData(int, void *, int); -__PYX_EXTERN_C DL_IMPORT(void) DownloadHandler_Complete(int); -__PYX_EXTERN_C DL_IMPORT(void) V8ContextHandler_OnContextCreated(CefRefPtr, CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) V8ContextHandler_OnContextReleased(CefRefPtr, CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) V8ContextHandler_OnUncaughtException(CefRefPtr, CefRefPtr, CefRefPtr, CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) V8FunctionHandler_Execute(CefRefPtr, int, CefString &, CefRefPtr, CefV8ValueList &, CefRefPtr &, CefString &); - -#endif /* !__PYX_HAVE_API__cefpython_py27 */ - -#if PY_MAJOR_VERSION < 3 -PyMODINIT_FUNC initcefpython_py27(void); -#else -PyMODINIT_FUNC PyInit_cefpython_py27(void); -#endif - -#endif /* !__PYX_HAVE__cefpython_py27 */ diff --git a/cefpython/cef1/windows/setup/delete_pyx_files.bat b/cefpython/cef1/windows/setup/delete_pyx_files.bat deleted file mode 100644 index ae1c5fbd1..000000000 --- a/cefpython/cef1/windows/setup/delete_pyx_files.bat +++ /dev/null @@ -1,2 +0,0 @@ -for /R %~dp0 %%f in (*.pyx) do del "%%f" -pause \ No newline at end of file diff --git a/cefpython/cef1/windows/setup/fix_includes.py b/cefpython/cef1/windows/setup/fix_includes.py deleted file mode 100644 index e25922ba5..000000000 --- a/cefpython/cef1/windows/setup/fix_includes.py +++ /dev/null @@ -1,109 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -# First, it copies all .pyx files from upper directory to setup/. -# Then, fixes repeating of "include" statements in pyx files. - -# Only the mainfile needs to have "include" statements, -# but we're using PyCharm and to get rid of "unresolved references" -# and other errors displayed in pycharm we are adding "include" -# statements in all of the pyx files. - -# I'm not 100% sure how includes work in Cython, but I suspect that -# a few includes of the same file will include the same content more -# than once, it should work, but function and variable definitions are -# duplicated, it is some kind of overhead and it could lead to some -# problems in the future, better to fix it now. - -# It also checks cdef & cpdef functions whether they are not missing "except *", -# it is required to add it when returning non-python type. - -import glob -import os -import re -import shutil -import sys - -def ExceptAllMissing(content): - - # This is not perfect, won't detect C++ custom types, but will find - # the built-in types, templates and pointers. - patterns = [] - patterns.append( - r"\bcp?def\s+" - "((int|short|long|double|char|unsigned|float|double|cpp_bool" - "|cpp_string|cpp_wstring|uint64_t|uintptr_t|void" - "|CefString)\s+)+" - "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") - patterns.append( - r"\bcp?def\s+" - # A template ends with bracket: CefRefPtr[CefBrowser] - # or a pointer ends with asterisk: CefBrowser* - "[^\s]+[\]*]\s+" - "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") - patterns.append( - r"\bcp?def\s+" - # A reference, eg. CefString& - "[^\s]+&\s+" - "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") - - for pattern in patterns: - match = re.search(pattern, content) - if match: break - - if match: - lineNumber = (content.count("\n", 0, match.start()) + 1) - return lineNumber - -print("\n") -mainfile = "cefpython.pyx" - -pyxfiles = glob.glob("../../../*.pyx") -if not len(pyxfiles): - sys.exit(1) -pyxfiles = [file for file in pyxfiles if file.find(mainfile) == -1] -# Now, pyxfiles contains all pyx files except the mainfile (cefpython.pyx), -# we do not fix includes in mainfile. - -# So that this is the right directory we're in. -if os.path.exists("setup"): - print("Wrong directory, we should be inside setup!") - sys.exit(1) - -# Remove old pyx files in setup directory. -oldpyxfiles = glob.glob("./*.pyx") -print("Removing old pyx files in /setup/: %s" % oldpyxfiles) -for pyxfile in oldpyxfiles: - if os.path.exists(pyxfile): - os.remove(pyxfile) - -# Copying pyxfiles and reading its contents. - -print("Copying .pyx files to /setup/: %s" % pyxfiles) -shutil.copy("../../../%s" % mainfile, "./%s" % mainfile) -# Rest of the files will be copied in for loop below. - -print("Fixing includes in .pyx files:") -for pyxfile in pyxfiles: - newfile = "./%s" % os.path.basename(pyxfile) - shutil.copy(pyxfile, newfile) - pyxfile = newfile - with open(pyxfile, "r") as pyxfileopened: - content = pyxfileopened.read() - lineNumber = ExceptAllMissing(content) - if lineNumber: - print("WARNING: 'except *' missing in a cdef/cpdef function, " - "in file %s on line %d" % (os.path.basename(pyxfile), lineNumber)) - sys.exit(1) - # Do not remove the newline - so that line numbers are exact with originals. - (content, subs) = re.subn(r"^include[\t ]+[\"'][^\"'\n\r]+[\"'][\t ]*", "", content, flags=re.MULTILINE) - if subs: - print("%s includes removed in: %s" % (subs, os.path.basename(pyxfile))) - # Reading and writing with the same handle using "r+" mode doesn't work, - # you need to seek(0) and write the same amount of bytes that was in the - # file, otherwise old data from the end of file stays. - with open(pyxfile, "w") as pyxfileopened: - pyxfileopened.write(content) - -print("\n") diff --git a/cefpython/cef1/windows/setup/setup.py b/cefpython/cef1/windows/setup/setup.py deleted file mode 100644 index c32d1f468..000000000 --- a/cefpython/cef1/windows/setup/setup.py +++ /dev/null @@ -1,108 +0,0 @@ -from distutils.core import setup -# Use "Extension" from Cython.Distutils so that "cython_directives" works. -# from distutils.extension import Extension -from Cython.Distutils import build_ext, Extension -import sys -import platform -from Cython.Compiler import Options - -# Stop on first error, otherwise hundreds of errors appear in the console. -Options.fast_fail = True - -# Written to cython_includes/compile_time_constants.pxi -CEF_VERSION = 1 - -""" -Building libcef_dll_wrapper ---------------------------- - -libcef_dll_wrapper needs to be compiled with /MD, otherwise you get linker errors -of type "already defined". When you try to compile using /MD you may get warnings: - - warning C4275: non dll-interface class 'stdext::exception' used as base for - dll-interface class 'std::bad_typeid' see declaration of 'stdext::exception' - see declaration of 'std::bad_typeid' - -Which results in build errors. To solve it you need to add command line option: - - -D_HAS_EXCEPTIONS=1 - -Enabling C++ exceptions ("/EHsc") is not required. -""" - -# Python version string: "27" or "32". -PYTHON_VERSION = str(sys.version_info.major) + str(sys.version_info.minor) - -def CompileTimeConstants(): - - print("Generating: cython_includes/compile_time_constants.pxi") - with open("./../../../cython_includes/compile_time_constants.pxi", "w") as fd: - fd.write('# This file was generated by setup.py\n') - # A way around Python 3.2 bug: UNAME_SYSNAME is not set. - fd.write('DEF UNAME_SYSNAME = "%s"\n' % platform.uname()[0]) - fd.write('DEF CEF_VERSION = %s\n' % CEF_VERSION) - fd.write('DEF PY_MAJOR_VERSION = %s\n' % sys.version_info.major) - -CompileTimeConstants() - -ext_modules = [Extension( - - "cefpython_py%s" % PYTHON_VERSION, - ["cefpython.pyx"], - - # Ignore the warning in the console: - # > C:\Python27\lib\distutils\extension.py:133: UserWarning: - # > Unknown Extension options: 'cython_directives' warnings.warn(msg) - cython_directives={ - # Any conversion to unicode must be explicit using .decode(). - "c_string_type": "bytes", - "c_string_encoding": "utf8", - }, - - language='c++', - - include_dirs=[ - r'./../', - r'./../../', - r'./../../../', - r'./../../../cython_includes/', - ], - - library_dirs=[ - r'./', - r"c:/Program Files (x86)/Windows Kits/8.0/Lib/win8/um/x86/", - r'./../../http_authentication/Release/', - r'./../../v8function_handler/Release_py%s/' % PYTHON_VERSION, - r'./../../client_handler/Release_py%s/' % PYTHON_VERSION, - r'./../../../cpp_utils/Release/cpp_utils.lib', - ], - - libraries=[ - 'libcef', - 'libcef_dll_wrapper', - 'User32', - 'Gdi32', - 'http_authentication', # Build with /MD. - 'v8function_handler_py%s' % PYTHON_VERSION, # Build with /MD. - 'client_handler_py%s' % PYTHON_VERSION # Build with /MD. - ], - - # /EHsc - using STL string, multimap and others that use C++ exceptions. - extra_compile_args=['/EHsc'], - - # '/ignore:4217' - silence warnings: "locally defined symbol _V8FunctionHandler_Execute - # imported in function "public: virtual bool __thiscall V8FunctionHandler::Execute". - # client_handler or other vcprojects include setup/cefpython.h, - # this is a list of functions with "public" statement that is - # accessible from c++. - extra_link_args=['/ignore:4217'], - - # Defining macros: - # define_macros = [("UNICODE","1"), ("_UNICODE","1"), ] -)] - -setup( - name = 'cefpython_py%s' % PYTHON_VERSION, - cmdclass = {'build_ext': build_ext}, - ext_modules = ext_modules -) diff --git a/cefpython/cef1/windows/stdint.h b/cefpython/cef1/windows/stdint.h deleted file mode 100644 index d02608a59..000000000 --- a/cefpython/cef1/windows/stdint.h +++ /dev/null @@ -1,247 +0,0 @@ -// ISO C9x compliant stdint.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006-2008 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. The name of the author may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_STDINT_H_ // [ -#define _MSC_STDINT_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include - -// For Visual Studio 6 in C++ mode and for many Visual Studio versions when -// compiling for ARM we should wrap include with 'extern "C++" {}' -// or compiler give many errors like this: -// error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#ifdef __cplusplus -extern "C" { -#endif -# include -#ifdef __cplusplus -} -#endif - -// Define _W64 macros to mark types changing their size, like intptr_t. -#ifndef _W64 -# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 -# define _W64 __w64 -# else -# define _W64 -# endif -#endif - - -// 7.18.1 Integer types - -// 7.18.1.1 Exact-width integer types - -// Visual Studio 6 and Embedded Visual C++ 4 doesn't -// realize that, e.g. char has the same size as __int8 -// so we give up on __intX for them. -#if (_MSC_VER < 1300) - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; -#else - typedef signed __int8 int8_t; - typedef signed __int16 int16_t; - typedef signed __int32 int32_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; -#endif -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; - - -// 7.18.1.2 Minimum-width integer types -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -// 7.18.1.3 Fastest minimum-width integer types -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; - -// 7.18.1.4 Integer types capable of holding object pointers -#ifdef _WIN64 // [ - typedef signed __int64 intptr_t; - typedef unsigned __int64 uintptr_t; -#else // _WIN64 ][ - typedef _W64 signed int intptr_t; - typedef _W64 unsigned int uintptr_t; -#endif // _WIN64 ] - -// 7.18.1.5 Greatest-width integer types -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - - -// 7.18.2 Limits of specified-width integer types - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 - -// 7.18.2.1 Limits of exact-width integer types -#define INT8_MIN ((int8_t)_I8_MIN) -#define INT8_MAX _I8_MAX -#define INT16_MIN ((int16_t)_I16_MIN) -#define INT16_MAX _I16_MAX -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX _I64_MAX -#define UINT8_MAX _UI8_MAX -#define UINT16_MAX _UI16_MAX -#define UINT32_MAX _UI32_MAX -#define UINT64_MAX _UI64_MAX - -// 7.18.2.2 Limits of minimum-width integer types -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -// 7.18.2.3 Limits of fastest minimum-width integer types -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -// 7.18.2.4 Limits of integer types capable of holding object pointers -#ifdef _WIN64 // [ -# define INTPTR_MIN INT64_MIN -# define INTPTR_MAX INT64_MAX -# define UINTPTR_MAX UINT64_MAX -#else // _WIN64 ][ -# define INTPTR_MIN INT32_MIN -# define INTPTR_MAX INT32_MAX -# define UINTPTR_MAX UINT32_MAX -#endif // _WIN64 ] - -// 7.18.2.5 Limits of greatest-width integer types -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -// 7.18.3 Limits of other integer types - -#ifdef _WIN64 // [ -# define PTRDIFF_MIN _I64_MIN -# define PTRDIFF_MAX _I64_MAX -#else // _WIN64 ][ -# define PTRDIFF_MIN _I32_MIN -# define PTRDIFF_MAX _I32_MAX -#endif // _WIN64 ] - -#define SIG_ATOMIC_MIN INT_MIN -#define SIG_ATOMIC_MAX INT_MAX - -#ifndef SIZE_MAX // [ -# ifdef _WIN64 // [ -# define SIZE_MAX _UI64_MAX -# else // _WIN64 ][ -# define SIZE_MAX _UI32_MAX -# endif // _WIN64 ] -#endif // SIZE_MAX ] - -// WCHAR_MIN and WCHAR_MAX are also defined in -#ifndef WCHAR_MIN // [ -# define WCHAR_MIN 0 -#endif // WCHAR_MIN ] -#ifndef WCHAR_MAX // [ -# define WCHAR_MAX _UI16_MAX -#endif // WCHAR_MAX ] - -#define WINT_MIN 0 -#define WINT_MAX _UI16_MAX - -#endif // __STDC_LIMIT_MACROS ] - - -// 7.18.4 Limits of other integer types - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 - -// 7.18.4.1 Macros for minimum-width integer constants - -#define INT8_C(val) val##i8 -#define INT16_C(val) val##i16 -#define INT32_C(val) val##i32 -#define INT64_C(val) val##i64 - -#define UINT8_C(val) val##ui8 -#define UINT16_C(val) val##ui16 -#define UINT32_C(val) val##ui32 -#define UINT64_C(val) val##ui64 - -// 7.18.4.2 Macros for greatest-width integer constants -#define INTMAX_C INT64_C -#define UINTMAX_C UINT64_C - -#endif // __STDC_CONSTANT_MACROS ] - - -#endif // _MSC_STDINT_H_ ] diff --git a/cefpython/cef1/wx-subpackage/README.txt b/cefpython/cef1/wx-subpackage/README.txt deleted file mode 100644 index a58c7f449..000000000 --- a/cefpython/cef1/wx-subpackage/README.txt +++ /dev/null @@ -1,6 +0,0 @@ -This is a wxPython subpackage for the cefpython1 package -that provides an easy to use API for the wxPython GUI library. - -Author: Greg Kacy -License: BSD 3-clause - diff --git a/cefpython/cef1/wx-subpackage/__init__.py b/cefpython/cef1/wx-subpackage/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/cefpython/cef1/wx-subpackage/chromectrl.py b/cefpython/cef1/wx-subpackage/chromectrl.py deleted file mode 100644 index ada24b32c..000000000 --- a/cefpython/cef1/wx-subpackage/chromectrl.py +++ /dev/null @@ -1,314 +0,0 @@ -# Additional and wx specific layer of abstraction for the cefpython -# __author__ = "Greg Kacy " - -#-------------------------------------------------------------------------------- - -from cefpython1 import cefpython -from cefpython1.wx.utils import ExceptHook -import os, sys, platform -import wx -import wx.lib.buttons as buttons - -#------------------------------------------------------------------------------- - -# Default timer interval when timer used to service CEF message loop -DEFAULT_TIMER_MILLIS = 10 - -#------------------------------------------------------------------------------- - -class NavigationBar(wx.Panel): - def __init__(self, parent, *args, **kwargs): - wx.Panel.__init__(self, parent, *args, **kwargs) - - self.bitmapDir = os.path.join(os.path.dirname( - os.path.abspath(__file__)), "images") - - self._InitComponents() - self._LayoutComponents() - self._InitEventHandlers() - - def _InitComponents(self): - self.backBtn = buttons.GenBitmapButton(self, -1, - wx.Bitmap(os.path.join(self.bitmapDir, "Arrow Left.png"), - wx.BITMAP_TYPE_PNG), style=wx.BORDER_NONE) - self.forwardBtn = buttons.GenBitmapButton(self, -1, - wx.Bitmap(os.path.join(self.bitmapDir, "Arrow Right.png"), - wx.BITMAP_TYPE_PNG), style=wx.BORDER_NONE) - self.reloadBtn = buttons.GenBitmapButton(self, -1, - wx.Bitmap(os.path.join(self.bitmapDir, "Button Load.png"), - wx.BITMAP_TYPE_PNG), style=wx.BORDER_NONE) - - self.url = wx.TextCtrl(self, id=-1, style=0) - - self.historyPopup = wx.Menu() - - def _LayoutComponents(self): - sizer = wx.BoxSizer(wx.HORIZONTAL) - sizer.Add(self.backBtn, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL| - wx.ALL, 0) - sizer.Add(self.forwardBtn, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL| - wx.ALL, 0) - sizer.Add(self.reloadBtn, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL| - wx.ALL, 0) - - sizer.Add(self.url, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 12) - - self.SetSizer(sizer) - self.Fit() - - def _InitEventHandlers(self): - self.backBtn.Bind(wx.EVT_CONTEXT_MENU, self.OnButtonContext) - - def __del__(self): - self.historyPopup.Destroy() - - def GetBackButton(self): - return self.backBtn - - def GetForwardButton(self): - return self.forwardBtn - - def GetReloadButton(self): - return self.reloadBtn - - def GetUrlCtrl(self): - return self.url - - def InitHistoryPopup(self): - self.historyPopup = wx.Menu() - - def AddToHistory(self, url): - self.historyPopup.Append(-1, url) - - def OnButtonContext(self, event): - self.PopupMenu(self.historyPopup) - - -class ChromeWindow(wx.Window): - """ - Standalone CEF component. The class provides facilites for interacting - with wx message loop - """ - def __init__(self, parent, url="", useTimer=False, - timerMillis=DEFAULT_TIMER_MILLIS, size=(-1, -1), - *args, **kwargs): - wx.Window.__init__(self, parent, id=wx.ID_ANY, size=size, - *args, **kwargs) - # On Linux absolute file urls need to start with "file://" - # otherwise a path of "/home/some" is converted to "http://home/some". - if platform.system() == "Linux": - if url.startswith("/"): - url = "file://" + url - self.url = url - - windowInfo = cefpython.WindowInfo() - if platform.system() == "Windows": - windowInfo.SetAsChild(self.GetHandle()) - elif platform.system() == "Linux": - windowInfo.SetAsChild(self.GetGtkWidget()) - else: - raise Exception("Unsupported OS") - - # TODO: allow for custom browser settings for the ChromeWindow - browserSettings = {} - if platform.system() == "Linux": - # Disable plugins on Linux as Flash will crash the application - # in CEF 1 on Linux, it's a known problem. - if not "plugins_disabled" in browserSettings: - browserSettings["plugins_disabled"] = True - - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings=browserSettings, navigateUrl=url) - - if platform.system() == "Windows": - self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) - self.Bind(wx.EVT_SIZE, self.OnSize) - if useTimer: - self.timerID = 1 - self._CreateTimer(timerMillis) - else: - self.Bind(wx.EVT_IDLE, self.OnIdle) - self._useTimer = useTimer - - def __del__(self): - '''cleanup stuff''' - if self._useTimer: - self.timer.Stop() - # Calling Unbind() is unnecessary and will cause problems on Windows 8, see: - # https://groups.google.com/d/topic/cefpython/iXE7e1ekArI/discussion - # | self.Unbind(wx.EVT_IDLE) - self.browser.CloseBrowser() - - def _CreateTimer(self, millis): - self.timer = wx.Timer(self, self.timerID) - self.timer.Start(millis) # - wx.EVT_TIMER(self, self.timerID, self.OnTimer) - - def OnTimer(self, event): - """Service CEF message loop when useTimer is True""" - cefpython.MessageLoopWork() - - def OnIdle(self, event): - """Service CEF message loop when useTimer is False""" - cefpython.MessageLoopWork() - event.Skip() - - def OnSetFocus(self, event): - """OS_WIN only.""" - cefpython.WindowUtils.OnSetFocus(self.GetHandle(), 0, 0, 0) - event.Skip() - - def OnSize(self, event): - """OS_WIN only. Handle the the size event""" - cefpython.WindowUtils.OnSize(self.GetHandle(), 0, 0, 0) - event.Skip() - - def GetBrowser(self): - """Returns the CEF's browser object""" - return self.browser - - def LoadUrl(self, url, onLoadStart=None, onLoadEnd=None): - if onLoadStart or onLoadEnd: - self.GetBrowser().SetClientHandler( - CallbackClientHandler(onLoadStart, onLoadEnd)) - self.GetBrowser().GetMainFrame().LoadUrl(url) - - -class ChromeCtrl(wx.Panel): - def __init__(self, parent, url="", useTimer=False, - timerMillis=DEFAULT_TIMER_MILLIS, hasNavBar=True, - *args, **kwargs): - wx.Panel.__init__(self, parent, *args, **kwargs) - - self.chromeWindow = ChromeWindow(self, url=str(url), useTimer=useTimer) - sizer = wx.BoxSizer(wx.VERTICAL) - self.navigationBar = None - if hasNavBar: - self.navigationBar = self.CreateNavigationBar() - sizer.Add(self.navigationBar, 0, wx.EXPAND|wx.ALL, 0) - self._InitEventHandlers() - - sizer.Add(self.chromeWindow, 1, wx.EXPAND, 0) - - self.SetSizer(sizer) - self.Fit() - - ch = DefaultClientHandler(self) - self.SetClientHandler(ch) - if self.navigationBar: - self.UpdateButtonsState() - - def _InitEventHandlers(self): - self.navigationBar.backBtn.Bind(wx.EVT_BUTTON, self.OnLeft) - self.navigationBar.forwardBtn.Bind(wx.EVT_BUTTON, self.OnRight) - self.navigationBar.reloadBtn.Bind(wx.EVT_BUTTON, self.OnReload) - - def GetNavigationBar(self): - return self.navigationBar - - def SetNavigationBar(self, navigationBar): - sizer = self.GetSizer() - if self.navigationBar: - # remove previous one - sizer.Replace(self.navigationBar, navigationBar) - self.navigationBar.Hide() - del self.navigationBar - else: - sizer.Insert(0, navigationBar, 0, wx.EXPAND) - self.navigationBar = navigationBar - sizer.Fit(self) - - def CreateNavigationBar(self): - np = NavigationBar(self) - return np - - def SetClientHandler(self, handler): - self.chromeWindow.GetBrowser().SetClientHandler(handler) - - def OnLeft(self, event): - if self.chromeWindow.GetBrowser().CanGoBack(): - self.chromeWindow.GetBrowser().GoBack() - self.UpdateButtonsState() - - def OnRight(self, event): - if self.chromeWindow.GetBrowser().CanGoForward(): - self.chromeWindow.GetBrowser().GoForward() - self.UpdateButtonsState() - - def OnReload(self, event): - self.chromeWindow.GetBrowser().Reload() - self.UpdateButtonsState() - - def UpdateButtonsState(self): - self.navigationBar.backBtn.Enable( - self.chromeWindow.GetBrowser().CanGoBack()) - self.navigationBar.forwardBtn.Enable( - self.chromeWindow.GetBrowser().CanGoForward()) - - def OnLoadStart(self, browser, frame): - if self.navigationBar: - self.UpdateButtonsState() - self.navigationBar.GetUrlCtrl().SetValue( - browser.GetMainFrame().GetUrl()) - self.navigationBar.AddToHistory(browser.GetMainFrame().GetUrl()) - - def OnLoadEnd(self, browser, frame, httpStatusCode): - pass - -class DefaultClientHandler(object): - def __init__(self, parentCtrl): - self.parentCtrl = parentCtrl - - def OnLoadStart(self, browser, frame): - self.parentCtrl.OnLoadStart(browser, frame) - - def OnLoadEnd(self, browser, frame, httpStatusCode): - self.parentCtrl.OnLoadEnd(browser, frame, httpStatusCode) - - def OnLoadError(self, browser, frame, errorCode, failedUrl, errorText): - # TODO - print("ERROR LOADING URL : %s" % failedUrl) - -class CallbackClientHandler(object): - def __init__(self, onLoadStart=None, onLoadEnd=None): - self.onLoadStart = onLoadStart - self.onLoadEnd = onLoadEnd - - def OnLoadStart(self, browser, frame): - if self.onLoadStart and frame.GetUrl() != "about:blank": - self.onLoadStart(browser, frame) - - def OnLoadEnd(self, browser, frame, httpStatusCode): - if self.onLoadEnd and frame.GetUrl() != "about:blank": - self.onLoadEnd(browser, frame, httpStatusCode) - - def OnLoadError(self, browser, frame, errorCode, failedUrl, errorText): - # TODO - print("ERROR LOADING URL : %s" % failedUrl) - -#------------------------------------------------------------------------------- - -def Initialize(settings=None): - """Initializes CEF, We should do it before initializing wx - If no settings passed a default is used - """ - sys.excepthook = ExceptHook - if not settings: - settings = {} - if not "log_severity" in settings: - settings["log_severity"] = cefpython.LOGSEVERITY_INFO - if not "log_file" in settings: - settings["log_file"] = "" - if platform.system() == "Linux": - # On Linux we need to set locales and resources directories. - if not "locales_dir_path" in settings: - settings["locales_dir_path"] = cefpython.GetModuleDirectory()+( - "/locales") - if not "resources_dir_path" in settings: - settings["resources_dir_path"] = cefpython.GetModuleDirectory() - - cefpython.Initialize(settings) - -def Shutdown(): - """Shuts down CEF, should be called by app exiting code""" - cefpython.Shutdown() diff --git a/cefpython/cef1/wx-subpackage/examples/back.png b/cefpython/cef1/wx-subpackage/examples/back.png deleted file mode 100644 index 3e8f12fe24c6e042bc7ef4badb15449f71529ace..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1348 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 - - - - sample 1 - - - - -sample1.py - wxPython example for the CEF Python framework - -

Google Search

- - http://www.google.com/ - -

User agent

- - - -

Popup

- - - window.open('sample1.html') - -










-










-










- - - diff --git a/cefpython/cef1/wx-subpackage/examples/sample1.py b/cefpython/cef1/wx-subpackage/examples/sample1.py deleted file mode 100644 index 788c514e7..000000000 --- a/cefpython/cef1/wx-subpackage/examples/sample1.py +++ /dev/null @@ -1,34 +0,0 @@ -# Simple sample ilustrating the usage of CEFWindow class -# __author__ = "Greg Kacy " - -import os -import wx -import cefpython1.wx.chromectrl as chrome - -class MainFrame(wx.Frame): - def __init__(self): - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, - title='cefwx example1', size=(600,400)) - - self.cefWindow = chrome.ChromeWindow(self, - url=os.path.join(os.path.dirname(os.path.abspath(__file__)), - "sample1.html")) - - sizer = wx.BoxSizer() - sizer.Add(self.cefWindow, 1, wx.EXPAND, 0) - self.SetSizer(sizer) - - self.Bind(wx.EVT_CLOSE, self.OnClose) - - def OnClose(self, event): - self.Destroy() - -if __name__ == '__main__': - chrome.Initialize() - print('sample1.py: wx.version=%s' % wx.version()) - app = wx.PySimpleApp() - MainFrame().Show() - app.MainLoop() - # Important: do the wx cleanup before calling Shutdown. - del app - chrome.Shutdown() diff --git a/cefpython/cef1/wx-subpackage/examples/sample2.py b/cefpython/cef1/wx-subpackage/examples/sample2.py deleted file mode 100644 index d6ae5ebfd..000000000 --- a/cefpython/cef1/wx-subpackage/examples/sample2.py +++ /dev/null @@ -1,74 +0,0 @@ -# Slightly more advanced sample illustrating the usage of CEFWindow class -# __author__ = "Greg Kacy " - -import wx -import wx.lib.agw.flatnotebook as fnb -import cefpython1.wx.chromectrl as chrome - -ROOT_NAME = "My Locations" - -URLS = ["http://gmail.com", - "http://maps.google.com", - "http://youtube.com", - "http://yahoo.com", - "http://wikipedia.com", - "http://cyaninc.com", - "http://tavmjong.free.fr/INKSCAPE/MANUAL/web/svg_tests.php" - ] - - -class MainFrame(wx.Frame): - def __init__(self): - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, - title='cefwx example2', size=(1024, 768)) - - self.initComponents() - self.layoutComponents() - self.initEventHandlers() - - def initComponents(self): - self.tree = wx.TreeCtrl(self, id=-1, size=(200, -1)) - self.root = self.tree.AddRoot(ROOT_NAME) - for url in URLS: - self.tree.AppendItem(self.root, url) - self.tree.Expand(self.root) - - self.tabs = fnb.FlatNotebook(self, wx.ID_ANY, agwStyle=fnb.FNB_NODRAG | fnb.FNB_X_ON_TAB) - - def layoutComponents(self): - sizer = wx.BoxSizer(wx.HORIZONTAL) - sizer.Add(self.tree, 0, wx.EXPAND) - sizer.Add(self.tabs, 1, wx.EXPAND) - self.SetSizer(sizer) - - def initEventHandlers(self): - self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, self.tree) - self.Bind(fnb.EVT_FLATNOTEBOOK_PAGE_CLOSING, self.OnPageClosing) - self.Bind(wx.EVT_CLOSE, self.OnClose) - - def OnSelChanged(self, event): - self.item = event.GetItem() - url = self.tree.GetItemText(self.item) - if url and url != ROOT_NAME: - cefPanel = chrome.ChromeCtrl(self.tabs, useTimer=True, url=str(url)) - self.tabs.AddPage(cefPanel, url) - self.tabs.SetSelection(self.tabs.GetPageCount()-1) - event.Skip() - - def OnPageClosing(self, event): - print("sample2.py: One could place some extra closing stuff here") - event.Skip() - - def OnClose(self, event): - self.Destroy() - -if __name__ == '__main__': - chrome.Initialize() - print('sample2.py: wx.version=%s' % wx.version()) - app = wx.PySimpleApp() - MainFrame().Show() - app.MainLoop() - # Important: do the wx cleanup before calling Shutdown. - del app - chrome.Shutdown() - diff --git a/cefpython/cef1/wx-subpackage/examples/sample3.py b/cefpython/cef1/wx-subpackage/examples/sample3.py deleted file mode 100644 index bffa5db76..000000000 --- a/cefpython/cef1/wx-subpackage/examples/sample3.py +++ /dev/null @@ -1,79 +0,0 @@ -# Slightly more advanced sample illustrating the usage of CEFWindow class -# __author__ = "Greg Kacy " - -import os -import wx -import wx.lib.agw.flatnotebook as fnb -import cefpython1.wx.chromectrl as chrome - -class MainFrame(wx.Frame): - def __init__(self): - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, - title='cefwx example3', size=(800,600)) - self._InitComponents() - self._LayoutComponents() - self._InitEventHandlers() - - def _InitComponents(self): - self.tabs = fnb.FlatNotebook(self, wx.ID_ANY, - agwStyle=fnb.FNB_NODRAG|fnb.FNB_X_ON_TAB) - - ctrl1 = chrome.ChromeCtrl(self.tabs, useTimer=True, - url="wikipedia.org") - ctrl1.GetNavigationBar().GetUrlCtrl().SetEditable(False) - ctrl1.GetNavigationBar().GetBackButton().SetBitmapLabel( - wx.Bitmap(os.path.join(os.path.dirname(os.path.abspath(__file__)), - "back.png"), wx.BITMAP_TYPE_PNG)) - ctrl1.GetNavigationBar().GetForwardButton().SetBitmapLabel( - wx.Bitmap(os.path.join(os.path.dirname(os.path.abspath(__file__)), - "forward.png"), wx.BITMAP_TYPE_PNG)) - ctrl1.GetNavigationBar().GetReloadButton().SetBitmapLabel( - wx.Bitmap(os.path.join(os.path.dirname(os.path.abspath(__file__)), - "reload_page.png"), wx.BITMAP_TYPE_PNG)) - - self.tabs.AddPage(ctrl1, "Wikipedia") - - ctrl2 = chrome.ChromeCtrl(self.tabs, useTimer=True, url="google.com", - hasNavBar=False) - self.tabs.AddPage(ctrl2, "Google") - - ctrl3 = chrome.ChromeCtrl(self.tabs, useTimer=True, url="greenpeace.org") - ctrl3.SetNavigationBar(CustomNavigationBar(ctrl3)) - self.tabs.AddPage(ctrl3, "Greenpeace") - - def _LayoutComponents(self): - sizer = wx.BoxSizer(wx.HORIZONTAL) - sizer.Add(self.tabs, 1, wx.EXPAND) - self.SetSizer(sizer) - - def _InitEventHandlers(self): - self.Bind(wx.EVT_CLOSE, self.OnClose) - - def OnClose(self, event): - self.Destroy() - - -class CustomNavigationBar(chrome.NavigationBar): - def _LayoutComponents(self): - sizer = wx.BoxSizer(wx.HORIZONTAL) - sizer.Add(self.url, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 12) - - sizer.Add(self.GetBackButton(), 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL| - wx.ALL, 0) - sizer.Add(self.GetForwardButton(), 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL| - wx.ALL, 0) - # in this example we dont want reload button - self.GetReloadButton().Hide() - self.SetSizer(sizer) - self.Fit() - -if __name__ == '__main__': - chrome.Initialize() - print('sample3.py: wx.version=%s' % wx.version()) - app = wx.PySimpleApp() - MainFrame().Show() - app.MainLoop() - # Important: do the wx cleanup before calling Shutdown. - del app - chrome.Shutdown() - diff --git a/cefpython/cef1/wx-subpackage/images/Arrow Left.png b/cefpython/cef1/wx-subpackage/images/Arrow Left.png deleted file mode 100644 index 640c707d1b16d355aad519d42cadaf3af17c6e09..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3798 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 ContentFilterHandler( - self.contentFilterId)) - - def SetHandler(self, handler): - assert handler, "ContentFilterHandler is empty" - has_OnData = hasattr(handler, "OnData") and ( - callable(getattr(handler, "OnData"))) - has_OnDrain = hasattr(handler, "OnDrain") and ( - callable(getattr(handler, "OnDrain"))) - assert has_OnData, "ContentFilterHandler is missing OnData() method" - assert has_OnDrain, "ContentFilterHandler is missing OnDrain() method" - self.handler = handler - - def HasHandler(self): - return bool(self.handler) - - cdef object GetCallback(self, str funcName): - if not self.handler: - return None - if hasattr(self.handler, funcName) and ( - callable(getattr(self.handler, funcName))): - return getattr(self.handler, funcName) - - cdef CefRefPtr[CefContentFilter] GetCefContentFilter(self) except *: - return self.cefContentFilter - -# ------------------------------------------------------------------------------ -# C++ ContentFilterHandler -# ------------------------------------------------------------------------------ - -cdef public void ContentFilterHandler_ProcessData( - int contentFilterId, - const void* data, - int data_size, - CefRefPtr[CefStreamReader]& substitute_data - ) except * with gil: - cdef PyContentFilter contentFilter - cdef object callback - cdef PyStreamReader pyStreamReader - try: - contentFilter = GetPyContentFilter(contentFilterId) - if contentFilter: - callback = contentFilter.GetCallback("OnData") - if callback: - pyStreamReader = PyStreamReader() - callback(VoidPtrToString(data, data_size), pyStreamReader) - if pyStreamReader.HasCefStreamReader(): - substitute_data.swap(pyStreamReader.GetCefStreamReader()) - except: - (exc_type, exc_value, exc_trace) = sys.exc_info() - sys.excepthook(exc_type, exc_value, exc_trace) - -cdef public void ContentFilterHandler_Drain( - int contentFilterId, - CefRefPtr[CefStreamReader]& remainder - ) except * with gil: - cdef PyContentFilter contentFilter - cdef object callback - cdef PyStreamReader pyStreamReader - try: - contentFilter = GetPyContentFilter(contentFilterId) - if contentFilter: - callback = contentFilter.GetCallback("OnDrain") - if callback: - pyStreamReader = PyStreamReader() - callback(pyStreamReader) - if pyStreamReader.HasCefStreamReader(): - remainder.swap(pyStreamReader.GetCefStreamReader()) - except: - (exc_type, exc_value, exc_trace) = sys.exc_info() - sys.excepthook(exc_type, exc_value, exc_trace) diff --git a/cefpython/ctags.bat b/cefpython/ctags.bat deleted file mode 100644 index 4ea2c523d..000000000 --- a/cefpython/ctags.bat +++ /dev/null @@ -1,10 +0,0 @@ -REM CTags provides code completion, finding definition/use of an identifier, -REM it supports 41 languages including Cython, see: http://ctags.sourceforge.net/ -REM Many editors are supported, see http://ctags.sourceforge.net/tools.html , -REM though there are much more, but unlisted there. - -REM kinds: p = function prototypes [off by default] -REM --c++-kinds=+p - -call C:\ctags58\ctags.exe -R --c++-kinds=+p --exclude=setup --exclude=cefpython_py27.py --exclude=cefpython_py32.py -f ctags -pause \ No newline at end of file diff --git a/cefpython/cython_includes/cef_content_filter.pxd b/cefpython/cython_includes/cef_content_filter.pxd deleted file mode 100644 index 5c63a5499..000000000 --- a/cefpython/cython_includes/cef_content_filter.pxd +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -from cef_base cimport CefBase - -cdef extern from "include/cef_content_filter.h": - cdef cppclass CefContentFilter(CefBase): - pass diff --git a/cefpython/cython_includes/cef_drag.pxd b/cefpython/cython_includes/cef_drag.pxd deleted file mode 100644 index 35705b4c3..000000000 --- a/cefpython/cython_includes/cef_drag.pxd +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -from libc.limits cimport UINT_MAX - -cdef extern from "include/internal/cef_types.h": - cdef enum cef_drag_operations_mask_t: - DRAG_OPERATION_NONE = 0, - DRAG_OPERATION_COPY = 1, - DRAG_OPERATION_LINK = 2, - DRAG_OPERATION_GENERIC = 4, - DRAG_OPERATION_PRIVATE = 8, - DRAG_OPERATION_MOVE = 16, - DRAG_OPERATION_DELETE = 32, - DRAG_OPERATION_EVERY = UINT_MAX diff --git a/cefpython/cython_includes/cef_drag_data.pxd b/cefpython/cython_includes/cef_drag_data.pxd deleted file mode 100644 index 4f79942b2..000000000 --- a/cefpython/cython_includes/cef_drag_data.pxd +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -from libcpp cimport bool as cpp_bool -from cef_string cimport CefString -from libcpp.vector cimport vector as cpp_vector - -cdef extern from "include/cef_drag_data.h": - cdef cppclass CefDragData: - cpp_bool IsLink() - cpp_bool IsFragment() - cpp_bool IsFile() - CefString GetLinkURL() - CefString GetLinkTitle() - CefString GetLinkMetadata() - CefString GetFragmentText() - CefString GetFragmentHtml() - CefString GetFragmentBaseURL() - CefString GetFileName() - cpp_bool GetFileNames(cpp_vector[CefString]& names) diff --git a/cefpython/cython_includes/cef_frame.pxd b/cefpython/cython_includes/cef_frame.pxd index 0d20768c9..b8ff4c0b8 100644 --- a/cefpython/cython_includes/cef_frame.pxd +++ b/cefpython/cython_includes/cef_frame.pxd @@ -15,56 +15,26 @@ from cef_string_visitor cimport CefStringVisitor cdef extern from "include/cef_frame.h": - IF CEF_VERSION == 1: - cdef cppclass CefFrame(CefBase): - void ExecuteJavaScript(CefString& jsCode, CefString& scriptUrl, int startLine) - CefString GetURL() - int64 GetIdentifier() - CefRefPtr[CefV8Context] GetV8Context() - cpp_bool IsMain() - void LoadURL(CefString& url) - void Undo() - void Redo() - void Cut() - void Copy() - void Paste() - void Delete() - void SelectAll() - void ViewSource() - void Print() - CefString GetSource() - CefString GetText() - void LoadString(CefString& string_val, CefString& url) - # virtual void LoadStream(CefRefPtr stream, const CefString& url) =0; - cpp_bool IsFocused() - CefString GetName() - # virtual void VisitDOM(CefRefPtr visitor) =0; - CefRefPtr[CefFrame] GetParent() - CefRefPtr[CefBrowser] GetBrowser() - - ELIF CEF_VERSION == 3: - cdef cppclass CefFrame(CefBase): - cpp_bool IsValid() - void ExecuteJavaScript(CefString& jsCode, CefString& scriptUrl, int startLine) - CefString GetURL() - int64 GetIdentifier() - CefRefPtr[CefV8Context] GetV8Context() - cpp_bool IsMain() - void LoadURL(CefString& url) - void Undo() - void Redo() - void Cut() - void Copy() - void Paste() - void Delete() - void SelectAll() - void ViewSource() - # void Print() - void GetSource(CefRefPtr[CefStringVisitor] visitor) - void GetText(CefRefPtr[CefStringVisitor] visitor) - void LoadString(CefString& string_val, CefString& url) - cpp_bool IsFocused() - CefString GetName() - # virtual void VisitDOM(CefRefPtr visitor) =0; - CefRefPtr[CefFrame] GetParent() - CefRefPtr[CefBrowser] GetBrowser() + cdef cppclass CefFrame(CefBase): + cpp_bool IsValid() + void ExecuteJavaScript(CefString& jsCode, CefString& scriptUrl, int startLine) + CefString GetURL() + int64 GetIdentifier() + CefRefPtr[CefV8Context] GetV8Context() + cpp_bool IsMain() + void LoadURL(CefString& url) + void Undo() + void Redo() + void Cut() + void Copy() + void Paste() + void Delete() + void SelectAll() + void ViewSource() + void GetSource(CefRefPtr[CefStringVisitor] visitor) + void GetText(CefRefPtr[CefStringVisitor] visitor) + void LoadString(CefString& string_val, CefString& url) + cpp_bool IsFocused() + CefString GetName() + CefRefPtr[CefFrame] GetParent() + CefRefPtr[CefBrowser] GetBrowser() diff --git a/cefpython/cython_includes/cef_stream.pxd b/cefpython/cython_includes/cef_stream.pxd deleted file mode 100644 index 33b26f1c7..000000000 --- a/cefpython/cython_includes/cef_stream.pxd +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -from cef_base cimport CefBase - -cdef extern from "include/cef_stream.h": - - cdef cppclass CefStreamReader(CefBase): - pass diff --git a/cefpython/cython_includes/cef_stream_static.pxd b/cefpython/cython_includes/cef_stream_static.pxd deleted file mode 100644 index 0bd433fc1..000000000 --- a/cefpython/cython_includes/cef_stream_static.pxd +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -from cef_ptr cimport CefRefPtr -from cef_stream cimport CefStreamReader -from cef_string cimport CefString - -cdef extern from "include/cef_stream.h" namespace "CefStreamReader": - cdef CefRefPtr[CefStreamReader] CreateForFile(const CefString& fileName) - cdef CefRefPtr[CefStreamReader] CreateForData(void* data, size_t size) \ No newline at end of file diff --git a/cefpython/cython_includes/content_filter_handler.pxd b/cefpython/cython_includes/content_filter_handler.pxd deleted file mode 100644 index 270d61e77..000000000 --- a/cefpython/cython_includes/content_filter_handler.pxd +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -cdef extern from "client_handler/content_filter_handler.h": - cdef cppclass ContentFilterHandler: - ContentFilterHandler(int contentFilterId) diff --git a/cefpython/drag_data.pyx b/cefpython/drag_data.pyx deleted file mode 100644 index 10311513e..000000000 --- a/cefpython/drag_data.pyx +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -cdef PyDragData CreatePyDragData(CefRefPtr[CefDragData] cefDragData): - cdef PyDragData pyDragData = PyDragData() - pyDragData.cefDragData = cefDragData - return pyDragData - -cdef class PyDragData: - cdef CefRefPtr[CefDragData] cefDragData - - cpdef py_bool IsLink(self): - return self.cefDragData.get().IsLink() - - cpdef py_bool IsFragment(self): - return self.cefDragData.get().IsFragment() - - cpdef py_bool IsFile(self): - return self.cefDragData.get().IsFile() - - cpdef str GetLinkUrl(self): - return CefToPyString(self.cefDragData.get().GetLinkURL()) - - cpdef str GetLinkTitle(self): - return CefToPyString(self.cefDragData.get().GetLinkTitle()) - - cpdef str GetLinkMetadata(self): - return CefToPyString(self.cefDragData.get().GetLinkMetadata()) - - cpdef str GetFragmentText(self): - return CefToPyString(self.cefDragData.get().GetFragmentText()) - - cpdef str GetFragmentHtml(self): - return CefToPyString(self.cefDragData.get().GetFragmentHtml()) - - cpdef str GetFragmentBaseUrl(self): - return CefToPyString(self.cefDragData.get().GetFragmentBaseURL()) - - cpdef str GetFile(self): - return CefToPyString(self.cefDragData.get().GetFileName()) - - cpdef list GetFiles(self): - cdef cpp_vector[CefString] files - cdef cpp_vector[CefString].iterator it - cdef cpp_bool succeeded = self.cefDragData.get().GetFileNames(files) - cdef CefString value - cdef list ret = [] - if succeeded: - it = files.begin() - while it != files.end(): - value = deref(it) - ret.append(CefToPyString(value)) - preinc(it) - return ret - else: - return [] diff --git a/cefpython/drag_handler.pyx b/cefpython/drag_handler.pyx deleted file mode 100644 index b033a3100..000000000 --- a/cefpython/drag_handler.pyx +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -class Drag: - Operation = { - "None": DRAG_OPERATION_NONE, - "Copy": DRAG_OPERATION_COPY, - "Link": DRAG_OPERATION_LINK, - "Generic": DRAG_OPERATION_GENERIC, - "Private": DRAG_OPERATION_PRIVATE, - "Move" : DRAG_OPERATION_MOVE, - "Delete": DRAG_OPERATION_DELETE, - "Every": DRAG_OPERATION_EVERY, - } - -cdef public cpp_bool DragHandler_OnDragStart( - CefRefPtr[CefBrowser] browser, - CefRefPtr[CefDragData] dragData, - cef_drag_operations_mask_t mask - ) except * with gil: - cdef PyBrowser pyBrowser - cdef PyDragData pyDragData - cdef object callback - cdef py_bool ret - try: - pyBrowser = GetPyBrowser(browser) - pyDragData = CreatePyDragData(dragData) - callback = pyBrowser.GetClientCallback("OnDragStart") - if callback: - # The max value for mask is UINT_MAX. - ret = callback(pyBrowser, pyDragData, mask) - return bool(ret) - else: - return False - except: - (exc_type, exc_value, exc_trace) = sys.exc_info() - sys.excepthook(exc_type, exc_value, exc_trace) - -cdef public cpp_bool DragHandler_OnDragEnter( - CefRefPtr[CefBrowser] browser, - CefRefPtr[CefDragData] dragData, - cef_drag_operations_mask_t mask - ) except * with gil: - cdef PyBrowser pyBrowser - cdef PyDragData pyDragData - cdef object callback - cdef py_bool ret - try: - pyBrowser = GetPyBrowser(browser) - pyDragData = CreatePyDragData(dragData) - callback = pyBrowser.GetClientCallback("OnDragEnter") - if callback: - # The max value for mask is UINT_MAX. - ret = callback(pyBrowser, pyDragData, mask) - return bool(ret) - else: - return False - except: - (exc_type, exc_value, exc_trace) = sys.exc_info() - sys.excepthook(exc_type, exc_value, exc_trace) diff --git a/cefpython/imports.pyx b/cefpython/imports.pyx index 9bc2cc1ba..afdf32841 100644 --- a/cefpython/imports.pyx +++ b/cefpython/imports.pyx @@ -127,7 +127,6 @@ ELIF UNAME_SYSNAME == "Linux": cimport cef_types_linux from cef_time cimport * -from cef_drag cimport * IF CEF_VERSION == 1: from cef_v8 cimport * @@ -138,19 +137,13 @@ IF CEF_VERSION == 1: from cef_web_urlrequest_cef1 cimport * cimport cef_web_urlrequest_static_cef1 from web_request_client_cef1 cimport * - from cef_stream cimport * - cimport cef_stream_static from cef_response_cef1 cimport * - from cef_stream cimport * - from cef_content_filter cimport * - from content_filter_handler cimport * from cef_download_handler cimport * from download_handler cimport * from cef_cookie_cef1 cimport * cimport cef_cookie_manager_namespace from cookie_visitor cimport * from cef_render_handler cimport * - from cef_drag_data cimport * IF UNAME_SYSNAME == "Windows": IF CEF_VERSION == 1: diff --git a/cefpython/stream.pyx b/cefpython/stream.pyx deleted file mode 100644 index ad823b75c..000000000 --- a/cefpython/stream.pyx +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -cdef class PyStreamReader: - cdef CefRefPtr[CefStreamReader] cefStreamReader - - cdef cpp_bool HasCefStreamReader(self) except *: - if self.cefStreamReader != NULL and self.cefStreamReader.get(): - return True - return False - - cdef CefRefPtr[CefStreamReader] GetCefStreamReader(self) except *: - if self.HasCefStreamReader(): - return self.cefStreamReader - return NULL - - cpdef py_void SetFile(self, py_string file): - if os.path.exists(file): - self.cefStreamReader = cef_stream_static.CreateForFile( - PyToCefStringValue(file)) - else: - raise Exception("File does not exist: %s" % file) - - cpdef py_void SetData(self, py_string data): - cdef cpp_string cppString = data - # CreateForData() requires "void* data", we can't just pass - # cppString.c_str() as it is const, we need to copy all data. - cdef void* voidData - cdef int dataLength = cppString.length() - voidData = malloc(dataLength) - memcpy(voidData, cppString.c_str(), dataLength) - self.cefStreamReader = cef_stream_static.CreateForData( - voidData, dataLength) - free(voidData) diff --git a/docs/API.md b/docs/API.md index e294cad0a..1d5d9acd2 100644 --- a/docs/API.md +++ b/docs/API.md @@ -1,46 +1,45 @@ -# API - -### Settings - - * [ApplicationSettings](ApplicationSettings) dictionary - * [BrowserSettings](BrowserSettings) dictionary - * [CommandLineSwitches](CommandLineSwitches) dictionary - -### Objects - - * [Browser](Browser) object - * [Callback](Callback) object - * [ContentFilter](ContentFilter) object - * [Cookie](Cookie) class - * [CookieManager](CookieManager) class - * [DpiAware](DpiAware) class (Win) - * [DragData](DragData) object - * [Frame](Frame) object - * [JavascriptBindings](JavascriptBindings) class - * [JavascriptCallback](JavascriptCallback) object - * [PaintBuffer](PaintBuffer) object - * [Request](Request) class - * [Response](Response) object - * [StreamReader](StreamReader) object - * [WebPluginInfo](WebPluginInfo) object - * [WebRequest](WebRequest) class - * [WindowInfo](WindowInfo) class - * [WindowUtils](WindowUtils) class - -### Handlers - - * [DisplayHandler](DisplayHandler) - * [DownloadHandler](DownloadHandler) - * [DragHandler](DragHandler) - * [JavascriptContextHandler](JavascriptContextHandler) - * [JavascriptDialogHandler](JavascriptDialogHandler) - * [KeyboardHandler](KeyboardHandler) - * [LifespanHandler](LifespanHandler) - * [LoadHandler](LoadHandler) - * [RenderHandler](RenderHandler) - * [RequestHandler](RequestHandler) - * [ResourceHandler](ResourceHandler) - -### Modules - - * [cefpython](cefpython) module +# API + + + + +### Settings + + * [ApplicationSettings](settings/ApplicationSettings.md) dictionary + * [BrowserSettings](settings/BrowserSettings.md) dictionary + * [CommandLineSwitches](settings/CommandLineSwitches.md) dictionary + +### Objects + + * [Browser](objects/Browser.md) object + * [Callback](objects/Callback.md) object + * [Cookie](objects/Cookie.md) class + * [CookieManager](objects/CookieManager.md) class + * [DpiAware](objects/DpiAware.md) class (Win) + * [Frame](objects/Frame.md) object + * [JavascriptBindings](objects/JavascriptBindings.md) class + * [JavascriptCallback](objects/JavascriptCallback.md) object + * [PaintBuffer](objects/PaintBuffer.md) object + * [Request](objects/Request.md) class + * [Response](objects/Response.md) object + * [WebPluginInfo](objects/WebPluginInfo.md) object + * [WebRequest](objects/WebRequest.md) class + * [WindowInfo](objects/WindowInfo.md) class + * [WindowUtils](objects/WindowUtils.md) class + +### Handlers + + * [DisplayHandler](handlers/DisplayHandler.md) + * [DownloadHandler](handlers/DownloadHandler.md) + * [JavascriptContextHandler](handlers/JavascriptContextHandler.md) + * [JavascriptDialogHandler](handlers/JavascriptDialogHandler.md) + * [KeyboardHandler](handlers/KeyboardHandler.md) + * [LifespanHandler](handlers/LifespanHandler.md) + * [LoadHandler](handlers/LoadHandler.md) + * [RenderHandler](handlers/RenderHandler.md) + * [RequestHandler](handlers/RequestHandler.md) + * [ResourceHandler](handlers/ResourceHandler.md) + +### Modules + + * [cefpython](modules/cefpython.md) module diff --git a/docs/handlers/KeyboardHandler.md b/docs/handlers/KeyboardHandler.md index 664ca7034..4b01c69c7 100644 --- a/docs/handlers/KeyboardHandler.md +++ b/docs/handlers/KeyboardHandler.md @@ -1,101 +1,72 @@ -# KeyboardHandler callbacks # - -This handler allows you to handle events related to keyboard input and is called only for the main frame. - -For an example of how to implement handler see [cefpython](cefpython).CreateBrowser(). For a list of all handler interfaces see [API > Client handlers](API#Client_handlers). - -## CEF 3 ## - -bool **OnPreKeyEvent**([Browser](Browser) browser, `KeyEvent` event, `MSG*|GdkEvent*|NSEvent*` eventHandle, list& isKeyboardShortcutOut) - -> Called before a keyboard event is sent to the renderer. |event| contains -> information about the keyboard event. |eventHandle| is the operating system -> event message, if any. Return true if the event was handled or false -> otherwise. If the event will be handled in `OnKeyEvent()` as a keyboard -> shortcut, set `isKeyboardShortcutOut[0]` to true and return false. - -> `KeyEvent` is a dictionary with the following keys: - - * "**type**" (`KeyEventType`) - The type of keyboard event - * "**modifiers**" (uint32) - Bit flags describing any pressed modifier keys. See `KeyEventFlags` for values. - * "**windows\_key\_code**" (int) - The Windows key code for the key event. This value is used by the DOM specification. Sometimes it comes directly from the event (i.e. on Windows) and sometimes it's determined using a mapping function. See `"WebCore/platform/chromium/KeyboardCodes.h"` for the list of values. - * "**native\_key\_code**" (int) - The actual key code genenerated by the platform. - * "**is\_system\_key**" (int) - Indicates whether the event is considered a "system key" event (see http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx for details). This value will always be false on non-Windows platforms. - * "**character**" (wchar\_t or unsigned short) - The character generated by the keystroke. - * "**unmodified\_character**" (wchar\_t or unsigned short) - Same as |character| but unmodified by any concurrently-held modifiers (except shift). This is useful for working out shortcut keys. - * "**focus\_on\_editable\_field**" (bool) - True if the focus is currently on an editable field on the page. This is useful for determining if standard key events should be intercepted. - -> `KeyEventType` is one of: - -> `cefpython.KEYEVENT_RAWKEYDOWN`
-
cefpython.KEYEVENT_KEYDOWN
-cefpython.KEYEVENT_KEYUP
-cefpython.KEYEVENT_CHAR
- -
KeyEventFlags constants ("modifiers" key):
- -
cefpython.EVENTFLAG_NONE
-cefpython.EVENTFLAG_CAPS_LOCK_ON
-cefpython.EVENTFLAG_SHIFT_DOWN
-cefpython.EVENTFLAG_CONTROL_DOWN
-cefpython.EVENTFLAG_ALT_DOWN
-cefpython.EVENTFLAG_LEFT_MOUSE_BUTTON
-cefpython.EVENTFLAG_MIDDLE_MOUSE_BUTTON
-cefpython.EVENTFLAG_RIGHT_MOUSE_BUTTON
-// Mac OS-X command key.
-cefpython.EVENTFLAG_COMMAND_DOWN
-cefpython.EVENTFLAG_NUM_LOCK_ON
-cefpython.EVENTFLAG_IS_KEY_PAD
-cefpython.EVENTFLAG_IS_LEFT
-cefpython.EVENTFLAG_IS_RIGHT
- - -bool OnKeyEvent(Browser browser, KeyEvent event, MSG*|GdkEvent*|NSEvent* eventHandle)
-
-
Called after the renderer and JavaScript in the page has had a chance to
-handle the event. |event| contains information about the keyboard event.
-|os_event| is the operating system event message, if any. Return true if
-the keyboard event was handled or false otherwise.
- -
Description of the KeyEvent type is in the OnPreKeyEvent() callback.
- -

CEF 1

- -bool OnKeyEvent(Browser browser, int eventType, VirtualKey keyCode, int modifiers, bool isSystemKey, bool isAfterJavascript)
-
-
Called when the browser component receives a keyboard event. This method
-is called both before the event is passed to the renderer and after
-javascript in the page has had a chance to handle the event. |type| is the type of keyboard event, |code| is the windows scan-code for the event, |modifiers| is a set of bit- flags describing any pressed modifier keys and |isSystemKey| is true if Windows considers this a WM_SYSKEYDOWN message.
- -
If |isAfterJavaScript| is true then javascript in the page has had a chance to handle the event and has chosen not to. Only KEYEVENT_RAWKEYDOWN, KEYEVENT_KEYDOWN and
-KEYEVENT_CHAR events will be sent with |isAfterJavaScript| set to true. Return true if the keyboard event was handled or false to allow continued handling of the event by the renderer.
- -
|eventType| constants:
- -
cefpython.KEYEVENT_RAWKEYDOWN
-cefpython.KEYEVENT_KEYDOWN
-cefpython.KEYEVENT_KEYUP
-cefpython.KEYEVENT_CHAR
- -
Example of implementing KeyboardHandler:
- -
	def OnKeyEvent(browser, eventType, keyCode, modifiers, isSystemKey, isAfterJavascript):
- # Let's bind developer tools to F12 key.
- if keyCode == cefpython.VK_F12 and eventType == cefpython.KEYEVENT_RAWKEYDOWN and cefpython.IsKeyModifier(cefpython.KEY_NONE, modifiers) and not isSystemKey:
- browser.ShowDevTools()
- return True
- # Bind F5 to refresh browser window.
- if keyCode == cefpython.VK_F5 and eventType == cefpython.KEYEVENT_RAWKEYDOWN and cefpython.IsKeyModifier(cefpython.KEY_NONE, modifiers) and not isSystemKey:
- browser.ReloadIgnoreCache()
- return True
- return False
-
- -
To check against |modifiers| you can use function cefpython.IsKeyModifier(KEY_*, modifiers) where KEY_* is one of:
- -
cefpython.KEY_NONE # neither of alt/shift/ctrl is pressed
-cefpython.KEY_SHIFT
-cefpython.KEY_CTRL
-cefpython.KEY_ALT
-cefpython.KEY_META
-cefpython.KEY_KEYPAD
\ No newline at end of file +# KeyboardHandler + + + + +This handler allows you to handle events related to keyboard input and is called only for the main frame. For an example of how to implement handler see [cefpython](../modules/cefpython.md).CreateBrowser(). + +## Callbacks + +### OnPreKeyEvent + +| Parameter | Type | +| --- | --- | +| browser | [Browser](../objects/Browser.md) | +| event | KeyEvent | +| eventHandle | MSG\* / GdkEvent\* / NSEvent\*` | +| isKeyboardShortcutOut | out list[0] -> bool | +| __Return__ | void | + +Called before a keyboard event is sent to the renderer. |event| contains +information about the keyboard event. |eventHandle| is the operating system +event message, if any. Return true if the event was handled or false +otherwise. If the event will be handled in OnKeyEvent() as a keyboard +shortcut, set isKeyboardShortcutOut[0] to True and return False. + +KeyEvent is a dictionary with the following keys: + +| Key | Type | Description | +| --- | --- | --- | +| type | KeyEventType | The type of keyboard event | +| modifiers | KeyEventFlags | Bit flags describing any pressed modifier keys | +| windows_key_code | int | The Windows key code for the key event. This value is used by the DOM specification. Sometimes it comes directly from the event (i.e. on Windows) and sometimes it's determined using a mapping function. See "chromium/KeyboardCodes.h" for a list of values. | +| native_key_code | int | The actual key code genenerated by the platform | +| is_system_key | int | Indicates whether the event is considered a "system key" event. For Windows see [WM_SYSKEYDOWN](http://msdn.microsoft.com/en-us/library/ms646286.aspx). This value will always be false on non-Windows platforms. | +| character | wchar_t or unsigned short | The character generated by the keystroke | +| unmodified_character | wchar_t or unsigned short | Same as 'character' but unmodified by any concurrently-held modifiers (except shift). This is useful for working out shortcut keys. | +| focus_on_editable_field | bool | True if the focus is currently on an editable field on the page. This is useful for determining if standard key events should be intercepted. | + +KeyEventType constants: +* cefpython.KEYEVENT_RAWKEYDOWN +* cefpython.KEYEVENT_KEYDOWN +* cefpython.KEYEVENT_KEYUP +* cefpython.KEYEVENT_CHAR + +KeyEventFlags constants: +* cefpython.EVENTFLAG_NONE +* cefpython.EVENTFLAG_CAPS_LOCK_ON +* cefpython.EVENTFLAG_SHIFT_DOWN +* cefpython.EVENTFLAG_CONTROL_DOWN +* cefpython.EVENTFLAG_ALT_DOWN +* cefpython.EVENTFLAG_LEFT_MOUSE_BUTTON +* cefpython.EVENTFLAG_MIDDLE_MOUSE_BUTTON +* cefpython.EVENTFLAG_RIGHT_MOUSE_BUTTON +* cefpython.EVENTFLAG_COMMAND_DOWN (Mac) +* cefpython.EVENTFLAG_NUM_LOCK_ON (Mac) +* cefpython.EVENTFLAG_IS_KEY_PAD (Mac) +* cefpython.EVENTFLAG_IS_LEFT (Mac) +* cefpython.EVENTFLAG_IS_RIGHT (Mac) + +### OnKeyEvent + +| Parameter | Type | +| --- | --- | +| browser | [Browser](../objects/Browser.md) | +| event | KeyEvent | +| eventHandle | MSG\* / GdkEvent\* / NSEvent\* | +| __Return__ | void | + +Called after the renderer and javascript in the page has had a chance to +handle the event. |event| contains information about the keyboard event. +|os_event| is the operating system event message, if any. Return true if +the keyboard event was handled or false otherwise. Description of the KeyEvent type is in the OnPreKeyEvent() callback. diff --git a/docs/objects/NetworkError.md b/docs/objects/NetworkError.md index 7061e0fbe..ebfa1587d 100644 --- a/docs/objects/NetworkError.md +++ b/docs/objects/NetworkError.md @@ -1,239 +1,247 @@ -# Network error constants # +# Network error -These constants are for use with: [LoadHandler](LoadHandler).`OnLoadError()`, [WebRequestClient](WebRequestClient).`OnError()`, [RequestHandler](RequestHandler).`OnCertificateError()`. +These constants are defined in the main [cefpython](../modules/cefpython.md) module. They are for use with: +* [LoadHandler](../handlers/LoadHandler.md).OnLoadError() +* [WebRequestClient](WebRequestClient.md).OnError() +* [RequestHandler](../handlers/RequestHandler.md).OnCertificateError() -For an up-to-date list of error codes see "net\_error\_list.h" in the Chromium trunk: http://src.chromium.org/viewvc/chrome/trunk/src/net/base/net_error_list.h?view=markup +For an up-to-date list of error codes see [net_error_list.h](http://src.chromium.org/viewvc/chrome/trunk/src/net/base/net_error_list.h?view=markup) in Chromium. -cefpython.**ERR\_NONE** + + -> No error. +## Constants -cefpython.**ERR\_ABORTED** +### ERR_NONE -> An operation was aborted (due to user action). +No error. -cefpython.**ERR\_ACCESS\_DENIED** +### ERR_ABORTED -> Permission to access a resource, other than the network, was denied. +An operation was aborted (due to user action). -cefpython.**ERR\_ADDRESS\_INVALID** +### ERR_ACCESS_DENIED -> The IP address or port number is invalid (e.g., cannot connect to the IP address 0 or the port 0). +Permission to access a resource, other than the network, was denied. -cefpython.**ERR\_ADDRESS\_UNREACHABLE** +### ERR_ADDRESS_INVALID -> The IP address is unreachable. This usually means that there is no route to the specified host or network. +The IP address or port number is invalid (e.g., cannot connect to the IP address 0 or the port 0). -cefpython.**ERR\_CACHE\_MISS** +### ERR_ADDRESS_UNREACHABLE -> The cache does not have the requested entry. +The IP address is unreachable. This usually means that there is no route to the specified host or network. -cefpython.**ERR\_CERT\_AUTHORITY\_INVALID** +### ERR_CACHE_MISS -> The server responded with a certificate that is signed by an authority -> we don't trust. That could mean: +The cache does not have the requested entry. + +### ERR_CERT_AUTHORITY_INVALID + +The server responded with a certificate that is signed by an authority +we don't trust. That could mean: 1. An attacker has substituted the real certificate for a cert that contains his public key and is signed by his cousin. 1. The server operator has a legitimate certificate from a CA we don't know about, but should trust. 1. The server is presenting a self-signed certificate, providing no defense against active attackers (but foiling passive attackers). -cefpython.**ERR\_CERT\_COMMON\_NAME\_INVALID** +### ERR_CERT_COMMON_NAME_INVALID -> The server responded with a certificate whose common name did not match -> the host name. This could mean: +The server responded with a certificate whose common name did not match +the host name. This could mean: 1. An attacker has redirected our traffic to his server and is presenting a certificate for which he knows the private key. 1. The server is misconfigured and responding with the wrong cert. 1. The user is on a wireless network and is being redirected to the network's login page. 1. The OS has used a DNS search suffix and the server doesn't have a certificate for the abbreviated name in the address bar. -cefpython.**ERR\_CERT\_CONTAINS\_ERRORS** +### ERR_CERT_CONTAINS_ERRORS -> The server responded with a certificate that contains errors. -> This error is not recoverable. MSDN describes this error as follows: -> "The SSL certificate contains errors." -> NOTE: It's unclear how this differs from ERR\_CERT\_INVALID. For consistency, -> use that code instead of this one from now on. +The server responded with a certificate that contains errors. +This error is not recoverable. MSDN describes this error as follows: +"The SSL certificate contains errors." +NOTE: It's unclear how this differs from ERR_CERT_INVALID. For consistency, +use that code instead of this one from now on. -cefpython.**ERR\_CERT\_DATE\_INVALID** +### ERR_CERT_DATE_INVALID -> The server responded with a certificate that, by our clock, appears to -> either not yet be valid or to have expired. This could mean: +The server responded with a certificate that, by our clock, appears to +either not yet be valid or to have expired. This could mean: 1. An attacker is presenting an old certificate for which he has managed to obtain the private key. 1. The server is misconfigured and is not presenting a valid cert. 1. Our clock is wrong. -cefpython.**ERR\_CERT\_END** +### ERR_CERT_END -> The value immediately past the last certificate error code. +The value immediately past the last certificate error code. -cefpython.**ERR\_CERT\_INVALID** +### ERR_CERT_INVALID -> The server responded with a certificate that is invalid. -> This error is not recoverable. -> MSDN describes this error as follows: -> "The SSL certificate is invalid." +The server responded with a certificate that is invalid. +This error is not recoverable. +MSDN describes this error as follows: +"The SSL certificate is invalid." -cefpython.**ERR\_CERT\_NO\_REVOCATION\_MECHANISM** +### ERR_CERT_NO_REVOCATION_MECHANISM -> The certificate has no mechanism for determining if it is revoked. In -> effect, this certificate cannot be revoked. +The certificate has no mechanism for determining if it is revoked. In +effect, this certificate cannot be revoked. -cefpython.**ERR\_CERT\_REVOKED** +### ERR_CERT_REVOKED -> The server responded with a certificate has been revoked. -> We have the capability to ignore this error, but it is probably not the -> thing to do. +The server responded with a certificate has been revoked. +We have the capability to ignore this error, but it is probably not the +thing to do. -cefpython.**ERR\_CERT\_UNABLE\_TO\_CHECK\_REVOCATION** +### ERR_CERT_UNABLE_TO_CHECK_REVOCATION -> Revocation information for the security certificate for this site is not -> available. This could mean: +Revocation information for the security certificate for this site is not +available. This could mean: 1. An attacker has compromised the private key in the certificate and is blocking our attempt to find out that the cert was revoked. 1. The certificate is unrevoked, but the revocation server is busy or unavailable. -cefpython.**ERR\_CONNECTION\_ABORTED** +### ERR_CONNECTION_ABORTED -> A connection timed out as a result of not receiving an ACK for data sent. -> This can include a FIN packet that did not get ACK'd. +A connection timed out as a result of not receiving an ACK for data sent. +This can include a FIN packet that did not get ACK'd. -cefpython.**ERR\_CONNECTION\_CLOSED** +### ERR_CONNECTION_CLOSED -> A connection was closed (corresponding to a TCP FIN). +A connection was closed (corresponding to a TCP FIN). -cefpython.**ERR\_CONNECTION\_FAILED** +### ERR_CONNECTION_FAILED -> A connection attempt failed. +A connection attempt failed. -cefpython.**ERR\_CONNECTION\_REFUSED** +### ERR_CONNECTION_REFUSED -> A connection attempt was refused. +A connection attempt was refused. -cefpython.**ERR\_CONNECTION\_RESET** +### ERR_CONNECTION_RESET -> A connection was reset (corresponding to a TCP RST). +A connection was reset (corresponding to a TCP RST). -cefpython.**ERR\_DISALLOWED\_URL\_SCHEME** +### ERR_DISALLOWED_URL_SCHEME -> The scheme of the URL is disallowed. +The scheme of the URL is disallowed. -cefpython.**ERR\_EMPTY\_RESPONSE** +### ERR_EMPTY_RESPONSE -> The server closed the connection without sending any data. +The server closed the connection without sending any data. -cefpython.**ERR\_FAILED** +### ERR_FAILED -> A generic failure occurred. +A generic failure occurred. -cefpython.**ERR\_FILE\_NOT\_FOUND** +### ERR_FILE_NOT_FOUND -> The file or directory cannot be found. +The file or directory cannot be found. -cefpython.**ERR\_FILE\_TOO\_BIG** +### ERR_FILE_TOO_BIG -> The file is too large. +The file is too large. -cefpython.**ERR\_INSECURE\_RESPONSE** +### ERR_INSECURE_RESPONSE -> The server's response was insecure (e.g. there was a cert error). +The server's response was insecure (e.g. there was a cert error). -cefpython.**ERR\_INTERNET\_DISCONNECTED** +### ERR_INTERNET_DISCONNECTED -> The Internet connection has been lost. +The Internet connection has been lost. -cefpython.**ERR\_INVALID\_ARGUMENT** +### ERR_INVALID_ARGUMENT -> An argument to the function is incorrect. +An argument to the function is incorrect. -cefpython.**ERR\_INVALID\_CHUNKED\_ENCODING** +### ERR_INVALID_CHUNKED_ENCODING -> Error in chunked transfer encoding. +Error in chunked transfer encoding. -cefpython.**ERR\_INVALID\_HANDLE** +### ERR_INVALID_HANDLE -> The handle or file descriptor is invalid. +The handle or file descriptor is invalid. -cefpython.**ERR\_INVALID\_RESPONSE** +### ERR_INVALID_RESPONSE -> The server's response was invalid. +The server's response was invalid. -cefpython.**ERR\_INVALID\_URL** +### ERR_INVALID_URL -> The URL is invalid. +The URL is invalid. -cefpython.**ERR\_METHOD\_NOT\_SUPPORTED** +### ERR_METHOD_NOT_SUPPORTED -> The server did not support the request method. +The server did not support the request method. -cefpython.**ERR\_NAME\_NOT\_RESOLVED** +### ERR_NAME_NOT_RESOLVED -> The host name could not be resolved. +The host name could not be resolved. -cefpython.**ERR\_NO\_SSL\_VERSIONS\_ENABLED** +### ERR_NO_SSL_VERSIONS_ENABLED -> No SSL protocol versions are enabled. +No SSL protocol versions are enabled. -cefpython.**ERR\_NOT\_IMPLEMENTED** +### ERR_NOT_IMPLEMENTED -> The operation failed because of unimplemented functionality. +The operation failed because of unimplemented functionality. -cefpython.**ERR\_RESPONSE\_HEADERS\_TOO\_BIG** +### ERR_RESPONSE_HEADERS_TOO_BIG -> The headers section of the response is too large. +The headers section of the response is too large. -cefpython.**ERR\_SSL\_CLIENT\_AUTH\_CERT\_NEEDED** +### ERR_SSL_CLIENT_AUTH_CERT_NEEDED -> The server requested a client certificate for SSL client authentication. +The server requested a client certificate for SSL client authentication. -cefpython.**ERR\_SSL\_PROTOCOL\_ERROR** +### ERR_SSL_PROTOCOL_ERROR -> An SSL protocol error occurred. +An SSL protocol error occurred. -cefpython.**ERR\_SSL\_RENEGOTIATION\_REQUESTED** +### ERR_SSL_RENEGOTIATION_REQUESTED -> The server requested a renegotiation (rehandshake). +The server requested a renegotiation (rehandshake). -cefpython.**ERR\_SSL\_VERSION\_OR\_CIPHER\_MISMATCH** +### ERR_SSL_VERSION_OR_CIPHER_MISMATCH -> The client and server don't support a common SSL protocol version or -> cipher suite. +The client and server don't support a common SSL protocol version or +cipher suite. -cefpython.**ERR\_TIMED\_OUT** +### ERR_TIMED_OUT -> An operation timed out. +An operation timed out. -cefpython.**ERR\_TOO\_MANY\_REDIRECTS** +### ERR_TOO_MANY_REDIRECTS -> Attempting to load an URL resulted in too many redirects. +Attempting to load an URL resulted in too many redirects. -cefpython.**ERR\_TUNNEL\_CONNECTION\_FAILED** +### ERR_TUNNEL_CONNECTION_FAILED -> A tunnel connection through the proxy could not be established. +A tunnel connection through the proxy could not be established. -cefpython.**ERR\_UNEXPECTED** +### ERR_UNEXPECTED -> An unexpected error. This may be caused by a programming mistake or an -> invalid assumption. +An unexpected error. This may be caused by a programming mistake or an +invalid assumption. -cefpython.**ERR\_UNEXPECTED\_PROXY\_AUTH** +### ERR_UNEXPECTED_PROXY_AUTH -> The response was 407 (Proxy Authentication Required), yet we did not send -> the request to a proxy. +The response was 407 (Proxy Authentication Required), yet we did not send +the request to a proxy. -cefpython.**ERR\_UNKNOWN\_URL\_SCHEME** +### ERR_UNKNOWN_URL_SCHEME -> The scheme of the URL is unknown. +The scheme of the URL is unknown. -cefpython.**ERR\_UNSAFE\_PORT** +### ERR_UNSAFE_PORT -> Attempting to load an URL with an unsafe port number. These are port -> numbers that correspond to services, which are not robust to spurious input -> that may be constructed as a result of an allowed web construct (e.g., HTTP -> looks a lot like SMTP, so form submission to port 25 is denied). +Attempting to load an URL with an unsafe port number. These are port +numbers that correspond to services, which are not robust to spurious input +that may be constructed as a result of an allowed web construct (e.g., HTTP +looks a lot like SMTP, so form submission to port 25 is denied). -cefpython.**ERR\_UNSAFE\_REDIRECT** +### ERR_UNSAFE_REDIRECT -> Attempting to load an URL resulted in an unsafe redirect (e.g., a redirect -> to file:// is considered unsafe). \ No newline at end of file +Attempting to load an URL resulted in an unsafe redirect (e.g., a redirect +to file:// is considered unsafe). diff --git a/docs/objects/WindowUtils.md b/docs/objects/WindowUtils.md index 626523145..9a99e7bed 100644 --- a/docs/objects/WindowUtils.md +++ b/docs/objects/WindowUtils.md @@ -1,41 +1,104 @@ -# WindowUtils class # +# WindowUtils class -All methods of this class are static. Access this class through [cefpython](cefpython).`WindowUtils`. +All methods of this class are static. Many of the Windows-only functions here are utilized in the PyWin32 example. -def **OnSetFocus**(int `windowHandle`, long `msg`, long `wparam`, long `lparam`) + + -> This method processes WM\_SETFOCUS message which is sent to a window after it has gained the keyboard focus. +## Methods -def **OnSize**(int `windowHandle`, long `msg`, long `wparam`, long `lparam`) +### OnSetFocus (Win) -> This method processes WM\_SIZE message which is sent to a window after its size has changed. +| Parameter | Type | +| --- | --- | +| windowHandle | int | +| msg | long | +| wparam | long | +| lparam | long | +| __Return__ | void | -def **OnEraseBackground**(int `windowHandle`, long `msg`, long `wparam`, long `lparam`) +Windows-only. This method processes WM_SETFOCUS message which is sent to a window after it has gained the keyboard focus. -> This method processes WM\_ERASEBKGND message which is sent when the window background must be erased (for example, when a window is resized). +### OnSize (Win) -> This is a Windows-only function. +| Parameter | Type | +| --- | --- | +| windowHandle | int | +| msg | long | +| wparam | long | +| lparam | long | +| __Return__ | void | -def **SetTitle**([Browser](Browser) `browser`, str `title`) +Windows-only. This method processes WM_SIZE message which is sent to a window after its size has changed. -> Set the title for the main window or popup window. The default implementation of [DisplayHandler](DisplayHandler).`OnTitleChange()` calls this method to set the title for a window. +### OnEraseBackground (Win) -def **SetIcon**([Browser](Browser) `browser`, string `icon`="inherit") +| Parameter | Type | +| --- | --- | +| windowHandle | int | +| msg | long | +| wparam | long | +| lparam | long | +| __Return__ | void | -> Set the icon for the popup window. The default implementation of [DisplayHandler](DisplayHandler).`OnTitleChange()` calls this method to set the icon for a window that wasn't created explicitily (for example a popup window), the icon is inherited from the parent window. Icon parameter accepts only "inherit", you cannot pass here a path to an icon (currently not implemented). +Windows-only. This method processes WM_ERASEBKGND message which is sent when the window background must be erased (for example, when a window is resized). -def **GetParentHandle**(int `windowHandle`) +### SetTitle (Win) -> Get a parent handle. +| Parameter | Type | +| --- | --- | +| browser | [Browser](Browser.md) | +| title | str | +| __Return__ | void | -def **IsWindowHandle**(int `windowHandle`) +Windows-only. Set the title for the main window or popup window. The default implementation of [DisplayHandler](../handlers/DisplayHandler.md).OnTitleChange() calls this method to set the title for a window. -> Check whether this is a valid window handle. +### SetIcon (Win) -def **gtk\_plug\_new**(long long `GdkNativeWindow`) +| Parameter | Type | +| --- | --- | +| browser | [Browser](Browser.md) | +| icon="inherit" | string | +| __Return__ | void | -> Available only on Linux. This method is utilized in the pyqt example. +Windows-only. Set the icon for the popup window. The default implementation of [DisplayHandler](../handlers/DisplayHandler.md).OnTitleChange() calls this method to set the icon for a window that wasn't created explicitily (for example a popup window), the icon is inherited from the parent window. Icon parameter accepts only "inherit", you cannot pass here a path to an icon (currently not implemented). -def **gtk\_widget\_show**(long long `GtkWidget*`) +### GetParentHandle -> Available only on Linux. This method is utilized in the pyqt example. \ No newline at end of file +| Parameter | Type | +| --- | --- | +| windowHandle | int | +| __Return__ | void | + +Get a parent handle. + +On Linux and Mac this method always returns 0. @TODO. + +### IsWindowHandle + +| Parameter | Type | +| --- | --- | +| windowHandle | int | +| __Return__ | void | + +Check whether this is a valid window handle. + +On Linux and Mac this method always returns True. @TODO. + +### gtk_plug_new (Linux) + +| Parameter | Type | +| --- | --- | +| long GdkNativeWindow | long | +| __Return__ | void | + +Linux-only. This method is utilized in the PyQt example. + +### gtk_widget_show (Linux) + +| Parameter | Type | +| --- | --- | +| long GtkWidget* | long | +| __Return__ | void | + +Linux-only. This method is utilized in the PyQt example. diff --git a/docs/settings/BrowserSettings.md b/docs/settings/BrowserSettings.md index 384f12ead..89532044d 100644 --- a/docs/settings/BrowserSettings.md +++ b/docs/settings/BrowserSettings.md @@ -7,7 +7,7 @@ These settings can be passed to [cefpython](../modules/cefpython.md).CreateBrowser(). -Many of these settings have their command line switch equivalent, see the [Command line switches](Command-line-switches.md) page. +Many of these settings have their command line switch equivalent, see the [CommandLineSwitches](CommandLineSwitches.md) page. In some cases, the default values of settings that are suggested by its name may not always be correct. This is because in one of CEF releases naming of these settings changed, and they started to accept states (enabled or disabled), instead of the state being included in its name (some_option_disabled). CEF Python tries to be backwards compatible, that's why the old naming convention is still used. Read description of setting and if you see that it mentions command line switch that starts with "disable-", it means that its default state is "enabled". If the command line switch starts with "enable-" then its default state is "disabled". diff --git a/tools/apidocs.py b/tools/apidocs.py index e69de29bb..100b18230 100644 --- a/tools/apidocs.py +++ b/tools/apidocs.py @@ -0,0 +1,22 @@ +"""Generate API docs from sources. + +The cefpython3 package must be first built and installed before running +this tool. It inspects both Cython sources and the dynamic module. +""" + + +def apidocs_objects(): + pass + + +def apidocs_handlers(): + pass + + +def apidocs_settings(): + pass + + +def apidocs_types(): + """CEF enums eg. TerminationStatus, KeyEvent, KeyEventFlags.""" + pass diff --git a/tools/build.py b/tools/build.py index e69de29bb..3c1393baf 100644 --- a/tools/build.py +++ b/tools/build.py @@ -0,0 +1,5 @@ +"""Build the cefpython modules with Cython. + +@TODO: check Cython version, it should be exact - read it + from requirements.txt +""" diff --git a/cefpython/tests/test-launch.sh b/tools/issue131-stress-test.sh old mode 100755 new mode 100644 similarity index 97% rename from cefpython/tests/test-launch.sh rename to tools/issue131-stress-test.sh index 16d247aa5..9cd7634ab --- a/cefpython/tests/test-launch.sh +++ b/tools/issue131-stress-test.sh @@ -20,7 +20,7 @@ for ((i = 1; i <= $1; i++)); do read -p "Press ENTER to exit" exit $code fi - echo RUN $i OK + echo RUN $i OK done echo TEST SUCCEEDED diff --git a/tools/requirements.txt b/tools/requirements.txt index 3fd490d9b..0e79a3bb2 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -1 +1,2 @@ defopt >= 1.0.1 +cython == 0.19.2 From 62c8c48561dfd8e29dcd3709341795490aeabd4c Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 24 Feb 2016 19:56:09 +0100 Subject: [PATCH 002/557] Code and documentation cleanup PART 3. Added patches/ and version/ dirs. --- README.md | 5 +- cefpython/base.h | 23 ++++++++ cefpython/version/cefpython_version.h | 32 ++++++++++ patches/Build-CEF-with-patches.md | 46 +++++++++++++++ patches/issue125_win_linux_mac/PATCH.md | 6 ++ .../http_cache_transaction.cc.patch | 14 +++++ patches/issue218_linux/PATCH.md | 7 +++ .../browser_host_impl_gtk.cc.patch | 58 +++++++++++++++++++ patches/issue73_linux/PATCH.md | 8 +++ patches/issue73_linux/include.gypi | 5 ++ patches/issue73_linux/use_allocator_none.sh | 1 + tools/automate.py | 7 +++ tools/build.py | 3 + 13 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 cefpython/base.h create mode 100644 cefpython/version/cefpython_version.h create mode 100644 patches/Build-CEF-with-patches.md create mode 100644 patches/issue125_win_linux_mac/PATCH.md create mode 100644 patches/issue125_win_linux_mac/http_cache_transaction.cc.patch create mode 100644 patches/issue218_linux/PATCH.md create mode 100644 patches/issue218_linux/browser_host_impl_gtk.cc.patch create mode 100644 patches/issue73_linux/PATCH.md create mode 100644 patches/issue73_linux/include.gypi create mode 100644 patches/issue73_linux/use_allocator_none.sh diff --git a/README.md b/README.md index 68439def0..396e8956b 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,10 @@ __Notes__: * Repository rewritten on 2016-02-15 to reduce its size. - Please clone it again. Issue #103. + Please clone it again. * There is an ongoing big refactoring with code and documentation cleanup. The last stable code is in the cefpython31 branch. - Issue #208. + Use documentation from the Wiki tab, the docs/ directory is still + under works. # CEF Python diff --git a/cefpython/base.h b/cefpython/base.h new file mode 100644 index 000000000..f4a4176b3 --- /dev/null +++ b/cefpython/base.h @@ -0,0 +1,23 @@ +// Copyright (c) 2016 The CEF Python authors. All rights reserved. + +#pragma once + +#define STR_(x) #x +#define STR(x) STR_(x) + +#if defined(_WIN32) + #define OS_WIN 1 + #define OS_LINUX 0 + #define OS_MAC 0 + #define OS_POSTFIX "win" +#elif defined(__linux__) + #define OS_WIN 0 + #define OS_LINUX 1 + #define OS_MAC 0 + #define OS_POSTFIX "linux" +#elif defined(__APPLE__) + #define OS_WIN 0 + #define OS_LINUX 0 + #define OS_MAC 1 + #define OS_POSTFIX "mac" +#endif diff --git a/cefpython/version/cefpython_version.h b/cefpython/version/cefpython_version.h new file mode 100644 index 000000000..d548540e5 --- /dev/null +++ b/cefpython/version/cefpython_version.h @@ -0,0 +1,32 @@ +// Copyright (c) 2016 The CEF Python authors. All rights reserved. + +// The cef_version_win.h and other platform dependent headers +// come from CEF binary distributions. These header files are +// generated by CEF during builds. + +#pragma once + +#include "base.h" +#include "cef_version_" OS_POSTFIX ".h" + +#define CEFPYTHON_VERSION_MAJOR 47 +#define CEFPYTHON_VERSION_MINOR 0 +#define CEFPYTHON_VERSION \ + STR(CEFPYTHON_VERSION_MAJOR) "." \ + STR(CEFPYTHON_VERSION_MINOR) + +// @todo: overwrite during build +// Possible values: "stable", "rc", "alpha" +#define CEFPYTHON_RELEASE_TYPE + +// @todo: overwrite during build +#define CEFPYTHON_COMMIT_NUMBER +#define CEFPYTHON_COMMIT_HASH +#define CEFPYTHON_COMMIT_SHORT + +#define CHROME_VERSION \ + STR(CHROME_VERSION_MAJOR) "." \ + STR(CHROME_VERSION_MINOR) "." \ + STR(CHROME_VERSION_BUILD) "." \ + STR(CHROME_VERSION_PATCH) +#define CHROMIUM_VERSION CHROME_VERSION diff --git a/patches/Build-CEF-with-patches.md b/patches/Build-CEF-with-patches.md new file mode 100644 index 000000000..a6dd132d9 --- /dev/null +++ b/patches/Build-CEF-with-patches.md @@ -0,0 +1,46 @@ +# Build CEF with the cefpython patches applied + +CEF Python official binaries come with custom CEF binaries +with a few patches applied for our use case. + +On Linux before running any CEF tools apply the issue73 patch +first. + +To build CEF follow the instructions on the Branches and +Building CEF wiki page: +https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding + +Use the automate-git.py tool, for example: +``` +mkdir chromium && cd chromium +python automate-git.py --download-dir=./ --branch=2526 --no-debug-build --verbose-build --build-log-file +``` + +After it is built apply patches and rebuild: +``` +cd chromium/src +ninja -v -j2 -Cout\Release cefclient +``` + +## How to patch + +Create a patch from unstaged changes in current directory: +``` +cd chromium/src/cef/ +git diff > cef.gyp.patch +``` + +Apply a patch in current directory: +``` +cd chromium/src/cef/ +git apply cef.gyp.patch +``` + +## Ninja build slowing down computer + +If ninja slows down your computer too much, build manually with +this command (where -j2 means to run 2 jobs in parallel) +``` +cd chromium/src +ninja -v -j2 -Cout\Release cefclient +``` diff --git a/patches/issue125_win_linux_mac/PATCH.md b/patches/issue125_win_linux_mac/PATCH.md new file mode 100644 index 000000000..b296c63af --- /dev/null +++ b/patches/issue125_win_linux_mac/PATCH.md @@ -0,0 +1,6 @@ +Patch to fix HTTPS cache problems on pages with certificate errors: +https://github.com/cztomczak/cefpython/issues/125 + +Apply the patch in the "chromium/src/" directory. +Modifications are made to the HttpCache::Transaction:: +WriteResponseInfoToEntry function. diff --git a/patches/issue125_win_linux_mac/http_cache_transaction.cc.patch b/patches/issue125_win_linux_mac/http_cache_transaction.cc.patch new file mode 100644 index 000000000..76622a995 --- /dev/null +++ b/patches/issue125_win_linux_mac/http_cache_transaction.cc.patch @@ -0,0 +1,14 @@ +Index: net/http/http_cache_transaction.cc +=================================================================== +--- http_cache_transaction.cc (revision 241641) ++++ http_cache_transaction.cc (working copy) +@@ -2240,7 +2240,8 @@ + // reverse-map the cert status to a net error and replay the net error. + if ((cache_->mode() != RECORD && + response_.headers->HasHeaderValue("cache-control", "no-store")) || +- net::IsCertStatusError(response_.ssl_info.cert_status)) { ++ (!cache_->GetSession()->params().ignore_certificate_errors && ++ net::IsCertStatusError(response_.ssl_info.cert_status))) { + DoneWritingToEntry(false); + ReportCacheActionFinish(); + if (net_log_.IsLoggingAllEvents()) \ No newline at end of file diff --git a/patches/issue218_linux/PATCH.md b/patches/issue218_linux/PATCH.md new file mode 100644 index 000000000..28640c1e9 --- /dev/null +++ b/patches/issue218_linux/PATCH.md @@ -0,0 +1,7 @@ +Fixes to the CEF GTK implementation on Linux: +https://github.com/cztomczak/cefpython/issues/218 + +Apply the patch in the `~/chromium/src/cef/` directory. + +Modifications are made to the CefBrowserHostImpl:: +PlatformCreateWindow function. diff --git a/patches/issue218_linux/browser_host_impl_gtk.cc.patch b/patches/issue218_linux/browser_host_impl_gtk.cc.patch new file mode 100644 index 000000000..a910792fa --- /dev/null +++ b/patches/issue218_linux/browser_host_impl_gtk.cc.patch @@ -0,0 +1,58 @@ +Index: libcef/browser/browser_host_impl_gtk.cc +=================================================================== +--- browser_host_impl_gtk.cc (revision 1639) ++++ browser_host_impl_gtk.cc (working copy) +@@ -273,8 +273,43 @@ + + // Parent the TabContents to the browser window. + window_info_.widget = web_contents_->GetView()->GetNativeView(); +- gtk_container_add(GTK_CONTAINER(window_info_.parent_widget), +- window_info_.widget); ++ if (GTK_IS_BOX(window_info_.parent_widget)) { ++ gtk_box_pack_start(GTK_BOX(window_info_.parent_widget), ++ window_info_.widget, TRUE, TRUE, 0); ++ } else { ++ // Parent view shouldn't contain any children, but in wxWidgets library ++ // there will be GtkPizza widget for Panel or any other control. ++ GList *children, *iter; ++ children = gtk_container_get_children(GTK_CONTAINER( ++ window_info_.parent_widget)); ++ GtkWidget* child = NULL; ++ GtkWidget* vbox = gtk_vbox_new(FALSE, 0); ++ for (iter = children; iter != NULL; iter = g_list_next(iter)) { ++ child = GTK_WIDGET(iter->data); ++ // We will have to keep a reference to that child that we remove, ++ // otherwise we will get lots of warnings like "invalid unclassed ++ // pointer in cast to `GtkPizza'". First we increase a reference, ++ // we need to do this for a moment before we add this child to the ++ // vbox, then we will decrease that reference. ++ g_object_ref(G_OBJECT(child)); ++ gtk_container_remove(GTK_CONTAINER(window_info_.parent_widget), child); ++ } ++ g_list_free(children); ++ gtk_box_pack_start(GTK_BOX(vbox), window_info_.widget, TRUE, TRUE, 0); ++ if (child != NULL) { ++ // This child is packed to the box only so that its reference lives, ++ // as it might be referenced from other code thus resulting in errors. ++ gtk_box_pack_end(GTK_BOX(vbox), child, FALSE, FALSE, 0); ++ gtk_widget_hide(GTK_WIDGET(child)); ++ g_object_unref(G_OBJECT(child)); ++ } ++ gtk_widget_show(GTK_WIDGET(vbox)); ++ if (GTK_IS_SCROLLED_WINDOW(window_info_.parent_widget)) ++ gtk_scrolled_window_add_with_viewport( ++ GTK_SCROLLED_WINDOW(window_info_.parent_widget), vbox); ++ else ++ gtk_container_add(GTK_CONTAINER(window_info_.parent_widget), vbox); ++ } + + g_signal_connect(G_OBJECT(window_info_.widget), "destroy", + G_CALLBACK(browser_destroy), this); +@@ -293,6 +328,8 @@ + prefs->inactive_selection_bg_color = SkColorSetRGB(200, 200, 200); + prefs->inactive_selection_fg_color = SkColorSetRGB(50, 50, 50); + ++ gtk_widget_show_all(GTK_WIDGET(window_info_.widget)); ++ + return true; + } \ No newline at end of file diff --git a/patches/issue73_linux/PATCH.md b/patches/issue73_linux/PATCH.md new file mode 100644 index 000000000..979320f0d --- /dev/null +++ b/patches/issue73_linux/PATCH.md @@ -0,0 +1,8 @@ +Patch to fix tcmalloc issue on Linux: +https://github.com/cztomczak/cefpython/issues/73 + +You have two options: +1. Copy `include.gypi` to `~/.gyp/`. +2. Or run the `use_allocator_none.sh` script - this will set + the GYP_DEFINES env variable, but it will last only for + current session. diff --git a/patches/issue73_linux/include.gypi b/patches/issue73_linux/include.gypi new file mode 100644 index 000000000..a5869aebb --- /dev/null +++ b/patches/issue73_linux/include.gypi @@ -0,0 +1,5 @@ +{ + 'variables': { + 'use_allocator': 'none', + }, +} \ No newline at end of file diff --git a/patches/issue73_linux/use_allocator_none.sh b/patches/issue73_linux/use_allocator_none.sh new file mode 100644 index 000000000..d9dfc6550 --- /dev/null +++ b/patches/issue73_linux/use_allocator_none.sh @@ -0,0 +1 @@ +export GYP_DEFINES="use_allocator=none" diff --git a/tools/automate.py b/tools/automate.py index e69de29bb..61a413490 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -0,0 +1,7 @@ +"""An equivalent for automate-git.py in upstream CEF. + +This tool will allow to: +1. Build cefpython using prepared CEF binaries. +2. Build CEF from sources with the cefpython patches + applied and then build cefpython. +""" diff --git a/tools/build.py b/tools/build.py index 3c1393baf..7f608abcb 100644 --- a/tools/build.py +++ b/tools/build.py @@ -2,4 +2,7 @@ @TODO: check Cython version, it should be exact - read it from requirements.txt + +If you would like to build CEF from sources see the +automate.py script or the patches/ directory. """ From 2a47413a6c64ca67d6f492e85e20ebebda2c678e Mon Sep 17 00:00:00 2001 From: cztomczak Date: Thu, 25 Feb 2016 19:56:03 +0100 Subject: [PATCH 003/557] automate.py and patches. Not yet working. --- patches/Build-CEF-with-patches.md | 39 +- patches/issue125_win_linux_mac/PATCH.md | 5 +- .../http_cache_transaction.cc.patch | 26 +- patches/issue218_linux/PATCH.md | 6 +- patches/issue73_linux/PATCH.md | 8 +- patches/issue73_linux/use_allocator_none.sh | 1 - tools/automate-git.py | 1057 +++++++++++++++++ tools/automate-git.py.patch | 0 tools/automate.py | 268 ++++- tools/requirements.txt | 2 +- 10 files changed, 1361 insertions(+), 51 deletions(-) delete mode 100644 patches/issue73_linux/use_allocator_none.sh create mode 100644 tools/automate-git.py create mode 100644 tools/automate-git.py.patch diff --git a/patches/Build-CEF-with-patches.md b/patches/Build-CEF-with-patches.md index a6dd132d9..aef91a8d9 100644 --- a/patches/Build-CEF-with-patches.md +++ b/patches/Build-CEF-with-patches.md @@ -1,45 +1,48 @@ # Build CEF with the cefpython patches applied +Use tools/automate.py with the --build-cef flag to build CEF +in an automated way with patches in this directory applied. + + +# Build manually + CEF Python official binaries come with custom CEF binaries with a few patches applied for our use case. -On Linux before running any CEF tools apply the issue73 patch +On Linux before running any of CEF tools apply the issue73 patch first. To build CEF follow the instructions on the Branches and Building CEF wiki page: https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding -Use the automate-git.py tool, for example: -``` -mkdir chromium && cd chromium -python automate-git.py --download-dir=./ --branch=2526 --no-debug-build --verbose-build --build-log-file -``` +After it is successfully built - apply patches, rebuild and remake +distribs. + +Note that CEF patches must be applied in the +"download_dir/chromium/src/cef/" directory, not in the "download_dir/cef/" +directory. -After it is built apply patches and rebuild: -``` -cd chromium/src -ninja -v -j2 -Cout\Release cefclient -``` ## How to patch -Create a patch from unstaged changes in current directory: +Apply a patch in current directory: ``` cd chromium/src/cef/ -git diff > cef.gyp.patch +git apply cef.gyp.patch ``` -Apply a patch in current directory: +Create a patch from unstaged changes in current directory: ``` cd chromium/src/cef/ -git apply cef.gyp.patch +git diff --relative > cef.gyp.patch ``` -## Ninja build slowing down computer -If ninja slows down your computer too much, build manually with -this command (where -j2 means to run 2 jobs in parallel) +## Ninja build slows down computer + +If ninja slows down your computer too much (6 parallel jobs by default), +build manually with this command (where -j2 means to run 2 jobs in parallel): ``` cd chromium/src ninja -v -j2 -Cout\Release cefclient diff --git a/patches/issue125_win_linux_mac/PATCH.md b/patches/issue125_win_linux_mac/PATCH.md index b296c63af..1c6c6121d 100644 --- a/patches/issue125_win_linux_mac/PATCH.md +++ b/patches/issue125_win_linux_mac/PATCH.md @@ -1,6 +1,5 @@ -Patch to fix HTTPS cache problems on pages with certificate errors: +Patch to Chromium. Fixes HTTPS cache problems on sites with certificate errors: https://github.com/cztomczak/cefpython/issues/125 Apply the patch in the "chromium/src/" directory. -Modifications are made to the HttpCache::Transaction:: -WriteResponseInfoToEntry function. +It modifies WriteResponseInfoToEntry(). diff --git a/patches/issue125_win_linux_mac/http_cache_transaction.cc.patch b/patches/issue125_win_linux_mac/http_cache_transaction.cc.patch index 76622a995..24628bf8a 100644 --- a/patches/issue125_win_linux_mac/http_cache_transaction.cc.patch +++ b/patches/issue125_win_linux_mac/http_cache_transaction.cc.patch @@ -1,14 +1,14 @@ -Index: net/http/http_cache_transaction.cc -=================================================================== ---- http_cache_transaction.cc (revision 241641) -+++ http_cache_transaction.cc (working copy) -@@ -2240,7 +2240,8 @@ - // reverse-map the cert status to a net error and replay the net error. - if ((cache_->mode() != RECORD && - response_.headers->HasHeaderValue("cache-control", "no-store")) || -- net::IsCertStatusError(response_.ssl_info.cert_status)) { -+ (!cache_->GetSession()->params().ignore_certificate_errors && -+ net::IsCertStatusError(response_.ssl_info.cert_status))) { +diff --git a/http_cache_transaction.cc b/http_cache_transaction.cc +index 9dd8458..e61f1f0 100644 +--- a/http_cache_transaction.cc ++++ b/http_cache_transaction.cc +@@ -2661,7 +2661,8 @@ int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { + // blocking page is shown. An alternative would be to reverse-map the cert + // status to a net error and replay the net error. + if ((response_.headers->HasHeaderValue("cache-control", "no-store")) || +- IsCertStatusError(response_.ssl_info.cert_status)) { ++ (!cache_->GetSession()->params().ignore_certificate_errors && ++ IsCertStatusError(response_.ssl_info.cert_status))) { DoneWritingToEntry(false); - ReportCacheActionFinish(); - if (net_log_.IsLoggingAllEvents()) \ No newline at end of file + if (net_log_.IsCapturing()) + net_log_.EndEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); diff --git a/patches/issue218_linux/PATCH.md b/patches/issue218_linux/PATCH.md index 28640c1e9..b29641008 100644 --- a/patches/issue218_linux/PATCH.md +++ b/patches/issue218_linux/PATCH.md @@ -1,7 +1,5 @@ -Fixes to the CEF GTK implementation on Linux: +Patch to CEF. Fixes GTK/wxPython issues on Linux: https://github.com/cztomczak/cefpython/issues/218 Apply the patch in the `~/chromium/src/cef/` directory. - -Modifications are made to the CefBrowserHostImpl:: -PlatformCreateWindow function. +It modifies PlatformCreateWindow(). diff --git a/patches/issue73_linux/PATCH.md b/patches/issue73_linux/PATCH.md index 979320f0d..ba91a6f41 100644 --- a/patches/issue73_linux/PATCH.md +++ b/patches/issue73_linux/PATCH.md @@ -1,8 +1,4 @@ -Patch to fix tcmalloc issue on Linux: +Patch to CEF. Fixes tcmalloc issue on Linux: https://github.com/cztomczak/cefpython/issues/73 -You have two options: -1. Copy `include.gypi` to `~/.gyp/`. -2. Or run the `use_allocator_none.sh` script - this will set - the GYP_DEFINES env variable, but it will last only for - current session. +Copy the "include.gypi" file to "~/.gyp/". diff --git a/patches/issue73_linux/use_allocator_none.sh b/patches/issue73_linux/use_allocator_none.sh deleted file mode 100644 index d9dfc6550..000000000 --- a/patches/issue73_linux/use_allocator_none.sh +++ /dev/null @@ -1 +0,0 @@ -export GYP_DEFINES="use_allocator=none" diff --git a/tools/automate-git.py b/tools/automate-git.py new file mode 100644 index 000000000..b970a6ea1 --- /dev/null +++ b/tools/automate-git.py @@ -0,0 +1,1057 @@ +""" This is a modified copy of automate-git.py from upstream CEF. + +Some modifications were applied for CEF Python specific use case. +There is a patch file with the same name as this script that contains +differences from the original file. + +Usage: automate-git.py [options] + + This utility implements automation for the download, update, build and +distribution of CEF. + +Options: + -h, --help show this help message and exit + --download-dir=DIR Download directory with no spaces [required]. + --depot-tools-dir=DIR + Download directory for depot_tools. + --depot-tools-archive=DEPOTTOOLSARCHIVE + Zip archive file that contains a single top-level + depot_tools directory. + --branch=BRANCH Branch of CEF to build (trunk, 1916, ...). This will + be used to name the CEF download directory and to + identify the correct URL if --url is not specified. + The default value is trunk. + --url=URL CEF download URL. If not specified the default URL + will be used. + --chromium-url=CHROMIUMURL + Chromium download URL. If not specified the default + URL will be used. + --checkout=CHECKOUT Version of CEF to checkout. If not specified the most + recent remote version of the branch will be used. + --chromium-checkout=CHROMIUMCHECKOUT + Version of Chromium to checkout (Git branch/hash/tag). + This overrides the value specified by CEF in + CHROMIUM_BUILD_COMPATIBILITY.txt. + --force-config Force creation of a new gclient config file. + --force-clean Force a clean checkout of Chromium and CEF. This will + trigger a new update, build and distribution. + --force-clean-deps Force a clean checkout of Chromium dependencies. Used + in combination with --force-clean. + --dry-run Output commands without executing them. + --dry-run-platform=DRYRUNPLATFORM + Simulate a dry run on the specified platform (windows, + macosx, linux). Must be used in combination with the + --dry-run flag. + --force-update Force a Chromium and CEF update. This will trigger a + new build and distribution. + --no-update Do not update Chromium or CEF. Pass --force-build or + --force-distrib if you desire a new build or + distribution. + --no-cef-update Do not update CEF. Pass --force-build or --force- + distrib if you desire a new build or distribution. + --no-chromium-update Do not update Chromium. + --no-depot-tools-update + Do not update depot_tools. + --force-build Force CEF debug and release builds. This builds + cefclient on all platforms and chrome_sandbox on + Linux. + --no-build Do not build CEF. + --build-tests Also build the cef_unittests target. + --no-debug-build Don't perform the CEF debug build. + --no-release-build Don't perform the CEF release build. + --verbose-build Show all command lines while building. + --build-log-file Write build logs to file. The file will be named + "build-[branch]-[debug|release].log" in the download + directory. + --x64-build Build for 64-bit systems (Windows and Mac OS X only). + --force-distrib Force creation of a CEF binary distribution. + --no-distrib Don't create a CEF binary distribution. + --minimal-distrib Create a minimal CEF binary distribution. + --minimal-distrib-only + Create a minimal CEF binary distribution only. + --client-distrib Create a client CEF binary distribution. + --client-distrib-only + Create a client CEF binary distribution only. + --no-distrib-docs Don't create CEF documentation. + --no-distrib-archive Don't create archives for output directories. + --clean-artifacts Clean the artifacts output directory. + --distrib-subdir=DISTRIBSUBDIR + CEF distrib dir name, child of + chromium/src/cef/binary_distrib +""" + +# Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +from optparse import OptionParser +import os +import shlex +import shutil +import subprocess +import sys +import tempfile +import urllib +import zipfile + +## +# Default URLs. +## + +depot_tools_url = 'https://chromium.googlesource.com/chromium/tools/depot_tools.git' +depot_tools_archive_url = 'https://src.chromium.org/svn/trunk/tools/depot_tools.zip' + +cef_git_url = 'https://bitbucket.org/chromiumembedded/cef.git' + + +## +# Global system variables. +## + +# Script directory. +script_dir = os.path.dirname(__file__) + + +## +# Helper functions. +## + +def msg(message): + """ Output a message. """ + sys.stdout.write('--> ' + message + "\n") + +def run(command_line, working_dir, depot_tools_dir=None, output_file=None): + """ Runs the specified command. """ + # add depot_tools to the path + env = os.environ + if not depot_tools_dir is None: + env['PATH'] = depot_tools_dir+os.pathsep+env['PATH'] + + sys.stdout.write('-------- Running "'+command_line+'" in "'+\ + working_dir+'"...'+"\n") + if not options.dryrun: + args = shlex.split(command_line.replace('\\', '\\\\')) + + if not output_file: + return subprocess.check_call(args, cwd=working_dir, env=env, + shell=(sys.platform == 'win32')) + with open(output_file, "w") as f: + return subprocess.check_call(args, cwd=working_dir, env=env, + shell=(sys.platform == 'win32'), + stderr=subprocess.STDOUT, stdout=f) + +def create_directory(path): + """ Creates a directory if it doesn't already exist. """ + if not os.path.exists(path): + msg("Creating directory %s" % (path)); + if not options.dryrun: + os.makedirs(path) + +def delete_directory(path): + """ Removes an existing directory. """ + if os.path.exists(path): + msg("Removing directory %s" % (path)); + if not options.dryrun: + shutil.rmtree(path, onerror=onerror) + +def copy_directory(source, target, allow_overwrite=False): + """ Copies a directory from source to target. """ + if not options.dryrun and os.path.exists(target): + if not allow_overwrite: + raise Exception("Directory %s already exists" % (target)) + remove_directory(target) + if os.path.exists(source): + msg("Copying directory %s to %s" % (source, target)); + if not options.dryrun: + shutil.copytree(source, target) + +def move_directory(source, target, allow_overwrite=False): + """ Copies a directory from source to target. """ + if not options.dryrun and os.path.exists(target): + if not allow_overwrite: + raise Exception("Directory %s already exists" % (target)) + remove_directory(target) + if os.path.exists(source): + msg("Moving directory %s to %s" % (source, target)); + if not options.dryrun: + shutil.move(source, target) + +def is_git_checkout(path): + """ Returns true if the path represents a git checkout. """ + return os.path.exists(os.path.join(path, '.git')) + +def exec_cmd(cmd, path): + """ Execute the specified command and return the result. """ + out = '' + err = '' + sys.stdout.write("-------- Running \"%s\" in \"%s\"...\n" % (cmd, path)) + parts = cmd.split() + try: + process = subprocess.Popen(parts, cwd=path, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=(sys.platform == 'win32')) + out, err = process.communicate() + except IOError, (errno, strerror): + raise + except: + raise + return {'out': out, 'err': err} + +def get_git_hash(path, branch): + """ Returns the git hash for the specified branch/tag/hash. """ + cmd = "%s rev-parse %s" % (git_exe, branch) + result = exec_cmd(cmd, path) + if result['out'] != '': + return result['out'].strip() + return 'Unknown' + +def get_git_url(path): + """ Returns the origin url for the specified path. """ + cmd = "%s config --get remote.origin.url" % (git_exe) + result = exec_cmd(cmd, path) + if result['out'] != '': + return result['out'].strip() + return 'Unknown' + +def download_and_extract(src, target, contents_prefix): + """ Extracts the contents of src, which may be a URL or local file, to the + target directory. """ + temporary = False + + if src[:4] == 'http': + # Attempt to download a URL. + opener = urllib.FancyURLopener({}) + response = opener.open(src) + + temporary = True + handle, archive_path = tempfile.mkstemp(suffix = '.zip') + os.write(handle, response.read()) + os.close(handle) + elif os.path.exists(src): + # Use a local file. + archive_path = src + else: + raise Exception('Path type is unsupported or does not exist: ' + src) + + if not zipfile.is_zipfile(archive_path): + raise Exception('Not a valid zip archive: ' + src) + + def remove_prefix(zip, prefix): + offset = len(prefix) + for zipinfo in zip.infolist(): + name = zipinfo.filename + if len(name) > offset and name[:offset] == prefix: + zipinfo.filename = name[offset:] + yield zipinfo + + # Attempt to extract the archive file. + try: + os.makedirs(target) + zf = zipfile.ZipFile(archive_path, 'r') + zf.extractall(target, remove_prefix(zf, contents_prefix)) + except: + shutil.rmtree(target, onerror=onerror) + raise + zf.close() + + # Delete the archive file if temporary. + if temporary and os.path.exists(archive_path): + os.remove(archive_path) + +def read_config_file(path): + """ Read a configuration file. """ + if os.path.exists(path): + fp = open(path, 'r') + data = fp.read() + fp.close() + else: + raise Exception("Path does not exist: %s" % (path)) + + # Parse the contents. + return eval(data, {'__builtins__': None}, None) + +def write_config_file(path, contents): + """ Write a configuration file. """ + msg('Writing file: %s' % path) + if not options.dryrun: + fp = open(path, 'w') + fp.write("{\n") + for key in sorted(contents.keys()): + fp.write(" '%s': '%s',\n" % (key, contents[key])) + fp.write("}\n") + fp.close() + +def read_branch_config_file(path): + """ Read the CEF branch from the specified path. """ + config_file = os.path.join(path, 'cef.branch') + if os.path.isfile(config_file): + contents = read_config_file(config_file) + if 'branch' in contents: + return contents['branch'] + return '' + +def write_branch_config_file(path, branch): + """ Write the CEF branch to the specified path. """ + config_file = os.path.join(path, 'cef.branch') + if not os.path.isfile(config_file): + write_config_file(config_file, {'branch': branch}) + +def remove_deps_entry(path, entry): + """ Remove an entry from the Chromium DEPS file at the specified path. """ + msg('Updating DEPS file: %s' % path) + if not options.dryrun: + # Read the DEPS file. + fp = open(path, 'r') + lines = fp.readlines() + fp.close() + + # Write the DEPS file. + # Each entry takes 2 lines. Skip both lines if found. + fp = open(path, 'w') + skip_next = False + for line in lines: + if skip_next: + skip_next = False + continue + elif line.find(entry) >= 0: + skip_next = True + continue + fp.write(line) + fp.close() + +def apply_deps_patch(): + """ Patch the Chromium DEPS file if necessary. """ + # Starting with 43.0.2357.126 the DEPS file is now 100% Git and the .DEPS.git + # file is no longer created. Look for the older file first in case we're + # building an older branch version. + deps_file = '.DEPS.git' + deps_path = os.path.join(chromium_src_dir, deps_file) + if not os.path.isfile(deps_path): + deps_file = 'DEPS' + deps_path = os.path.join(chromium_src_dir, deps_file) + + if os.path.isfile(deps_path): + msg("Chromium DEPS file: %s" % (deps_path)) + patch_file = os.path.join(cef_dir, 'patch', 'patches', deps_file + '.patch') + if os.path.exists(patch_file): + # Attempt to apply the DEPS patch file that may exist with newer branches. + patch_tool = os.path.join(cef_dir, 'tools', 'patcher.py') + run('%s %s --patch-file "%s" --patch-dir "%s"' % + (python_exe, patch_tool, patch_file, chromium_src_dir), + chromium_src_dir, depot_tools_dir) + elif cef_branch != 'trunk' and int(cef_branch) <= 1916: + # Release branch DEPS files older than 37.0.2007.0 may include a 'src' + # entry. This entry needs to be removed otherwise `gclient sync` will + # fail. + remove_deps_entry(deps_path, "'src'") + else: + raise Exception("Path does not exist: %s" % (deps_path)) + +def onerror(func, path, exc_info): + """ + Error handler for ``shutil.rmtree``. + + If the error is due to an access error (read only file) + it attempts to add write permission and then retries. + + If the error is for another reason it re-raises the error. + + Usage : ``shutil.rmtree(path, onerror=onerror)`` + """ + import stat + if not os.access(path, os.W_OK): + # Is the error an access error ? + os.chmod(path, stat.S_IWUSR) + func(path) + else: + raise + + +## +# Program entry point. +## + +# Cannot be loaded as a module. +if __name__ != "__main__": + sys.stderr.write('This file cannot be loaded as a module!') + sys.exit() + +# Parse command-line options. +disc = """ +This utility implements automation for the download, update, build and +distribution of CEF. +""" + +parser = OptionParser(description=disc) + +# Setup options. +parser.add_option('--download-dir', dest='downloaddir', metavar='DIR', + help='Download directory with no spaces [required].') +parser.add_option('--depot-tools-dir', dest='depottoolsdir', metavar='DIR', + help='Download directory for depot_tools.', default='') +parser.add_option('--depot-tools-archive', dest='depottoolsarchive', + help='Zip archive file that contains a single top-level '+\ + 'depot_tools directory.', default='') +parser.add_option('--branch', dest='branch', + help='Branch of CEF to build (trunk, 1916, ...). This '+\ + 'will be used to name the CEF download directory and '+\ + 'to identify the correct URL if --url is not '+\ + 'specified. The default value is trunk.', + default='trunk') +parser.add_option('--url', dest='url', + help='CEF download URL. If not specified the default URL '+\ + 'will be used.', + default='') +parser.add_option('--chromium-url', dest='chromiumurl', + help='Chromium download URL. If not specified the default '+\ + 'URL will be used.', + default='') +parser.add_option('--checkout', dest='checkout', + help='Version of CEF to checkout. If not specified the '+\ + 'most recent remote version of the branch will be used.', + default='') +parser.add_option('--chromium-checkout', dest='chromiumcheckout', + help='Version of Chromium to checkout (Git '+\ + 'branch/hash/tag). This overrides the value specified '+\ + 'by CEF in CHROMIUM_BUILD_COMPATIBILITY.txt.', + default='') + +# Miscellaneous options. +parser.add_option('--force-config', + action='store_true', dest='forceconfig', default=False, + help='Force creation of a new gclient config file.') +parser.add_option('--force-clean', + action='store_true', dest='forceclean', default=False, + help='Force a clean checkout of Chromium and CEF. This will'+\ + ' trigger a new update, build and distribution.') +parser.add_option('--force-clean-deps', + action='store_true', dest='forcecleandeps', default=False, + help='Force a clean checkout of Chromium dependencies. Used'+\ + ' in combination with --force-clean.') +parser.add_option('--dry-run', + action='store_true', dest='dryrun', default=False, + help="Output commands without executing them.") +parser.add_option('--dry-run-platform', dest='dryrunplatform', default=None, + help='Simulate a dry run on the specified platform '+\ + '(windows, macosx, linux). Must be used in combination'+\ + ' with the --dry-run flag.') + +# Update-related options. +parser.add_option('--force-update', + action='store_true', dest='forceupdate', default=False, + help='Force a Chromium and CEF update. This will trigger a '+\ + 'new build and distribution.') +parser.add_option('--no-update', + action='store_true', dest='noupdate', default=False, + help='Do not update Chromium or CEF. Pass --force-build or '+\ + '--force-distrib if you desire a new build or '+\ + 'distribution.') +parser.add_option('--no-cef-update', + action='store_true', dest='nocefupdate', default=False, + help='Do not update CEF. Pass --force-build or '+\ + '--force-distrib if you desire a new build or '+\ + 'distribution.') +parser.add_option('--no-chromium-update', + action='store_true', dest='nochromiumupdate', default=False, + help='Do not update Chromium.') +parser.add_option('--no-depot-tools-update', + action='store_true', dest='nodepottoolsupdate', default=False, + help='Do not update depot_tools.') + +# Build-related options. +parser.add_option('--force-build', + action='store_true', dest='forcebuild', default=False, + help='Force CEF debug and release builds. This builds '+\ + 'cefclient on all platforms and chrome_sandbox on '+\ + 'Linux.') +parser.add_option('--no-build', + action='store_true', dest='nobuild', default=False, + help='Do not build CEF.') +parser.add_option('--build-tests', + action='store_true', dest='buildtests', default=False, + help='Also build the cef_unittests target.') +parser.add_option('--no-debug-build', + action='store_true', dest='nodebugbuild', default=False, + help="Don't perform the CEF debug build.") +parser.add_option('--no-release-build', + action='store_true', dest='noreleasebuild', default=False, + help="Don't perform the CEF release build.") +parser.add_option('--verbose-build', + action='store_true', dest='verbosebuild', default=False, + help='Show all command lines while building.') +parser.add_option('--build-log-file', + action='store_true', dest='buildlogfile', default=False, + help='Write build logs to file. The file will be named '+\ + '"build-[branch]-[debug|release].log" in the download '+\ + 'directory.') +parser.add_option('--x64-build', + action='store_true', dest='x64build', default=False, + help='Build for 64-bit systems (Windows and Mac OS X only).') + +# Distribution-related options. +parser.add_option('--force-distrib', + action='store_true', dest='forcedistrib', default=False, + help='Force creation of a CEF binary distribution.') +parser.add_option('--no-distrib', + action='store_true', dest='nodistrib', default=False, + help="Don't create a CEF binary distribution.") +parser.add_option('--minimal-distrib', + action='store_true', dest='minimaldistrib', default=False, + help='Create a minimal CEF binary distribution.') +parser.add_option('--minimal-distrib-only', + action='store_true', dest='minimaldistribonly', default=False, + help='Create a minimal CEF binary distribution only.') +parser.add_option('--client-distrib', + action='store_true', dest='clientdistrib', default=False, + help='Create a client CEF binary distribution.') +parser.add_option('--client-distrib-only', + action='store_true', dest='clientdistribonly', default=False, + help='Create a client CEF binary distribution only.') +parser.add_option('--no-distrib-docs', + action='store_true', dest='nodistribdocs', default=False, + help="Don't create CEF documentation.") +parser.add_option('--no-distrib-archive', + action='store_true', dest='nodistribarchive', default=False, + help="Don't create archives for output directories.") +parser.add_option('--clean-artifacts', + action='store_true', dest='cleanartifacts', default=False, + help='Clean the artifacts output directory.') +parser.add_option('--distrib-subdir', dest='distribsubdir', + help='CEF distrib dir name, child of '+\ + 'chromium/src/cef/binary_distrib', + default='') + +(options, args) = parser.parse_args() + +if options.downloaddir is None: + print "The --download-dir option is required." + parser.print_help(sys.stderr) + sys.exit() + +# Opt into component-specific flags for later use. +if options.noupdate: + options.nocefupdate = True + options.nochromiumupdate = True + options.nodepottoolsupdate = True + +if (options.nochromiumupdate and options.forceupdate) or \ + (options.nocefupdate and options.forceupdate) or \ + (options.nobuild and options.forcebuild) or \ + (options.nodistrib and options.forcedistrib): + print "Invalid combination of options." + parser.print_help(sys.stderr) + sys.exit() + +if (options.noreleasebuild and \ + (options.minimaldistrib or options.minimaldistribonly or \ + options.clientdistrib or options.clientdistribonly)) or \ + (options.minimaldistribonly and options.clientdistribonly): + print 'Invalid combination of options.' + parser.print_help(sys.stderr) + sys.exit() + +# Operating system. +if options.dryrun and options.dryrunplatform is not None: + platform = options.dryrunplatform + if not platform in ['windows', 'macosx', 'linux']: + print 'Invalid dry-run-platform value: %s' % (platform) + sys.exit() +elif sys.platform == 'win32': + platform = 'windows' +elif sys.platform == 'darwin': + platform = 'macosx' +elif sys.platform.startswith('linux'): + platform = 'linux' +else: + print 'Unknown operating system platform' + sys.exit() + +# Script extension. +if platform == 'windows': + script_ext = '.bat' +else: + script_ext = '.sh' + +if options.x64build and platform != 'windows' and platform != 'macosx': + print 'The x64 build option is only used on Windows and Mac OS X.' + sys.exit() + +if platform == 'windows' and not 'GYP_MSVS_VERSION' in os.environ.keys(): + print 'You must set the GYP_MSVS_VERSION environment variable on Windows.' + sys.exit() + +# CEF branch. +if options.branch != 'trunk' and not options.branch.isdigit(): + print 'Invalid branch value: %s' % (options.branch) +cef_branch = options.branch + +if cef_branch != 'trunk' and int(cef_branch) <= 1453: + print 'The requested branch is too old to build using this tool' + sys.exit() + +# True if the requested branch is 2272 or newer. +branch_is_2272_or_newer = (cef_branch == 'trunk' or int(cef_branch) >= 2272) + +# True if the requested branch is 2357 or newer. +branch_is_2357_or_newer = (cef_branch == 'trunk' or int(cef_branch) >= 2357) + +# Starting with 43.0.2357.126 the DEPS file is now 100% Git and the .DEPS.git +# file is no longer created. +if branch_is_2357_or_newer: + deps_file = 'DEPS' +else: + deps_file = '.DEPS.git' + +if platform == 'macosx' and not options.x64build and branch_is_2272_or_newer: + print '32-bit Mac OS X builds are no longer supported with 2272 branch and '+\ + 'newer. Add --x64-build flag to generate a 64-bit build.' + sys.exit() + +# True if GYP_DEFINES=target_arch=x64 must be set. +gyp_needs_target_arch_x64 = options.x64build and \ + (platform == 'windows' or \ + (platform == 'macosx' and not branch_is_2272_or_newer)) + +# Options that force the sources to change. +force_change = options.forceclean or options.forceupdate + +if platform == 'windows': + # Avoid errors when the "vs_toolchain.py update" Chromium hook runs. + os.environ['DEPOT_TOOLS_WIN_TOOLCHAIN'] = '0' + + +## +# Manage the download directory. +## + +# Create the download directory if necessary. +download_dir = os.path.abspath(options.downloaddir) +create_directory(download_dir) + +msg("Download Directory: %s" % (download_dir)) + + +## +# Manage the depot_tools directory. +## + +# Check if the depot_tools directory exists. +if options.depottoolsdir != '': + depot_tools_dir = os.path.abspath(options.depottoolsdir) +else: + depot_tools_dir = os.path.join(download_dir, 'depot_tools') + +msg("Depot Tools Directory: %s" % (depot_tools_dir)) + +if not os.path.exists(depot_tools_dir): + if platform == 'windows' and options.depottoolsarchive == '': + # On Windows download depot_tools as an archive file since we can't assume + # that git is already installed. + options.depottoolsarchive = depot_tools_archive_url + + if options.depottoolsarchive != '': + # Extract depot_tools from an archive file. + msg('Extracting %s to %s.' % \ + (options.depottoolsarchive, depot_tools_dir)) + if not options.dryrun: + download_and_extract(options.depottoolsarchive, depot_tools_dir, \ + 'depot_tools/') + else: + # On Linux and OS X check out depot_tools using Git. + run('git clone '+depot_tools_url+' '+depot_tools_dir, download_dir) + +if not options.nodepottoolsupdate: + # Update depot_tools. + # On Windows this will download required python and git binaries. + msg('Updating depot_tools') + if platform == 'windows': + run('update_depot_tools.bat', depot_tools_dir, depot_tools_dir); + else: + run('update_depot_tools', depot_tools_dir, depot_tools_dir); + +# Determine the executables to use. +if platform == 'windows': + # Force use of the version bundled with depot_tools. + git_exe = os.path.join(depot_tools_dir, 'git.bat') + python_exe = os.path.join(depot_tools_dir, 'python.bat') + if options.dryrun and not os.path.exists(git_exe): + sys.stdout.write("WARNING: --dry-run assumes that depot_tools" \ + " is already in your PATH. If it isn't\nplease" \ + " specify a --depot-tools-dir value.\n") + git_exe = 'git.bat' + python_exe = 'python.bat' +else: + git_exe = 'git' + python_exe = 'python' + + +## +# Manage the cef directory. +## + +cef_dir = os.path.join(download_dir, 'cef') + +# Delete the existing CEF directory if requested. +if options.forceclean and os.path.exists(cef_dir): + delete_directory(cef_dir) + +# Determine the type of CEF checkout to use. +if os.path.exists(cef_dir) and not is_git_checkout(cef_dir): + raise Exception("Not a valid CEF Git checkout: %s" % (cef_dir)) + +# Determine the CEF download URL to use. +if options.url == '': + cef_url = cef_git_url +else: + cef_url = options.url + +# Verify that the requested CEF URL matches the existing checkout. +if not options.nocefupdate and os.path.exists(cef_dir): + cef_existing_url = get_git_url(cef_dir) + if cef_url != cef_existing_url: + raise Exception( + 'Requested CEF checkout URL %s does not match existing URL %s' % + (cef_url, cef_existing_url)) + +msg("CEF Branch: %s" % (cef_branch)) +msg("CEF URL: %s" % (cef_url)) +msg("CEF Source Directory: %s" % (cef_dir)) + +# Determine the CEF Git branch to use. +if options.checkout == '': + # Target the most recent branch commit from the remote repo. + if cef_branch == 'trunk': + cef_checkout = 'origin/master' + else: + cef_checkout = 'origin/' + cef_branch +else: + cef_checkout = options.checkout + +# Create the CEF checkout if necessary. +if not options.nocefupdate and not os.path.exists(cef_dir): + cef_checkout_new = True + run('%s clone %s %s' % (git_exe, cef_url, cef_dir), download_dir, \ + depot_tools_dir) +else: + cef_checkout_new = False + +# Update the CEF checkout if necessary. +if not options.nocefupdate and os.path.exists(cef_dir): + cef_current_hash = get_git_hash(cef_dir, 'HEAD') + + if not cef_checkout_new: + # Fetch new sources. + run('%s fetch' % (git_exe), cef_dir, depot_tools_dir) + + cef_desired_hash = get_git_hash(cef_dir, cef_checkout) + cef_checkout_changed = cef_checkout_new or force_change or \ + cef_current_hash != cef_desired_hash + + msg("CEF Current Checkout: %s" % (cef_current_hash)) + msg("CEF Desired Checkout: %s (%s)" % (cef_desired_hash, cef_checkout)) + + if cef_checkout_changed: + # Checkout the requested branch. + run('%s checkout %s%s' % + (git_exe, ('--force ' if options.forceclean else ''), cef_checkout), \ + cef_dir, depot_tools_dir) +else: + cef_checkout_changed = False + + +## +# Manage the out directory. +## + +out_dir = os.path.join(download_dir, 'out_' + cef_branch) + +# Delete the existing out directory if requested. +if options.forceclean and os.path.exists(out_dir): + delete_directory(out_dir) + +msg("CEF Output Directory: %s" % (out_dir)) + + +## +# Manage the chromium directory. +## + +# Create the chromium directory if necessary. +chromium_dir = os.path.join(download_dir, 'chromium') +create_directory(chromium_dir) + +chromium_src_dir = os.path.join(chromium_dir, 'src') +cef_src_dir = os.path.join(chromium_src_dir, 'cef') +out_src_dir = os.path.join(chromium_src_dir, 'out') + +if options.chromiumurl != '': + chromium_url = options.chromiumurl; +else: + chromium_url = 'https://chromium.googlesource.com/chromium/src.git' + +# Create gclient configuration file. +gclient_file = os.path.join(chromium_dir, '.gclient') +if not os.path.exists(gclient_file) or options.forceconfig: + # Exclude unnecessary directories. Intentionally written without newlines. + gclient_spec = \ + "solutions = [{"+\ + "u'managed': False,"+\ + "u'name': u'src', "+\ + "u'url': u'" + chromium_url + "', "+\ + "u'custom_deps': {"+\ + "u'build': None, "+\ + "u'build/scripts/command_wrapper/bin': None, "+\ + "u'build/scripts/gsd_generate_index': None, "+\ + "u'build/scripts/private/data/reliability': None, "+\ + "u'build/scripts/tools/deps2git': None, "+\ + "u'build/third_party/lighttpd': None, "+\ + "u'commit-queue': None, "+\ + "u'depot_tools': None, "+\ + "u'src/chrome_frame/tools/test/reference_build/chrome': None, "+\ + "u'src/chrome/tools/test/reference_build/chrome_linux': None, "+\ + "u'src/chrome/tools/test/reference_build/chrome_mac': None, "+\ + "u'src/chrome/tools/test/reference_build/chrome_win': None, "+\ + "}, "+\ + "u'deps_file': u'" + deps_file + "', "+\ + "u'safesync_url': u''"+\ + "}]" + + msg('Writing file: %s' % gclient_file) + if not options.dryrun: + fp = open(gclient_file, 'w') + fp.write(gclient_spec) + fp.close() + +# Initial Chromium checkout. +if not options.nochromiumupdate and not os.path.exists(chromium_src_dir): + chromium_checkout_new = True + run("gclient sync --nohooks --with_branch_heads --jobs 16", chromium_dir, \ + depot_tools_dir) +else: + chromium_checkout_new = False + +# Verify the Chromium checkout. +if not options.dryrun and not is_git_checkout(chromium_src_dir): + raise Exception('Not a valid git checkout: %s' % (chromium_src_dir)) + +if os.path.exists(chromium_src_dir): + msg("Chromium URL: %s" % (get_git_url(chromium_src_dir))) + +# Determine the Chromium checkout options required by CEF. +if options.chromiumcheckout == '': + # Read the build compatibility file to identify the checkout name. + compat_path = os.path.join(cef_dir, 'CHROMIUM_BUILD_COMPATIBILITY.txt') + config = read_config_file(compat_path) + + if 'chromium_checkout' in config: + chromium_checkout = config['chromium_checkout'] + else: + raise Exception("Missing chromium_checkout value in %s" % (compat_path)) +else: + chromium_checkout = options.chromiumcheckout + +# Determine if the Chromium checkout needs to change. +if not options.nochromiumupdate and os.path.exists(chromium_src_dir): + chromium_current_hash = get_git_hash(chromium_src_dir, 'HEAD') + chromium_desired_hash = get_git_hash(chromium_src_dir, chromium_checkout) + chromium_checkout_changed = chromium_checkout_new or force_change or \ + chromium_current_hash != chromium_desired_hash + + msg("Chromium Current Checkout: %s" % (chromium_current_hash)) + msg("Chromium Desired Checkout: %s (%s)" % \ + (chromium_desired_hash, chromium_checkout)) +else: + chromium_checkout_changed = options.dryrun + +# Delete the existing src/cef directory. It will be re-copied from the download +# directory later. +if cef_checkout_changed and os.path.exists(cef_src_dir): + delete_directory(cef_src_dir) + +# Delete the existing src/out directory if requested. +if options.forceclean and os.path.exists(out_src_dir): + delete_directory(out_src_dir) + +# Move the existing src/out directory to the correct location in the download +# directory. It will be moved back from the download directory later. +if os.path.exists(out_src_dir): + old_branch = read_branch_config_file(out_src_dir) + if old_branch != '' and (chromium_checkout_changed or \ + old_branch != cef_branch): + old_out_dir = os.path.join(download_dir, 'out_' + old_branch) + move_directory(out_src_dir, old_out_dir) + +# Update the Chromium checkout. +if chromium_checkout_changed: + if not chromium_checkout_new: + if options.forceclean and options.forcecleandeps: + # Remove all local changes including third-party git checkouts managed by + # gclient. + run("%s clean -dffx" % (git_exe), chromium_src_dir, depot_tools_dir) + else: + # Revert all changes in the Chromium checkout. + run("gclient revert --nohooks", chromium_dir, depot_tools_dir) + + # Fetch new sources. + run("%s fetch" % (git_exe), chromium_src_dir, depot_tools_dir) + # Also fetch tags, which are required for release branch builds. + run("%s fetch --tags" % (git_exe), chromium_src_dir, depot_tools_dir) + + # Checkout the requested branch. + run("%s checkout %s%s" % \ + (git_exe, ('--force ' if options.forceclean else ''), chromium_checkout), \ + chromium_src_dir, depot_tools_dir) + + # Patch the Chromium DEPS file if necessary. + apply_deps_patch() + + # Set the GYP_CHROMIUM_NO_ACTION value temporarily so that `gclient sync` does + # not run gyp. + os.environ['GYP_CHROMIUM_NO_ACTION'] = '1' + + # Update third-party dependencies including branch/tag information. + run("gclient sync %s--with_branch_heads --jobs 16" % \ + (('--reset ' if options.forceclean else '')), \ + chromium_dir, depot_tools_dir) + + # Clear the GYP_CHROMIUM_NO_ACTION value. + del os.environ['GYP_CHROMIUM_NO_ACTION'] + + # Delete the src/out directory created by `gclient sync`. + delete_directory(out_src_dir) + +# Restore the src/cef directory. +if os.path.exists(cef_dir) and not os.path.exists(cef_src_dir): + copy_directory(cef_dir, cef_src_dir) + +# Restore the src/out directory. +out_src_dir_exists = os.path.exists(out_src_dir) +if os.path.exists(out_dir) and not out_src_dir_exists: + move_directory(out_dir, out_src_dir) + out_src_dir_exists = True +elif not out_src_dir_exists: + create_directory(out_src_dir) + +# Write the config file for identifying the branch. +write_branch_config_file(out_src_dir, cef_branch) + + +## +# Build CEF. +## + +if not options.nobuild and (chromium_checkout_changed or \ + cef_checkout_changed or options.forcebuild or \ + not out_src_dir_exists): + # Building should also force a distribution. + options.forcedistrib = True + + # Set GYP environment variables. + os.environ['GYP_GENERATORS'] = 'ninja' + if gyp_needs_target_arch_x64: + if 'GYP_DEFINES' in os.environ.keys(): + os.environ['GYP_DEFINES'] = os.environ['GYP_DEFINES'] + ' ' + \ + 'target_arch=x64' + else: + os.environ['GYP_DEFINES'] = 'target_arch=x64' + + # Print all build-related environment variables including any that were set + # previously. + for key in os.environ.keys(): + if key.startswith('GYP_') or key.startswith('DEPOT_TOOLS_'): + msg('%s=%s' % (key, os.environ[key])) + + # Run the cef_create_projects script to generate project files. + path = os.path.join(cef_src_dir, 'cef_create_projects'+script_ext) + run(path, cef_src_dir, depot_tools_dir) + + # Build using Ninja. + command = 'ninja -C ' + if options.verbosebuild: + command = 'ninja -v -C' + target = ' cefclient' + if options.buildtests: + target = target + ' cef_unittests' + if platform == 'linux': + target = target + ' chrome_sandbox' + build_dir_suffix = '' + if platform == 'windows' and options.x64build: + build_dir_suffix = '_x64' + + if not options.nodebugbuild: + # Make a CEF Debug build. + run(command + os.path.join('out', 'Debug' + build_dir_suffix) + target, \ + chromium_src_dir, depot_tools_dir, + os.path.join(download_dir, 'build-%s-debug.log' % (cef_branch)) \ + if options.buildlogfile else None) + + if not options.noreleasebuild: + # Make a CEF Release build. + run(command + os.path.join('out', 'Release' + build_dir_suffix) + target, \ + chromium_src_dir, depot_tools_dir, + os.path.join(download_dir, 'build-%s-release.log' % (cef_branch)) \ + if options.buildlogfile else None) + +elif not options.nobuild: + msg('Not building. The source hashes have not changed and ' + + 'the output folder "%s" already exists' % (out_src_dir)) + + +## +# Create the CEF binary distribution. +## + +if not options.nodistrib and (chromium_checkout_changed or \ + cef_checkout_changed or options.forcedistrib): + if not options.forceclean and options.cleanartifacts: + # Clean the artifacts output directory. + artifacts_path = os.path.join(cef_src_dir, 'binary_distrib') + delete_directory(artifacts_path) + + # Determine the requested distribution types. + distrib_types = [] + if options.minimaldistribonly: + distrib_types.append('minimal') + elif options.clientdistribonly: + distrib_types.append('client') + else: + distrib_types.append('standard') + if options.minimaldistrib: + distrib_types.append('minimal') + if options.clientdistrib: + distrib_types.append('client') + + cef_tools_dir = os.path.join(cef_src_dir, 'tools') + + # Create the requested distribution types. + first_type = True + for type in distrib_types: + path = os.path.join(cef_tools_dir, 'make_distrib'+script_ext) + if options.nodebugbuild or options.noreleasebuild or type != 'standard': + path = path + ' --allow-partial' + path = path + ' --ninja-build' + if options.x64build: + path = path + ' --x64-build' + + if type == 'minimal': + path = path + ' --minimal' + elif type == 'client': + path = path + ' --client' + + if first_type: + if options.nodistribdocs: + path = path + ' --no-docs' + if options.nodistribarchive: + path = path + ' --no-archive' + first_type = False + else: + # Don't create the symbol archives or documentation more than once. + path = path + ' --no-symbols --no-docs' + + # Override the subdirectory name of binary_distrib if the caller requested. + if options.distribsubdir != '': + path = path + ' --distrib-subdir=' + options.distribsubdir + + # Create the distribution. + run(path, cef_tools_dir, depot_tools_dir) diff --git a/tools/automate-git.py.patch b/tools/automate-git.py.patch new file mode 100644 index 000000000..e69de29bb diff --git a/tools/automate.py b/tools/automate.py index 61a413490..0f5747621 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -1,7 +1,265 @@ -"""An equivalent for automate-git.py in upstream CEF. +# Copyright (c) 2016 The CEF Python authors. All rights reserved. + +"""Build cefpython. Use prebuilt CEF binaries or build CEF from sources. + +Usage: + automate.py (--prebuilt-cef | --build-cef) + [--cef-branch BRANCH] [--cef-commit COMMIT] + [--build-dir BUILDDIR] [--cef-build-dir CEFBUILDDIR] + [--gyp-generators ] + [--gyp-msvs-version <2013>] + automate.py (-h | --help) [type -h to show full description for options] + + +Options: + -h --help Show this help message. + --prebuilt-cef Whether to use prebuilt CEF binaries. Prebuilt + binaries for Linux are build on Debian/Ubuntu. + --build-cef Whether to build CEF from sources with the cefpython + patches applied. + --cef-branch CEF branch. Defaults to CHROME_VERSION_BUILD from + "cefpython/version/cef_version_{platform}.h". + --cef-commit CEF revision. Defaults to CEF_COMMIT_HASH from + "cefpython/version/cef_version_{platform}.h". + --build-dir Build directory. + --cef-build-dir CEF build directory. By default same as --build-dir. + --gyp-generators Set GYP_GENERATORS [default: ninja,msvs-ninja]. + --gyp-msvs-version Set GYP_MSVS_VERSION [default: 2013]. + +""" + +# @TODO: -j2 +# cd chromium/src +# ninja -v -j2 -Cout\Release cefclient + +import os +import sys +import shlex +import subprocess +import platform +import docopt +import struct +import re + +# CONSTANTS +ARCH32 = (8 * struct.calcsize('P') == 32) +ARCH64 = (8 * struct.calcsize('P') == 64) +OS_POSTFIX = ("win" if platform.system() == "Windows" else + "linux" if platform.system() == "Linux" else + "mac" if platform.system() == "Darwin" else "unknown") + + +class Options(object): + """Options populated from command-line plus internal options.""" + + # From command-line + prebuilt_cef = False + build_cef = False + cef_branch = "" + cef_commit = "" + build_dir = "" + cef_build_dir = "" + gyp_generators = "" + gyp_msvs_version = "" + + # Other options + depot_tools_dir = "" + tools_dir = "" + cefpython_dir = "" + + @staticmethod + def setup(docopt_args): + """Setup options.""" + Options.populate_attrs(docopt_args) + + Options.tools_dir = os.path.dirname(os.path.realpath(__file__)) + Options.cefpython_dir = os.path.dirname(Options.tools_dir) + + # --build-dir + if Options.build_dir: + Options.build_dir = os.path.realpath(Options.build_dir) + else: + Options.build_dir = os.path.join(Options.cefpython_dir, "build") + + # --cef-build-dir + if Options.cef_build_dir: + Options.cef_build_dir = os.path.realpath(Options.cef_build_dir) + else: + Options.cef_build_dir = Options.build_dir + + # --depot-tools-dir + Options.depot_tools_dir = os.path.join(Options.cef_build_dir, + "depot_tools") + + @staticmethod + def populate_attrs(docopt_args): + """Populate this object attributes using command line arguments.""" + usage = __doc__ + for key in docopt_args: + value = docopt_args[key] + if key.startswith("--"): + match = re.search(r"\[%s\s+([^\]]+)\]" % (re.escape(key),), + usage) + if match: + arg_key = match.group(1) + value = docopt_args[arg_key] + key2 = key.replace("--", "").replace("-", "_") + setattr(Options, key2, value) + + +def main(): + """Main entry point.""" + Options.setup(docopt.docopt(__doc__)) + + if Options.prebuilt_cef: + PrebuiltCEF() + elif Options.build_cef: + BuildCEF() + + +class Run(object): + """Run commands: python, git, etc.""" + + def getenv(self): + """Env variables passed to shell when running commands.""" + # GYP_GENERATORS + # GYP_MSVS_VERSION + env = os.environ + env["PATH"] = Options.depot_tools_dir + os.pathsep + env["PATH"] + env["GYP_GENERATORS"] = Options.gyp_generators + env["GYP_MSVS_VERSION"] = Options.gyp_msvs_version + # Issue73 patch applied here. + env["GYP_DEFINES"] = "use_allocator=none" + return env + + def command(self, command_line, working_dir): + """Run command in a given directory with env variables set.""" + print("[automate.py] Running '"+command_line+"' in '" + + working_dir+"'...") + args = shlex.split(command_line.replace("\\", "\\\\")) + return subprocess.check_call(args, cwd=working_dir, env=self.getenv(), + shell=(platform.system() == "Windows")) + + def python(self, command_line, working_dir): + """Run python script using depot_tools.""" + if platform.system() == "Windows": + python = os.path.join(Options.depot_tools_dir, "python.bat") + else: + python = "python" + return self.command("%s %s" % (python, command_line), working_dir) + + def git(self, command_line, working_dir): + """Run git command using depot_tools.""" + if platform.system() == "Windows": + git = os.path.join(Options.depot_tools_dir, "git.bat") + else: + git = "git" + return self.command("%s %s" % (git, command_line), working_dir) + + def automate_git(self, command_line): + """Run CEF automate-git.py.""" + script = os.path.join(Options.cef_build_dir, "cef", "automate-git.py") + args = [ + "--download-dir", Options.cef_build_dir, + ] + # args... @TODO + """C:\chromium>call python automate-git.py --download-dir=./test/ + --branch=2526 --no-debug-build --verbose-build + --no-cef-update --no-chromium-update --no-build""" + if ARCH64: + args.append("--x64-build") + args = " ".join(args) + return self.python(script+" "+args+" "+command_line, + Options.cef_build_dir) + + +class Version(object): + """Which CEF version to use: branch and commit.""" + header_file = "" + + def get_branch(self): + """Get CEF branch from cmd-line or from the 'cefpython/version/' + dir. """ + if Options.cef_branch: + return Options.cef_branch + contents = self.get_header_file_contents() + match = re.match(r"#define CHROME_VERSION_BUILD (\d+)", contents) + if not match: + print("[automate.py] CHROME_VERSION_BUILD not found in " + + self.header_file) + sys.exit(1) + return match.group(1) + + def get_commit(self): + """Get CEF commit from cmd-line or from the 'cefpython/version' + dir. """ + if Options.cef_commit: + return Options.cef_commit + contents = self.get_header_file_contents() + match = re.match(r"#define CEF_COMMIT_HASH \"(\w+)\"", contents) + if not match: + print("[automate.py] CEF_COMMIT_HASH not found in " + + self.header_file) + sys.exit(1) + return match.group(1) + + def get_header_file_contents(self): + """Get platform specific header file contents with version info.""" + self.header_file = os.path.join(Options.cefpython_dir, "cefpython", + "version", "cef_version_" + + OS_POSTFIX+".h") + with open(self.header_file, "rU") as fp: + contents = fp.read() + return contents + + +class PrebuiltCEF(object): + """Download CEF prebuilt binaries from GitHub Releases, + eg tag 'upstream-cef47'.""" + pass + + +class BuildCEF(object): + """Build CEF """ + pass + + +class Download(object): + """Download operations: file downloads, git clones.""" + + def depot_tools(self): + """depot_tools comes with Python and Git on Windows.""" + pass + + def cef_sources(self): + """Download CEF sources and checkout specific branch and commit.""" + pass + + def prebuilt_cef(self): + """Download CEF prebuilt binaries.""" + pass + + +class Patches(object): + """CEF python patches are in the 'cefpython/patches/ directory. """ + + def apply_all(self): + """Apply 'cefpython/patches/' to Chromium and/or CEF sources.""" + # Issue73 is applied in Run.getenv() by setting appropriate env var. + pass + -This tool will allow to: -1. Build cefpython using prepared CEF binaries. -2. Build CEF from sources with the cefpython patches - applied and then build cefpython. """ +def download_chromium_sources(): + pass +def create_cef_projects(): + pass +def ninja_build_cefclient(): + pass +def make_cef_distrib(): + pass +""" + + +if __name__ == "__main__": + main() diff --git a/tools/requirements.txt b/tools/requirements.txt index 0e79a3bb2..eabcc789f 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -1,2 +1,2 @@ -defopt >= 1.0.1 +docopt >= 0.6.2 cython == 0.19.2 From 200ef00bddc8071ba163447d6a201247e411fabc Mon Sep 17 00:00:00 2001 From: cztomczak Date: Fri, 26 Feb 2016 16:02:25 +0100 Subject: [PATCH 004/557] Added tools/toc.py to generate TOC for .md files (Issue #217) --- tools/doctoc.py | 0 tools/toc.py | 155 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) delete mode 100644 tools/doctoc.py create mode 100644 tools/toc.py diff --git a/tools/doctoc.py b/tools/doctoc.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tools/toc.py b/tools/toc.py new file mode 100644 index 000000000..96d75d330 --- /dev/null +++ b/tools/toc.py @@ -0,0 +1,155 @@ +# Copyright (c) 2016 The CEF Python Authors. All rights reserved. + +"""Create Table of contents (TOC) for a single .md file or for a directory. + +Usage: + toc.py FILE + toc.py DIR +""" + +import os +import sys +import re +import glob + + +def main(): + """Main entry point.""" + if (len(sys.argv) == 1 or + "-h" in sys.argv or + "--help" in sys.argv or + "/?" in sys.argv): + print(__doc__.strip()) + sys.exit(0) + arg1 = sys.argv[1] + if os.path.isdir(arg1): + (modified, warnings) = toc_dir(arg1) + if modified: + print("Done") + else: + print("No changes to TOCs. Files not modified.") + else: + (modified, warnings) = toc_file(arg1) + if modified: + print("Done") + else: + print("No changes to TOC. File not modified.") + if warnings: + print("Warnings: "+str(warnings)) + + +def toc_file(file_): + """A single file was passed to doctoc. Return bool whether modified + and the number of warnings.""" + with open(file_, "rb") as fo: + orig_contents = fo.read() + # Fix new lines just in case. Not using Python's "rU", + # it is causing strange issues. + orig_contents = re.sub(r"(\r\n|\r|\n)", os.linesep, orig_contents) + (tocsize, contents, warnings) = create_toc(orig_contents, file_) + if contents != orig_contents: + with open(file_, "wb") as fo: + fo.write(contents) + tocsize_str = ("TOC size: "+str(tocsize) if tocsize + else "TOC removed") + print("Modified: "+file_+" ("+tocsize_str+")") + return True, warnings + else: + return False, warnings + + +def toc_dir(dir_): + """A directory was passed to doctoc. Return bool whether any file was + modified and the number of warnings.""" + files = glob.glob(os.path.join(dir_, "*.md")) + modified_any = False + for file_ in files: + (modified, warnings) = toc_file(file_) + modified_any = True if modified else False + return modified_any, warnings + + +def create_toc(contents, file_): + """Create or modify TOC for the document contents.""" + match = re.search(r"Table of contents:%s(\s*\* \[[^\]]+\]\([^)]+\)%s){2,}" + % (os.linesep, os.linesep), contents) + oldtoc = match.group(0) if match else None + (tocsize, toc, warnings) = parse_headings(contents, file_) + if oldtoc: + if not toc: + # If toc removed need to remove an additional new lines + # that was inserted after toc. + contents = contents.replace(oldtoc+os.linesep, toc) + else: + contents = contents.replace(oldtoc, toc) + elif tocsize: + # Insert after H1, but if there is text directly after H1 + # then insert after that text. + first_line = False + if not re.search(r"^#\s+", contents): + print("WARNING: missing H1 on first line. Ignoring file: "+file_) + return 0, contents, warnings+1 + lines = contents.splitlines() + contents = "" + toc_inserted = False + for line in lines: + if not first_line: + first_line = True + else: + if not toc_inserted and re.search(r"^(##|###)", line): + contents = contents[0:-len(os.linesep)] + contents += toc + os.linesep + os.linesep + toc_inserted = True + contents += line + os.linesep + return tocsize, contents, warnings + + +def parse_headings(raw_contents, file_): + """Parse contents looking for headings. Return a tuple with number + of TOC elements, the TOC fragment and the number of warnings.""" + # Remove code blocks + parsable_contents = re.sub(r"```[\s\S]+?```", "", raw_contents) + # Parse H1,H2,H3 + headings = re.findall(r"^(#|##|###)\s+(.*)", parsable_contents, + re.MULTILINE) + toc = "Table of contents:" + os.linesep + tocsize = 0 + warnings = 0 + count_h1 = 0 + count_h2 = 0 + for heading in headings: + level = heading[0] + level = (1 if level == "#" else + 2 if level == "##" else + 3 if level == "###" else None) + assert level is not None + title = heading[1].strip() + if level == 1: + count_h1 += 1 + if count_h1 > 1: + warnings += 1 + print("WARNING: found more than one H1 in "+file_) + continue + if level == 2: + count_h2 += 1 + hash_ = title.lower() + hash_ = re.sub(r"[^a-z0-9- ]+", r"", hash_) + hash_ = hash_.replace(" ", "-") + hash_ = re.sub(r"[-]+", r"-", hash_) + hash_ = re.sub(r"-$", r"", hash_) + indent = "" + if level == 3: + if count_h2: + # If there was no H2 yet then H3 shouldn't have indent. + indent = " " * 2 + toc += indent + "* [%s](#%s)" % (title, hash_) + os.linesep + tocsize += 1 + if tocsize <= 1: + # If there is only one H2/H3 heading do not create TOC. + toc = "" + tocsize = 0 + return tocsize, toc, warnings + + +if __name__ == "__main__": + main() From c0af649c0cdd22b216daf5bc23d2844cf0f702c4 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 27 Feb 2016 13:28:15 +0100 Subject: [PATCH 005/557] Added Tutorial drafts that as of now just outline topics yet to be written. --- Tutorial-beginner.md | 59 ++++++++++++++++++++++++++++++++++++++++ Tutorial-intermediate.md | 52 +++++++++++++++++++++++++++++++++++ tools/README.md | 4 +-- tools/toc.py | 2 ++ 4 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 Tutorial-beginner.md create mode 100644 Tutorial-intermediate.md diff --git a/Tutorial-beginner.md b/Tutorial-beginner.md new file mode 100644 index 000000000..553237aa8 --- /dev/null +++ b/Tutorial-beginner.md @@ -0,0 +1,59 @@ +This is just a draft that outlines topics yet to be written. +TODO: see the CEF Tutorial wiki + +# Tutorial + + +## Download and install + +* download from Releases/ +* types of packages for each platform +* install from PyPI using pip (Win/Mac) + + +## Simple example using wxPython + +* paste code, most simple example loading www.google.com, + shouldn't be more than 20 lines. + +* Explain all functions from the example: + - initialize() + you can call initialize and shutdown only once + - shutdown() + - to exit cleanly + - cookies or other storage might not be saved (flushed every 30 secs) + process might freeze (XP experienced) + - messageloop + - messageloopwork + - messageloop faster, but this one allows integration into + existing message loop + +* ExceptHook in examples so that all processes are closed in + case of a python error + +* there are more examples in the examples/ directory. + + +## Settings + +* Describe a few most commonly used settings. +* Command-line switches from Chromium. +* Disable developer-tools or context menu + - application settings context menu dict. + + +## Documentation and help + +* see the api/ directory. + - API categories.md and API full index.md + will help you navigate through API. + +* knowledge base document + +* "Search this repository" to search through documentation and code + +* Try google "cef +search-phrase" + +* Forum - ask questions and report problems there, not in Issue Tracker + +* See Tutorial-intermediate. diff --git a/Tutorial-intermediate.md b/Tutorial-intermediate.md new file mode 100644 index 000000000..17f6c9271 --- /dev/null +++ b/Tutorial-intermediate.md @@ -0,0 +1,52 @@ +This is just a draft that outlines topics yet to be written. +TODO: see the CEF General Usage and Javascript Integration wikis. + +# Tutorial - intermediate + +* Read first Tutorial-beginner. + + +## Architecture + +* subprocess.exe +* browser process +* renderer process +* gpu process +* zygote on linux +* Describe browser process threads + + +## Handlers + +* What are handlers. +* Handler callbacks may be called either on UI thread or IO thread. + Use functions for posting tasks when need to access UI thread from IO thread. +* Example code how to use handlers - use base code from Tutorial-beginner. + - keyboard handler F12 devtools and F5 + - loadhandler onloadstart to insert js to all pages + - loadhandler onloadingstatechange when page completed loading + - onloaderror + + +## Javascript integration + +* how to expose function to js +* how to communicate two-way js<>python +* callbacks +* js errors handling +* example code how to use - use base code from Tutorial-beginner. + + +## Plugins + +* Load PPAPI flash plugin + - console window issue on Windows in CEF 47, possible solutions + + +## Off-screen rendering + +* Describe difference between windowed rendering and off-screen rendering. +* Panda3D and Kivy - offscreen +* The rest - windowed +* Describe render handler callbacks in kivy - how this works. + diff --git a/tools/README.md b/tools/README.md index 906b2ed70..b93ab5dfb 100644 --- a/tools/README.md +++ b/tools/README.md @@ -11,13 +11,11 @@ pip install -r requirements.txt apidocs.py - generate API docs from Cython sources automate.py - download CEF binaries, build and optionally install/run build.py - build the cefpython module -doctoc.py - generate table of contents for all .md in docs/ make_distrib.py - make distribution packages (msi, wheel, deb pkg and more) run.py - rebuild and install if changed, and run example(s) -setpython.bat - change python installation in PATH (Windows) -setpython.sh - change python installation in PATH (Linux and Mac) test_distrib.py - for all distribution packages install each of them and run unit tests and all examples +toc.py - generate Table of contents for .md files translator.py - generate code from the CEF header files unittests.py - run unit tests ``` diff --git a/tools/toc.py b/tools/toc.py index 96d75d330..30c057813 100644 --- a/tools/toc.py +++ b/tools/toc.py @@ -5,6 +5,8 @@ Usage: toc.py FILE toc.py DIR + +To ignore file when generating TOC, put an empty line just before H1. """ import os From cc2dda9ceddab41f9b65bb7b54ee5b7d485a7307 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Tue, 1 Mar 2016 10:56:20 +0100 Subject: [PATCH 006/557] Remove the docs/ dir --- docs/API.md | 45 --- docs/Audio-and-Video.md | 52 --- docs/Donations.md | 21 -- docs/Help-and-search.md | 44 --- docs/Home.md | 54 --- docs/Internal-development.md | 75 ---- docs/Javascript-errors.md | 15 - docs/Knowledge-Base.md | 52 --- docs/Plugins.md | 37 -- docs/Security.md | 13 - docs/build/Build-on-Linux.md | 417 --------------------- docs/build/Build-on-Mac.md | 131 ------- docs/build/Build-on-Windows.md | 272 -------------- docs/download/Download-CEF3-Linux.md | 63 ---- docs/download/Download-CEF3-Mac.md | 47 --- docs/download/Download-CEF3-Windows.md | 47 --- docs/handlers/DisplayHandler.md | 85 ----- docs/handlers/DownloadHandler.md | 34 -- docs/handlers/JavascriptContextHandler.md | 26 -- docs/handlers/JavascriptDialogHandler.md | 60 --- docs/handlers/KeyboardHandler.md | 72 ---- docs/handlers/LifespanHandler.md | 81 ---- docs/handlers/LoadHandler.md | 74 ---- docs/handlers/RenderHandler.md | 167 --------- docs/handlers/RequestHandler.md | 218 ----------- docs/handlers/ResourceHandler.md | 57 --- docs/misc/Architecture-and-features.md | 120 ------ docs/misc/Inno-Setup-installer.md | 3 - docs/misc/Release-notes.md | 141 ------- docs/misc/Version-numbering.md | 15 - docs/modules/cefpython.md | 195 ---------- docs/objects/Browser.md | 433 ---------------------- docs/objects/Callback.md | 13 - docs/objects/Cookie.md | 111 ------ docs/objects/CookieManager.md | 190 ---------- docs/objects/CookieVisitor.md | 17 - docs/objects/DpiAware.md | 66 ---- docs/objects/Frame.md | 232 ------------ docs/objects/JavascriptBindings.md | 111 ------ docs/objects/JavascriptCallback.md | 23 -- docs/objects/NetworkError.md | 247 ------------ docs/objects/PaintBuffer.md | 15 - docs/objects/Request.md | 315 ---------------- docs/objects/Response.md | 101 ----- docs/objects/StringVisitor.md | 13 - docs/objects/VirtualKey.md | 185 --------- docs/objects/WebPluginInfo.md | 19 - docs/objects/WebRequest.md | 99 ----- docs/objects/WebRequestClient.md | 89 ----- docs/objects/WindowInfo.md | 27 -- docs/objects/WindowUtils.md | 104 ------ docs/settings/ApplicationSettings.md | 291 --------------- docs/settings/BrowserSettings.md | 126 ------- docs/settings/CommandLineSwitches.md | 67 ---- 54 files changed, 5627 deletions(-) delete mode 100644 docs/API.md delete mode 100644 docs/Audio-and-Video.md delete mode 100644 docs/Donations.md delete mode 100644 docs/Help-and-search.md delete mode 100644 docs/Home.md delete mode 100644 docs/Internal-development.md delete mode 100644 docs/Javascript-errors.md delete mode 100644 docs/Knowledge-Base.md delete mode 100644 docs/Plugins.md delete mode 100644 docs/Security.md delete mode 100644 docs/build/Build-on-Linux.md delete mode 100644 docs/build/Build-on-Mac.md delete mode 100644 docs/build/Build-on-Windows.md delete mode 100644 docs/download/Download-CEF3-Linux.md delete mode 100644 docs/download/Download-CEF3-Mac.md delete mode 100644 docs/download/Download-CEF3-Windows.md delete mode 100644 docs/handlers/DisplayHandler.md delete mode 100644 docs/handlers/DownloadHandler.md delete mode 100644 docs/handlers/JavascriptContextHandler.md delete mode 100644 docs/handlers/JavascriptDialogHandler.md delete mode 100644 docs/handlers/KeyboardHandler.md delete mode 100644 docs/handlers/LifespanHandler.md delete mode 100644 docs/handlers/LoadHandler.md delete mode 100644 docs/handlers/RenderHandler.md delete mode 100644 docs/handlers/RequestHandler.md delete mode 100644 docs/handlers/ResourceHandler.md delete mode 100644 docs/misc/Architecture-and-features.md delete mode 100644 docs/misc/Inno-Setup-installer.md delete mode 100644 docs/misc/Release-notes.md delete mode 100644 docs/misc/Version-numbering.md delete mode 100644 docs/modules/cefpython.md delete mode 100644 docs/objects/Browser.md delete mode 100644 docs/objects/Callback.md delete mode 100644 docs/objects/Cookie.md delete mode 100644 docs/objects/CookieManager.md delete mode 100644 docs/objects/CookieVisitor.md delete mode 100644 docs/objects/DpiAware.md delete mode 100644 docs/objects/Frame.md delete mode 100644 docs/objects/JavascriptBindings.md delete mode 100644 docs/objects/JavascriptCallback.md delete mode 100644 docs/objects/NetworkError.md delete mode 100644 docs/objects/PaintBuffer.md delete mode 100644 docs/objects/Request.md delete mode 100644 docs/objects/Response.md delete mode 100644 docs/objects/StringVisitor.md delete mode 100644 docs/objects/VirtualKey.md delete mode 100644 docs/objects/WebPluginInfo.md delete mode 100644 docs/objects/WebRequest.md delete mode 100644 docs/objects/WebRequestClient.md delete mode 100644 docs/objects/WindowInfo.md delete mode 100644 docs/objects/WindowUtils.md delete mode 100644 docs/settings/ApplicationSettings.md delete mode 100644 docs/settings/BrowserSettings.md delete mode 100644 docs/settings/CommandLineSwitches.md diff --git a/docs/API.md b/docs/API.md deleted file mode 100644 index 1d5d9acd2..000000000 --- a/docs/API.md +++ /dev/null @@ -1,45 +0,0 @@ -# API - - - - -### Settings - - * [ApplicationSettings](settings/ApplicationSettings.md) dictionary - * [BrowserSettings](settings/BrowserSettings.md) dictionary - * [CommandLineSwitches](settings/CommandLineSwitches.md) dictionary - -### Objects - - * [Browser](objects/Browser.md) object - * [Callback](objects/Callback.md) object - * [Cookie](objects/Cookie.md) class - * [CookieManager](objects/CookieManager.md) class - * [DpiAware](objects/DpiAware.md) class (Win) - * [Frame](objects/Frame.md) object - * [JavascriptBindings](objects/JavascriptBindings.md) class - * [JavascriptCallback](objects/JavascriptCallback.md) object - * [PaintBuffer](objects/PaintBuffer.md) object - * [Request](objects/Request.md) class - * [Response](objects/Response.md) object - * [WebPluginInfo](objects/WebPluginInfo.md) object - * [WebRequest](objects/WebRequest.md) class - * [WindowInfo](objects/WindowInfo.md) class - * [WindowUtils](objects/WindowUtils.md) class - -### Handlers - - * [DisplayHandler](handlers/DisplayHandler.md) - * [DownloadHandler](handlers/DownloadHandler.md) - * [JavascriptContextHandler](handlers/JavascriptContextHandler.md) - * [JavascriptDialogHandler](handlers/JavascriptDialogHandler.md) - * [KeyboardHandler](handlers/KeyboardHandler.md) - * [LifespanHandler](handlers/LifespanHandler.md) - * [LoadHandler](handlers/LoadHandler.md) - * [RenderHandler](handlers/RenderHandler.md) - * [RequestHandler](handlers/RequestHandler.md) - * [ResourceHandler](handlers/ResourceHandler.md) - -### Modules - - * [cefpython](modules/cefpython.md) module diff --git a/docs/Audio-and-Video.md b/docs/Audio-and-Video.md deleted file mode 100644 index ab7c73bdd..000000000 --- a/docs/Audio-and-Video.md +++ /dev/null @@ -1,52 +0,0 @@ -# Audio and Video support - -### Preface - -CEF supports WebM & Ogg Theora video codecs. MPEG-4 & H.264 -are proprietary codecs and are not included in Chromium builds, -as there are [licensing issues](https://bitbucket.org/chromiumembedded/cef/issues/371/cannot-play-proprietary-audio-or-video): - -> Codecs like MP3 and AAC are included in Google Chrome releases but -> not Chromium builds. This is because these formats are not open and -> require licensing. Distributing these codecs with your application -> without a licensing agreement may violate the law in certain countries. -> You should discuss with a lawyer if appropriate. - -### Audio support - -Open [html5test.com](http://html5test.com/) and see the Audio section. Results as of CEF v47: - -``` -audio element Yes ✔ -Loop audio Yes ✔ -Preload in the background Yes ✔ -Web Audio API Yes ✔ -Speech Recognition Prefixed ✔ -Speech Synthesis Yes ✔ -PCM audio support Yes ✔ -AAC support No ✘ -MP3 support No ✘ -Ogg Vorbis support Yes ✔ -Ogg Opus support Yes ✔ -WebM with Vorbis support Yes ✔ -WebM with Opus support Yes ✔ -``` - -### Video support - -Open [html5test.com](http://html5test.com/) and see the Video section. Results as of CEF v47: -``` -video element Yes ✔ -Subtitles Yes ✔ -Audio track selection No ✘ -Video track selection No ✘ -Poster images Yes ✔ -Codec detection Yes ✔ -DRM support Yes ✔ -Media Source extensions Yes ✔ -MPEG-4 ASP support No ✘ -H.264 support No ✘ -Ogg Theora support Yes ✔ -WebM with VP8 support Yes ✔ -WebM with VP9 support Yes ✔ -``` diff --git a/docs/Donations.md b/docs/Donations.md deleted file mode 100644 index 8eb042381..000000000 --- a/docs/Donations.md +++ /dev/null @@ -1,21 +0,0 @@ -# Donations - -CEF Python is an open source project founded by [Czarek Tomczak](http://www.linkedin.com/in/czarektomczak) in 2012 to provide python bindings for the [Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef). If you would like to support general CEF Python development efforts by making a donation please click the Paypal "Donate" button below: - - - -At this time CEF Python is unable to accept donations that sponsor the development of specific features. If you are interested in sponsorship opportunities please contact Czarek directly. - -## Thanks - -* Thanks to the numerous individuals that made a Paypal donation: - Walter Purvis, Rokas Stupuras, Alex Rattray, Greg Kacy, Paul Korzhyk. -* Thanks to those that have donated their time through code contributions. - See the [AUTHORS.txt](../AUTHORS.txt) file. -* Many thanks to [Cyan Inc.](http://www.cyaninc.com/) for sponsoring this project, making CEF Python 3 more mature. Lots of new features were added, including javascript bindings and Linux support. -* Thanks to [Rentouch GmbH](http://www.rentouch.ch/) for sponsoring the - development of the off-screen rendering support in CEF Python 3. -* Thanks to Thomas Wusatiuk for sponsoring the development of the web - response reading features in CEF Python 3. -* Thanks to Adam Duston for donating a Macbook to aid the development - of the Mac port. diff --git a/docs/Help-and-search.md b/docs/Help-and-search.md deleted file mode 100644 index 216aedb30..000000000 --- a/docs/Help-and-search.md +++ /dev/null @@ -1,44 +0,0 @@ -Documentation and API is available on [Wiki Pages](../wiki). - -### Questions and problems - -Ask questions and report problems on the ![CEF Python Forum](https://www.google.com/images/icons/material/product/1x/groups_24dp.png) -[CEF Python Forum](https://groups.google.com/d/forum/cefpython). - -See also the [cefpython](http://stackoverflow.com/questions/tagged/cefpython) tag on StackOverflow. - -Before creating an issue in the tracker it is best to discuss it first on the Forum. When creating issue include information like: OS, Python version, library version (wxPython etc), cefpython version and say which example you're running (try to reproduce your issue with one of official cefpython examples). - -### Search - -Search through wiki pages with the ![Github](https://www.google.com/images/icons/product/chrome_web_store-24.png) [Github Wiki Search](https://github.com/linyows/github-wiki-search) plugin. - -You can find many useful information on the ![CEF Python Forum](https://www.google.com/images/icons/material/product/1x/groups_24dp.png) [CEF Python Forum](https://groups.google.com/d/forum/cefpython). - -Try searching in CEF Python issues [All Issues](https://github.com/cztomczak/cefpython/issues?utf8=%E2%9C%93&q=is%3Aissue). - -Another option for wiki search is to use Google: [**site**:github.com/cztomczak/cefpython/wiki/](https://www.google.com/search?q=site%3Agithub.com%2Fcztomczak%2Fcefpython%2Fwiki%2F&hl=en&gfe_rd=cr&gws_rd=cr). - -Try also searching upstream ![CEF Forum](https://www.google.com/images/icons/product/chrome-24.png) [CEF Forum](http://magpcss.org/ceforum/) - a valuable resource of information. - -You can search upstream CEF Issues [CEF Issues](https://bitbucket.org/chromiumembedded/cef/issues) as well. - -## Knowledge Base - -See the [Knowledge Base](KnowledgeBase) wiki page. - -## Contributing - -Not looking for help, but instead want to help? Great, read further. - -1. Subscribe to [Forum](https://groups.google.com/d/forum/cefpython) updates by setting membership settings to send Daily summaries via email - help other users solve problems. - -2. Subscribe to be notified of new [cefpython](http://stackoverflow.com/questions/tagged/cefpython) tagged questions on StackOverflow through [RSS feed](http://stackoverflow.com/feeds/tag/cefpython) or by enabling email subscritpion through [Tag Sets](http://blog.stackoverflow.com/2010/11/tag-sets-on-stack-exchange/). - -3. Anyone can edit Wiki Pages - help us improve documentation. Besides the built-in online editor you can also clone wiki locally (use git clone for [this url](https://github.com/cztomczak/cefpython.wiki.git)) and easily edit markdown pages with [Atom editor](https://atom.io/) and the [markdown-preview](https://atom.io/packages/markdown-preview) plugin (ctrl+shift+m to preview, also set live preview and split pane in settings). - -Want to do some more? Read On! - -4. See the [good first issue](https://github.com/cztomczak/cefpython/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) and [help wanted](https://github.com/cztomczak/cefpython/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) labeled issues. These are Good First Issues for anyone who knows any of: Python, Git, Unit testing, CI builds or just plain English (documentation help). No need to know obfuscated languages like Cython/C/C++ and you still can help. - -5. If you are interested in donating time to help with the CEF Python development (Cython/C/C++ skills) please see the [Internal development](InternalDevelopment) wiki page. diff --git a/docs/Home.md b/docs/Home.md deleted file mode 100644 index dff7c3786..000000000 --- a/docs/Home.md +++ /dev/null @@ -1,54 +0,0 @@ - - -### [Help and search](Help-and-search) - -* [Questions and problems](Help-and-search#questions-and-problems) -* [Search](Help-and-search#search) -* [Knowledge Base](KnowledgeBase) -* [Contributing](Help-and-search#contributing) - -### [API](API) - -* [Settings](API#settings) -* [Classes and objects](API#classes-and-objects) -* [Client handlers](API#client-handlers) -* [Modules](API#modules) - -### Examples - -* [Kivy](Kivy) (off-screen) -* [Panda3D](Panda3D) (off-screen) -* [PyGTK](PyGTK) -* [PyQt](PyQt) -* [PySide](PySide) -* [PyWin32](https://github.com/cztomczak/cefpython/blob/master/cefpython/cef3/windows/binaries_32bit/pywin32.py) -* [wxPython](wxPython) - -### Downloads - -* [Windows downloads](Download_CEF3_Windows) -* [Linux downloads](Download_CEF3_Linux) -* [Mac downloads](Download_CEF3_Mac) - -### Build instructions - -* [Build on Windows](BuildOnWindows) -* [Build on Linux](BuildOnLinux) -* [Build on Mac](BuildOnMac) -* [Internal development](InternalDevelopment) - -### Other pages - -* [Architecture and features](ArchitectureFeatures) -* [Plugins](Plugins) -* [Audio and Video](AudioVideo) -* [High DPI support](DpiAware) -* [Javascript errors](JavascriptErrors) -* [Security](Security) -* [Version numbering](VersionNumbering) -* [Release notes](ReleaseNotes) -* [Donations](Donations) - -TODO: move other pages to the [Knowledge Base](KnowledgeBase) wiki page, or in case of longer pages provide links to these pages on KB. - -A complete list of all wiki pages can be seen by expanding the Pages sidebar on the top to the right. \ No newline at end of file diff --git a/docs/Internal-development.md b/docs/Internal-development.md deleted file mode 100644 index 4a11c9008..000000000 --- a/docs/Internal-development.md +++ /dev/null @@ -1,75 +0,0 @@ -## Track project updates ## - -To track Git commits subscribe to this [RSS feed](../../commits/master.atom) -or just watch the project and be notified via email or GitHub site. - -## Cython IDE - -* PyCharm - https://www.jetbrains.com/pycharm/ -* LiClipse (PyDev) - http://www.liclipse.com/ -* For [Submlime Text 3](https://www.sublimetext.com/3) editor use the [Cython syntax highlighting](https://github.com/NotSqrt/sublime-cython) and [CTags](https://github.com/SublimeText/CTags) plugins. - -## Build instructions ## - -See build instructions on these wiki pages: - * [BuildOnWindows](BuildOnWindows) - * [BuildOnLinux](BuildOnLinux) - * [BuildOnMac](BuildOnMac) - -## Python/Cython style guidelines ## - - * try to comply with the [PEP 8 style guide](http://www.python.org/dev/peps/pep-0008/) - * use 4 spaces for indentation - * commit unix-style newlines (\n) - * limit all lines to a maximum of 79 characters (comments should be shorter, max 60-65 chars) - * do your best for the new code to be consistent with existing code base - -## Debug CEF stack trace ## - - 1. Install gdb with the command "sudo apt-get install gdb" - 2. Type "gdb python" - 3. Inside gdb type "run pyqt.py" - 4. On segmentation fault to display stack trace type "bt" - -## Debug Cython ## - -Debugging Cython is currently supported only on Linux. Before you can -debug you have to install the following packages: -``` -python-dbg -python-wxgtk2.8-dbg -``` - -Install Cython with the debug version of Python: -``` -cd Cython-0.19.2/ -sudo python-dbg setup.py install -``` - -To debug CEF Python add the "debug" argument to the "compile.py" script: -`python-dbg compile.py 99.99 --debug` . - -After a while you should see a GDB console awaiting a command, to run -the app type `cy run` . - -To get the stack trace type `cy backtrace` . - -The command for running and debugging script is: -`cygdb . --args python-dbg wxpython.py` . - -To run commands automatically in gdb add "-x gdb.cmds" flag. Some example -commands in gdb.cmds file: `cy run` and `quit` . - -The final command would look like: -`cygdb . -x gdb.cmds --args python-dbg wxpython.py` . - -For more commands see the "Using the debugger" section in the Cython documentation: -http://docs.cython.org/src/userguide/debugging.html#using-the-debugger - -## Updating to a newer CEF version ## - -To see changes in the CEF API compare "cefpython/include/" directory with -the new CEF "include/" directory (exclude the "capi/" directory). When -doing so compare the CEF header files downloaded directly from the CEF git -repository, as the CEF "include/" directory obtained from binary build will -not include platform specific header files. diff --git a/docs/Javascript-errors.md b/docs/Javascript-errors.md deleted file mode 100644 index 6e1c1193a..000000000 --- a/docs/Javascript-errors.md +++ /dev/null @@ -1,15 +0,0 @@ -# Javascript Errors # - -Typically when you browse a webpage your javascript errors appear in the developer tools javascript console. In cefadvanced.py example there is a binding to F12 key for opening developer tools. - -## Catching errors programmatically ## - -To catch errors programmatically implement [JavascriptContextHandler](JavascriptContextHandler).`OnUncaughtException()`. - -## Javascript bindings and callbacks ## - -When a python function is invoked from javascript and it fails, a python exception is thrown. It is written to the console and logged to the "error.log" file, then application exits. You may change this behavior by modifying `ExceptHook` function found in examples. - -A python exception might be thrown when in a context of a javascript callback. For example: javascript invokes a python function and passes a javascript callback to it, which is later called when python function finishes its job, if there is a javascript exception thrown during execution of the javascript callback, then a python exception will be thrown. - -See also [Issue 11](../issues/11) - "Throw JS / Python exceptions according to execution context". \ No newline at end of file diff --git a/docs/Knowledge-Base.md b/docs/Knowledge-Base.md deleted file mode 100644 index f8048f3b7..000000000 --- a/docs/Knowledge-Base.md +++ /dev/null @@ -1,52 +0,0 @@ -# Knowledge Base # - -## Windows XP support - -CEF Python 49.0 will be the last version to support Windows XP. This is due to Chromium/CEF dropping XP support. - -## Mac 32-bit support - -Since version 39, Chromium and Google Chrome are not available in 32-bit version for MAC OS X. - -Download cefpython 31.2 for Mac 32-bit from [Google Drive archive](https://drive.google.com/folderview?id=0B1di2XiBBfacOEM0aUFJZFU0R3c&usp=drive_web&tid=0B1di2XiBBfacOFpJb1dERGZSRnc#list). This release includes both 32-bit and 64-bit binaries. - -## Flash works in Google Chrome, but doesn't work in CEF Python - -Google Chrome bundles a proprietary version of Flash called Pepper Flash. CEF Python does not include Flash out of the box. You need to install Flash Plugin (PPAPI version) in your OS: - -1. Go to http://get.adobe.com/flashplayer/otherversions/ -2. Select an operating system -3. Select PPAPI version of plugin (for Opera and Chromium) - -NOTE: in old CEF you had to download NPAPI plugin, in newer CEF (Chrome 47 release) you need to download PPAPI plugin. - -## Black/White browser screen ## - -If you get a black or white screen then this may be caused by incompatible GPU (video card) drivers. There are following solutions to this: - -1. When CEF Python is updated to a newer Chrome version then the problem may be fixed. Check with current Google Chrome if this is the case. - -2. Try updating your video card drivers to the latest version available. - -3. You can disable GPU hardware acceleration by adding the "disable-gpu" and "disable-gpu-compositing" command line switches. See the CommandLineSwitches wiki page. Note that this will degrade performance if you're using any advanced 3D features. It will affect 2d accelerated content as well. - -Note that when web page uses WebGL then the black screen may still appear even after disabling GPU hardware acceleration. However that shouldn't be a concern as it's not supposed to work anyway. Though you may not see a nice message about WebGL not being supported. All other websites that do not use webgl will work fine. - -## Windows XP support - -On XP you should disable GPU acceleration by using the "disable-gpu" and "disable-gpu-compositing" switches. See the [Command line switches](CommandLineSwitches) wiki page. - -## Feature X works in Google Chrome, but doesn't work in CEF Python - -CEF Python embeds Chromium Embedded Framework which is based on Chromium browser. Functionality may differ a bit from Google Chrome. The browser from Google is a proprietary software that for example includes MPEG-4/H.264 codecs that aren't included in the open source Chromium. CEF also doesn't support Chrome Extensions. - -To see if some feature is working or a bug is fixed in newer CEF release perform the following steps: - -1. Go to http://www.cefbuilds.com/ -2. Choose a branch -3. Download TestApp binaries -4. Run the cefclient executable - -## How to capture Audio and Video in HTML5? - -To be able to use the getUserMedia() function you need to set the "enable-media-stream" switch. See the [Command line switches](CommandLineSwitches) wiki page. \ No newline at end of file diff --git a/docs/Plugins.md b/docs/Plugins.md deleted file mode 100644 index 81aab3967..000000000 --- a/docs/Plugins.md +++ /dev/null @@ -1,37 +0,0 @@ -# Plugins # - -CEF Python automatically loads plugins installed on your system, it works similarly to Chrome. To disable loading of plugins you have to set BrowserSettings.`plugins_disabled` to True for each browser you create. - -Both CEF 1 & CEF 3 support NPAPI plugins. CEF 3 supports also PPAPI plugins, but it is not yet fully tested. - -To see a list of plugins that are being loaded run `cefclient.exe`, a test browser that is included in cefpython binary zip, from the menu select Tests > Plugin Info. - -## Enable Flash Player ## - -To enable Flash player in CEF Python you have to install NPAPI version of Flash in your OS: - - 1. Go to http://get.adobe.com/flashplayer/otherversions/ - 1. Select your operating system - 1. Select NPAPI version of plugin (for Firefox) - -After that run cefclient.exe > Tests > Plugin Info and you should see: - -``` -Flash is installed! -Name: Shockwave Flash -Description: Shockwave Flash 11.5 r502 -Version: 11,5,502,110 -Path: C:\Windows\SysWOW64\Macromed\Flash\NPSWF32_11_5_502_110.dll -``` - -## Flash on Linux ## - -Flash plugin will crash on Linux in CEF 1, see [Issue 553 in CEF Issue Tracker](https://bitbucket.org/chromiumembedded/cef/issues/553/linux-crash-loading-flash-youtube-video). - -## Custom plugins ## - -With CEF you can load custom plugin by providing a path to it. In CEF 1 you can do this through ApplicationSettings.`extra_plugin_paths` option, but it is not yet implemented in cefpython 1. In CEF 3 there are functions `CefAddWebPluginPath()` & `CefAddWebPluginDirectory()` defined in `cef_web_plugin.h`, but it is also not yet implemented in cefpython 3. - -Google Chrome comes with an internal flash player called Pepper Flash Player (a PPAPI plugin), it can be found in `"c:\Program Files (x86)\Google\Chrome\Application\23.0.1271.91\PepperFlash"`, but to be able to distribute it with your app you need a licensing agreement in place with Adobe. - -There is an api in CEF for getting info about a plugin, the file is "include/cef\_web\_plugin.h", it is not yet implemented in cefpython. \ No newline at end of file diff --git a/docs/Security.md b/docs/Security.md deleted file mode 100644 index f39414546..000000000 --- a/docs/Security.md +++ /dev/null @@ -1,13 +0,0 @@ -# Security # - -The quote from the CEF forum regarding the security in CEF:
-http://magpcss.org/ceforum/viewtopic.php?f=10&t=10222 - -
CEF offers significant integration capabilities beyond what is offered by a standard Google Chrome browser installation. The trade off for these additional capabilities is that organizations using CEF must take responsibility for their own application security. CEF and the underlying open source projects (Chromium, WebKit, etc) involve a significant amount of code and offer no warranties. Organizations should document and follow best practices to minimize potential security risks. Here are some recommended best practices that organizations can consider:
- -
  • Only load known/trusted content. This is by far the best way to avoid potential security issues.
    -
  • Disable plugins. This will avoid a large category of security issues caused by buggy versions of Flash, Java, etc.
    -
  • Do not explicitly disable or bypass security features in your application. For example, do not enable CefBrowserSettings that bypass security features or add fake headers to bypass HTTP access control.
    -
  • Keep your application up to date with the newest CEF release branch. You may want to update the underlying Chromium release version and perform your own builds to take immediate advantage of any bug fixes.
    -
  • Enforce good programming practices. Every organization should have best practices for design, testing and verification.
    -
  • Audit your application for potential security issues. Every decision that may have security consequences should be evaluated by people who are knowledgeable about security considerations. \ No newline at end of file diff --git a/docs/build/Build-on-Linux.md b/docs/build/Build-on-Linux.md deleted file mode 100644 index d7b2c5f44..000000000 --- a/docs/build/Build-on-Linux.md +++ /dev/null @@ -1,417 +0,0 @@ -# Build instructions for Linux # - -The original instructions on building Chromium/CEF can be found on the CEF project [Branches and Building](https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding) wiki page. - -Table of contents: - - -## Preliminary notes ## - - * These instructions were tested on Ubuntu 12.04 and Python 2.7. Python 3.4 is not yet supported ([Issue 121](../issues/121)) - * The path to chromium directory should not contain any spaces - * If building on Fedora see this (4.) comment: [comment](../issues/72) - -## Using precompiled binaries from cefbuilds.com ## - -You can use precompiled binaries from [cefbuilds.com](http://cefbuilds.com/), so that it is not required to compile Chromium/CEF from sources. However this comes with some limitations, as such binaries won't have applied patches provided in the instructions on this page. There are several patches applied when building Chromium/CEF from sources: - * wxpython patch - without this patch you won't be able to run the wxpython examples. However you should be just fine running the `pygtk_.py` example. Not sure about the pyqt/pyside examples, these would need to be tested. - * tcmalloc patch - when this patch is not applied, the cefpython library must be imported the very first in application before any other libraries ([Issue 73](../issues/73)) - * https caching certificate errors patch - https caching on sites with certificate errors won't be enabled - -CEF branch and revision from cefbuilds.com must match the ones provided in the [BUILD\_COMPATIBILITY.txt](../blob/master/cefpython/cef3/BUILD_COMPATIBILITY.txt) file. For example in a file named "CEF3.1650.1639", the 1650 number is a branch and the 1639 number is a revision. See also the VersionNumbering wiki page for more details. - -When using precompiled binaries you can ignore steps on this page that refer to building Chromium/CEF that do not apply. - -## Install the necessary tools ## - -1. Make sure you have an up to date version of GIT. As of this writing syncing chromium works fine with GIT 1.7.9.5. - -``` -sudo apt-get install git -git --version -``` - -2. Install depot tools to your chromium directory (includes gclient tool that we'll be using later). - -``` -mkdir ~/chromium/ -cd ~/chromium/ -git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git -``` - -3. Add depot tools to your path for the current terminal session: - -``` -export PATH="$PATH":`pwd`/depot_tools -``` - -4. Check SVN version, it should be 1.6.x, otherwise you will get into troubles. You can install it using "`sudo apt-get install subversion`" command. - -``` -svn --version -``` - -5. Make sure you are running an up to date version of G++, as of this writing compiling works fine with G++ 4.6.3. Install it using "`sudo apt-get install g++`" command. - -``` -g++ --version -``` - -## Configure Chromium to use a specific revision ## - -1. Go open the BUILD\_COMPATIBILITY.txt file. - -For CEF 1: ../blob/master/cefpython/cef1/BUILD_COMPATIBILITY.txt - -For CEF 3: ../blob/master/cefpython/cef3/BUILD_COMPATIBILITY.txt - -Later we will need the "Chromium release url" and and the "CEF repository url" so keep it in sight. - -2. Configure Chromium to use a specific revision (through a release url) by running the "gclient config" command, the release url we will be using is from the BUILD\_COMPATIBILITY.txt file: - -``` -cd ~/chromium/ -gclient config {Chromium release url} -``` - -3. Edit the "~/chromium/.gclient" file and modify the "custom\_deps" to reduce the size of the sources to downoad: - -``` - "custom_deps": { - "src/content/test/data/layout_tests/LayoutTests": None, - "src/chrome/tools/test/reference_build/chrome_win": None, - "src/chrome_frame/tools/test/reference_build/chrome_win": None, - "src/chrome/tools/test/reference_build/chrome_linux": None, - "src/chrome/tools/test/reference_build/chrome_mac": None, - "src/third_party/hunspell_dictionaries": None, - }, -``` - -This excludes some directories that contain lots of data (many many gigabytes) that would extend the time significantly when synchronizing Chromium sources with the revision we've selected. - -## Download the Chromium sources ## - -Download the Chromium sources by running the "gclient sync" command. The Chromium sources will be updated to the revision based on the release url we've configured earlier via "gclient config". Read also the "Possible issues" section below in case you encounter errors. - -``` -cd ~/chromium/ -gclient sync --jobs 8 --force -``` - -This can take a while and sometimes it can break with some errors when a download fails. In such case you should run the "gclient sync" command once again. One of the last messages in the console should be: - -``` -Updating projects from gyp files... -``` - -#### Possible issues while running "gclient sync" #### - - * You may encounter an error while checking out the gsutil repo, fix it [by removing gsutil entries from the DEPS file](http://src.chromium.org/viewvc/chrome/releases/33.0.1750.29/DEPS?r1=245305&r2=245304&pathrev=245305). - - * If gclient sync fails with error message saying that "gmodule-2.0" / "gtk+-2.0" / "gthread-2.0" packages are missing, then you will have to run the "install-build-deps.sh" script to install the dependencies. See the next section for details on how to do that. After it's done, run the "gclient sync" command **once again**. - -## Install Chromium build dependencies ## - -1. Install build dependencies by running this script, it might ask you for the root password during installation of libraries, so you might as well run it via "sudo". - - * When it asks for the debug symbols answer "No" - * IMPORTANT: When the "ttf-mscorefonts-installer" graphical installer pops up, click `` when it displays the License file, but later **click `` when it asks to accept the EULA license terms**. If you install these fonts your font experience on websites might deteriorate in Chrome/Firefox/other browsers, as it affects not only CEF (font issues observed on Ubuntu 12.04 32bit). - -``` -cd ~/chromium/src/build/ -sudo ./install-build-deps.sh --no-chromeos-fonts -``` - -If you see the "Installation complete" or "Skipping installation of Chrome OS fonts" messages at the end then everything went well. - -2. Install also the libgtkglext1-dev package that is a dependency of the CEF off-screen rendering. - -``` -sudo apt-get update -sudo apt-get install libgtkglext1-dev -``` - -## Download the CEF sources ## - -Download the CEF sources, the repository url can be found in the BUILD\_COMPATIBILITY.txt file that was mentioned earlier. - -``` -cd ~/chromium/src/ -svn checkout {CEF repository url} cef -``` - -This will download the CEF sources to the "cef" directory. - -## Download the CEF Python sources ## - -Run the "git clone" command for the CEF Python repository. The command below will create "`~/cefpython/`" directory. - -``` -cd ~/ -git clone https://github.com/cztomczak/cefpython -``` - -## Fix the CEF GTK implementation ## - -There are a few problems with the current CEF GTK implementation. There is a bug causing the embedded CEF window to be initially hidden. Another issue is that CEF requires the container to be of type BOX (eg. GtkVBox). In wxPython apps there is even an another issue, each wx control is embraced with a `GtkPizza` window and this needs to be fixed as well. - -Apply the patch in the `"~/chromium/src/cef/`" directory. Modifications are made to the `CefBrowserHostImpl::PlatformCreateWindow` function. - -``` -Index: libcef/browser/browser_host_impl_gtk.cc -=================================================================== ---- browser_host_impl_gtk.cc (revision 1639) -+++ browser_host_impl_gtk.cc (working copy) -@@ -273,8 +273,43 @@ - - // Parent the TabContents to the browser window. - window_info_.widget = web_contents_->GetView()->GetNativeView(); -- gtk_container_add(GTK_CONTAINER(window_info_.parent_widget), -- window_info_.widget); -+ if (GTK_IS_BOX(window_info_.parent_widget)) { -+ gtk_box_pack_start(GTK_BOX(window_info_.parent_widget), -+ window_info_.widget, TRUE, TRUE, 0); -+ } else { -+ // Parent view shouldn't contain any children, but in wxWidgets library -+ // there will be GtkPizza widget for Panel or any other control. -+ GList *children, *iter; -+ children = gtk_container_get_children(GTK_CONTAINER( -+ window_info_.parent_widget)); -+ GtkWidget* child = NULL; -+ GtkWidget* vbox = gtk_vbox_new(FALSE, 0); -+ for (iter = children; iter != NULL; iter = g_list_next(iter)) { -+ child = GTK_WIDGET(iter->data); -+ // We will have to keep a reference to that child that we remove, -+ // otherwise we will get lots of warnings like "invalid unclassed -+ // pointer in cast to `GtkPizza'". First we increase a reference, -+ // we need to do this for a moment before we add this child to the -+ // vbox, then we will decrease that reference. -+ g_object_ref(G_OBJECT(child)); -+ gtk_container_remove(GTK_CONTAINER(window_info_.parent_widget), child); -+ } -+ g_list_free(children); -+ gtk_box_pack_start(GTK_BOX(vbox), window_info_.widget, TRUE, TRUE, 0); -+ if (child != NULL) { -+ // This child is packed to the box only so that its reference lives, -+ // as it might be referenced from other code thus resulting in errors. -+ gtk_box_pack_end(GTK_BOX(vbox), child, FALSE, FALSE, 0); -+ gtk_widget_hide(GTK_WIDGET(child)); -+ g_object_unref(G_OBJECT(child)); -+ } -+ gtk_widget_show(GTK_WIDGET(vbox)); -+ if (GTK_IS_SCROLLED_WINDOW(window_info_.parent_widget)) -+ gtk_scrolled_window_add_with_viewport( -+ GTK_SCROLLED_WINDOW(window_info_.parent_widget), vbox); -+ else -+ gtk_container_add(GTK_CONTAINER(window_info_.parent_widget), vbox); -+ } - - g_signal_connect(G_OBJECT(window_info_.widget), "destroy", - G_CALLBACK(browser_destroy), this); -@@ -293,6 +328,8 @@ - prefs->inactive_selection_bg_color = SkColorSetRGB(200, 200, 200); - prefs->inactive_selection_fg_color = SkColorSetRGB(50, 50, 50); - -+ gtk_widget_show_all(GTK_WIDGET(window_info_.widget)); -+ - return true; - } -``` - -### wxPython auto-focus issue ### - -In wxPython apps, this patch will remove the `GtkPizza` element, and it may cause issues with setting focus on a wx control that embeds the cef browser. However, if you click with a mouse inside the browser window, focus will work fine. It is the automatic focus that will be missing. This could probably be fixed by making a native OS call to focus the window. Although, this would require another dependency, for example this could be accomplished using the `pygtk` package. Another solution would be for cefpython to expose the GTK window focus function to WindowUtils, there are already a few GTK API functions exposed that are used by the pyqt example. - -## Fix HTTPS caching on sites with SSL certificate errors (optional) ## - -This is an optional fix. By default Chromium disables caching when there is certificate error. This patch will fix the HTTPS caching only when [ApplicationSettings](ApplicationSettings.md).ignore\_certificate\_errors is set to True. Official cefpython binaries have this fix applied, starting with the 31.0 release. See also [Issue 125](https://code.google.com/p/cefpython/issues/detail?id=125). - -Apply the patch in the "`~/chromium/src/`" directory. Modifications are made in the `HttpCache::Transaction::WriteResponseInfoToEntry` function. - -``` -Index: net/http/http_cache_transaction.cc -=================================================================== ---- http_cache_transaction.cc (revision 241641) -+++ http_cache_transaction.cc (working copy) -@@ -2240,7 +2240,8 @@ - // reverse-map the cert status to a net error and replay the net error. - if ((cache_->mode() != RECORD && - response_.headers->HasHeaderValue("cache-control", "no-store")) || -- net::IsCertStatusError(response_.ssl_info.cert_status)) { -+ (!cache_->GetSession()->params().ignore_certificate_errors && -+ net::IsCertStatusError(response_.ssl_info.cert_status))) { - DoneWritingToEntry(false); - ReportCacheActionFinish(); - if (net_log_.IsLoggingAllEvents()) -``` - -## Disable the tcmalloc memory allocation global hook (optional, but recommended) ## - -If tcmalloc hook is enabled it will cause troubles when CEF is not the very first library being imported in python scripts. In result of which you could be getting random unrelated segmentation faults all over app. See [Issue 73](https://code.google.com/p/cefpython/issues/detail?id=73) for more details. - -Official cefpython binaries have this fix applied, starting with the 31.0 release. - -To disable tcmalloc: - -1. Create the `~/.gyp/` directory and the `~/.gyp/include.gypi` file. Next edit the file and paste the following contents: - -``` -{ - 'variables': { - 'linux_use_tcmalloc': 0, - 'use_allocator': 'none', - }, -} -``` - -2. Remove the allocator dependency in the "chromium/src/cef/cef.gyp" file. Find the lines below and remove the line containing "`allocator.gyp`". There are two such lines present in this file (for win and linux), you may as well remove both of them. - -``` -[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', { - 'dependencies':[ - '<(DEPTH)/base/allocator/allocator.gyp:allocator', -``` - -## Build CEF binaries and libraries ## - -1. Generate the build files based on the GYP configuration by running the "cef\_create\_projects.sh" script. - -``` -cd ~/chromium/src/cef/ -./cef_create_projects.sh -``` - -The last message should inform about the `~/.gyp/include.gypi` being used (if you decided to disable tcmalloc hook): - -``` -Using overrides found in /home/czarek/.gyp/include.gypi -``` - -2. Build the release version of cefclient. - -``` -cd ~/chromium/src/ -make -j4 BUILDTYPE=Release cefclient -``` - -3. Create the cefclient distribution package. - -``` -cd ~/chromium/src/cef/tools/ -./make_distrib.sh --allow-partial -``` - -4. Go to the `"cef_binary_*/"` directory and build the libcef\_dll\_wrapper project and cefclient projects. - -``` -cd ~/chromium/src/cef/binary_distrib/cef_binary_* -make -j4 BUILDTYPE=Release libcef_dll_wrapper -make -j4 BUILDTYPE=Release cefclient -``` - -The succession of building the projects is important. The libcef\_dll\_wrapper project needs to be build first, before cefclient. Otherwise you will get an error message saying "make: Nothing to be done for libcef\_dll\_wrapper". - -The libcef\_dll\_wrapper project builds a static library for the C++ API of CEF. - -5. Copy the libcef\_dll\_wrapper static library to the cefpython `"lib_64bit"` directory (or 32bit). If the directory doesn't exist create one. You have to copy both the `"libcef_dll_wrapper.a"` file and the `"libcef_dll_wrapper/"` directory containing the ".o" files. - -``` -mkdir ~/cefpython/cefpython/cef3/linux/setup/lib_64bit/ -cd ~/chromium/src/cef/binary_distrib/cef_binary_*/out/Release/obj.target/ -cp -r libcef_dll_wrapper libcef_dll_wrapper.a ~/cefpython/cefpython/cef3/linux/setup/lib_64bit/ -``` - -If you've been building project previously, then remove the contents of the `"lib_64bit"` directory (or 32bit). - -6. Copy the CEF binaries to the cefpython `"binaries_64bit/"` directory (or 32bit), including the README.txt which includes some useful information about required/optional binary files and version of CEF. - -``` -cd ~/chromium/src/cef/binary_distrib/cef_binary_*/out/Release/ -cp -r locales/ files/ cefclient *.pak *.so ~/cefpython/cefpython/cef3/linux/binaries_64bit/ -cp ~/chromium/src/cef/binary_distrib/cef_binary_*/README.txt ~/cefpython/cefpython/cef3/linux/binaries_64bit/ -``` - -If you've been building project previously, then remove the contents of the `"binaries_64bit"` directory (or 32bit), but do not remove the python examples (**.py**.html) nor the LICENSE.txt file. - -The files/ directory contains test files for the cefclient (executable) sample browser. The cefclient executable is an optional binary and may be removed, though it is a good idea to keep it in case there are some issues with CEF Python. In such case reproducing the issue with cefclient is a basis for reporting the issue to upstream CEF. - -## Install Cython ## - -Download Cython 0.19.2 from PYPI: - -https://pypi.python.org/pypi/Cython/0.19.2 - -Extract it, then run "setup.py install" command via sudo: - -``` -sudo python setup.py install -``` - -## Build the CEF Python module ## - -Go to the cefpython "linux/" directory and run the "compile.py" script: - -``` -cd ~/cefpython/cefpython/cef3/linux/ -python compile.py -``` - -Building the makefiles may fail for the first time if the "setup/cefpython.h" is not up-to-date. If this happens you will be asked whether to continue, answer Yes to that. You will be prompted a few times, but don't worry just keep going. The compilation will fail, but the "setup/cefpython.h" file will be generated. Now **compile it again** by running the "python compile.py" command, it should succeed this time. - -If everything went well then the `"cefpython_py27.so"` module should be created in the `"binaries_64bit/"` directory (or 32bit) and the "wxpython.py" example should be launched. - -If you're building on OS other than Ubuntu then you may get errors about the missing header files, for example: - -``` -/usr/include/glib-2.0/glib/gtypes.h:34:24: fatal error: glibconfig.h: No such file or directory -compilation terminated. -``` - -To fix it, find the "glibconfig.h" file somewhere in the "/usr/" directory and add that directory to the includes by editing the "~/cefpython/cefpython/cef3/linux/setup/setup.py" script. Append it to the "include\_dirs" list. - -## Create a portable zip ## - -To create a portable zip just compress the files in the `"binaries_64bit/"` directory (or 32bit). - -## Create a setup package ## - -To create a setup package run the "make-setup.py" script: - -``` -cd ~/cefpython/cefpython/cef3/linux/installer/ -python make-setup.py -v 31.0 -``` - -If everything went fine then you should see a setup package created in the current directory. - -## Create a Debian package ## - -Before creating a debian package some dependencies need to be installed (stdeb version 0.6.0 required): - -``` -sudo apt-get install python-support python-pip fakeroot -sudo pip install stdeb==0.6.0 -``` - -If you were updating CEF version then you may need to generate package dependencies. It will save results to deps.txt file which later will be used by make-deb.py. - -``` -cd ~/cefpython/cefpython/cef3/linux/installer/ -python find-deps.py -``` - -After that run the "make-deb.py" script: - -``` -cd ~/cefpython/cefpython/cef3/linux/installer/ -python make-deb.py -v 31.0 -``` - -If debian package build succeeded the last two messages from the console should be: - -``` -dpkg-deb: building package `python-cefpython3' in `./python-cefpython3_31.0-1_amd64.deb'. -[make-deb.py] DONE -``` - -The debian package should be created in the `deb_archive/` directory. \ No newline at end of file diff --git a/docs/build/Build-on-Mac.md b/docs/build/Build-on-Mac.md deleted file mode 100644 index c2a9bb96c..000000000 --- a/docs/build/Build-on-Mac.md +++ /dev/null @@ -1,131 +0,0 @@ -# Build instructions for Mac # - -The original instructions on building Chromium/CEF can be found on the CEF project [Branches and Building](https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding) wiki page. - -Table of contents: - - -## Preliminary notes ## - - * These instructions were tested using: - * OS X 10.9.4 Mavericks - * Fresh install of Python 2.7.9 from python.org - * XCode 4.6.3 - * Command Line Tools for XCode, Apr 2014 - * XCode 6 is not supported by CEF (officially) - -## TODO ## - - * Fix HTTPS caching on sites with SSL certificate errors (optional) - * Disable the tcmalloc memory allocation global hook (optional, but recommended) - [Issue 155](../issues/155) - -## Prepare environment ## - -You need to set the following environment variables: - * CC=gcc - * CXX=g++ - * CEF\_CCFLAGS and ARCHFLAGS - either "-arch i386" when building 32bit or "-arch x86\_64" for 64bit - -If you're building 32bit on 64bit then: - * Create an alias python="arch -i386 python" - * Set the `CEF_CCFLAGS` and `ARCHFLAGS` env variables to `"-arch i386"` - -### An example script to prepare 32-bit environment ### - -Save it as mac32.sh and type "`source mac32.sh`". - -``` -#!/bin/bash - -PATH=/usr/local/bin:$PATH -export PATH -alias python="arch -i386 python" - -CEF_CCFLAGS="-arch i386" -export CEF_CCFLAGS - -ARCHFLAGS="-arch i386" -export ARCHFLAGS - -export CC=gcc -export CXX=g++ -``` - -### An example script to prepare 64-bit environment ### - -Save it as mac64.sh and type "`source mac64.sh`". - -``` -#!/bin/bash - -PATH=/usr/local/bin:$PATH -export PATH - -CEF_CCFLAGS="-arch x86_64" -export CEF_CCFLAGS - -ARCHFLAGS="-arch x86_64" -export ARCHFLAGS - -export CC=gcc -export CXX=g++ -``` - - -## Install Cython ## - -Download Cython 0.19.2 from PYPI. Latest versions are not supported, see [Issue 110](../issues/110). - -https://pypi.python.org/pypi/Cython/0.19.2 - -Extract it and install. Before installing make sure you have exported the CC, CXX and ARCHFLAGS environment variables. Cython compilation will fail if it tries to compile for both 32bit and 64bit, that's why it is required to set ARCHFLAGS to either 32bit or 64bit architecture. - -``` -python setup.py install -``` - -## Download CEF binaries and build cefclient ## - -Download CEF ready binaries from [cefbuilds.com](http://cefbuilds.com/). The branch and revision must match with the ones provided in the [BUILD\_COMPATIBILITY.txt](../blob/master/cefpython/cef3/BUILD_COMPATIBILITY.txt) file. - -Extract the archive. In our case this will create the `cef_binary_3.1650.1639_macosx32` directory to which we will later reference as the `cef_binary` directory. - -Open the cefclient.xcodeproj project. When using Xcode 4.2 or newer you will need to change the "Compiler for C/C++/Objective-C" setting to "LLVM GCC 4.2" under "Build Settings" for each target. - -Change build configuration to Release. From menu: Product > Scheme > Edit Scheme > Run > Build configuration: Release and OK. Click the Run button to build the project. - -If there are errors while compiling `cefclient_osr_widget_mac.mm` then fix them: - * Remove the `"(readwrite, atomic)"` string that appears before `"bool was_last_mouse_down_on_view"` - * Move the `sendScrollWheelEvet` method up in the source file before it is referenced by the `shortCircuitScrollWheelEvent` method - -Go to the `xcodebuild/Release/` directory and run `cefclient.app` to see if everything works fine. - -## Download the CEF Python sources ## - -``` -git clone https://github.com/cztomczak/cefpython -``` - -## Copy CEF binaries and libraries to the CEF Python directories ## - - * Copy "cef\_binary/xcodebuild/Release/libcef\_dll\_wrapper.a" to "cefpython/cef3/mac/setup/lib\_32bit/" - * Copy "`cef_binary/Release/*.dylib|so`" to "cefpython/cef3/mac/binaries\_32bit/" - * Copy "cef\_binary/Resources/" to "cefpython/cef3/mac/binaries\_32bit/Resources/" - -## Build the CEF Python module ## - -``` -cd cefpython/cef3/mac/ -python compile.py -``` - -## Build packages for distribution ## - -``` -cd cefpython/cef3/mac/installer/ -./build_all.sh -``` - -This should create dist/ directory with a Python Wheel package and a Distutils source package. - -If you've built the cefpython module for both 32bit and 64bit and binaries are available in both mac/binaries\_32bit/ and mac/binaries\_64bit/ directories, then the setup script will create packages with fat binaries that can run on both 32bit and 64bit. \ No newline at end of file diff --git a/docs/build/Build-on-Windows.md b/docs/build/Build-on-Windows.md deleted file mode 100644 index 69e488cb9..000000000 --- a/docs/build/Build-on-Windows.md +++ /dev/null @@ -1,272 +0,0 @@ -# Build instructions for Windows # - -The original instructions on building Chromium/CEF can be found on the CEF project [Branches and Building](https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding) wiki page. - -Table of contents: - - -## Preliminary notes ## - - * The steps of downloading and building Chromium from sources may be skipped by downloading CEF ready binaries from [cefbuilds.com](http://cefbuilds.com/). The branch and revision must match with the ones provided in the [BUILD\_COMPATIBILITY.txt](../blob/master/cefpython/cef3/BUILD_COMPATIBILITY.txt) file. - * The path to the chromium directory should not contain any spaces - * Compiling cefpython was tested with Python 2.7 / 3.2 (32bit). See [Issue 121](../issues/121) for Python 3.4 support. - * To build Chromium you will need Windows 7 64-bit or later. - * The result binaries require at least Windows XP SP3 to run. - * To build 64-bit binaries you will need VS2008 Pro. The Express edition cannot is missing the x64 platform configuration. - -## Install the Chromium tools ## - -1. See the "Build environment" section on the Chromium project site, the instructions are available for Visual Studio 2010 and for the Express edition which is free: - -(link seems no more relevant, as Chrome now officially uses VS 2013, but CEF Python probably still requires VS 2010 as it uses an older version of Chrome) - -http://www.chromium.org/developers/how-tos/build-instructions-windows#TOC-Build-environment - -You have to install Visual Studio 2010 with Service Packs and x64 compiler tools, Windows SDK and DirectX SDK. Do not install the Cygwin. - -2. Install depot\_tools: - -``` -git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git -``` - -If you do not have git installed download and extract depot\_tools from here: - -https://src.chromium.org/svn/trunk/tools/depot_tools.zip - -3. Add depot\_tools directory to your system PATH (Advanced System Settings > Environment Variables > System variables > PATH). - -4. Run the gclient once command: - -``` -gclient once -``` - -This will install git, svn and python to the depot\_tools directory. - -5. Python 2.6.2 has been installed to the depot\_tools directory that shall be used from now on by gclient and the CEF tools, if you have some other python in your system PATH then this may cause conflicts, remove it or add depot\_tools at the beginning of the system PATH. After the PATH is modified make sure you're running the python from depot tools by running the command: - -``` -python --version -``` - -It should display "Python 2.6.2". - -## Configure Chromium to use a specific revision ## - -1. Go open the BUILD\_COMPATIBILITY.txt file. - -For CEF 1: ../blob/master/cefpython/cef1/BUILD_COMPATIBILITY.txt - -For CEF 3: ../blob/master/cefpython/cef3/BUILD_COMPATIBILITY.txt - -Later we will need the "Chromium release url" and and the "CEF repository url" so keep it in sight. - -2. Create the "chromium" directory: - -``` -mkdir chromium -``` - -3. Configure Chromium to use a specific revision (through a release url) by running the "gclient config" command, the release url we will be using is from the BUILD\_COMPATIBILITY.txt file: - -``` -cd chromium/ -gclient config {Chromium release url} -``` - -4. Edit the "chromium/.gclient" and edit the "custom\_deps" to reduce the size of the sources to downoad: - -``` - "custom_deps": { - "src/content/test/data/layout_tests/LayoutTests": None, - "src/chrome/tools/test/reference_build/chrome_win": None, - "src/chrome_frame/tools/test/reference_build/chrome_win": None, - "src/chrome/tools/test/reference_build/chrome_linux": None, - "src/chrome/tools/test/reference_build/chrome_mac": None, - "src/third_party/hunspell_dictionaries": None, - }, -``` - -This excludes some directories that contain lots of data (many many gigabytes) that would extend the time significantly when synchronizing Chromium sources with the revision we've selected. - -5. Type the "svn ls" command and permanently accept the SSL certificate if it appears: - -``` -svn ls https://src.chromium.org/chrome -``` - -## Download the Chromium sources ## - -Download the Chromium sources by running the "gclient sync" command. The Chromium sources will be updated to the revision based on the release url we've configured earlier via "gclient config". Read also the "Possible issues" section below in case you encounter errors. - -``` -cd chromium/ -gclient sync --jobs 8 --force -``` - -This can take a while and sometimes it can break with some errors when a download fails. In such case you should run the "gclient sync" command once again. One of the last messages in the console should be: - -``` -Updating projects from gyp files... -``` - -#### Possible issues while running "gclient sync" #### - - * You may encounter an error while checking out the gsutil repo, fix it [by removing gsutil entries from the DEPS file](http://src.chromium.org/viewvc/chrome/releases/33.0.1750.29/DEPS?r1=245305&r2=245304&pathrev=245305). - -## Download the CEF sources ## - -Download the CEF sources, the repository url can be found in the BUILD\_COMPATIBILITY.txt file. - -``` -cd chromium/src/ -svn checkout {CEF repository url} cef -``` - -This will download the CEF sources to the "cef" directory inside the Chromium "src" directory. - -## Download the CEF Python sources ## - -Run the "git clone" command for the CEF Python repository. This download can take hundreds of megabytes. - -``` -git clone https://github.com/cztomczak/cefpython -``` - -## Fix HTTPS caching on sites with SSL certificate errors (optional) ## - -This is an optional fix. By default Chromium disables caching when there is certificate error. This patch will fix the HTTPS caching only when [ApplicationSettings](ApplicationSettings.md).ignore\_certificate\_errors is set to True. Official cefpython binaries have this fix applied, starting with the 31.0 release. See also [Issue 125](https://code.google.com/p/cefpython/issues/detail?id=125). - -Apply the patch in the "`~/chromium/src/`" directory. Modifications are made in the `HttpCache::Transaction::WriteResponseInfoToEntry` function. - -``` -Index: net/http/http_cache_transaction.cc -=================================================================== ---- http_cache_transaction.cc (revision 241641) -+++ http_cache_transaction.cc (working copy) -@@ -2240,7 +2240,8 @@ - // reverse-map the cert status to a net error and replay the net error. - if ((cache_->mode() != RECORD && - response_.headers->HasHeaderValue("cache-control", "no-store")) || -- net::IsCertStatusError(response_.ssl_info.cert_status)) { -+ (!cache_->GetSession()->params().ignore_certificate_errors && -+ net::IsCertStatusError(response_.ssl_info.cert_status))) { - DoneWritingToEntry(false); - ReportCacheActionFinish(); - if (net_log_.IsLoggingAllEvents()) -``` - - - -## Build CEF binaries and libraries ## - -1. Set the "GYP\_MSVS\_VERSION" environment variable depending on version of Visual Studio you are using. For Visual Studio 2010 set it to "2010", for the Express edition set it to "2010e". - -2. Generate the build files based on the GYP configuration by running the "cef\_create\_projects.bat" script. - -``` -cd chromium/src/cef/ -cef_create_projects.bat -``` - -3. Open the "cef.sln" solution file, change the configuration to Release mode and build it. - -``` -cd chromium/src/cef/ -cef.sln -``` - -After it's built you can close the solution. - -4. Run the "make\_distrib.bat" script. - -``` -cd chromium/src/cef/tools/ -make_distrib.bat --allow-partial -``` - -5. Go to the "chromium/src/cef/binary\_distrib/cef\_binary\_xxxx\_windows/" directory, for the next few steps we will be calling this directory the "cef\_binary" directory. - -6. Open the "cef\_binary/cefclient2010.sln" solution, change the configuration to Release mode and build it. - -7. Copy the "cef\_binary/README.txt" file to the "cefpython/cef3/windows/binaries\_32bit/" directory. - -8. Go to the "cef\_binary/Release/" directory and copy the "libcef.lib" file to the "cefpython/cef3/windows/setup/" directory. - -9. Go to the "cef\_binary/out/Release/" directory, copy the following files: - - * locales/ directory - * all the .exe, .dll and .pak files - -Copy them to the "cefpython/cef3/windows/binaries\_32bit/" directory. - -If you already had any binaries in the "binaries\_32bit/" directory from the previous build process then delete them first, but do not delete the visual c runtime dlls (msvcm90.dll, msvcp90.dll, msvcr90.dll). - -It might be useful to copy also the debug symbols for the CEF library, so that you can debug the stack trace when there is an error in the CEF library. To copy the debug symbols go to the "chromium/src/cef/binary\_distrib/cef\_binary\_3.1650.1646\_windows32\_release\_symbols/" directory and copy the "libcef.dll.pdb" file to the "cefpython/cef3/windows/binaries\_32bit/" directory. - -## Install CEF Python build dependencies ## - -1. Install Visual Studio 2008 with Service Pack 1 or the Express edition which is free. Building Python is supported only on VS2008, thus the same requirement stands for Cython. - -2. Install [Windows SDK 7.0](http://www.microsoft.com/en-us/download/confirmation.aspx?id=18950) to the default location. - -GRMSDK\_EN\_DVD.iso - for Windows 32bit
    -GRMSDKX_EN_DVD.iso - for Windows 64bit
    -
    -3. Download Cython 0.19.2 from PYPI. Later version are not supported by cefpython. Extract it and install:
    -
    python setup.py install
    -
    - -4. (Optional) Install the pywin32 extension to run the pywin32 example.
    -
    -

    Build the CEF Python static libraries

    - -1. Before building static libraries you have to set the "PYTHON_INCLUDE_PATH" environment variable, it should point to the include/ directory in the python installation directory. If you have python installed to the "C:\Python27\" directory (or "C:\Python34\", "C:\Python27_x64\", "C:\Python27_amd64", "C:\Python27_64", "C:\Python34_x64\" etc.), then setting the "PYTHON_INCLUDE_PATH" environment variable is not required.
    -
    -2. Go to the "chromium/src/cef/binary_distrib/cef_binary/" directory, open the "libcef_dll_wrapper.vcproj" project file in Visual Studio 2008 (not VS2010) and change the configuration to Release mode.
    -
    -2a. Change the properties of the "libcef_dll_wrapper" project:
    -
    • Set the "C/C++ > Output files > Program Database File Name" option an empty string. This will get rid of warnings during cython compilation
    - -Build it. Go to the cef_binary/out/Release/lib/ directory and rename "libcef_dll_wrapper.lib" to "libcef_dll_wrapper_mt.lib". Copy it to the cefpython/cef3/windows/setup/lib_32bit/ directory.
    -
    -2b. Change the properties of the "libcef_dll_wrapper" project:
    -
    • Set the "C/C++ > Code Generation > Runtime Library" to "Multi-threaded DLL (/MD)".
      -
    • In "C/C++ > Command Line" add a flag: "-D_HAS_EXCEPTIONS=1" (or set "multi_threaded_dll" in your GYP configuration, see CEF Issue 970).
    - -Build it. After it's built, go to the "cef_binary/out/Release/lib/" directory. Rename "libcef_dll_wrapper.lib" to "libcef_dll_wrapper_md.lib" and copy it to the "cefpython/cef3/windows/setup/lib_32bit/" directory.
    -
    -

    Build the CEF Python module

    - -Go to the "cefpython/cef3/windows/" directory.
    -
    -There is one thing to do before building. An up-to-date "cefpython.h" file needs to be generated, signatures of the Cython public functions are there. To generate this file you need to run the compile.bat script and ignore any errors you see. When asked whether to continue press "y" (yes). The compile.bat script expects first argument to be release version number:
    -
    compile.bat 31.2
    -
    - -After cefpython.h was generated run the compile.bat script once again.
    -
    -If everything went fine then the "cefpython_py27.pyd" (or py34.pyd) module should be created in the "cefpython/cef3/windows/binaries_32bit/" directory and the "wxpython.py" example should be launched automatically.
    -
    -The compile.bat script also accepts additional flags that can be passed after the version argument:
    -
    • --rebuild - to rebuild vcproj builds
      -
    • --py27-32bit, --py27-64bit, --py34-32bit, --py34-64bit - these allow to set PATH for specific Python version. This path contains minimum set of directories to allow detecting possible issues early.
    - -

    Build packages for distribution

    - -To be able to build the inno setup installer you have to install Inno Setup 5. It should be installed to the deafault location "c:\Program Files (x86)\Inno Setup 5\ISCC.exe", otherwise you will have to edit the "make-installer.py" script and change the path. To disable creation of inno setup installer package pass the "--disable-inno-setup" flag after the version number argument.
    -
    -You will also need the pip package manager, please see here on how to install it on Windows. It needs to be a recent version of pip, so that Python Wheels are supported. The build_all.bat script will install some dependencies (setuptools, wheel) if they are missing. If you have some old versions of pip/setuptools/wheel installed, then you need to upgrade them by typing these commands:
    -
    -
    pip install --upgrade pip
    -pip install --upgrade setuptools
    -pip install --upgrade wheel
    -
    - -To create multiple packages run the build_all.bat script. The first argument is a version number. There are also optional flags that you can pass after the version argument: --disable-inno-setup, --py27-32bit, --py27-64bit, --py34-32bit, --py34-64bit.
    -
    cd cefpython/cef3/windows/installer/
    -build_all.bat win32 31.2
    -
    - -If everything went fine then you should see multiple distributions created in the dist/ directory. \ No newline at end of file diff --git a/docs/download/Download-CEF3-Linux.md b/docs/download/Download-CEF3-Linux.md deleted file mode 100644 index 3f9926686..000000000 --- a/docs/download/Download-CEF3-Linux.md +++ /dev/null @@ -1,63 +0,0 @@ -# Download CEF Python 3 for Linux # - - -## Introduction ## - -The binaries were built by following the instructions on the [BuildOnLinux](BuildOnLinux) wiki page.
    -Linux release is sponsored by Cyan Inc. - -Version information
    -The latest version is 31.2 (stable), released on January 10, 2015.
    -The Chrome version is 31.0.1650.69. Based on CEF 3 branch 1650 rev. 1639.
    -For an explanation of these numbers see the VersionNumbering wiki page.
    -
    -Release notes
    -For a list of changes in current and past binary distributions see
    -the ReleaseNotes wiki page.
    -
    -

    Downloads

    - -There are two distributions available for linux: a Debian package and a Distutils Setup. Both 32-bit and 64-bit platforms are supported. Only Python 2.7 downloads are available. Python 3.4 is not yet supported, see Issue 121.
    -
    -Download from Google Drive.
    -
    -Download from Dropbox.
    -
    -

    Install location on Ubuntu

    - -Debian package installs to:
    -
    /usr/share/pyshared/cefpython3/
    -/usr/lib/pymodules/python2.7/cefpython3/ (symbolic links to /usr/share/pyshared/cefpthon3/)
    -
    - -Distutils package installs to:
    -
    /usr/local/lib/python2.7/dist-packages/cefpython3/
    -
    - -Note that if you've installed both the Debian package and the Distutils package, then the Distutils package will take precedence when importing the cefpython3 module.
    -
    -

    Examples

    - -Go to examples/ directory that is inside cefpython3/ package. For location of this directory see the previous section "Install location on Ubuntu".
    -
    -It is recommended to run the wxpython.py example which presents the most features. To install wx toolkit type:
    -
    sudo apt-get install python-wxtools
    -
    - - - -

    Uninstall

    - -To uninstall the Debian package type:
    -
    sudo apt-get remove python-cefpython3
    -
    - -To uninstall the Distutils package type:
    -
    sudo rm -rf /usr/local/lib/python2.7/dist-packages/cefpython3*
    -
    \ No newline at end of file diff --git a/docs/download/Download-CEF3-Mac.md b/docs/download/Download-CEF3-Mac.md deleted file mode 100644 index 78673d3b1..000000000 --- a/docs/download/Download-CEF3-Mac.md +++ /dev/null @@ -1,47 +0,0 @@ -# Download CEF Python 3 for Mac # - -Table of contents: - - -## Introduction ## - -The binaries were built by following the instructions on the [BuildOnMac](BuildOnMac) wiki page.
    - -Version information
    -The latest version is 31.2 for OSX 10.7+, released on January 13, 2015.
    -Chrome version is 31.0.1650.69. Based on CEF 3 branch 1650 rev. 1639.
    -For an explanation of these numbers see the VersionNumbering wiki page.
    -
    -Release notes
    -For a list of changes in current and past binary distributions see
    -the ReleaseNotes wiki page.
    -
    -Stability note
    -Chrome switched to only 64-bit builds on Mac starting with Chrome 39. Earlier versions of Chrome 64bit are not considered stable. CEF Python currently ships Chrome 31 and during testing everything worked fine. But if you want the best stability it is recommended that you use 32bit binaries.
    -
    -

    Install from PyPI

    - -To install the PyPI/cefpython3 package using the pip package manager type:
    -
    pip install cefpython3
    -
    - -If there are problems installing the cefpython3 package, then it might be caused by an old version of pip which may not support Python Wheels. To upgrade pip type: "pip install --upgrade pip".
    -
    -When using preinstalled Python that ships with OS X, to install pip type "sudo easy_install pip" and to install the cefpython3 package type "sudo pip install cefpython3".
    -
    -

    Downloads

    - -Packages are available only for Python 2.7. All packages contain fat binaries and can run on both 32bit and 64bit. Python 3.4 is not yet supported, see Issue 121.
    -
    -Download from Google Drive.
    -
    -Download from Dropbox.
    -
    -

    Examples

    - -To run some examples go to the examples/ directory that is inside the cefpython3 package. Type "pip show cefpython3" to see where the cefpython3 package was installed. It is recommended to run the wxpython.py example which presents the most features.
    -
    - - -Note that when using preinstalled Python that ships with OS X and running examples from the "/Library/Python/2.7/site-packages/cefpython3/examples" directory, you might encounter an error "Segmentation fault: 11". This will occur if app doesn't have permission to write to the "debug.log" file. To fix it run the "sudo chmod 666 debug.log wx/debug.log" command in the examples/ directory. This is to be fixed in VersionNumbering wiki page.
    -
    -Release notes
    -For a list of changes in current and past binary distributions see
    -the ReleaseNotes wiki page.
    -
    -Stability note
    -For best stability please use 32bit binaries. 64bit binaries do work fine, but are not yet considered stable in upstream CEF/Chromium.
    -
    -

    Install from PyPI

    - -To install the PyPI/cefpython3 package using the pip package manager (see how to install pip), type:
    -
    pip install cefpython3
    -
    - -If there are problems installing the cefpython3 package, then it might be caused by an old version of pip which may not support Python Wheels. To upgrade pip type: "pip install --upgrade pip".
    -
    -

    Downloads

    - -Python 2.7 32-bit and 64-bit downloads are available. Python 3.4 is not yet supported, see Issue 121.
    -
    -Download from Google Drive.
    -
    -Download from Dropbox.
    -
    -

    Examples

    - -To run some examples go to the examples/ directory that is inside the cefpython3 package. Type "pip show cefpython3" to see where the cefpython3 package was installed. It is recommended to run the wxpython.py example which presents the most features.
    -
    • wxpython.py - example of embedding using the wxPython GUI toolkit. Includes many tests of advanced features.
      -
    • pywin32.py - example of embeddig using the pywin32 extension.
      -
    • pygtk_.py - example of embedding using the PyGTK GUI toolkit
      -
    • pyqt.py - example of embedding using the PyQt UI framework
      -
    • pyside.py - example of embedding using the PySide UI framework
      -
    • The Inno setup and Distutils distributions come with the cefpython3.wx module with more wxPython examples. See sample1.py, sample2.py, sample3.py.
    - -

    Notes

    - -
    • 64bit binaries do not have applied the patch that fixes HTTPS caching on sites with SSL certificate errors (Issue 125). \ No newline at end of file diff --git a/docs/handlers/DisplayHandler.md b/docs/handlers/DisplayHandler.md deleted file mode 100644 index 589f848b2..000000000 --- a/docs/handlers/DisplayHandler.md +++ /dev/null @@ -1,85 +0,0 @@ -# DisplayHandler callbacks # - -Implement this interface to handle events related to browser display state. The methods of this class will be called on the UI thread. - -For an example of how to implement handler see [cefpython](cefpython).CreateBrowser(). For a list of all handler interfaces see [API > Client handlers](API#Client_handlers). - -## CEF 3 ## - -void **OnAddressChange**([Browser](Browser) browser, [Frame](Frame) frame, string url) - -> Called when a frame's address has changed. - -void **OnTitleChange**([Browser](Browser) browser, string title) - -> Called when the page title changes. - -bool **OnTooltip**([Browser](Browser) browser, `list& textOut`) - -> Called when the browser is about to display a tooltip. `textOut[0]` contains the -> text that will be displayed in the tooltip. To handle the display of the -> tooltip yourself return true. Otherwise, you can optionally modify `textOut[0]` -> and then return false to allow the browser to display the tooltip. -> When window rendering is disabled the application is responsible for -> drawing tooltips and the return value is ignored. - -void **OnStatusMessage**([Browser](Browser) browser, string value) - -> Called when the browser receives a status message. - -bool **OnConsoleMessage**([Browser](Browser) browser, string message, string source, int line) - -> Called to display a console message. Return true to stop the message from -> being output to the console. - -## CEF 1 ## - -void **OnAddressChange**([Browser](Browser) `browser`, [Frame](Frame) `frame`, string `url`) - -> Called when a frame's address has changed. - -bool **OnConsoleMessage**([Browser](Browser) `browser`, string `message`, string `source`, int `line`) - -> Called to display a console message. Return true to stop the message from being output to the console. - -> From testing it seems that this function gets called only for console.log(), console.warn(), console.error() and console.info(). You will not get all the messages that appear in developer tools console, see this thread: http://magpcss.org/ceforum/viewtopic.php?f=6&t=3347 - -void **OnContentsSizeChange**([Browser](Browser) `browser`, [Frame](Frame) `frame`, int `width`, int `height`) - -> Called when the size of the content area has changed. - -void **OnFaviconUrlChange**([Browser](Browser) `browser`, string`[]`& `icon_urls`) - -> Not yet implemented in CEF Python. - -void **OnNavStateChange**([Browser](Browser) `browser`, bool `canGoBack`, bool `canGoForward`) - -> Called when the navigation state has changed. - -void **OnStatusMessage**([Browser](Browser) `browser`, string `text`, int `statusType`) - -> Called when the browser receives a status message. |text| contains the text that will be displayed in the status message and |statusType| indicates the status message type. - -> `statusType` can be one of: - -> cefpython.`STATUSTYPE_TEXT`
      -
      cefpython.STATUSTYPE_MOUSEOVER_URL
      -cefpython.STATUSTYPE_KEYBOARD_FOCUS_URL
      - -bool OnTitleChange(Browser browser, string title)
      -
      -
      Called when the page title changes. Implement this function to handle window titles for popup windows.
      - -
      There is a default implementation of this function that sets titles for popup windows, otherwise they appeared on the taskbar with no title:
      -
      	cefpython.WindowUtils.SetTitle(browser, title)
      - cefpython.WindowUtils.SetIcon(browser, "inherit")
      -
      - -
      Return True to call these two functions automatically, otherwise return False.
      - -
      If you would like to implement it differently, have a look at the default implementation of SetTitle() & SetIcon() in WindowUtils:
      -../blob/master/cefpython/window_utils_win.pyx
      - -bool OnTooltip(Browser browser, string &text[0])
      -
      -
      Called when the browser is about to display a tooltip. |text| contains the text that will be displayed in the tooltip. To handle the display of the tooltip yourself return true. Otherwise, you can optionally modify |text| and then return false to allow the browser to display the tooltip. \ No newline at end of file diff --git a/docs/handlers/DownloadHandler.md b/docs/handlers/DownloadHandler.md deleted file mode 100644 index 88e6a081e..000000000 --- a/docs/handlers/DownloadHandler.md +++ /dev/null @@ -1,34 +0,0 @@ -# DownloadHandler callbacks # - -See also [Browser](Browser).`StartDownload()`. - -## CEF 3 ## - -In CEF 3 downloads are handled automatically if ApplicationSettings.`downloads_enabled` is set to True (default). A default `SaveAs` file dialog provided by OS is displayed. If the download is aborted by user LoadHandler.`OnLoadError` will get called with errorCode ERR\_ABORTED. - -There is no download progress available. If you need such feature you will have to create a custom implementation of downloads. It would need to be investigated which callbacks from client handlers would allow for such implementation. Take a look at RequestHandler.`OnBeforeBrowse`, `OnBeforeResourceLoad`, and/or ResourceHandler. - -On Linux there is a bug and ERR\_ABORTED is reported even for successful downloads. See the comments in the wxpython.py example. - -A download handler with callbacks like `OnBeforeDownload` and -`OnDownloadUpdated` may be exposed to CEF Python in the future. - -## CEF 1 ## - -See [RequestHandler](RequestHandler).`GetDownloadHandler()`. - -You must keep a strong reference to the `DownloadHandler` object while downloading, otherwise it gets destroyed and the `DownloadHandler` callbacks won't be called. - -The callbacks of the `DownloadHandler` class will always be called on the UI thread. - -An example `DownloadHandler` can be found in the wxpython.py script. - -bool **OnData**(str data) - -> A portion of the file contents have been received. This method will be -> called multiple times until the download is complete. Return |True| to -> continue receiving data and |False| to cancel. - -void **OnComplete**() - -> The download is complete. \ No newline at end of file diff --git a/docs/handlers/JavascriptContextHandler.md b/docs/handlers/JavascriptContextHandler.md deleted file mode 100644 index dc7318115..000000000 --- a/docs/handlers/JavascriptContextHandler.md +++ /dev/null @@ -1,26 +0,0 @@ -# JavascriptContextHandler callbacks # - -Implement this interface to handle javascript exceptions globally. - -For an example of how to implement handler see [cefpython](cefpython).CreateBrowser(). For a list of all handler interfaces see [API > Client handlers](API#Client_handlers). - -void **OnContextCreated**([Browser](Browser) `browser`, [Frame](Frame) `frame`) - -> In CEF 1 called immediately after the V8 context for a frame has been created. - -> In CEF 3 called shortly after (process message delay) the V8 context for a frame has been created. - -void **OnContextReleased**([Browser](Browser) `browser`, [Frame](Frame) `frame`) - -> In CEF 1 called immediately before the V8 context for a frame is released. - -> In CEF 3 called shortly after (process message delay) the V8 context for a frame was released. - -> Due to multi-process architecture in CEF 3, this function won't -> get called for the main frame in main browser. To send a message -> from the renderer process a parent browser is used. If this is -> the main frame then this would mean that the browser is being -> destroyed, thus we can't send a process message using this browser. -> There is no guarantee that this will get called for frames in the -> main browser, if the browser is destroyed shortly after the frames -> were released. diff --git a/docs/handlers/JavascriptDialogHandler.md b/docs/handlers/JavascriptDialogHandler.md deleted file mode 100644 index 076a61015..000000000 --- a/docs/handlers/JavascriptDialogHandler.md +++ /dev/null @@ -1,60 +0,0 @@ -# Javascript Dialog handler # - -Implement this interface to handle events related to Javascript dialogs. The methods of this class will be called on the UI thread. - -## JavascriptDialogCallback ## - -Callback interface used for asynchronous continuation of Javascript dialog -requests. - -void **Continue**(bool allow, str userInput) - -> Continue the javascript dialog request. Set |allow| to true if the OK button was -> pressed. The |userInput| value should be specified for prompt dialogs. - - -## Callbacks ## - -bool **OnJavascriptDialog**([Browser](Browser) browser, str origin\_url, str accept\_lang, int dialog\_type, str message\_text, str default\_prompt\_text, `JavascriptDialogCallback` callback, bool& suppress\_message`[0]`) - -> Called to run a Javascript dialog. The |default\_prompt\_text| value will be -> specified for prompt dialogs only. Set |suppress\_message| to true and -> return false to suppress the message (suppressing messages is preferable -> to immediately executing the callback as this is used to detect presumably -> malicious behavior like spamming alert messages in onbeforeunload). Set -> |suppress\_message| to false and return false to use the default -> implementation (the default implementation will show one modal dialog at a -> time and suppress any additional dialog requests until the displayed dialog -> is dismissed). Return true if the application will use a custom dialog or -> if the callback has been executed immediately. Custom dialogs may be either -> modal or modeless. If a custom dialog is used the application must execute -> |callback| once the custom dialog is dismissed. - -> The `dialog_type` param may be one of: -``` -cefpython.JSDIALOGTYPE_ALERT -cefpython.JSDIALOGTYPE_CONFIRM -cefpython.JSDIALOGTYPE_PROMPT -``` - - -bool **OnBeforeUnloadJavascriptDialog**([Browser](Browser) browser, str message\_text, bool is\_reload, `JavascriptDialogCallback` callback) - -> Called to run a dialog asking the user if they want to leave a page. Return -> false to use the default dialog implementation. Return true if the -> application will use a custom dialog or if the callback has been executed -> immediately. Custom dialogs may be either modal or modeless. If a custom -> dialog is used the application must execute |callback| once the custom -> dialog is dismissed. - - -void **OnResetJavascriptDialogState**([Browser](Browser) browser) - -> Called to cancel any pending dialogs and reset any saved dialog state. Will -> be called due to events like page navigation irregardless of whether any -> dialogs are currently pending. - - -void **OnJavascriptDialogClosed**([Browser](Browser) browser) - -> Called when the default implementation dialog is closed. \ No newline at end of file diff --git a/docs/handlers/KeyboardHandler.md b/docs/handlers/KeyboardHandler.md deleted file mode 100644 index 4b01c69c7..000000000 --- a/docs/handlers/KeyboardHandler.md +++ /dev/null @@ -1,72 +0,0 @@ -# KeyboardHandler - - - - -This handler allows you to handle events related to keyboard input and is called only for the main frame. For an example of how to implement handler see [cefpython](../modules/cefpython.md).CreateBrowser(). - -## Callbacks - -### OnPreKeyEvent - -| Parameter | Type | -| --- | --- | -| browser | [Browser](../objects/Browser.md) | -| event | KeyEvent | -| eventHandle | MSG\* / GdkEvent\* / NSEvent\*` | -| isKeyboardShortcutOut | out list[0] -> bool | -| __Return__ | void | - -Called before a keyboard event is sent to the renderer. |event| contains -information about the keyboard event. |eventHandle| is the operating system -event message, if any. Return true if the event was handled or false -otherwise. If the event will be handled in OnKeyEvent() as a keyboard -shortcut, set isKeyboardShortcutOut[0] to True and return False. - -KeyEvent is a dictionary with the following keys: - -| Key | Type | Description | -| --- | --- | --- | -| type | KeyEventType | The type of keyboard event | -| modifiers | KeyEventFlags | Bit flags describing any pressed modifier keys | -| windows_key_code | int | The Windows key code for the key event. This value is used by the DOM specification. Sometimes it comes directly from the event (i.e. on Windows) and sometimes it's determined using a mapping function. See "chromium/KeyboardCodes.h" for a list of values. | -| native_key_code | int | The actual key code genenerated by the platform | -| is_system_key | int | Indicates whether the event is considered a "system key" event. For Windows see [WM_SYSKEYDOWN](http://msdn.microsoft.com/en-us/library/ms646286.aspx). This value will always be false on non-Windows platforms. | -| character | wchar_t or unsigned short | The character generated by the keystroke | -| unmodified_character | wchar_t or unsigned short | Same as 'character' but unmodified by any concurrently-held modifiers (except shift). This is useful for working out shortcut keys. | -| focus_on_editable_field | bool | True if the focus is currently on an editable field on the page. This is useful for determining if standard key events should be intercepted. | - -KeyEventType constants: -* cefpython.KEYEVENT_RAWKEYDOWN -* cefpython.KEYEVENT_KEYDOWN -* cefpython.KEYEVENT_KEYUP -* cefpython.KEYEVENT_CHAR - -KeyEventFlags constants: -* cefpython.EVENTFLAG_NONE -* cefpython.EVENTFLAG_CAPS_LOCK_ON -* cefpython.EVENTFLAG_SHIFT_DOWN -* cefpython.EVENTFLAG_CONTROL_DOWN -* cefpython.EVENTFLAG_ALT_DOWN -* cefpython.EVENTFLAG_LEFT_MOUSE_BUTTON -* cefpython.EVENTFLAG_MIDDLE_MOUSE_BUTTON -* cefpython.EVENTFLAG_RIGHT_MOUSE_BUTTON -* cefpython.EVENTFLAG_COMMAND_DOWN (Mac) -* cefpython.EVENTFLAG_NUM_LOCK_ON (Mac) -* cefpython.EVENTFLAG_IS_KEY_PAD (Mac) -* cefpython.EVENTFLAG_IS_LEFT (Mac) -* cefpython.EVENTFLAG_IS_RIGHT (Mac) - -### OnKeyEvent - -| Parameter | Type | -| --- | --- | -| browser | [Browser](../objects/Browser.md) | -| event | KeyEvent | -| eventHandle | MSG\* / GdkEvent\* / NSEvent\* | -| __Return__ | void | - -Called after the renderer and javascript in the page has had a chance to -handle the event. |event| contains information about the keyboard event. -|os_event| is the operating system event message, if any. Return true if -the keyboard event was handled or false otherwise. Description of the KeyEvent type is in the OnPreKeyEvent() callback. diff --git a/docs/handlers/LifespanHandler.md b/docs/handlers/LifespanHandler.md deleted file mode 100644 index d7b006920..000000000 --- a/docs/handlers/LifespanHandler.md +++ /dev/null @@ -1,81 +0,0 @@ -# LifespanHandler callbacks # - -Implement this interface to handle events related to browser life span. The methods of this class will be called on the UI thread. - -For an example of how to implement a handler see [cefpython](cefpython).CreateBrowser(). For a list of all handler interfaces see [API > Client handlers](API#Client_handlers). - -## CEF 3 ## - -bool **OnBeforePopup**([Browser](Browser) browser, [Frame](Frame) frame, string targetUrl, string targetFrameName, dict popupFeatures, list out windowInfo, object client, list out browserSettings, list out noJavascriptAccess) - -> Called on the IO thread before a new popup window is created. The |browser| -> and |frame| parameters represent the source of the popup request. The -> |targetUrl| and |targetFrameName| values may be empty if none were -> specified with the request. The |popupFeatures| structure contains -> information about the requested popup window. To allow creation of the -> popup window optionally modify |windowInfo`[0]`| (see WindowInfo), |client|, |browserSettings`[0]`| (see BrowserSettings) and -> |noJavascriptAccess`[0]`| and return false. To cancel creation of the popup -> window return true. The |client| and |settings| values will default to the -> source browser's values. The |`noJavascriptAccess[0]`| value indicates whether -> the new browser window should be scriptable and in the same process as the -> source browser. - -> Note that if you return True and create the popup window yourself, then the popup window and parent window will not be able to script each other. There will be no "window.opener" property available in the popup window. - -> Arguments not yet ported (None value): popupFeatures, windowInfo, client, browserSettings. - -void **`_`OnAfterCreated**([Browser](Browser) browser) - -> Called after a new browser is created. - -> This callback will be executed during browser creation, thus you must call [cefpython](cefpython).`SetGlobalClientCallback()` to use it. The callback name was prefixed with "`_`" to distinguish this special behavior. - -bool **RunModal**([Browser](Browser) browser) - -> Called when a modal window is about to display and the modal loop should -> begin running. Return false to use the default modal loop implementation or -> true to use a custom implementation. - -bool **DoClose**([Browser](Browser) browser) - -> Called when a browser has recieved a request to close. This may result -> directly from a call to [Browser](Browser).`CloseBrowser` or indirectly if the -> browser is a top-level OS window created by CEF and the user attempts to -> close the window. This method will be called after the Javascript -> 'onunload' event has been fired. It will not be called for browsers after -> the associated OS window has been destroyed (for those browsers it is no -> longer possible to cancel the close). - -> See complete description of this callback in [cef\_life\_span\_handler.h](../blob/master/cefpython/cef3/include/cef_life_span_handler.h). - -void **OnBeforeClose**([Browser](Browser) browser) - -> Called just before a browser is destroyed. Release all references to the -> browser object and do not attempt to execute any methods on the browser -> object after this callback returns. If this is a modal window and a custom -> modal loop implementation was provided in `RunModal()` this callback should -> be used to exit the custom modal loop. See `DoClose()` documentation for -> additional usage information. - - -## CEF 1 ## - -bool **DoClose**([Browser](Browser) `browser`) - -> Called when a window has recieved a request to close. Return false to proceed with the window close or true to cancel the window close. If this is a modal window and a custom modal loop implementation was provided in RunModal() this callback should be used to restore the opener window to a usable state. - -void **OnAfterCreated**([Browser](Browser) `browser`) - -> Called after a new window is created. - -void **OnBeforeClose**([Browser](Browser) `browser`) - -> Called just before a window is closed. If this is a modal window and a custom modal loop implementation was provided in RunModal() this callback should be used to exit the custom modal loop. - -bool **OnBeforePopup**([Browser](Browser) `parentBrowser`, CefPopupFeatures& `popupFeatures`, CefWindowInfo &`windowInfo`, string &`url`, [BrowserSettings](BrowserSettings) &`settings`) - -> Not yet implemented. Called before a new popup window is created. The |parentBrowser| parameter will point to the parent browser window. The |popupFeatures| parameter will contain information about the style of popup window requested. Return false to have the framework create the new popup window based on the parameters in |windowInfo|. Return true to cancel creation of the popup window. By default, a newly created popup window will have the same client and settings as the parent window. To change the client for the new window modify the object that |client| points to. To change the settings for the new window modify the |settings| structure. - -bool **RunModal**([Browser](Browser) `browser`) - -> Called when a modal window is about to display and the modal loop should begin running. Return false to use the default modal loop implementation or true to use a custom implementation. \ No newline at end of file diff --git a/docs/handlers/LoadHandler.md b/docs/handlers/LoadHandler.md deleted file mode 100644 index 23418ba5c..000000000 --- a/docs/handlers/LoadHandler.md +++ /dev/null @@ -1,74 +0,0 @@ -# LoadHandler callbacks # - -Implement this interface to handle events related to browser load status. The methods of this class will be called on the UI thread. - -For an example of how to implement handler see [cefpython](cefpython).CreateBrowser(). For a list of all handler interfaces see [API > Client handlers](API#Client_handlers). - -## CEF 3 ## - -void **OnLoadingStateChange**([Browser](Browser) browser, bool isLoading, bool canGoBack, bool canGoForward) - -> Called when the loading state has changed. This callback will be executed -> twice. Once when loading is initiated either programmatically or by user -> action, and once when loading is terminated due to completion, cancellation -> of failure. - -void **OnLoadStart**([Browser](Browser) browser, [Frame](Frame) frame) - -> Called when the browser begins loading a frame. The |frame| value will -> never be empty -- call the IsMain() method to check if this frame is the -> main frame. Multiple frames may be loading at the same time. Sub-frames may -> start or continue loading after the main frame load has ended. This method -> may not be called for a particular frame if the load request for that frame -> fails. For notification of overall browser load status use -> [DisplayHandler](DisplayHandler).`OnLoadingStateChange` instead. - -void **OnDomReady**() - -> Not yet implemented. See [Issue 32](../issues/32). - -void **OnLoadEnd**([Browser](Browser) browser, [Frame](Frame) frame, int httpStatusCode) - -> Called when the browser is done loading a frame. The |frame| value will -> never be empty -- call the IsMain() method to check if this frame is the -> main frame. Multiple frames may be loading at the same time. Sub-frames may -> start or continue loading after the main frame load has ended. This method -> will always be called for all frames irrespective of whether the request -> completes successfully. - -> This event behaves like window.onload, it waits for all the content to load (e.g. images), there is currently no callback for a DOMContentLoaded event, see [Issue 32](../issues/32). - -> There are some cases when this callback won't get called, see this topic: http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=10906 - -void **OnLoadError**([Browser](Browser) browser, [Frame](Frame) frame, [NetworkError](NetworkError) errorCode, list& errorText, string failedUrl) - -> Called when the resource load for a navigation fails or is canceled. -> |errorCode| is the error code number, |`errorText[0]`| is the error text and -> |failedUrl| is the URL that failed to load. See net\base\net\_error\_list.h -> for complete descriptions of the error codes. - -> This callback may get called when [Browser](Browser).`StopLoad` is called, or when file download is aborted (see DownloadHandler). - -## CEF 1 ## - -void **OnDomReady**() - -> Not yet implemented. See [Issue 32](../issues/32). - -void **OnLoadEnd**([Browser](Browser) `browser`, [Frame](Frame) `frame`, int `httpStatusCode`) - -> Called when the browser is done loading a frame (top frame, iframe, frameset, popup). The |Frame| value will never be empty -- call the IsMain() method to check if this frame is the main frame. Multiple frames may be loading at the same time. Sub-frames may start or continue loading after the main frame load has ended. This method will always be called for all frames irrespective of whether the request completes successfully. - -> This event behaves like window.onload, it waits for all the content to load (e.g. images), there is currently no callback for a DOMContentLoaded event, see [Issue 32](../issues/32). - -> There are some cases when this callback won't get called, see this topic: http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=10906 - -bool **OnLoadError**([Browser](Browser) `browser`, [Frame](Frame) `frame`, int [errorCode](NetworkError), string `failedURL`, string list &`errorText`) - -> Called when the browser fails to load a frame (top frame, iframe, frameset, popup). |errorCode| is the error code number and |failedUrl| is the URL that failed to load. To provide custom error text assign the text to `errorText[0]` and return true. Otherwise, return false for the default error text. - -> OnLoadError may be called very early in the navigation process before |frame| or its GetURL() value has been set, thus the availability of additional parameter `failedURL`. - -void **OnLoadStart**([Browser](Browser), [Frame](Frame)) - -> Called when the browser begins loading a frame (top frame, iframe, frameset, popup). The |Frame| value will never be empty -- call the IsMain() method to check if this frame is the main frame. Multiple frames may be loading at the same time. Sub-frames may start or continue loading after the main frame load has ended. This method may not be called for a particular frame if the load request for that frame fails. \ No newline at end of file diff --git a/docs/handlers/RenderHandler.md b/docs/handlers/RenderHandler.md deleted file mode 100644 index 606038078..000000000 --- a/docs/handlers/RenderHandler.md +++ /dev/null @@ -1,167 +0,0 @@ -# RenderHandler callbacks # - -Implement this interface to handle events when window rendering is disabled (off-screen rendering). The methods of this class will be called on the UI thread. - -## CEF 3 ## - -bool **GetRootScreenRect**([Browser](Browser) browser, list out `rect`) - -> Called to retrieve the root window rectangle in screen coordinates. Return true if the rectangle was provided. - -bool **GetViewRect**([Browser](Browser) `browser`, list out `rect`) - -> Called to retrieve the view rectangle which is relative to screen coordinates. Return true if the rectangle was provided. - -> The `rect` list should contain 4 elements: [x, y, width, height]. - -bool **GetScreenRect**([Browser](Browser) `browser`, list out `rect`) - -> Called to retrieve the simulated screen rectangle. Return true if the rectangle was provided. - -> The `rect` list should contain 4 elements: [x, y, width, height]. - -bool **GetScreenPoint**([Browser](Browser) `browser`, int `viewX`, int `viewY`, list out `screenCoordinates`) - -> Called to retrieve the translation from view coordinates to actual screen coordinates. Return true if the screen coordinates were provided. - -> The `screenCoordinates` list should contain 2 elements: [x, y]. - -bool **GetScreenInfo**([Browser](Browser) browser, `CefScreenInfo`& screen\_info) - -> Not yet implemented. - -> Called to allow the client to fill in the `CefScreenInfo` object with appropriate values. Return true if the |screen\_info| structure has been modified. If the screen info rectangle is left empty the rectangle from `GetViewRect` will be used. If the rectangle is still empty or invalid popups may not be drawn correctly. - -> `CefScreenInfo` structure: - -``` -typedef struct _cef_screen_info_t { - /// - // Device scale factor. Specifies the ratio between physical and logical - // pixels. - /// - float device_scale_factor; - - /// - // The screen depth in bits per pixel. - /// - int depth; - - /// - // The bits per color component. This assumes that the colors are balanced - // equally. - /// - int depth_per_component; - - /// - // This can be true for black and white printers. - /// - bool is_monochrome; - - /// - // This is set from the rcMonitor member of MONITORINFOEX, to whit: - // "A RECT structure that specifies the display monitor rectangle, - // expressed in virtual-screen coordinates. Note that if the monitor - // is not the primary display monitor, some of the rectangle's - // coordinates may be negative values." - // - // The |rect| and |available_rect| properties are used to determine the - // available surface for rendering popup views. - /// - cef_rect_t rect; - - /// - // This is set from the rcWork member of MONITORINFOEX, to whit: - // "A RECT structure that specifies the work area rectangle of the - // display monitor that can be used by applications, expressed in - // virtual-screen coordinates. Windows uses this rectangle to - // maximize an application on the monitor. The rest of the area in - // rcMonitor contains system windows such as the task bar and side - // bars. Note that if the monitor is not the primary display monitor, - // some of the rectangle's coordinates may be negative values". - // - // The |rect| and |available_rect| properties are used to determine the - // available surface for rendering popup views. - /// - cef_rect_t available_rect; -``` - -void **OnPopupShow**([Browser](Browser) `browser`, bool `show`) - -> Called when the browser wants to show or hide the popup widget. The popup should be shown if |show| is true and hidden if |show| is false. - -void **OnPopupSize**([Browser](Browser) `browser`, list `rect`) - -> Called when the browser wants to move or resize the popup widget. |rect| contains the new location and size. - -> The `rect` list should contain 4 elements: [x, y, width, height]. - -void **OnPaint**([Browser](Browser) `browser`, int `paintElementType`, list out `dirtyRects`, [PaintBuffer](PaintBuffer) `buffer`, int width, int height) - -> Called when an element should be painted. |paintElementType| indicates whether the element is the view or the popup widget. |buffer| contains the pixel data for the whole image. |dirtyRects| contains the set of rectangles that need to be repainted. On Windows |buffer| will be width\*height\*4 bytes in size and represents a BGRA image with an upper-left origin. The BrowserSettings.animation\_frame\_rate value controls the rate at which this method is called. - -> `paintElementType` is one of: - -> cefpython.`PET_VIEW`
      -
      cefpython.PET_POPUP
      - -
      dirtyRects is a list of rects: [[x, y, width, height], [..]]
      - -void OnCursorChange(Browser browser, CursorHandle cursor)
      -
      -
      Called when the browser window's cursor has changed.
      - -
      CursorHandle is an int pointer.
      - -void OnScrollOffsetChanged(Browser browser)
      -
      -
      Called when the scroll offset has changed.
      - -

      CEF 1

      - -In CEF 1 off-screen rendering is not supported on Linux.
      -
      -bool GetViewRect(Browser browser, list out rect)
      -
      -
      Called to retrieve the view rectangle which is relative to screen coordinates. Return true if the rectangle was provided.
      - -
      The rect list should contain 4 elements: [x, y, width, height].
      - -bool GetScreenRect(Browser browser, list out rect)
      -
      -
      Called to retrieve the simulated screen rectangle. Return true if the rectangle was provided.
      - -
      The rect list should contain 4 elements: [x, y, width, height].
      - -bool GetScreenPoint(Browser browser, int viewX, int viewY, list out screenCoordinates)
      -
      -
      Called to retrieve the translation from view coordinates to actual screen coordinates. Return true if the screen coordinates were provided.
      - -
      The screenCoordinates list should contain 2 elements: [x, y].
      - -void OnPopupShow(Browser browser, bool show)
      -
      -
      Called when the browser wants to show or hide the popup widget. The popup should be shown if |show| is true and hidden if |show| is false.
      - -void OnPopupSize(Browser browser, list rect)
      -
      -
      Called when the browser wants to move or resize the popup widget. |rect| contains the new location and size.
      - -
      The rect list should contain 4 elements: [x, y, width, height].
      - -void OnPaint(Browser browser, int paintElementType, list out dirtyRects, PaintBuffer buffer)
      -
      -
      Called when an element should be painted. |paintElementType| indicates whether the element is the view or the popup widget. |buffer| contains the pixel data for the whole image. |dirtyRects| contains the set of rectangles that need to be repainted. On Windows |buffer| will be width*height*4 bytes in size and represents a BGRA image with an upper-left origin. The BrowserSettings.animation_frame_rate value controls the rate at which this method is called.
      - -
      paintElementType is one of:
      - -
      cefpython.PET_VIEW
      -cefpython.PET_POPUP
      - -
      dirtyRects is a list of rects: [[x, y, width, height], [..]]
      - -void OnCursorChange(Browser browser, CursorHandle cursor)
      -
      -
      Called when the browser window's cursor has changed.
      - -
      On Windows CursorHandle is an int pointer of a HANDLE. \ No newline at end of file diff --git a/docs/handlers/RequestHandler.md b/docs/handlers/RequestHandler.md deleted file mode 100644 index 33f481327..000000000 --- a/docs/handlers/RequestHandler.md +++ /dev/null @@ -1,218 +0,0 @@ -# RequestHandler callbacks # - -Implement this interface to handle events related to browser requests. - -For an example of how to implement handler see [cefpython](cefpython).CreateBrowser(). For a list of all handler interfaces see [API > Client handlers](API#Client_handlers). - -The `RequestHandler` tests can be found in the wxpython.py script. - -## CEF 3 ## - -void **OnBeforeBrowse**([Browser](Browser) browser, [Frame](Frame) frame, [Request](Request) request, bool isRedirect) - -> Called on the UI thread before browser navigation. Return true to cancel -> the navigation or false to allow the navigation to proceed. The |request| -> object cannot be modified in this callback. -> [DisplayHandler](DisplayHandler).`OnLoadingStateChange` will be called twice in all cases. -> If the navigation is allowed [LoadHandler](LoadHandler).`OnLoadStart` and -> `OnLoadEnd` will be called. If the navigation is canceled -> [LoadHandler](LoadHandler).`OnLoadError` will be called with an |errorCode| value of -> ERR\_ABORTED. - -bool **OnBeforeResourceLoad**([Browser](Browser) browser, [Frame](Frame) frame, [Request](Request) request) - -> Called on the IO thread before a resource request is loaded. The |request| -> object may be modified. To cancel the request return true otherwise return false. - -[ResourceHandler](ResourceHandler) **GetResourceHandler**([Browser](Browser) browser, [Frame](Frame) frame, [Request](Request) request) - -> Called on the IO thread before a resource is loaded. To allow the resource -> to load normally return None. To specify a handler for the resource return -> a [ResourceHandler](ResourceHandler) object. The |request| object should not be modified in -> this callback. - -> The [ResourceHandler](ResourceHandler) object is a python class that implements the `ResourceHandler` callbacks. Remember to keep a strong reference to this object while resource is being loaded. - -> The `GetResourceHandler` example can be found in the `wxpython-response.py` script on Linux. - -void **OnResourceResponse**() - -> Not yet available in CEF 3 (see [CEF Issue 515](https://bitbucket.org/chromiumembedded/cef/issues/515)), though it can be emulated, see the comment below. - -> You can implement this functionality by using [ResourceHandler](ResourceHandler) -> and [WebRequest](WebRequest) / [WebRequestClient](WebRequestClient). For an example see the `_OnResourceResponse()` method in the [wxpython-response.py](../blob/master/cefpython/cef3/linux/binaries_64bit/wxpython-response.py) script. - -void **OnResourceRedirect**([Browser](Browser) browser, [Frame](Frame) frame, string oldUrl, list& newUrlOut) - -> Called on the IO thread when a resource load is redirected. The |oldUrl| -> parameter will contain the old URL. The `newUrlOut[0]` parameter will contain -> the new URL and can be changed if desired. - -bool **GetAuthCredentials**([Browser](Browser) browser, [Frame](Frame) frame, bool isProxy, string host, int port, string realm, string scheme, `AuthCallback` callback) { - -> Called on the IO thread when the browser needs credentials from the user. -> |isProxy| indicates whether the host is a proxy server. |host| contains the -> hostname and |port| contains the port number. Return true to continue the -> request and call `AuthCallback`::Continue() when the authentication -> information is available. Return false to cancel the request. - -> The `AuthCallback` object methods: - * void Continue(string username, string password) - * void Cancel() - -bool **OnQuotaRequest**([Browser](Browser) browser, string originUrl, long newSize, `QuotaCallback` callback) - -> Called on the IO thread when javascript requests a specific storage quota -> size via the `webkitStorageInfo.requestQuota` function. |originUrl| is the -> origin of the page making the request. |newSize| is the requested quota -> size in bytes. Return true and call `QuotaCallback::Continue()` either in -> this method or at a later time to grant or deny the request. Return False -> to cancel the request. - -> The `QuotaCallback` object methods: - * void Continue(bool allow) - * void Cancel() - -[CookieManager](CookieManager) **GetCookieManager**([Browser](Browser) browser|None, string mainUrl) - -> Called on the IO thread to retrieve the cookie manager. |mainUrl| is the URL of the top-level frame. Cookies managers can be unique per browser or shared across multiple browsers. The global cookie manager will be used if this method returns None. - -> To successfully implement separate cookie manager per browser session, you have to set ApplicationSettings.`unique_request_context_per_browser` to True. Otherwise the browser param passed to this callback will always be the same first browser that was created using [cefpython](cefpython).`CreateBrowserSync`. - -> Popup browsers created javascript's window.open share the same renderer process and request context. If you want to have separate cookie managers for popups created using window.open then you have to implement the LifespanHandler.`OnBeforePopup` callback. Return True in that callback to cancel popup creation and instead create the window on your own and embed browser in it. The `CreateAnotherBrowser` function from the wxpython example does that. - -> IMPORTANT: in an exceptional case the `browser` parameter could be None, so you should handle such case. During testing this issue did not occur, but it may happen in some yet unknown scenarios. - -void **OnProtocolExecution**([Browser](Browser) browser, string url, list& allowExecutionOut) - -> Called on the UI thread to handle requests for URLs with an unknown -> protocol component. Set `allowExecutionOut[0]` to True to attempt execution -> via the registered OS protocol handler, if any. -> SECURITY WARNING: YOU SHOULD USE THIS METHOD TO ENFORCE RESTRICTIONS BASED -> ON SCHEME, HOST OR OTHER URL ANALYSIS BEFORE ALLOWING OS EXECUTION. - -> There's no default implementation for OnProtocolExecution on Linux, -> you have to make OS system call on your own. You probably also need -> to use [LoadHandler](LoadHandler)::`OnLoadError()` when implementing this on Linux. - -bool **`_`OnBeforePluginLoad**([Browser](Browser) browser, string url, string policyUrl, [WebPluginInfo](WebPluginInfo) info) - -> Called on the browser process IO thread before a plugin is loaded. Return -> True to block loading of the plugin. - -> This callback will be executed during browser creation, thus you must call [cefpython](cefpython).`SetGlobalClientCallback()` to use it. The callback name was prefixed with "`_`" to distinguish this special behavior. - -> Plugins are loaded on demand, only when website requires it. -> This callback is called every time the page tries to load a plugin (perhaps even multiple times per plugin). - -bool **`_`OnCertificateError**([NetworkError](NetworkError) certError, string requestUrl, `AllowCertificateErrorCallback` callback) - -> This callback is not associated with any specific browser, thus you must call [cefpython](cefpython).`SetGlobalClientCallback()` to use it. The callback name was prefixed with "`_`" to distinguish this special behavior. - -> Called on the UI thread to handle requests for URLs with an invalid -> SSL certificate. Return True and call `AllowCertificateErrorCallback`:: -> `Continue()` either in this method or at a later time to continue or cancel -> the request. Return False to cancel the request immediately. If |callback| -> is empty the error cannot be recovered from and the request will be -> canceled automatically. If [ApplicationSettings](ApplicationSettings).`ignore_certificate_errors` is set -> all invalid certificates will be accepted without calling this method. - -> The `AllowCertificateErrorCallback` object methods: - * void Continue(bool allow) - -void **OnRendererProcessTerminated**([Browser](Browser) browser, `TerminationStatus` status) - -> Called when the render process terminates unexpectedly. |status| indicates -> how the process terminated. - -> `TerminationStatus` constants: - * cefpython.TS\_ABNORMAL\_TERMINATION - Non-zero exit status. - * cefpython.TS\_PROCESS\_WAS\_KILLED - SIGKILL or task manager kill. - * cefpython.TS\_PROCESS\_CRASHED - Segmentation fault. - -void **OnPluginCrashed**([Browser](Browser) browser, string pluginPath) - -> Called when a plugin has crashed. |pluginPath| is the path of the plugin -> that crashed. - -## CEF 1 ## - -bool **OnBeforeBrowse**([Browser](Browser) `browser`, [Frame](Frame) `frame`, [Request](Request) `request`, int `navType`, bool `isRedirect`) - -> Called on the UI thread before browser navigation. Return true to cancel the navigation or false to allow the navigation to proceed. - -> You cannot modify request headers nor post data via the [Request](Request) -> object in this callback, you have to do it in `OnBeforeResourceLoad()`. - -> `|navType|` can be one of: - -> `cefpython.NAVTYPE_LINKCLICKED`
      -
      cefpython.NAVTYPE_FORMSUBMITTED
      -cefpython.NAVTYPE_BACKFORWARD
      -cefpython.NAVTYPE_RELOAD
      -cefpython.NAVTYPE_FORMRESUBMITTED
      -cefpython.NAVTYPE_OTHER
      -cefpython.NAVTYPE_LINKDROPPED
      - -bool OnBeforeResourceLoad(Browser browser, Request request, string& redirectURL[0], StreamReader streamReader, Response response, int loadFlags)
      -
      -
      Called on the IO thread before a resource is loaded. To allow the resource
      -to load normally return false. To redirect the resource to a new url
      -populate the |redirectUrl| value and return false. To specify data for the
      -resource set it through |streamReader|, use the |response|
      -object to set mime type, HTTP status code and optional header values, and
      -return false. To cancel loading of the resource return true. Any
      -modifications to |request| will be observed. If the URL in |request| is
      -changed and |redirectUrl| is also set, the URL in |request| will be used.
      - -void OnResourceRedirect(Browser browser, string oldURL, string& newURL[0])
      -
      -
      Called on the IO thread when a resource load is redirected. The |oldURL| parameter will contain the old URL. The |newURL[0]| parameter will contain the new URL and can be changed if desired.
      - -void OnResourceResponse(Browser browser, string url, Response response, ContentFilter& filter[0])
      -
      -
      Called on the UI thread after a response to the resource request is received. Set |filter| if response content needs to be monitored and/or modified as it arrives.
      - -
      ContentFilter is not yet implemented, as of the moment you can only read responses using the Response object.
      - -
      This function does not get called for local disk resources (file:///). If you want to track local disk resources that failed to load, the way to go is to implement Schemehandler (see thread here: http://magpcss.org/ceforum/viewtopic.php?f=6&t=3442)
      - -bool OnProtocolExecution(Browser browser, string URL, bool& allowOSExecution[0])
      -
      -
      Called on the IO thread to handle requests for URLs with an unknown
      -protocol component. Return true to indicate that the request should
      -succeed because it was handled externally. Set |allowOSExecution[0]| to true and return false to attempt execution via the registered OS protocol handler, if any. If false is returned and either |allowOSExecution[0]| is false or OS protocol handler execution fails then the request will fail with an error condition.
      - -
      SECURITY WARNING: you should use this method to enforce restrictions based on scheme, host or other url analysis before allowing os execution.
      - -DownloadHandler GetDownloadHandler(Browser browser, string mimeType, string filename, int contentLength)
      -
      -
      Called on the UI thread when a server indicates via the
      -'Content-Disposition' header that a response represents a file to download.
      -|mimeType| is the mime type for the download, |fileName| is the suggested
      -target file name and |contentLength| is either the value of the
      -'Content-Size' header or -1 if no size was provided.
      - -
      Return a DownloadHandler object to download the file or False
      -to cancel the file download.
      - -
      The DownloadHandler object is a python class that implements the
      -DownloadHandler callbacks, you must keep a strong reference to
      -this object while download is proceeding, otherwise it gets destroyed
      -and the callbacks won't be called.
      - -bool GetAuthCredentials(Browser browser, bool isProxy, string host, int port, string realm, string scheme, string& username[0], string& password[0])
      -
      -
      On Windows there is a default implementation for Http Authentication. On Linux there is no default implementation.
      - -
      Called on the IO thread when the browser needs credentials from the user. |isProxy| indicates whether the host is a proxy server. |host| contains the hostname and port number. Set |username[0]| and |password[0]| and return true to handle the request. Return false to cancel the request.
      - -CookieManager GetCookieManager(Browser browser, string mainUrl)
      -
      -
      Called on the IO thread to retrieve the cookie manager. |mainUrl| is the URL of the top-level frame. Cookies managers can be unique per browser or shared across multiple browsers. The global cookie manager will be used if this method returns None.
      - -
      This method may be called multiple times for the same browser,
      -if you return a cookie manager you need to save it somewhere
      -so that you don't create a new one on next call, use
      -Browser.SetUserData() and Browser.GetUserData() for
      -that purpose. \ No newline at end of file diff --git a/docs/handlers/ResourceHandler.md b/docs/handlers/ResourceHandler.md deleted file mode 100644 index 86b5b9b76..000000000 --- a/docs/handlers/ResourceHandler.md +++ /dev/null @@ -1,57 +0,0 @@ -# `ResourceHandler` callbacks # - -Class used to implement a custom request handler interface. The methods of this class will always be called on the IO thread. - -See [RequestHandler](RequestHandler).`GetResourceHandler()`. - -You must keep a strong reference to the `ResourceHandler` object while resource is being loaded, otherwise it gets destroyed and the `ResourceHandler` callbacks won't be called. - -Make requests using [WebRequest](WebRequest) and [WebRequestClient](WebRequestClient). - -The `ResourceHandler` example can be found in the [wxpython-response.py](../blob/master/cefpython/cef3/linux/binaries_64bit/wxpython-response.py) script. - -## CEF 3 ## - -bool **ProcessRequest**([Request](Request) request, [Callback](Callback) callback) - -> Begin processing the request. To handle the request return True and call -> [Callback](Callback).`Continue()` once the response header information is available -> (`Callback::Continue()` can also be called from inside this method if -> header information is available immediately). To cancel the request return -> False. - - -void **GetResponseHeaders**([Response](Response) response, list& responseLengthOut, list& redirectUrlOut) - -> Retrieve response header information. If the response length is not known -> set `responseLengthOut[0]` to -1 and `ReadResponse()` will be called until it -> returns false. If the response length is known set `responseLengthOut[0]` -> to a positive value and `ReadResponse()` will be called until it returns -> false or the specified number of bytes have been read. Use the |response| -> object to set the mime type, http status code and other optional header -> values. To redirect the request to a new URL set `redirectUrlOut[0]` to the new url. - - -bool **ReadResponse**(list& dataOut, int bytesToRead, list& bytesReadOut, [Callback](Callback) callback) - -> Read response data. If data is available immediately copy up to -> `bytesToRead` bytes into `dataOut[0]`, set `bytesReadOut[0]` to the number of -> bytes copied, and return true. To read the data at a later time set -> `bytesReadOut[0]` to 0, return true and call `callback.Continue()` when the -> data is available. To indicate response completion return false. - - -bool **CanGetCookie**([Cookie](Cookie) cookie) - -> Return true if the specified cookie can be sent with the request or false -> otherwise. If false is returned for any cookie then no cookies will be sent -> with the request. - -bool **CanSetCookie**([Cookie](Cookie) cookie) - -> Return true if the specified cookie returned with the response can be set -> or false otherwise. - -void **Cancel**() - -> Request processing has been canceled. \ No newline at end of file diff --git a/docs/misc/Architecture-and-features.md b/docs/misc/Architecture-and-features.md deleted file mode 100644 index bbe94dbd3..000000000 --- a/docs/misc/Architecture-and-features.md +++ /dev/null @@ -1,120 +0,0 @@ -# Architecture & Features # - -Table of contents: - -## CEF 3 summary ## - * supports html5 audio/video, good performance of webgl and other accelerated content - * uses multi process architecture and [Chromium Content API](http://www.chromium.org/developers/content-module/content-api), thus giving performance and features similar to Chrome - * V8 engine is runing in a separate process so javascript integration can be done only through asynchronous messaging between processes, in CEF 1 you can call javascript and python back synchronously - * single process is for debugging purposes only, it is unstable, it will likely be fixed in the future as Chromium for mobile devices needs a stable single-process mode - -CEF 3 comes with the the latest version of Chrome. - - -For more information on CEF architecture see this wiki page on the Chromium Embedded project: -http://code.google.com/p/chromiumembedded/wiki/Architecture - -## CEF 3 features ported in CEF Python 3 ## - - * [Frame](Frame) object - * [Browser](Browser) object - * [ApplicationSettings](ApplicationSettings) - * [BrowserSettings](BrowserSettings) - * [DownloadHandler](DownloadHandler) - * [JavascriptBindings](JavascriptBindings) - * [JavascriptCallback](JavascriptCallback) - * Python callbacks - * [JavascriptContextHandler](JavascriptContextHandler) (partially) - * JavascriptDialogHandler - * [RequestHandler](RequestHandler) - * [Request](Request) object - * [WebPluginInfo](WebPluginInfo) - * [Cookie](Cookie) - * [CookieManager](CookieManager) - * [CookieVisitor](CookieVisitor) - * [LoadHandler](LoadHandler) - * [RenderHandler](RenderHandler) - * [ResourceHandler](ResourceHandler) - * [Response](Response) object - * [WebRequest](WebRequest) and [WebRequestClient](WebRequestClient) - * [LifespanHandler](LifespanHandler) (partially) - -## CEF 3 features not yet ported to CEF Python 3 ## - - * [context menu handler](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_context_menu_handler.h) & [menu model](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_menu_model.h) - API is not provided, but context menu is configurable, see ApplicationSettings.`context_menu` - * [dialog handler](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_dialog_handler.h) - * [dom manipulation](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_dom.h) - won't be implemented as it was deprecated and has memory leaks. The recommended way is to manipulate DOM through javascript and report to python through javascript bindings. - * [focus handler](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_focus_handler.h) - * [geolocation](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_geolocation.h) & [geolocation handler](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_geolocation_handler.h) - * [origin whitelist](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_origin_whitelist.h) - * [proxy handler](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_proxy_handler.h) - * [render process handler](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_render_process_handler.h) - * [resource bundle handler](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_resource_bundle_handler.h) - * [custom scheme](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_scheme.h) - * [stream reader & writer](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_stream.h) for request response - * [trace notifications](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_trace.h) & [trace event](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_trace_event.h) - * [web plugin](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_web_plugin.h) (WebPluginInfo already implemented) - * [xml reader](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_xml_reader.h) - * [zip reader](https://bitbucket.org/chromiumembedded/cef/src/master/include/cef_zip_reader.h) - -## CEF 1 summary ## - * single process architecture - * more feature complete API than in CEF 3 (as of the moment) - * html5 audio and video support was removed (see [Issue 18](https://code.google.com/p/cefpython/issues/detail?id=18)) - * uses Webkit API - * reduced memory usage and closer integration with the client application - * [reduced performance](http://code.google.com/p/chromiumembedded/issues/detail?id=304) with certain types of accelerated content and [crashes](http://code.google.com/p/chromiumembedded/issues/detail?id=242) due to plugins like Flash running in the same process. - -CEF 1 is currently in maintenance mode and the latest version available includes Chrome 27. - -## Known problems in CEF 1 ## - -Flash plugin will crash on Linux, see [Issue 553 in CEF Issue Tracker](http://code.google.com/p/chromiumembedded/issues/detail?id=553). However, Pepper Flash Player might work in CEF 3 on Linux (not yet tested). - -## CEF 1 features ported to CEF Python 1 ## - - * [Frame](Frame) object - * [Browser](Browser) object - * [application settings](ApplicationSettings) - * [browser settings](BrowserSettings) - * [javascript bindings](JavascriptBindings) - * [javascript callbacks](JavascriptCallback) & python callbacks - * [display handler](DisplayHandler) - * [keyboard handler](KeyboardHandler) - * [lifespan handler](LifespanHandler) (partially) - * [load handler](LoadHandler) - * [render handler](RenderHandler) - * [request handler](RequestHandler) (partially) - * [Response](Response) object - * [javascript context handler](JavascriptContextHandler) (partially) - * [ContentFilter](ContentFilter) for resource response - * [Request](Request) object - * [StreamReader](StreamReader) for request response - * [WebRequest](WebRequest) - * [Cookie](Cookie) class - * [CookieManager](CookieManager) class - * [CookieVisitor](CookieVisitor) callbacks - * [DownloadHandler](DownloadHandler) - * [DragHandler](DragHandler) - * [DragData](DragData) - -## CEF 1 features not yet ported to CEF Python 1 ## - - * [dom manipulation](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_dom.h) - won't be implemented as it was deprecated and has memory leaks. The recommended way is to manipulate DOM through javascript and report to python through javascript bindings. - * [find handler](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_find_handler.h) - * [focus handler](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_focus_handler.h) - * [geolocation](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_geolocation.h) & [geolocation handler](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_geolocation_handler.h) - * [jsdialog handler](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_jsdialog_handler.h) - * [menu handler](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_menu_handler.h) - * [plugin info](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_nplugin.h) - * [origin whitelist](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_origin_whitelist.h) - * [javascript extensions](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_v8.h?r=972#53) - * [permission handler for extensions](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_permission_handler.h) - * [print handler](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_print_handler.h) - * [proxy handler](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_proxy_handler.h) - * [resource bundle handler](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_resource_bundle_handler.h) - * [custom scheme](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_scheme.h) - * [web plugin](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_web_plugin.h) - * [xml reader](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_xml_reader.h) - * [zip reader](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_zip_reader.h) - * [zoom handler](http://code.google.com/p/chromiumembedded/source/browse/trunk/cef1/include/cef_zoom_handler.h) \ No newline at end of file diff --git a/docs/misc/Inno-Setup-installer.md b/docs/misc/Inno-Setup-installer.md deleted file mode 100644 index c76e0b775..000000000 --- a/docs/misc/Inno-Setup-installer.md +++ /dev/null @@ -1,3 +0,0 @@ -# Inno Setup installer on Windows # - -Inno setup can be installed from command line without user interaction by passing the /SILENT flag. See all [command line parameters](http://www.jrsoftware.org/ishelp/topic_setupcmdline.htm) that can be passed to the inno setup installer. See also Inno Setup website: http://www.jrsoftware.org/isinfo.php \ No newline at end of file diff --git a/docs/misc/Release-notes.md b/docs/misc/Release-notes.md deleted file mode 100644 index d355c1e12..000000000 --- a/docs/misc/Release-notes.md +++ /dev/null @@ -1,141 +0,0 @@ -# Release notes # - -This document is DEPRECATED and won't be used anymore for newer releases. - -Version 31.3 not yet released. - * Added `__version__` attribute in the cefpython3.cefpython module ([Issue 167](../issues/167)) - * Added methods [Browser](Browser).`ExecuteFunction()` / `ExecuteJavascript()` which are wrappers for calling [Browser](Browser).`GetMainFrame()`.`ExecuteFunction()` / `ExecuteJavascript()`. - * Added functions [cefpython](cefpython).`GetAppSetting()` / `GetCommandLineSwitch()` - -Version 31.2 released on January 10, 2015. - * Initial release of Windows 64bit binaries ([Issue 82](../issues/82)) - * Initial release for Mac ([Issue 21](../issues/21)). See the [Download\_CEF3\_Mac](Download_CEF3_Mac) and BuildOnMac wiki pages. - * Fixed BC break in cefpython.wx.chromectrl introduced in 31.1 - * Windows binaries do not ship the msvcr90.dll and Microsoft.VC90.CRT.manifest files anymore. The subprocess.exe executable does not depend on msvcr90.dll anymore. - -Version 31.1 released on December 4, 2014. - * (Windows) When cefpython detects that application is DPI aware (may be enabled by user in .exe properties) then it will set ApplicationSettings."auto\_zooming" to "system\_dpi" automatically. Added the DpiAware.`IsProcessDpiAware` method. See revision c11190523824. - * Added new callbacks to LifespanHandler: `_OnAfterCreated`, `RunModal`, `DoClose`, `OnBeforeClose`. Thanks to Simon Hatt for the patch ([Issue 139](../issues/139)). - * Fixed issue with `GetApplicationPath()` returning wrong directory in some cases. All examples have been updated. See revision 6b141a8f54b4. - * Improvements to Linux installers (debian package, setup.py). See [Issue 149](../issues/149), [Issue 147](../issues/147), [Issue 145](../issues/145), [Issue 105](../issues/105), [Issue 99](../issues/99). - * Windows users can now install cefpython3 package from PyPI. [Issue 144](../issues/144). - -Version 31.0 released on August 1, 2014. - * Updated Chrome to version 31.0.1650.69 ([Issue 124](../issues/124)) - * Added Qt example on Linux ([Issue 88](../issues/88)) - * Added GTK example on Linux ([Issue 95](../issues/95)) - * Added High DPI support on Windows. See the DpiAware wiki page and the ApplicationSettings.`auto_zooming` option. Example usage is in the wxpython.py example. See [Issue 112](../issues/112), [Issue 128](../issues/128). - * Added Developer Tools support. See [Browser](Browser).`ShowDevTools`. Can be launched from mouse context menu as well. See also ApplicationSettings.`remote_debugging_port`, a default value of 0 enables devtools, to disable set it to -1. ([Issue 81](../issues/81)) - * Mouse context menu is now configurable, see ApplicationSettings.`context_menu`. New menu items added: "Reload", "Open in external browser", "Developer Tools". ([Issue 122](../issues/122)) - * Implemented a default DownloadHandler. File downloads are handled automatically with no additional code required. Added new option ApplicationSettings.`downloads_enabled`. ([Issue 87](../issues/87)) - * Exposed API for execution of tasks on various threads. This fixes problems with keyboard in popups in the wxpython.py example on Windows, an example usage is there. See [cefpython](cefpython).`PostTask`. See [Issue 61](../issues/61), [Issue 80](../issues/80). - * Fixed issues with embedding multiple browsers in tabs ([Issue 97](../issues/97)) - * Fixed CEF message loop processing in wx.chromectrl, it could cause performance penalties when opening multiple browser tabs/windows ([Issue 129](../issues/129)) - * Fixed the browser cleanup code in the `OnClose` event in the wxpython examples, it could possibly cause crashes during shutdown ([Issue 107](../issues/107)) - * Fixed a crash in V8 javascript bindings when a call to [Frame](Frame).`LoadUrl` changed origin (scheme + domain). For example when a redirect to a different domain was being made. This problem occured only when javascript bindings were set ([Issue 130](../issues/130)). - * Enabled caching on HTTPS even when there is certificate error, but only when ApplicationSettings.`ignore_certificate_errors` is set to True ([Issue 125](../issues/125)) - * Disabled tcmalloc hook on Linux in the CEF Python official binaries. It caused crashes when cefpython was not the very first library being imported ([Issue 73](../issues/73)). - * Added the JavascriptDialogHandler ([Issue 118](../issues/118)) - * Added new option ApplicationSettings.unique\_request\_context\_per\_browser - * Fixed problems with unique cookie manager per browser session. See notes in the RequestHandler.`GetCookieManager` callback ([Issue 126](../issues/126)). - * Fixed cookie problems during POST requests in the ResourceHandler example on Linux ([Issue 127](../issues/127)) - * Fixed loading of local file urls that contained hash ([Issue 114](../issues/114)) - * Added the [Browser](Browser).`GetUrl` and `LoadUrl` methods - * Redesigned the wxpython.py example. Added table of contents and source code highlighting among others. - * Moved DisplayHandler.`OnLoadingStateChange` to LoadHandler (does not affect code) - * Moved LoadHandler.`OnRendererProcessTerminated` and `OnPluginCrashed` to RequestHandler (does not affect code) - * Updated descriptions many of the settings on the [ApplicationSettings](ApplicationSettings) and [BrowserSettings](BrowserSettings) wiki pages. A certain set of options can now also be set using command line switches. - * Added new option ApplicationSettings.background\_color - -Version 29.4 released on January 15, 2014. - * Added `commandLineSwitches` param to [cefpython](cefpython).Initialize(). See the [CommandLineSwitches](CommandLineSwitches) wiki page. Thanks to Finn Hughes for the patch. See [Issue 65](../issues/65). - * Debug options set in python (debug and log\_file) are now shared with the C++ browser process code. See [Issue 98](../issues/98). - * Added new option "debug" to ApplicationSettings. Overwriting the g\_debug global variable in the cefpython module is now deprecated. See [Issue 100](../issues/100). - * See revisions: [fd0ed30fb387](https://code.google.com/p/cefpython/source/detail?r=fd0ed30fb387d515986b2d20b635a8f90a715c66) - -Version 29.3 released on January 13, 2014. - * `CreateBrowserSync()`, `Shutdown()` and others are now called without GIL (global interpreter lock), to avoid deadlocks, see [Issue 102](../issues/102). - * Added support for Distutils setup on Windows. Created MSI installer and Self-extracting zip for distribution using Distutils setup, see the BuildOnWindows wiki page for instructions ([Issue 108](../issues/108)). - * See revisions: [ec1ce788373b](https://code.google.com/p/cefpython/source/detail?r=ec1ce788373bb9e0fd2cedd71e900c3877e9185a), [00f8606dbebc](https://code.google.com/p/cefpython/source/detail?r=00f8606dbebc40a061049b213271d3a4fb3b04e3), [75a19a8a9a1a](https://code.google.com/p/cefpython/source/detail?r=75a19a8a9a1a9eeb92d98464bd040892430b6eac) - -Version 29.2 released on December 26, 2013. - * Debian packages support on Linux, see the ["Create a Debian package"](https://code.google.com/p/cefpython/wiki/BuildOnLinux#Create_a_Debian_package) section on the BuildOnLinux wiki page - * Fixes to [package installer on Windows](PackageInstallerOnWindows). Do not show examples in explorer window after installation has completed, when in /SILENT mode. - * Added LifespanHandler.`OnBeforePopup`, see [Issue 93](../issues/93). Thanks to Greg Farrell for the patch. - * Added RequestHandler.`OnBeforeBrowse`, see [Issue 94](../issues/94). Thanks to Greg Farrell for the patch. - * Added new methods to [Frame](Frame): `GetSource()` and `GetText()`. See [Issue 96](../issues/96). Thanks to Greg Farrell for the patch. - * See revisions: [13c472369c35](https://code.google.com/p/cefpython/source/detail?r=13c472369c356e41eda4caf82bcbe494a4cf6835), [f8abf0d73a64](https://code.google.com/p/cefpython/source/detail?r=f8abf0d73a646993e67065f1138e24bf9ae3691a), [893f4659f8e5](https://code.google.com/p/cefpython/source/detail?r=893f4659f8e570c334571ac0aa5c94b7b861856a), [be7029d302f3](https://code.google.com/p/cefpython/source/detail?r=be7029d302f36065dd7aa091d82987f7c6b18eb6), [dcbbd8edf0a0](https://code.google.com/p/cefpython/source/detail?r=dcbbd8edf0a0fec617fa7e4acb41a318755ae84e) - -Version 29.1 released on December 15, 2013 - * Updated Package Installer (Inno Setup Exe), the command line installation process with /SILENT flag does not require user interaction anymore. Also by default it will uninstall any existing cefpython3 package. - * Fixes to the wx examples (both wxpython.py and wx.chromectrl), changed behavior of browser cleanup on close. By default a timer is used to process CEF message loop work, earlier it was EVT\_IDLE. - * See revision [9bc68b3954ae](https://code.google.com/p/cefpython/source/detail?r=9bc68b3954ae0ac1a889060e756335bedfbda435) - -Version 29.0 released on November 1, 2013. - * Updated to Chrome 29.0.1547.80 CEF rev. 1491 - * Added [cefpython](cefpython).`SetOsModalLoop()`. - * Added [Browser](Browser).`Print()`, `Find()`, `StopFinding()`. - -Version 27.6 released on September 24, 2013. - * Implemented response reading features: [RequestHandler](RequestHandler).`GetResourceHandler()`, [ResourceHandler](ResourceHandler), [Response](Response), [WebRequest](WebRequest), [WebRequestClient](WebRequestClient), [Callback](Callback). - * Added [wxpython-response.py](https://code.google.com/p/cefpython/source/browse/cefpython/cef3/linux/binaries_64bit/wxpython-response.py?r=c08fc026e625) script that emulates `OnResourceResponse` callback (not yet available in CEF 3) by utilizing [ResourceHandler](ResourceHandler) and [WebRequest](WebRequest). - * This release was sponsored by Thomas Wusatiuk - -Version 27.5 released on September 18, 2013. - * Added support for the ` -
      -
      You should see the reverse of your message below: -
      - - - diff --git a/cefpython/cef3/linux/binaries_64bit/files/dialogs.html b/cefpython/cef3/linux/binaries_64bit/files/dialogs.html deleted file mode 100644 index b815a5e42..000000000 --- a/cefpython/cef3/linux/binaries_64bit/files/dialogs.html +++ /dev/null @@ -1,64 +0,0 @@ - - -Dialog Test - - - -
      -Click a button to show the associated dialog type. -
      -
      -
      -
      input type="file": -
      -
      -
      -

      -
      - - diff --git a/cefpython/cef3/linux/binaries_64bit/files/domaccess.html b/cefpython/cef3/linux/binaries_64bit/files/domaccess.html deleted file mode 100644 index 87bd23e38..000000000 --- a/cefpython/cef3/linux/binaries_64bit/files/domaccess.html +++ /dev/null @@ -1,13 +0,0 @@ - - -

      Select some portion of the below page content and click the "Describe Selection" button. The selected region will then be described below.

      -

      This is p1

      -

      This is p2

      -

      This is p3

      -

      This is p4

      -
      - -

      The description will appear here.

      -
      - - diff --git a/cefpython/cef3/linux/binaries_64bit/files/localstorage.html b/cefpython/cef3/linux/binaries_64bit/files/localstorage.html deleted file mode 100644 index 87c6e68cb..000000000 --- a/cefpython/cef3/linux/binaries_64bit/files/localstorage.html +++ /dev/null @@ -1,24 +0,0 @@ - - - -Click the "Add Line" button to add a line or the "Clear" button to clear.
      -This data will persist across sessions if a cache path was specified.
      - - -
      - - - diff --git a/cefpython/cef3/linux/binaries_64bit/files/logo.png b/cefpython/cef3/linux/binaries_64bit/files/logo.png deleted file mode 100644 index 41dd728df08295acf843dce12d9d19a342922df7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19879 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 eIt+)cS^poYk|IgQ(8)vq0000 - OSR Test - - - -

      - OSR Testing h1 - Focus and blur - - this page and will get this red black -

      -
        -
      1. OnPaint should be called each time a page loads
      2. -
      3. Move mouse - to require an OnCursorChange call
      4. -
      5. Hover will color this with - red. Will trigger OnPaint once on enter and once on leave
      6. -
      7. Right clicking will show contextual menu and will request - GetScreenPoint
      8. -
      9. IsWindowRenderingDisabled should be true
      10. -
      11. WasResized should trigger full repaint if size changes. -
      12. -
      13. Invalidate should trigger OnPaint once
      14. -
      15. Click and write here with SendKeyEvent to trigger repaints: -
      16. -
      17. Click here with SendMouseClickEvent to navigate: -
      18. -
      19. Mouse over this element will - trigger show a tooltip
      20. -
      -
      -
      -
      -
      -
      -
      - - diff --git a/cefpython/cef3/linux/binaries_64bit/files/other_tests.html b/cefpython/cef3/linux/binaries_64bit/files/other_tests.html deleted file mode 100644 index a36ca4538..000000000 --- a/cefpython/cef3/linux/binaries_64bit/files/other_tests.html +++ /dev/null @@ -1,33 +0,0 @@ - - -Other Tests - - -

      Various other internal and external tests.

      - - - diff --git a/cefpython/cef3/linux/binaries_64bit/files/performance.html b/cefpython/cef3/linux/binaries_64bit/files/performance.html deleted file mode 100644 index aa64d51d7..000000000 --- a/cefpython/cef3/linux/binaries_64bit/files/performance.html +++ /dev/null @@ -1,293 +0,0 @@ - - - - Performance Tests - - - -

      Performance Tests

      - Filter: -
      - -
      - - - - - - - - - - - - - -
      NameIterations per RunAvg (ms)Min (ms)Max (ms)StdDev (ms)Runs (ms)
      -
      - -
      - - Result 1: -
      Result 2: -
      - -
      - - - - - - - - - - -
      NameResult 1 Avg (ms)Result 2 Avg (ms)% Diff
      -
      - - - - - diff --git a/cefpython/cef3/linux/binaries_64bit/files/performance2.html b/cefpython/cef3/linux/binaries_64bit/files/performance2.html deleted file mode 100644 index 6664de7b2..000000000 --- a/cefpython/cef3/linux/binaries_64bit/files/performance2.html +++ /dev/null @@ -1,442 +0,0 @@ - - - - Performance Tests (2) - - - -

      Performance Tests (2)

      - -
      - - - - - - - - - - - - - - - - - - - -
      Settings:
      Iterations:
      Samples:
      Mode:Asynchronous - Synchronous -
      -
      - - -
      - -
      - - - - - - - - - - - - - - - - - - - -
      EnabledNameSamples x IterationsMin, msAvg, msMax, msAverage calls/secMeasuring InacurracyMemory, MBMemory delta, MBDescription
      -
      - - - - - diff --git a/cefpython/cef3/linux/binaries_64bit/files/transparency.html b/cefpython/cef3/linux/binaries_64bit/files/transparency.html deleted file mode 100644 index a8dd3b46e..000000000 --- a/cefpython/cef3/linux/binaries_64bit/files/transparency.html +++ /dev/null @@ -1,63 +0,0 @@ - - - -Transparency Examples - - - - -

      Image Transparency

      -Hover over an image to make it fully opaque.
      -klematis -klematis - -

      Block Transparency

      -White 0% White 25% White 50% White 75% White 100% -
      -Black 0% Black 25% Black 50% Black 75% Black 100% - - - diff --git a/cefpython/cef3/linux/binaries_64bit/files/window.html b/cefpython/cef3/linux/binaries_64bit/files/window.html deleted file mode 100644 index 4521ccb5f..000000000 --- a/cefpython/cef3/linux/binaries_64bit/files/window.html +++ /dev/null @@ -1,44 +0,0 @@ - - -Window Test - - - -
      -Click a button to perform the associated window action. -
      -
      -
      (minimizes and then restores the window as topmost) -
      X: Y: Width: Height: -
      - - diff --git a/cefpython/cef3/linux/binaries_64bit/files/xmlhttprequest.html b/cefpython/cef3/linux/binaries_64bit/files/xmlhttprequest.html deleted file mode 100644 index 051f81486..000000000 --- a/cefpython/cef3/linux/binaries_64bit/files/xmlhttprequest.html +++ /dev/null @@ -1,19 +0,0 @@ - - - -
      -URL: -
      -
      -
      - - diff --git a/cefpython/cef3/wx-subpackage/__init__.py b/cefpython/cef3/wx-subpackage/__init__.py deleted file mode 100644 index 340aae166..000000000 --- a/cefpython/cef3/wx-subpackage/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# This dummy file is overwritten by "__init__.py.template", see: -# cefpython/cef3/windows/installer/ -# cefpython/cef3/linux/installer/ diff --git a/cefpython/cef3/cefpython_public_api.h b/cefpython/cefpython_public_api.h similarity index 100% rename from cefpython/cef3/cefpython_public_api.h rename to cefpython/cefpython_public_api.h diff --git a/cefpython/cef3/client_handler/.gitignore b/cefpython/client_handler/.gitignore similarity index 100% rename from cefpython/cef3/client_handler/.gitignore rename to cefpython/client_handler/.gitignore diff --git a/cefpython/cef3/client_handler/Makefile b/cefpython/client_handler/Makefile similarity index 100% rename from cefpython/cef3/client_handler/Makefile rename to cefpython/client_handler/Makefile diff --git a/cefpython/cef3/client_handler/client_handler.cpp b/cefpython/client_handler/client_handler.cpp similarity index 100% rename from cefpython/cef3/client_handler/client_handler.cpp rename to cefpython/client_handler/client_handler.cpp diff --git a/cefpython/cef3/client_handler/client_handler.h b/cefpython/client_handler/client_handler.h similarity index 100% rename from cefpython/cef3/client_handler/client_handler.h rename to cefpython/client_handler/client_handler.h diff --git a/cefpython/cef3/client_handler/client_handler_py27_32bit.vcproj b/cefpython/client_handler/client_handler_py27_32bit.vcproj similarity index 100% rename from cefpython/cef3/client_handler/client_handler_py27_32bit.vcproj rename to cefpython/client_handler/client_handler_py27_32bit.vcproj diff --git a/cefpython/cef3/client_handler/client_handler_py27_64bit.vcproj b/cefpython/client_handler/client_handler_py27_64bit.vcproj similarity index 100% rename from cefpython/cef3/client_handler/client_handler_py27_64bit.vcproj rename to cefpython/client_handler/client_handler_py27_64bit.vcproj diff --git a/cefpython/cef3/client_handler/client_handler_py34_32bit.vcproj b/cefpython/client_handler/client_handler_py34_32bit.vcproj similarity index 100% rename from cefpython/cef3/client_handler/client_handler_py34_32bit.vcproj rename to cefpython/client_handler/client_handler_py34_32bit.vcproj diff --git a/cefpython/cef3/client_handler/cookie_visitor.cpp b/cefpython/client_handler/cookie_visitor.cpp similarity index 100% rename from cefpython/cef3/client_handler/cookie_visitor.cpp rename to cefpython/client_handler/cookie_visitor.cpp diff --git a/cefpython/cef3/client_handler/cookie_visitor.h b/cefpython/client_handler/cookie_visitor.h similarity index 100% rename from cefpython/cef3/client_handler/cookie_visitor.h rename to cefpython/client_handler/cookie_visitor.h diff --git a/cefpython/cef3/client_handler/dpi_aware.cpp b/cefpython/client_handler/dpi_aware.cpp similarity index 100% rename from cefpython/cef3/client_handler/dpi_aware.cpp rename to cefpython/client_handler/dpi_aware.cpp diff --git a/cefpython/cef3/client_handler/dpi_aware.h b/cefpython/client_handler/dpi_aware.h similarity index 100% rename from cefpython/cef3/client_handler/dpi_aware.h rename to cefpython/client_handler/dpi_aware.h diff --git a/cefpython/cef3/client_handler/request_context_handler.cpp b/cefpython/client_handler/request_context_handler.cpp similarity index 100% rename from cefpython/cef3/client_handler/request_context_handler.cpp rename to cefpython/client_handler/request_context_handler.cpp diff --git a/cefpython/cef3/client_handler/request_context_handler.h b/cefpython/client_handler/request_context_handler.h similarity index 100% rename from cefpython/cef3/client_handler/request_context_handler.h rename to cefpython/client_handler/request_context_handler.h diff --git a/cefpython/cef3/client_handler/resource_handler.cpp b/cefpython/client_handler/resource_handler.cpp similarity index 100% rename from cefpython/cef3/client_handler/resource_handler.cpp rename to cefpython/client_handler/resource_handler.cpp diff --git a/cefpython/cef3/client_handler/resource_handler.h b/cefpython/client_handler/resource_handler.h similarity index 100% rename from cefpython/cef3/client_handler/resource_handler.h rename to cefpython/client_handler/resource_handler.h diff --git a/cefpython/cef3/client_handler/string_visitor.cpp b/cefpython/client_handler/string_visitor.cpp similarity index 100% rename from cefpython/cef3/client_handler/string_visitor.cpp rename to cefpython/client_handler/string_visitor.cpp diff --git a/cefpython/cef3/client_handler/string_visitor.h b/cefpython/client_handler/string_visitor.h similarity index 100% rename from cefpython/cef3/client_handler/string_visitor.h rename to cefpython/client_handler/string_visitor.h diff --git a/cefpython/cef3/client_handler/task.cpp b/cefpython/client_handler/task.cpp similarity index 100% rename from cefpython/cef3/client_handler/task.cpp rename to cefpython/client_handler/task.cpp diff --git a/cefpython/cef3/client_handler/task.h b/cefpython/client_handler/task.h similarity index 100% rename from cefpython/cef3/client_handler/task.h rename to cefpython/client_handler/task.h diff --git a/cefpython/cef3/client_handler/util_mac.h b/cefpython/client_handler/util_mac.h similarity index 100% rename from cefpython/cef3/client_handler/util_mac.h rename to cefpython/client_handler/util_mac.h diff --git a/cefpython/cef3/client_handler/util_mac.mm b/cefpython/client_handler/util_mac.mm similarity index 100% rename from cefpython/cef3/client_handler/util_mac.mm rename to cefpython/client_handler/util_mac.mm diff --git a/cefpython/cef3/client_handler/web_request_client.cpp b/cefpython/client_handler/web_request_client.cpp similarity index 100% rename from cefpython/cef3/client_handler/web_request_client.cpp rename to cefpython/client_handler/web_request_client.cpp diff --git a/cefpython/cef3/client_handler/web_request_client.h b/cefpython/client_handler/web_request_client.h similarity index 100% rename from cefpython/cef3/client_handler/web_request_client.h rename to cefpython/client_handler/web_request_client.h diff --git a/cefpython/cef3/include/cef_app.h b/cefpython/include/cef_app.h similarity index 100% rename from cefpython/cef3/include/cef_app.h rename to cefpython/include/cef_app.h diff --git a/cefpython/cef3/include/cef_application_mac.h b/cefpython/include/cef_application_mac.h similarity index 100% rename from cefpython/cef3/include/cef_application_mac.h rename to cefpython/include/cef_application_mac.h diff --git a/cefpython/cef3/include/cef_auth_callback.h b/cefpython/include/cef_auth_callback.h similarity index 100% rename from cefpython/cef3/include/cef_auth_callback.h rename to cefpython/include/cef_auth_callback.h diff --git a/cefpython/cef3/include/cef_base.h b/cefpython/include/cef_base.h similarity index 100% rename from cefpython/cef3/include/cef_base.h rename to cefpython/include/cef_base.h diff --git a/cefpython/cef3/include/cef_browser.h b/cefpython/include/cef_browser.h similarity index 100% rename from cefpython/cef3/include/cef_browser.h rename to cefpython/include/cef_browser.h diff --git a/cefpython/cef3/include/cef_browser_process_handler.h b/cefpython/include/cef_browser_process_handler.h similarity index 100% rename from cefpython/cef3/include/cef_browser_process_handler.h rename to cefpython/include/cef_browser_process_handler.h diff --git a/cefpython/cef3/include/cef_callback.h b/cefpython/include/cef_callback.h similarity index 100% rename from cefpython/cef3/include/cef_callback.h rename to cefpython/include/cef_callback.h diff --git a/cefpython/cef3/include/cef_client.h b/cefpython/include/cef_client.h similarity index 100% rename from cefpython/cef3/include/cef_client.h rename to cefpython/include/cef_client.h diff --git a/cefpython/cef3/include/cef_command_line.h b/cefpython/include/cef_command_line.h similarity index 100% rename from cefpython/cef3/include/cef_command_line.h rename to cefpython/include/cef_command_line.h diff --git a/cefpython/cef3/include/cef_context_menu_handler.h b/cefpython/include/cef_context_menu_handler.h similarity index 100% rename from cefpython/cef3/include/cef_context_menu_handler.h rename to cefpython/include/cef_context_menu_handler.h diff --git a/cefpython/cef3/include/cef_cookie.h b/cefpython/include/cef_cookie.h similarity index 100% rename from cefpython/cef3/include/cef_cookie.h rename to cefpython/include/cef_cookie.h diff --git a/cefpython/cef3/include/cef_dialog_handler.h b/cefpython/include/cef_dialog_handler.h similarity index 100% rename from cefpython/cef3/include/cef_dialog_handler.h rename to cefpython/include/cef_dialog_handler.h diff --git a/cefpython/cef3/include/cef_display_handler.h b/cefpython/include/cef_display_handler.h similarity index 100% rename from cefpython/cef3/include/cef_display_handler.h rename to cefpython/include/cef_display_handler.h diff --git a/cefpython/cef3/include/cef_dom.h b/cefpython/include/cef_dom.h similarity index 100% rename from cefpython/cef3/include/cef_dom.h rename to cefpython/include/cef_dom.h diff --git a/cefpython/cef3/include/cef_download_handler.h b/cefpython/include/cef_download_handler.h similarity index 100% rename from cefpython/cef3/include/cef_download_handler.h rename to cefpython/include/cef_download_handler.h diff --git a/cefpython/cef3/include/cef_download_item.h b/cefpython/include/cef_download_item.h similarity index 100% rename from cefpython/cef3/include/cef_download_item.h rename to cefpython/include/cef_download_item.h diff --git a/cefpython/cef3/include/cef_drag_data.h b/cefpython/include/cef_drag_data.h similarity index 100% rename from cefpython/cef3/include/cef_drag_data.h rename to cefpython/include/cef_drag_data.h diff --git a/cefpython/cef3/include/cef_drag_handler.h b/cefpython/include/cef_drag_handler.h similarity index 100% rename from cefpython/cef3/include/cef_drag_handler.h rename to cefpython/include/cef_drag_handler.h diff --git a/cefpython/cef3/include/cef_focus_handler.h b/cefpython/include/cef_focus_handler.h similarity index 100% rename from cefpython/cef3/include/cef_focus_handler.h rename to cefpython/include/cef_focus_handler.h diff --git a/cefpython/cef3/include/cef_frame.h b/cefpython/include/cef_frame.h similarity index 100% rename from cefpython/cef3/include/cef_frame.h rename to cefpython/include/cef_frame.h diff --git a/cefpython/cef3/include/cef_geolocation.h b/cefpython/include/cef_geolocation.h similarity index 100% rename from cefpython/cef3/include/cef_geolocation.h rename to cefpython/include/cef_geolocation.h diff --git a/cefpython/cef3/include/cef_geolocation_handler.h b/cefpython/include/cef_geolocation_handler.h similarity index 100% rename from cefpython/cef3/include/cef_geolocation_handler.h rename to cefpython/include/cef_geolocation_handler.h diff --git a/cefpython/cef3/include/cef_jsdialog_handler.h b/cefpython/include/cef_jsdialog_handler.h similarity index 100% rename from cefpython/cef3/include/cef_jsdialog_handler.h rename to cefpython/include/cef_jsdialog_handler.h diff --git a/cefpython/cef3/include/cef_keyboard_handler.h b/cefpython/include/cef_keyboard_handler.h similarity index 100% rename from cefpython/cef3/include/cef_keyboard_handler.h rename to cefpython/include/cef_keyboard_handler.h diff --git a/cefpython/cef3/include/cef_life_span_handler.h b/cefpython/include/cef_life_span_handler.h similarity index 100% rename from cefpython/cef3/include/cef_life_span_handler.h rename to cefpython/include/cef_life_span_handler.h diff --git a/cefpython/cef3/include/cef_load_handler.h b/cefpython/include/cef_load_handler.h similarity index 100% rename from cefpython/cef3/include/cef_load_handler.h rename to cefpython/include/cef_load_handler.h diff --git a/cefpython/cef3/include/cef_menu_model.h b/cefpython/include/cef_menu_model.h similarity index 100% rename from cefpython/cef3/include/cef_menu_model.h rename to cefpython/include/cef_menu_model.h diff --git a/cefpython/cef3/include/cef_origin_whitelist.h b/cefpython/include/cef_origin_whitelist.h similarity index 100% rename from cefpython/cef3/include/cef_origin_whitelist.h rename to cefpython/include/cef_origin_whitelist.h diff --git a/cefpython/cef3/include/cef_path_util.h b/cefpython/include/cef_path_util.h similarity index 100% rename from cefpython/cef3/include/cef_path_util.h rename to cefpython/include/cef_path_util.h diff --git a/cefpython/cef3/include/cef_process_message.h b/cefpython/include/cef_process_message.h similarity index 100% rename from cefpython/cef3/include/cef_process_message.h rename to cefpython/include/cef_process_message.h diff --git a/cefpython/cef3/include/cef_process_util.h b/cefpython/include/cef_process_util.h similarity index 100% rename from cefpython/cef3/include/cef_process_util.h rename to cefpython/include/cef_process_util.h diff --git a/cefpython/cef3/include/cef_render_handler.h b/cefpython/include/cef_render_handler.h similarity index 100% rename from cefpython/cef3/include/cef_render_handler.h rename to cefpython/include/cef_render_handler.h diff --git a/cefpython/cef3/include/cef_render_process_handler.h b/cefpython/include/cef_render_process_handler.h similarity index 100% rename from cefpython/cef3/include/cef_render_process_handler.h rename to cefpython/include/cef_render_process_handler.h diff --git a/cefpython/cef3/include/cef_request.h b/cefpython/include/cef_request.h similarity index 100% rename from cefpython/cef3/include/cef_request.h rename to cefpython/include/cef_request.h diff --git a/cefpython/cef3/include/cef_request_context.h b/cefpython/include/cef_request_context.h similarity index 100% rename from cefpython/cef3/include/cef_request_context.h rename to cefpython/include/cef_request_context.h diff --git a/cefpython/cef3/include/cef_request_context_handler.h b/cefpython/include/cef_request_context_handler.h similarity index 100% rename from cefpython/cef3/include/cef_request_context_handler.h rename to cefpython/include/cef_request_context_handler.h diff --git a/cefpython/cef3/include/cef_request_handler.h b/cefpython/include/cef_request_handler.h similarity index 100% rename from cefpython/cef3/include/cef_request_handler.h rename to cefpython/include/cef_request_handler.h diff --git a/cefpython/cef3/include/cef_resource_bundle_handler.h b/cefpython/include/cef_resource_bundle_handler.h similarity index 100% rename from cefpython/cef3/include/cef_resource_bundle_handler.h rename to cefpython/include/cef_resource_bundle_handler.h diff --git a/cefpython/cef3/include/cef_resource_handler.h b/cefpython/include/cef_resource_handler.h similarity index 100% rename from cefpython/cef3/include/cef_resource_handler.h rename to cefpython/include/cef_resource_handler.h diff --git a/cefpython/cef3/include/cef_response.h b/cefpython/include/cef_response.h similarity index 100% rename from cefpython/cef3/include/cef_response.h rename to cefpython/include/cef_response.h diff --git a/cefpython/cef3/include/cef_runnable.h b/cefpython/include/cef_runnable.h similarity index 100% rename from cefpython/cef3/include/cef_runnable.h rename to cefpython/include/cef_runnable.h diff --git a/cefpython/cef3/include/cef_scheme.h b/cefpython/include/cef_scheme.h similarity index 100% rename from cefpython/cef3/include/cef_scheme.h rename to cefpython/include/cef_scheme.h diff --git a/cefpython/cef3/include/cef_stream.h b/cefpython/include/cef_stream.h similarity index 100% rename from cefpython/cef3/include/cef_stream.h rename to cefpython/include/cef_stream.h diff --git a/cefpython/cef3/include/cef_string_visitor.h b/cefpython/include/cef_string_visitor.h similarity index 100% rename from cefpython/cef3/include/cef_string_visitor.h rename to cefpython/include/cef_string_visitor.h diff --git a/cefpython/cef3/include/cef_task.h b/cefpython/include/cef_task.h similarity index 100% rename from cefpython/cef3/include/cef_task.h rename to cefpython/include/cef_task.h diff --git a/cefpython/cef3/include/cef_trace.h b/cefpython/include/cef_trace.h similarity index 100% rename from cefpython/cef3/include/cef_trace.h rename to cefpython/include/cef_trace.h diff --git a/cefpython/cef3/include/cef_trace_event.h b/cefpython/include/cef_trace_event.h similarity index 100% rename from cefpython/cef3/include/cef_trace_event.h rename to cefpython/include/cef_trace_event.h diff --git a/cefpython/cef3/include/cef_url.h b/cefpython/include/cef_url.h similarity index 100% rename from cefpython/cef3/include/cef_url.h rename to cefpython/include/cef_url.h diff --git a/cefpython/cef3/include/cef_urlrequest.h b/cefpython/include/cef_urlrequest.h similarity index 100% rename from cefpython/cef3/include/cef_urlrequest.h rename to cefpython/include/cef_urlrequest.h diff --git a/cefpython/cef3/include/cef_v8.h b/cefpython/include/cef_v8.h similarity index 100% rename from cefpython/cef3/include/cef_v8.h rename to cefpython/include/cef_v8.h diff --git a/cefpython/cef3/include/cef_values.h b/cefpython/include/cef_values.h similarity index 100% rename from cefpython/cef3/include/cef_values.h rename to cefpython/include/cef_values.h diff --git a/cefpython/cef3/include/cef_web_plugin.h b/cefpython/include/cef_web_plugin.h similarity index 100% rename from cefpython/cef3/include/cef_web_plugin.h rename to cefpython/include/cef_web_plugin.h diff --git a/cefpython/cef3/include/cef_xml_reader.h b/cefpython/include/cef_xml_reader.h similarity index 100% rename from cefpython/cef3/include/cef_xml_reader.h rename to cefpython/include/cef_xml_reader.h diff --git a/cefpython/cef3/include/cef_zip_reader.h b/cefpython/include/cef_zip_reader.h similarity index 100% rename from cefpython/cef3/include/cef_zip_reader.h rename to cefpython/include/cef_zip_reader.h diff --git a/cefpython/cef3/include/internal/cef_build.h b/cefpython/include/internal/cef_build.h similarity index 100% rename from cefpython/cef3/include/internal/cef_build.h rename to cefpython/include/internal/cef_build.h diff --git a/cefpython/cef3/include/internal/cef_export.h b/cefpython/include/internal/cef_export.h similarity index 100% rename from cefpython/cef3/include/internal/cef_export.h rename to cefpython/include/internal/cef_export.h diff --git a/cefpython/cef3/include/internal/cef_linux.h b/cefpython/include/internal/cef_linux.h similarity index 100% rename from cefpython/cef3/include/internal/cef_linux.h rename to cefpython/include/internal/cef_linux.h diff --git a/cefpython/cef3/include/internal/cef_mac.h b/cefpython/include/internal/cef_mac.h similarity index 100% rename from cefpython/cef3/include/internal/cef_mac.h rename to cefpython/include/internal/cef_mac.h diff --git a/cefpython/cef3/include/internal/cef_ptr.h b/cefpython/include/internal/cef_ptr.h similarity index 100% rename from cefpython/cef3/include/internal/cef_ptr.h rename to cefpython/include/internal/cef_ptr.h diff --git a/cefpython/cef3/include/internal/cef_string.h b/cefpython/include/internal/cef_string.h similarity index 100% rename from cefpython/cef3/include/internal/cef_string.h rename to cefpython/include/internal/cef_string.h diff --git a/cefpython/cef3/include/internal/cef_string_list.h b/cefpython/include/internal/cef_string_list.h similarity index 100% rename from cefpython/cef3/include/internal/cef_string_list.h rename to cefpython/include/internal/cef_string_list.h diff --git a/cefpython/cef3/include/internal/cef_string_map.h b/cefpython/include/internal/cef_string_map.h similarity index 100% rename from cefpython/cef3/include/internal/cef_string_map.h rename to cefpython/include/internal/cef_string_map.h diff --git a/cefpython/cef3/include/internal/cef_string_multimap.h b/cefpython/include/internal/cef_string_multimap.h similarity index 100% rename from cefpython/cef3/include/internal/cef_string_multimap.h rename to cefpython/include/internal/cef_string_multimap.h diff --git a/cefpython/cef3/include/internal/cef_string_types.h b/cefpython/include/internal/cef_string_types.h similarity index 100% rename from cefpython/cef3/include/internal/cef_string_types.h rename to cefpython/include/internal/cef_string_types.h diff --git a/cefpython/cef3/include/internal/cef_string_wrappers.h b/cefpython/include/internal/cef_string_wrappers.h similarity index 100% rename from cefpython/cef3/include/internal/cef_string_wrappers.h rename to cefpython/include/internal/cef_string_wrappers.h diff --git a/cefpython/cef3/include/internal/cef_time.h b/cefpython/include/internal/cef_time.h similarity index 100% rename from cefpython/cef3/include/internal/cef_time.h rename to cefpython/include/internal/cef_time.h diff --git a/cefpython/cef3/include/internal/cef_tuple.h b/cefpython/include/internal/cef_tuple.h similarity index 100% rename from cefpython/cef3/include/internal/cef_tuple.h rename to cefpython/include/internal/cef_tuple.h diff --git a/cefpython/cef3/include/internal/cef_types.h b/cefpython/include/internal/cef_types.h similarity index 100% rename from cefpython/cef3/include/internal/cef_types.h rename to cefpython/include/internal/cef_types.h diff --git a/cefpython/cef3/include/internal/cef_types_linux.h b/cefpython/include/internal/cef_types_linux.h similarity index 100% rename from cefpython/cef3/include/internal/cef_types_linux.h rename to cefpython/include/internal/cef_types_linux.h diff --git a/cefpython/cef3/include/internal/cef_types_mac.h b/cefpython/include/internal/cef_types_mac.h similarity index 100% rename from cefpython/cef3/include/internal/cef_types_mac.h rename to cefpython/include/internal/cef_types_mac.h diff --git a/cefpython/cef3/include/internal/cef_types_win.h b/cefpython/include/internal/cef_types_win.h similarity index 100% rename from cefpython/cef3/include/internal/cef_types_win.h rename to cefpython/include/internal/cef_types_win.h diff --git a/cefpython/cef3/include/internal/cef_types_wrappers.h b/cefpython/include/internal/cef_types_wrappers.h similarity index 100% rename from cefpython/cef3/include/internal/cef_types_wrappers.h rename to cefpython/include/internal/cef_types_wrappers.h diff --git a/cefpython/cef3/include/internal/cef_win.h b/cefpython/include/internal/cef_win.h similarity index 100% rename from cefpython/cef3/include/internal/cef_win.h rename to cefpython/include/internal/cef_win.h diff --git a/cefpython/cef3/include/wrapper/cef_byte_read_handler.h b/cefpython/include/wrapper/cef_byte_read_handler.h similarity index 100% rename from cefpython/cef3/include/wrapper/cef_byte_read_handler.h rename to cefpython/include/wrapper/cef_byte_read_handler.h diff --git a/cefpython/cef3/include/wrapper/cef_stream_resource_handler.h b/cefpython/include/wrapper/cef_stream_resource_handler.h similarity index 100% rename from cefpython/cef3/include/wrapper/cef_stream_resource_handler.h rename to cefpython/include/wrapper/cef_stream_resource_handler.h diff --git a/cefpython/cef3/include/wrapper/cef_xml_object.h b/cefpython/include/wrapper/cef_xml_object.h similarity index 100% rename from cefpython/cef3/include/wrapper/cef_xml_object.h rename to cefpython/include/wrapper/cef_xml_object.h diff --git a/cefpython/cef3/include/wrapper/cef_zip_archive.h b/cefpython/include/wrapper/cef_zip_archive.h similarity index 100% rename from cefpython/cef3/include/wrapper/cef_zip_archive.h rename to cefpython/include/wrapper/cef_zip_archive.h diff --git a/cefpython/cef3/linux/.gitignore b/cefpython/linux/.gitignore similarity index 100% rename from cefpython/cef3/linux/.gitignore rename to cefpython/linux/.gitignore diff --git a/cefpython/cef3/linux/CEF-GTK-patch.txt b/cefpython/linux/CEF-GTK-patch.txt similarity index 100% rename from cefpython/cef3/linux/CEF-GTK-patch.txt rename to cefpython/linux/CEF-GTK-patch.txt diff --git a/cefpython/cef3/linux/binaries_32bit/LICENSE.txt b/cefpython/linux/binaries_32bit/LICENSE.txt similarity index 100% rename from cefpython/cef3/linux/binaries_32bit/LICENSE.txt rename to cefpython/linux/binaries_32bit/LICENSE.txt diff --git a/cefpython/cef3/linux/binaries_32bit/README.txt b/cefpython/linux/binaries_32bit/README.txt similarity index 100% rename from cefpython/cef3/linux/binaries_32bit/README.txt rename to cefpython/linux/binaries_32bit/README.txt diff --git a/cefpython/cef3/linux/binaries_32bit/example.html b/cefpython/linux/binaries_32bit/example.html similarity index 100% rename from cefpython/cef3/linux/binaries_32bit/example.html rename to cefpython/linux/binaries_32bit/example.html diff --git a/cefpython/cef3/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.css b/cefpython/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.css old mode 100755 new mode 100644 similarity index 100% rename from cefpython/cef3/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.css rename to cefpython/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.css diff --git a/cefpython/cef3/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.js b/cefpython/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.js old mode 100755 new mode 100644 similarity index 100% rename from cefpython/cef3/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.js rename to cefpython/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.js diff --git a/cefpython/cef3/linux/binaries_32bit/kivy-select-boxes/kivy-test.html b/cefpython/linux/binaries_32bit/kivy-select-boxes/kivy-test.html similarity index 100% rename from cefpython/cef3/linux/binaries_32bit/kivy-select-boxes/kivy-test.html rename to cefpython/linux/binaries_32bit/kivy-select-boxes/kivy-test.html diff --git a/cefpython/cef3/linux/binaries_32bit/kivy-select-boxes/readme.md b/cefpython/linux/binaries_32bit/kivy-select-boxes/readme.md old mode 100755 new mode 100644 similarity index 100% rename from cefpython/cef3/linux/binaries_32bit/kivy-select-boxes/readme.md rename to cefpython/linux/binaries_32bit/kivy-select-boxes/readme.md diff --git a/cefpython/cef3/linux/binaries_32bit/kivy_.py b/cefpython/linux/binaries_32bit/kivy_.py similarity index 100% rename from cefpython/cef3/linux/binaries_32bit/kivy_.py rename to cefpython/linux/binaries_32bit/kivy_.py diff --git a/cefpython/cef3/linux/binaries_32bit/prism.css b/cefpython/linux/binaries_32bit/prism.css similarity index 100% rename from cefpython/cef3/linux/binaries_32bit/prism.css rename to cefpython/linux/binaries_32bit/prism.css diff --git a/cefpython/cef3/linux/binaries_32bit/prism.js b/cefpython/linux/binaries_32bit/prism.js similarity index 100% rename from cefpython/cef3/linux/binaries_32bit/prism.js rename to cefpython/linux/binaries_32bit/prism.js diff --git a/cefpython/cef3/linux/binaries_32bit/pygtk_.py b/cefpython/linux/binaries_32bit/pygtk_.py similarity index 100% rename from cefpython/cef3/linux/binaries_32bit/pygtk_.py rename to cefpython/linux/binaries_32bit/pygtk_.py diff --git a/cefpython/cef3/linux/binaries_32bit/pyqt.py b/cefpython/linux/binaries_32bit/pyqt.py similarity index 100% rename from cefpython/cef3/linux/binaries_32bit/pyqt.py rename to cefpython/linux/binaries_32bit/pyqt.py diff --git a/cefpython/cef3/linux/binaries_32bit/wxpython-response.py b/cefpython/linux/binaries_32bit/wxpython-response.py similarity index 100% rename from cefpython/cef3/linux/binaries_32bit/wxpython-response.py rename to cefpython/linux/binaries_32bit/wxpython-response.py diff --git a/cefpython/cef3/linux/binaries_32bit/wxpython.html b/cefpython/linux/binaries_32bit/wxpython.html similarity index 100% rename from cefpython/cef3/linux/binaries_32bit/wxpython.html rename to cefpython/linux/binaries_32bit/wxpython.html diff --git a/cefpython/cef3/linux/binaries_32bit/wxpython.py b/cefpython/linux/binaries_32bit/wxpython.py similarity index 100% rename from cefpython/cef3/linux/binaries_32bit/wxpython.py rename to cefpython/linux/binaries_32bit/wxpython.py diff --git a/cefpython/cef3/linux/binaries_64bit/LICENSE.txt b/cefpython/linux/binaries_64bit/LICENSE.txt similarity index 100% rename from cefpython/cef3/linux/binaries_64bit/LICENSE.txt rename to cefpython/linux/binaries_64bit/LICENSE.txt diff --git a/cefpython/cef3/linux/binaries_64bit/README.txt b/cefpython/linux/binaries_64bit/README.txt similarity index 100% rename from cefpython/cef3/linux/binaries_64bit/README.txt rename to cefpython/linux/binaries_64bit/README.txt diff --git a/cefpython/cef3/linux/binaries_64bit/example.html b/cefpython/linux/binaries_64bit/example.html similarity index 100% rename from cefpython/cef3/linux/binaries_64bit/example.html rename to cefpython/linux/binaries_64bit/example.html diff --git a/cefpython/cef3/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.css b/cefpython/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.css old mode 100755 new mode 100644 similarity index 100% rename from cefpython/cef3/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.css rename to cefpython/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.css diff --git a/cefpython/cef3/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.js b/cefpython/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.js old mode 100755 new mode 100644 similarity index 100% rename from cefpython/cef3/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.js rename to cefpython/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.js diff --git a/cefpython/cef3/linux/binaries_64bit/kivy-select-boxes/kivy-test.html b/cefpython/linux/binaries_64bit/kivy-select-boxes/kivy-test.html similarity index 100% rename from cefpython/cef3/linux/binaries_64bit/kivy-select-boxes/kivy-test.html rename to cefpython/linux/binaries_64bit/kivy-select-boxes/kivy-test.html diff --git a/cefpython/cef3/linux/binaries_64bit/kivy-select-boxes/readme.md b/cefpython/linux/binaries_64bit/kivy-select-boxes/readme.md old mode 100755 new mode 100644 similarity index 100% rename from cefpython/cef3/linux/binaries_64bit/kivy-select-boxes/readme.md rename to cefpython/linux/binaries_64bit/kivy-select-boxes/readme.md diff --git a/cefpython/cef3/linux/binaries_64bit/kivy_.py b/cefpython/linux/binaries_64bit/kivy_.py similarity index 100% rename from cefpython/cef3/linux/binaries_64bit/kivy_.py rename to cefpython/linux/binaries_64bit/kivy_.py diff --git a/cefpython/cef3/linux/binaries_64bit/prism.css b/cefpython/linux/binaries_64bit/prism.css similarity index 100% rename from cefpython/cef3/linux/binaries_64bit/prism.css rename to cefpython/linux/binaries_64bit/prism.css diff --git a/cefpython/cef3/linux/binaries_64bit/prism.js b/cefpython/linux/binaries_64bit/prism.js similarity index 100% rename from cefpython/cef3/linux/binaries_64bit/prism.js rename to cefpython/linux/binaries_64bit/prism.js diff --git a/cefpython/cef3/linux/binaries_64bit/pygtk_.py b/cefpython/linux/binaries_64bit/pygtk_.py similarity index 100% rename from cefpython/cef3/linux/binaries_64bit/pygtk_.py rename to cefpython/linux/binaries_64bit/pygtk_.py diff --git a/cefpython/cef3/linux/binaries_64bit/pyqt.py b/cefpython/linux/binaries_64bit/pyqt.py similarity index 100% rename from cefpython/cef3/linux/binaries_64bit/pyqt.py rename to cefpython/linux/binaries_64bit/pyqt.py diff --git a/cefpython/cef3/linux/binaries_64bit/wxpython-response.py b/cefpython/linux/binaries_64bit/wxpython-response.py similarity index 100% rename from cefpython/cef3/linux/binaries_64bit/wxpython-response.py rename to cefpython/linux/binaries_64bit/wxpython-response.py diff --git a/cefpython/cef3/linux/binaries_64bit/wxpython.html b/cefpython/linux/binaries_64bit/wxpython.html similarity index 100% rename from cefpython/cef3/linux/binaries_64bit/wxpython.html rename to cefpython/linux/binaries_64bit/wxpython.html diff --git a/cefpython/cef3/linux/binaries_64bit/wxpython.py b/cefpython/linux/binaries_64bit/wxpython.py similarity index 100% rename from cefpython/cef3/linux/binaries_64bit/wxpython.py rename to cefpython/linux/binaries_64bit/wxpython.py diff --git a/cefpython/cef3/linux/compile.py b/cefpython/linux/compile.py similarity index 99% rename from cefpython/cef3/linux/compile.py rename to cefpython/linux/compile.py index 609ae3f8e..1540c6ce1 100644 --- a/cefpython/cef3/linux/compile.py +++ b/cefpython/linux/compile.py @@ -61,7 +61,7 @@ if what != "y": sys.exit(1) -os.chdir("./../cef3/client_handler/") +os.chdir("./../client_handler/") subprocess.call("rm -f *.o *.a", shell=True) ret = subprocess.call("make -f Makefile", shell=True) diff --git a/cefpython/cef3/linux/installer/.gitignore b/cefpython/linux/installer/.gitignore similarity index 100% rename from cefpython/cef3/linux/installer/.gitignore rename to cefpython/linux/installer/.gitignore diff --git a/cefpython/cef3/linux/installer/README.txt b/cefpython/linux/installer/README.txt similarity index 100% rename from cefpython/cef3/linux/installer/README.txt rename to cefpython/linux/installer/README.txt diff --git a/cefpython/cef3/linux/installer/__init__.py.template b/cefpython/linux/installer/__init__.py.template similarity index 100% rename from cefpython/cef3/linux/installer/__init__.py.template rename to cefpython/linux/installer/__init__.py.template diff --git a/cefpython/cef3/linux/installer/build-n-run-wx-chromectrl.sh b/cefpython/linux/installer/build-n-run-wx-chromectrl.sh old mode 100755 new mode 100644 similarity index 100% rename from cefpython/cef3/linux/installer/build-n-run-wx-chromectrl.sh rename to cefpython/linux/installer/build-n-run-wx-chromectrl.sh diff --git a/cefpython/cef3/linux/installer/debian.postinst b/cefpython/linux/installer/debian.postinst similarity index 100% rename from cefpython/cef3/linux/installer/debian.postinst rename to cefpython/linux/installer/debian.postinst diff --git a/cefpython/cef3/linux/installer/deps.txt b/cefpython/linux/installer/deps.txt similarity index 100% rename from cefpython/cef3/linux/installer/deps.txt rename to cefpython/linux/installer/deps.txt diff --git a/cefpython/cef3/linux/installer/find-deps.py b/cefpython/linux/installer/find-deps.py similarity index 100% rename from cefpython/cef3/linux/installer/find-deps.py rename to cefpython/linux/installer/find-deps.py diff --git a/cefpython/cef3/linux/installer/make-deb.py b/cefpython/linux/installer/make-deb.py similarity index 99% rename from cefpython/cef3/linux/installer/make-deb.py rename to cefpython/linux/installer/make-deb.py index 24007c729..3fd7b8300 100644 --- a/cefpython/cef3/linux/installer/make-deb.py +++ b/cefpython/linux/installer/make-deb.py @@ -60,7 +60,7 @@ VERSION = None -# cefpython/cef3/linux/installer +# cefpython/linux/installer INSTALLER = os.path.dirname(os.path.abspath(__file__)) # installer/cefpython3-31.0-linux-64bit-setup/ diff --git a/cefpython/cef3/linux/installer/make-setup.py b/cefpython/linux/installer/make-setup.py similarity index 100% rename from cefpython/cef3/linux/installer/make-setup.py rename to cefpython/linux/installer/make-setup.py diff --git a/cefpython/cef3/linux/installer/setup.cfg.template b/cefpython/linux/installer/setup.cfg.template similarity index 100% rename from cefpython/cef3/linux/installer/setup.cfg.template rename to cefpython/linux/installer/setup.cfg.template diff --git a/cefpython/cef3/linux/installer/setup.py.template b/cefpython/linux/installer/setup.py.template similarity index 100% rename from cefpython/cef3/linux/installer/setup.py.template rename to cefpython/linux/installer/setup.py.template diff --git a/cefpython/cef3/linux/installer/stdeb.cfg.template b/cefpython/linux/installer/stdeb.cfg.template similarity index 100% rename from cefpython/cef3/linux/installer/stdeb.cfg.template rename to cefpython/linux/installer/stdeb.cfg.template diff --git a/cefpython/cef3/linux/rebuild.sh b/cefpython/linux/rebuild.sh old mode 100755 new mode 100644 similarity index 100% rename from cefpython/cef3/linux/rebuild.sh rename to cefpython/linux/rebuild.sh diff --git a/cefpython/cef3/linux/setup/.gitignore b/cefpython/linux/setup/.gitignore similarity index 100% rename from cefpython/cef3/linux/setup/.gitignore rename to cefpython/linux/setup/.gitignore diff --git a/cefpython/cef3/linux/setup/cefpython.h b/cefpython/linux/setup/cefpython.h similarity index 100% rename from cefpython/cef3/linux/setup/cefpython.h rename to cefpython/linux/setup/cefpython.h diff --git a/cefpython/cef3/linux/setup/fix_pyx_files.py b/cefpython/linux/setup/fix_pyx_files.py similarity index 100% rename from cefpython/cef3/linux/setup/fix_pyx_files.py rename to cefpython/linux/setup/fix_pyx_files.py diff --git a/cefpython/cef3/linux/setup/setup.py b/cefpython/linux/setup/setup.py old mode 100755 new mode 100644 similarity index 100% rename from cefpython/cef3/linux/setup/setup.py rename to cefpython/linux/setup/setup.py diff --git a/cefpython/cef3/linux/wxpython.sh b/cefpython/linux/wxpython.sh old mode 100755 new mode 100644 similarity index 100% rename from cefpython/cef3/linux/wxpython.sh rename to cefpython/linux/wxpython.sh diff --git a/cefpython/cef3/mac/.gitignore b/cefpython/mac/.gitignore similarity index 100% rename from cefpython/cef3/mac/.gitignore rename to cefpython/mac/.gitignore diff --git a/cefpython/cef3/mac/binaries_32bit/prism.css b/cefpython/mac/binaries_32bit/prism.css similarity index 100% rename from cefpython/cef3/mac/binaries_32bit/prism.css rename to cefpython/mac/binaries_32bit/prism.css diff --git a/cefpython/cef3/mac/binaries_32bit/prism.js b/cefpython/mac/binaries_32bit/prism.js similarity index 100% rename from cefpython/cef3/mac/binaries_32bit/prism.js rename to cefpython/mac/binaries_32bit/prism.js diff --git a/cefpython/cef3/mac/binaries_32bit/wxpython.html b/cefpython/mac/binaries_32bit/wxpython.html similarity index 100% rename from cefpython/cef3/mac/binaries_32bit/wxpython.html rename to cefpython/mac/binaries_32bit/wxpython.html diff --git a/cefpython/cef3/mac/binaries_32bit/wxpython.py b/cefpython/mac/binaries_32bit/wxpython.py similarity index 100% rename from cefpython/cef3/mac/binaries_32bit/wxpython.py rename to cefpython/mac/binaries_32bit/wxpython.py diff --git a/cefpython/cef3/mac/binaries_64bit/prism.css b/cefpython/mac/binaries_64bit/prism.css similarity index 100% rename from cefpython/cef3/mac/binaries_64bit/prism.css rename to cefpython/mac/binaries_64bit/prism.css diff --git a/cefpython/cef3/mac/binaries_64bit/prism.js b/cefpython/mac/binaries_64bit/prism.js similarity index 100% rename from cefpython/cef3/mac/binaries_64bit/prism.js rename to cefpython/mac/binaries_64bit/prism.js diff --git a/cefpython/cef3/mac/binaries_64bit/wxpython.html b/cefpython/mac/binaries_64bit/wxpython.html similarity index 100% rename from cefpython/cef3/mac/binaries_64bit/wxpython.html rename to cefpython/mac/binaries_64bit/wxpython.html diff --git a/cefpython/cef3/mac/binaries_64bit/wxpython.py b/cefpython/mac/binaries_64bit/wxpython.py similarity index 100% rename from cefpython/cef3/mac/binaries_64bit/wxpython.py rename to cefpython/mac/binaries_64bit/wxpython.py diff --git a/cefpython/cef3/mac/compile.py b/cefpython/mac/compile.py similarity index 99% rename from cefpython/cef3/mac/compile.py rename to cefpython/mac/compile.py index 30848f8fd..1a5a8072a 100644 --- a/cefpython/cef3/mac/compile.py +++ b/cefpython/mac/compile.py @@ -79,7 +79,7 @@ if what != "y": sys.exit(1) -os.chdir("./../cef3/client_handler/") +os.chdir("./../client_handler/") subprocess.call("rm -f *.o *.a", shell=True) ret = subprocess.call("make -f Makefile", shell=True) diff --git a/cefpython/cef3/mac/installer/.gitignore b/cefpython/mac/installer/.gitignore similarity index 100% rename from cefpython/cef3/mac/installer/.gitignore rename to cefpython/mac/installer/.gitignore diff --git a/cefpython/cef3/mac/installer/__init__.py.template b/cefpython/mac/installer/__init__.py.template similarity index 100% rename from cefpython/cef3/mac/installer/__init__.py.template rename to cefpython/mac/installer/__init__.py.template diff --git a/cefpython/cef3/mac/installer/build_all.sh b/cefpython/mac/installer/build_all.sh old mode 100755 new mode 100644 similarity index 100% rename from cefpython/cef3/mac/installer/build_all.sh rename to cefpython/mac/installer/build_all.sh diff --git a/cefpython/cef3/mac/installer/build_run_chromectrl.sh b/cefpython/mac/installer/build_run_chromectrl.sh old mode 100755 new mode 100644 similarity index 100% rename from cefpython/cef3/mac/installer/build_run_chromectrl.sh rename to cefpython/mac/installer/build_run_chromectrl.sh diff --git a/cefpython/cef3/mac/installer/make-setup.py b/cefpython/mac/installer/make-setup.py similarity index 100% rename from cefpython/cef3/mac/installer/make-setup.py rename to cefpython/mac/installer/make-setup.py diff --git a/cefpython/cef3/mac/installer/setup.py.template b/cefpython/mac/installer/setup.py.template similarity index 100% rename from cefpython/cef3/mac/installer/setup.py.template rename to cefpython/mac/installer/setup.py.template diff --git a/cefpython/cef3/mac/mac32.sh b/cefpython/mac/mac32.sh old mode 100755 new mode 100644 similarity index 100% rename from cefpython/cef3/mac/mac32.sh rename to cefpython/mac/mac32.sh diff --git a/cefpython/cef3/mac/mac64.sh b/cefpython/mac/mac64.sh old mode 100755 new mode 100644 similarity index 100% rename from cefpython/cef3/mac/mac64.sh rename to cefpython/mac/mac64.sh diff --git a/cefpython/cef3/mac/setup/.gitignore b/cefpython/mac/setup/.gitignore similarity index 100% rename from cefpython/cef3/mac/setup/.gitignore rename to cefpython/mac/setup/.gitignore diff --git a/cefpython/cef3/mac/setup/cefpython.h b/cefpython/mac/setup/cefpython.h similarity index 100% rename from cefpython/cef3/mac/setup/cefpython.h rename to cefpython/mac/setup/cefpython.h diff --git a/cefpython/cef3/mac/setup/fix_pyx_files.py b/cefpython/mac/setup/fix_pyx_files.py similarity index 100% rename from cefpython/cef3/mac/setup/fix_pyx_files.py rename to cefpython/mac/setup/fix_pyx_files.py diff --git a/cefpython/cef3/mac/setup/lib_32bit/README b/cefpython/mac/setup/lib_32bit/README similarity index 100% rename from cefpython/cef3/mac/setup/lib_32bit/README rename to cefpython/mac/setup/lib_32bit/README diff --git a/cefpython/cef3/mac/setup/lib_64bit/README b/cefpython/mac/setup/lib_64bit/README similarity index 100% rename from cefpython/cef3/mac/setup/lib_64bit/README rename to cefpython/mac/setup/lib_64bit/README diff --git a/cefpython/cef3/mac/setup/setup.py b/cefpython/mac/setup/setup.py old mode 100755 new mode 100644 similarity index 100% rename from cefpython/cef3/mac/setup/setup.py rename to cefpython/mac/setup/setup.py diff --git a/cefpython/cef3/subprocess/.gitignore b/cefpython/subprocess/.gitignore similarity index 100% rename from cefpython/cef3/subprocess/.gitignore rename to cefpython/subprocess/.gitignore diff --git a/cefpython/cef3/subprocess/Makefile b/cefpython/subprocess/Makefile similarity index 100% rename from cefpython/cef3/subprocess/Makefile rename to cefpython/subprocess/Makefile diff --git a/cefpython/cef3/subprocess/Makefile-libcefpythonapp b/cefpython/subprocess/Makefile-libcefpythonapp similarity index 100% rename from cefpython/cef3/subprocess/Makefile-libcefpythonapp rename to cefpython/subprocess/Makefile-libcefpythonapp diff --git a/cefpython/cef3/subprocess/cefpython_app.cpp b/cefpython/subprocess/cefpython_app.cpp similarity index 100% rename from cefpython/cef3/subprocess/cefpython_app.cpp rename to cefpython/subprocess/cefpython_app.cpp diff --git a/cefpython/cef3/subprocess/cefpython_app.h b/cefpython/subprocess/cefpython_app.h similarity index 100% rename from cefpython/cef3/subprocess/cefpython_app.h rename to cefpython/subprocess/cefpython_app.h diff --git a/cefpython/cef3/subprocess/javascript_callback.cpp b/cefpython/subprocess/javascript_callback.cpp similarity index 100% rename from cefpython/cef3/subprocess/javascript_callback.cpp rename to cefpython/subprocess/javascript_callback.cpp diff --git a/cefpython/cef3/subprocess/javascript_callback.h b/cefpython/subprocess/javascript_callback.h similarity index 100% rename from cefpython/cef3/subprocess/javascript_callback.h rename to cefpython/subprocess/javascript_callback.h diff --git a/cefpython/cef3/subprocess/libcefpythonapp_py27_32bit.vcproj b/cefpython/subprocess/libcefpythonapp_py27_32bit.vcproj similarity index 100% rename from cefpython/cef3/subprocess/libcefpythonapp_py27_32bit.vcproj rename to cefpython/subprocess/libcefpythonapp_py27_32bit.vcproj diff --git a/cefpython/cef3/subprocess/libcefpythonapp_py27_64bit.vcproj b/cefpython/subprocess/libcefpythonapp_py27_64bit.vcproj similarity index 100% rename from cefpython/cef3/subprocess/libcefpythonapp_py27_64bit.vcproj rename to cefpython/subprocess/libcefpythonapp_py27_64bit.vcproj diff --git a/cefpython/cef3/subprocess/libcefpythonapp_py34_32bit.vcproj b/cefpython/subprocess/libcefpythonapp_py34_32bit.vcproj similarity index 100% rename from cefpython/cef3/subprocess/libcefpythonapp_py34_32bit.vcproj rename to cefpython/subprocess/libcefpythonapp_py34_32bit.vcproj diff --git a/cefpython/cef3/subprocess/main.cpp b/cefpython/subprocess/main.cpp similarity index 100% rename from cefpython/cef3/subprocess/main.cpp rename to cefpython/subprocess/main.cpp diff --git a/cefpython/cef3/subprocess/subprocess_32bit.vcproj b/cefpython/subprocess/subprocess_32bit.vcproj similarity index 100% rename from cefpython/cef3/subprocess/subprocess_32bit.vcproj rename to cefpython/subprocess/subprocess_32bit.vcproj diff --git a/cefpython/cef3/subprocess/subprocess_64bit.vcproj b/cefpython/subprocess/subprocess_64bit.vcproj similarity index 100% rename from cefpython/cef3/subprocess/subprocess_64bit.vcproj rename to cefpython/subprocess/subprocess_64bit.vcproj diff --git a/cefpython/cef3/subprocess/v8function_handler.cpp b/cefpython/subprocess/v8function_handler.cpp similarity index 100% rename from cefpython/cef3/subprocess/v8function_handler.cpp rename to cefpython/subprocess/v8function_handler.cpp diff --git a/cefpython/cef3/subprocess/v8function_handler.h b/cefpython/subprocess/v8function_handler.h similarity index 100% rename from cefpython/cef3/subprocess/v8function_handler.h rename to cefpython/subprocess/v8function_handler.h diff --git a/cefpython/cef3/subprocess/v8utils.cpp b/cefpython/subprocess/v8utils.cpp similarity index 100% rename from cefpython/cef3/subprocess/v8utils.cpp rename to cefpython/subprocess/v8utils.cpp diff --git a/cefpython/cef3/subprocess/v8utils.h b/cefpython/subprocess/v8utils.h similarity index 100% rename from cefpython/cef3/subprocess/v8utils.h rename to cefpython/subprocess/v8utils.h diff --git a/cefpython/cef3/util.h b/cefpython/util.h similarity index 100% rename from cefpython/cef3/util.h rename to cefpython/util.h diff --git a/cefpython/cef3/windows/.gitignore b/cefpython/windows/.gitignore similarity index 100% rename from cefpython/cef3/windows/.gitignore rename to cefpython/windows/.gitignore diff --git a/cefpython/cef3/windows/binaries_32bit/LICENSE.txt b/cefpython/windows/binaries_32bit/LICENSE.txt similarity index 100% rename from cefpython/cef3/windows/binaries_32bit/LICENSE.txt rename to cefpython/windows/binaries_32bit/LICENSE.txt diff --git a/cefpython/cef3/windows/binaries_32bit/README.txt b/cefpython/windows/binaries_32bit/README.txt similarity index 100% rename from cefpython/cef3/windows/binaries_32bit/README.txt rename to cefpython/windows/binaries_32bit/README.txt diff --git a/cefpython/cef3/windows/binaries_32bit/cefwindow.py b/cefpython/windows/binaries_32bit/cefwindow.py similarity index 100% rename from cefpython/cef3/windows/binaries_32bit/cefwindow.py rename to cefpython/windows/binaries_32bit/cefwindow.py diff --git a/cefpython/cef3/windows/binaries_32bit/example.html b/cefpython/windows/binaries_32bit/example.html similarity index 100% rename from cefpython/cef3/windows/binaries_32bit/example.html rename to cefpython/windows/binaries_32bit/example.html diff --git a/cefpython/cef3/windows/binaries_32bit/icon.ico b/cefpython/windows/binaries_32bit/icon.ico similarity index 100% rename from cefpython/cef3/windows/binaries_32bit/icon.ico rename to cefpython/windows/binaries_32bit/icon.ico diff --git a/cefpython/cef3/windows/binaries_32bit/prism.css b/cefpython/windows/binaries_32bit/prism.css similarity index 100% rename from cefpython/cef3/windows/binaries_32bit/prism.css rename to cefpython/windows/binaries_32bit/prism.css diff --git a/cefpython/cef3/windows/binaries_32bit/prism.js b/cefpython/windows/binaries_32bit/prism.js similarity index 100% rename from cefpython/cef3/windows/binaries_32bit/prism.js rename to cefpython/windows/binaries_32bit/prism.js diff --git a/cefpython/cef3/windows/binaries_32bit/pygtk_.py b/cefpython/windows/binaries_32bit/pygtk_.py similarity index 100% rename from cefpython/cef3/windows/binaries_32bit/pygtk_.py rename to cefpython/windows/binaries_32bit/pygtk_.py diff --git a/cefpython/cef3/windows/binaries_32bit/pyqt.py b/cefpython/windows/binaries_32bit/pyqt.py similarity index 100% rename from cefpython/cef3/windows/binaries_32bit/pyqt.py rename to cefpython/windows/binaries_32bit/pyqt.py diff --git a/cefpython/cef3/windows/binaries_32bit/pyside.py b/cefpython/windows/binaries_32bit/pyside.py similarity index 100% rename from cefpython/cef3/windows/binaries_32bit/pyside.py rename to cefpython/windows/binaries_32bit/pyside.py diff --git a/cefpython/cef3/windows/binaries_32bit/pywin32.py b/cefpython/windows/binaries_32bit/pywin32.py similarity index 100% rename from cefpython/cef3/windows/binaries_32bit/pywin32.py rename to cefpython/windows/binaries_32bit/pywin32.py diff --git a/cefpython/cef3/windows/binaries_32bit/smoke.css b/cefpython/windows/binaries_32bit/smoke.css similarity index 100% rename from cefpython/cef3/windows/binaries_32bit/smoke.css rename to cefpython/windows/binaries_32bit/smoke.css diff --git a/cefpython/cef3/windows/binaries_32bit/smoke.min.js b/cefpython/windows/binaries_32bit/smoke.min.js similarity index 100% rename from cefpython/cef3/windows/binaries_32bit/smoke.min.js rename to cefpython/windows/binaries_32bit/smoke.min.js diff --git a/cefpython/cef3/windows/binaries_32bit/wxpython.html b/cefpython/windows/binaries_32bit/wxpython.html similarity index 100% rename from cefpython/cef3/windows/binaries_32bit/wxpython.html rename to cefpython/windows/binaries_32bit/wxpython.html diff --git a/cefpython/cef3/windows/binaries_32bit/wxpython.py b/cefpython/windows/binaries_32bit/wxpython.py similarity index 100% rename from cefpython/cef3/windows/binaries_32bit/wxpython.py rename to cefpython/windows/binaries_32bit/wxpython.py diff --git a/cefpython/cef3/windows/binaries_64bit/LICENSE.txt b/cefpython/windows/binaries_64bit/LICENSE.txt similarity index 100% rename from cefpython/cef3/windows/binaries_64bit/LICENSE.txt rename to cefpython/windows/binaries_64bit/LICENSE.txt diff --git a/cefpython/cef3/windows/binaries_64bit/README.txt b/cefpython/windows/binaries_64bit/README.txt similarity index 100% rename from cefpython/cef3/windows/binaries_64bit/README.txt rename to cefpython/windows/binaries_64bit/README.txt diff --git a/cefpython/cef3/windows/binaries_64bit/cefwindow.py b/cefpython/windows/binaries_64bit/cefwindow.py similarity index 100% rename from cefpython/cef3/windows/binaries_64bit/cefwindow.py rename to cefpython/windows/binaries_64bit/cefwindow.py diff --git a/cefpython/cef3/windows/binaries_64bit/example.html b/cefpython/windows/binaries_64bit/example.html similarity index 100% rename from cefpython/cef3/windows/binaries_64bit/example.html rename to cefpython/windows/binaries_64bit/example.html diff --git a/cefpython/cef3/windows/binaries_64bit/icon.ico b/cefpython/windows/binaries_64bit/icon.ico similarity index 100% rename from cefpython/cef3/windows/binaries_64bit/icon.ico rename to cefpython/windows/binaries_64bit/icon.ico diff --git a/cefpython/cef3/windows/binaries_64bit/prism.css b/cefpython/windows/binaries_64bit/prism.css similarity index 100% rename from cefpython/cef3/windows/binaries_64bit/prism.css rename to cefpython/windows/binaries_64bit/prism.css diff --git a/cefpython/cef3/windows/binaries_64bit/prism.js b/cefpython/windows/binaries_64bit/prism.js similarity index 100% rename from cefpython/cef3/windows/binaries_64bit/prism.js rename to cefpython/windows/binaries_64bit/prism.js diff --git a/cefpython/cef3/windows/binaries_64bit/pygtk_.py b/cefpython/windows/binaries_64bit/pygtk_.py similarity index 100% rename from cefpython/cef3/windows/binaries_64bit/pygtk_.py rename to cefpython/windows/binaries_64bit/pygtk_.py diff --git a/cefpython/cef3/windows/binaries_64bit/pyqt.py b/cefpython/windows/binaries_64bit/pyqt.py similarity index 100% rename from cefpython/cef3/windows/binaries_64bit/pyqt.py rename to cefpython/windows/binaries_64bit/pyqt.py diff --git a/cefpython/cef3/windows/binaries_64bit/pyside.py b/cefpython/windows/binaries_64bit/pyside.py similarity index 100% rename from cefpython/cef3/windows/binaries_64bit/pyside.py rename to cefpython/windows/binaries_64bit/pyside.py diff --git a/cefpython/cef3/windows/binaries_64bit/pywin32.py b/cefpython/windows/binaries_64bit/pywin32.py similarity index 100% rename from cefpython/cef3/windows/binaries_64bit/pywin32.py rename to cefpython/windows/binaries_64bit/pywin32.py diff --git a/cefpython/cef3/windows/binaries_64bit/smoke.css b/cefpython/windows/binaries_64bit/smoke.css similarity index 100% rename from cefpython/cef3/windows/binaries_64bit/smoke.css rename to cefpython/windows/binaries_64bit/smoke.css diff --git a/cefpython/cef3/windows/binaries_64bit/smoke.min.js b/cefpython/windows/binaries_64bit/smoke.min.js similarity index 100% rename from cefpython/cef3/windows/binaries_64bit/smoke.min.js rename to cefpython/windows/binaries_64bit/smoke.min.js diff --git a/cefpython/cef3/windows/binaries_64bit/wxpython.html b/cefpython/windows/binaries_64bit/wxpython.html similarity index 100% rename from cefpython/cef3/windows/binaries_64bit/wxpython.html rename to cefpython/windows/binaries_64bit/wxpython.html diff --git a/cefpython/cef3/windows/binaries_64bit/wxpython.py b/cefpython/windows/binaries_64bit/wxpython.py similarity index 100% rename from cefpython/cef3/windows/binaries_64bit/wxpython.py rename to cefpython/windows/binaries_64bit/wxpython.py diff --git a/cefpython/cef3/windows/cefpython.rc b/cefpython/windows/cefpython.rc similarity index 100% rename from cefpython/cef3/windows/cefpython.rc rename to cefpython/windows/cefpython.rc diff --git a/cefpython/cef3/windows/compile.bat b/cefpython/windows/compile.bat similarity index 100% rename from cefpython/cef3/windows/compile.bat rename to cefpython/windows/compile.bat diff --git a/cefpython/cef3/windows/compile.cmd b/cefpython/windows/compile.cmd similarity index 100% rename from cefpython/cef3/windows/compile.cmd rename to cefpython/windows/compile.cmd diff --git a/cefpython/cef3/windows/installer/.gitignore b/cefpython/windows/installer/.gitignore similarity index 100% rename from cefpython/cef3/windows/installer/.gitignore rename to cefpython/windows/installer/.gitignore diff --git a/cefpython/cef3/windows/installer/README.txt b/cefpython/windows/installer/README.txt similarity index 100% rename from cefpython/cef3/windows/installer/README.txt rename to cefpython/windows/installer/README.txt diff --git a/cefpython/cef3/windows/installer/__init__.py.template b/cefpython/windows/installer/__init__.py.template similarity index 100% rename from cefpython/cef3/windows/installer/__init__.py.template rename to cefpython/windows/installer/__init__.py.template diff --git a/cefpython/cef3/windows/installer/build_all.bat b/cefpython/windows/installer/build_all.bat similarity index 100% rename from cefpython/cef3/windows/installer/build_all.bat rename to cefpython/windows/installer/build_all.bat diff --git a/cefpython/cef3/windows/installer/innosetup.template b/cefpython/windows/installer/innosetup.template similarity index 100% rename from cefpython/cef3/windows/installer/innosetup.template rename to cefpython/windows/installer/innosetup.template diff --git a/cefpython/cef3/windows/installer/make-installer.py b/cefpython/windows/installer/make-installer.py similarity index 100% rename from cefpython/cef3/windows/installer/make-installer.py rename to cefpython/windows/installer/make-installer.py diff --git a/cefpython/cef3/windows/installer/make-setup.py b/cefpython/windows/installer/make-setup.py similarity index 100% rename from cefpython/cef3/windows/installer/make-setup.py rename to cefpython/windows/installer/make-setup.py diff --git a/cefpython/cef3/windows/installer/setup.cfg.template b/cefpython/windows/installer/setup.cfg.template similarity index 100% rename from cefpython/cef3/windows/installer/setup.cfg.template rename to cefpython/windows/installer/setup.cfg.template diff --git a/cefpython/cef3/windows/installer/setup.py.template b/cefpython/windows/installer/setup.py.template similarity index 100% rename from cefpython/cef3/windows/installer/setup.py.template rename to cefpython/windows/installer/setup.py.template diff --git a/cefpython/cef3/windows/setup/.gitignore b/cefpython/windows/setup/.gitignore similarity index 100% rename from cefpython/cef3/windows/setup/.gitignore rename to cefpython/windows/setup/.gitignore diff --git a/cefpython/cef3/windows/setup/cefpython.h b/cefpython/windows/setup/cefpython.h similarity index 100% rename from cefpython/cef3/windows/setup/cefpython.h rename to cefpython/windows/setup/cefpython.h diff --git a/cefpython/cef3/windows/setup/compile_rc.py b/cefpython/windows/setup/compile_rc.py similarity index 100% rename from cefpython/cef3/windows/setup/compile_rc.py rename to cefpython/windows/setup/compile_rc.py diff --git a/cefpython/cef3/windows/setup/delete_pyx_files.bat b/cefpython/windows/setup/delete_pyx_files.bat similarity index 100% rename from cefpython/cef3/windows/setup/delete_pyx_files.bat rename to cefpython/windows/setup/delete_pyx_files.bat diff --git a/cefpython/cef3/windows/setup/fix_cefpython_h.py b/cefpython/windows/setup/fix_cefpython_h.py similarity index 100% rename from cefpython/cef3/windows/setup/fix_cefpython_h.py rename to cefpython/windows/setup/fix_cefpython_h.py diff --git a/cefpython/cef3/windows/setup/fix_pyx_files.py b/cefpython/windows/setup/fix_pyx_files.py similarity index 100% rename from cefpython/cef3/windows/setup/fix_pyx_files.py rename to cefpython/windows/setup/fix_pyx_files.py diff --git a/cefpython/cef3/windows/setup/lib_32bit/README b/cefpython/windows/setup/lib_32bit/README similarity index 100% rename from cefpython/cef3/windows/setup/lib_32bit/README rename to cefpython/windows/setup/lib_32bit/README diff --git a/cefpython/cef3/windows/setup/lib_64bit/README b/cefpython/windows/setup/lib_64bit/README similarity index 100% rename from cefpython/cef3/windows/setup/lib_64bit/README rename to cefpython/windows/setup/lib_64bit/README diff --git a/cefpython/cef3/windows/setup/setup.py b/cefpython/windows/setup/setup.py similarity index 100% rename from cefpython/cef3/windows/setup/setup.py rename to cefpython/windows/setup/setup.py diff --git a/cefpython/cef3/windows/stdint.h b/cefpython/windows/stdint.h similarity index 100% rename from cefpython/cef3/windows/stdint.h rename to cefpython/windows/stdint.h diff --git a/cefpython/cef3/windows/wxpython.bat b/cefpython/windows/wxpython.bat similarity index 100% rename from cefpython/cef3/windows/wxpython.bat rename to cefpython/windows/wxpython.bat diff --git a/cefpython/cef3/wx-subpackage/README.txt b/cefpython/wx-subpackage/README.txt similarity index 100% rename from cefpython/cef3/wx-subpackage/README.txt rename to cefpython/wx-subpackage/README.txt diff --git a/cefpython/wx-subpackage/__init__.py b/cefpython/wx-subpackage/__init__.py new file mode 100644 index 000000000..6959848d9 --- /dev/null +++ b/cefpython/wx-subpackage/__init__.py @@ -0,0 +1,3 @@ +# This dummy file is overwritten by "__init__.py.template", see: +# cefpython/windows/installer/ +# cefpython/linux/installer/ diff --git a/cefpython/cef3/wx-subpackage/chromectrl.py b/cefpython/wx-subpackage/chromectrl.py similarity index 97% rename from cefpython/cef3/wx-subpackage/chromectrl.py rename to cefpython/wx-subpackage/chromectrl.py index 4841e7290..d4ea557b7 100644 --- a/cefpython/cef3/wx-subpackage/chromectrl.py +++ b/cefpython/wx-subpackage/chromectrl.py @@ -1,421 +1,421 @@ -# Additional and wx specific layer of abstraction for the cefpython -# __author__ = "Greg Kacy " - -#------------------------------------------------------------------------------- - -from cefpython3 import cefpython -import os, sys, platform -import wx -import wx.lib.buttons as buttons - -#------------------------------------------------------------------------------- - -# CEF Python application settings -g_settings = None - -def Debug(msg): - if g_settings and "debug" in g_settings and g_settings["debug"]: - print("[chromectrl.py] "+msg) - -#------------------------------------------------------------------------------- - -# Default timer interval when timer used to service CEF message loop -DEFAULT_TIMER_MILLIS = 10 - -# A global timer for CEF message loop processing. -g_messageLoopTimer = None - -def CreateMessageLoopTimer(timerMillis): - # This function gets called multiple times for each ChromeWindow - # instance. - global g_messageLoopTimer - Debug("CreateMesageLoopTimer") - if g_messageLoopTimer: - return - g_messageLoopTimer = wx.Timer() - g_messageLoopTimer.Start(timerMillis) - Debug("g_messageLoopTimer.GetId() = "\ - +str(g_messageLoopTimer.GetId())) - wx.EVT_TIMER(g_messageLoopTimer, g_messageLoopTimer.GetId(),\ - MessageLoopTimer) - -def MessageLoopTimer(event): - cefpython.MessageLoopWork() - -def DestroyMessageLoopTimer(): - global g_messageLoopTimer - Debug("DestroyMessageLoopTimer") - if g_messageLoopTimer: - g_messageLoopTimer.Stop() - g_messageLoopTimer = None - else: - # There was no browser created during session. - Debug("DestroyMessageLoopTimer: timer not started") - -#------------------------------------------------------------------------------- - -class NavigationBar(wx.Panel): - def __init__(self, parent, *args, **kwargs): - wx.Panel.__init__(self, parent, *args, **kwargs) - - self.bitmapDir = os.path.join(os.path.dirname( - os.path.abspath(__file__)), "images") - - self._InitComponents() - self._LayoutComponents() - self._InitEventHandlers() - - def _InitComponents(self): - self.backBtn = buttons.GenBitmapButton(self, -1, - wx.Bitmap(os.path.join(self.bitmapDir, "Arrow Left.png"), - wx.BITMAP_TYPE_PNG), style=wx.BORDER_NONE) - self.forwardBtn = buttons.GenBitmapButton(self, -1, - wx.Bitmap(os.path.join(self.bitmapDir, "Arrow Right.png"), - wx.BITMAP_TYPE_PNG), style=wx.BORDER_NONE) - self.reloadBtn = buttons.GenBitmapButton(self, -1, - wx.Bitmap(os.path.join(self.bitmapDir, "Button Load.png"), - wx.BITMAP_TYPE_PNG), style=wx.BORDER_NONE) - - self.url = wx.TextCtrl(self, id=-1, style=0) - - self.historyPopup = wx.Menu() - - def _LayoutComponents(self): - sizer = wx.BoxSizer(wx.HORIZONTAL) - sizer.Add(self.backBtn, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL| - wx.ALL, 0) - sizer.Add(self.forwardBtn, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL| - wx.ALL, 0) - sizer.Add(self.reloadBtn, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL| - wx.ALL, 0) - - sizer.Add(self.url, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 12) - - self.SetSizer(sizer) - self.Fit() - - def _InitEventHandlers(self): - self.backBtn.Bind(wx.EVT_CONTEXT_MENU, self.OnButtonContext) - - def __del__(self): - self.historyPopup.Destroy() - - def GetBackButton(self): - return self.backBtn - - def GetForwardButton(self): - return self.forwardBtn - - def GetReloadButton(self): - return self.reloadBtn - - def GetUrlCtrl(self): - return self.url - - def InitHistoryPopup(self): - self.historyPopup = wx.Menu() - - def AddToHistory(self, url): - self.historyPopup.Append(-1, url) - - def OnButtonContext(self, event): - self.PopupMenu(self.historyPopup) - - -class ChromeWindow(wx.Window): - """ - Standalone CEF component. The class provides facilites for interacting - with wx message loop - """ - def __init__(self, parent, url="", useTimer=True, - timerMillis=DEFAULT_TIMER_MILLIS, browserSettings=None, - size=(-1, -1), *args, **kwargs): - wx.Window.__init__(self, parent, id=wx.ID_ANY, size=size, - *args, **kwargs) - - # This timer is not used anymore, but creating it for backwards - # compatibility. In one of external projects ChromeWindow.timer.Stop() - # is being called during browser destruction. - self.timer = wx.Timer() - - # On Linux absolute file urls need to start with "file://" - # otherwise a path of "/home/some" is converted to "http://home/some". - if platform.system() in ["Linux", "Darwin"]: - if url.startswith("/"): - url = "file://" + url - self.url = url - - windowInfo = cefpython.WindowInfo() - if platform.system() == "Windows": - windowInfo.SetAsChild(self.GetHandle()) - elif platform.system() == "Linux": - windowInfo.SetAsChild(self.GetGtkWidget()) - elif platform.system() == "Darwin": - (width, height) = self.GetClientSizeTuple() - windowInfo.SetAsChild(self.GetHandle(), - [0, 0, width, height]) - else: - raise Exception("Unsupported OS") - - if not browserSettings: - browserSettings = {} - - # Disable plugins: - # | browserSettings["plugins_disabled"] = True - - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings=browserSettings, navigateUrl=url) - - if platform.system() == "Windows": - self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) - self.Bind(wx.EVT_SIZE, self.OnSize) - - self._useTimer = useTimer - if useTimer: - CreateMessageLoopTimer(timerMillis) - else: - # Currently multiple EVT_IDLE events might be registered - # when creating multiple ChromeWindow instances. This will - # result in calling CEF message loop work multiple times - # simultaneously causing performance penalties and possibly - # some unwanted behavior (CEF Python Issue 129). - Debug("WARNING: Using EVT_IDLE for CEF message loop processing"\ - " is not recommended") - self.Bind(wx.EVT_IDLE, self.OnIdle) - - self.Bind(wx.EVT_CLOSE, self.OnClose) - - def OnClose(self, event): - if not self._useTimer: - try: - self.Unbind(wx.EVT_IDLE) - except: - # Calling Unbind() may cause problems on Windows 8: - # https://groups.google.com/d/topic/cefpython/iXE7e1ekArI/discussion - # (it was causing problems in __del__, this might not - # be true anymore in OnClose, but still let's make sure) - pass - self.browser.ParentWindowWillClose() - - def OnIdle(self, event): - """Service CEF message loop when useTimer is False""" - cefpython.MessageLoopWork() - event.Skip() - - def OnSetFocus(self, event): - """OS_WIN only.""" - cefpython.WindowUtils.OnSetFocus(self.GetHandle(), 0, 0, 0) - event.Skip() - - def OnSize(self, event): - """OS_WIN only. Handle the the size event""" - cefpython.WindowUtils.OnSize(self.GetHandle(), 0, 0, 0) - event.Skip() - - def GetBrowser(self): - """Returns the CEF's browser object""" - return self.browser - - def LoadUrl(self, url, onLoadStart=None, onLoadEnd=None): - if onLoadStart or onLoadEnd: - self.GetBrowser().SetClientHandler( - CallbackClientHandler(onLoadStart, onLoadEnd)) - - browser = self.GetBrowser() - if cefpython.g_debug: - Debug("LoadUrl() self: %s" % self) - Debug("browser: %s" % browser) - Debug("browser id: %s" % browser.GetIdentifier()) - Debug("mainframe: %s" % browser.GetMainFrame()) - Debug("mainframe id: %s" % \ - browser.GetMainFrame().GetIdentifier()) - self.GetBrowser().GetMainFrame().LoadUrl(url) - - #wx.CallLater(100, browser.ReloadIgnoreCache) - #wx.CallLater(200, browser.GetMainFrame().LoadUrl, url) - - -class ChromeCtrl(wx.Panel): - def __init__(self, parent, url="", useTimer=True, - timerMillis=DEFAULT_TIMER_MILLIS, - browserSettings=None, hasNavBar=True, - *args, **kwargs): - # You also have to set the wx.WANTS_CHARS style for - # all parent panels/controls, if it's deeply embedded. - wx.Panel.__init__(self, parent, style=wx.WANTS_CHARS, *args, **kwargs) - - self.chromeWindow = ChromeWindow(self, url=str(url), useTimer=useTimer, - browserSettings=browserSettings) - sizer = wx.BoxSizer(wx.VERTICAL) - self.navigationBar = None - if hasNavBar: - self.navigationBar = self.CreateNavigationBar() - sizer.Add(self.navigationBar, 0, wx.EXPAND|wx.ALL, 0) - self._InitEventHandlers() - - sizer.Add(self.chromeWindow, 1, wx.EXPAND, 0) - - self.SetSizer(sizer) - self.Fit() - - ch = DefaultClientHandler(self) - self.SetClientHandler(ch) - if self.navigationBar: - self.UpdateButtonsState() - - def _InitEventHandlers(self): - self.navigationBar.backBtn.Bind(wx.EVT_BUTTON, self.OnLeft) - self.navigationBar.forwardBtn.Bind(wx.EVT_BUTTON, self.OnRight) - self.navigationBar.reloadBtn.Bind(wx.EVT_BUTTON, self.OnReload) - - def GetNavigationBar(self): - return self.navigationBar - - def SetNavigationBar(self, navigationBar): - sizer = self.GetSizer() - if self.navigationBar: - # remove previous one - sizer.Replace(self.navigationBar, navigationBar) - self.navigationBar.Hide() - del self.navigationBar - else: - sizer.Insert(0, navigationBar, 0, wx.EXPAND) - self.navigationBar = navigationBar - sizer.Fit(self) - - def CreateNavigationBar(self): - np = NavigationBar(self) - return np - - def SetClientHandler(self, handler): - self.chromeWindow.GetBrowser().SetClientHandler(handler) - - def OnLeft(self, event): - if self.chromeWindow.GetBrowser().CanGoBack(): - self.chromeWindow.GetBrowser().GoBack() - self.UpdateButtonsState() - self.chromeWindow.GetBrowser().SetFocus(True) - - def OnRight(self, event): - if self.chromeWindow.GetBrowser().CanGoForward(): - self.chromeWindow.GetBrowser().GoForward() - self.UpdateButtonsState() - self.chromeWindow.GetBrowser().SetFocus(True) - - def OnReload(self, event): - self.chromeWindow.GetBrowser().Reload() - self.UpdateButtonsState() - self.chromeWindow.GetBrowser().SetFocus(True) - - def UpdateButtonsState(self): - self.navigationBar.backBtn.Enable( - self.chromeWindow.GetBrowser().CanGoBack()) - self.navigationBar.forwardBtn.Enable( - self.chromeWindow.GetBrowser().CanGoForward()) - - def OnLoadStart(self, browser, frame): - if self.navigationBar: - self.UpdateButtonsState() - self.navigationBar.GetUrlCtrl().SetValue( - browser.GetMainFrame().GetUrl()) - self.navigationBar.AddToHistory(browser.GetMainFrame().GetUrl()) - - def OnLoadEnd(self, browser, frame, httpStatusCode): - if self.navigationBar: - # In CEF 3 the CanGoBack() and CanGoForward() methods - # sometimes do work, sometimes do not, when called from - # the OnLoadStart event. That's why we're calling it again - # here. This is still not perfect as OnLoadEnd() is not - # guaranteed to get called for all types of pages. See the - # cefpython documentation: - # https://code.google.com/p/cefpython/wiki/LoadHandler - # OnDomReady() would be perfect, but is still not implemented. - # Another option is to implement our own browser state - # using the OnLoadStart and OnLoadEnd callbacks. - self.UpdateButtonsState() - -class DefaultClientHandler(object): - def __init__(self, parentCtrl): - self.parentCtrl = parentCtrl - - def OnLoadStart(self, browser, frame): - self.parentCtrl.OnLoadStart(browser, frame) - - def OnLoadEnd(self, browser, frame, httpStatusCode): - self.parentCtrl.OnLoadEnd(browser, frame, httpStatusCode) - - def OnLoadError(self, browser, frame, errorCode, errorText, failedUrl): - # TODO - Debug("ERROR LOADING URL : %s" % failedUrl) - -class CallbackClientHandler(object): - def __init__(self, onLoadStart=None, onLoadEnd=None): - self._onLoadStart = onLoadStart - self._onLoadEnd = onLoadEnd - - def OnLoadStart(self, browser, frame): - if self._onLoadStart and frame.GetUrl() != "about:blank": - self._onLoadStart(browser, frame) - - def OnLoadEnd(self, browser, frame, httpStatusCode): - if self._onLoadEnd and frame.GetUrl() != "about:blank": - self._onLoadEnd(browser, frame, httpStatusCode) - - def OnLoadError(self, browser, frame, errorCode, errorText, failedUrl): - # TODO - Debug("ERROR LOADING URL : %s, %s" % (failedUrl, frame.GetUrl())) - -#------------------------------------------------------------------------------- - -def Initialize(settings=None, debug=False): - """Initializes CEF, We should do it before initializing wx - If no settings passed a default is used - """ - switches = {} - global g_settings - if not settings: - settings = {} - - if not "log_severity" in settings: - settings["log_severity"] = cefpython.LOGSEVERITY_INFO - if not "log_file" in settings: - settings["log_file"] = "" - - if platform.system() == "Linux": - # On Linux we need to set locales and resources directories. - if not "locales_dir_path" in settings: - settings["locales_dir_path"] = \ - cefpython.GetModuleDirectory() + "/locales" - if not "resources_dir_path" in settings: - settings["resources_dir_path"] = cefpython.GetModuleDirectory() - elif platform.system() == "Darwin": - # On Mac we need to set the resoures dir and the locale_pak switch - if not "resources_dir_path" in settings: - settings["resources_dir_path"] = (cefpython.GetModuleDirectory() - + "/Resources") - locale_pak = (cefpython.GetModuleDirectory() - + "/Resources/en.lproj/locale.pak") - if "locale_pak" in settings: - locale_pak = settings["locale_pak"] - del settings["locale_pak"] - switches["locale_pak"] = locale_pak - - if not "browser_subprocess_path" in settings: - settings["browser_subprocess_path"] = \ - "%s/%s" % (cefpython.GetModuleDirectory(), "subprocess") - - # DEBUGGING options: - # ------------------ - if debug: - settings["debug"] = True # cefpython messages in console and log_file - settings["log_severity"] = cefpython.LOGSEVERITY_VERBOSE - settings["log_file"] = "debug.log" # Set to "" to disable. - settings["release_dcheck_enabled"] = True - - g_settings = settings - cefpython.Initialize(settings, switches) - -def Shutdown(): - """Shuts down CEF, should be called by app exiting code""" - DestroyMessageLoopTimer() - cefpython.Shutdown() +# Additional and wx specific layer of abstraction for the cefpython +# __author__ = "Greg Kacy " + +#------------------------------------------------------------------------------- + +from cefpython3 import cefpython +import os, sys, platform +import wx +import wx.lib.buttons as buttons + +#------------------------------------------------------------------------------- + +# CEF Python application settings +g_settings = None + +def Debug(msg): + if g_settings and "debug" in g_settings and g_settings["debug"]: + print("[chromectrl.py] "+msg) + +#------------------------------------------------------------------------------- + +# Default timer interval when timer used to service CEF message loop +DEFAULT_TIMER_MILLIS = 10 + +# A global timer for CEF message loop processing. +g_messageLoopTimer = None + +def CreateMessageLoopTimer(timerMillis): + # This function gets called multiple times for each ChromeWindow + # instance. + global g_messageLoopTimer + Debug("CreateMesageLoopTimer") + if g_messageLoopTimer: + return + g_messageLoopTimer = wx.Timer() + g_messageLoopTimer.Start(timerMillis) + Debug("g_messageLoopTimer.GetId() = "\ + +str(g_messageLoopTimer.GetId())) + wx.EVT_TIMER(g_messageLoopTimer, g_messageLoopTimer.GetId(),\ + MessageLoopTimer) + +def MessageLoopTimer(event): + cefpython.MessageLoopWork() + +def DestroyMessageLoopTimer(): + global g_messageLoopTimer + Debug("DestroyMessageLoopTimer") + if g_messageLoopTimer: + g_messageLoopTimer.Stop() + g_messageLoopTimer = None + else: + # There was no browser created during session. + Debug("DestroyMessageLoopTimer: timer not started") + +#------------------------------------------------------------------------------- + +class NavigationBar(wx.Panel): + def __init__(self, parent, *args, **kwargs): + wx.Panel.__init__(self, parent, *args, **kwargs) + + self.bitmapDir = os.path.join(os.path.dirname( + os.path.abspath(__file__)), "images") + + self._InitComponents() + self._LayoutComponents() + self._InitEventHandlers() + + def _InitComponents(self): + self.backBtn = buttons.GenBitmapButton(self, -1, + wx.Bitmap(os.path.join(self.bitmapDir, "Arrow Left.png"), + wx.BITMAP_TYPE_PNG), style=wx.BORDER_NONE) + self.forwardBtn = buttons.GenBitmapButton(self, -1, + wx.Bitmap(os.path.join(self.bitmapDir, "Arrow Right.png"), + wx.BITMAP_TYPE_PNG), style=wx.BORDER_NONE) + self.reloadBtn = buttons.GenBitmapButton(self, -1, + wx.Bitmap(os.path.join(self.bitmapDir, "Button Load.png"), + wx.BITMAP_TYPE_PNG), style=wx.BORDER_NONE) + + self.url = wx.TextCtrl(self, id=-1, style=0) + + self.historyPopup = wx.Menu() + + def _LayoutComponents(self): + sizer = wx.BoxSizer(wx.HORIZONTAL) + sizer.Add(self.backBtn, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL| + wx.ALL, 0) + sizer.Add(self.forwardBtn, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL| + wx.ALL, 0) + sizer.Add(self.reloadBtn, 0, wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL| + wx.ALL, 0) + + sizer.Add(self.url, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 12) + + self.SetSizer(sizer) + self.Fit() + + def _InitEventHandlers(self): + self.backBtn.Bind(wx.EVT_CONTEXT_MENU, self.OnButtonContext) + + def __del__(self): + self.historyPopup.Destroy() + + def GetBackButton(self): + return self.backBtn + + def GetForwardButton(self): + return self.forwardBtn + + def GetReloadButton(self): + return self.reloadBtn + + def GetUrlCtrl(self): + return self.url + + def InitHistoryPopup(self): + self.historyPopup = wx.Menu() + + def AddToHistory(self, url): + self.historyPopup.Append(-1, url) + + def OnButtonContext(self, event): + self.PopupMenu(self.historyPopup) + + +class ChromeWindow(wx.Window): + """ + Standalone CEF component. The class provides facilites for interacting + with wx message loop + """ + def __init__(self, parent, url="", useTimer=True, + timerMillis=DEFAULT_TIMER_MILLIS, browserSettings=None, + size=(-1, -1), *args, **kwargs): + wx.Window.__init__(self, parent, id=wx.ID_ANY, size=size, + *args, **kwargs) + + # This timer is not used anymore, but creating it for backwards + # compatibility. In one of external projects ChromeWindow.timer.Stop() + # is being called during browser destruction. + self.timer = wx.Timer() + + # On Linux absolute file urls need to start with "file://" + # otherwise a path of "/home/some" is converted to "http://home/some". + if platform.system() in ["Linux", "Darwin"]: + if url.startswith("/"): + url = "file://" + url + self.url = url + + windowInfo = cefpython.WindowInfo() + if platform.system() == "Windows": + windowInfo.SetAsChild(self.GetHandle()) + elif platform.system() == "Linux": + windowInfo.SetAsChild(self.GetGtkWidget()) + elif platform.system() == "Darwin": + (width, height) = self.GetClientSizeTuple() + windowInfo.SetAsChild(self.GetHandle(), + [0, 0, width, height]) + else: + raise Exception("Unsupported OS") + + if not browserSettings: + browserSettings = {} + + # Disable plugins: + # | browserSettings["plugins_disabled"] = True + + self.browser = cefpython.CreateBrowserSync(windowInfo, + browserSettings=browserSettings, navigateUrl=url) + + if platform.system() == "Windows": + self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) + self.Bind(wx.EVT_SIZE, self.OnSize) + + self._useTimer = useTimer + if useTimer: + CreateMessageLoopTimer(timerMillis) + else: + # Currently multiple EVT_IDLE events might be registered + # when creating multiple ChromeWindow instances. This will + # result in calling CEF message loop work multiple times + # simultaneously causing performance penalties and possibly + # some unwanted behavior (CEF Python Issue 129). + Debug("WARNING: Using EVT_IDLE for CEF message loop processing"\ + " is not recommended") + self.Bind(wx.EVT_IDLE, self.OnIdle) + + self.Bind(wx.EVT_CLOSE, self.OnClose) + + def OnClose(self, event): + if not self._useTimer: + try: + self.Unbind(wx.EVT_IDLE) + except: + # Calling Unbind() may cause problems on Windows 8: + # https://groups.google.com/d/topic/cefpython/iXE7e1ekArI/discussion + # (it was causing problems in __del__, this might not + # be true anymore in OnClose, but still let's make sure) + pass + self.browser.ParentWindowWillClose() + + def OnIdle(self, event): + """Service CEF message loop when useTimer is False""" + cefpython.MessageLoopWork() + event.Skip() + + def OnSetFocus(self, event): + """OS_WIN only.""" + cefpython.WindowUtils.OnSetFocus(self.GetHandle(), 0, 0, 0) + event.Skip() + + def OnSize(self, event): + """OS_WIN only. Handle the the size event""" + cefpython.WindowUtils.OnSize(self.GetHandle(), 0, 0, 0) + event.Skip() + + def GetBrowser(self): + """Returns the CEF's browser object""" + return self.browser + + def LoadUrl(self, url, onLoadStart=None, onLoadEnd=None): + if onLoadStart or onLoadEnd: + self.GetBrowser().SetClientHandler( + CallbackClientHandler(onLoadStart, onLoadEnd)) + + browser = self.GetBrowser() + if cefpython.g_debug: + Debug("LoadUrl() self: %s" % self) + Debug("browser: %s" % browser) + Debug("browser id: %s" % browser.GetIdentifier()) + Debug("mainframe: %s" % browser.GetMainFrame()) + Debug("mainframe id: %s" % \ + browser.GetMainFrame().GetIdentifier()) + self.GetBrowser().GetMainFrame().LoadUrl(url) + + #wx.CallLater(100, browser.ReloadIgnoreCache) + #wx.CallLater(200, browser.GetMainFrame().LoadUrl, url) + + +class ChromeCtrl(wx.Panel): + def __init__(self, parent, url="", useTimer=True, + timerMillis=DEFAULT_TIMER_MILLIS, + browserSettings=None, hasNavBar=True, + *args, **kwargs): + # You also have to set the wx.WANTS_CHARS style for + # all parent panels/controls, if it's deeply embedded. + wx.Panel.__init__(self, parent, style=wx.WANTS_CHARS, *args, **kwargs) + + self.chromeWindow = ChromeWindow(self, url=str(url), useTimer=useTimer, + browserSettings=browserSettings) + sizer = wx.BoxSizer(wx.VERTICAL) + self.navigationBar = None + if hasNavBar: + self.navigationBar = self.CreateNavigationBar() + sizer.Add(self.navigationBar, 0, wx.EXPAND|wx.ALL, 0) + self._InitEventHandlers() + + sizer.Add(self.chromeWindow, 1, wx.EXPAND, 0) + + self.SetSizer(sizer) + self.Fit() + + ch = DefaultClientHandler(self) + self.SetClientHandler(ch) + if self.navigationBar: + self.UpdateButtonsState() + + def _InitEventHandlers(self): + self.navigationBar.backBtn.Bind(wx.EVT_BUTTON, self.OnLeft) + self.navigationBar.forwardBtn.Bind(wx.EVT_BUTTON, self.OnRight) + self.navigationBar.reloadBtn.Bind(wx.EVT_BUTTON, self.OnReload) + + def GetNavigationBar(self): + return self.navigationBar + + def SetNavigationBar(self, navigationBar): + sizer = self.GetSizer() + if self.navigationBar: + # remove previous one + sizer.Replace(self.navigationBar, navigationBar) + self.navigationBar.Hide() + del self.navigationBar + else: + sizer.Insert(0, navigationBar, 0, wx.EXPAND) + self.navigationBar = navigationBar + sizer.Fit(self) + + def CreateNavigationBar(self): + np = NavigationBar(self) + return np + + def SetClientHandler(self, handler): + self.chromeWindow.GetBrowser().SetClientHandler(handler) + + def OnLeft(self, event): + if self.chromeWindow.GetBrowser().CanGoBack(): + self.chromeWindow.GetBrowser().GoBack() + self.UpdateButtonsState() + self.chromeWindow.GetBrowser().SetFocus(True) + + def OnRight(self, event): + if self.chromeWindow.GetBrowser().CanGoForward(): + self.chromeWindow.GetBrowser().GoForward() + self.UpdateButtonsState() + self.chromeWindow.GetBrowser().SetFocus(True) + + def OnReload(self, event): + self.chromeWindow.GetBrowser().Reload() + self.UpdateButtonsState() + self.chromeWindow.GetBrowser().SetFocus(True) + + def UpdateButtonsState(self): + self.navigationBar.backBtn.Enable( + self.chromeWindow.GetBrowser().CanGoBack()) + self.navigationBar.forwardBtn.Enable( + self.chromeWindow.GetBrowser().CanGoForward()) + + def OnLoadStart(self, browser, frame): + if self.navigationBar: + self.UpdateButtonsState() + self.navigationBar.GetUrlCtrl().SetValue( + browser.GetMainFrame().GetUrl()) + self.navigationBar.AddToHistory(browser.GetMainFrame().GetUrl()) + + def OnLoadEnd(self, browser, frame, httpStatusCode): + if self.navigationBar: + # In CEF 3 the CanGoBack() and CanGoForward() methods + # sometimes do work, sometimes do not, when called from + # the OnLoadStart event. That's why we're calling it again + # here. This is still not perfect as OnLoadEnd() is not + # guaranteed to get called for all types of pages. See the + # cefpython documentation: + # https://code.google.com/p/cefpython/wiki/LoadHandler + # OnDomReady() would be perfect, but is still not implemented. + # Another option is to implement our own browser state + # using the OnLoadStart and OnLoadEnd callbacks. + self.UpdateButtonsState() + +class DefaultClientHandler(object): + def __init__(self, parentCtrl): + self.parentCtrl = parentCtrl + + def OnLoadStart(self, browser, frame): + self.parentCtrl.OnLoadStart(browser, frame) + + def OnLoadEnd(self, browser, frame, httpStatusCode): + self.parentCtrl.OnLoadEnd(browser, frame, httpStatusCode) + + def OnLoadError(self, browser, frame, errorCode, errorText, failedUrl): + # TODO + Debug("ERROR LOADING URL : %s" % failedUrl) + +class CallbackClientHandler(object): + def __init__(self, onLoadStart=None, onLoadEnd=None): + self._onLoadStart = onLoadStart + self._onLoadEnd = onLoadEnd + + def OnLoadStart(self, browser, frame): + if self._onLoadStart and frame.GetUrl() != "about:blank": + self._onLoadStart(browser, frame) + + def OnLoadEnd(self, browser, frame, httpStatusCode): + if self._onLoadEnd and frame.GetUrl() != "about:blank": + self._onLoadEnd(browser, frame, httpStatusCode) + + def OnLoadError(self, browser, frame, errorCode, errorText, failedUrl): + # TODO + Debug("ERROR LOADING URL : %s, %s" % (failedUrl, frame.GetUrl())) + +#------------------------------------------------------------------------------- + +def Initialize(settings=None, debug=False): + """Initializes CEF, We should do it before initializing wx + If no settings passed a default is used + """ + switches = {} + global g_settings + if not settings: + settings = {} + + if not "log_severity" in settings: + settings["log_severity"] = cefpython.LOGSEVERITY_INFO + if not "log_file" in settings: + settings["log_file"] = "" + + if platform.system() == "Linux": + # On Linux we need to set locales and resources directories. + if not "locales_dir_path" in settings: + settings["locales_dir_path"] = \ + cefpython.GetModuleDirectory() + "/locales" + if not "resources_dir_path" in settings: + settings["resources_dir_path"] = cefpython.GetModuleDirectory() + elif platform.system() == "Darwin": + # On Mac we need to set the resoures dir and the locale_pak switch + if not "resources_dir_path" in settings: + settings["resources_dir_path"] = (cefpython.GetModuleDirectory() + + "/Resources") + locale_pak = (cefpython.GetModuleDirectory() + + "/Resources/en.lproj/locale.pak") + if "locale_pak" in settings: + locale_pak = settings["locale_pak"] + del settings["locale_pak"] + switches["locale_pak"] = locale_pak + + if not "browser_subprocess_path" in settings: + settings["browser_subprocess_path"] = \ + "%s/%s" % (cefpython.GetModuleDirectory(), "subprocess") + + # DEBUGGING options: + # ------------------ + if debug: + settings["debug"] = True # cefpython messages in console and log_file + settings["log_severity"] = cefpython.LOGSEVERITY_VERBOSE + settings["log_file"] = "debug.log" # Set to "" to disable. + settings["release_dcheck_enabled"] = True + + g_settings = settings + cefpython.Initialize(settings, switches) + +def Shutdown(): + """Shuts down CEF, should be called by app exiting code""" + DestroyMessageLoopTimer() + cefpython.Shutdown() diff --git a/cefpython/cef3/wx-subpackage/examples/back.png b/cefpython/wx-subpackage/examples/back.png similarity index 100% rename from cefpython/cef3/wx-subpackage/examples/back.png rename to cefpython/wx-subpackage/examples/back.png diff --git a/cefpython/cef3/wx-subpackage/examples/forward.png b/cefpython/wx-subpackage/examples/forward.png similarity index 100% rename from cefpython/cef3/wx-subpackage/examples/forward.png rename to cefpython/wx-subpackage/examples/forward.png diff --git a/cefpython/cef3/wx-subpackage/examples/reload_page.png b/cefpython/wx-subpackage/examples/reload_page.png similarity index 100% rename from cefpython/cef3/wx-subpackage/examples/reload_page.png rename to cefpython/wx-subpackage/examples/reload_page.png diff --git a/cefpython/cef3/wx-subpackage/examples/sample1.html b/cefpython/wx-subpackage/examples/sample1.html similarity index 100% rename from cefpython/cef3/wx-subpackage/examples/sample1.html rename to cefpython/wx-subpackage/examples/sample1.html diff --git a/cefpython/cef3/wx-subpackage/examples/sample1.py b/cefpython/wx-subpackage/examples/sample1.py similarity index 97% rename from cefpython/cef3/wx-subpackage/examples/sample1.py rename to cefpython/wx-subpackage/examples/sample1.py index 83d63f260..e61019a50 100644 --- a/cefpython/cef3/wx-subpackage/examples/sample1.py +++ b/cefpython/wx-subpackage/examples/sample1.py @@ -1,60 +1,60 @@ -# Simple sample ilustrating the usage of CEFWindow class. - -# On Mac the cefpython library must be imported the very first, -# before any other libraries (Issue 155). -import cefpython3.wx.chromectrl as chrome - -import os -import wx -import platform - -class MainFrame(wx.Frame): - def __init__(self): - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, - title='cefwx example1', size=(800,600)) - - self.cefWindow = chrome.ChromeWindow(self, - url=os.path.join(os.path.dirname(os.path.abspath(__file__)), - "sample1.html")) - - sizer = wx.BoxSizer() - sizer.Add(self.cefWindow, 1, wx.EXPAND, 0) - self.SetSizer(sizer) - - self.Bind(wx.EVT_CLOSE, self.OnClose) - - def OnClose(self, event): - # Remember to destroy all CEF browser references before calling - # Destroy(), so that browser closes cleanly. In this specific - # example there are no references kept, but keep this in mind - # for the future. - self.Destroy() - # On Mac the code after app.MainLoop() never executes, so - # need to call CEF shutdown here. - if platform.system() == "Darwin": - chrome.Shutdown() - wx.GetApp().Exit() - -class MyApp(wx.App): - def OnInit(self): - frame = MainFrame() - self.SetTopWindow(frame) - frame.Show() - return True - -if __name__ == '__main__': - chrome.Initialize({ - "debug": True, - "log_file": "debug.log", - "log_severity": chrome.cefpython.LOGSEVERITY_INFO, - "release_dcheck_enabled": True, - # "cache_path": "webcache/", - }) - print('[sample1.py] wx.version=%s' % wx.version()) - app = MyApp(False) - app.MainLoop() - # Important: do the wx cleanup before calling Shutdown - del app - # On Mac Shutdown is called in OnClose - if platform.system() in ["Linux", "Windows"]: - chrome.Shutdown() +# Simple sample ilustrating the usage of CEFWindow class. + +# On Mac the cefpython library must be imported the very first, +# before any other libraries (Issue 155). +import cefpython3.wx.chromectrl as chrome + +import os +import wx +import platform + +class MainFrame(wx.Frame): + def __init__(self): + wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, + title='cefwx example1', size=(800,600)) + + self.cefWindow = chrome.ChromeWindow(self, + url=os.path.join(os.path.dirname(os.path.abspath(__file__)), + "sample1.html")) + + sizer = wx.BoxSizer() + sizer.Add(self.cefWindow, 1, wx.EXPAND, 0) + self.SetSizer(sizer) + + self.Bind(wx.EVT_CLOSE, self.OnClose) + + def OnClose(self, event): + # Remember to destroy all CEF browser references before calling + # Destroy(), so that browser closes cleanly. In this specific + # example there are no references kept, but keep this in mind + # for the future. + self.Destroy() + # On Mac the code after app.MainLoop() never executes, so + # need to call CEF shutdown here. + if platform.system() == "Darwin": + chrome.Shutdown() + wx.GetApp().Exit() + +class MyApp(wx.App): + def OnInit(self): + frame = MainFrame() + self.SetTopWindow(frame) + frame.Show() + return True + +if __name__ == '__main__': + chrome.Initialize({ + "debug": True, + "log_file": "debug.log", + "log_severity": chrome.cefpython.LOGSEVERITY_INFO, + "release_dcheck_enabled": True, + # "cache_path": "webcache/", + }) + print('[sample1.py] wx.version=%s' % wx.version()) + app = MyApp(False) + app.MainLoop() + # Important: do the wx cleanup before calling Shutdown + del app + # On Mac Shutdown is called in OnClose + if platform.system() in ["Linux", "Windows"]: + chrome.Shutdown() diff --git a/cefpython/cef3/wx-subpackage/examples/sample2.py b/cefpython/wx-subpackage/examples/sample2.py similarity index 97% rename from cefpython/cef3/wx-subpackage/examples/sample2.py rename to cefpython/wx-subpackage/examples/sample2.py index 3c218a5f6..7f77cb88d 100644 --- a/cefpython/cef3/wx-subpackage/examples/sample2.py +++ b/cefpython/wx-subpackage/examples/sample2.py @@ -1,121 +1,121 @@ -# Slightly more advanced sample illustrating the usage of CEFWindow class. - -# On Mac the cefpython library must be imported the very first, -# before any other libraries (Issue 155). -import cefpython3.wx.chromectrl as chrome - -# TODO: There is something wrong happening on Linux. CPU usage -# for the python process is 100% all the time. This problem -# does not occur on Windows, nor in sample1.py/sample3.py. -# It must have something to do with invalid usage of the wx -# controls in this example. - -import wx -import wx.lib.agw.flatnotebook as fnb -import platform -import sys - -ROOT_NAME = "My Locations" - -URLS = ["http://gmail.com", - "http://maps.google.com", - "http://youtube.com", - "http://yahoo.com", - "http://wikipedia.com", - "http://cyaninc.com", - "http://tavmjong.free.fr/INKSCAPE/MANUAL/web/svg_tests.php" - ] - - -class MainFrame(wx.Frame): - def __init__(self): - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, - title='cefwx example2', size=(800, 600)) - - self.initComponents() - self.layoutComponents() - self.initEventHandlers() - if len(sys.argv) == 2 and sys.argv[1] == "test-launch": - wx.CallLater(500, self.testLaunch) - - def testLaunch(self): - # This hash is checked by /tests/test-launch.sh script - # to detect whether CEF initialized successfully. - print("b8ba7d9945c22425328df2e21fbb64cd") - self.Close() - - def initComponents(self): - self.tree = wx.TreeCtrl(self, id=-1, size=(200, -1)) - self.root = self.tree.AddRoot(ROOT_NAME) - for url in URLS: - self.tree.AppendItem(self.root, url) - self.tree.Expand(self.root) - - self.tabs = fnb.FlatNotebook(self, wx.ID_ANY, - agwStyle=fnb.FNB_NODRAG | fnb.FNB_X_ON_TAB) - # You also have to set the wx.WANTS_CHARS style for - # all parent panels/controls, if it's deeply embedded. - self.tabs.SetWindowStyleFlag(wx.WANTS_CHARS) - - def layoutComponents(self): - sizer = wx.BoxSizer(wx.HORIZONTAL) - sizer.Add(self.tree, 0, wx.EXPAND) - sizer.Add(self.tabs, 1, wx.EXPAND) - self.SetSizer(sizer) - - def initEventHandlers(self): - self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, self.tree) - self.Bind(fnb.EVT_FLATNOTEBOOK_PAGE_CLOSING, self.OnPageClosing) - self.Bind(wx.EVT_CLOSE, self.OnClose) - - def OnSelChanged(self, event): - self.item = event.GetItem() - url = self.tree.GetItemText(self.item) - if url and url != ROOT_NAME: - cefPanel = chrome.ChromeCtrl(self.tabs, useTimer=True, url=str(url)) - self.tabs.AddPage(cefPanel, url) - self.tabs.SetSelection(self.tabs.GetPageCount()-1) - event.Skip() - - def OnPageClosing(self, event): - print("sample2.py: One could place some extra closing stuff here") - event.Skip() - - def OnClose(self, event): - # Remember to destroy all CEF browser references before calling - # Destroy(), so that browser closes cleanly. In this specific - # example there are no references kept, but keep this in mind - # for the future. - self.Destroy() - # On Mac the code after app.MainLoop() never executes, so - # need to call CEF shutdown here. - if platform.system() == "Darwin": - chrome.Shutdown() - wx.GetApp().Exit() - - -class MyApp(wx.App): - def OnInit(self): - frame = MainFrame() - self.SetTopWindow(frame) - frame.Show() - return True - - -if __name__ == '__main__': - chrome.Initialize() - if platform.system() == "Linux": - # CEF initialization fails intermittently on Linux during - # launch of a subprocess (Issue 131). The solution is - # to offload cpu for half a second after Initialize - # has returned (it still runs some stuff in its thread). - import time - time.sleep(0.5) - print('sample2.py: wx.version=%s' % wx.version()) - app = MyApp(False) - app.MainLoop() - # Important: do the wx cleanup before calling Shutdown - del app - # On Mac Shutdown is called in OnClose - if platform.system() in ["Linux", "Windows"]: - chrome.Shutdown() +# Slightly more advanced sample illustrating the usage of CEFWindow class. + +# On Mac the cefpython library must be imported the very first, +# before any other libraries (Issue 155). +import cefpython3.wx.chromectrl as chrome + +# TODO: There is something wrong happening on Linux. CPU usage +# for the python process is 100% all the time. This problem +# does not occur on Windows, nor in sample1.py/sample3.py. +# It must have something to do with invalid usage of the wx +# controls in this example. + +import wx +import wx.lib.agw.flatnotebook as fnb +import platform +import sys + +ROOT_NAME = "My Locations" + +URLS = ["http://gmail.com", + "http://maps.google.com", + "http://youtube.com", + "http://yahoo.com", + "http://wikipedia.com", + "http://cyaninc.com", + "http://tavmjong.free.fr/INKSCAPE/MANUAL/web/svg_tests.php" + ] + + +class MainFrame(wx.Frame): + def __init__(self): + wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, + title='cefwx example2', size=(800, 600)) + + self.initComponents() + self.layoutComponents() + self.initEventHandlers() + if len(sys.argv) == 2 and sys.argv[1] == "test-launch": + wx.CallLater(500, self.testLaunch) + + def testLaunch(self): + # This hash is checked by /tests/test-launch.sh script + # to detect whether CEF initialized successfully. + print("b8ba7d9945c22425328df2e21fbb64cd") + self.Close() + + def initComponents(self): + self.tree = wx.TreeCtrl(self, id=-1, size=(200, -1)) + self.root = self.tree.AddRoot(ROOT_NAME) + for url in URLS: + self.tree.AppendItem(self.root, url) + self.tree.Expand(self.root) + + self.tabs = fnb.FlatNotebook(self, wx.ID_ANY, + agwStyle=fnb.FNB_NODRAG | fnb.FNB_X_ON_TAB) + # You also have to set the wx.WANTS_CHARS style for + # all parent panels/controls, if it's deeply embedded. + self.tabs.SetWindowStyleFlag(wx.WANTS_CHARS) + + def layoutComponents(self): + sizer = wx.BoxSizer(wx.HORIZONTAL) + sizer.Add(self.tree, 0, wx.EXPAND) + sizer.Add(self.tabs, 1, wx.EXPAND) + self.SetSizer(sizer) + + def initEventHandlers(self): + self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, self.tree) + self.Bind(fnb.EVT_FLATNOTEBOOK_PAGE_CLOSING, self.OnPageClosing) + self.Bind(wx.EVT_CLOSE, self.OnClose) + + def OnSelChanged(self, event): + self.item = event.GetItem() + url = self.tree.GetItemText(self.item) + if url and url != ROOT_NAME: + cefPanel = chrome.ChromeCtrl(self.tabs, useTimer=True, url=str(url)) + self.tabs.AddPage(cefPanel, url) + self.tabs.SetSelection(self.tabs.GetPageCount()-1) + event.Skip() + + def OnPageClosing(self, event): + print("sample2.py: One could place some extra closing stuff here") + event.Skip() + + def OnClose(self, event): + # Remember to destroy all CEF browser references before calling + # Destroy(), so that browser closes cleanly. In this specific + # example there are no references kept, but keep this in mind + # for the future. + self.Destroy() + # On Mac the code after app.MainLoop() never executes, so + # need to call CEF shutdown here. + if platform.system() == "Darwin": + chrome.Shutdown() + wx.GetApp().Exit() + + +class MyApp(wx.App): + def OnInit(self): + frame = MainFrame() + self.SetTopWindow(frame) + frame.Show() + return True + + +if __name__ == '__main__': + chrome.Initialize() + if platform.system() == "Linux": + # CEF initialization fails intermittently on Linux during + # launch of a subprocess (Issue 131). The solution is + # to offload cpu for half a second after Initialize + # has returned (it still runs some stuff in its thread). + import time + time.sleep(0.5) + print('sample2.py: wx.version=%s' % wx.version()) + app = MyApp(False) + app.MainLoop() + # Important: do the wx cleanup before calling Shutdown + del app + # On Mac Shutdown is called in OnClose + if platform.system() in ["Linux", "Windows"]: + chrome.Shutdown() diff --git a/cefpython/cef3/wx-subpackage/examples/sample3.py b/cefpython/wx-subpackage/examples/sample3.py similarity index 100% rename from cefpython/cef3/wx-subpackage/examples/sample3.py rename to cefpython/wx-subpackage/examples/sample3.py diff --git a/cefpython/cef3/wx-subpackage/images/Arrow Left.png b/cefpython/wx-subpackage/images/Arrow Left.png similarity index 100% rename from cefpython/cef3/wx-subpackage/images/Arrow Left.png rename to cefpython/wx-subpackage/images/Arrow Left.png diff --git a/cefpython/cef3/wx-subpackage/images/Arrow Right.png b/cefpython/wx-subpackage/images/Arrow Right.png similarity index 100% rename from cefpython/cef3/wx-subpackage/images/Arrow Right.png rename to cefpython/wx-subpackage/images/Arrow Right.png diff --git a/cefpython/cef3/wx-subpackage/images/Button Load.png b/cefpython/wx-subpackage/images/Button Load.png similarity index 100% rename from cefpython/cef3/wx-subpackage/images/Button Load.png rename to cefpython/wx-subpackage/images/Button Load.png diff --git a/cefpython/cef3/wx-subpackage/utils.py b/cefpython/wx-subpackage/utils.py similarity index 100% rename from cefpython/cef3/wx-subpackage/utils.py rename to cefpython/wx-subpackage/utils.py From 42c5964a19e4b01fe40f9931e2787558617e7a6e Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 14 May 2016 12:45:18 +0200 Subject: [PATCH 029/557] Rename wx-subpackage/ to wx/ and update installer files. --- cefpython/linux/installer/make-setup.py | 4 ++-- cefpython/mac/installer/build_run_chromectrl.sh | 2 +- cefpython/mac/installer/make-setup.py | 4 ++-- cefpython/windows/installer/make-installer.py | 3 +-- cefpython/windows/installer/make-setup.py | 4 ++-- cefpython/{wx-subpackage => wx}/README.txt | 0 cefpython/{wx-subpackage => wx}/__init__.py | 0 cefpython/{wx-subpackage => wx}/chromectrl.py | 0 cefpython/{wx-subpackage => wx}/examples/back.png | Bin .../{wx-subpackage => wx}/examples/forward.png | Bin .../{wx-subpackage => wx}/examples/reload_page.png | Bin .../{wx-subpackage => wx}/examples/sample1.html | 0 cefpython/{wx-subpackage => wx}/examples/sample1.py | 0 cefpython/{wx-subpackage => wx}/examples/sample2.py | 0 cefpython/{wx-subpackage => wx}/examples/sample3.py | 0 .../{wx-subpackage => wx}/images/Arrow Left.png | Bin .../{wx-subpackage => wx}/images/Arrow Right.png | Bin .../{wx-subpackage => wx}/images/Button Load.png | Bin cefpython/{wx-subpackage => wx}/utils.py | 0 19 files changed, 8 insertions(+), 9 deletions(-) rename cefpython/{wx-subpackage => wx}/README.txt (100%) rename cefpython/{wx-subpackage => wx}/__init__.py (100%) rename cefpython/{wx-subpackage => wx}/chromectrl.py (100%) rename cefpython/{wx-subpackage => wx}/examples/back.png (100%) rename cefpython/{wx-subpackage => wx}/examples/forward.png (100%) rename cefpython/{wx-subpackage => wx}/examples/reload_page.png (100%) rename cefpython/{wx-subpackage => wx}/examples/sample1.html (100%) rename cefpython/{wx-subpackage => wx}/examples/sample1.py (100%) rename cefpython/{wx-subpackage => wx}/examples/sample2.py (100%) rename cefpython/{wx-subpackage => wx}/examples/sample3.py (100%) rename cefpython/{wx-subpackage => wx}/images/Arrow Left.png (100%) rename cefpython/{wx-subpackage => wx}/images/Arrow Right.png (100%) rename cefpython/{wx-subpackage => wx}/images/Button Load.png (100%) rename cefpython/{wx-subpackage => wx}/utils.py (100%) diff --git a/cefpython/linux/installer/make-setup.py b/cefpython/linux/installer/make-setup.py index 2773f8a68..153963107 100644 --- a/cefpython/linux/installer/make-setup.py +++ b/cefpython/linux/installer/make-setup.py @@ -138,8 +138,8 @@ def main(): ret = os.system("mv "+package_dir+"/*.css "+package_dir+"/examples/") assert ret == 0 - print("Copying wx-subpackage to wx dir in package dir") - wx_subpackage_dir = os.path.abspath(installer_dir+"/../../wx-subpackage/") + print("Copying wx/ to package dir") + wx_subpackage_dir = os.path.abspath(installer_dir+"/../../wx/") ret = os.system("cp -rf "+wx_subpackage_dir+"/* "+package_dir+"/wx/") assert ret == 0 diff --git a/cefpython/mac/installer/build_run_chromectrl.sh b/cefpython/mac/installer/build_run_chromectrl.sh index 828b30754..a0d12ce59 100644 --- a/cefpython/mac/installer/build_run_chromectrl.sh +++ b/cefpython/mac/installer/build_run_chromectrl.sh @@ -15,7 +15,7 @@ pip install --upgrade cefpython3 --no-index --find-links=file://$cwd if [ $? -ne 0 ]; then echo "ERROR: pip install cefpython3..." && exit 1; fi; cd ../ -cd ../../wx-subpackage/examples/ +cd ../../wx/examples/ python sample1.py #if [ $? -ne 0 ]; then echo "ERROR: python sample1.py" && exit 1; fi; diff --git a/cefpython/mac/installer/make-setup.py b/cefpython/mac/installer/make-setup.py index 70bb16b0e..81a70825e 100644 --- a/cefpython/mac/installer/make-setup.py +++ b/cefpython/mac/installer/make-setup.py @@ -140,8 +140,8 @@ def main(): ret = os.system("mv "+package_dir+"/*.css "+package_dir+"/examples/") assert ret == 0 - print("Copying wx-subpackage to wx dir in package dir") - wx_subpackage_dir = os.path.abspath(installer_dir+"/../../wx-subpackage/") + print("Copying wx/ to package dir") + wx_subpackage_dir = os.path.abspath(installer_dir+"/../../wx/") ret = os.system("cp -rf "+wx_subpackage_dir+"/* "+package_dir+"/wx/") assert ret == 0 diff --git a/cefpython/windows/installer/make-installer.py b/cefpython/windows/installer/make-installer.py index ef8c715b8..ab31d5365 100644 --- a/cefpython/windows/installer/make-installer.py +++ b/cefpython/windows/installer/make-installer.py @@ -43,8 +43,7 @@ def main(): + str(sys.version_info.major) + str(sys.version_info.minor) + ".pyd") vars["INSTALLER_DIR"] = os.getcwd() - vars["WX_SUBPACKAGE_DIR"] = os.path.realpath(os.getcwd()+r"\..\.." - "\wx-subpackage") + vars["WX_SUBPACKAGE_DIR"] = os.path.realpath(os.getcwd()+r"\..\..\wx") vars["PLATFORM"] = sysconfig.get_platform() if BITS == "32bit": diff --git a/cefpython/windows/installer/make-setup.py b/cefpython/windows/installer/make-setup.py index 037237b4d..27d521e30 100644 --- a/cefpython/windows/installer/make-setup.py +++ b/cefpython/windows/installer/make-setup.py @@ -151,8 +151,8 @@ def main(): glob_move(package_dir+"/*.css", package_dir+"/examples/") glob_move(package_dir+"/*.js", package_dir+"/examples/") - print("Copying wx-subpackage to wx dir in package dir") - wx_subpackage_dir = os.path.abspath(installer_dir+"/../../wx-subpackage/") + print("Copying wx/ to package dir") + wx_subpackage_dir = os.path.abspath(installer_dir+"/../../wx/") glob_copy(wx_subpackage_dir+"/*", package_dir+"/wx/") print("Moving wx examples from wx/examples to examples/wx") diff --git a/cefpython/wx-subpackage/README.txt b/cefpython/wx/README.txt similarity index 100% rename from cefpython/wx-subpackage/README.txt rename to cefpython/wx/README.txt diff --git a/cefpython/wx-subpackage/__init__.py b/cefpython/wx/__init__.py similarity index 100% rename from cefpython/wx-subpackage/__init__.py rename to cefpython/wx/__init__.py diff --git a/cefpython/wx-subpackage/chromectrl.py b/cefpython/wx/chromectrl.py similarity index 100% rename from cefpython/wx-subpackage/chromectrl.py rename to cefpython/wx/chromectrl.py diff --git a/cefpython/wx-subpackage/examples/back.png b/cefpython/wx/examples/back.png similarity index 100% rename from cefpython/wx-subpackage/examples/back.png rename to cefpython/wx/examples/back.png diff --git a/cefpython/wx-subpackage/examples/forward.png b/cefpython/wx/examples/forward.png similarity index 100% rename from cefpython/wx-subpackage/examples/forward.png rename to cefpython/wx/examples/forward.png diff --git a/cefpython/wx-subpackage/examples/reload_page.png b/cefpython/wx/examples/reload_page.png similarity index 100% rename from cefpython/wx-subpackage/examples/reload_page.png rename to cefpython/wx/examples/reload_page.png diff --git a/cefpython/wx-subpackage/examples/sample1.html b/cefpython/wx/examples/sample1.html similarity index 100% rename from cefpython/wx-subpackage/examples/sample1.html rename to cefpython/wx/examples/sample1.html diff --git a/cefpython/wx-subpackage/examples/sample1.py b/cefpython/wx/examples/sample1.py similarity index 100% rename from cefpython/wx-subpackage/examples/sample1.py rename to cefpython/wx/examples/sample1.py diff --git a/cefpython/wx-subpackage/examples/sample2.py b/cefpython/wx/examples/sample2.py similarity index 100% rename from cefpython/wx-subpackage/examples/sample2.py rename to cefpython/wx/examples/sample2.py diff --git a/cefpython/wx-subpackage/examples/sample3.py b/cefpython/wx/examples/sample3.py similarity index 100% rename from cefpython/wx-subpackage/examples/sample3.py rename to cefpython/wx/examples/sample3.py diff --git a/cefpython/wx-subpackage/images/Arrow Left.png b/cefpython/wx/images/Arrow Left.png similarity index 100% rename from cefpython/wx-subpackage/images/Arrow Left.png rename to cefpython/wx/images/Arrow Left.png diff --git a/cefpython/wx-subpackage/images/Arrow Right.png b/cefpython/wx/images/Arrow Right.png similarity index 100% rename from cefpython/wx-subpackage/images/Arrow Right.png rename to cefpython/wx/images/Arrow Right.png diff --git a/cefpython/wx-subpackage/images/Button Load.png b/cefpython/wx/images/Button Load.png similarity index 100% rename from cefpython/wx-subpackage/images/Button Load.png rename to cefpython/wx/images/Button Load.png diff --git a/cefpython/wx-subpackage/utils.py b/cefpython/wx/utils.py similarity index 100% rename from cefpython/wx-subpackage/utils.py rename to cefpython/wx/utils.py From b6e0a9bc2f24c2ec740915299e24b4e2de6b1a46 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 14 May 2016 12:51:31 +0200 Subject: [PATCH 030/557] Fix wxpython navigation bar images - Issue #221. --- cefpython/wx/chromectrl.py | 6 +++--- cefpython/wx/images/Arrow Left.png | Bin 3798 -> 0 bytes cefpython/wx/images/Arrow Right.png | Bin 3824 -> 0 bytes cefpython/wx/images/Button Load.png | Bin 4880 -> 0 bytes cefpython/wx/images/back.png | Bin 0 -> 1348 bytes cefpython/wx/images/forward.png | Bin 0 -> 1311 bytes cefpython/wx/images/reload_page.png | Bin 0 -> 1420 bytes 7 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 cefpython/wx/images/Arrow Left.png delete mode 100644 cefpython/wx/images/Arrow Right.png delete mode 100644 cefpython/wx/images/Button Load.png create mode 100644 cefpython/wx/images/back.png create mode 100644 cefpython/wx/images/forward.png create mode 100644 cefpython/wx/images/reload_page.png diff --git a/cefpython/wx/chromectrl.py b/cefpython/wx/chromectrl.py index d4ea557b7..1d08b4b99 100644 --- a/cefpython/wx/chromectrl.py +++ b/cefpython/wx/chromectrl.py @@ -67,13 +67,13 @@ def __init__(self, parent, *args, **kwargs): def _InitComponents(self): self.backBtn = buttons.GenBitmapButton(self, -1, - wx.Bitmap(os.path.join(self.bitmapDir, "Arrow Left.png"), + wx.Bitmap(os.path.join(self.bitmapDir, "back.png"), wx.BITMAP_TYPE_PNG), style=wx.BORDER_NONE) self.forwardBtn = buttons.GenBitmapButton(self, -1, - wx.Bitmap(os.path.join(self.bitmapDir, "Arrow Right.png"), + wx.Bitmap(os.path.join(self.bitmapDir, "forward.png"), wx.BITMAP_TYPE_PNG), style=wx.BORDER_NONE) self.reloadBtn = buttons.GenBitmapButton(self, -1, - wx.Bitmap(os.path.join(self.bitmapDir, "Button Load.png"), + wx.Bitmap(os.path.join(self.bitmapDir, "reload_page.png"), wx.BITMAP_TYPE_PNG), style=wx.BORDER_NONE) self.url = wx.TextCtrl(self, id=-1, style=0) diff --git a/cefpython/wx/images/Arrow Left.png b/cefpython/wx/images/Arrow Left.png deleted file mode 100644 index 640c707d1b16d355aad519d42cadaf3af17c6e09..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3798 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 Date: Sat, 14 May 2016 13:08:43 +0200 Subject: [PATCH 031/557] Fix paths in compile scripts - issue caused by moving the cef3/ directory. --- cefpython/linux/compile.py | 9 +-------- cefpython/linux/setup/fix_pyx_files.py | 4 ++-- cefpython/linux/setup/setup.py | 8 +++----- cefpython/mac/compile.py | 2 +- cefpython/mac/setup/fix_pyx_files.py | 4 ++-- cefpython/mac/setup/setup.py | 8 +++----- cefpython/windows/setup/fix_pyx_files.py | 4 ++-- cefpython/windows/setup/setup.py | 7 +++---- 8 files changed, 17 insertions(+), 29 deletions(-) diff --git a/cefpython/linux/compile.py b/cefpython/linux/compile.py index 1540c6ce1..a6d7fe28b 100644 --- a/cefpython/linux/compile.py +++ b/cefpython/linux/compile.py @@ -52,7 +52,7 @@ # fails and then run the compile.py script again and this time # make should succeed. -os.chdir("./../../cpp_utils/") +os.chdir("./../cpp_utils/") subprocess.call("rm -f *.o *.a", shell=True) ret = subprocess.call("make -f Makefile", shell=True) @@ -90,13 +90,6 @@ # .copy() will also copy Permission bits shutil.copy("./subprocess", subprocess_exe) -# os.chdir("./../v8function_handler/") -# ret = subprocess.call("make -f Makefile", shell=True) -# if ret != 0: -# what = raw_input("make failed, press 'y' to continue, 'n' to stop: ") -# if what != "y": -# sys.exit(1) - os.chdir("./../linux/") try: diff --git a/cefpython/linux/setup/fix_pyx_files.py b/cefpython/linux/setup/fix_pyx_files.py index e25922ba5..0c91e336d 100644 --- a/cefpython/linux/setup/fix_pyx_files.py +++ b/cefpython/linux/setup/fix_pyx_files.py @@ -59,7 +59,7 @@ def ExceptAllMissing(content): print("\n") mainfile = "cefpython.pyx" -pyxfiles = glob.glob("../../../*.pyx") +pyxfiles = glob.glob("../../*.pyx") if not len(pyxfiles): sys.exit(1) pyxfiles = [file for file in pyxfiles if file.find(mainfile) == -1] @@ -81,7 +81,7 @@ def ExceptAllMissing(content): # Copying pyxfiles and reading its contents. print("Copying .pyx files to /setup/: %s" % pyxfiles) -shutil.copy("../../../%s" % mainfile, "./%s" % mainfile) +shutil.copy("../../%s" % mainfile, "./%s" % mainfile) # Rest of the files will be copied in for loop below. print("Fixing includes in .pyx files:") diff --git a/cefpython/linux/setup/setup.py b/cefpython/linux/setup/setup.py index 999e39e22..28464e2b2 100644 --- a/cefpython/linux/setup/setup.py +++ b/cefpython/linux/setup/setup.py @@ -24,7 +24,7 @@ def CompileTimeConstants(): print("Generating: cython_includes/compile_time_constants.pxi") - with open("./../../../cython_includes/compile_time_constants.pxi", "w") as fd: + with open("./../../cython_includes/compile_time_constants.pxi", "w") as fd: fd.write('# This file was generated by setup.py\n') # A way around Python 3.2 bug: UNAME_SYSNAME is not set. fd.write('DEF UNAME_SYSNAME = "%s"\n' % platform.uname()[0]) @@ -51,8 +51,7 @@ def CompileTimeConstants(): include_dirs=[ r'./../', r'./../../', - r'./../../../', - r'./../../../cython_includes/', + r'./../../cython_includes/', '/usr/include/gtk-2.0', '/usr/include/glib-2.0', '/usr/include/cairo', @@ -74,10 +73,9 @@ def CompileTimeConstants(): # http_authentication not implemented on Linux. library_dirs=[ r'./lib_%s' % BITS, - # r'./../../v8function_handler/', r'./../../client_handler/', r'./../../subprocess/', # libcefpythonapp - r'./../../../cpp_utils/' + r'./../../cpp_utils/' ], libraries=[ diff --git a/cefpython/mac/compile.py b/cefpython/mac/compile.py index 1a5a8072a..2d8a048d7 100644 --- a/cefpython/mac/compile.py +++ b/cefpython/mac/compile.py @@ -70,7 +70,7 @@ # fails and then run the compile.py script again and this time # make should succeed. -os.chdir("./../../cpp_utils/") +os.chdir("./../cpp_utils/") subprocess.call("rm -f *.o *.a", shell=True) ret = subprocess.call("make -f Makefile", shell=True) diff --git a/cefpython/mac/setup/fix_pyx_files.py b/cefpython/mac/setup/fix_pyx_files.py index e25922ba5..0c91e336d 100644 --- a/cefpython/mac/setup/fix_pyx_files.py +++ b/cefpython/mac/setup/fix_pyx_files.py @@ -59,7 +59,7 @@ def ExceptAllMissing(content): print("\n") mainfile = "cefpython.pyx" -pyxfiles = glob.glob("../../../*.pyx") +pyxfiles = glob.glob("../../*.pyx") if not len(pyxfiles): sys.exit(1) pyxfiles = [file for file in pyxfiles if file.find(mainfile) == -1] @@ -81,7 +81,7 @@ def ExceptAllMissing(content): # Copying pyxfiles and reading its contents. print("Copying .pyx files to /setup/: %s" % pyxfiles) -shutil.copy("../../../%s" % mainfile, "./%s" % mainfile) +shutil.copy("../../%s" % mainfile, "./%s" % mainfile) # Rest of the files will be copied in for loop below. print("Fixing includes in .pyx files:") diff --git a/cefpython/mac/setup/setup.py b/cefpython/mac/setup/setup.py index 4a2b2e013..3ba1eef6f 100644 --- a/cefpython/mac/setup/setup.py +++ b/cefpython/mac/setup/setup.py @@ -32,7 +32,7 @@ def CompileTimeConstants(): print("Generating: cython_includes/compile_time_constants.pxi") - with open("./../../../cython_includes/compile_time_constants.pxi", "w") as fd: + with open("./../../cython_includes/compile_time_constants.pxi", "w") as fd: fd.write('# This file was generated by setup.py\n') # A way around Python 3.2 bug: UNAME_SYSNAME is not set. fd.write('DEF UNAME_SYSNAME = "%s"\n' % platform.uname()[0]) @@ -59,8 +59,7 @@ def CompileTimeConstants(): include_dirs=[ r'./../', r'./../../', - r'./../../../', - r'./../../../cython_includes/', + r'./../../cython_includes/', '/usr/include/gtk-2.0', '/usr/include/glib-2.0', '/usr/include/cairo', @@ -82,10 +81,9 @@ def CompileTimeConstants(): # http_authentication not implemented on Linux. library_dirs=[ r'./lib_%s' % BITS, - # r'./../../v8function_handler/', r'./../../client_handler/', r'./../../subprocess/', # libcefpythonapp - r'./../../../cpp_utils/' + r'./../../cpp_utils/' ], libraries=[ diff --git a/cefpython/windows/setup/fix_pyx_files.py b/cefpython/windows/setup/fix_pyx_files.py index 33d3b55ab..86ba1dbcb 100644 --- a/cefpython/windows/setup/fix_pyx_files.py +++ b/cefpython/windows/setup/fix_pyx_files.py @@ -57,7 +57,7 @@ def ExceptAllMissing(content): print("\n") mainfile = "cefpython.pyx" -pyxfiles = glob.glob("../../../*.pyx") +pyxfiles = glob.glob("../../*.pyx") if not len(pyxfiles): sys.exit(1) pyxfiles = [file for file in pyxfiles if file.find(mainfile) == -1] @@ -79,7 +79,7 @@ def ExceptAllMissing(content): # Copying pyxfiles and reading its contents. print("Copying .pyx files to /setup/: %s" % pyxfiles) -shutil.copy("../../../%s" % mainfile, "./%s" % mainfile) +shutil.copy("../../%s" % mainfile, "./%s" % mainfile) # Rest of the files will be copied in for loop below. print("Fixing includes in .pyx files:") diff --git a/cefpython/windows/setup/setup.py b/cefpython/windows/setup/setup.py index 3a5cece3e..752adf55f 100644 --- a/cefpython/windows/setup/setup.py +++ b/cefpython/windows/setup/setup.py @@ -27,7 +27,7 @@ # Generate compile_time_constants.pxi def CompileTimeConstants(): print("[setup.py] Generating: cython_includes/compile_time_constants.pxi") - with open("../../../cython_includes/compile_time_constants.pxi", "w") as fd: + with open("../../cython_includes/compile_time_constants.pxi", "w") as fd: fd.write('# This file was generated by setup.py\n') # A way around Python 3.2 bug: UNAME_SYSNAME is not set. fd.write('DEF UNAME_SYSNAME = "%s"\n' % platform.uname()[0]) @@ -63,8 +63,7 @@ def CompileTimeConstants(): include_dirs=[ r'./../', r'./../../', - r'./../../../', - r'./../../../cython_includes/'], + r'./../../cython_includes/'], library_dirs=[ winsdk_lib, @@ -72,7 +71,7 @@ def CompileTimeConstants(): r'./lib_%s' % (BITS), r'./../../client_handler/Release_py%s_%s/' % (PYVER, BITS), r'./../../subprocess/Release_py%s_%s/' % (PYVER, BITS), - r'./../../../cpp_utils/Release_%s/' % (BITS), + r'./../../cpp_utils/Release_%s/' % (BITS), ], libraries=[ From a00c8a49940a7073e1678a681b7e51bdc49fa9d1 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 14 May 2016 16:38:29 +0200 Subject: [PATCH 032/557] Get rid of the CEF_VERSION compile time constant. Issue #106. Update api/ docs. --- api/API-index.md | 1 - api/cefpython.md | 12 - cefpython/browser.pyx | 539 +++++------------- cefpython/cefpython.pyx | 58 +- cefpython/cython_includes/cef_app.pxd | 26 +- .../cython_includes/cef_browser_static.pxd | 31 +- cefpython/cython_includes/cef_linux.pxd | 7 +- cefpython/cython_includes/cef_mac.pxd | 7 +- .../cython_includes/cef_types_wrappers.pxd | 5 +- cefpython/cython_includes/cef_win.pxd | 7 +- cefpython/javascript_bindings.pyx | 102 +--- cefpython/linux/setup/setup.py | 4 - cefpython/mac/setup/setup.py | 4 - cefpython/settings.pyx | 474 ++++++--------- cefpython/utils.pyx | 9 - cefpython/windows/setup/setup.py | 4 - 16 files changed, 408 insertions(+), 882 deletions(-) diff --git a/api/API-index.md b/api/API-index.md index c0df88789..ed0f73a1b 100644 --- a/api/API-index.md +++ b/api/API-index.md @@ -128,7 +128,6 @@ * [GetModuleDirectory](cefpython.md#getmoduledirectory) * [Initialize](cefpython.md#initialize) * [IsThread](cefpython.md#isthread) - * [IsKeyModifier](cefpython.md#iskeymodifier) * [MessageLoop](cefpython.md#messageloop) * [MessageLoopWork](cefpython.md#messageloopwork) * [PostTask](cefpython.md#posttask) diff --git a/api/cefpython.md b/api/cefpython.md index 43a364f81..552e66026 100644 --- a/api/cefpython.md +++ b/api/cefpython.md @@ -16,7 +16,6 @@ Table of contents: * [GetModuleDirectory](#getmoduledirectory) * [Initialize](#initialize) * [IsThread](#isthread) - * [IsKeyModifier](#iskeymodifier) * [MessageLoop](#messageloop) * [MessageLoopWork](#messageloopwork) * [PostTask](#posttask) @@ -138,17 +137,6 @@ List of threads in the Renderer process: * TID_RENDERER: The main thread in the renderer. Used for all webkit and V8 interaction. -### IsKeyModifier - -| Parameter | Type | -| --- | --- | -| key | int | -| modifiers | int | -| __Return__ | bool | - -For use with [KeyboardHandler](KeyboardHandler.md) to check whether ALT, SHIFT or CTRL are pressed. - - ### MessageLoop | | | diff --git a/cefpython/browser.pyx b/cefpython/browser.pyx index f8dc612d0..3059344b8 100644 --- a/cefpython/browser.pyx +++ b/cefpython/browser.pyx @@ -2,16 +2,6 @@ # License: New BSD License. # Website: http://code.google.com/p/cefpython/ -IF CEF_VERSION == 1: - # In CEF 1 there are both KT_KEYDOWN and KEYEVENT_KEYDOWN, and - # these are different constants, making a bit of confusion. - # In CEF 1 KT_ is for SendKeyEvent, KEYEVENT_ is for OnKeyEvent(). - # In CEF 3 there are only KEYEVENT_* constants. - KEYTYPE_KEYDOWN = cef_types.KT_KEYDOWN - KEYTYPE_KEYUP = cef_types.KT_KEYUP - KEYTYPE_CHAR = cef_types.KT_CHAR - -# Both CEF 1 and CEF 3. # cef_mouse_button_type_t, SendMouseClickEvent(). MOUSEBUTTON_LEFT = cef_types.MBT_LEFT MOUSEBUTTON_MIDDLE = cef_types.MBT_MIDDLE @@ -22,12 +12,10 @@ MOUSEBUTTON_RIGHT = cef_types.MBT_RIGHT cdef dict g_pyBrowsers = {} -IF CEF_VERSION == 3: - # Unused function warning in CEF 1. - cdef PyBrowser GetPyBrowserById(int browserId): - if browserId in g_pyBrowsers: - return g_pyBrowsers[browserId] - return None +cdef PyBrowser GetPyBrowserById(int browserId): + if browserId in g_pyBrowsers: + return g_pyBrowsers[browserId] + return None cdef PyBrowser GetPyBrowser(CefRefPtr[CefBrowser] cefBrowser): global g_pyBrowsers @@ -85,24 +73,21 @@ cdef PyBrowser GetPyBrowser(CefRefPtr[CefBrowser] cefBrowser): pyBrowser.SetJavascriptBindings(javascriptBindings) return pyBrowser -IF CEF_VERSION == 3: - # Unused function warning in CEF 1. - cdef void RemovePyBrowser(int browserId) except *: - # Called from LifespanHandler_OnBeforeClose(). - # TODO: call this function also in CEF 1. - global g_pyBrowsers - if browserId in g_pyBrowsers: - if len(g_pyBrowsers) == 1: - # This is the last browser remaining. - if g_sharedRequestContext.get(): - # A similar release is done in Shutdown and CloseBrowser. - Debug("RemovePyBrowser: releasing shared request context") - g_sharedRequestContext.Assign(NULL) - Debug("del g_pyBrowsers[%s]" % browserId) - del g_pyBrowsers[browserId] - else: - Debug("RemovePyBrowser() FAILED: browser not found, id = %s" \ - % browserId) +cdef void RemovePyBrowser(int browserId) except *: + # Called from LifespanHandler_OnBeforeClose(). + global g_pyBrowsers + if browserId in g_pyBrowsers: + if len(g_pyBrowsers) == 1: + # This is the last browser remaining. + if g_sharedRequestContext.get(): + # A similar release is done in Shutdown and CloseBrowser. + Debug("RemovePyBrowser: releasing shared request context") + g_sharedRequestContext.Assign(NULL) + Debug("del g_pyBrowsers[%s]" % browserId) + del g_pyBrowsers[browserId] + else: + Debug("RemovePyBrowser() FAILED: browser not found, id = %s" \ + % browserId) cpdef PyBrowser GetBrowserByWindowHandle(WindowHandle windowHandle): cdef PyBrowser pyBrowser @@ -150,16 +135,14 @@ cdef class PyBrowser: raise Exception("PyBrowser.GetCefBrowser() failed: CefBrowser " "was destroyed") - IF CEF_VERSION == 3: - - cdef CefRefPtr[CefBrowserHost] GetCefBrowserHost(self) except *: - cdef CefRefPtr[CefBrowserHost] cefBrowserHost = ( - self.GetCefBrowser().get().GetHost()) - if cefBrowserHost != NULL and cefBrowserHost.get(): - return cefBrowserHost - raise Exception("PyBrowser.GetCefBrowserHost() failed: this " - "method can only be called in the browser " - "process.") + cdef CefRefPtr[CefBrowserHost] GetCefBrowserHost(self) except *: + cdef CefRefPtr[CefBrowserHost] cefBrowserHost = ( + self.GetCefBrowser().get().GetHost()) + if cefBrowserHost != NULL and cefBrowserHost.get(): + return cefBrowserHost + raise Exception("PyBrowser.GetCefBrowserHost() failed: this " + "method can only be called in the browser " + "process.") def __init__(self): self.clientCallbacks = {} @@ -171,56 +154,6 @@ cdef class PyBrowser: free(self.imageBuffer) cpdef py_void SetClientCallback(self, py_string name, object callback): - IF CEF_VERSION == 1: - self.SetClientCallback_CEF1(name, callback) - ELIF CEF_VERSION == 3: - self.SetClientCallback_CEF3(name, callback) - - # ------------------------------------------------------------------------- - # CEF 1 - # ------------------------------------------------------------------------- - cpdef py_void SetClientCallback_CEF1(self, - py_string name, object callback): - if not self.allowedClientCallbacks: - # CefLoadHandler. - self.allowedClientCallbacks += ["OnLoadEnd", "OnLoadError", - "OnLoadStart"] - # CefKeyboardHandler. - self.allowedClientCallbacks += ["OnKeyEvent"] - # CefV8ContextHandler. - self.allowedClientCallbacks += ["OnContextCreated", - "OnContextReleased" ,"OnUncaughtException"] - # CefRequestHandler. - self.allowedClientCallbacks += ["OnBeforeBrowse", - "OnBeforeResourceLoad", "OnResourceRedirect", - "OnResourceResponse", "OnProtocolExecution", - "GetDownloadHandler", "GetAuthCredentials", - "GetCookieManager"] - - # CefDisplayHandler. - self.allowedClientCallbacks += ["OnAddressChange", - "OnConsoleMessage", "OnContentsSizeChange", - "OnNavStateChange", "OnStatusMessage", "OnTitleChange", - "OnTooltip"] - # LifespanHandler. - self.allowedClientCallbacks += ["DoClose", "OnAfterCreated", - "OnBeforeClose", "RunModal"] - # RenderHandler - self.allowedClientCallbacks += ["GetViewRect", "GetScreenRect", - "GetScreenPoint", "OnPopupShow", "OnPopupSize", - "OnPaint", "OnCursorChange"] - # DragHandler - self.allowedClientCallbacks += ["OnDragStart", "OnDragEnter"] - if name not in self.allowedClientCallbacks: - raise Exception("Browser.SetClientCallback() failed: unknown " - "callback: %s" % name) - self.clientCallbacks[name] = callback - - # ------------------------------------------------------------------------- - # CEF 3 - # ------------------------------------------------------------------------- - cpdef py_void SetClientCallback_CEF3(self, - py_string name, object callback): if not self.allowedClientCallbacks: # DisplayHandler self.allowedClientCallbacks += [ @@ -291,13 +224,7 @@ cdef class PyBrowser: cpdef py_void SetJavascriptBindings(self, JavascriptBindings bindings): self.javascriptBindings = bindings - IF CEF_VERSION == 1: - if self.GetUserData("__v8ContextCreated"): - Debug("Browser.SetJavascriptBindings(): v8 context already" - "created, calling Rebind()") - self.javascriptBindings.Rebind() - ELIF CEF_VERSION == 3: - self.javascriptBindings.Rebind() + self.javascriptBindings.Rebind() cpdef JavascriptBindings GetJavascriptBindings(self): return self.javascriptBindings @@ -313,34 +240,22 @@ cdef class PyBrowser: return self.GetCefBrowser().get().CanGoForward() cpdef py_void ParentWindowWillClose(self): - IF CEF_VERSION == 1: - self.GetCefBrowser().get().ParentWindowWillClose() - ELIF CEF_VERSION == 3: - self.GetCefBrowserHost().get().ParentWindowWillClose() + self.GetCefBrowserHost().get().ParentWindowWillClose() cpdef py_void CloseBrowser(self, py_bool forceClose=False): - IF CEF_VERSION == 1: - Debug("CefBrowser::CloseBrowser(%s)" % forceClose) - self.GetCefBrowser().get().CloseBrowser(bool(forceClose)) - ELIF CEF_VERSION == 3: - # ParentWindowWillClose() should be called by user when - # implementing LifespanHandler::DoClose(). - # | Debug("CefBrowser::ParentWindowWillClose()") - # | self.GetCefBrowserHost().get().ParentWindowWillClose() - if len(g_pyBrowsers) == 1: - # This is the last browser remaining. - if g_sharedRequestContext.get(): - # A similar release is done in Shutdown - # and RemovePyBrowser. - Debug("CloseBrowser: releasing shared request context") - g_sharedRequestContext.Assign(NULL) - Debug("CefBrowser::CloseBrowser(%s)" % forceClose) - self.GetCefBrowserHost().get().CloseBrowser(bool(forceClose)) - - IF CEF_VERSION == 1: - - cpdef py_void CloseDevTools(self): - self.GetCefBrowser().get().CloseDevTools() + # ParentWindowWillClose() should be called by user when + # implementing LifespanHandler::DoClose(). + # | Debug("CefBrowser::ParentWindowWillClose()") + # | self.GetCefBrowserHost().get().ParentWindowWillClose() + if len(g_pyBrowsers) == 1: + # This is the last browser remaining. + if g_sharedRequestContext.get(): + # A similar release is done in Shutdown + # and RemovePyBrowser. + Debug("CloseBrowser: releasing shared request context") + g_sharedRequestContext.Assign(NULL) + Debug("CefBrowser::CloseBrowser(%s)" % forceClose) + self.GetCefBrowserHost().get().CloseBrowser(bool(forceClose)) def ExecuteFunction(self, *args): self.GetMainFrame().ExecuteFunction(*args) @@ -354,12 +269,8 @@ cdef class PyBrowser: py_bool findNext): cdef CefString cefSearchText PyToCefString(searchText, cefSearchText) - IF CEF_VERSION == 3: - self.GetCefBrowserHost().get().Find(searchId, cefSearchText, - bool(forward), bool(matchCase), bool(findNext)) - ELIF CEF_VERSION == 1: - self.GetCefBrowser().get().Find(searchId, cefSearchText, - bool(forward), bool(matchCase), bool(findNext)) + self.GetCefBrowserHost().get().Find(searchId, cefSearchText, + bool(forward), bool(matchCase), bool(findNext)) cpdef PyFrame GetFocusedFrame(self): assert IsThread(TID_UI), ( @@ -373,10 +284,9 @@ cdef class PyBrowser: PyToCefString(name, cefName) return GetPyFrame(self.GetCefBrowser().get().GetFrame(cefName)) - IF CEF_VERSION == 3: - cpdef object GetFrameByIdentifier(self, object identifier): - return GetPyFrame(self.GetCefBrowser().get().GetFrame( - long(identifier))) + cpdef object GetFrameByIdentifier(self, object identifier): + return GetPyFrame(self.GetCefBrowser().get().GetFrame( + long(identifier))) cpdef list GetFrameNames(self): assert IsThread(TID_UI), ( @@ -409,10 +319,8 @@ cdef class PyBrowser: cpdef WindowHandle GetOpenerWindowHandle(self) except *: cdef WindowHandle hwnd - IF CEF_VERSION == 1: - hwnd = self.GetCefBrowser().get().GetOpenerWindowHandle() - ELIF CEF_VERSION == 3: - hwnd = self.GetCefBrowserHost().get().GetOpenerWindowHandle() + hwnd = \ + self.GetCefBrowserHost().get().GetOpenerWindowHandle() return hwnd cpdef WindowHandle GetOuterWindowHandle(self) except *: @@ -431,21 +339,12 @@ cdef class PyBrowser: cpdef WindowHandle GetWindowHandle(self) except *: cdef WindowHandle hwnd - IF CEF_VERSION == 1: - hwnd = self.GetCefBrowser().get().GetWindowHandle() - ELIF CEF_VERSION == 3: - hwnd = self.GetCefBrowserHost().get().GetWindowHandle() + hwnd = self.GetCefBrowserHost().get().GetWindowHandle() return hwnd cpdef double GetZoomLevel(self) except *: - IF CEF_VERSION == 1: - assert IsThread(TID_UI), ( - "Browser.GetZoomLevel() may only be called on UI thread") cdef double zoomLevel - IF CEF_VERSION == 1: - zoomLevel = self.GetCefBrowser().get().GetZoomLevel() - ELIF CEF_VERSION == 3: - zoomLevel = self.GetCefBrowserHost().get().GetZoomLevel() + zoomLevel = self.GetCefBrowserHost().get().GetZoomLevel() return zoomLevel cpdef py_void GoBack(self): @@ -457,27 +356,14 @@ cdef class PyBrowser: cpdef py_bool HasDocument(self): return self.GetCefBrowser().get().HasDocument() - IF CEF_VERSION == 1: - cpdef py_void HidePopup(self): - self.GetCefBrowser().get().HidePopup() - cpdef py_bool IsFullscreen(self): return bool(self.isFullscreen) cpdef py_bool IsPopup(self): return self.GetCefBrowser().get().IsPopup() - IF CEF_VERSION == 1: - cpdef py_bool IsPopupVisible(self): - assert IsThread(TID_UI), ( - "Browser.IsPopupVisible() may only be called on UI thread") - return self.GetCefBrowser().get().IsPopupVisible() - cpdef py_bool IsWindowRenderingDisabled(self): - IF CEF_VERSION == 1: - return self.GetCefBrowser().get().IsWindowRenderingDisabled() - ELIF CEF_VERSION == 3: - return self.GetCefBrowserHost().get().IsWindowRenderingDisabled() + return self.GetCefBrowserHost().get().IsWindowRenderingDisabled() cpdef py_string LoadUrl(self, py_string url): self.GetMainFrame().LoadUrl(url) @@ -485,9 +371,8 @@ cdef class PyBrowser: cpdef py_void Navigate(self, py_string url): self.LoadUrl(url) - IF CEF_VERSION == 3: - cpdef py_void Print(self): - self.GetCefBrowserHost().get().Print() + cpdef py_void Print(self): + self.GetCefBrowserHost().get().Print() cpdef py_void Reload(self): self.GetCefBrowser().get().Reload() @@ -496,19 +381,13 @@ cdef class PyBrowser: self.GetCefBrowser().get().ReloadIgnoreCache() cpdef py_void SetFocus(self, enable): - IF CEF_VERSION == 1: - self.GetCefBrowser().get().SetFocus(bool(enable)) - ELIF CEF_VERSION == 3: - self.GetCefBrowserHost().get().SetFocus(bool(enable)) + self.GetCefBrowserHost().get().SetFocus(bool(enable)) cpdef py_void SetUserData(self, object key, object value): self.userData[key] = value cpdef py_void SetZoomLevel(self, double zoomLevel): - IF CEF_VERSION == 1: - self.GetCefBrowser().get().SetZoomLevel(zoomLevel) - ELIF CEF_VERSION == 3: - self.GetCefBrowserHost().get().SetZoomLevel(zoomLevel) + self.GetCefBrowserHost().get().SetZoomLevel(zoomLevel) cpdef py_void ShowDevTools(self): cdef CefString cefUrl = self.GetCefBrowserHost().get().GetDevToolsURL(\ @@ -527,10 +406,7 @@ cdef class PyBrowser: self.GetCefBrowser().get().StopLoad() cpdef py_void StopFinding(self, py_bool clearSelection): - IF CEF_VERSION == 3: - self.GetCefBrowserHost().get().StopFinding(bool(clearSelection)) - ELIF CEF_VERSION == 1: - self.GetCefBrowser().get().StopFinding(bool(clearSelection)) + self.GetCefBrowserHost().get().StopFinding(bool(clearSelection)) cpdef py_void ToggleFullscreen(self): IF UNAME_SYSNAME == "Windows": @@ -613,206 +489,101 @@ cdef class PyBrowser: self.isFullscreen = int(not bool(self.isFullscreen)) - # Off-screen rendering. - - IF CEF_VERSION == 1: - - cpdef tuple GetSize(self, PaintElementType paintElementType): - assert IsThread(TID_UI), ( - "Browser.GetSize(): this method should only be called " - "on the UI thread") - cdef int width = 0 - cdef int height = 0 - cdef cpp_bool ret = self.GetCefBrowser().get().GetSize( - paintElementType, width, height) - if ret: - return (width, height) - else: - return (0, 0) - - cpdef py_void SetSize(self, PaintElementType paintElementType, - int width, int height): - self.GetCefBrowser().get().SetSize(paintElementType, width, height) - - cpdef py_void Invalidate(self, list dirtyRect): - assert len(dirtyRect) == 4, ( - "Browser.Invalidate() failed, dirtyRect is invalid") - cdef CefRect cefRect = CefRect( - dirtyRect[0], dirtyRect[1], dirtyRect[2], dirtyRect[3]) - self.GetCefBrowser().get().Invalidate(cefRect) - - IF CEF_VERSION == 1 and UNAME_SYSNAME == "Windows": - cpdef PaintBuffer GetImage(self, PaintElementType paintElementType, - int width, int height): - assert IsThread(TID_UI), ( - "Browser.GetImage(): this method should only be called " - "on the UI thread") - - IF UNAME_SYSNAME == "Windows": - return self.GetImage_Windows(paintElementType, width, height) - ELSE: - return None - - cdef PaintBuffer GetImage_Windows(self, - PaintElementType paintElementType, int width, int height): - if not self.imageBuffer: - self.imageBuffer = malloc(width*height*4) - cdef cpp_bool ret = self.GetCefBrowser().get().GetImage( - paintElementType, width, height, self.imageBuffer) - cdef PaintBuffer paintBuffer - if ret: - paintBuffer = CreatePaintBuffer( - self.imageBuffer, width, height) - return paintBuffer - else: - return None - - # Sending mouse/key events. - IF CEF_VERSION == 1: - cpdef py_void SendKeyEvent(self, cef_types.cef_key_type_t keyType, - tuple keyInfo, int modifiers): - cdef CefKeyInfo cefKeyInfo - IF UNAME_SYSNAME == "Windows": - assert len(keyInfo) == 3, "Invalid keyInfo param" - cefKeyInfo.key = keyInfo[0] - cefKeyInfo.sysChar = keyInfo[1] - cefKeyInfo.imeChar = keyInfo[2] - ELIF UNAME_SYSNAME == "Darwin": - cefKeyInfo.keyCode = keyInfo[0] - cefKeyInfo.character = keyInfo[1] - cefKeyInfo.characterNoModifiers = keyInfo[2] - ELIF UNAME_SYSNAME == "Linux": - cefKeyInfo.key = keyInfo[0] - ELSE: - raise Exception("Invalid UNAME_SYSNAME") - - self.GetCefBrowser().get().SendKeyEvent(keyType, cefKeyInfo, - modifiers) - - cpdef py_void SendMouseClickEvent(self, int x, int y, - cef_types.cef_mouse_button_type_t mouseButtonType, - py_bool mouseUp, int clickCount, int modifiers=0): - self.GetCefBrowser().get().SendMouseClickEvent(x, y, - mouseButtonType, bool(mouseUp), clickCount) - - cpdef py_void SendMouseMoveEvent(self, int x, int y, - py_bool mouseLeave, int modifiers=0): - self.GetCefBrowser().get().SendMouseMoveEvent(x, y, - bool(mouseLeave)) - - cpdef py_void SendMouseWheelEvent(self, int x, int y, - int deltaX, int deltaY, int modifiers=0): - self.GetCefBrowser().get().SendMouseWheelEvent(x, y, - deltaX, deltaY) - - cpdef py_void SendFocusEvent(self, py_bool setFocus): - self.GetCefBrowser().get().SendFocusEvent(bool(setFocus)) - - cpdef py_void SendCaptureLostEvent(self): - self.GetCefBrowser().get().SendCaptureLostEvent() - - ELIF CEF_VERSION == 3: - cpdef py_void SendKeyEvent(self, dict pyEvent): - cdef CefKeyEvent cefEvent - if "type" in pyEvent: - cefEvent.type = int(pyEvent["type"]) - if "modifiers" in pyEvent: - cefEvent.modifiers = long(pyEvent["modifiers"]) - if ("windows_key_code" in pyEvent) and UNAME_SYSNAME == "Windows": - cefEvent.windows_key_code = int(pyEvent["windows_key_code"]) - if "native_key_code" in pyEvent: - cefEvent.native_key_code = int(pyEvent["native_key_code"]) - if "is_system_key" in pyEvent: - cefEvent.is_system_key = bool(pyEvent["is_system_key"]) - if "character" in pyEvent: - cefEvent.character = int(pyEvent["character"]) - if "unmodified_character" in pyEvent: - cefEvent.unmodified_character = \ - int(pyEvent["unmodified_character"]) - if "focus_on_editable_field" in pyEvent: - cefEvent.focus_on_editable_field = \ - bool(pyEvent["focus_on_editable_field"]) - self.GetCefBrowserHost().get().SendKeyEvent(cefEvent) - - cpdef py_void SendMouseClickEvent(self, int x, int y, - cef_types.cef_mouse_button_type_t mouseButtonType, - py_bool mouseUp, int clickCount, int modifiers=0): - cdef CefMouseEvent mouseEvent - mouseEvent.x = x - mouseEvent.y = y - mouseEvent.modifiers = modifiers - self.GetCefBrowserHost().get().SendMouseClickEvent(mouseEvent, - mouseButtonType, bool(mouseUp), clickCount) - - cpdef py_void SendMouseMoveEvent(self, int x, int y, - py_bool mouseLeave, int modifiers=0): - cdef CefMouseEvent mouseEvent - mouseEvent.x = x - mouseEvent.y = y - mouseEvent.modifiers = modifiers - self.GetCefBrowserHost().get().SendMouseMoveEvent(mouseEvent, - bool(mouseLeave)) - - cpdef py_void SendMouseWheelEvent(self, int x, int y, - int deltaX, int deltaY, int modifiers=0): - cdef CefMouseEvent mouseEvent - mouseEvent.x = x - mouseEvent.y = y - mouseEvent.modifiers = modifiers - self.GetCefBrowserHost().get().SendMouseWheelEvent(mouseEvent, - deltaX, deltaY) - - cpdef py_void SendFocusEvent(self, py_bool setFocus): - self.GetCefBrowserHost().get().SendFocusEvent(bool(setFocus)) - - cpdef py_void SendCaptureLostEvent(self): - self.GetCefBrowserHost().get().SendCaptureLostEvent() - # ENDIF CEF_VERSION == 3 / Sending mouse/key events. - - IF CEF_VERSION == 3: - cpdef py_void StartDownload(self, py_string url): - self.GetCefBrowserHost().get().StartDownload(PyToCefStringValue( - url)) - - cpdef py_void SetMouseCursorChangeDisabled(self, py_bool disabled): - self.GetCefBrowserHost().get().SetMouseCursorChangeDisabled( - bool(disabled)) - - cpdef py_bool IsMouseCursorChangeDisabled(self): - return self.GetCefBrowserHost().get().IsMouseCursorChangeDisabled() - - cpdef py_void WasResized(self): - self.GetCefBrowserHost().get().WasResized() - - cpdef py_void WasHidden(self, py_bool hidden): - self.GetCefBrowserHost().get().WasHidden(bool(hidden)) - - cpdef py_void NotifyScreenInfoChanged(self): - self.GetCefBrowserHost().get().NotifyScreenInfoChanged() - - # virtual CefTextInputContext GetNSTextInputContext() =0; - # virtual void HandleKeyEventBeforeTextInputClient(CefEventHandle keyEvent) =0; - # virtual void HandleKeyEventAfterTextInputClient(CefEventHandle keyEvent) =0; - - cdef void SendProcessMessage(self, cef_process_id_t targetProcess, - object frameId, py_string messageName, list pyArguments - ) except *: - cdef CefRefPtr[CefProcessMessage] message = \ - CefProcessMessage_Create(PyToCefStringValue(messageName)) - # This does not work, no idea why, the CEF implementation - # seems not to allow it, both Assign() and swap() do not work: - # | message.get().GetArgumentList().Assign(arguments.get()) - # | message.get().GetArgumentList().swap(arguments) - cdef CefRefPtr[CefListValue] messageArguments = \ - message.get().GetArgumentList() - PyListToExistingCefListValue(self.GetIdentifier(), frameId, - pyArguments, messageArguments) - Debug("SendProcessMessage(): message=%s, arguments size=%d" % ( - messageName, - message.get().GetArgumentList().get().GetSize())) - cdef cpp_bool success = \ - self.GetCefBrowser().get().SendProcessMessage( - targetProcess, message) - if not success: - raise Exception("Browser.SendProcessMessage() failed: "\ - "messageName=%s" % messageName) + cpdef py_void SendKeyEvent(self, dict pyEvent): + cdef CefKeyEvent cefEvent + if "type" in pyEvent: + cefEvent.type = int(pyEvent["type"]) + if "modifiers" in pyEvent: + cefEvent.modifiers = long(pyEvent["modifiers"]) + if ("windows_key_code" in pyEvent) and UNAME_SYSNAME == "Windows": + cefEvent.windows_key_code = int(pyEvent["windows_key_code"]) + if "native_key_code" in pyEvent: + cefEvent.native_key_code = int(pyEvent["native_key_code"]) + if "is_system_key" in pyEvent: + cefEvent.is_system_key = bool(pyEvent["is_system_key"]) + if "character" in pyEvent: + cefEvent.character = int(pyEvent["character"]) + if "unmodified_character" in pyEvent: + cefEvent.unmodified_character = \ + int(pyEvent["unmodified_character"]) + if "focus_on_editable_field" in pyEvent: + cefEvent.focus_on_editable_field = \ + bool(pyEvent["focus_on_editable_field"]) + self.GetCefBrowserHost().get().SendKeyEvent(cefEvent) + + cpdef py_void SendMouseClickEvent(self, int x, int y, + cef_types.cef_mouse_button_type_t mouseButtonType, + py_bool mouseUp, int clickCount, int modifiers=0): + cdef CefMouseEvent mouseEvent + mouseEvent.x = x + mouseEvent.y = y + mouseEvent.modifiers = modifiers + self.GetCefBrowserHost().get().SendMouseClickEvent(mouseEvent, + mouseButtonType, bool(mouseUp), clickCount) + + cpdef py_void SendMouseMoveEvent(self, int x, int y, + py_bool mouseLeave, int modifiers=0): + cdef CefMouseEvent mouseEvent + mouseEvent.x = x + mouseEvent.y = y + mouseEvent.modifiers = modifiers + self.GetCefBrowserHost().get().SendMouseMoveEvent(mouseEvent, + bool(mouseLeave)) + + cpdef py_void SendMouseWheelEvent(self, int x, int y, + int deltaX, int deltaY, int modifiers=0): + cdef CefMouseEvent mouseEvent + mouseEvent.x = x + mouseEvent.y = y + mouseEvent.modifiers = modifiers + self.GetCefBrowserHost().get().SendMouseWheelEvent(mouseEvent, + deltaX, deltaY) + + cpdef py_void SendFocusEvent(self, py_bool setFocus): + self.GetCefBrowserHost().get().SendFocusEvent(bool(setFocus)) + + cpdef py_void SendCaptureLostEvent(self): + self.GetCefBrowserHost().get().SendCaptureLostEvent() + + cpdef py_void StartDownload(self, py_string url): + self.GetCefBrowserHost().get().StartDownload(PyToCefStringValue( + url)) + + cpdef py_void SetMouseCursorChangeDisabled(self, py_bool disabled): + self.GetCefBrowserHost().get().SetMouseCursorChangeDisabled( + bool(disabled)) + + cpdef py_bool IsMouseCursorChangeDisabled(self): + return self.GetCefBrowserHost().get().IsMouseCursorChangeDisabled() + + cpdef py_void WasResized(self): + self.GetCefBrowserHost().get().WasResized() + + cpdef py_void WasHidden(self, py_bool hidden): + self.GetCefBrowserHost().get().WasHidden(bool(hidden)) + + cpdef py_void NotifyScreenInfoChanged(self): + self.GetCefBrowserHost().get().NotifyScreenInfoChanged() + + cdef void SendProcessMessage(self, cef_process_id_t targetProcess, + object frameId, py_string messageName, list pyArguments + ) except *: + cdef CefRefPtr[CefProcessMessage] message = \ + CefProcessMessage_Create(PyToCefStringValue(messageName)) + # This does not work, no idea why, the CEF implementation + # seems not to allow it, both Assign() and swap() do not work: + # | message.get().GetArgumentList().Assign(arguments.get()) + # | message.get().GetArgumentList().swap(arguments) + cdef CefRefPtr[CefListValue] messageArguments = \ + message.get().GetArgumentList() + PyListToExistingCefListValue(self.GetIdentifier(), frameId, + pyArguments, messageArguments) + Debug("SendProcessMessage(): message=%s, arguments size=%d" % ( + messageName, + message.get().GetArgumentList().get().GetSize())) + cdef cpp_bool success = \ + self.GetCefBrowser().get().SendProcessMessage( + targetProcess, message) + if not success: + raise Exception("Browser.SendProcessMessage() failed: "\ + "messageName=%s" % messageName) diff --git a/cefpython/cefpython.pyx b/cefpython/cefpython.pyx index 123313098..75c923944 100644 --- a/cefpython/cefpython.pyx +++ b/cefpython/cefpython.pyx @@ -137,15 +137,10 @@ include "browser.pyx" include "frame.pyx" include "settings.pyx" -IF UNAME_SYSNAME == "Windows" and CEF_VERSION == 1: - # Off-screen rendering currently supported only on Windows - include "paint_buffer_cef1.pyx" IF UNAME_SYSNAME == "Windows": include "window_utils_win.pyx" include "dpi_aware_win.pyx" - IF CEF_VERSION == 1: - include "http_authentication_win.pyx" ELIF UNAME_SYSNAME == "Linux": include "window_utils_linux.pyx" ELIF UNAME_SYSNAME == "Darwin": @@ -302,29 +297,27 @@ def Initialize(applicationSettings=None, commandLineSwitches=None): # CEF options - default values. if not "multi_threaded_message_loop" in applicationSettings: applicationSettings["multi_threaded_message_loop"] = False - IF CEF_VERSION == 3: - if not "single_process" in applicationSettings: - applicationSettings["single_process"] = False + if not "single_process" in applicationSettings: + applicationSettings["single_process"] = False cdef CefRefPtr[CefApp] cefApp - IF CEF_VERSION == 3: - cefApp = new CefPythonApp() - IF UNAME_SYSNAME == "Windows": - cdef HINSTANCE hInstance = GetModuleHandle(NULL) - cdef CefMainArgs cefMainArgs = CefMainArgs(hInstance) - ELIF UNAME_SYSNAME == "Linux": - # TODO: use the CefMainArgs(int argc, char** argv) constructor. - cdef CefMainArgs cefMainArgs - ELIF UNAME_SYSNAME == "Darwin": - # TODO: use the CefMainArgs(int argc, char** argv) constructor. - cdef CefMainArgs cefMainArgs - cdef int exitCode = 1 - with nogil: - exitCode = CefExecuteProcess(cefMainArgs, cefApp) - Debug("CefExecuteProcess(): exitCode = %s" % exitCode) - if exitCode >= 0: - sys.exit(exitCode) + cefApp = new CefPythonApp() + IF UNAME_SYSNAME == "Windows": + cdef HINSTANCE hInstance = GetModuleHandle(NULL) + cdef CefMainArgs cefMainArgs = CefMainArgs(hInstance) + ELIF UNAME_SYSNAME == "Linux": + # TODO: use the CefMainArgs(int argc, char** argv) constructor. + cdef CefMainArgs cefMainArgs + ELIF UNAME_SYSNAME == "Darwin": + # TODO: use the CefMainArgs(int argc, char** argv) constructor. + cdef CefMainArgs cefMainArgs + cdef int exitCode = 1 + with nogil: + exitCode = CefExecuteProcess(cefMainArgs, cefApp) + Debug("CefExecuteProcess(): exitCode = %s" % exitCode) + if exitCode >= 0: + sys.exit(exitCode) # Make a copy as applicationSettings is a reference only # that might get destroyed later. @@ -345,12 +338,8 @@ def Initialize(applicationSettings=None, commandLineSwitches=None): Debug("CefInitialize()") cdef cpp_bool ret - IF CEF_VERSION == 1: - with nogil: - ret = CefInitialize(cefApplicationSettings, cefApp) - ELIF CEF_VERSION == 3: - with nogil: - ret = CefInitialize(cefMainArgs, cefApplicationSettings, cefApp) + with nogil: + ret = CefInitialize(cefMainArgs, cefApplicationSettings, cefApp) if not ret: Debug("CefInitialize() failed") @@ -421,13 +410,6 @@ def CreateBrowserSync(windowInfo, browserSettings, navigateUrl, requestContext=N cdef PyBrowser pyBrowser = GetPyBrowser(cefBrowser) pyBrowser.SetUserData("__outerWindowHandle", int(windowInfo.parentWindowHandle)) - # IF CEF_VERSION == 3: - # Test whether process message sent before renderer thread is created - # will be delivered - OK. - # Debug("Sending 'CreateBrowserSync() done' message to the Renderer") - # pyBrowser.SendProcessMessage(cef_types.PID_RENDERER, - # "CreateBrowserSync() done") - return pyBrowser def MessageLoop(): diff --git a/cefpython/cython_includes/cef_app.pxd b/cefpython/cython_includes/cef_app.pxd index 9b4de4df7..887e1f2ba 100644 --- a/cefpython/cython_includes/cef_app.pxd +++ b/cefpython/cython_includes/cef_app.pxd @@ -12,32 +12,24 @@ from cef_ptr cimport CefRefPtr from cef_base cimport CefBase from libcpp cimport bool as cpp_bool -IF CEF_VERSION == 3: - IF UNAME_SYSNAME == "Windows": - from cef_win cimport CefMainArgs - ELIF UNAME_SYSNAME == "Linux": - from cef_linux cimport CefMainArgs - ELIF UNAME_SYSNAME == "Darwin": - from cef_mac cimport CefMainArgs +IF UNAME_SYSNAME == "Windows": + from cef_win cimport CefMainArgs +ELIF UNAME_SYSNAME == "Linux": + from cef_linux cimport CefMainArgs +ELIF UNAME_SYSNAME == "Darwin": + from cef_mac cimport CefMainArgs cdef extern from "include/cef_app.h": cdef cppclass CefApp(CefBase): pass - IF CEF_VERSION == 3: - cdef int CefExecuteProcess(CefMainArgs& args, CefRefPtr[CefApp] application) nogil + cdef int CefExecuteProcess(CefMainArgs& args, CefRefPtr[CefApp] application) nogil - IF CEF_VERSION == 1: - cdef cpp_bool CefInitialize(CefSettings&, CefRefPtr[CefApp]) nogil - ELIF CEF_VERSION == 3: - cdef cpp_bool CefInitialize(CefMainArgs&, CefSettings&, CefRefPtr[CefApp]) nogil + cdef cpp_bool CefInitialize(CefMainArgs&, CefSettings&, CefRefPtr[CefApp]) nogil cdef void CefRunMessageLoop() nogil cdef void CefDoMessageLoopWork() nogil cdef void CefQuitMessageLoop() nogil cdef void CefShutdown() nogil - - IF CEF_VERSION == 3: - cdef void CefSetOSModalLoop(cpp_bool osModalLoop) nogil - + cdef void CefSetOSModalLoop(cpp_bool osModalLoop) nogil diff --git a/cefpython/cython_includes/cef_browser_static.pxd b/cefpython/cython_includes/cef_browser_static.pxd index 40d300d5b..e68d822ef 100644 --- a/cefpython/cython_includes/cef_browser_static.pxd +++ b/cefpython/cython_includes/cef_browser_static.pxd @@ -18,25 +18,12 @@ from cef_browser cimport CefBrowser from libcpp cimport bool as cpp_bool from cef_string cimport CefString -IF CEF_VERSION == 1: - - # Specifying namespace allows to import a static method. - cdef extern from "include/cef_browser.h" namespace "CefBrowser": - - cdef CefRefPtr[CefBrowser] CreateBrowserSync( - CefWindowInfo&, - CefRefPtr[CefClient], - CefString&, - CefBrowserSettings&) nogil - -ELIF CEF_VERSION == 3: - - # Specifying namespace allows to import a static method. - cdef extern from "include/cef_browser.h" namespace "CefBrowserHost": - - cdef CefRefPtr[CefBrowser] CreateBrowserSync( - CefWindowInfo&, - CefRefPtr[CefClient], - CefString&, - CefBrowserSettings&, - CefRefPtr[CefRequestContext]) nogil +# Specifying namespace allows to import a static method. +cdef extern from "include/cef_browser.h" namespace "CefBrowserHost": + + cdef CefRefPtr[CefBrowser] CreateBrowserSync( + CefWindowInfo&, + CefRefPtr[CefClient], + CefString&, + CefBrowserSettings&, + CefRefPtr[CefRequestContext]) nogil diff --git a/cefpython/cython_includes/cef_linux.pxd b/cefpython/cython_includes/cef_linux.pxd index c2f93d33a..33b4e7a8a 100644 --- a/cefpython/cython_includes/cef_linux.pxd +++ b/cefpython/cython_includes/cef_linux.pxd @@ -19,8 +19,7 @@ cdef extern from "include/internal/cef_linux.h": void SetTransparentPainting(cpp_bool) void SetAsOffScreen(CefWindowHandle) - IF CEF_VERSION == 3: - cdef cppclass CefMainArgs(CefStructBase): - CefMainArgs() - CefMainArgs(int argc_arg, char** argv_arg) + cdef cppclass CefMainArgs(CefStructBase): + CefMainArgs() + CefMainArgs(int argc_arg, char** argv_arg) diff --git a/cefpython/cython_includes/cef_mac.pxd b/cefpython/cython_includes/cef_mac.pxd index 67343b3a7..bab3b3846 100644 --- a/cefpython/cython_includes/cef_mac.pxd +++ b/cefpython/cython_includes/cef_mac.pxd @@ -19,7 +19,6 @@ cdef extern from "include/internal/cef_linux.h": void SetTransparentPainting(cpp_bool) void SetAsOffScreen(CefWindowHandle) - IF CEF_VERSION == 3: - cdef cppclass CefMainArgs(CefStructBase): - CefMainArgs() - CefMainArgs(int argc_arg, char** argv_arg) + cdef cppclass CefMainArgs(CefStructBase): + CefMainArgs() + CefMainArgs(int argc_arg, char** argv_arg) diff --git a/cefpython/cython_includes/cef_types_wrappers.pxd b/cefpython/cython_includes/cef_types_wrappers.pxd index 4e469835c..e1c816dc9 100644 --- a/cefpython/cython_includes/cef_types_wrappers.pxd +++ b/cefpython/cython_includes/cef_types_wrappers.pxd @@ -6,9 +6,8 @@ include "compile_time_constants.pxi" from libcpp cimport bool as cpp_bool from cef_string cimport cef_string_t -IF CEF_VERSION == 3: - from cef_types cimport cef_state_t - from cef_types cimport cef_color_t +from cef_types cimport cef_state_t +from cef_types cimport cef_color_t cdef extern from "include/internal/cef_types_wrappers.h": diff --git a/cefpython/cython_includes/cef_win.pxd b/cefpython/cython_includes/cef_win.pxd index 1999e937d..1581104bb 100644 --- a/cefpython/cython_includes/cef_win.pxd +++ b/cefpython/cython_includes/cef_win.pxd @@ -20,9 +20,8 @@ cdef extern from "include/internal/cef_win.h": void SetTransparentPainting(int) void SetAsOffScreen(HWND) - IF CEF_VERSION == 3: - cdef cppclass CefMainArgs(CefStructBase): - CefMainArgs() - CefMainArgs(HINSTANCE hInstance) + cdef cppclass CefMainArgs(CefStructBase): + CefMainArgs() + CefMainArgs(HINSTANCE hInstance) ctypedef _cef_key_info_t CefKeyInfo diff --git a/cefpython/javascript_bindings.pyx b/cefpython/javascript_bindings.pyx index ea81d8bae..25a448ce9 100644 --- a/cefpython/javascript_bindings.pyx +++ b/cefpython/javascript_bindings.pyx @@ -80,78 +80,36 @@ cdef class JavascriptBindings: else: self.properties[name] = value - - IF CEF_VERSION == 1: - cpdef py_void Rebind(self): - # Rebind may also be used for first-time bindings, in - # a case when v8 process/thread was created too fast, - # see Browser.SetJavascriptBindings() that checks whether - # OnContextCreated() event already happened, if so it will - # call Rebind() to do the javascript bindings. - assert IsThread(TID_UI), ( - "JavascriptBindings.Rebind() may only be called on UI thread") - cdef CefRefPtr[CefBrowser] cefBrowser - cdef CefRefPtr[CefFrame] cefFrame - cdef CefRefPtr[CefV8Context] v8Context - cdef cpp_bool sameContext - cdef PyBrowser pyBrowser - cdef PyFrame pyFrame - cdef list frames - global g_pyBrowsers - for pyBrowser in g_pyBrowsers: - # These javascript bindings may have been binded - # to many browsers. - if pyBrowser.GetJavascriptBindings() != self: - continue - if self.bindToFrames: - frames = pyBrowser.GetFrames() - else: - frames = [pyBrowser.GetMainFrame()] - for frameId in self.frames: - pyBrowser = self.frames[frameId][0] - pyFrame = self.frames[frameId][1] - cefBrowser = pyBrowser.GetCefBrowser() - cefFrame = pyFrame.GetCefFrame() - v8Context = cefFrame.get().GetV8Context() - sameContext = v8Context.get().IsSame(cef_v8_static.GetCurrentContext()) - if not sameContext: - Debug("JavascriptBindings.Rebind(): inside a different context, calling v8Context.Enter()") - assert v8Context.get().Enter(), "v8Context.Enter() failed" - V8ContextHandler_OnContextCreated(cefBrowser, cefFrame, v8Context) - if not sameContext: - assert v8Context.get().Exit(), "v8Context.Exit() failed" - ELIF CEF_VERSION == 3: - cpdef py_void Rebind(self): - # In CEF Python 3 due to its multi-process architecture - # Rebind() is used for both first-time binding and rebinding. - cdef PyBrowser pyBrowser - cdef dict functions - cdef dict properties - cdef dict objects - cdef dict methods - global g_pyBrowsers - for browserId, pyBrowser in g_pyBrowsers.iteritems(): - if pyBrowser.GetJavascriptBindings() != self: - continue - # Send to the Renderer process: functions, properties, - # objects and its methods, bindToFrames. - functions = {} - for funcName in self.functions: - functions[funcName] = None - properties = self.properties - objects = {} - for objectName in self.objects: - methods = {} - for methodName in self.objects[objectName]: - methods[methodName] = None - objects[objectName] = methods - pyBrowser.SendProcessMessage(cef_types.PID_RENDERER, - 0, "DoJavascriptBindings", [{ - "functions": functions, - "properties": properties, - "objects": objects, - "bindToFrames": self.bindToFrames - }]) + cpdef py_void Rebind(self): + # Rebind() is called for both first-time binding and rebinding. + cdef PyBrowser pyBrowser + cdef dict functions + cdef dict properties + cdef dict objects + cdef dict methods + global g_pyBrowsers + for browserId, pyBrowser in g_pyBrowsers.iteritems(): + if pyBrowser.GetJavascriptBindings() != self: + continue + # Send to the Renderer process: functions, properties, + # objects and its methods, bindToFrames. + functions = {} + for funcName in self.functions: + functions[funcName] = None + properties = self.properties + objects = {} + for objectName in self.objects: + methods = {} + for methodName in self.objects[objectName]: + methods[methodName] = None + objects[objectName] = methods + pyBrowser.SendProcessMessage(cef_types.PID_RENDERER, + 0, "DoJavascriptBindings", [{ + "functions": functions, + "properties": properties, + "objects": objects, + "bindToFrames": self.bindToFrames + }]) cpdef dict GetProperties(self): return self.properties diff --git a/cefpython/linux/setup/setup.py b/cefpython/linux/setup/setup.py index 28464e2b2..9617100e2 100644 --- a/cefpython/linux/setup/setup.py +++ b/cefpython/linux/setup/setup.py @@ -15,9 +15,6 @@ # Stop on first error, otherwise hundreds of errors appear in the console. Options.fast_fail = True -# Written to cython_includes/compile_time_constants.pxi -CEF_VERSION = 3 - # Python version string: "27" or "32". PYTHON_VERSION = str(sys.version_info.major) + str(sys.version_info.minor) @@ -28,7 +25,6 @@ def CompileTimeConstants(): fd.write('# This file was generated by setup.py\n') # A way around Python 3.2 bug: UNAME_SYSNAME is not set. fd.write('DEF UNAME_SYSNAME = "%s"\n' % platform.uname()[0]) - fd.write('DEF CEF_VERSION = %s\n' % CEF_VERSION) fd.write('DEF PY_MAJOR_VERSION = %s\n' % sys.version_info.major) CompileTimeConstants() diff --git a/cefpython/mac/setup/setup.py b/cefpython/mac/setup/setup.py index 3ba1eef6f..a8389c739 100644 --- a/cefpython/mac/setup/setup.py +++ b/cefpython/mac/setup/setup.py @@ -23,9 +23,6 @@ # Stop on first error, otherwise hundreds of errors appear in the console. Options.fast_fail = True -# Written to cython_includes/compile_time_constants.pxi -CEF_VERSION = 3 - # Python version string: "27" or "32". PYTHON_VERSION = str(sys.version_info.major) + str(sys.version_info.minor) @@ -36,7 +33,6 @@ def CompileTimeConstants(): fd.write('# This file was generated by setup.py\n') # A way around Python 3.2 bug: UNAME_SYSNAME is not set. fd.write('DEF UNAME_SYSNAME = "%s"\n' % platform.uname()[0]) - fd.write('DEF CEF_VERSION = %s\n' % CEF_VERSION) fd.write('DEF PY_MAJOR_VERSION = %s\n' % sys.version_info.major) CompileTimeConstants() diff --git a/cefpython/settings.pyx b/cefpython/settings.pyx index 577560460..49becf15e 100644 --- a/cefpython/settings.pyx +++ b/cefpython/settings.pyx @@ -103,305 +103,179 @@ cdef void SetBrowserSettings( cdef CefString* cefString for key in browserSettings: - - IF CEF_VERSION == 1: - - if key == "animation_frame_rate": - cefBrowserSettings.animation_frame_rate = int(browserSettings[key]) - elif key == "drag_drop_disabled": - cefBrowserSettings.drag_drop_disabled = bool(browserSettings[key]) - elif key == "load_drops_disabled": - cefBrowserSettings.load_drops_disabled = bool(browserSettings[key]) - elif key == "history_disabled": - cefBrowserSettings.history_disabled = bool(browserSettings[key]) - elif key == "standard_font_family": - cefString = new CefString(&cefBrowserSettings.standard_font_family) - PyToCefStringPointer(browserSettings[key], cefString) - del cefString - elif key == "fixed_font_family": - cefString = new CefString(&cefBrowserSettings.fixed_font_family) - PyToCefStringPointer(browserSettings[key], cefString) - del cefString - elif key == "serif_font_family": - cefString = new CefString(&cefBrowserSettings.serif_font_family) - PyToCefStringPointer(browserSettings[key], cefString) - del cefString - elif key == "sans_serif_font_family": - cefString = new CefString(&cefBrowserSettings.sans_serif_font_family) - PyToCefStringPointer(browserSettings[key], cefString) - del cefString - elif key == "cursive_font_family": - cefString = new CefString(&cefBrowserSettings.cursive_font_family) - PyToCefStringPointer(browserSettings[key], cefString) - del cefString - elif key == "fantasy_font_family": - cefString = new CefString(&cefBrowserSettings.fantasy_font_family) - PyToCefStringPointer(browserSettings[key], cefString) - del cefString - elif key == "default_font_size": - cefBrowserSettings.default_font_size = int(browserSettings[key]) - elif key == "default_fixed_font_size": - cefBrowserSettings.default_fixed_font_size = int(browserSettings[key]) - elif key == "minimum_font_size": - cefBrowserSettings.minimum_font_size = int(browserSettings[key]) - elif key == "minimum_logical_font_size": - cefBrowserSettings.minimum_logical_font_size = int(browserSettings[key]) - elif key == "remote_fonts_disabled": - cefBrowserSettings.remote_fonts_disabled = bool(browserSettings[key]) - elif key == "default_encoding": - cefString = new CefString(&cefBrowserSettings.default_encoding) - PyToCefStringPointer(browserSettings[key], cefString) - del cefString - elif key == "encoding_detector_enabled": - cefBrowserSettings.encoding_detector_enabled = bool(browserSettings[key]) - elif key == "javascript_disabled": - cefBrowserSettings.javascript_disabled = bool(browserSettings[key]) - elif key == "javascript_open_windows_disallowed": - cefBrowserSettings.javascript_open_windows_disallowed = bool(browserSettings[key]) - elif key == "javascript_close_windows_disallowed": - cefBrowserSettings.javascript_close_windows_disallowed = bool(browserSettings[key]) - elif key == "javascript_access_clipboard_disallowed": - cefBrowserSettings.javascript_access_clipboard_disallowed = bool(browserSettings[key]) - elif key == "dom_paste_disabled": - cefBrowserSettings.dom_paste_disabled = bool(browserSettings[key]) - elif key == "caret_browsing_enabled": - cefBrowserSettings.caret_browsing_enabled = bool(browserSettings[key]) - elif key == "java_disabled": - cefBrowserSettings.java_disabled = bool(browserSettings[key]) - elif key == "plugins_disabled": - cefBrowserSettings.plugins_disabled = bool(browserSettings[key]) - elif key == "universal_access_from_file_urls_allowed": - cefBrowserSettings.universal_access_from_file_urls_allowed = bool(browserSettings[key]) - elif key == "file_access_from_file_urls_allowed": - cefBrowserSettings.file_access_from_file_urls_allowed = bool(browserSettings[key]) - elif key == "web_security_disabled": - cefBrowserSettings.web_security_disabled = bool(browserSettings[key]) - elif key == "xss_auditor_enabled": - cefBrowserSettings.xss_auditor_enabled = bool(browserSettings[key]) - elif key == "image_load_disabled": - cefBrowserSettings.image_load_disabled = bool(browserSettings[key]) - elif key == "shrink_standalone_images_to_fit": - cefBrowserSettings.shrink_standalone_images_to_fit = bool(browserSettings[key]) - elif key == "site_specific_quirks_disabled": - cefBrowserSettings.site_specific_quirks_disabled = bool(browserSettings[key]) - elif key == "text_area_resize_disabled": - cefBrowserSettings.text_area_resize_disabled = bool(browserSettings[key]) - elif key == "page_cache_disabled": - cefBrowserSettings.page_cache_disabled = bool(browserSettings[key]) - elif key == "tab_to_links_disabled": - cefBrowserSettings.tab_to_links_disabled = bool(browserSettings[key]) - elif key == "hyperlink_auditing_disabled": - cefBrowserSettings.hyperlink_auditing_disabled = bool(browserSettings[key]) - elif key == "user_style_sheet_enabled": - cefBrowserSettings.user_style_sheet_enabled = bool(browserSettings[key]) - elif key == "user_style_sheet_location": - cefString = new CefString(&cefBrowserSettings.user_style_sheet_location) - PyToCefStringPointer(browserSettings[key], cefString) - del cefString - elif key == "author_and_user_styles_disabled": - cefBrowserSettings.author_and_user_styles_disabled = bool(browserSettings[key]) - elif key == "local_storage_disabled": - cefBrowserSettings.local_storage_disabled = bool(browserSettings[key]) - elif key == "databases_disabled": - cefBrowserSettings.databases_disabled = bool(browserSettings[key]) - elif key == "application_cache_disabled": - cefBrowserSettings.application_cache_disabled = bool(browserSettings[key]) - elif key == "webgl_disabled": - cefBrowserSettings.webgl_disabled = bool(browserSettings[key]) - elif key == "accelerated_compositing_enabled": - cefBrowserSettings.accelerated_compositing_enabled = bool(browserSettings[key]) - elif key == "accelerated_layers_disabled": - cefBrowserSettings.accelerated_layers_disabled = bool(browserSettings[key]) - elif key == "accelerated_video_disabled": - cefBrowserSettings.accelerated_video_disabled = bool(browserSettings[key]) - elif key == "accelerated_2d_canvas_disabled": - cefBrowserSettings.accelerated_2d_canvas_disabled = bool(browserSettings[key]) - elif key == "accelerated_filters_disabled": - cefBrowserSettings.accelerated_filters_disabled = bool(browserSettings[key]) - elif key == "accelerated_plugins_disabled": - cefBrowserSettings.accelerated_plugins_disabled = bool(browserSettings[key]) - elif key == "developer_tools_disabled": - cefBrowserSettings.developer_tools_disabled = bool(browserSettings[key]) - elif key == "fullscreen_enabled": - cefBrowserSettings.fullscreen_enabled = bool(browserSettings[key]) + if key == "standard_font_family": + cefString = new CefString(&cefBrowserSettings.standard_font_family) + PyToCefStringPointer(browserSettings[key], cefString) + del cefString + elif key == "fixed_font_family": + cefString = new CefString(&cefBrowserSettings.fixed_font_family) + PyToCefStringPointer(browserSettings[key], cefString) + del cefString + elif key == "serif_font_family": + cefString = new CefString(&cefBrowserSettings.serif_font_family) + PyToCefStringPointer(browserSettings[key], cefString) + del cefString + elif key == "sans_serif_font_family": + cefString = new CefString(&cefBrowserSettings.sans_serif_font_family) + PyToCefStringPointer(browserSettings[key], cefString) + del cefString + elif key == "cursive_font_family": + cefString = new CefString(&cefBrowserSettings.cursive_font_family) + PyToCefStringPointer(browserSettings[key], cefString) + del cefString + elif key == "fantasy_font_family": + cefString = new CefString(&cefBrowserSettings.fantasy_font_family) + PyToCefStringPointer(browserSettings[key], cefString) + del cefString + elif key == "default_font_size": + cefBrowserSettings.default_font_size = int(browserSettings[key]) + elif key == "default_fixed_font_size": + cefBrowserSettings.default_fixed_font_size = int(browserSettings[key]) + elif key == "minimum_font_size": + cefBrowserSettings.minimum_font_size = int(browserSettings[key]) + elif key == "minimum_logical_font_size": + cefBrowserSettings.minimum_logical_font_size = int(browserSettings[key]) + elif key == "default_encoding": + cefString = new CefString(&cefBrowserSettings.default_encoding) + PyToCefStringPointer(browserSettings[key], cefString) + del cefString + elif key == "user_style_sheet_location": + cefString = new CefString(&cefBrowserSettings.user_style_sheet_location) + PyToCefStringPointer(browserSettings[key], cefString) + del cefString + elif key == "remote_fonts_disabled": + if browserSettings[key]: + cefBrowserSettings.remote_fonts = cef_types.STATE_DISABLED else: - raise Exception("Invalid browserSettings key: %s" % key) - - ELIF CEF_VERSION == 3: - - if key == "standard_font_family": - cefString = new CefString(&cefBrowserSettings.standard_font_family) - PyToCefStringPointer(browserSettings[key], cefString) - del cefString - elif key == "fixed_font_family": - cefString = new CefString(&cefBrowserSettings.fixed_font_family) - PyToCefStringPointer(browserSettings[key], cefString) - del cefString - elif key == "serif_font_family": - cefString = new CefString(&cefBrowserSettings.serif_font_family) - PyToCefStringPointer(browserSettings[key], cefString) - del cefString - elif key == "sans_serif_font_family": - cefString = new CefString(&cefBrowserSettings.sans_serif_font_family) - PyToCefStringPointer(browserSettings[key], cefString) - del cefString - elif key == "cursive_font_family": - cefString = new CefString(&cefBrowserSettings.cursive_font_family) - PyToCefStringPointer(browserSettings[key], cefString) - del cefString - elif key == "fantasy_font_family": - cefString = new CefString(&cefBrowserSettings.fantasy_font_family) - PyToCefStringPointer(browserSettings[key], cefString) - del cefString - elif key == "default_font_size": - cefBrowserSettings.default_font_size = int(browserSettings[key]) - elif key == "default_fixed_font_size": - cefBrowserSettings.default_fixed_font_size = int(browserSettings[key]) - elif key == "minimum_font_size": - cefBrowserSettings.minimum_font_size = int(browserSettings[key]) - elif key == "minimum_logical_font_size": - cefBrowserSettings.minimum_logical_font_size = int(browserSettings[key]) - elif key == "default_encoding": - cefString = new CefString(&cefBrowserSettings.default_encoding) - PyToCefStringPointer(browserSettings[key], cefString) - del cefString - elif key == "user_style_sheet_location": - cefString = new CefString(&cefBrowserSettings.user_style_sheet_location) - PyToCefStringPointer(browserSettings[key], cefString) - del cefString - elif key == "remote_fonts_disabled": - if browserSettings[key]: - cefBrowserSettings.remote_fonts = cef_types.STATE_DISABLED - else: - cefBrowserSettings.remote_fonts = cef_types.STATE_ENABLED - elif key == "javascript_disabled": - if browserSettings[key]: - cefBrowserSettings.javascript = cef_types.STATE_DISABLED - else: - cefBrowserSettings.javascript = cef_types.STATE_ENABLED - elif key == "javascript_open_windows_disallowed": - if browserSettings[key]: - cefBrowserSettings.javascript_open_windows = ( - cef_types.STATE_DISABLED) - else: - cefBrowserSettings.javascript_open_windows = ( - cef_types.STATE_ENABLED) - elif key == "javascript_close_windows_disallowed": - if browserSettings[key]: - cefBrowserSettings.javascript_close_windows = ( - cef_types.STATE_DISABLED) - else: - cefBrowserSettings.javascript_close_windows = ( - cef_types.STATE_ENABLED) - elif key == "javascript_access_clipboard_disallowed": - if browserSettings[key]: - cefBrowserSettings.javascript_access_clipboard = ( - cef_types.STATE_DISABLED) - else: - cefBrowserSettings.javascript_access_clipboard = ( - cef_types.STATE_ENABLED) - elif key == "dom_paste_disabled": - if browserSettings[key]: - cefBrowserSettings.javascript_dom_paste = ( - cef_types.STATE_DISABLED) - else: - cefBrowserSettings.javascript_dom_paste = ( - cef_types.STATE_ENABLED) - elif key == "caret_browsing_enabled": - if browserSettings[key]: - cefBrowserSettings.caret_browsing = ( - cef_types.STATE_ENABLED) - else: - cefBrowserSettings.caret_browsing = ( - cef_types.STATE_DISABLED) - elif key == "java_disabled": - if browserSettings[key]: - cefBrowserSettings.java = cef_types.STATE_DISABLED - else: - cefBrowserSettings.java = cef_types.STATE_ENABLED - elif key == "plugins_disabled": - if browserSettings[key]: - cefBrowserSettings.plugins = cef_types.STATE_DISABLED - else: - cefBrowserSettings.plugins = cef_types.STATE_ENABLED - elif key == "universal_access_from_file_urls_allowed": - if browserSettings[key]: - cefBrowserSettings.universal_access_from_file_urls = ( - cef_types.STATE_ENABLED) - else: - cefBrowserSettings.universal_access_from_file_urls = ( - cef_types.STATE_DISABLED) - elif key == "file_access_from_file_urls_allowed": - if browserSettings[key]: - cefBrowserSettings.file_access_from_file_urls = ( - cef_types.STATE_ENABLED) - else: - cefBrowserSettings.file_access_from_file_urls = ( - cef_types.STATE_DISABLED) - elif key == "web_security_disabled": - if browserSettings[key]: - cefBrowserSettings.web_security = cef_types.STATE_DISABLED - else: - cefBrowserSettings.web_security = cef_types.STATE_ENABLED - elif key == "image_load_disabled": - if browserSettings[key]: - cefBrowserSettings.image_loading = cef_types.STATE_DISABLED - else: - cefBrowserSettings.image_loading = cef_types.STATE_ENABLED - elif key == "shrink_standalone_images_to_fit": - if browserSettings[key]: - cefBrowserSettings.image_shrink_standalone_to_fit = ( - cef_types.STATE_ENABLED) - else: - cefBrowserSettings.image_shrink_standalone_to_fit = ( - cef_types.STATE_DISABLED) - elif key == "text_area_resize_disabled": - if browserSettings[key]: - cefBrowserSettings.text_area_resize = ( - cef_types.STATE_DISABLED) - else: - cefBrowserSettings.text_area_resize = ( - cef_types.STATE_ENABLED) - elif key == "tab_to_links_disabled": - if browserSettings[key]: - cefBrowserSettings.tab_to_links = cef_types.STATE_DISABLED - else: - cefBrowserSettings.tab_to_links = cef_types.STATE_ENABLED - elif key == "author_and_user_styles_disabled": - if browserSettings[key]: - cefBrowserSettings.author_and_user_styles = ( - cef_types.STATE_DISABLED) - else: - cefBrowserSettings.author_and_user_styles = ( - cef_types.STATE_ENABLED) - elif key == "local_storage_disabled": - if browserSettings[key]: - cefBrowserSettings.local_storage = cef_types.STATE_DISABLED - else: - cefBrowserSettings.local_storage = cef_types.STATE_ENABLED - elif key == "databases_disabled": - if browserSettings[key]: - cefBrowserSettings.databases = cef_types.STATE_DISABLED - else: - cefBrowserSettings.databases = cef_types.STATE_ENABLED - elif key == "application_cache_disabled": - if browserSettings[key]: - cefBrowserSettings.application_cache = ( - cef_types.STATE_DISABLED) - else: - cefBrowserSettings.application_cache = ( - cef_types.STATE_ENABLED) - elif key == "webgl_disabled": - if browserSettings[key]: - cefBrowserSettings.webgl = cef_types.STATE_DISABLED - else: - cefBrowserSettings.webgl = cef_types.STATE_ENABLED - elif key == "accelerated_compositing_disabled": - if browserSettings[key]: - cefBrowserSettings.accelerated_compositing = ( - cef_types.STATE_DISABLED) - else: - cefBrowserSettings.accelerated_compositing = ( - cef_types.STATE_ENABLED) + cefBrowserSettings.remote_fonts = cef_types.STATE_ENABLED + elif key == "javascript_disabled": + if browserSettings[key]: + cefBrowserSettings.javascript = cef_types.STATE_DISABLED + else: + cefBrowserSettings.javascript = cef_types.STATE_ENABLED + elif key == "javascript_open_windows_disallowed": + if browserSettings[key]: + cefBrowserSettings.javascript_open_windows = ( + cef_types.STATE_DISABLED) + else: + cefBrowserSettings.javascript_open_windows = ( + cef_types.STATE_ENABLED) + elif key == "javascript_close_windows_disallowed": + if browserSettings[key]: + cefBrowserSettings.javascript_close_windows = ( + cef_types.STATE_DISABLED) + else: + cefBrowserSettings.javascript_close_windows = ( + cef_types.STATE_ENABLED) + elif key == "javascript_access_clipboard_disallowed": + if browserSettings[key]: + cefBrowserSettings.javascript_access_clipboard = ( + cef_types.STATE_DISABLED) + else: + cefBrowserSettings.javascript_access_clipboard = ( + cef_types.STATE_ENABLED) + elif key == "dom_paste_disabled": + if browserSettings[key]: + cefBrowserSettings.javascript_dom_paste = ( + cef_types.STATE_DISABLED) + else: + cefBrowserSettings.javascript_dom_paste = ( + cef_types.STATE_ENABLED) + elif key == "caret_browsing_enabled": + if browserSettings[key]: + cefBrowserSettings.caret_browsing = ( + cef_types.STATE_ENABLED) else: - raise Exception("Invalid browserSettings key: %s" % key) + cefBrowserSettings.caret_browsing = ( + cef_types.STATE_DISABLED) + elif key == "java_disabled": + if browserSettings[key]: + cefBrowserSettings.java = cef_types.STATE_DISABLED + else: + cefBrowserSettings.java = cef_types.STATE_ENABLED + elif key == "plugins_disabled": + if browserSettings[key]: + cefBrowserSettings.plugins = cef_types.STATE_DISABLED + else: + cefBrowserSettings.plugins = cef_types.STATE_ENABLED + elif key == "universal_access_from_file_urls_allowed": + if browserSettings[key]: + cefBrowserSettings.universal_access_from_file_urls = ( + cef_types.STATE_ENABLED) + else: + cefBrowserSettings.universal_access_from_file_urls = ( + cef_types.STATE_DISABLED) + elif key == "file_access_from_file_urls_allowed": + if browserSettings[key]: + cefBrowserSettings.file_access_from_file_urls = ( + cef_types.STATE_ENABLED) + else: + cefBrowserSettings.file_access_from_file_urls = ( + cef_types.STATE_DISABLED) + elif key == "web_security_disabled": + if browserSettings[key]: + cefBrowserSettings.web_security = cef_types.STATE_DISABLED + else: + cefBrowserSettings.web_security = cef_types.STATE_ENABLED + elif key == "image_load_disabled": + if browserSettings[key]: + cefBrowserSettings.image_loading = cef_types.STATE_DISABLED + else: + cefBrowserSettings.image_loading = cef_types.STATE_ENABLED + elif key == "shrink_standalone_images_to_fit": + if browserSettings[key]: + cefBrowserSettings.image_shrink_standalone_to_fit = ( + cef_types.STATE_ENABLED) + else: + cefBrowserSettings.image_shrink_standalone_to_fit = ( + cef_types.STATE_DISABLED) + elif key == "text_area_resize_disabled": + if browserSettings[key]: + cefBrowserSettings.text_area_resize = ( + cef_types.STATE_DISABLED) + else: + cefBrowserSettings.text_area_resize = ( + cef_types.STATE_ENABLED) + elif key == "tab_to_links_disabled": + if browserSettings[key]: + cefBrowserSettings.tab_to_links = cef_types.STATE_DISABLED + else: + cefBrowserSettings.tab_to_links = cef_types.STATE_ENABLED + elif key == "author_and_user_styles_disabled": + if browserSettings[key]: + cefBrowserSettings.author_and_user_styles = ( + cef_types.STATE_DISABLED) + else: + cefBrowserSettings.author_and_user_styles = ( + cef_types.STATE_ENABLED) + elif key == "local_storage_disabled": + if browserSettings[key]: + cefBrowserSettings.local_storage = cef_types.STATE_DISABLED + else: + cefBrowserSettings.local_storage = cef_types.STATE_ENABLED + elif key == "databases_disabled": + if browserSettings[key]: + cefBrowserSettings.databases = cef_types.STATE_DISABLED + else: + cefBrowserSettings.databases = cef_types.STATE_ENABLED + elif key == "application_cache_disabled": + if browserSettings[key]: + cefBrowserSettings.application_cache = ( + cef_types.STATE_DISABLED) + else: + cefBrowserSettings.application_cache = ( + cef_types.STATE_ENABLED) + elif key == "webgl_disabled": + if browserSettings[key]: + cefBrowserSettings.webgl = cef_types.STATE_DISABLED + else: + cefBrowserSettings.webgl = cef_types.STATE_ENABLED + elif key == "accelerated_compositing_disabled": + if browserSettings[key]: + cefBrowserSettings.accelerated_compositing = ( + cef_types.STATE_DISABLED) + else: + cefBrowserSettings.accelerated_compositing = ( + cef_types.STATE_ENABLED) + else: + raise Exception("Invalid browserSettings key: %s" % key) diff --git a/cefpython/utils.pyx b/cefpython/utils.pyx index 5453d99fb..f2ff50714 100644 --- a/cefpython/utils.pyx +++ b/cefpython/utils.pyx @@ -96,15 +96,6 @@ cpdef str GetNavigateUrl(py_string url): return str(url) -IF CEF_VERSION == 1: - cpdef py_bool IsKeyModifier(int key, int modifiers): - if key == KEY_NONE: - # Same as: return (KEY_CTRL & modifiers) != KEY_CTRL - # and (KEY_ALT & modifiers) != KEY_ALT - # and (KEY_SHIFT & modifiers) != KEY_SHIFT - return ((KEY_SHIFT | KEY_CTRL | KEY_ALT) & modifiers) == 0 - return (key & modifiers) == key - cpdef str GetModuleDirectory(): import re, os, platform if platform.system() == "Linux" and os.getenv("CEFPYTHON3_PATH"): diff --git a/cefpython/windows/setup/setup.py b/cefpython/windows/setup/setup.py index 752adf55f..4b25202b9 100644 --- a/cefpython/windows/setup/setup.py +++ b/cefpython/windows/setup/setup.py @@ -18,9 +18,6 @@ # Stop on first error, otherwise hundreds of errors appear in the console. Options.fast_fail = True -# Written to cython_includes/compile_time_constants.pxi -CEF_VERSION = 3 - # Python version string: "27" or "32". PYVER = str(sys.version_info.major) + str(sys.version_info.minor) @@ -31,7 +28,6 @@ def CompileTimeConstants(): fd.write('# This file was generated by setup.py\n') # A way around Python 3.2 bug: UNAME_SYSNAME is not set. fd.write('DEF UNAME_SYSNAME = "%s"\n' % platform.uname()[0]) - fd.write('DEF CEF_VERSION = %s\n' % CEF_VERSION) fd.write('DEF PY_MAJOR_VERSION = %s\n' % sys.version_info.major) CompileTimeConstants() From 43d59954fe30d2742c20b7a6a81c72e83ff6c89f Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 14 May 2016 16:51:55 +0200 Subject: [PATCH 033/557] Fix link in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8788fb394..4c309df06 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Table of contents: ## Introduction -CEF Python is an open source project founded by [Czarek Tomczak](http://www.linkedin.com/in/czarektomczak) in 2012 to provide python bindings for the [Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef). See the growing list of [applications using CEF](http://en.wikipedia.org/wiki/Chromium_Embedded_Framework#Applications_using_CEF) on wikipedia. Examples of embedding CEF browser are available for many popular GUI toolkits including: [wxPython](../../wiki/wxPython), [PyGTK](../../wiki/PyGTK), [PyQt](../../wiki/PyQt), [PySide](../../wiki/PySide), [Kivy](../../wiki/Kivy), [Panda3D](../../wiki/Panda3D) and [PyWin32](../master/cefpython/cef3/windows/binaries_32bit/pywin32.py). +CEF Python is an open source project founded by [Czarek Tomczak](http://www.linkedin.com/in/czarektomczak) in 2012 to provide python bindings for the [Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef). See the growing list of [applications using CEF](http://en.wikipedia.org/wiki/Chromium_Embedded_Framework#Applications_using_CEF) on wikipedia. Examples of embedding CEF browser are available for many popular GUI toolkits including: [wxPython](../../wiki/wxPython), [PyGTK](../../wiki/PyGTK), [PyQt](../../wiki/PyQt), [PySide](../../wiki/PySide), [Kivy](../../wiki/Kivy), [Panda3D](../../wiki/Panda3D) and [PyWin32](../master/cefpython/windows/binaries_32bit/pywin32.py). Some use cases for CEF: From 10c2069e4aa2349bef6491b99567cc311665cccc Mon Sep 17 00:00:00 2001 From: Czarek Tomczak Date: Fri, 20 May 2016 17:09:43 +0000 Subject: [PATCH 034/557] Fix link --- api/JavascriptBindings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/JavascriptBindings.md b/api/JavascriptBindings.md index 99180a804..171ffc7fe 100644 --- a/api/JavascriptBindings.md +++ b/api/JavascriptBindings.md @@ -31,7 +31,7 @@ There are plans to support binding data by reference (a list, dict or object's p ## Example usage -See the [wxpython.py](../blob/master/cefpython/cef3/windows/binaries_32bit/wxpython.py) example for an example usage of javascript bindings, javascript callbacks and python callbacks. +See the [wxpython.py](../blob/master/cefpython/windows/binaries_32bit/wxpython.py) example for an example usage of javascript bindings, javascript callbacks and python callbacks. From a86711e505fc011cc746d539ce7ff50f6797e6af Mon Sep 17 00:00:00 2001 From: Czarek Tomczak Date: Fri, 20 May 2016 17:11:13 +0000 Subject: [PATCH 035/557] Fix link --- api/JavascriptBindings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/JavascriptBindings.md b/api/JavascriptBindings.md index 171ffc7fe..cc1f9efcb 100644 --- a/api/JavascriptBindings.md +++ b/api/JavascriptBindings.md @@ -31,7 +31,7 @@ There are plans to support binding data by reference (a list, dict or object's p ## Example usage -See the [wxpython.py](../blob/master/cefpython/windows/binaries_32bit/wxpython.py) example for an example usage of javascript bindings, javascript callbacks and python callbacks. +See the [wxpython.py](../cefpython/windows/binaries_32bit/wxpython.py) example for an example usage of javascript bindings, javascript callbacks and python callbacks. From d7eb667b24bb06b33343872395aa2c4c7e4e7055 Mon Sep 17 00:00:00 2001 From: Czarek Tomczak Date: Fri, 20 May 2016 17:21:31 +0000 Subject: [PATCH 036/557] Update Browser.md - add SetJavascriptBindings() --- api/Browser.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/api/Browser.md b/api/Browser.md index 1832296a7..17e0a6ef8 100644 --- a/api/Browser.md +++ b/api/Browser.md @@ -58,6 +58,7 @@ Table of contents: * [SetClientHandler](#setclienthandler) * [SetFocus](#setfocus) * [SetMouseCursorChangeDisabled](#setmousecursorchangedisabled) + * [SetJavascriptBindings](#setjavascriptbindings) * [SetUserData](#setuserdata) * [SetZoomLevel](#setzoomlevel) * [ShowDevTools](#showdevtools) @@ -649,6 +650,14 @@ Set focus for the browser window. If |enable| is true focus will be set to the w Set whether mouse cursor change is disabled. +### SetJavascriptBindings + +| Parameter | Type | +| --- | --- | +| bindings | [JavascriptBindings](JavascriptBindings.md) | +| __Return__ | void | + + ### SetUserData | Parameter | Type | From 3f6c6ba8579867f804185b30845b76245e103c8b Mon Sep 17 00:00:00 2001 From: Czarek Tomczak Date: Fri, 20 May 2016 17:22:36 +0000 Subject: [PATCH 037/557] Update JavascriptBindings.md --- api/JavascriptBindings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/JavascriptBindings.md b/api/JavascriptBindings.md index cc1f9efcb..de9047db0 100644 --- a/api/JavascriptBindings.md +++ b/api/JavascriptBindings.md @@ -18,7 +18,7 @@ Table of contents: ## Introduction -With this class you can expose python functions, objects and data. Binding is made to javascript "window" object. Instantiate this class and pass it to [cefpython](cefpython.md).CreateBrowserSync(). See also [javascript callbacks](JavascriptCallback.md). +With this class you can expose python functions, objects and data. Binding is made to javascript "window" object. Instantiate this class and pass it using [Browser](Browser.md).SetJavascriptBindings(). See also [javascript callbacks](JavascriptCallback.md). To initiate communication from python, when there is no javascript callback available yet, use [Frame](Frame.md).ExecuteJavascript() or [Frame](Frame.md).ExecuteFunction(). To get main frame for browser call [Browser](Browser.md).GetMainFrame(). From c778bdc08004f3b09a069ff8817df12ed8fca63c Mon Sep 17 00:00:00 2001 From: Czarek Tomczak Date: Fri, 20 May 2016 17:23:40 +0000 Subject: [PATCH 038/557] Update Browser.md --- api/Browser.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api/Browser.md b/api/Browser.md index 17e0a6ef8..8ec0cdffa 100644 --- a/api/Browser.md +++ b/api/Browser.md @@ -657,12 +657,14 @@ Set whether mouse cursor change is disabled. | bindings | [JavascriptBindings](JavascriptBindings.md) | | __Return__ | void | +Set javascript bindings. + ### SetUserData | Parameter | Type | | --- | --- | -| | mixedkey | +| key | mixed | | value | mixed | | __Return__ | void | From b48676955eb2363f08c18c179c0e3cfdcd3045d3 Mon Sep 17 00:00:00 2001 From: Czarek Tomczak Date: Sat, 21 May 2016 08:49:46 +0200 Subject: [PATCH 039/557] Fix return value in OnBeforeBrowse --- api/RequestHandler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/RequestHandler.md b/api/RequestHandler.md index 248197e26..a21b97a46 100644 --- a/api/RequestHandler.md +++ b/api/RequestHandler.md @@ -38,7 +38,7 @@ Table of contents: | frame | [Frame](Frame.md) | | request | [Request](Request.md) | | isRedirect | bool | -| __Return__ | void | +| __Return__ | bool | Called on the UI thread before browser navigation. Return true to cancel the navigation or false to allow the navigation to proceed. The |request| From 9c18902584577d20dd0b343d2098a673584fb175 Mon Sep 17 00:00:00 2001 From: Czarek Tomczak Date: Sat, 21 May 2016 08:56:00 +0200 Subject: [PATCH 040/557] Fix link to an example --- api/ResourceHandler.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/ResourceHandler.md b/api/ResourceHandler.md index 75df54938..ddf97af09 100644 --- a/api/ResourceHandler.md +++ b/api/ResourceHandler.md @@ -11,7 +11,7 @@ You must keep a strong reference to the `ResourceHandler` object while resource Make requests using [WebRequest](WebRequest.md) and [WebRequestClient](WebRequestClient.md). -The `ResourceHandler` example can be found in the [wxpython-response.py](../blob/master/cefpython/cef3/linux/binaries_64bit/wxpython-response.py) script. +The `ResourceHandler` example can be found in the [wxpython-response.py](../cefpython/linux/binaries_64bit/wxpython-response.py) script. Table of contents: From f587649345e8e74dc22f754b4b483638eac775b3 Mon Sep 17 00:00:00 2001 From: Czarek Tomczak Date: Tue, 24 May 2016 14:06:09 +0200 Subject: [PATCH 041/557] Add links to examples --- api/RenderHandler.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/api/RenderHandler.md b/api/RenderHandler.md index 6fe063d47..e10bbe016 100644 --- a/api/RenderHandler.md +++ b/api/RenderHandler.md @@ -5,6 +5,11 @@ Implement this interface to handle events when window rendering is disabled (off-screen rendering). The methods of this class will be called on the UI thread. +Off-screen rendering examples: +* [Kivy](Kivy) +* [Panda3D](Panda3D) +* [cefpython_offscreen_no_UI_framework.py](https://gist.github.com/stefanbacon/7b1571d57aee54aa9f8e9021b4848d06) - most basic usage of OSR to take screenshot of a page + Table of contents: * [Callbacks](#callbacks) From c5cfb4ee2942d4ca48b19ec0b57ac8eed0368eaa Mon Sep 17 00:00:00 2001 From: Czarek Tomczak Date: Tue, 24 May 2016 14:07:37 +0200 Subject: [PATCH 042/557] Fix links --- api/RenderHandler.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/RenderHandler.md b/api/RenderHandler.md index e10bbe016..0c936420f 100644 --- a/api/RenderHandler.md +++ b/api/RenderHandler.md @@ -6,8 +6,8 @@ Implement this interface to handle events when window rendering is disabled (off-screen rendering). The methods of this class will be called on the UI thread. Off-screen rendering examples: -* [Kivy](Kivy) -* [Panda3D](Panda3D) +* [Kivy](https://github.com/cztomczak/cefpython/wiki/Kivy) +* [Panda3D](https://github.com/cztomczak/cefpython/wiki/Panda3D) * [cefpython_offscreen_no_UI_framework.py](https://gist.github.com/stefanbacon/7b1571d57aee54aa9f8e9021b4848d06) - most basic usage of OSR to take screenshot of a page From 9943cd601eb9a01b9bf78b2a5407b054813a5b37 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 25 May 2016 09:57:43 +0200 Subject: [PATCH 043/557] Update old Google Code links to issues --- cefpython/mac/binaries_32bit/wxpython.py | 2 +- cefpython/mac/binaries_64bit/wxpython.py | 2 +- cefpython/process_message_utils.pyx | 2 +- cefpython/subprocess/v8utils.cpp | 2 +- cefpython/windows/binaries_32bit/wxpython.html | 2 +- cefpython/windows/binaries_32bit/wxpython.py | 2 +- cefpython/windows/binaries_64bit/wxpython.html | 2 +- cefpython/windows/binaries_64bit/wxpython.py | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cefpython/mac/binaries_32bit/wxpython.py b/cefpython/mac/binaries_32bit/wxpython.py index 7fa98e27a..f060a18aa 100644 --- a/cefpython/mac/binaries_32bit/wxpython.py +++ b/cefpython/mac/binaries_32bit/wxpython.py @@ -11,7 +11,7 @@ # then freed using tcmalloc then this would result in random # segmentation faults in an application. See Issue 155 which # is to provide CEF builds on Mac with tcmalloc disabled: -# https://code.google.com/p/cefpython/issues/detail?id=155 +# https://github.com/cztomczak/cefpython/issues/155 import ctypes, os, sys libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)),\ diff --git a/cefpython/mac/binaries_64bit/wxpython.py b/cefpython/mac/binaries_64bit/wxpython.py index 7fa98e27a..f060a18aa 100644 --- a/cefpython/mac/binaries_64bit/wxpython.py +++ b/cefpython/mac/binaries_64bit/wxpython.py @@ -11,7 +11,7 @@ # then freed using tcmalloc then this would result in random # segmentation faults in an application. See Issue 155 which # is to provide CEF builds on Mac with tcmalloc disabled: -# https://code.google.com/p/cefpython/issues/detail?id=155 +# https://github.com/cztomczak/cefpython/issues/155 import ctypes, os, sys libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)),\ diff --git a/cefpython/process_message_utils.pyx b/cefpython/process_message_utils.pyx index f6a1b2dec..799f7ae4d 100644 --- a/cefpython/process_message_utils.pyx +++ b/cefpython/process_message_utils.pyx @@ -5,7 +5,7 @@ # CefListValue->SetXxxx() functions need first param to be be cast # to (int) because GetSize() returns size_t and generates a warning # when compiling on VS2008 for x64 platform. Issue reported here: -# https://code.google.com/p/cefpython/issues/detail?id=165 +# https://github.com/cztomczak/cefpython/issues/165 # Here in pyx you also need to convert Py_ssize_t returned by # enumerate(), to an int. diff --git a/cefpython/subprocess/v8utils.cpp b/cefpython/subprocess/v8utils.cpp index 1d5bd461e..ef2248869 100644 --- a/cefpython/subprocess/v8utils.cpp +++ b/cefpython/subprocess/v8utils.cpp @@ -5,7 +5,7 @@ // CefListValue->SetXxxx() functions need first param to be be cast // to (int) because GetSize() returns size_t and generates a warning // when compiling on VS2008 for x64 platform. Issue reported here: -// https://code.google.com/p/cefpython/issues/detail?id=165 +// https://github.com/cztomczak/cefpython/issues/165 #include "v8utils.h" #include "javascript_callback.h" diff --git a/cefpython/windows/binaries_32bit/wxpython.html b/cefpython/windows/binaries_32bit/wxpython.html index 59f3b09fd..b3ea3afe8 100644 --- a/cefpython/windows/binaries_32bit/wxpython.html +++ b/cefpython/windows/binaries_32bit/wxpython.html @@ -100,7 +100,7 @@

      Popups

      There are problems with keyboard in wxPython when popup windows are created -by CEF ( +by CEF ( Issue 80). To create the popup window of our own, the LifespanHandler::OnBeforePopup callback was implemented. Note that this has its implications, the popup window and parent window will not be able to diff --git a/cefpython/windows/binaries_32bit/wxpython.py b/cefpython/windows/binaries_32bit/wxpython.py index ed12af696..b45ed3069 100644 --- a/cefpython/windows/binaries_32bit/wxpython.py +++ b/cefpython/windows/binaries_32bit/wxpython.py @@ -652,7 +652,7 @@ def OnBeforePopup(self, browser, frame, targetUrl, targetFrameName, # occurs only in wxPython. PyGTK or PyQt do not require this fix. # The solution is to create window explicitilly, and not depend # on CEF to create window internally. See Issue 80 for details: - # https://code.google.com/p/cefpython/issues/detail?id=80 + # https://github.com/cztomczak/cefpython/issues/80 # If you set allowPopups=True then CEF will create popup window. # The wx.Frame cannot be created here, as this callback is diff --git a/cefpython/windows/binaries_64bit/wxpython.html b/cefpython/windows/binaries_64bit/wxpython.html index 59f3b09fd..b3ea3afe8 100644 --- a/cefpython/windows/binaries_64bit/wxpython.html +++ b/cefpython/windows/binaries_64bit/wxpython.html @@ -100,7 +100,7 @@

      Popups

      There are problems with keyboard in wxPython when popup windows are created -by CEF ( +by CEF ( Issue 80). To create the popup window of our own, the LifespanHandler::OnBeforePopup callback was implemented. Note that this has its implications, the popup window and parent window will not be able to diff --git a/cefpython/windows/binaries_64bit/wxpython.py b/cefpython/windows/binaries_64bit/wxpython.py index ed12af696..b45ed3069 100644 --- a/cefpython/windows/binaries_64bit/wxpython.py +++ b/cefpython/windows/binaries_64bit/wxpython.py @@ -652,7 +652,7 @@ def OnBeforePopup(self, browser, frame, targetUrl, targetFrameName, # occurs only in wxPython. PyGTK or PyQt do not require this fix. # The solution is to create window explicitilly, and not depend # on CEF to create window internally. See Issue 80 for details: - # https://code.google.com/p/cefpython/issues/detail?id=80 + # https://github.com/cztomczak/cefpython/issues/80 # If you set allowPopups=True then CEF will create popup window. # The wx.Frame cannot be created here, as this callback is From 96999f12a2cd187d4b90c13437f5f036227736ef Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 25 May 2016 10:32:20 +0200 Subject: [PATCH 044/557] Refactor files structure: cefpython/ -> src/ . More... Fix links to examples and other files. Update BUILD_COMPATIBILITY.txt - deprecated. Rename and update the Authors and License files. --- AUTHORS.txt => Authors | 0 LICENSE.txt => License | 2 +- README.md | 2 +- api/JavascriptBindings.md | 2 +- api/LifespanHandler.md | 3 ++- api/RequestHandler.md | 3 ++- api/ResourceHandler.md | 3 ++- cefpython/BUILD_COMPATIBILITY.txt | 16 ---------------- {cefpython => src}/.gitignore | 0 src/BUILD_COMPATIBILITY.txt | 2 ++ {cefpython => src}/DebugLog.h | 0 {cefpython => src}/LOG_DEBUG.h | 0 {cefpython => src}/app.pyx | 0 {cefpython => src}/browser.pyx | 0 {cefpython => src}/browser_process_handler.pyx | 0 {cefpython => src}/callback.pyx | 0 {cefpython => src}/cefpython.pyx | 0 {cefpython => src}/cefpython_public_api.h | 0 {cefpython => src}/client_handler/.gitignore | 0 {cefpython => src}/client_handler/Makefile | 0 .../client_handler/client_handler.cpp | 0 .../client_handler/client_handler.h | 0 .../client_handler_py27_32bit.vcproj | 0 .../client_handler_py27_64bit.vcproj | 0 .../client_handler_py34_32bit.vcproj | 0 .../client_handler/cookie_visitor.cpp | 0 .../client_handler/cookie_visitor.h | 0 {cefpython => src}/client_handler/dpi_aware.cpp | 0 {cefpython => src}/client_handler/dpi_aware.h | 0 .../client_handler/request_context_handler.cpp | 0 .../client_handler/request_context_handler.h | 0 .../client_handler/resource_handler.cpp | 0 .../client_handler/resource_handler.h | 0 .../client_handler/string_visitor.cpp | 0 .../client_handler/string_visitor.h | 0 {cefpython => src}/client_handler/task.cpp | 0 {cefpython => src}/client_handler/task.h | 0 {cefpython => src}/client_handler/util_mac.h | 0 {cefpython => src}/client_handler/util_mac.mm | 0 .../client_handler/web_request_client.cpp | 0 .../client_handler/web_request_client.h | 0 {cefpython => src}/command_line.pyx | 0 {cefpython => src}/cookie.pyx | 0 {cefpython => src}/cpp_utils/.gitignore | 0 {cefpython => src}/cpp_utils/Makefile | 0 {cefpython => src}/cpp_utils/PaintBuffer.cpp | 0 {cefpython => src}/cpp_utils/PaintBuffer.h | 0 .../cpp_utils/cpp_utils_32bit.vcproj | 0 .../cpp_utils/cpp_utils_64bit.vcproj | 0 {cefpython => src}/cpp_utils/stdint_win.h | 0 {cefpython => src}/cython_includes/cef_app.pxd | 0 {cefpython => src}/cython_includes/cef_base.pxd | 0 .../cython_includes/cef_browser.pxd | 0 .../cython_includes/cef_browser_static.pxd | 0 .../cython_includes/cef_callback.pxd | 0 .../cython_includes/cef_client.pxd | 0 .../cython_includes/cef_command_line.pxd | 0 .../cython_includes/cef_cookie.pxd | 0 .../cef_cookie_manager_namespace.pxd | 0 .../cython_includes/cef_frame.pxd | 0 .../cython_includes/cef_jsdialog_handler.pxd | 0 .../cython_includes/cef_linux.pxd | 0 {cefpython => src}/cython_includes/cef_mac.pxd | 0 .../cython_includes/cef_platform.pxd | 0 .../cython_includes/cef_process_message.pxd | 0 {cefpython => src}/cython_includes/cef_ptr.pxd | 0 .../cython_includes/cef_request.pxd | 0 .../cython_includes/cef_request_context.pxd | 0 .../cef_request_context_handler.pxd | 0 .../cython_includes/cef_request_handler.pxd | 0 .../cython_includes/cef_resource_handler.pxd | 0 .../cython_includes/cef_response.pxd | 0 .../cython_includes/cef_runnable.pxd | 0 .../cython_includes/cef_string.pxd | 0 .../cython_includes/cef_string_visitor.pxd | 0 {cefpython => src}/cython_includes/cef_task.pxd | 0 {cefpython => src}/cython_includes/cef_time.pxd | 0 .../cython_includes/cef_types.pxd | 0 .../cython_includes/cef_types_linux.pxd | 0 .../cython_includes/cef_types_mac.pxd | 0 .../cython_includes/cef_types_win.pxd | 0 .../cython_includes/cef_types_wrappers.pxd | 0 .../cython_includes/cef_urlrequest.pxd | 0 .../cython_includes/cef_values.pxd | 0 .../cython_includes/cef_web_plugin.pxd | 0 {cefpython => src}/cython_includes/cef_win.pxd | 0 .../cython_includes/cefpython_app.pxd | 0 .../cython_includes/client_handler.pxd | 0 .../cython_includes/cookie_visitor.pxd | 0 .../cython_includes/cpp_utils.pxd | 0 {cefpython => src}/cython_includes/ctime.pxd | 0 .../cython_includes/dpi_aware_win.pxd | 0 {cefpython => src}/cython_includes/linux.pxd | 0 {cefpython => src}/cython_includes/mac.pxd | 0 {cefpython => src}/cython_includes/multimap.pxd | 0 .../cython_includes/request_context_handler.pxd | 0 .../cython_includes/resource_handler.pxd | 0 .../cython_includes/string_visitor.pxd | 0 {cefpython => src}/cython_includes/task.pxd | 0 .../cython_includes/web_request_client.pxd | 0 {cefpython => src}/cython_includes/windows.pxd | 0 {cefpython => src}/cython_includes/wstring.pxd | 0 {cefpython => src}/display_handler.pyx | 0 {cefpython => src}/dpi_aware_win.pyx | 0 {cefpython => src}/frame.pyx | 0 {cefpython => src}/imports.pyx | 0 {cefpython => src}/include/cef_app.h | 0 .../include/cef_application_mac.h | 0 {cefpython => src}/include/cef_auth_callback.h | 0 {cefpython => src}/include/cef_base.h | 0 {cefpython => src}/include/cef_browser.h | 0 .../include/cef_browser_process_handler.h | 0 {cefpython => src}/include/cef_callback.h | 0 {cefpython => src}/include/cef_client.h | 0 {cefpython => src}/include/cef_command_line.h | 0 .../include/cef_context_menu_handler.h | 0 {cefpython => src}/include/cef_cookie.h | 0 {cefpython => src}/include/cef_dialog_handler.h | 0 .../include/cef_display_handler.h | 0 {cefpython => src}/include/cef_dom.h | 0 .../include/cef_download_handler.h | 0 {cefpython => src}/include/cef_download_item.h | 0 {cefpython => src}/include/cef_drag_data.h | 0 {cefpython => src}/include/cef_drag_handler.h | 0 {cefpython => src}/include/cef_focus_handler.h | 0 {cefpython => src}/include/cef_frame.h | 0 {cefpython => src}/include/cef_geolocation.h | 0 .../include/cef_geolocation_handler.h | 0 .../include/cef_jsdialog_handler.h | 0 .../include/cef_keyboard_handler.h | 0 .../include/cef_life_span_handler.h | 0 {cefpython => src}/include/cef_load_handler.h | 0 {cefpython => src}/include/cef_menu_model.h | 0 .../include/cef_origin_whitelist.h | 0 {cefpython => src}/include/cef_path_util.h | 0 .../include/cef_process_message.h | 0 {cefpython => src}/include/cef_process_util.h | 0 {cefpython => src}/include/cef_render_handler.h | 0 .../include/cef_render_process_handler.h | 0 {cefpython => src}/include/cef_request.h | 0 .../include/cef_request_context.h | 0 .../include/cef_request_context_handler.h | 0 .../include/cef_request_handler.h | 0 .../include/cef_resource_bundle_handler.h | 0 .../include/cef_resource_handler.h | 0 {cefpython => src}/include/cef_response.h | 0 {cefpython => src}/include/cef_runnable.h | 0 {cefpython => src}/include/cef_scheme.h | 0 {cefpython => src}/include/cef_stream.h | 0 {cefpython => src}/include/cef_string_visitor.h | 0 {cefpython => src}/include/cef_task.h | 0 {cefpython => src}/include/cef_trace.h | 0 {cefpython => src}/include/cef_trace_event.h | 0 {cefpython => src}/include/cef_url.h | 0 {cefpython => src}/include/cef_urlrequest.h | 0 {cefpython => src}/include/cef_v8.h | 0 {cefpython => src}/include/cef_values.h | 0 {cefpython => src}/include/cef_web_plugin.h | 0 {cefpython => src}/include/cef_xml_reader.h | 0 {cefpython => src}/include/cef_zip_reader.h | 0 {cefpython => src}/include/internal/cef_build.h | 0 .../include/internal/cef_export.h | 0 {cefpython => src}/include/internal/cef_linux.h | 0 {cefpython => src}/include/internal/cef_mac.h | 0 {cefpython => src}/include/internal/cef_ptr.h | 0 .../include/internal/cef_string.h | 0 .../include/internal/cef_string_list.h | 0 .../include/internal/cef_string_map.h | 0 .../include/internal/cef_string_multimap.h | 0 .../include/internal/cef_string_types.h | 0 .../include/internal/cef_string_wrappers.h | 0 {cefpython => src}/include/internal/cef_time.h | 0 {cefpython => src}/include/internal/cef_tuple.h | 0 {cefpython => src}/include/internal/cef_types.h | 0 .../include/internal/cef_types_linux.h | 0 .../include/internal/cef_types_mac.h | 0 .../include/internal/cef_types_win.h | 0 .../include/internal/cef_types_wrappers.h | 0 {cefpython => src}/include/internal/cef_win.h | 0 .../include/wrapper/cef_byte_read_handler.h | 0 .../wrapper/cef_stream_resource_handler.h | 0 .../include/wrapper/cef_xml_object.h | 0 .../include/wrapper/cef_zip_archive.h | 0 {cefpython => src}/javascript_bindings.pyx | 0 {cefpython => src}/javascript_callback.pyx | 0 .../javascript_dialog_handler.pyx | 0 {cefpython => src}/keyboard_handler.pyx | 0 {cefpython => src}/lifespan_handler.pyx | 0 {cefpython => src}/linux/.gitignore | 0 {cefpython => src}/linux/CEF-GTK-patch.txt | 0 .../linux/binaries_32bit/LICENSE.txt | 0 .../linux/binaries_32bit/README.txt | 0 .../linux/binaries_32bit/example.html | 0 .../kivy-select-boxes/kivy-selectBox.css | 0 .../kivy-select-boxes/kivy-selectBox.js | 0 .../kivy-select-boxes/kivy-test.html | 0 .../binaries_32bit/kivy-select-boxes/readme.md | 0 .../linux/binaries_32bit/kivy_.py | 0 .../linux/binaries_32bit/prism.css | 0 .../linux/binaries_32bit/prism.js | 0 .../linux/binaries_32bit/pygtk_.py | 0 {cefpython => src}/linux/binaries_32bit/pyqt.py | 0 .../linux/binaries_32bit/wxpython-response.py | 0 .../linux/binaries_32bit/wxpython.html | 0 .../linux/binaries_32bit/wxpython.py | 0 .../linux/binaries_64bit/LICENSE.txt | 0 .../linux/binaries_64bit/README.txt | 0 .../linux/binaries_64bit/example.html | 0 .../kivy-select-boxes/kivy-selectBox.css | 0 .../kivy-select-boxes/kivy-selectBox.js | 0 .../kivy-select-boxes/kivy-test.html | 0 .../binaries_64bit/kivy-select-boxes/readme.md | 0 .../linux/binaries_64bit/kivy_.py | 0 .../linux/binaries_64bit/prism.css | 0 .../linux/binaries_64bit/prism.js | 0 .../linux/binaries_64bit/pygtk_.py | 0 {cefpython => src}/linux/binaries_64bit/pyqt.py | 0 .../linux/binaries_64bit/wxpython-response.py | 0 .../linux/binaries_64bit/wxpython.html | 0 .../linux/binaries_64bit/wxpython.py | 0 {cefpython => src}/linux/compile.py | 0 {cefpython => src}/linux/installer/.gitignore | 0 {cefpython => src}/linux/installer/README.txt | 0 .../linux/installer/__init__.py.template | 0 .../installer/build-n-run-wx-chromectrl.sh | 0 .../linux/installer/debian.postinst | 0 {cefpython => src}/linux/installer/deps.txt | 0 {cefpython => src}/linux/installer/find-deps.py | 0 {cefpython => src}/linux/installer/make-deb.py | 0 .../linux/installer/make-setup.py | 0 .../linux/installer/setup.cfg.template | 0 .../linux/installer/setup.py.template | 0 .../linux/installer/stdeb.cfg.template | 0 {cefpython => src}/linux/rebuild.sh | 0 {cefpython => src}/linux/setup/.gitignore | 0 {cefpython => src}/linux/setup/cefpython.h | 0 {cefpython => src}/linux/setup/fix_pyx_files.py | 0 {cefpython => src}/linux/setup/setup.py | 0 {cefpython => src}/linux/wxpython.sh | 0 {cefpython => src}/load_handler.pyx | 0 {cefpython => src}/mac/.gitignore | 0 {cefpython => src}/mac/binaries_32bit/prism.css | 0 {cefpython => src}/mac/binaries_32bit/prism.js | 0 .../mac/binaries_32bit/wxpython.html | 0 .../mac/binaries_32bit/wxpython.py | 0 {cefpython => src}/mac/binaries_64bit/prism.css | 0 {cefpython => src}/mac/binaries_64bit/prism.js | 0 .../mac/binaries_64bit/wxpython.html | 0 .../mac/binaries_64bit/wxpython.py | 0 {cefpython => src}/mac/compile.py | 0 {cefpython => src}/mac/installer/.gitignore | 0 .../mac/installer/__init__.py.template | 0 {cefpython => src}/mac/installer/build_all.sh | 0 .../mac/installer/build_run_chromectrl.sh | 0 {cefpython => src}/mac/installer/make-setup.py | 0 .../mac/installer/setup.py.template | 0 {cefpython => src}/mac/mac32.sh | 0 {cefpython => src}/mac/mac64.sh | 0 {cefpython => src}/mac/setup/.gitignore | 0 {cefpython => src}/mac/setup/cefpython.h | 0 {cefpython => src}/mac/setup/fix_pyx_files.py | 0 {cefpython => src}/mac/setup/lib_32bit/README | 0 {cefpython => src}/mac/setup/lib_64bit/README | 0 {cefpython => src}/mac/setup/setup.py | 0 {cefpython => src}/network_error.pyx | 0 {cefpython => src}/paint_buffer.pyx | 0 {cefpython => src}/process_message_utils.pyx | 0 {cefpython => src}/python_callback.pyx | 0 {cefpython => src}/render_handler.pyx | 0 {cefpython => src}/request.pyx | 0 {cefpython => src}/request_handler.pyx | 0 {cefpython => src}/resource_handler.pyx | 0 {cefpython => src}/response.pyx | 0 {cefpython => src}/settings.pyx | 0 {cefpython => src}/string_utils.pyx | 0 {cefpython => src}/string_utils_win.pyx | 0 {cefpython => src}/string_visitor.pyx | 0 {cefpython => src}/subprocess/.gitignore | 0 {cefpython => src}/subprocess/Makefile | 0 .../subprocess/Makefile-libcefpythonapp | 0 {cefpython => src}/subprocess/cefpython_app.cpp | 0 {cefpython => src}/subprocess/cefpython_app.h | 0 .../subprocess/javascript_callback.cpp | 0 .../subprocess/javascript_callback.h | 0 .../libcefpythonapp_py27_32bit.vcproj | 0 .../libcefpythonapp_py27_64bit.vcproj | 0 .../libcefpythonapp_py34_32bit.vcproj | 0 {cefpython => src}/subprocess/main.cpp | 0 .../subprocess/subprocess_32bit.vcproj | 0 .../subprocess/subprocess_64bit.vcproj | 0 .../subprocess/v8function_handler.cpp | 0 .../subprocess/v8function_handler.h | 0 {cefpython => src}/subprocess/v8utils.cpp | 0 {cefpython => src}/subprocess/v8utils.h | 0 {cefpython => src}/task.pyx | 0 {cefpython => src}/time_utils.pyx | 0 {cefpython => src}/util.h | 0 {cefpython => src}/utils.pyx | 0 {cefpython => src}/v8context_handler.pyx | 0 {cefpython => src}/v8function_handler.pyx | 0 {cefpython => src}/virtual_keys.pyx | 0 {cefpython => src}/web_plugin_info.pyx | 0 {cefpython => src}/web_request.pyx | 0 {cefpython => src}/window_info.pyx | 0 {cefpython => src}/window_utils_linux.pyx | 0 {cefpython => src}/window_utils_mac.pyx | 0 {cefpython => src}/window_utils_win.pyx | 0 {cefpython => src}/windows/.gitignore | 0 .../windows/binaries_32bit/LICENSE.txt | 0 .../windows/binaries_32bit/README.txt | 0 .../windows/binaries_32bit/cefwindow.py | 0 .../windows/binaries_32bit/example.html | 0 .../windows/binaries_32bit/icon.ico | Bin .../windows/binaries_32bit/prism.css | 0 .../windows/binaries_32bit/prism.js | 0 .../windows/binaries_32bit/pygtk_.py | 0 .../windows/binaries_32bit/pyqt.py | 0 .../windows/binaries_32bit/pyside.py | 0 .../windows/binaries_32bit/pywin32.py | 0 .../windows/binaries_32bit/smoke.css | 0 .../windows/binaries_32bit/smoke.min.js | 0 .../windows/binaries_32bit/wxpython.html | 0 .../windows/binaries_32bit/wxpython.py | 0 .../windows/binaries_64bit/LICENSE.txt | 0 .../windows/binaries_64bit/README.txt | 0 .../windows/binaries_64bit/cefwindow.py | 0 .../windows/binaries_64bit/example.html | 0 .../windows/binaries_64bit/icon.ico | Bin .../windows/binaries_64bit/prism.css | 0 .../windows/binaries_64bit/prism.js | 0 .../windows/binaries_64bit/pygtk_.py | 0 .../windows/binaries_64bit/pyqt.py | 0 .../windows/binaries_64bit/pyside.py | 0 .../windows/binaries_64bit/pywin32.py | 0 .../windows/binaries_64bit/smoke.css | 0 .../windows/binaries_64bit/smoke.min.js | 0 .../windows/binaries_64bit/wxpython.html | 0 .../windows/binaries_64bit/wxpython.py | 0 {cefpython => src}/windows/cefpython.rc | 0 {cefpython => src}/windows/compile.bat | 0 {cefpython => src}/windows/compile.cmd | 0 {cefpython => src}/windows/installer/.gitignore | 0 {cefpython => src}/windows/installer/README.txt | 0 .../windows/installer/__init__.py.template | 0 .../windows/installer/build_all.bat | 0 .../windows/installer/innosetup.template | 0 .../windows/installer/make-installer.py | 0 .../windows/installer/make-setup.py | 0 .../windows/installer/setup.cfg.template | 0 .../windows/installer/setup.py.template | 0 {cefpython => src}/windows/setup/.gitignore | 0 {cefpython => src}/windows/setup/cefpython.h | 0 {cefpython => src}/windows/setup/compile_rc.py | 0 .../windows/setup/delete_pyx_files.bat | 0 .../windows/setup/fix_cefpython_h.py | 0 .../windows/setup/fix_pyx_files.py | 0 .../windows/setup/lib_32bit/README | 0 .../windows/setup/lib_64bit/README | 0 {cefpython => src}/windows/setup/setup.py | 0 {cefpython => src}/windows/stdint.h | 0 {cefpython => src}/windows/wxpython.bat | 0 {cefpython => src}/wx/README.txt | 0 {cefpython => src}/wx/__init__.py | 0 {cefpython => src}/wx/chromectrl.py | 0 {cefpython => src}/wx/examples/back.png | Bin {cefpython => src}/wx/examples/forward.png | Bin {cefpython => src}/wx/examples/reload_page.png | Bin {cefpython => src}/wx/examples/sample1.html | 0 {cefpython => src}/wx/examples/sample1.py | 0 {cefpython => src}/wx/examples/sample2.py | 0 {cefpython => src}/wx/examples/sample3.py | 0 {cefpython => src}/wx/images/back.png | Bin {cefpython => src}/wx/images/forward.png | Bin {cefpython => src}/wx/images/reload_page.png | Bin {cefpython => src}/wx/utils.py | 0 375 files changed, 11 insertions(+), 22 deletions(-) rename AUTHORS.txt => Authors (100%) rename LICENSE.txt => License (96%) delete mode 100644 cefpython/BUILD_COMPATIBILITY.txt rename {cefpython => src}/.gitignore (100%) create mode 100644 src/BUILD_COMPATIBILITY.txt rename {cefpython => src}/DebugLog.h (100%) rename {cefpython => src}/LOG_DEBUG.h (100%) rename {cefpython => src}/app.pyx (100%) rename {cefpython => src}/browser.pyx (100%) rename {cefpython => src}/browser_process_handler.pyx (100%) rename {cefpython => src}/callback.pyx (100%) rename {cefpython => src}/cefpython.pyx (100%) rename {cefpython => src}/cefpython_public_api.h (100%) rename {cefpython => src}/client_handler/.gitignore (100%) rename {cefpython => src}/client_handler/Makefile (100%) rename {cefpython => src}/client_handler/client_handler.cpp (100%) rename {cefpython => src}/client_handler/client_handler.h (100%) rename {cefpython => src}/client_handler/client_handler_py27_32bit.vcproj (100%) rename {cefpython => src}/client_handler/client_handler_py27_64bit.vcproj (100%) rename {cefpython => src}/client_handler/client_handler_py34_32bit.vcproj (100%) rename {cefpython => src}/client_handler/cookie_visitor.cpp (100%) rename {cefpython => src}/client_handler/cookie_visitor.h (100%) rename {cefpython => src}/client_handler/dpi_aware.cpp (100%) rename {cefpython => src}/client_handler/dpi_aware.h (100%) rename {cefpython => src}/client_handler/request_context_handler.cpp (100%) rename {cefpython => src}/client_handler/request_context_handler.h (100%) rename {cefpython => src}/client_handler/resource_handler.cpp (100%) rename {cefpython => src}/client_handler/resource_handler.h (100%) rename {cefpython => src}/client_handler/string_visitor.cpp (100%) rename {cefpython => src}/client_handler/string_visitor.h (100%) rename {cefpython => src}/client_handler/task.cpp (100%) rename {cefpython => src}/client_handler/task.h (100%) rename {cefpython => src}/client_handler/util_mac.h (100%) rename {cefpython => src}/client_handler/util_mac.mm (100%) rename {cefpython => src}/client_handler/web_request_client.cpp (100%) rename {cefpython => src}/client_handler/web_request_client.h (100%) rename {cefpython => src}/command_line.pyx (100%) rename {cefpython => src}/cookie.pyx (100%) rename {cefpython => src}/cpp_utils/.gitignore (100%) rename {cefpython => src}/cpp_utils/Makefile (100%) rename {cefpython => src}/cpp_utils/PaintBuffer.cpp (100%) rename {cefpython => src}/cpp_utils/PaintBuffer.h (100%) rename {cefpython => src}/cpp_utils/cpp_utils_32bit.vcproj (100%) rename {cefpython => src}/cpp_utils/cpp_utils_64bit.vcproj (100%) rename {cefpython => src}/cpp_utils/stdint_win.h (100%) rename {cefpython => src}/cython_includes/cef_app.pxd (100%) rename {cefpython => src}/cython_includes/cef_base.pxd (100%) rename {cefpython => src}/cython_includes/cef_browser.pxd (100%) rename {cefpython => src}/cython_includes/cef_browser_static.pxd (100%) rename {cefpython => src}/cython_includes/cef_callback.pxd (100%) rename {cefpython => src}/cython_includes/cef_client.pxd (100%) rename {cefpython => src}/cython_includes/cef_command_line.pxd (100%) rename {cefpython => src}/cython_includes/cef_cookie.pxd (100%) rename {cefpython => src}/cython_includes/cef_cookie_manager_namespace.pxd (100%) rename {cefpython => src}/cython_includes/cef_frame.pxd (100%) rename {cefpython => src}/cython_includes/cef_jsdialog_handler.pxd (100%) rename {cefpython => src}/cython_includes/cef_linux.pxd (100%) rename {cefpython => src}/cython_includes/cef_mac.pxd (100%) rename {cefpython => src}/cython_includes/cef_platform.pxd (100%) rename {cefpython => src}/cython_includes/cef_process_message.pxd (100%) rename {cefpython => src}/cython_includes/cef_ptr.pxd (100%) rename {cefpython => src}/cython_includes/cef_request.pxd (100%) rename {cefpython => src}/cython_includes/cef_request_context.pxd (100%) rename {cefpython => src}/cython_includes/cef_request_context_handler.pxd (100%) rename {cefpython => src}/cython_includes/cef_request_handler.pxd (100%) rename {cefpython => src}/cython_includes/cef_resource_handler.pxd (100%) rename {cefpython => src}/cython_includes/cef_response.pxd (100%) rename {cefpython => src}/cython_includes/cef_runnable.pxd (100%) rename {cefpython => src}/cython_includes/cef_string.pxd (100%) rename {cefpython => src}/cython_includes/cef_string_visitor.pxd (100%) rename {cefpython => src}/cython_includes/cef_task.pxd (100%) rename {cefpython => src}/cython_includes/cef_time.pxd (100%) rename {cefpython => src}/cython_includes/cef_types.pxd (100%) rename {cefpython => src}/cython_includes/cef_types_linux.pxd (100%) rename {cefpython => src}/cython_includes/cef_types_mac.pxd (100%) rename {cefpython => src}/cython_includes/cef_types_win.pxd (100%) rename {cefpython => src}/cython_includes/cef_types_wrappers.pxd (100%) rename {cefpython => src}/cython_includes/cef_urlrequest.pxd (100%) rename {cefpython => src}/cython_includes/cef_values.pxd (100%) rename {cefpython => src}/cython_includes/cef_web_plugin.pxd (100%) rename {cefpython => src}/cython_includes/cef_win.pxd (100%) rename {cefpython => src}/cython_includes/cefpython_app.pxd (100%) rename {cefpython => src}/cython_includes/client_handler.pxd (100%) rename {cefpython => src}/cython_includes/cookie_visitor.pxd (100%) rename {cefpython => src}/cython_includes/cpp_utils.pxd (100%) rename {cefpython => src}/cython_includes/ctime.pxd (100%) rename {cefpython => src}/cython_includes/dpi_aware_win.pxd (100%) rename {cefpython => src}/cython_includes/linux.pxd (100%) rename {cefpython => src}/cython_includes/mac.pxd (100%) rename {cefpython => src}/cython_includes/multimap.pxd (100%) rename {cefpython => src}/cython_includes/request_context_handler.pxd (100%) rename {cefpython => src}/cython_includes/resource_handler.pxd (100%) rename {cefpython => src}/cython_includes/string_visitor.pxd (100%) rename {cefpython => src}/cython_includes/task.pxd (100%) rename {cefpython => src}/cython_includes/web_request_client.pxd (100%) rename {cefpython => src}/cython_includes/windows.pxd (100%) rename {cefpython => src}/cython_includes/wstring.pxd (100%) rename {cefpython => src}/display_handler.pyx (100%) rename {cefpython => src}/dpi_aware_win.pyx (100%) rename {cefpython => src}/frame.pyx (100%) rename {cefpython => src}/imports.pyx (100%) rename {cefpython => src}/include/cef_app.h (100%) rename {cefpython => src}/include/cef_application_mac.h (100%) rename {cefpython => src}/include/cef_auth_callback.h (100%) rename {cefpython => src}/include/cef_base.h (100%) rename {cefpython => src}/include/cef_browser.h (100%) rename {cefpython => src}/include/cef_browser_process_handler.h (100%) rename {cefpython => src}/include/cef_callback.h (100%) rename {cefpython => src}/include/cef_client.h (100%) rename {cefpython => src}/include/cef_command_line.h (100%) rename {cefpython => src}/include/cef_context_menu_handler.h (100%) rename {cefpython => src}/include/cef_cookie.h (100%) rename {cefpython => src}/include/cef_dialog_handler.h (100%) rename {cefpython => src}/include/cef_display_handler.h (100%) rename {cefpython => src}/include/cef_dom.h (100%) rename {cefpython => src}/include/cef_download_handler.h (100%) rename {cefpython => src}/include/cef_download_item.h (100%) rename {cefpython => src}/include/cef_drag_data.h (100%) rename {cefpython => src}/include/cef_drag_handler.h (100%) rename {cefpython => src}/include/cef_focus_handler.h (100%) rename {cefpython => src}/include/cef_frame.h (100%) rename {cefpython => src}/include/cef_geolocation.h (100%) rename {cefpython => src}/include/cef_geolocation_handler.h (100%) rename {cefpython => src}/include/cef_jsdialog_handler.h (100%) rename {cefpython => src}/include/cef_keyboard_handler.h (100%) rename {cefpython => src}/include/cef_life_span_handler.h (100%) rename {cefpython => src}/include/cef_load_handler.h (100%) rename {cefpython => src}/include/cef_menu_model.h (100%) rename {cefpython => src}/include/cef_origin_whitelist.h (100%) rename {cefpython => src}/include/cef_path_util.h (100%) rename {cefpython => src}/include/cef_process_message.h (100%) rename {cefpython => src}/include/cef_process_util.h (100%) rename {cefpython => src}/include/cef_render_handler.h (100%) rename {cefpython => src}/include/cef_render_process_handler.h (100%) rename {cefpython => src}/include/cef_request.h (100%) rename {cefpython => src}/include/cef_request_context.h (100%) rename {cefpython => src}/include/cef_request_context_handler.h (100%) rename {cefpython => src}/include/cef_request_handler.h (100%) rename {cefpython => src}/include/cef_resource_bundle_handler.h (100%) rename {cefpython => src}/include/cef_resource_handler.h (100%) rename {cefpython => src}/include/cef_response.h (100%) rename {cefpython => src}/include/cef_runnable.h (100%) rename {cefpython => src}/include/cef_scheme.h (100%) rename {cefpython => src}/include/cef_stream.h (100%) rename {cefpython => src}/include/cef_string_visitor.h (100%) rename {cefpython => src}/include/cef_task.h (100%) rename {cefpython => src}/include/cef_trace.h (100%) rename {cefpython => src}/include/cef_trace_event.h (100%) rename {cefpython => src}/include/cef_url.h (100%) rename {cefpython => src}/include/cef_urlrequest.h (100%) rename {cefpython => src}/include/cef_v8.h (100%) rename {cefpython => src}/include/cef_values.h (100%) rename {cefpython => src}/include/cef_web_plugin.h (100%) rename {cefpython => src}/include/cef_xml_reader.h (100%) rename {cefpython => src}/include/cef_zip_reader.h (100%) rename {cefpython => src}/include/internal/cef_build.h (100%) rename {cefpython => src}/include/internal/cef_export.h (100%) rename {cefpython => src}/include/internal/cef_linux.h (100%) rename {cefpython => src}/include/internal/cef_mac.h (100%) rename {cefpython => src}/include/internal/cef_ptr.h (100%) rename {cefpython => src}/include/internal/cef_string.h (100%) rename {cefpython => src}/include/internal/cef_string_list.h (100%) rename {cefpython => src}/include/internal/cef_string_map.h (100%) rename {cefpython => src}/include/internal/cef_string_multimap.h (100%) rename {cefpython => src}/include/internal/cef_string_types.h (100%) rename {cefpython => src}/include/internal/cef_string_wrappers.h (100%) rename {cefpython => src}/include/internal/cef_time.h (100%) rename {cefpython => src}/include/internal/cef_tuple.h (100%) rename {cefpython => src}/include/internal/cef_types.h (100%) rename {cefpython => src}/include/internal/cef_types_linux.h (100%) rename {cefpython => src}/include/internal/cef_types_mac.h (100%) rename {cefpython => src}/include/internal/cef_types_win.h (100%) rename {cefpython => src}/include/internal/cef_types_wrappers.h (100%) rename {cefpython => src}/include/internal/cef_win.h (100%) rename {cefpython => src}/include/wrapper/cef_byte_read_handler.h (100%) rename {cefpython => src}/include/wrapper/cef_stream_resource_handler.h (100%) rename {cefpython => src}/include/wrapper/cef_xml_object.h (100%) rename {cefpython => src}/include/wrapper/cef_zip_archive.h (100%) rename {cefpython => src}/javascript_bindings.pyx (100%) rename {cefpython => src}/javascript_callback.pyx (100%) rename {cefpython => src}/javascript_dialog_handler.pyx (100%) rename {cefpython => src}/keyboard_handler.pyx (100%) rename {cefpython => src}/lifespan_handler.pyx (100%) rename {cefpython => src}/linux/.gitignore (100%) rename {cefpython => src}/linux/CEF-GTK-patch.txt (100%) rename {cefpython => src}/linux/binaries_32bit/LICENSE.txt (100%) rename {cefpython => src}/linux/binaries_32bit/README.txt (100%) rename {cefpython => src}/linux/binaries_32bit/example.html (100%) rename {cefpython => src}/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.css (100%) rename {cefpython => src}/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.js (100%) rename {cefpython => src}/linux/binaries_32bit/kivy-select-boxes/kivy-test.html (100%) rename {cefpython => src}/linux/binaries_32bit/kivy-select-boxes/readme.md (100%) rename {cefpython => src}/linux/binaries_32bit/kivy_.py (100%) rename {cefpython => src}/linux/binaries_32bit/prism.css (100%) rename {cefpython => src}/linux/binaries_32bit/prism.js (100%) rename {cefpython => src}/linux/binaries_32bit/pygtk_.py (100%) rename {cefpython => src}/linux/binaries_32bit/pyqt.py (100%) rename {cefpython => src}/linux/binaries_32bit/wxpython-response.py (100%) rename {cefpython => src}/linux/binaries_32bit/wxpython.html (100%) rename {cefpython => src}/linux/binaries_32bit/wxpython.py (100%) rename {cefpython => src}/linux/binaries_64bit/LICENSE.txt (100%) rename {cefpython => src}/linux/binaries_64bit/README.txt (100%) rename {cefpython => src}/linux/binaries_64bit/example.html (100%) rename {cefpython => src}/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.css (100%) rename {cefpython => src}/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.js (100%) rename {cefpython => src}/linux/binaries_64bit/kivy-select-boxes/kivy-test.html (100%) rename {cefpython => src}/linux/binaries_64bit/kivy-select-boxes/readme.md (100%) rename {cefpython => src}/linux/binaries_64bit/kivy_.py (100%) rename {cefpython => src}/linux/binaries_64bit/prism.css (100%) rename {cefpython => src}/linux/binaries_64bit/prism.js (100%) rename {cefpython => src}/linux/binaries_64bit/pygtk_.py (100%) rename {cefpython => src}/linux/binaries_64bit/pyqt.py (100%) rename {cefpython => src}/linux/binaries_64bit/wxpython-response.py (100%) rename {cefpython => src}/linux/binaries_64bit/wxpython.html (100%) rename {cefpython => src}/linux/binaries_64bit/wxpython.py (100%) rename {cefpython => src}/linux/compile.py (100%) rename {cefpython => src}/linux/installer/.gitignore (100%) rename {cefpython => src}/linux/installer/README.txt (100%) rename {cefpython => src}/linux/installer/__init__.py.template (100%) rename {cefpython => src}/linux/installer/build-n-run-wx-chromectrl.sh (100%) rename {cefpython => src}/linux/installer/debian.postinst (100%) rename {cefpython => src}/linux/installer/deps.txt (100%) rename {cefpython => src}/linux/installer/find-deps.py (100%) rename {cefpython => src}/linux/installer/make-deb.py (100%) rename {cefpython => src}/linux/installer/make-setup.py (100%) rename {cefpython => src}/linux/installer/setup.cfg.template (100%) rename {cefpython => src}/linux/installer/setup.py.template (100%) rename {cefpython => src}/linux/installer/stdeb.cfg.template (100%) rename {cefpython => src}/linux/rebuild.sh (100%) rename {cefpython => src}/linux/setup/.gitignore (100%) rename {cefpython => src}/linux/setup/cefpython.h (100%) rename {cefpython => src}/linux/setup/fix_pyx_files.py (100%) rename {cefpython => src}/linux/setup/setup.py (100%) rename {cefpython => src}/linux/wxpython.sh (100%) rename {cefpython => src}/load_handler.pyx (100%) rename {cefpython => src}/mac/.gitignore (100%) rename {cefpython => src}/mac/binaries_32bit/prism.css (100%) rename {cefpython => src}/mac/binaries_32bit/prism.js (100%) rename {cefpython => src}/mac/binaries_32bit/wxpython.html (100%) rename {cefpython => src}/mac/binaries_32bit/wxpython.py (100%) rename {cefpython => src}/mac/binaries_64bit/prism.css (100%) rename {cefpython => src}/mac/binaries_64bit/prism.js (100%) rename {cefpython => src}/mac/binaries_64bit/wxpython.html (100%) rename {cefpython => src}/mac/binaries_64bit/wxpython.py (100%) rename {cefpython => src}/mac/compile.py (100%) rename {cefpython => src}/mac/installer/.gitignore (100%) rename {cefpython => src}/mac/installer/__init__.py.template (100%) rename {cefpython => src}/mac/installer/build_all.sh (100%) rename {cefpython => src}/mac/installer/build_run_chromectrl.sh (100%) rename {cefpython => src}/mac/installer/make-setup.py (100%) rename {cefpython => src}/mac/installer/setup.py.template (100%) rename {cefpython => src}/mac/mac32.sh (100%) rename {cefpython => src}/mac/mac64.sh (100%) rename {cefpython => src}/mac/setup/.gitignore (100%) rename {cefpython => src}/mac/setup/cefpython.h (100%) rename {cefpython => src}/mac/setup/fix_pyx_files.py (100%) rename {cefpython => src}/mac/setup/lib_32bit/README (100%) rename {cefpython => src}/mac/setup/lib_64bit/README (100%) rename {cefpython => src}/mac/setup/setup.py (100%) rename {cefpython => src}/network_error.pyx (100%) rename {cefpython => src}/paint_buffer.pyx (100%) rename {cefpython => src}/process_message_utils.pyx (100%) rename {cefpython => src}/python_callback.pyx (100%) rename {cefpython => src}/render_handler.pyx (100%) rename {cefpython => src}/request.pyx (100%) rename {cefpython => src}/request_handler.pyx (100%) rename {cefpython => src}/resource_handler.pyx (100%) rename {cefpython => src}/response.pyx (100%) rename {cefpython => src}/settings.pyx (100%) rename {cefpython => src}/string_utils.pyx (100%) rename {cefpython => src}/string_utils_win.pyx (100%) rename {cefpython => src}/string_visitor.pyx (100%) rename {cefpython => src}/subprocess/.gitignore (100%) rename {cefpython => src}/subprocess/Makefile (100%) rename {cefpython => src}/subprocess/Makefile-libcefpythonapp (100%) rename {cefpython => src}/subprocess/cefpython_app.cpp (100%) rename {cefpython => src}/subprocess/cefpython_app.h (100%) rename {cefpython => src}/subprocess/javascript_callback.cpp (100%) rename {cefpython => src}/subprocess/javascript_callback.h (100%) rename {cefpython => src}/subprocess/libcefpythonapp_py27_32bit.vcproj (100%) rename {cefpython => src}/subprocess/libcefpythonapp_py27_64bit.vcproj (100%) rename {cefpython => src}/subprocess/libcefpythonapp_py34_32bit.vcproj (100%) rename {cefpython => src}/subprocess/main.cpp (100%) rename {cefpython => src}/subprocess/subprocess_32bit.vcproj (100%) rename {cefpython => src}/subprocess/subprocess_64bit.vcproj (100%) rename {cefpython => src}/subprocess/v8function_handler.cpp (100%) rename {cefpython => src}/subprocess/v8function_handler.h (100%) rename {cefpython => src}/subprocess/v8utils.cpp (100%) rename {cefpython => src}/subprocess/v8utils.h (100%) rename {cefpython => src}/task.pyx (100%) rename {cefpython => src}/time_utils.pyx (100%) rename {cefpython => src}/util.h (100%) rename {cefpython => src}/utils.pyx (100%) rename {cefpython => src}/v8context_handler.pyx (100%) rename {cefpython => src}/v8function_handler.pyx (100%) rename {cefpython => src}/virtual_keys.pyx (100%) rename {cefpython => src}/web_plugin_info.pyx (100%) rename {cefpython => src}/web_request.pyx (100%) rename {cefpython => src}/window_info.pyx (100%) rename {cefpython => src}/window_utils_linux.pyx (100%) rename {cefpython => src}/window_utils_mac.pyx (100%) rename {cefpython => src}/window_utils_win.pyx (100%) rename {cefpython => src}/windows/.gitignore (100%) rename {cefpython => src}/windows/binaries_32bit/LICENSE.txt (100%) rename {cefpython => src}/windows/binaries_32bit/README.txt (100%) rename {cefpython => src}/windows/binaries_32bit/cefwindow.py (100%) rename {cefpython => src}/windows/binaries_32bit/example.html (100%) rename {cefpython => src}/windows/binaries_32bit/icon.ico (100%) rename {cefpython => src}/windows/binaries_32bit/prism.css (100%) rename {cefpython => src}/windows/binaries_32bit/prism.js (100%) rename {cefpython => src}/windows/binaries_32bit/pygtk_.py (100%) rename {cefpython => src}/windows/binaries_32bit/pyqt.py (100%) rename {cefpython => src}/windows/binaries_32bit/pyside.py (100%) rename {cefpython => src}/windows/binaries_32bit/pywin32.py (100%) rename {cefpython => src}/windows/binaries_32bit/smoke.css (100%) rename {cefpython => src}/windows/binaries_32bit/smoke.min.js (100%) rename {cefpython => src}/windows/binaries_32bit/wxpython.html (100%) rename {cefpython => src}/windows/binaries_32bit/wxpython.py (100%) rename {cefpython => src}/windows/binaries_64bit/LICENSE.txt (100%) rename {cefpython => src}/windows/binaries_64bit/README.txt (100%) rename {cefpython => src}/windows/binaries_64bit/cefwindow.py (100%) rename {cefpython => src}/windows/binaries_64bit/example.html (100%) rename {cefpython => src}/windows/binaries_64bit/icon.ico (100%) rename {cefpython => src}/windows/binaries_64bit/prism.css (100%) rename {cefpython => src}/windows/binaries_64bit/prism.js (100%) rename {cefpython => src}/windows/binaries_64bit/pygtk_.py (100%) rename {cefpython => src}/windows/binaries_64bit/pyqt.py (100%) rename {cefpython => src}/windows/binaries_64bit/pyside.py (100%) rename {cefpython => src}/windows/binaries_64bit/pywin32.py (100%) rename {cefpython => src}/windows/binaries_64bit/smoke.css (100%) rename {cefpython => src}/windows/binaries_64bit/smoke.min.js (100%) rename {cefpython => src}/windows/binaries_64bit/wxpython.html (100%) rename {cefpython => src}/windows/binaries_64bit/wxpython.py (100%) rename {cefpython => src}/windows/cefpython.rc (100%) rename {cefpython => src}/windows/compile.bat (100%) rename {cefpython => src}/windows/compile.cmd (100%) rename {cefpython => src}/windows/installer/.gitignore (100%) rename {cefpython => src}/windows/installer/README.txt (100%) rename {cefpython => src}/windows/installer/__init__.py.template (100%) rename {cefpython => src}/windows/installer/build_all.bat (100%) rename {cefpython => src}/windows/installer/innosetup.template (100%) rename {cefpython => src}/windows/installer/make-installer.py (100%) rename {cefpython => src}/windows/installer/make-setup.py (100%) rename {cefpython => src}/windows/installer/setup.cfg.template (100%) rename {cefpython => src}/windows/installer/setup.py.template (100%) rename {cefpython => src}/windows/setup/.gitignore (100%) rename {cefpython => src}/windows/setup/cefpython.h (100%) rename {cefpython => src}/windows/setup/compile_rc.py (100%) rename {cefpython => src}/windows/setup/delete_pyx_files.bat (100%) rename {cefpython => src}/windows/setup/fix_cefpython_h.py (100%) rename {cefpython => src}/windows/setup/fix_pyx_files.py (100%) rename {cefpython => src}/windows/setup/lib_32bit/README (100%) rename {cefpython => src}/windows/setup/lib_64bit/README (100%) rename {cefpython => src}/windows/setup/setup.py (100%) rename {cefpython => src}/windows/stdint.h (100%) rename {cefpython => src}/windows/wxpython.bat (100%) rename {cefpython => src}/wx/README.txt (100%) rename {cefpython => src}/wx/__init__.py (100%) rename {cefpython => src}/wx/chromectrl.py (100%) rename {cefpython => src}/wx/examples/back.png (100%) rename {cefpython => src}/wx/examples/forward.png (100%) rename {cefpython => src}/wx/examples/reload_page.png (100%) rename {cefpython => src}/wx/examples/sample1.html (100%) rename {cefpython => src}/wx/examples/sample1.py (100%) rename {cefpython => src}/wx/examples/sample2.py (100%) rename {cefpython => src}/wx/examples/sample3.py (100%) rename {cefpython => src}/wx/images/back.png (100%) rename {cefpython => src}/wx/images/forward.png (100%) rename {cefpython => src}/wx/images/reload_page.png (100%) rename {cefpython => src}/wx/utils.py (100%) diff --git a/AUTHORS.txt b/Authors similarity index 100% rename from AUTHORS.txt rename to Authors diff --git a/LICENSE.txt b/License similarity index 96% rename from LICENSE.txt rename to License index 2b6aad16d..6ff3fbf37 100644 --- a/LICENSE.txt +++ b/License @@ -1,4 +1,4 @@ -Copyright (c) 2012 The CEF Python authors - see the AUTHORS.txt file. +Copyright (c) 2012 The CEF Python authors - see the Authors file. All rights reserved. Licensed under the BSD 3-clause license. See project website: https://github.com/cztomczak/cefpython diff --git a/README.md b/README.md index 4c309df06..1f855ce6c 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Table of contents: ## Introduction -CEF Python is an open source project founded by [Czarek Tomczak](http://www.linkedin.com/in/czarektomczak) in 2012 to provide python bindings for the [Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef). See the growing list of [applications using CEF](http://en.wikipedia.org/wiki/Chromium_Embedded_Framework#Applications_using_CEF) on wikipedia. Examples of embedding CEF browser are available for many popular GUI toolkits including: [wxPython](../../wiki/wxPython), [PyGTK](../../wiki/PyGTK), [PyQt](../../wiki/PyQt), [PySide](../../wiki/PySide), [Kivy](../../wiki/Kivy), [Panda3D](../../wiki/Panda3D) and [PyWin32](../master/cefpython/windows/binaries_32bit/pywin32.py). +CEF Python is an open source project founded by [Czarek Tomczak](http://www.linkedin.com/in/czarektomczak) in 2012 to provide python bindings for the [Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef). See the growing list of [applications using CEF](http://en.wikipedia.org/wiki/Chromium_Embedded_Framework#Applications_using_CEF) on wikipedia. Examples of embedding CEF browser are available for many popular GUI toolkits including: [wxPython](../../wiki/wxPython), [PyGTK](../../wiki/PyGTK), [PyQt](../../wiki/PyQt), [PySide](../../wiki/PySide), [Kivy](../../wiki/Kivy), [Panda3D](../../wiki/Panda3D) and [PyWin32](src/windows/binaries_32bit/pywin32.py). Some use cases for CEF: diff --git a/api/JavascriptBindings.md b/api/JavascriptBindings.md index de9047db0..b00aa9527 100644 --- a/api/JavascriptBindings.md +++ b/api/JavascriptBindings.md @@ -31,7 +31,7 @@ There are plans to support binding data by reference (a list, dict or object's p ## Example usage -See the [wxpython.py](../cefpython/windows/binaries_32bit/wxpython.py) example for an example usage of javascript bindings, javascript callbacks and python callbacks. +See the [wxpython.py](../src/windows/binaries_32bit/wxpython.py) example for an example usage of javascript bindings, javascript callbacks and python callbacks. diff --git a/api/LifespanHandler.md b/api/LifespanHandler.md index 51cf02736..93a2c1548 100644 --- a/api/LifespanHandler.md +++ b/api/LifespanHandler.md @@ -91,7 +91,8 @@ close the window. This method will be called after the Javascript the associated OS window has been destroyed (for those browsers it is no longer possible to cancel the close). -See complete description of this callback in [cef_life_span_handler.h](../blob/master/cefpython/cef3/include/cef_life_span_handler.h). +See complete description of this callback in [cef_life_span_handler.h] +(../src/include/cef_life_span_handler.h). ### OnBeforeClose diff --git a/api/RequestHandler.md b/api/RequestHandler.md index a21b97a46..1afbe107c 100644 --- a/api/RequestHandler.md +++ b/api/RequestHandler.md @@ -91,7 +91,8 @@ The `GetResourceHandler` example can be found in the `wxpython-response.py` scri Not yet available in CEF 3 (see [CEF Issue 515](https://bitbucket.org/chromiumembedded/cef/issues/515)), though it can be emulated, see the comment below. You can implement this functionality by using [ResourceHandler](ResourceHandler.md) -and [WebRequest](WebRequest.md) / [WebRequestClient](WebRequestClient.md). For an example see the _OnResourceResponse() method in the [wxpython-response.py](../blob/master/cefpython/cef3/linux/binaries_64bit/wxpython-response.py) script. +and [WebRequest](WebRequest.md) / [WebRequestClient](WebRequestClient.md). For an example see the _OnResourceResponse() method in the [wxpython-response.py] +(../src/linux/binaries_64bit/wxpython-response.py) script. ### OnResourceRedirect diff --git a/api/ResourceHandler.md b/api/ResourceHandler.md index ddf97af09..f1f8ff28f 100644 --- a/api/ResourceHandler.md +++ b/api/ResourceHandler.md @@ -11,7 +11,8 @@ You must keep a strong reference to the `ResourceHandler` object while resource Make requests using [WebRequest](WebRequest.md) and [WebRequestClient](WebRequestClient.md). -The `ResourceHandler` example can be found in the [wxpython-response.py](../cefpython/linux/binaries_64bit/wxpython-response.py) script. +The `ResourceHandler` example can be found in the [wxpython-response.py] +(../src/linux/binaries_64bit/wxpython-response.py) script. Table of contents: diff --git a/cefpython/BUILD_COMPATIBILITY.txt b/cefpython/BUILD_COMPATIBILITY.txt deleted file mode 100644 index b4fbba792..000000000 --- a/cefpython/BUILD_COMPATIBILITY.txt +++ /dev/null @@ -1,16 +0,0 @@ -Chromium/CEF branch: - 1650 -Chromium release url: - http://src.chromium.org/svn/releases/31.0.1650.69 -CEF revision: - 1639 -CEF repository url: - http://chromiumembedded.googlecode.com/svn/branches/1650/cef3@1639 - ----- - -To convert chromium revision back to version string use this url: -http://src.chromium.org/viewvc/chrome/branches/xxxx/src/chrome/VERSION?revision=xxxx - -The latest chromium version in given branch: -http://src.chromium.org/viewvc/chrome/branches/xxxx/src/chrome/VERSION diff --git a/cefpython/.gitignore b/src/.gitignore similarity index 100% rename from cefpython/.gitignore rename to src/.gitignore diff --git a/src/BUILD_COMPATIBILITY.txt b/src/BUILD_COMPATIBILITY.txt new file mode 100644 index 000000000..edee3c73f --- /dev/null +++ b/src/BUILD_COMPATIBILITY.txt @@ -0,0 +1,2 @@ +Since Chrome47 release version information is provided in header +files in the src/version/ directory. diff --git a/cefpython/DebugLog.h b/src/DebugLog.h similarity index 100% rename from cefpython/DebugLog.h rename to src/DebugLog.h diff --git a/cefpython/LOG_DEBUG.h b/src/LOG_DEBUG.h similarity index 100% rename from cefpython/LOG_DEBUG.h rename to src/LOG_DEBUG.h diff --git a/cefpython/app.pyx b/src/app.pyx similarity index 100% rename from cefpython/app.pyx rename to src/app.pyx diff --git a/cefpython/browser.pyx b/src/browser.pyx similarity index 100% rename from cefpython/browser.pyx rename to src/browser.pyx diff --git a/cefpython/browser_process_handler.pyx b/src/browser_process_handler.pyx similarity index 100% rename from cefpython/browser_process_handler.pyx rename to src/browser_process_handler.pyx diff --git a/cefpython/callback.pyx b/src/callback.pyx similarity index 100% rename from cefpython/callback.pyx rename to src/callback.pyx diff --git a/cefpython/cefpython.pyx b/src/cefpython.pyx similarity index 100% rename from cefpython/cefpython.pyx rename to src/cefpython.pyx diff --git a/cefpython/cefpython_public_api.h b/src/cefpython_public_api.h similarity index 100% rename from cefpython/cefpython_public_api.h rename to src/cefpython_public_api.h diff --git a/cefpython/client_handler/.gitignore b/src/client_handler/.gitignore similarity index 100% rename from cefpython/client_handler/.gitignore rename to src/client_handler/.gitignore diff --git a/cefpython/client_handler/Makefile b/src/client_handler/Makefile similarity index 100% rename from cefpython/client_handler/Makefile rename to src/client_handler/Makefile diff --git a/cefpython/client_handler/client_handler.cpp b/src/client_handler/client_handler.cpp similarity index 100% rename from cefpython/client_handler/client_handler.cpp rename to src/client_handler/client_handler.cpp diff --git a/cefpython/client_handler/client_handler.h b/src/client_handler/client_handler.h similarity index 100% rename from cefpython/client_handler/client_handler.h rename to src/client_handler/client_handler.h diff --git a/cefpython/client_handler/client_handler_py27_32bit.vcproj b/src/client_handler/client_handler_py27_32bit.vcproj similarity index 100% rename from cefpython/client_handler/client_handler_py27_32bit.vcproj rename to src/client_handler/client_handler_py27_32bit.vcproj diff --git a/cefpython/client_handler/client_handler_py27_64bit.vcproj b/src/client_handler/client_handler_py27_64bit.vcproj similarity index 100% rename from cefpython/client_handler/client_handler_py27_64bit.vcproj rename to src/client_handler/client_handler_py27_64bit.vcproj diff --git a/cefpython/client_handler/client_handler_py34_32bit.vcproj b/src/client_handler/client_handler_py34_32bit.vcproj similarity index 100% rename from cefpython/client_handler/client_handler_py34_32bit.vcproj rename to src/client_handler/client_handler_py34_32bit.vcproj diff --git a/cefpython/client_handler/cookie_visitor.cpp b/src/client_handler/cookie_visitor.cpp similarity index 100% rename from cefpython/client_handler/cookie_visitor.cpp rename to src/client_handler/cookie_visitor.cpp diff --git a/cefpython/client_handler/cookie_visitor.h b/src/client_handler/cookie_visitor.h similarity index 100% rename from cefpython/client_handler/cookie_visitor.h rename to src/client_handler/cookie_visitor.h diff --git a/cefpython/client_handler/dpi_aware.cpp b/src/client_handler/dpi_aware.cpp similarity index 100% rename from cefpython/client_handler/dpi_aware.cpp rename to src/client_handler/dpi_aware.cpp diff --git a/cefpython/client_handler/dpi_aware.h b/src/client_handler/dpi_aware.h similarity index 100% rename from cefpython/client_handler/dpi_aware.h rename to src/client_handler/dpi_aware.h diff --git a/cefpython/client_handler/request_context_handler.cpp b/src/client_handler/request_context_handler.cpp similarity index 100% rename from cefpython/client_handler/request_context_handler.cpp rename to src/client_handler/request_context_handler.cpp diff --git a/cefpython/client_handler/request_context_handler.h b/src/client_handler/request_context_handler.h similarity index 100% rename from cefpython/client_handler/request_context_handler.h rename to src/client_handler/request_context_handler.h diff --git a/cefpython/client_handler/resource_handler.cpp b/src/client_handler/resource_handler.cpp similarity index 100% rename from cefpython/client_handler/resource_handler.cpp rename to src/client_handler/resource_handler.cpp diff --git a/cefpython/client_handler/resource_handler.h b/src/client_handler/resource_handler.h similarity index 100% rename from cefpython/client_handler/resource_handler.h rename to src/client_handler/resource_handler.h diff --git a/cefpython/client_handler/string_visitor.cpp b/src/client_handler/string_visitor.cpp similarity index 100% rename from cefpython/client_handler/string_visitor.cpp rename to src/client_handler/string_visitor.cpp diff --git a/cefpython/client_handler/string_visitor.h b/src/client_handler/string_visitor.h similarity index 100% rename from cefpython/client_handler/string_visitor.h rename to src/client_handler/string_visitor.h diff --git a/cefpython/client_handler/task.cpp b/src/client_handler/task.cpp similarity index 100% rename from cefpython/client_handler/task.cpp rename to src/client_handler/task.cpp diff --git a/cefpython/client_handler/task.h b/src/client_handler/task.h similarity index 100% rename from cefpython/client_handler/task.h rename to src/client_handler/task.h diff --git a/cefpython/client_handler/util_mac.h b/src/client_handler/util_mac.h similarity index 100% rename from cefpython/client_handler/util_mac.h rename to src/client_handler/util_mac.h diff --git a/cefpython/client_handler/util_mac.mm b/src/client_handler/util_mac.mm similarity index 100% rename from cefpython/client_handler/util_mac.mm rename to src/client_handler/util_mac.mm diff --git a/cefpython/client_handler/web_request_client.cpp b/src/client_handler/web_request_client.cpp similarity index 100% rename from cefpython/client_handler/web_request_client.cpp rename to src/client_handler/web_request_client.cpp diff --git a/cefpython/client_handler/web_request_client.h b/src/client_handler/web_request_client.h similarity index 100% rename from cefpython/client_handler/web_request_client.h rename to src/client_handler/web_request_client.h diff --git a/cefpython/command_line.pyx b/src/command_line.pyx similarity index 100% rename from cefpython/command_line.pyx rename to src/command_line.pyx diff --git a/cefpython/cookie.pyx b/src/cookie.pyx similarity index 100% rename from cefpython/cookie.pyx rename to src/cookie.pyx diff --git a/cefpython/cpp_utils/.gitignore b/src/cpp_utils/.gitignore similarity index 100% rename from cefpython/cpp_utils/.gitignore rename to src/cpp_utils/.gitignore diff --git a/cefpython/cpp_utils/Makefile b/src/cpp_utils/Makefile similarity index 100% rename from cefpython/cpp_utils/Makefile rename to src/cpp_utils/Makefile diff --git a/cefpython/cpp_utils/PaintBuffer.cpp b/src/cpp_utils/PaintBuffer.cpp similarity index 100% rename from cefpython/cpp_utils/PaintBuffer.cpp rename to src/cpp_utils/PaintBuffer.cpp diff --git a/cefpython/cpp_utils/PaintBuffer.h b/src/cpp_utils/PaintBuffer.h similarity index 100% rename from cefpython/cpp_utils/PaintBuffer.h rename to src/cpp_utils/PaintBuffer.h diff --git a/cefpython/cpp_utils/cpp_utils_32bit.vcproj b/src/cpp_utils/cpp_utils_32bit.vcproj similarity index 100% rename from cefpython/cpp_utils/cpp_utils_32bit.vcproj rename to src/cpp_utils/cpp_utils_32bit.vcproj diff --git a/cefpython/cpp_utils/cpp_utils_64bit.vcproj b/src/cpp_utils/cpp_utils_64bit.vcproj similarity index 100% rename from cefpython/cpp_utils/cpp_utils_64bit.vcproj rename to src/cpp_utils/cpp_utils_64bit.vcproj diff --git a/cefpython/cpp_utils/stdint_win.h b/src/cpp_utils/stdint_win.h similarity index 100% rename from cefpython/cpp_utils/stdint_win.h rename to src/cpp_utils/stdint_win.h diff --git a/cefpython/cython_includes/cef_app.pxd b/src/cython_includes/cef_app.pxd similarity index 100% rename from cefpython/cython_includes/cef_app.pxd rename to src/cython_includes/cef_app.pxd diff --git a/cefpython/cython_includes/cef_base.pxd b/src/cython_includes/cef_base.pxd similarity index 100% rename from cefpython/cython_includes/cef_base.pxd rename to src/cython_includes/cef_base.pxd diff --git a/cefpython/cython_includes/cef_browser.pxd b/src/cython_includes/cef_browser.pxd similarity index 100% rename from cefpython/cython_includes/cef_browser.pxd rename to src/cython_includes/cef_browser.pxd diff --git a/cefpython/cython_includes/cef_browser_static.pxd b/src/cython_includes/cef_browser_static.pxd similarity index 100% rename from cefpython/cython_includes/cef_browser_static.pxd rename to src/cython_includes/cef_browser_static.pxd diff --git a/cefpython/cython_includes/cef_callback.pxd b/src/cython_includes/cef_callback.pxd similarity index 100% rename from cefpython/cython_includes/cef_callback.pxd rename to src/cython_includes/cef_callback.pxd diff --git a/cefpython/cython_includes/cef_client.pxd b/src/cython_includes/cef_client.pxd similarity index 100% rename from cefpython/cython_includes/cef_client.pxd rename to src/cython_includes/cef_client.pxd diff --git a/cefpython/cython_includes/cef_command_line.pxd b/src/cython_includes/cef_command_line.pxd similarity index 100% rename from cefpython/cython_includes/cef_command_line.pxd rename to src/cython_includes/cef_command_line.pxd diff --git a/cefpython/cython_includes/cef_cookie.pxd b/src/cython_includes/cef_cookie.pxd similarity index 100% rename from cefpython/cython_includes/cef_cookie.pxd rename to src/cython_includes/cef_cookie.pxd diff --git a/cefpython/cython_includes/cef_cookie_manager_namespace.pxd b/src/cython_includes/cef_cookie_manager_namespace.pxd similarity index 100% rename from cefpython/cython_includes/cef_cookie_manager_namespace.pxd rename to src/cython_includes/cef_cookie_manager_namespace.pxd diff --git a/cefpython/cython_includes/cef_frame.pxd b/src/cython_includes/cef_frame.pxd similarity index 100% rename from cefpython/cython_includes/cef_frame.pxd rename to src/cython_includes/cef_frame.pxd diff --git a/cefpython/cython_includes/cef_jsdialog_handler.pxd b/src/cython_includes/cef_jsdialog_handler.pxd similarity index 100% rename from cefpython/cython_includes/cef_jsdialog_handler.pxd rename to src/cython_includes/cef_jsdialog_handler.pxd diff --git a/cefpython/cython_includes/cef_linux.pxd b/src/cython_includes/cef_linux.pxd similarity index 100% rename from cefpython/cython_includes/cef_linux.pxd rename to src/cython_includes/cef_linux.pxd diff --git a/cefpython/cython_includes/cef_mac.pxd b/src/cython_includes/cef_mac.pxd similarity index 100% rename from cefpython/cython_includes/cef_mac.pxd rename to src/cython_includes/cef_mac.pxd diff --git a/cefpython/cython_includes/cef_platform.pxd b/src/cython_includes/cef_platform.pxd similarity index 100% rename from cefpython/cython_includes/cef_platform.pxd rename to src/cython_includes/cef_platform.pxd diff --git a/cefpython/cython_includes/cef_process_message.pxd b/src/cython_includes/cef_process_message.pxd similarity index 100% rename from cefpython/cython_includes/cef_process_message.pxd rename to src/cython_includes/cef_process_message.pxd diff --git a/cefpython/cython_includes/cef_ptr.pxd b/src/cython_includes/cef_ptr.pxd similarity index 100% rename from cefpython/cython_includes/cef_ptr.pxd rename to src/cython_includes/cef_ptr.pxd diff --git a/cefpython/cython_includes/cef_request.pxd b/src/cython_includes/cef_request.pxd similarity index 100% rename from cefpython/cython_includes/cef_request.pxd rename to src/cython_includes/cef_request.pxd diff --git a/cefpython/cython_includes/cef_request_context.pxd b/src/cython_includes/cef_request_context.pxd similarity index 100% rename from cefpython/cython_includes/cef_request_context.pxd rename to src/cython_includes/cef_request_context.pxd diff --git a/cefpython/cython_includes/cef_request_context_handler.pxd b/src/cython_includes/cef_request_context_handler.pxd similarity index 100% rename from cefpython/cython_includes/cef_request_context_handler.pxd rename to src/cython_includes/cef_request_context_handler.pxd diff --git a/cefpython/cython_includes/cef_request_handler.pxd b/src/cython_includes/cef_request_handler.pxd similarity index 100% rename from cefpython/cython_includes/cef_request_handler.pxd rename to src/cython_includes/cef_request_handler.pxd diff --git a/cefpython/cython_includes/cef_resource_handler.pxd b/src/cython_includes/cef_resource_handler.pxd similarity index 100% rename from cefpython/cython_includes/cef_resource_handler.pxd rename to src/cython_includes/cef_resource_handler.pxd diff --git a/cefpython/cython_includes/cef_response.pxd b/src/cython_includes/cef_response.pxd similarity index 100% rename from cefpython/cython_includes/cef_response.pxd rename to src/cython_includes/cef_response.pxd diff --git a/cefpython/cython_includes/cef_runnable.pxd b/src/cython_includes/cef_runnable.pxd similarity index 100% rename from cefpython/cython_includes/cef_runnable.pxd rename to src/cython_includes/cef_runnable.pxd diff --git a/cefpython/cython_includes/cef_string.pxd b/src/cython_includes/cef_string.pxd similarity index 100% rename from cefpython/cython_includes/cef_string.pxd rename to src/cython_includes/cef_string.pxd diff --git a/cefpython/cython_includes/cef_string_visitor.pxd b/src/cython_includes/cef_string_visitor.pxd similarity index 100% rename from cefpython/cython_includes/cef_string_visitor.pxd rename to src/cython_includes/cef_string_visitor.pxd diff --git a/cefpython/cython_includes/cef_task.pxd b/src/cython_includes/cef_task.pxd similarity index 100% rename from cefpython/cython_includes/cef_task.pxd rename to src/cython_includes/cef_task.pxd diff --git a/cefpython/cython_includes/cef_time.pxd b/src/cython_includes/cef_time.pxd similarity index 100% rename from cefpython/cython_includes/cef_time.pxd rename to src/cython_includes/cef_time.pxd diff --git a/cefpython/cython_includes/cef_types.pxd b/src/cython_includes/cef_types.pxd similarity index 100% rename from cefpython/cython_includes/cef_types.pxd rename to src/cython_includes/cef_types.pxd diff --git a/cefpython/cython_includes/cef_types_linux.pxd b/src/cython_includes/cef_types_linux.pxd similarity index 100% rename from cefpython/cython_includes/cef_types_linux.pxd rename to src/cython_includes/cef_types_linux.pxd diff --git a/cefpython/cython_includes/cef_types_mac.pxd b/src/cython_includes/cef_types_mac.pxd similarity index 100% rename from cefpython/cython_includes/cef_types_mac.pxd rename to src/cython_includes/cef_types_mac.pxd diff --git a/cefpython/cython_includes/cef_types_win.pxd b/src/cython_includes/cef_types_win.pxd similarity index 100% rename from cefpython/cython_includes/cef_types_win.pxd rename to src/cython_includes/cef_types_win.pxd diff --git a/cefpython/cython_includes/cef_types_wrappers.pxd b/src/cython_includes/cef_types_wrappers.pxd similarity index 100% rename from cefpython/cython_includes/cef_types_wrappers.pxd rename to src/cython_includes/cef_types_wrappers.pxd diff --git a/cefpython/cython_includes/cef_urlrequest.pxd b/src/cython_includes/cef_urlrequest.pxd similarity index 100% rename from cefpython/cython_includes/cef_urlrequest.pxd rename to src/cython_includes/cef_urlrequest.pxd diff --git a/cefpython/cython_includes/cef_values.pxd b/src/cython_includes/cef_values.pxd similarity index 100% rename from cefpython/cython_includes/cef_values.pxd rename to src/cython_includes/cef_values.pxd diff --git a/cefpython/cython_includes/cef_web_plugin.pxd b/src/cython_includes/cef_web_plugin.pxd similarity index 100% rename from cefpython/cython_includes/cef_web_plugin.pxd rename to src/cython_includes/cef_web_plugin.pxd diff --git a/cefpython/cython_includes/cef_win.pxd b/src/cython_includes/cef_win.pxd similarity index 100% rename from cefpython/cython_includes/cef_win.pxd rename to src/cython_includes/cef_win.pxd diff --git a/cefpython/cython_includes/cefpython_app.pxd b/src/cython_includes/cefpython_app.pxd similarity index 100% rename from cefpython/cython_includes/cefpython_app.pxd rename to src/cython_includes/cefpython_app.pxd diff --git a/cefpython/cython_includes/client_handler.pxd b/src/cython_includes/client_handler.pxd similarity index 100% rename from cefpython/cython_includes/client_handler.pxd rename to src/cython_includes/client_handler.pxd diff --git a/cefpython/cython_includes/cookie_visitor.pxd b/src/cython_includes/cookie_visitor.pxd similarity index 100% rename from cefpython/cython_includes/cookie_visitor.pxd rename to src/cython_includes/cookie_visitor.pxd diff --git a/cefpython/cython_includes/cpp_utils.pxd b/src/cython_includes/cpp_utils.pxd similarity index 100% rename from cefpython/cython_includes/cpp_utils.pxd rename to src/cython_includes/cpp_utils.pxd diff --git a/cefpython/cython_includes/ctime.pxd b/src/cython_includes/ctime.pxd similarity index 100% rename from cefpython/cython_includes/ctime.pxd rename to src/cython_includes/ctime.pxd diff --git a/cefpython/cython_includes/dpi_aware_win.pxd b/src/cython_includes/dpi_aware_win.pxd similarity index 100% rename from cefpython/cython_includes/dpi_aware_win.pxd rename to src/cython_includes/dpi_aware_win.pxd diff --git a/cefpython/cython_includes/linux.pxd b/src/cython_includes/linux.pxd similarity index 100% rename from cefpython/cython_includes/linux.pxd rename to src/cython_includes/linux.pxd diff --git a/cefpython/cython_includes/mac.pxd b/src/cython_includes/mac.pxd similarity index 100% rename from cefpython/cython_includes/mac.pxd rename to src/cython_includes/mac.pxd diff --git a/cefpython/cython_includes/multimap.pxd b/src/cython_includes/multimap.pxd similarity index 100% rename from cefpython/cython_includes/multimap.pxd rename to src/cython_includes/multimap.pxd diff --git a/cefpython/cython_includes/request_context_handler.pxd b/src/cython_includes/request_context_handler.pxd similarity index 100% rename from cefpython/cython_includes/request_context_handler.pxd rename to src/cython_includes/request_context_handler.pxd diff --git a/cefpython/cython_includes/resource_handler.pxd b/src/cython_includes/resource_handler.pxd similarity index 100% rename from cefpython/cython_includes/resource_handler.pxd rename to src/cython_includes/resource_handler.pxd diff --git a/cefpython/cython_includes/string_visitor.pxd b/src/cython_includes/string_visitor.pxd similarity index 100% rename from cefpython/cython_includes/string_visitor.pxd rename to src/cython_includes/string_visitor.pxd diff --git a/cefpython/cython_includes/task.pxd b/src/cython_includes/task.pxd similarity index 100% rename from cefpython/cython_includes/task.pxd rename to src/cython_includes/task.pxd diff --git a/cefpython/cython_includes/web_request_client.pxd b/src/cython_includes/web_request_client.pxd similarity index 100% rename from cefpython/cython_includes/web_request_client.pxd rename to src/cython_includes/web_request_client.pxd diff --git a/cefpython/cython_includes/windows.pxd b/src/cython_includes/windows.pxd similarity index 100% rename from cefpython/cython_includes/windows.pxd rename to src/cython_includes/windows.pxd diff --git a/cefpython/cython_includes/wstring.pxd b/src/cython_includes/wstring.pxd similarity index 100% rename from cefpython/cython_includes/wstring.pxd rename to src/cython_includes/wstring.pxd diff --git a/cefpython/display_handler.pyx b/src/display_handler.pyx similarity index 100% rename from cefpython/display_handler.pyx rename to src/display_handler.pyx diff --git a/cefpython/dpi_aware_win.pyx b/src/dpi_aware_win.pyx similarity index 100% rename from cefpython/dpi_aware_win.pyx rename to src/dpi_aware_win.pyx diff --git a/cefpython/frame.pyx b/src/frame.pyx similarity index 100% rename from cefpython/frame.pyx rename to src/frame.pyx diff --git a/cefpython/imports.pyx b/src/imports.pyx similarity index 100% rename from cefpython/imports.pyx rename to src/imports.pyx diff --git a/cefpython/include/cef_app.h b/src/include/cef_app.h similarity index 100% rename from cefpython/include/cef_app.h rename to src/include/cef_app.h diff --git a/cefpython/include/cef_application_mac.h b/src/include/cef_application_mac.h similarity index 100% rename from cefpython/include/cef_application_mac.h rename to src/include/cef_application_mac.h diff --git a/cefpython/include/cef_auth_callback.h b/src/include/cef_auth_callback.h similarity index 100% rename from cefpython/include/cef_auth_callback.h rename to src/include/cef_auth_callback.h diff --git a/cefpython/include/cef_base.h b/src/include/cef_base.h similarity index 100% rename from cefpython/include/cef_base.h rename to src/include/cef_base.h diff --git a/cefpython/include/cef_browser.h b/src/include/cef_browser.h similarity index 100% rename from cefpython/include/cef_browser.h rename to src/include/cef_browser.h diff --git a/cefpython/include/cef_browser_process_handler.h b/src/include/cef_browser_process_handler.h similarity index 100% rename from cefpython/include/cef_browser_process_handler.h rename to src/include/cef_browser_process_handler.h diff --git a/cefpython/include/cef_callback.h b/src/include/cef_callback.h similarity index 100% rename from cefpython/include/cef_callback.h rename to src/include/cef_callback.h diff --git a/cefpython/include/cef_client.h b/src/include/cef_client.h similarity index 100% rename from cefpython/include/cef_client.h rename to src/include/cef_client.h diff --git a/cefpython/include/cef_command_line.h b/src/include/cef_command_line.h similarity index 100% rename from cefpython/include/cef_command_line.h rename to src/include/cef_command_line.h diff --git a/cefpython/include/cef_context_menu_handler.h b/src/include/cef_context_menu_handler.h similarity index 100% rename from cefpython/include/cef_context_menu_handler.h rename to src/include/cef_context_menu_handler.h diff --git a/cefpython/include/cef_cookie.h b/src/include/cef_cookie.h similarity index 100% rename from cefpython/include/cef_cookie.h rename to src/include/cef_cookie.h diff --git a/cefpython/include/cef_dialog_handler.h b/src/include/cef_dialog_handler.h similarity index 100% rename from cefpython/include/cef_dialog_handler.h rename to src/include/cef_dialog_handler.h diff --git a/cefpython/include/cef_display_handler.h b/src/include/cef_display_handler.h similarity index 100% rename from cefpython/include/cef_display_handler.h rename to src/include/cef_display_handler.h diff --git a/cefpython/include/cef_dom.h b/src/include/cef_dom.h similarity index 100% rename from cefpython/include/cef_dom.h rename to src/include/cef_dom.h diff --git a/cefpython/include/cef_download_handler.h b/src/include/cef_download_handler.h similarity index 100% rename from cefpython/include/cef_download_handler.h rename to src/include/cef_download_handler.h diff --git a/cefpython/include/cef_download_item.h b/src/include/cef_download_item.h similarity index 100% rename from cefpython/include/cef_download_item.h rename to src/include/cef_download_item.h diff --git a/cefpython/include/cef_drag_data.h b/src/include/cef_drag_data.h similarity index 100% rename from cefpython/include/cef_drag_data.h rename to src/include/cef_drag_data.h diff --git a/cefpython/include/cef_drag_handler.h b/src/include/cef_drag_handler.h similarity index 100% rename from cefpython/include/cef_drag_handler.h rename to src/include/cef_drag_handler.h diff --git a/cefpython/include/cef_focus_handler.h b/src/include/cef_focus_handler.h similarity index 100% rename from cefpython/include/cef_focus_handler.h rename to src/include/cef_focus_handler.h diff --git a/cefpython/include/cef_frame.h b/src/include/cef_frame.h similarity index 100% rename from cefpython/include/cef_frame.h rename to src/include/cef_frame.h diff --git a/cefpython/include/cef_geolocation.h b/src/include/cef_geolocation.h similarity index 100% rename from cefpython/include/cef_geolocation.h rename to src/include/cef_geolocation.h diff --git a/cefpython/include/cef_geolocation_handler.h b/src/include/cef_geolocation_handler.h similarity index 100% rename from cefpython/include/cef_geolocation_handler.h rename to src/include/cef_geolocation_handler.h diff --git a/cefpython/include/cef_jsdialog_handler.h b/src/include/cef_jsdialog_handler.h similarity index 100% rename from cefpython/include/cef_jsdialog_handler.h rename to src/include/cef_jsdialog_handler.h diff --git a/cefpython/include/cef_keyboard_handler.h b/src/include/cef_keyboard_handler.h similarity index 100% rename from cefpython/include/cef_keyboard_handler.h rename to src/include/cef_keyboard_handler.h diff --git a/cefpython/include/cef_life_span_handler.h b/src/include/cef_life_span_handler.h similarity index 100% rename from cefpython/include/cef_life_span_handler.h rename to src/include/cef_life_span_handler.h diff --git a/cefpython/include/cef_load_handler.h b/src/include/cef_load_handler.h similarity index 100% rename from cefpython/include/cef_load_handler.h rename to src/include/cef_load_handler.h diff --git a/cefpython/include/cef_menu_model.h b/src/include/cef_menu_model.h similarity index 100% rename from cefpython/include/cef_menu_model.h rename to src/include/cef_menu_model.h diff --git a/cefpython/include/cef_origin_whitelist.h b/src/include/cef_origin_whitelist.h similarity index 100% rename from cefpython/include/cef_origin_whitelist.h rename to src/include/cef_origin_whitelist.h diff --git a/cefpython/include/cef_path_util.h b/src/include/cef_path_util.h similarity index 100% rename from cefpython/include/cef_path_util.h rename to src/include/cef_path_util.h diff --git a/cefpython/include/cef_process_message.h b/src/include/cef_process_message.h similarity index 100% rename from cefpython/include/cef_process_message.h rename to src/include/cef_process_message.h diff --git a/cefpython/include/cef_process_util.h b/src/include/cef_process_util.h similarity index 100% rename from cefpython/include/cef_process_util.h rename to src/include/cef_process_util.h diff --git a/cefpython/include/cef_render_handler.h b/src/include/cef_render_handler.h similarity index 100% rename from cefpython/include/cef_render_handler.h rename to src/include/cef_render_handler.h diff --git a/cefpython/include/cef_render_process_handler.h b/src/include/cef_render_process_handler.h similarity index 100% rename from cefpython/include/cef_render_process_handler.h rename to src/include/cef_render_process_handler.h diff --git a/cefpython/include/cef_request.h b/src/include/cef_request.h similarity index 100% rename from cefpython/include/cef_request.h rename to src/include/cef_request.h diff --git a/cefpython/include/cef_request_context.h b/src/include/cef_request_context.h similarity index 100% rename from cefpython/include/cef_request_context.h rename to src/include/cef_request_context.h diff --git a/cefpython/include/cef_request_context_handler.h b/src/include/cef_request_context_handler.h similarity index 100% rename from cefpython/include/cef_request_context_handler.h rename to src/include/cef_request_context_handler.h diff --git a/cefpython/include/cef_request_handler.h b/src/include/cef_request_handler.h similarity index 100% rename from cefpython/include/cef_request_handler.h rename to src/include/cef_request_handler.h diff --git a/cefpython/include/cef_resource_bundle_handler.h b/src/include/cef_resource_bundle_handler.h similarity index 100% rename from cefpython/include/cef_resource_bundle_handler.h rename to src/include/cef_resource_bundle_handler.h diff --git a/cefpython/include/cef_resource_handler.h b/src/include/cef_resource_handler.h similarity index 100% rename from cefpython/include/cef_resource_handler.h rename to src/include/cef_resource_handler.h diff --git a/cefpython/include/cef_response.h b/src/include/cef_response.h similarity index 100% rename from cefpython/include/cef_response.h rename to src/include/cef_response.h diff --git a/cefpython/include/cef_runnable.h b/src/include/cef_runnable.h similarity index 100% rename from cefpython/include/cef_runnable.h rename to src/include/cef_runnable.h diff --git a/cefpython/include/cef_scheme.h b/src/include/cef_scheme.h similarity index 100% rename from cefpython/include/cef_scheme.h rename to src/include/cef_scheme.h diff --git a/cefpython/include/cef_stream.h b/src/include/cef_stream.h similarity index 100% rename from cefpython/include/cef_stream.h rename to src/include/cef_stream.h diff --git a/cefpython/include/cef_string_visitor.h b/src/include/cef_string_visitor.h similarity index 100% rename from cefpython/include/cef_string_visitor.h rename to src/include/cef_string_visitor.h diff --git a/cefpython/include/cef_task.h b/src/include/cef_task.h similarity index 100% rename from cefpython/include/cef_task.h rename to src/include/cef_task.h diff --git a/cefpython/include/cef_trace.h b/src/include/cef_trace.h similarity index 100% rename from cefpython/include/cef_trace.h rename to src/include/cef_trace.h diff --git a/cefpython/include/cef_trace_event.h b/src/include/cef_trace_event.h similarity index 100% rename from cefpython/include/cef_trace_event.h rename to src/include/cef_trace_event.h diff --git a/cefpython/include/cef_url.h b/src/include/cef_url.h similarity index 100% rename from cefpython/include/cef_url.h rename to src/include/cef_url.h diff --git a/cefpython/include/cef_urlrequest.h b/src/include/cef_urlrequest.h similarity index 100% rename from cefpython/include/cef_urlrequest.h rename to src/include/cef_urlrequest.h diff --git a/cefpython/include/cef_v8.h b/src/include/cef_v8.h similarity index 100% rename from cefpython/include/cef_v8.h rename to src/include/cef_v8.h diff --git a/cefpython/include/cef_values.h b/src/include/cef_values.h similarity index 100% rename from cefpython/include/cef_values.h rename to src/include/cef_values.h diff --git a/cefpython/include/cef_web_plugin.h b/src/include/cef_web_plugin.h similarity index 100% rename from cefpython/include/cef_web_plugin.h rename to src/include/cef_web_plugin.h diff --git a/cefpython/include/cef_xml_reader.h b/src/include/cef_xml_reader.h similarity index 100% rename from cefpython/include/cef_xml_reader.h rename to src/include/cef_xml_reader.h diff --git a/cefpython/include/cef_zip_reader.h b/src/include/cef_zip_reader.h similarity index 100% rename from cefpython/include/cef_zip_reader.h rename to src/include/cef_zip_reader.h diff --git a/cefpython/include/internal/cef_build.h b/src/include/internal/cef_build.h similarity index 100% rename from cefpython/include/internal/cef_build.h rename to src/include/internal/cef_build.h diff --git a/cefpython/include/internal/cef_export.h b/src/include/internal/cef_export.h similarity index 100% rename from cefpython/include/internal/cef_export.h rename to src/include/internal/cef_export.h diff --git a/cefpython/include/internal/cef_linux.h b/src/include/internal/cef_linux.h similarity index 100% rename from cefpython/include/internal/cef_linux.h rename to src/include/internal/cef_linux.h diff --git a/cefpython/include/internal/cef_mac.h b/src/include/internal/cef_mac.h similarity index 100% rename from cefpython/include/internal/cef_mac.h rename to src/include/internal/cef_mac.h diff --git a/cefpython/include/internal/cef_ptr.h b/src/include/internal/cef_ptr.h similarity index 100% rename from cefpython/include/internal/cef_ptr.h rename to src/include/internal/cef_ptr.h diff --git a/cefpython/include/internal/cef_string.h b/src/include/internal/cef_string.h similarity index 100% rename from cefpython/include/internal/cef_string.h rename to src/include/internal/cef_string.h diff --git a/cefpython/include/internal/cef_string_list.h b/src/include/internal/cef_string_list.h similarity index 100% rename from cefpython/include/internal/cef_string_list.h rename to src/include/internal/cef_string_list.h diff --git a/cefpython/include/internal/cef_string_map.h b/src/include/internal/cef_string_map.h similarity index 100% rename from cefpython/include/internal/cef_string_map.h rename to src/include/internal/cef_string_map.h diff --git a/cefpython/include/internal/cef_string_multimap.h b/src/include/internal/cef_string_multimap.h similarity index 100% rename from cefpython/include/internal/cef_string_multimap.h rename to src/include/internal/cef_string_multimap.h diff --git a/cefpython/include/internal/cef_string_types.h b/src/include/internal/cef_string_types.h similarity index 100% rename from cefpython/include/internal/cef_string_types.h rename to src/include/internal/cef_string_types.h diff --git a/cefpython/include/internal/cef_string_wrappers.h b/src/include/internal/cef_string_wrappers.h similarity index 100% rename from cefpython/include/internal/cef_string_wrappers.h rename to src/include/internal/cef_string_wrappers.h diff --git a/cefpython/include/internal/cef_time.h b/src/include/internal/cef_time.h similarity index 100% rename from cefpython/include/internal/cef_time.h rename to src/include/internal/cef_time.h diff --git a/cefpython/include/internal/cef_tuple.h b/src/include/internal/cef_tuple.h similarity index 100% rename from cefpython/include/internal/cef_tuple.h rename to src/include/internal/cef_tuple.h diff --git a/cefpython/include/internal/cef_types.h b/src/include/internal/cef_types.h similarity index 100% rename from cefpython/include/internal/cef_types.h rename to src/include/internal/cef_types.h diff --git a/cefpython/include/internal/cef_types_linux.h b/src/include/internal/cef_types_linux.h similarity index 100% rename from cefpython/include/internal/cef_types_linux.h rename to src/include/internal/cef_types_linux.h diff --git a/cefpython/include/internal/cef_types_mac.h b/src/include/internal/cef_types_mac.h similarity index 100% rename from cefpython/include/internal/cef_types_mac.h rename to src/include/internal/cef_types_mac.h diff --git a/cefpython/include/internal/cef_types_win.h b/src/include/internal/cef_types_win.h similarity index 100% rename from cefpython/include/internal/cef_types_win.h rename to src/include/internal/cef_types_win.h diff --git a/cefpython/include/internal/cef_types_wrappers.h b/src/include/internal/cef_types_wrappers.h similarity index 100% rename from cefpython/include/internal/cef_types_wrappers.h rename to src/include/internal/cef_types_wrappers.h diff --git a/cefpython/include/internal/cef_win.h b/src/include/internal/cef_win.h similarity index 100% rename from cefpython/include/internal/cef_win.h rename to src/include/internal/cef_win.h diff --git a/cefpython/include/wrapper/cef_byte_read_handler.h b/src/include/wrapper/cef_byte_read_handler.h similarity index 100% rename from cefpython/include/wrapper/cef_byte_read_handler.h rename to src/include/wrapper/cef_byte_read_handler.h diff --git a/cefpython/include/wrapper/cef_stream_resource_handler.h b/src/include/wrapper/cef_stream_resource_handler.h similarity index 100% rename from cefpython/include/wrapper/cef_stream_resource_handler.h rename to src/include/wrapper/cef_stream_resource_handler.h diff --git a/cefpython/include/wrapper/cef_xml_object.h b/src/include/wrapper/cef_xml_object.h similarity index 100% rename from cefpython/include/wrapper/cef_xml_object.h rename to src/include/wrapper/cef_xml_object.h diff --git a/cefpython/include/wrapper/cef_zip_archive.h b/src/include/wrapper/cef_zip_archive.h similarity index 100% rename from cefpython/include/wrapper/cef_zip_archive.h rename to src/include/wrapper/cef_zip_archive.h diff --git a/cefpython/javascript_bindings.pyx b/src/javascript_bindings.pyx similarity index 100% rename from cefpython/javascript_bindings.pyx rename to src/javascript_bindings.pyx diff --git a/cefpython/javascript_callback.pyx b/src/javascript_callback.pyx similarity index 100% rename from cefpython/javascript_callback.pyx rename to src/javascript_callback.pyx diff --git a/cefpython/javascript_dialog_handler.pyx b/src/javascript_dialog_handler.pyx similarity index 100% rename from cefpython/javascript_dialog_handler.pyx rename to src/javascript_dialog_handler.pyx diff --git a/cefpython/keyboard_handler.pyx b/src/keyboard_handler.pyx similarity index 100% rename from cefpython/keyboard_handler.pyx rename to src/keyboard_handler.pyx diff --git a/cefpython/lifespan_handler.pyx b/src/lifespan_handler.pyx similarity index 100% rename from cefpython/lifespan_handler.pyx rename to src/lifespan_handler.pyx diff --git a/cefpython/linux/.gitignore b/src/linux/.gitignore similarity index 100% rename from cefpython/linux/.gitignore rename to src/linux/.gitignore diff --git a/cefpython/linux/CEF-GTK-patch.txt b/src/linux/CEF-GTK-patch.txt similarity index 100% rename from cefpython/linux/CEF-GTK-patch.txt rename to src/linux/CEF-GTK-patch.txt diff --git a/cefpython/linux/binaries_32bit/LICENSE.txt b/src/linux/binaries_32bit/LICENSE.txt similarity index 100% rename from cefpython/linux/binaries_32bit/LICENSE.txt rename to src/linux/binaries_32bit/LICENSE.txt diff --git a/cefpython/linux/binaries_32bit/README.txt b/src/linux/binaries_32bit/README.txt similarity index 100% rename from cefpython/linux/binaries_32bit/README.txt rename to src/linux/binaries_32bit/README.txt diff --git a/cefpython/linux/binaries_32bit/example.html b/src/linux/binaries_32bit/example.html similarity index 100% rename from cefpython/linux/binaries_32bit/example.html rename to src/linux/binaries_32bit/example.html diff --git a/cefpython/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.css b/src/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.css similarity index 100% rename from cefpython/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.css rename to src/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.css diff --git a/cefpython/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.js b/src/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.js similarity index 100% rename from cefpython/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.js rename to src/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.js diff --git a/cefpython/linux/binaries_32bit/kivy-select-boxes/kivy-test.html b/src/linux/binaries_32bit/kivy-select-boxes/kivy-test.html similarity index 100% rename from cefpython/linux/binaries_32bit/kivy-select-boxes/kivy-test.html rename to src/linux/binaries_32bit/kivy-select-boxes/kivy-test.html diff --git a/cefpython/linux/binaries_32bit/kivy-select-boxes/readme.md b/src/linux/binaries_32bit/kivy-select-boxes/readme.md similarity index 100% rename from cefpython/linux/binaries_32bit/kivy-select-boxes/readme.md rename to src/linux/binaries_32bit/kivy-select-boxes/readme.md diff --git a/cefpython/linux/binaries_32bit/kivy_.py b/src/linux/binaries_32bit/kivy_.py similarity index 100% rename from cefpython/linux/binaries_32bit/kivy_.py rename to src/linux/binaries_32bit/kivy_.py diff --git a/cefpython/linux/binaries_32bit/prism.css b/src/linux/binaries_32bit/prism.css similarity index 100% rename from cefpython/linux/binaries_32bit/prism.css rename to src/linux/binaries_32bit/prism.css diff --git a/cefpython/linux/binaries_32bit/prism.js b/src/linux/binaries_32bit/prism.js similarity index 100% rename from cefpython/linux/binaries_32bit/prism.js rename to src/linux/binaries_32bit/prism.js diff --git a/cefpython/linux/binaries_32bit/pygtk_.py b/src/linux/binaries_32bit/pygtk_.py similarity index 100% rename from cefpython/linux/binaries_32bit/pygtk_.py rename to src/linux/binaries_32bit/pygtk_.py diff --git a/cefpython/linux/binaries_32bit/pyqt.py b/src/linux/binaries_32bit/pyqt.py similarity index 100% rename from cefpython/linux/binaries_32bit/pyqt.py rename to src/linux/binaries_32bit/pyqt.py diff --git a/cefpython/linux/binaries_32bit/wxpython-response.py b/src/linux/binaries_32bit/wxpython-response.py similarity index 100% rename from cefpython/linux/binaries_32bit/wxpython-response.py rename to src/linux/binaries_32bit/wxpython-response.py diff --git a/cefpython/linux/binaries_32bit/wxpython.html b/src/linux/binaries_32bit/wxpython.html similarity index 100% rename from cefpython/linux/binaries_32bit/wxpython.html rename to src/linux/binaries_32bit/wxpython.html diff --git a/cefpython/linux/binaries_32bit/wxpython.py b/src/linux/binaries_32bit/wxpython.py similarity index 100% rename from cefpython/linux/binaries_32bit/wxpython.py rename to src/linux/binaries_32bit/wxpython.py diff --git a/cefpython/linux/binaries_64bit/LICENSE.txt b/src/linux/binaries_64bit/LICENSE.txt similarity index 100% rename from cefpython/linux/binaries_64bit/LICENSE.txt rename to src/linux/binaries_64bit/LICENSE.txt diff --git a/cefpython/linux/binaries_64bit/README.txt b/src/linux/binaries_64bit/README.txt similarity index 100% rename from cefpython/linux/binaries_64bit/README.txt rename to src/linux/binaries_64bit/README.txt diff --git a/cefpython/linux/binaries_64bit/example.html b/src/linux/binaries_64bit/example.html similarity index 100% rename from cefpython/linux/binaries_64bit/example.html rename to src/linux/binaries_64bit/example.html diff --git a/cefpython/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.css b/src/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.css similarity index 100% rename from cefpython/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.css rename to src/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.css diff --git a/cefpython/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.js b/src/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.js similarity index 100% rename from cefpython/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.js rename to src/linux/binaries_64bit/kivy-select-boxes/kivy-selectBox.js diff --git a/cefpython/linux/binaries_64bit/kivy-select-boxes/kivy-test.html b/src/linux/binaries_64bit/kivy-select-boxes/kivy-test.html similarity index 100% rename from cefpython/linux/binaries_64bit/kivy-select-boxes/kivy-test.html rename to src/linux/binaries_64bit/kivy-select-boxes/kivy-test.html diff --git a/cefpython/linux/binaries_64bit/kivy-select-boxes/readme.md b/src/linux/binaries_64bit/kivy-select-boxes/readme.md similarity index 100% rename from cefpython/linux/binaries_64bit/kivy-select-boxes/readme.md rename to src/linux/binaries_64bit/kivy-select-boxes/readme.md diff --git a/cefpython/linux/binaries_64bit/kivy_.py b/src/linux/binaries_64bit/kivy_.py similarity index 100% rename from cefpython/linux/binaries_64bit/kivy_.py rename to src/linux/binaries_64bit/kivy_.py diff --git a/cefpython/linux/binaries_64bit/prism.css b/src/linux/binaries_64bit/prism.css similarity index 100% rename from cefpython/linux/binaries_64bit/prism.css rename to src/linux/binaries_64bit/prism.css diff --git a/cefpython/linux/binaries_64bit/prism.js b/src/linux/binaries_64bit/prism.js similarity index 100% rename from cefpython/linux/binaries_64bit/prism.js rename to src/linux/binaries_64bit/prism.js diff --git a/cefpython/linux/binaries_64bit/pygtk_.py b/src/linux/binaries_64bit/pygtk_.py similarity index 100% rename from cefpython/linux/binaries_64bit/pygtk_.py rename to src/linux/binaries_64bit/pygtk_.py diff --git a/cefpython/linux/binaries_64bit/pyqt.py b/src/linux/binaries_64bit/pyqt.py similarity index 100% rename from cefpython/linux/binaries_64bit/pyqt.py rename to src/linux/binaries_64bit/pyqt.py diff --git a/cefpython/linux/binaries_64bit/wxpython-response.py b/src/linux/binaries_64bit/wxpython-response.py similarity index 100% rename from cefpython/linux/binaries_64bit/wxpython-response.py rename to src/linux/binaries_64bit/wxpython-response.py diff --git a/cefpython/linux/binaries_64bit/wxpython.html b/src/linux/binaries_64bit/wxpython.html similarity index 100% rename from cefpython/linux/binaries_64bit/wxpython.html rename to src/linux/binaries_64bit/wxpython.html diff --git a/cefpython/linux/binaries_64bit/wxpython.py b/src/linux/binaries_64bit/wxpython.py similarity index 100% rename from cefpython/linux/binaries_64bit/wxpython.py rename to src/linux/binaries_64bit/wxpython.py diff --git a/cefpython/linux/compile.py b/src/linux/compile.py similarity index 100% rename from cefpython/linux/compile.py rename to src/linux/compile.py diff --git a/cefpython/linux/installer/.gitignore b/src/linux/installer/.gitignore similarity index 100% rename from cefpython/linux/installer/.gitignore rename to src/linux/installer/.gitignore diff --git a/cefpython/linux/installer/README.txt b/src/linux/installer/README.txt similarity index 100% rename from cefpython/linux/installer/README.txt rename to src/linux/installer/README.txt diff --git a/cefpython/linux/installer/__init__.py.template b/src/linux/installer/__init__.py.template similarity index 100% rename from cefpython/linux/installer/__init__.py.template rename to src/linux/installer/__init__.py.template diff --git a/cefpython/linux/installer/build-n-run-wx-chromectrl.sh b/src/linux/installer/build-n-run-wx-chromectrl.sh similarity index 100% rename from cefpython/linux/installer/build-n-run-wx-chromectrl.sh rename to src/linux/installer/build-n-run-wx-chromectrl.sh diff --git a/cefpython/linux/installer/debian.postinst b/src/linux/installer/debian.postinst similarity index 100% rename from cefpython/linux/installer/debian.postinst rename to src/linux/installer/debian.postinst diff --git a/cefpython/linux/installer/deps.txt b/src/linux/installer/deps.txt similarity index 100% rename from cefpython/linux/installer/deps.txt rename to src/linux/installer/deps.txt diff --git a/cefpython/linux/installer/find-deps.py b/src/linux/installer/find-deps.py similarity index 100% rename from cefpython/linux/installer/find-deps.py rename to src/linux/installer/find-deps.py diff --git a/cefpython/linux/installer/make-deb.py b/src/linux/installer/make-deb.py similarity index 100% rename from cefpython/linux/installer/make-deb.py rename to src/linux/installer/make-deb.py diff --git a/cefpython/linux/installer/make-setup.py b/src/linux/installer/make-setup.py similarity index 100% rename from cefpython/linux/installer/make-setup.py rename to src/linux/installer/make-setup.py diff --git a/cefpython/linux/installer/setup.cfg.template b/src/linux/installer/setup.cfg.template similarity index 100% rename from cefpython/linux/installer/setup.cfg.template rename to src/linux/installer/setup.cfg.template diff --git a/cefpython/linux/installer/setup.py.template b/src/linux/installer/setup.py.template similarity index 100% rename from cefpython/linux/installer/setup.py.template rename to src/linux/installer/setup.py.template diff --git a/cefpython/linux/installer/stdeb.cfg.template b/src/linux/installer/stdeb.cfg.template similarity index 100% rename from cefpython/linux/installer/stdeb.cfg.template rename to src/linux/installer/stdeb.cfg.template diff --git a/cefpython/linux/rebuild.sh b/src/linux/rebuild.sh similarity index 100% rename from cefpython/linux/rebuild.sh rename to src/linux/rebuild.sh diff --git a/cefpython/linux/setup/.gitignore b/src/linux/setup/.gitignore similarity index 100% rename from cefpython/linux/setup/.gitignore rename to src/linux/setup/.gitignore diff --git a/cefpython/linux/setup/cefpython.h b/src/linux/setup/cefpython.h similarity index 100% rename from cefpython/linux/setup/cefpython.h rename to src/linux/setup/cefpython.h diff --git a/cefpython/linux/setup/fix_pyx_files.py b/src/linux/setup/fix_pyx_files.py similarity index 100% rename from cefpython/linux/setup/fix_pyx_files.py rename to src/linux/setup/fix_pyx_files.py diff --git a/cefpython/linux/setup/setup.py b/src/linux/setup/setup.py similarity index 100% rename from cefpython/linux/setup/setup.py rename to src/linux/setup/setup.py diff --git a/cefpython/linux/wxpython.sh b/src/linux/wxpython.sh similarity index 100% rename from cefpython/linux/wxpython.sh rename to src/linux/wxpython.sh diff --git a/cefpython/load_handler.pyx b/src/load_handler.pyx similarity index 100% rename from cefpython/load_handler.pyx rename to src/load_handler.pyx diff --git a/cefpython/mac/.gitignore b/src/mac/.gitignore similarity index 100% rename from cefpython/mac/.gitignore rename to src/mac/.gitignore diff --git a/cefpython/mac/binaries_32bit/prism.css b/src/mac/binaries_32bit/prism.css similarity index 100% rename from cefpython/mac/binaries_32bit/prism.css rename to src/mac/binaries_32bit/prism.css diff --git a/cefpython/mac/binaries_32bit/prism.js b/src/mac/binaries_32bit/prism.js similarity index 100% rename from cefpython/mac/binaries_32bit/prism.js rename to src/mac/binaries_32bit/prism.js diff --git a/cefpython/mac/binaries_32bit/wxpython.html b/src/mac/binaries_32bit/wxpython.html similarity index 100% rename from cefpython/mac/binaries_32bit/wxpython.html rename to src/mac/binaries_32bit/wxpython.html diff --git a/cefpython/mac/binaries_32bit/wxpython.py b/src/mac/binaries_32bit/wxpython.py similarity index 100% rename from cefpython/mac/binaries_32bit/wxpython.py rename to src/mac/binaries_32bit/wxpython.py diff --git a/cefpython/mac/binaries_64bit/prism.css b/src/mac/binaries_64bit/prism.css similarity index 100% rename from cefpython/mac/binaries_64bit/prism.css rename to src/mac/binaries_64bit/prism.css diff --git a/cefpython/mac/binaries_64bit/prism.js b/src/mac/binaries_64bit/prism.js similarity index 100% rename from cefpython/mac/binaries_64bit/prism.js rename to src/mac/binaries_64bit/prism.js diff --git a/cefpython/mac/binaries_64bit/wxpython.html b/src/mac/binaries_64bit/wxpython.html similarity index 100% rename from cefpython/mac/binaries_64bit/wxpython.html rename to src/mac/binaries_64bit/wxpython.html diff --git a/cefpython/mac/binaries_64bit/wxpython.py b/src/mac/binaries_64bit/wxpython.py similarity index 100% rename from cefpython/mac/binaries_64bit/wxpython.py rename to src/mac/binaries_64bit/wxpython.py diff --git a/cefpython/mac/compile.py b/src/mac/compile.py similarity index 100% rename from cefpython/mac/compile.py rename to src/mac/compile.py diff --git a/cefpython/mac/installer/.gitignore b/src/mac/installer/.gitignore similarity index 100% rename from cefpython/mac/installer/.gitignore rename to src/mac/installer/.gitignore diff --git a/cefpython/mac/installer/__init__.py.template b/src/mac/installer/__init__.py.template similarity index 100% rename from cefpython/mac/installer/__init__.py.template rename to src/mac/installer/__init__.py.template diff --git a/cefpython/mac/installer/build_all.sh b/src/mac/installer/build_all.sh similarity index 100% rename from cefpython/mac/installer/build_all.sh rename to src/mac/installer/build_all.sh diff --git a/cefpython/mac/installer/build_run_chromectrl.sh b/src/mac/installer/build_run_chromectrl.sh similarity index 100% rename from cefpython/mac/installer/build_run_chromectrl.sh rename to src/mac/installer/build_run_chromectrl.sh diff --git a/cefpython/mac/installer/make-setup.py b/src/mac/installer/make-setup.py similarity index 100% rename from cefpython/mac/installer/make-setup.py rename to src/mac/installer/make-setup.py diff --git a/cefpython/mac/installer/setup.py.template b/src/mac/installer/setup.py.template similarity index 100% rename from cefpython/mac/installer/setup.py.template rename to src/mac/installer/setup.py.template diff --git a/cefpython/mac/mac32.sh b/src/mac/mac32.sh similarity index 100% rename from cefpython/mac/mac32.sh rename to src/mac/mac32.sh diff --git a/cefpython/mac/mac64.sh b/src/mac/mac64.sh similarity index 100% rename from cefpython/mac/mac64.sh rename to src/mac/mac64.sh diff --git a/cefpython/mac/setup/.gitignore b/src/mac/setup/.gitignore similarity index 100% rename from cefpython/mac/setup/.gitignore rename to src/mac/setup/.gitignore diff --git a/cefpython/mac/setup/cefpython.h b/src/mac/setup/cefpython.h similarity index 100% rename from cefpython/mac/setup/cefpython.h rename to src/mac/setup/cefpython.h diff --git a/cefpython/mac/setup/fix_pyx_files.py b/src/mac/setup/fix_pyx_files.py similarity index 100% rename from cefpython/mac/setup/fix_pyx_files.py rename to src/mac/setup/fix_pyx_files.py diff --git a/cefpython/mac/setup/lib_32bit/README b/src/mac/setup/lib_32bit/README similarity index 100% rename from cefpython/mac/setup/lib_32bit/README rename to src/mac/setup/lib_32bit/README diff --git a/cefpython/mac/setup/lib_64bit/README b/src/mac/setup/lib_64bit/README similarity index 100% rename from cefpython/mac/setup/lib_64bit/README rename to src/mac/setup/lib_64bit/README diff --git a/cefpython/mac/setup/setup.py b/src/mac/setup/setup.py similarity index 100% rename from cefpython/mac/setup/setup.py rename to src/mac/setup/setup.py diff --git a/cefpython/network_error.pyx b/src/network_error.pyx similarity index 100% rename from cefpython/network_error.pyx rename to src/network_error.pyx diff --git a/cefpython/paint_buffer.pyx b/src/paint_buffer.pyx similarity index 100% rename from cefpython/paint_buffer.pyx rename to src/paint_buffer.pyx diff --git a/cefpython/process_message_utils.pyx b/src/process_message_utils.pyx similarity index 100% rename from cefpython/process_message_utils.pyx rename to src/process_message_utils.pyx diff --git a/cefpython/python_callback.pyx b/src/python_callback.pyx similarity index 100% rename from cefpython/python_callback.pyx rename to src/python_callback.pyx diff --git a/cefpython/render_handler.pyx b/src/render_handler.pyx similarity index 100% rename from cefpython/render_handler.pyx rename to src/render_handler.pyx diff --git a/cefpython/request.pyx b/src/request.pyx similarity index 100% rename from cefpython/request.pyx rename to src/request.pyx diff --git a/cefpython/request_handler.pyx b/src/request_handler.pyx similarity index 100% rename from cefpython/request_handler.pyx rename to src/request_handler.pyx diff --git a/cefpython/resource_handler.pyx b/src/resource_handler.pyx similarity index 100% rename from cefpython/resource_handler.pyx rename to src/resource_handler.pyx diff --git a/cefpython/response.pyx b/src/response.pyx similarity index 100% rename from cefpython/response.pyx rename to src/response.pyx diff --git a/cefpython/settings.pyx b/src/settings.pyx similarity index 100% rename from cefpython/settings.pyx rename to src/settings.pyx diff --git a/cefpython/string_utils.pyx b/src/string_utils.pyx similarity index 100% rename from cefpython/string_utils.pyx rename to src/string_utils.pyx diff --git a/cefpython/string_utils_win.pyx b/src/string_utils_win.pyx similarity index 100% rename from cefpython/string_utils_win.pyx rename to src/string_utils_win.pyx diff --git a/cefpython/string_visitor.pyx b/src/string_visitor.pyx similarity index 100% rename from cefpython/string_visitor.pyx rename to src/string_visitor.pyx diff --git a/cefpython/subprocess/.gitignore b/src/subprocess/.gitignore similarity index 100% rename from cefpython/subprocess/.gitignore rename to src/subprocess/.gitignore diff --git a/cefpython/subprocess/Makefile b/src/subprocess/Makefile similarity index 100% rename from cefpython/subprocess/Makefile rename to src/subprocess/Makefile diff --git a/cefpython/subprocess/Makefile-libcefpythonapp b/src/subprocess/Makefile-libcefpythonapp similarity index 100% rename from cefpython/subprocess/Makefile-libcefpythonapp rename to src/subprocess/Makefile-libcefpythonapp diff --git a/cefpython/subprocess/cefpython_app.cpp b/src/subprocess/cefpython_app.cpp similarity index 100% rename from cefpython/subprocess/cefpython_app.cpp rename to src/subprocess/cefpython_app.cpp diff --git a/cefpython/subprocess/cefpython_app.h b/src/subprocess/cefpython_app.h similarity index 100% rename from cefpython/subprocess/cefpython_app.h rename to src/subprocess/cefpython_app.h diff --git a/cefpython/subprocess/javascript_callback.cpp b/src/subprocess/javascript_callback.cpp similarity index 100% rename from cefpython/subprocess/javascript_callback.cpp rename to src/subprocess/javascript_callback.cpp diff --git a/cefpython/subprocess/javascript_callback.h b/src/subprocess/javascript_callback.h similarity index 100% rename from cefpython/subprocess/javascript_callback.h rename to src/subprocess/javascript_callback.h diff --git a/cefpython/subprocess/libcefpythonapp_py27_32bit.vcproj b/src/subprocess/libcefpythonapp_py27_32bit.vcproj similarity index 100% rename from cefpython/subprocess/libcefpythonapp_py27_32bit.vcproj rename to src/subprocess/libcefpythonapp_py27_32bit.vcproj diff --git a/cefpython/subprocess/libcefpythonapp_py27_64bit.vcproj b/src/subprocess/libcefpythonapp_py27_64bit.vcproj similarity index 100% rename from cefpython/subprocess/libcefpythonapp_py27_64bit.vcproj rename to src/subprocess/libcefpythonapp_py27_64bit.vcproj diff --git a/cefpython/subprocess/libcefpythonapp_py34_32bit.vcproj b/src/subprocess/libcefpythonapp_py34_32bit.vcproj similarity index 100% rename from cefpython/subprocess/libcefpythonapp_py34_32bit.vcproj rename to src/subprocess/libcefpythonapp_py34_32bit.vcproj diff --git a/cefpython/subprocess/main.cpp b/src/subprocess/main.cpp similarity index 100% rename from cefpython/subprocess/main.cpp rename to src/subprocess/main.cpp diff --git a/cefpython/subprocess/subprocess_32bit.vcproj b/src/subprocess/subprocess_32bit.vcproj similarity index 100% rename from cefpython/subprocess/subprocess_32bit.vcproj rename to src/subprocess/subprocess_32bit.vcproj diff --git a/cefpython/subprocess/subprocess_64bit.vcproj b/src/subprocess/subprocess_64bit.vcproj similarity index 100% rename from cefpython/subprocess/subprocess_64bit.vcproj rename to src/subprocess/subprocess_64bit.vcproj diff --git a/cefpython/subprocess/v8function_handler.cpp b/src/subprocess/v8function_handler.cpp similarity index 100% rename from cefpython/subprocess/v8function_handler.cpp rename to src/subprocess/v8function_handler.cpp diff --git a/cefpython/subprocess/v8function_handler.h b/src/subprocess/v8function_handler.h similarity index 100% rename from cefpython/subprocess/v8function_handler.h rename to src/subprocess/v8function_handler.h diff --git a/cefpython/subprocess/v8utils.cpp b/src/subprocess/v8utils.cpp similarity index 100% rename from cefpython/subprocess/v8utils.cpp rename to src/subprocess/v8utils.cpp diff --git a/cefpython/subprocess/v8utils.h b/src/subprocess/v8utils.h similarity index 100% rename from cefpython/subprocess/v8utils.h rename to src/subprocess/v8utils.h diff --git a/cefpython/task.pyx b/src/task.pyx similarity index 100% rename from cefpython/task.pyx rename to src/task.pyx diff --git a/cefpython/time_utils.pyx b/src/time_utils.pyx similarity index 100% rename from cefpython/time_utils.pyx rename to src/time_utils.pyx diff --git a/cefpython/util.h b/src/util.h similarity index 100% rename from cefpython/util.h rename to src/util.h diff --git a/cefpython/utils.pyx b/src/utils.pyx similarity index 100% rename from cefpython/utils.pyx rename to src/utils.pyx diff --git a/cefpython/v8context_handler.pyx b/src/v8context_handler.pyx similarity index 100% rename from cefpython/v8context_handler.pyx rename to src/v8context_handler.pyx diff --git a/cefpython/v8function_handler.pyx b/src/v8function_handler.pyx similarity index 100% rename from cefpython/v8function_handler.pyx rename to src/v8function_handler.pyx diff --git a/cefpython/virtual_keys.pyx b/src/virtual_keys.pyx similarity index 100% rename from cefpython/virtual_keys.pyx rename to src/virtual_keys.pyx diff --git a/cefpython/web_plugin_info.pyx b/src/web_plugin_info.pyx similarity index 100% rename from cefpython/web_plugin_info.pyx rename to src/web_plugin_info.pyx diff --git a/cefpython/web_request.pyx b/src/web_request.pyx similarity index 100% rename from cefpython/web_request.pyx rename to src/web_request.pyx diff --git a/cefpython/window_info.pyx b/src/window_info.pyx similarity index 100% rename from cefpython/window_info.pyx rename to src/window_info.pyx diff --git a/cefpython/window_utils_linux.pyx b/src/window_utils_linux.pyx similarity index 100% rename from cefpython/window_utils_linux.pyx rename to src/window_utils_linux.pyx diff --git a/cefpython/window_utils_mac.pyx b/src/window_utils_mac.pyx similarity index 100% rename from cefpython/window_utils_mac.pyx rename to src/window_utils_mac.pyx diff --git a/cefpython/window_utils_win.pyx b/src/window_utils_win.pyx similarity index 100% rename from cefpython/window_utils_win.pyx rename to src/window_utils_win.pyx diff --git a/cefpython/windows/.gitignore b/src/windows/.gitignore similarity index 100% rename from cefpython/windows/.gitignore rename to src/windows/.gitignore diff --git a/cefpython/windows/binaries_32bit/LICENSE.txt b/src/windows/binaries_32bit/LICENSE.txt similarity index 100% rename from cefpython/windows/binaries_32bit/LICENSE.txt rename to src/windows/binaries_32bit/LICENSE.txt diff --git a/cefpython/windows/binaries_32bit/README.txt b/src/windows/binaries_32bit/README.txt similarity index 100% rename from cefpython/windows/binaries_32bit/README.txt rename to src/windows/binaries_32bit/README.txt diff --git a/cefpython/windows/binaries_32bit/cefwindow.py b/src/windows/binaries_32bit/cefwindow.py similarity index 100% rename from cefpython/windows/binaries_32bit/cefwindow.py rename to src/windows/binaries_32bit/cefwindow.py diff --git a/cefpython/windows/binaries_32bit/example.html b/src/windows/binaries_32bit/example.html similarity index 100% rename from cefpython/windows/binaries_32bit/example.html rename to src/windows/binaries_32bit/example.html diff --git a/cefpython/windows/binaries_32bit/icon.ico b/src/windows/binaries_32bit/icon.ico similarity index 100% rename from cefpython/windows/binaries_32bit/icon.ico rename to src/windows/binaries_32bit/icon.ico diff --git a/cefpython/windows/binaries_32bit/prism.css b/src/windows/binaries_32bit/prism.css similarity index 100% rename from cefpython/windows/binaries_32bit/prism.css rename to src/windows/binaries_32bit/prism.css diff --git a/cefpython/windows/binaries_32bit/prism.js b/src/windows/binaries_32bit/prism.js similarity index 100% rename from cefpython/windows/binaries_32bit/prism.js rename to src/windows/binaries_32bit/prism.js diff --git a/cefpython/windows/binaries_32bit/pygtk_.py b/src/windows/binaries_32bit/pygtk_.py similarity index 100% rename from cefpython/windows/binaries_32bit/pygtk_.py rename to src/windows/binaries_32bit/pygtk_.py diff --git a/cefpython/windows/binaries_32bit/pyqt.py b/src/windows/binaries_32bit/pyqt.py similarity index 100% rename from cefpython/windows/binaries_32bit/pyqt.py rename to src/windows/binaries_32bit/pyqt.py diff --git a/cefpython/windows/binaries_32bit/pyside.py b/src/windows/binaries_32bit/pyside.py similarity index 100% rename from cefpython/windows/binaries_32bit/pyside.py rename to src/windows/binaries_32bit/pyside.py diff --git a/cefpython/windows/binaries_32bit/pywin32.py b/src/windows/binaries_32bit/pywin32.py similarity index 100% rename from cefpython/windows/binaries_32bit/pywin32.py rename to src/windows/binaries_32bit/pywin32.py diff --git a/cefpython/windows/binaries_32bit/smoke.css b/src/windows/binaries_32bit/smoke.css similarity index 100% rename from cefpython/windows/binaries_32bit/smoke.css rename to src/windows/binaries_32bit/smoke.css diff --git a/cefpython/windows/binaries_32bit/smoke.min.js b/src/windows/binaries_32bit/smoke.min.js similarity index 100% rename from cefpython/windows/binaries_32bit/smoke.min.js rename to src/windows/binaries_32bit/smoke.min.js diff --git a/cefpython/windows/binaries_32bit/wxpython.html b/src/windows/binaries_32bit/wxpython.html similarity index 100% rename from cefpython/windows/binaries_32bit/wxpython.html rename to src/windows/binaries_32bit/wxpython.html diff --git a/cefpython/windows/binaries_32bit/wxpython.py b/src/windows/binaries_32bit/wxpython.py similarity index 100% rename from cefpython/windows/binaries_32bit/wxpython.py rename to src/windows/binaries_32bit/wxpython.py diff --git a/cefpython/windows/binaries_64bit/LICENSE.txt b/src/windows/binaries_64bit/LICENSE.txt similarity index 100% rename from cefpython/windows/binaries_64bit/LICENSE.txt rename to src/windows/binaries_64bit/LICENSE.txt diff --git a/cefpython/windows/binaries_64bit/README.txt b/src/windows/binaries_64bit/README.txt similarity index 100% rename from cefpython/windows/binaries_64bit/README.txt rename to src/windows/binaries_64bit/README.txt diff --git a/cefpython/windows/binaries_64bit/cefwindow.py b/src/windows/binaries_64bit/cefwindow.py similarity index 100% rename from cefpython/windows/binaries_64bit/cefwindow.py rename to src/windows/binaries_64bit/cefwindow.py diff --git a/cefpython/windows/binaries_64bit/example.html b/src/windows/binaries_64bit/example.html similarity index 100% rename from cefpython/windows/binaries_64bit/example.html rename to src/windows/binaries_64bit/example.html diff --git a/cefpython/windows/binaries_64bit/icon.ico b/src/windows/binaries_64bit/icon.ico similarity index 100% rename from cefpython/windows/binaries_64bit/icon.ico rename to src/windows/binaries_64bit/icon.ico diff --git a/cefpython/windows/binaries_64bit/prism.css b/src/windows/binaries_64bit/prism.css similarity index 100% rename from cefpython/windows/binaries_64bit/prism.css rename to src/windows/binaries_64bit/prism.css diff --git a/cefpython/windows/binaries_64bit/prism.js b/src/windows/binaries_64bit/prism.js similarity index 100% rename from cefpython/windows/binaries_64bit/prism.js rename to src/windows/binaries_64bit/prism.js diff --git a/cefpython/windows/binaries_64bit/pygtk_.py b/src/windows/binaries_64bit/pygtk_.py similarity index 100% rename from cefpython/windows/binaries_64bit/pygtk_.py rename to src/windows/binaries_64bit/pygtk_.py diff --git a/cefpython/windows/binaries_64bit/pyqt.py b/src/windows/binaries_64bit/pyqt.py similarity index 100% rename from cefpython/windows/binaries_64bit/pyqt.py rename to src/windows/binaries_64bit/pyqt.py diff --git a/cefpython/windows/binaries_64bit/pyside.py b/src/windows/binaries_64bit/pyside.py similarity index 100% rename from cefpython/windows/binaries_64bit/pyside.py rename to src/windows/binaries_64bit/pyside.py diff --git a/cefpython/windows/binaries_64bit/pywin32.py b/src/windows/binaries_64bit/pywin32.py similarity index 100% rename from cefpython/windows/binaries_64bit/pywin32.py rename to src/windows/binaries_64bit/pywin32.py diff --git a/cefpython/windows/binaries_64bit/smoke.css b/src/windows/binaries_64bit/smoke.css similarity index 100% rename from cefpython/windows/binaries_64bit/smoke.css rename to src/windows/binaries_64bit/smoke.css diff --git a/cefpython/windows/binaries_64bit/smoke.min.js b/src/windows/binaries_64bit/smoke.min.js similarity index 100% rename from cefpython/windows/binaries_64bit/smoke.min.js rename to src/windows/binaries_64bit/smoke.min.js diff --git a/cefpython/windows/binaries_64bit/wxpython.html b/src/windows/binaries_64bit/wxpython.html similarity index 100% rename from cefpython/windows/binaries_64bit/wxpython.html rename to src/windows/binaries_64bit/wxpython.html diff --git a/cefpython/windows/binaries_64bit/wxpython.py b/src/windows/binaries_64bit/wxpython.py similarity index 100% rename from cefpython/windows/binaries_64bit/wxpython.py rename to src/windows/binaries_64bit/wxpython.py diff --git a/cefpython/windows/cefpython.rc b/src/windows/cefpython.rc similarity index 100% rename from cefpython/windows/cefpython.rc rename to src/windows/cefpython.rc diff --git a/cefpython/windows/compile.bat b/src/windows/compile.bat similarity index 100% rename from cefpython/windows/compile.bat rename to src/windows/compile.bat diff --git a/cefpython/windows/compile.cmd b/src/windows/compile.cmd similarity index 100% rename from cefpython/windows/compile.cmd rename to src/windows/compile.cmd diff --git a/cefpython/windows/installer/.gitignore b/src/windows/installer/.gitignore similarity index 100% rename from cefpython/windows/installer/.gitignore rename to src/windows/installer/.gitignore diff --git a/cefpython/windows/installer/README.txt b/src/windows/installer/README.txt similarity index 100% rename from cefpython/windows/installer/README.txt rename to src/windows/installer/README.txt diff --git a/cefpython/windows/installer/__init__.py.template b/src/windows/installer/__init__.py.template similarity index 100% rename from cefpython/windows/installer/__init__.py.template rename to src/windows/installer/__init__.py.template diff --git a/cefpython/windows/installer/build_all.bat b/src/windows/installer/build_all.bat similarity index 100% rename from cefpython/windows/installer/build_all.bat rename to src/windows/installer/build_all.bat diff --git a/cefpython/windows/installer/innosetup.template b/src/windows/installer/innosetup.template similarity index 100% rename from cefpython/windows/installer/innosetup.template rename to src/windows/installer/innosetup.template diff --git a/cefpython/windows/installer/make-installer.py b/src/windows/installer/make-installer.py similarity index 100% rename from cefpython/windows/installer/make-installer.py rename to src/windows/installer/make-installer.py diff --git a/cefpython/windows/installer/make-setup.py b/src/windows/installer/make-setup.py similarity index 100% rename from cefpython/windows/installer/make-setup.py rename to src/windows/installer/make-setup.py diff --git a/cefpython/windows/installer/setup.cfg.template b/src/windows/installer/setup.cfg.template similarity index 100% rename from cefpython/windows/installer/setup.cfg.template rename to src/windows/installer/setup.cfg.template diff --git a/cefpython/windows/installer/setup.py.template b/src/windows/installer/setup.py.template similarity index 100% rename from cefpython/windows/installer/setup.py.template rename to src/windows/installer/setup.py.template diff --git a/cefpython/windows/setup/.gitignore b/src/windows/setup/.gitignore similarity index 100% rename from cefpython/windows/setup/.gitignore rename to src/windows/setup/.gitignore diff --git a/cefpython/windows/setup/cefpython.h b/src/windows/setup/cefpython.h similarity index 100% rename from cefpython/windows/setup/cefpython.h rename to src/windows/setup/cefpython.h diff --git a/cefpython/windows/setup/compile_rc.py b/src/windows/setup/compile_rc.py similarity index 100% rename from cefpython/windows/setup/compile_rc.py rename to src/windows/setup/compile_rc.py diff --git a/cefpython/windows/setup/delete_pyx_files.bat b/src/windows/setup/delete_pyx_files.bat similarity index 100% rename from cefpython/windows/setup/delete_pyx_files.bat rename to src/windows/setup/delete_pyx_files.bat diff --git a/cefpython/windows/setup/fix_cefpython_h.py b/src/windows/setup/fix_cefpython_h.py similarity index 100% rename from cefpython/windows/setup/fix_cefpython_h.py rename to src/windows/setup/fix_cefpython_h.py diff --git a/cefpython/windows/setup/fix_pyx_files.py b/src/windows/setup/fix_pyx_files.py similarity index 100% rename from cefpython/windows/setup/fix_pyx_files.py rename to src/windows/setup/fix_pyx_files.py diff --git a/cefpython/windows/setup/lib_32bit/README b/src/windows/setup/lib_32bit/README similarity index 100% rename from cefpython/windows/setup/lib_32bit/README rename to src/windows/setup/lib_32bit/README diff --git a/cefpython/windows/setup/lib_64bit/README b/src/windows/setup/lib_64bit/README similarity index 100% rename from cefpython/windows/setup/lib_64bit/README rename to src/windows/setup/lib_64bit/README diff --git a/cefpython/windows/setup/setup.py b/src/windows/setup/setup.py similarity index 100% rename from cefpython/windows/setup/setup.py rename to src/windows/setup/setup.py diff --git a/cefpython/windows/stdint.h b/src/windows/stdint.h similarity index 100% rename from cefpython/windows/stdint.h rename to src/windows/stdint.h diff --git a/cefpython/windows/wxpython.bat b/src/windows/wxpython.bat similarity index 100% rename from cefpython/windows/wxpython.bat rename to src/windows/wxpython.bat diff --git a/cefpython/wx/README.txt b/src/wx/README.txt similarity index 100% rename from cefpython/wx/README.txt rename to src/wx/README.txt diff --git a/cefpython/wx/__init__.py b/src/wx/__init__.py similarity index 100% rename from cefpython/wx/__init__.py rename to src/wx/__init__.py diff --git a/cefpython/wx/chromectrl.py b/src/wx/chromectrl.py similarity index 100% rename from cefpython/wx/chromectrl.py rename to src/wx/chromectrl.py diff --git a/cefpython/wx/examples/back.png b/src/wx/examples/back.png similarity index 100% rename from cefpython/wx/examples/back.png rename to src/wx/examples/back.png diff --git a/cefpython/wx/examples/forward.png b/src/wx/examples/forward.png similarity index 100% rename from cefpython/wx/examples/forward.png rename to src/wx/examples/forward.png diff --git a/cefpython/wx/examples/reload_page.png b/src/wx/examples/reload_page.png similarity index 100% rename from cefpython/wx/examples/reload_page.png rename to src/wx/examples/reload_page.png diff --git a/cefpython/wx/examples/sample1.html b/src/wx/examples/sample1.html similarity index 100% rename from cefpython/wx/examples/sample1.html rename to src/wx/examples/sample1.html diff --git a/cefpython/wx/examples/sample1.py b/src/wx/examples/sample1.py similarity index 100% rename from cefpython/wx/examples/sample1.py rename to src/wx/examples/sample1.py diff --git a/cefpython/wx/examples/sample2.py b/src/wx/examples/sample2.py similarity index 100% rename from cefpython/wx/examples/sample2.py rename to src/wx/examples/sample2.py diff --git a/cefpython/wx/examples/sample3.py b/src/wx/examples/sample3.py similarity index 100% rename from cefpython/wx/examples/sample3.py rename to src/wx/examples/sample3.py diff --git a/cefpython/wx/images/back.png b/src/wx/images/back.png similarity index 100% rename from cefpython/wx/images/back.png rename to src/wx/images/back.png diff --git a/cefpython/wx/images/forward.png b/src/wx/images/forward.png similarity index 100% rename from cefpython/wx/images/forward.png rename to src/wx/images/forward.png diff --git a/cefpython/wx/images/reload_page.png b/src/wx/images/reload_page.png similarity index 100% rename from cefpython/wx/images/reload_page.png rename to src/wx/images/reload_page.png diff --git a/cefpython/wx/utils.py b/src/wx/utils.py similarity index 100% rename from cefpython/wx/utils.py rename to src/wx/utils.py From 6b8636a01b4be699ea6e8c75d65269607159e348 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 25 May 2016 10:35:33 +0200 Subject: [PATCH 045/557] Update README - master branch is a work in progress. --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1f855ce6c..d1acfc232 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,11 @@ [![](https://img.shields.io/badge/pypi-v31.2-blue.svg "PyPI latest release")](https://pypi.python.org/pypi/cefpython3/) [![](https://img.shields.io/badge/commits%20since-v31.2-lightgray.svg "Commits since v31.2 release")](https://github.com/cztomczak/cefpython/compare/05366f2...master) -__NOTE__: Repository rewritten on 2016-02-15 to reduce its size. +__NOTES__: +* Repository rewritten on 2016-02-15 to reduce its size. Please clone it again. +* Master branch is a work in progress. When building use the cefpython31 + branch. Table of contents: * [Introduction](#introduction) From d9bbf7c905ec91f5c852acbbdc2b4c9313c9aad6 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Thu, 26 May 2016 07:29:40 +0200 Subject: [PATCH 046/557] Temporary fix for possible errors on shutdown, see comment. --- src/cefpython.pyx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/cefpython.pyx b/src/cefpython.pyx index 75c923944..6b11ad513 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -449,6 +449,13 @@ def Shutdown(): Debug("Shutdown()") with nogil: CefShutdown() + # Temporary fix for possible errors on shutdown. See this post: + # https://magpcss.org/ceforum/viewtopic.php?p=30858#p30858 + # May be fixed by host owned message loop, see Issue 1805: + # https://bitbucket.org/chromiumembedded/cef/issues/1805/ + for i in range(10): + CefDoMessageLoopWork() + def SetOsModalLoop(py_bool modalLoop): cdef cpp_bool cefModalLoop = bool(modalLoop) From 8d2c1e73720a20cadfab45e42a66a39e5bf06620 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Thu, 26 May 2016 07:46:48 +0200 Subject: [PATCH 047/557] Improve fix for possible errors on shutdown (previous commit). --- src/cefpython.pyx | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/cefpython.pyx b/src/cefpython.pyx index 6b11ad513..53bbe4a7c 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -118,6 +118,8 @@ g_debugFile = "debug.log" g_applicationSettings = {} g_commandLineSwitches = {} +_MessageLoopWork_wasused = False + cdef dict g_globalClientCallbacks = {} # If ApplicationSettings.unique_request_context_per_browser is False @@ -428,6 +430,10 @@ def MessageLoopWork(): # GIL must be released here otherwise we will get dead lock # when calling from c++ to python. + if not _MessageLoopWork_wasused: + global _MessageLoopWork_wasused + _MessageLoopWork_wasused = True + with nogil: CefDoMessageLoopWork(); @@ -448,13 +454,18 @@ def Shutdown(): g_sharedRequestContext.Assign(NULL) Debug("Shutdown()") with nogil: - CefShutdown() # Temporary fix for possible errors on shutdown. See this post: # https://magpcss.org/ceforum/viewtopic.php?p=30858#p30858 # May be fixed by host owned message loop, see Issue 1805: # https://bitbucket.org/chromiumembedded/cef/issues/1805/ - for i in range(10): - CefDoMessageLoopWork() + if _MessageLoopWork_wasused: + for i in range(10): + CefDoMessageLoopWork() + CefShutdown() + if _MessageLoopWork_wasused: + for i in range(10): + CefDoMessageLoopWork() + def SetOsModalLoop(py_bool modalLoop): From 2579b3986b0a868a6ddc1d7b0eaa4c7de7714c65 Mon Sep 17 00:00:00 2001 From: Czarek Tomczak Date: Mon, 30 May 2016 16:07:57 +0200 Subject: [PATCH 048/557] Update README.md Change badges from SVG to PNG so that they display correctly in Chrome on Linux. --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d1acfc232..4cca9dfd6 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # CEF Python -[![](https://img.shields.io/badge/python-2.7-yellow.svg "Python versions supported")](https://github.com/cztomczak/cefpython#cef-python) -[![](https://img.shields.io/badge/release-v31.2-orange.svg "GitHub latest release")](https://github.com/cztomczak/cefpython/releases/latest) -[![](https://img.shields.io/badge/pypi-v31.2-blue.svg "PyPI latest release")](https://pypi.python.org/pypi/cefpython3/) -[![](https://img.shields.io/badge/commits%20since-v31.2-lightgray.svg "Commits since v31.2 release")](https://github.com/cztomczak/cefpython/compare/05366f2...master) +[![](https://img.shields.io/badge/python-2.7-yellow.png "Python versions supported")](https://github.com/cztomczak/cefpython#cef-python) +[![](https://img.shields.io/badge/release-v31.2-orange.png "GitHub latest release")](https://github.com/cztomczak/cefpython/releases/latest) +[![](https://img.shields.io/badge/pypi-v31.2-blue.png "PyPI latest release")](https://pypi.python.org/pypi/cefpython3/) +[![](https://img.shields.io/badge/commits%20since-v31.2-lightgray.png "Commits since v31.2 release")](https://github.com/cztomczak/cefpython/compare/05366f2...master) __NOTES__: * Repository rewritten on 2016-02-15 to reduce its size. From 349db55ac1911208d8fc63f26a39a398a910bc09 Mon Sep 17 00:00:00 2001 From: Czarek Tomczak Date: Thu, 2 Jun 2016 06:38:25 +0200 Subject: [PATCH 049/557] Update Frame.md - LoadString and data uris --- api/Frame.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/api/Frame.md b/api/Frame.md index 013bf1f02..33627c4e8 100644 --- a/api/Frame.md +++ b/api/Frame.md @@ -218,9 +218,15 @@ True if this object is currently attached to a valid frame. | url | string | | __Return__ | void | +NOTE: LoadString is problematic due to the multi-process model and the need +to create a render process (which does not happen with LoadString). It is +best to use instead LoadUrl with a data uri, e.g. `LoadUrl("data:text/html,some+html+code+here")`. +Take also a look at a [custom resource handler](ResourceHandler.md). + Load the contents of |value| with the specified dummy |url|. |url| should have a standard scheme (for example, http scheme) or behaviors like -link clicks and web security restrictions may not behave as expected. LoadString() can be called only after the Renderer process has been created. +link clicks and web security restrictions may not behave as expected. +LoadString() can be called only after the Renderer process has been created. ### LoadUrl From ef401b3392f589f9546a8de178a781a1217227fc Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 20 Jun 2016 09:53:56 +0200 Subject: [PATCH 050/557] Create patches/ and tools/ directories - moved from pycef --- patches/include.gypi | 5 + patches/issue125_win_mac_linux | 5 + patches/issue125_win_mac_linux.patch | 14 + patches/issue218_linux | 5 + patches/issue218_linux.patch | 58 ++ patches/issue73_linux | 4 + patches/patch.py | 18 + tools/apidocs.py | 81 ++ tools/automate-git.py | 1069 ++++++++++++++++++++++++++ tools/automate-git.py.patch | 105 +++ tools/automate.py | 479 ++++++++++++ tools/requirements.txt | 2 + tools/toc.py | 166 ++++ 13 files changed, 2011 insertions(+) create mode 100644 patches/include.gypi create mode 100644 patches/issue125_win_mac_linux create mode 100644 patches/issue125_win_mac_linux.patch create mode 100644 patches/issue218_linux create mode 100644 patches/issue218_linux.patch create mode 100644 patches/issue73_linux create mode 100644 patches/patch.py create mode 100644 tools/apidocs.py create mode 100644 tools/automate-git.py create mode 100644 tools/automate-git.py.patch create mode 100644 tools/automate.py create mode 100644 tools/requirements.txt create mode 100644 tools/toc.py diff --git a/patches/include.gypi b/patches/include.gypi new file mode 100644 index 000000000..a5869aebb --- /dev/null +++ b/patches/include.gypi @@ -0,0 +1,5 @@ +{ + 'variables': { + 'use_allocator': 'none', + }, +} \ No newline at end of file diff --git a/patches/issue125_win_mac_linux b/patches/issue125_win_mac_linux new file mode 100644 index 000000000..f0496fda2 --- /dev/null +++ b/patches/issue125_win_mac_linux @@ -0,0 +1,5 @@ +Patch to Chromium. Fixes HTTPS cache problems on sites with certificate errors: +https://github.com/cztomczak/cefpython/issues/125 + +Apply the patch in the "chromium/src/net/http/" directory. It modifies +the WriteResponseInfoToEntry() method. diff --git a/patches/issue125_win_mac_linux.patch b/patches/issue125_win_mac_linux.patch new file mode 100644 index 000000000..508e891e2 --- /dev/null +++ b/patches/issue125_win_mac_linux.patch @@ -0,0 +1,14 @@ +diff --git http_cache_transaction.cc http_cache_transaction.cc +index 9dd8458..e61f1f0 100644 +--- http_cache_transaction.cc ++++ http_cache_transaction.cc +@@ -2661,7 +2661,8 @@ int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { + // blocking page is shown. An alternative would be to reverse-map the cert + // status to a net error and replay the net error. + if ((response_.headers->HasHeaderValue("cache-control", "no-store")) || +- IsCertStatusError(response_.ssl_info.cert_status)) { ++ (!cache_->GetSession()->params().ignore_certificate_errors && ++ IsCertStatusError(response_.ssl_info.cert_status))) { + DoneWritingToEntry(false); + if (net_log_.IsCapturing()) + net_log_.EndEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); diff --git a/patches/issue218_linux b/patches/issue218_linux new file mode 100644 index 000000000..6687effb0 --- /dev/null +++ b/patches/issue218_linux @@ -0,0 +1,5 @@ +Patch to CEF. Fixes GTK/wxPython issues on Linux: +https://github.com/cztomczak/cefpython/issues/218 + +Apply the patch in the `cef/libcef/browser/` directory. It modifies +the PlatformCreateWindow() method. diff --git a/patches/issue218_linux.patch b/patches/issue218_linux.patch new file mode 100644 index 000000000..a910792fa --- /dev/null +++ b/patches/issue218_linux.patch @@ -0,0 +1,58 @@ +Index: libcef/browser/browser_host_impl_gtk.cc +=================================================================== +--- browser_host_impl_gtk.cc (revision 1639) ++++ browser_host_impl_gtk.cc (working copy) +@@ -273,8 +273,43 @@ + + // Parent the TabContents to the browser window. + window_info_.widget = web_contents_->GetView()->GetNativeView(); +- gtk_container_add(GTK_CONTAINER(window_info_.parent_widget), +- window_info_.widget); ++ if (GTK_IS_BOX(window_info_.parent_widget)) { ++ gtk_box_pack_start(GTK_BOX(window_info_.parent_widget), ++ window_info_.widget, TRUE, TRUE, 0); ++ } else { ++ // Parent view shouldn't contain any children, but in wxWidgets library ++ // there will be GtkPizza widget for Panel or any other control. ++ GList *children, *iter; ++ children = gtk_container_get_children(GTK_CONTAINER( ++ window_info_.parent_widget)); ++ GtkWidget* child = NULL; ++ GtkWidget* vbox = gtk_vbox_new(FALSE, 0); ++ for (iter = children; iter != NULL; iter = g_list_next(iter)) { ++ child = GTK_WIDGET(iter->data); ++ // We will have to keep a reference to that child that we remove, ++ // otherwise we will get lots of warnings like "invalid unclassed ++ // pointer in cast to `GtkPizza'". First we increase a reference, ++ // we need to do this for a moment before we add this child to the ++ // vbox, then we will decrease that reference. ++ g_object_ref(G_OBJECT(child)); ++ gtk_container_remove(GTK_CONTAINER(window_info_.parent_widget), child); ++ } ++ g_list_free(children); ++ gtk_box_pack_start(GTK_BOX(vbox), window_info_.widget, TRUE, TRUE, 0); ++ if (child != NULL) { ++ // This child is packed to the box only so that its reference lives, ++ // as it might be referenced from other code thus resulting in errors. ++ gtk_box_pack_end(GTK_BOX(vbox), child, FALSE, FALSE, 0); ++ gtk_widget_hide(GTK_WIDGET(child)); ++ g_object_unref(G_OBJECT(child)); ++ } ++ gtk_widget_show(GTK_WIDGET(vbox)); ++ if (GTK_IS_SCROLLED_WINDOW(window_info_.parent_widget)) ++ gtk_scrolled_window_add_with_viewport( ++ GTK_SCROLLED_WINDOW(window_info_.parent_widget), vbox); ++ else ++ gtk_container_add(GTK_CONTAINER(window_info_.parent_widget), vbox); ++ } + + g_signal_connect(G_OBJECT(window_info_.widget), "destroy", + G_CALLBACK(browser_destroy), this); +@@ -293,6 +328,8 @@ + prefs->inactive_selection_bg_color = SkColorSetRGB(200, 200, 200); + prefs->inactive_selection_fg_color = SkColorSetRGB(50, 50, 50); + ++ gtk_widget_show_all(GTK_WIDGET(window_info_.widget)); ++ + return true; + } \ No newline at end of file diff --git a/patches/issue73_linux b/patches/issue73_linux new file mode 100644 index 000000000..837cb59d6 --- /dev/null +++ b/patches/issue73_linux @@ -0,0 +1,4 @@ +Patch to CEF. Fixes tcmalloc issue on Linux: +https://github.com/cztomczak/cefpython/issues/73 + +Copy the "include.gypi" file to the ~/.gyp/ directory. diff --git a/patches/patch.py b/patches/patch.py new file mode 100644 index 000000000..067e4d904 --- /dev/null +++ b/patches/patch.py @@ -0,0 +1,18 @@ +# CEF Python patches to Chromium and CEF. +# See upstream cef/patch/patch.cfg for how patching works in CEF. +# Current working directory is cef_build_dir/chromium/cef/ . +# See also docs/Build-instructions.md and tools/automate.py . + +import platform + +OS_POSTFIX = ("win" if platform.system() == "Windows" else + "linux" if platform.system() == "Linux" else + "mac" if platform.system() == "Darwin" else "unknown") + +patches.append( + { + # Fixes HTTPS cache problems on sites with certificate errors + 'name': 'issue125_win_mac_linux', + 'path': '../net/http/', + }, +) diff --git a/tools/apidocs.py b/tools/apidocs.py new file mode 100644 index 000000000..7ea06099f --- /dev/null +++ b/tools/apidocs.py @@ -0,0 +1,81 @@ +# Copyright (c) 2016 CEF Python, see the Authors file. All rights reserved. + +"""Generate API docs from sources. + +The pycef package must be first built and installed before running +this tool. It inspects both Cython sources and the dynamic module. + +TODO: +- generate api/ docs from Cython sources +- generate API-index.md, a list of all modules/functions/classes/methods + and constants/global module variables +- generate API-categories.md: objects, handlers, settings, types + (eg. TerminationStatus, KeyEvent, KeyEventFlags) +""" + +import os +import sys +import glob +import re + +# Constants +API_DIR = os.path.join( + os.path.dirname(os.path.dirname(__file__)), + "api" +) + + +def main(): + """Main entry point.""" + api_index() + + +def api_index(): + """Generate API-index.md file with all modules/classes/funcs/methods.""" + files = glob.glob(os.path.join(API_DIR, "*.md")) + contents = ("[API categories](API-categories.md) | " + + "[API index](API-index.md)\n\n" + + "# API index\n\n") + for file_ in files: + if "API-" in file_: + continue + with open(file_, "rb") as fo: + raw_mdcontents = fo.read() + + parsable_mdcontents = re.sub(r"```[\s\S]+?```", "", raw_mdcontents) + allmatches = re.findall(r"^(#|###)\s+(.*)", parsable_mdcontents, + re.MULTILINE) + for allmatch in allmatches: + hlevel = allmatch[0].strip() + title = allmatch[1].strip() + title = title.strip() + if hlevel == "#": + indent = "" + link = os.path.basename(file_) + elif hlevel == "###": + indent = " " + link = os.path.basename(file_) + "#" + headinghash(title) + # hash generation needs complete title. Now we can strip some. + title = re.sub(r"\(.*", r"", title) + else: + assert False, "Heading level unsupported" + contents += (indent + "* " + "[%s](%s)\n" % (title, link)) + indexfile = os.path.join(API_DIR, "API-index.md") + with open(indexfile, "wb") as fo: + fo.write(contents) + print("Created %s in %s" % (os.path.basename(indexfile), API_DIR)) + print("Done") + + +def headinghash(title): + """Get a link hash for a heading H1,H2,H3.""" + hash_ = title.lower() + hash_ = re.sub(r"[^a-z0-9_\- ]+", r"", hash_) + hash_ = hash_.replace(" ", "-") + hash_ = re.sub(r"[-]+", r"-", hash_) + hash_ = re.sub(r"-$", r"", hash_) + return hash_ + + +if __name__ == "__main__": + main() diff --git a/tools/automate-git.py b/tools/automate-git.py new file mode 100644 index 000000000..f17a22081 --- /dev/null +++ b/tools/automate-git.py @@ -0,0 +1,1069 @@ +""" See automate.py. This script is for internal usage only, don't +call it directly. This is a modified copy of automate-git.py from +upstream CEF. + +Some modifications were applied for CEF Python specific use case. +There is a patch file with the same name as this script that contains +differences from the original file. + +-------- + +Usage: automate-git.py [options] + + This utility implements automation for the download, update, build and +distribution of CEF. + +Options: + -h, --help show this help message and exit + --download-dir=DIR Download directory with no spaces [required]. + --depot-tools-dir=DIR + Download directory for depot_tools. + --depot-tools-archive=DEPOTTOOLSARCHIVE + Zip archive file that contains a single top-level + depot_tools directory. + --branch=BRANCH Branch of CEF to build (trunk, 1916, ...). This will + be used to name the CEF download directory and to + identify the correct URL if --url is not specified. + The default value is trunk. + --url=URL CEF download URL. If not specified the default URL + will be used. + --chromium-url=CHROMIUMURL + Chromium download URL. If not specified the default + URL will be used. + --checkout=CHECKOUT Version of CEF to checkout. If not specified the most + recent remote version of the branch will be used. + --chromium-checkout=CHROMIUMCHECKOUT + Version of Chromium to checkout (Git branch/hash/tag). + This overrides the value specified by CEF in + CHROMIUM_BUILD_COMPATIBILITY.txt. + --force-config Force creation of a new gclient config file. + --force-clean Force a clean checkout of Chromium and CEF. This will + trigger a new update, build and distribution. + --force-clean-deps Force a clean checkout of Chromium dependencies. Used + in combination with --force-clean. + --dry-run Output commands without executing them. + --dry-run-platform=DRYRUNPLATFORM + Simulate a dry run on the specified platform (windows, + macosx, linux). Must be used in combination with the + --dry-run flag. + --force-update Force a Chromium and CEF update. This will trigger a + new build and distribution. + --no-update Do not update Chromium or CEF. Pass --force-build or + --force-distrib if you desire a new build or + distribution. + --no-cef-update Do not update CEF. Pass --force-build or --force- + distrib if you desire a new build or distribution. + --no-chromium-update Do not update Chromium. + --no-depot-tools-update + Do not update depot_tools. + --force-build Force CEF debug and release builds. This builds + [build-target] on all platforms and chrome_sandbox on + Linux. + --no-build Do not build CEF. + --build-target=BUILDTARGET + Target name(s) to build (defaults to "cefclient"). + --build-tests Also build the cef_unittests target. + --no-debug-build Don't perform the CEF debug build. + --no-release-build Don't perform the CEF release build. + --verbose-build Show all command lines while building. + --build-log-file Write build logs to file. The file will be named + "build-[branch]-[debug|release].log" in the download + directory. + --x64-build Build for 64-bit systems (Windows and Mac OS X only). + --force-distrib Force creation of a CEF binary distribution. + --no-distrib Don't create a CEF binary distribution. + --minimal-distrib Create a minimal CEF binary distribution. + --minimal-distrib-only + Create a minimal CEF binary distribution only. + --client-distrib Create a client CEF binary distribution. + --client-distrib-only + Create a client CEF binary distribution only. + --no-distrib-docs Don't create CEF documentation. + --no-distrib-archive Don't create archives for output directories. + --clean-artifacts Clean the artifacts output directory. + --distrib-subdir=DISTRIBSUBDIR + CEF distrib dir name, child of + chromium/src/cef/binary_distrib +""" + +# Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights +# reserved. Use of this source code is governed by a BSD-style license that +# can be found in the LICENSE file. + +from optparse import OptionParser +import os +import shlex +import shutil +import subprocess +import sys +import tempfile +import urllib +import zipfile + +## +# Default URLs. +## + +depot_tools_url = 'https://chromium.googlesource.com/chromium/tools/depot_tools.git' +depot_tools_archive_url = 'https://storage.googleapis.com/chrome-infra/depot_tools.zip' + +cef_git_url = 'https://bitbucket.org/chromiumembedded/cef.git' + + +## +# Global system variables. +## + +# Script directory. +script_dir = os.path.dirname(__file__) + + +## +# Helper functions. +## + +def msg(message): + """ Output a message. """ + sys.stdout.write('--> ' + message + "\n") + +def run(command_line, working_dir, depot_tools_dir=None, output_file=None): + """ Runs the specified command. """ + # add depot_tools to the path + env = os.environ + if not depot_tools_dir is None: + env['PATH'] = depot_tools_dir+os.pathsep+env['PATH'] + + sys.stdout.write('-------- Running "'+command_line+'" in "'+\ + working_dir+'"...'+"\n") + if not options.dryrun: + args = shlex.split(command_line.replace('\\', '\\\\')) + + if not output_file: + return subprocess.check_call(args, cwd=working_dir, env=env, + shell=(sys.platform == 'win32')) + with open(output_file, "w") as f: + return subprocess.check_call(args, cwd=working_dir, env=env, + shell=(sys.platform == 'win32'), + stderr=subprocess.STDOUT, stdout=f) + +def create_directory(path): + """ Creates a directory if it doesn't already exist. """ + if not os.path.exists(path): + msg("Creating directory %s" % (path)); + if not options.dryrun: + os.makedirs(path) + +def delete_directory(path): + """ Removes an existing directory. """ + if os.path.exists(path): + msg("Removing directory %s" % (path)); + if not options.dryrun: + shutil.rmtree(path, onerror=onerror) + +def copy_directory(source, target, allow_overwrite=False): + """ Copies a directory from source to target. """ + if not options.dryrun and os.path.exists(target): + if not allow_overwrite: + raise Exception("Directory %s already exists" % (target)) + remove_directory(target) + if os.path.exists(source): + msg("Copying directory %s to %s" % (source, target)); + if not options.dryrun: + shutil.copytree(source, target) + +def move_directory(source, target, allow_overwrite=False): + """ Copies a directory from source to target. """ + if not options.dryrun and os.path.exists(target): + if not allow_overwrite: + raise Exception("Directory %s already exists" % (target)) + remove_directory(target) + if os.path.exists(source): + msg("Moving directory %s to %s" % (source, target)); + if not options.dryrun: + shutil.move(source, target) + +def is_git_checkout(path): + """ Returns true if the path represents a git checkout. """ + return os.path.exists(os.path.join(path, '.git')) + +def exec_cmd(cmd, path): + """ Execute the specified command and return the result. """ + out = '' + err = '' + sys.stdout.write("-------- Running \"%s\" in \"%s\"...\n" % (cmd, path)) + parts = cmd.split() + try: + process = subprocess.Popen(parts, cwd=path, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=(sys.platform == 'win32')) + out, err = process.communicate() + except IOError, (errno, strerror): + raise + except: + raise + return {'out': out, 'err': err} + +def get_git_hash(path, branch): + """ Returns the git hash for the specified branch/tag/hash. """ + cmd = "%s rev-parse %s" % (git_exe, branch) + result = exec_cmd(cmd, path) + if result['out'] != '': + return result['out'].strip() + return 'Unknown' + +def get_git_url(path): + """ Returns the origin url for the specified path. """ + cmd = "%s config --get remote.origin.url" % (git_exe) + result = exec_cmd(cmd, path) + if result['out'] != '': + return result['out'].strip() + return 'Unknown' + +def download_and_extract(src, target): + """ Extracts the contents of src, which may be a URL or local file, to the + target directory. """ + temporary = False + + if src[:4] == 'http': + # Attempt to download a URL. + opener = urllib.FancyURLopener({}) + response = opener.open(src) + + temporary = True + handle, archive_path = tempfile.mkstemp(suffix = '.zip') + os.write(handle, response.read()) + os.close(handle) + elif os.path.exists(src): + # Use a local file. + archive_path = src + else: + raise Exception('Path type is unsupported or does not exist: ' + src) + + if not zipfile.is_zipfile(archive_path): + raise Exception('Not a valid zip archive: ' + src) + + # Attempt to extract the archive file. + try: + os.makedirs(target) + zf = zipfile.ZipFile(archive_path, 'r') + zf.extractall(target) + except: + shutil.rmtree(target, onerror=onerror) + raise + zf.close() + + # Delete the archive file if temporary. + if temporary and os.path.exists(archive_path): + os.remove(archive_path) + +def read_config_file(path): + """ Read a configuration file. """ + if os.path.exists(path): + fp = open(path, 'r') + data = fp.read() + fp.close() + else: + raise Exception("Path does not exist: %s" % (path)) + + # Parse the contents. + return eval(data, {'__builtins__': None}, None) + +def write_config_file(path, contents): + """ Write a configuration file. """ + msg('Writing file: %s' % path) + if not options.dryrun: + fp = open(path, 'w') + fp.write("{\n") + for key in sorted(contents.keys()): + fp.write(" '%s': '%s',\n" % (key, contents[key])) + fp.write("}\n") + fp.close() + +def read_branch_config_file(path): + """ Read the CEF branch from the specified path. """ + config_file = os.path.join(path, 'cef.branch') + if os.path.isfile(config_file): + contents = read_config_file(config_file) + if 'branch' in contents: + return contents['branch'] + return '' + +def write_branch_config_file(path, branch): + """ Write the CEF branch to the specified path. """ + config_file = os.path.join(path, 'cef.branch') + if not os.path.isfile(config_file): + write_config_file(config_file, {'branch': branch}) + +def remove_deps_entry(path, entry): + """ Remove an entry from the Chromium DEPS file at the specified path. """ + msg('Updating DEPS file: %s' % path) + if not options.dryrun: + # Read the DEPS file. + fp = open(path, 'r') + lines = fp.readlines() + fp.close() + + # Write the DEPS file. + # Each entry takes 2 lines. Skip both lines if found. + fp = open(path, 'w') + skip_next = False + for line in lines: + if skip_next: + skip_next = False + continue + elif line.find(entry) >= 0: + skip_next = True + continue + fp.write(line) + fp.close() + +def apply_deps_patch(): + """ Patch the Chromium DEPS file if necessary. """ + # Starting with 43.0.2357.126 the DEPS file is now 100% Git and the .DEPS.git + # file is no longer created. Look for the older file first in case we're + # building an older branch version. + deps_file = '.DEPS.git' + deps_path = os.path.join(chromium_src_dir, deps_file) + if not os.path.isfile(deps_path): + deps_file = 'DEPS' + deps_path = os.path.join(chromium_src_dir, deps_file) + + if os.path.isfile(deps_path): + msg("Chromium DEPS file: %s" % (deps_path)) + patch_file = os.path.join(cef_dir, 'patch', 'patches', deps_file + '.patch') + if os.path.exists(patch_file): + # Attempt to apply the DEPS patch file that may exist with newer branches. + patch_tool = os.path.join(cef_dir, 'tools', 'patcher.py') + run('%s %s --patch-file "%s" --patch-dir "%s"' % + (python_exe, patch_tool, patch_file, chromium_src_dir), + chromium_src_dir, depot_tools_dir) + elif cef_branch != 'trunk' and int(cef_branch) <= 1916: + # Release branch DEPS files older than 37.0.2007.0 may include a 'src' + # entry. This entry needs to be removed otherwise `gclient sync` will + # fail. + remove_deps_entry(deps_path, "'src'") + else: + raise Exception("Path does not exist: %s" % (deps_path)) + +def onerror(func, path, exc_info): + """ + Error handler for ``shutil.rmtree``. + + If the error is due to an access error (read only file) + it attempts to add write permission and then retries. + + If the error is for another reason it re-raises the error. + + Usage : ``shutil.rmtree(path, onerror=onerror)`` + """ + import stat + if not os.access(path, os.W_OK): + # Is the error an access error ? + os.chmod(path, stat.S_IWUSR) + func(path) + else: + raise + + +## +# Program entry point. +## + +# Cannot be loaded as a module. +if __name__ != "__main__": + sys.stderr.write('This file cannot be loaded as a module!') + sys.exit() + +# Parse command-line options. +disc = """ +This utility implements automation for the download, update, build and +distribution of CEF. +""" + +parser = OptionParser(description=disc) + +# Setup options. +parser.add_option('--download-dir', dest='downloaddir', metavar='DIR', + help='Download directory with no spaces [required].') +parser.add_option('--depot-tools-dir', dest='depottoolsdir', metavar='DIR', + help='Download directory for depot_tools.', default='') +parser.add_option('--depot-tools-archive', dest='depottoolsarchive', + help='Zip archive file that contains a single top-level '+\ + 'depot_tools directory.', default='') +parser.add_option('--branch', dest='branch', + help='Branch of CEF to build (trunk, 1916, ...). This '+\ + 'will be used to name the CEF download directory and '+\ + 'to identify the correct URL if --url is not '+\ + 'specified. The default value is trunk.', + default='trunk') +parser.add_option('--url', dest='url', + help='CEF download URL. If not specified the default URL '+\ + 'will be used.', + default='') +parser.add_option('--chromium-url', dest='chromiumurl', + help='Chromium download URL. If not specified the default '+\ + 'URL will be used.', + default='') +parser.add_option('--checkout', dest='checkout', + help='Version of CEF to checkout. If not specified the '+\ + 'most recent remote version of the branch will be used.', + default='') +parser.add_option('--chromium-checkout', dest='chromiumcheckout', + help='Version of Chromium to checkout (Git '+\ + 'branch/hash/tag). This overrides the value specified '+\ + 'by CEF in CHROMIUM_BUILD_COMPATIBILITY.txt.', + default='') + +# Miscellaneous options. +parser.add_option('--force-config', + action='store_true', dest='forceconfig', default=False, + help='Force creation of a new gclient config file.') +parser.add_option('--force-clean', + action='store_true', dest='forceclean', default=False, + help='Force a clean checkout of Chromium and CEF. This will'+\ + ' trigger a new update, build and distribution.') +parser.add_option('--force-clean-deps', + action='store_true', dest='forcecleandeps', default=False, + help='Force a clean checkout of Chromium dependencies. Used'+\ + ' in combination with --force-clean.') +parser.add_option('--dry-run', + action='store_true', dest='dryrun', default=False, + help="Output commands without executing them.") +parser.add_option('--dry-run-platform', dest='dryrunplatform', default=None, + help='Simulate a dry run on the specified platform '+\ + '(windows, macosx, linux). Must be used in combination'+\ + ' with the --dry-run flag.') + +# Update-related options. +parser.add_option('--force-update', + action='store_true', dest='forceupdate', default=False, + help='Force a Chromium and CEF update. This will trigger a '+\ + 'new build and distribution.') +parser.add_option('--no-update', + action='store_true', dest='noupdate', default=False, + help='Do not update Chromium or CEF. Pass --force-build or '+\ + '--force-distrib if you desire a new build or '+\ + 'distribution.') +parser.add_option('--no-cef-update', + action='store_true', dest='nocefupdate', default=False, + help='Do not update CEF. Pass --force-build or '+\ + '--force-distrib if you desire a new build or '+\ + 'distribution.') +parser.add_option('--no-chromium-update', + action='store_true', dest='nochromiumupdate', default=False, + help='Do not update Chromium.') +parser.add_option('--no-depot-tools-update', + action='store_true', dest='nodepottoolsupdate', default=False, + help='Do not update depot_tools.') + +# Build-related options. +parser.add_option('--force-build', + action='store_true', dest='forcebuild', default=False, + help='Force CEF debug and release builds. This builds '+\ + '[build-target] on all platforms and chrome_sandbox '+\ + 'on Linux.') +parser.add_option('--no-build', + action='store_true', dest='nobuild', default=False, + help='Do not build CEF.') +parser.add_option('--build-target', dest='buildtarget', default='cefclient', + help='Target name(s) to build (defaults to "cefclient").') +parser.add_option('--build-tests', + action='store_true', dest='buildtests', default=False, + help='Also build the cef_unittests target.') +parser.add_option('--no-debug-build', + action='store_true', dest='nodebugbuild', default=False, + help="Don't perform the CEF debug build.") +parser.add_option('--no-release-build', + action='store_true', dest='noreleasebuild', default=False, + help="Don't perform the CEF release build.") +parser.add_option('--verbose-build', + action='store_true', dest='verbosebuild', default=False, + help='Show all command lines while building.') +parser.add_option('--build-log-file', + action='store_true', dest='buildlogfile', default=False, + help='Write build logs to file. The file will be named '+\ + '"build-[branch]-[debug|release].log" in the download '+\ + 'directory.') +parser.add_option('--x64-build', + action='store_true', dest='x64build', default=False, + help='Build for 64-bit systems (Windows and Mac OS X only).') + +# Distribution-related options. +parser.add_option('--force-distrib', + action='store_true', dest='forcedistrib', default=False, + help='Force creation of a CEF binary distribution.') +parser.add_option('--no-distrib', + action='store_true', dest='nodistrib', default=False, + help="Don't create a CEF binary distribution.") +parser.add_option('--minimal-distrib', + action='store_true', dest='minimaldistrib', default=False, + help='Create a minimal CEF binary distribution.') +parser.add_option('--minimal-distrib-only', + action='store_true', dest='minimaldistribonly', default=False, + help='Create a minimal CEF binary distribution only.') +parser.add_option('--client-distrib', + action='store_true', dest='clientdistrib', default=False, + help='Create a client CEF binary distribution.') +parser.add_option('--client-distrib-only', + action='store_true', dest='clientdistribonly', default=False, + help='Create a client CEF binary distribution only.') +parser.add_option('--no-distrib-docs', + action='store_true', dest='nodistribdocs', default=False, + help="Don't create CEF documentation.") +parser.add_option('--no-distrib-archive', + action='store_true', dest='nodistribarchive', default=False, + help="Don't create archives for output directories.") +parser.add_option('--clean-artifacts', + action='store_true', dest='cleanartifacts', default=False, + help='Clean the artifacts output directory.') +parser.add_option('--distrib-subdir', dest='distribsubdir', + help='CEF distrib dir name, child of '+\ + 'chromium/src/cef/binary_distrib', + default='') + +(options, args) = parser.parse_args() + +if options.downloaddir is None: + print "The --download-dir option is required." + parser.print_help(sys.stderr) + sys.exit() + +# Opt into component-specific flags for later use. +if options.noupdate: + options.nocefupdate = True + options.nochromiumupdate = True + options.nodepottoolsupdate = True + +if (options.nochromiumupdate and options.forceupdate) or \ + (options.nocefupdate and options.forceupdate) or \ + (options.nobuild and options.forcebuild) or \ + (options.nodistrib and options.forcedistrib): + print "Invalid combination of options." + parser.print_help(sys.stderr) + sys.exit() + +if (options.noreleasebuild and \ + (options.minimaldistrib or options.minimaldistribonly or \ + options.clientdistrib or options.clientdistribonly)) or \ + (options.minimaldistribonly and options.clientdistribonly): + print 'Invalid combination of options.' + parser.print_help(sys.stderr) + sys.exit() + +if (options.clientdistrib or options.clientdistribonly) and \ + options.buildtarget.find('cefclient') == -1: + print "A client distribution cannot be generated if --build-target "+\ + "excludes cefclient." + parser.print_help(sys.stderr) + sys.exit() + +# Operating system. +if options.dryrun and options.dryrunplatform is not None: + platform = options.dryrunplatform + if not platform in ['windows', 'macosx', 'linux']: + print 'Invalid dry-run-platform value: %s' % (platform) + sys.exit() +elif sys.platform == 'win32': + platform = 'windows' +elif sys.platform == 'darwin': + platform = 'macosx' +elif sys.platform.startswith('linux'): + platform = 'linux' +else: + print 'Unknown operating system platform' + sys.exit() + +# Script extension. +if platform == 'windows': + script_ext = '.bat' +else: + script_ext = '.sh' + +if options.x64build and platform != 'windows' and platform != 'macosx': + print 'The x64 build option is only used on Windows and Mac OS X.' + sys.exit() + +if platform == 'windows' and not 'GYP_MSVS_VERSION' in os.environ.keys(): + print 'You must set the GYP_MSVS_VERSION environment variable on Windows.' + sys.exit() + +# CEF branch. +if options.branch != 'trunk' and not options.branch.isdigit(): + print 'Invalid branch value: %s' % (options.branch) +cef_branch = options.branch + +if cef_branch != 'trunk' and int(cef_branch) <= 1453: + print 'The requested branch is too old to build using this tool' + sys.exit() + +# True if the requested branch is 2272 or newer. +branch_is_2272_or_newer = (cef_branch == 'trunk' or int(cef_branch) >= 2272) + +# True if the requested branch is 2357 or newer. +branch_is_2357_or_newer = (cef_branch == 'trunk' or int(cef_branch) >= 2357) + +# Starting with 43.0.2357.126 the DEPS file is now 100% Git and the .DEPS.git +# file is no longer created. +if branch_is_2357_or_newer: + deps_file = 'DEPS' +else: + deps_file = '.DEPS.git' + +if platform == 'macosx' and not options.x64build and branch_is_2272_or_newer: + print '32-bit Mac OS X builds are no longer supported with 2272 branch and '+\ + 'newer. Add --x64-build flag to generate a 64-bit build.' + sys.exit() + +# True if GYP_DEFINES=target_arch=x64 must be set. +gyp_needs_target_arch_x64 = options.x64build and \ + (platform == 'windows' or \ + (platform == 'macosx' and not branch_is_2272_or_newer)) + +# Options that force the sources to change. +force_change = options.forceclean or options.forceupdate + +if platform == 'windows': + # Avoid errors when the "vs_toolchain.py update" Chromium hook runs. + os.environ['DEPOT_TOOLS_WIN_TOOLCHAIN'] = '0' + + +## +# Manage the download directory. +## + +# Create the download directory if necessary. +download_dir = os.path.abspath(options.downloaddir) +create_directory(download_dir) + +msg("Download Directory: %s" % (download_dir)) + + +## +# Manage the depot_tools directory. +## + +# Check if the depot_tools directory exists. +if options.depottoolsdir != '': + depot_tools_dir = os.path.abspath(options.depottoolsdir) +else: + depot_tools_dir = os.path.join(download_dir, 'depot_tools') + +msg("Depot Tools Directory: %s" % (depot_tools_dir)) + +if not os.path.exists(depot_tools_dir): + if platform == 'windows' and options.depottoolsarchive == '': + # On Windows download depot_tools as an archive file since we can't assume + # that git is already installed. + options.depottoolsarchive = depot_tools_archive_url + + if options.depottoolsarchive != '': + # Extract depot_tools from an archive file. + msg('Extracting %s to %s.' % \ + (options.depottoolsarchive, depot_tools_dir)) + if not options.dryrun: + download_and_extract(options.depottoolsarchive, depot_tools_dir) + else: + # On Linux and OS X check out depot_tools using Git. + run('git clone '+depot_tools_url+' '+depot_tools_dir, download_dir) + +if not options.nodepottoolsupdate: + # Update depot_tools. + # On Windows this will download required python and git binaries. + msg('Updating depot_tools') + if platform == 'windows': + run('update_depot_tools.bat', depot_tools_dir, depot_tools_dir); + else: + run('update_depot_tools', depot_tools_dir, depot_tools_dir); + +# Determine the executables to use. +if platform == 'windows': + # Force use of the version bundled with depot_tools. + git_exe = os.path.join(depot_tools_dir, 'git.bat') + python_exe = os.path.join(depot_tools_dir, 'python.bat') + if options.dryrun and not os.path.exists(git_exe): + sys.stdout.write("WARNING: --dry-run assumes that depot_tools" \ + " is already in your PATH. If it isn't\nplease" \ + " specify a --depot-tools-dir value.\n") + git_exe = 'git.bat' + python_exe = 'python.bat' +else: + git_exe = 'git' + python_exe = 'python' + + +## +# Manage the cef directory. +## + +cef_dir = os.path.join(download_dir, 'cef') + +# Delete the existing CEF directory if requested. +if options.forceclean and os.path.exists(cef_dir): + delete_directory(cef_dir) + +# Determine the type of CEF checkout to use. +if os.path.exists(cef_dir) and not is_git_checkout(cef_dir): + raise Exception("Not a valid CEF Git checkout: %s" % (cef_dir)) + +# Determine the CEF download URL to use. +if options.url == '': + cef_url = cef_git_url +else: + cef_url = options.url + +# Verify that the requested CEF URL matches the existing checkout. +if not options.nocefupdate and os.path.exists(cef_dir): + cef_existing_url = get_git_url(cef_dir) + if cef_url != cef_existing_url: + raise Exception( + 'Requested CEF checkout URL %s does not match existing URL %s' % + (cef_url, cef_existing_url)) + +msg("CEF Branch: %s" % (cef_branch)) +msg("CEF URL: %s" % (cef_url)) +msg("CEF Source Directory: %s" % (cef_dir)) + +# Determine the CEF Git branch to use. +if options.checkout == '': + # Target the most recent branch commit from the remote repo. + if cef_branch == 'trunk': + cef_checkout = 'origin/master' + else: + cef_checkout = 'origin/' + cef_branch +else: + cef_checkout = options.checkout + +# Create the CEF checkout if necessary. +if not options.nocefupdate and not os.path.exists(cef_dir): + cef_checkout_new = True + run('%s clone %s %s' % (git_exe, cef_url, cef_dir), download_dir, \ + depot_tools_dir) +else: + cef_checkout_new = False + +# Update the CEF checkout if necessary. +if not options.nocefupdate and os.path.exists(cef_dir): + cef_current_hash = get_git_hash(cef_dir, 'HEAD') + + if not cef_checkout_new: + # Fetch new sources. + run('%s fetch' % (git_exe), cef_dir, depot_tools_dir) + + cef_desired_hash = get_git_hash(cef_dir, cef_checkout) + cef_checkout_changed = cef_checkout_new or force_change or \ + cef_current_hash != cef_desired_hash + + msg("CEF Current Checkout: %s" % (cef_current_hash)) + msg("CEF Desired Checkout: %s (%s)" % (cef_desired_hash, cef_checkout)) + + if cef_checkout_changed: + # Checkout the requested branch. + run('%s checkout %s%s' % + (git_exe, ('--force ' if options.forceclean else ''), cef_checkout), \ + cef_dir, depot_tools_dir) +else: + cef_checkout_changed = False + + +## +# Manage the out directory. +## + +out_dir = os.path.join(download_dir, 'out_' + cef_branch) + +# Delete the existing out directory if requested. +if options.forceclean and os.path.exists(out_dir): + delete_directory(out_dir) + +msg("CEF Output Directory: %s" % (out_dir)) + + +## +# Manage the chromium directory. +## + +# Create the chromium directory if necessary. +chromium_dir = os.path.join(download_dir, 'chromium') +create_directory(chromium_dir) + +chromium_src_dir = os.path.join(chromium_dir, 'src') +cef_src_dir = os.path.join(chromium_src_dir, 'cef') +out_src_dir = os.path.join(chromium_src_dir, 'out') + +if options.chromiumurl != '': + chromium_url = options.chromiumurl; +else: + chromium_url = 'https://chromium.googlesource.com/chromium/src.git' + +# Create gclient configuration file. +gclient_file = os.path.join(chromium_dir, '.gclient') +if not os.path.exists(gclient_file) or options.forceconfig: + # Exclude unnecessary directories. Intentionally written without newlines. + gclient_spec = \ + "solutions = [{"+\ + "u'managed': False,"+\ + "u'name': u'src', "+\ + "u'url': u'" + chromium_url + "', "+\ + "u'custom_deps': {"+\ + "u'build': None, "+\ + "u'build/scripts/command_wrapper/bin': None, "+\ + "u'build/scripts/gsd_generate_index': None, "+\ + "u'build/scripts/private/data/reliability': None, "+\ + "u'build/scripts/tools/deps2git': None, "+\ + "u'build/third_party/lighttpd': None, "+\ + "u'commit-queue': None, "+\ + "u'depot_tools': None, "+\ + "u'src/chrome_frame/tools/test/reference_build/chrome': None, "+\ + "u'src/chrome/tools/test/reference_build/chrome_linux': None, "+\ + "u'src/chrome/tools/test/reference_build/chrome_mac': None, "+\ + "u'src/chrome/tools/test/reference_build/chrome_win': None, "+\ + "}, "+\ + "u'deps_file': u'" + deps_file + "', "+\ + "u'safesync_url': u''"+\ + "}]" + + msg('Writing file: %s' % gclient_file) + if not options.dryrun: + fp = open(gclient_file, 'w') + fp.write(gclient_spec) + fp.close() + +# Initial Chromium checkout. +if not options.nochromiumupdate and not os.path.exists(chromium_src_dir): + chromium_checkout_new = True + run("gclient sync --nohooks --with_branch_heads --jobs 16", chromium_dir, \ + depot_tools_dir) +else: + chromium_checkout_new = False + +# Verify the Chromium checkout. +if not options.dryrun and not is_git_checkout(chromium_src_dir): + raise Exception('Not a valid git checkout: %s' % (chromium_src_dir)) + +if os.path.exists(chromium_src_dir): + msg("Chromium URL: %s" % (get_git_url(chromium_src_dir))) + +# Determine the Chromium checkout options required by CEF. +if options.chromiumcheckout == '': + # Read the build compatibility file to identify the checkout name. + compat_path = os.path.join(cef_dir, 'CHROMIUM_BUILD_COMPATIBILITY.txt') + config = read_config_file(compat_path) + + if 'chromium_checkout' in config: + chromium_checkout = config['chromium_checkout'] + else: + raise Exception("Missing chromium_checkout value in %s" % (compat_path)) +else: + chromium_checkout = options.chromiumcheckout + +# Determine if the Chromium checkout needs to change. +if not options.nochromiumupdate and os.path.exists(chromium_src_dir): + chromium_current_hash = get_git_hash(chromium_src_dir, 'HEAD') + chromium_desired_hash = get_git_hash(chromium_src_dir, chromium_checkout) + chromium_checkout_changed = chromium_checkout_new or force_change or \ + chromium_current_hash != chromium_desired_hash + + msg("Chromium Current Checkout: %s" % (chromium_current_hash)) + msg("Chromium Desired Checkout: %s (%s)" % \ + (chromium_desired_hash, chromium_checkout)) +else: + chromium_checkout_changed = options.dryrun + +# Delete the existing src/cef directory. It will be re-copied from the download +# directory later. +if cef_checkout_changed and os.path.exists(cef_src_dir): + delete_directory(cef_src_dir) + +# Delete the existing src/out directory if requested. +if options.forceclean and os.path.exists(out_src_dir): + delete_directory(out_src_dir) + +# Move the existing src/out directory to the correct location in the download +# directory. It will be moved back from the download directory later. +if os.path.exists(out_src_dir): + old_branch = read_branch_config_file(out_src_dir) + if old_branch != '' and (chromium_checkout_changed or \ + old_branch != cef_branch): + old_out_dir = os.path.join(download_dir, 'out_' + old_branch) + move_directory(out_src_dir, old_out_dir) + +# Update the Chromium checkout. +if chromium_checkout_changed: + if not chromium_checkout_new: + if options.forceclean and options.forcecleandeps: + # Remove all local changes including third-party git checkouts managed by + # gclient. + run("%s clean -dffx" % (git_exe), chromium_src_dir, depot_tools_dir) + else: + # Revert all changes in the Chromium checkout. + run("gclient revert --nohooks", chromium_dir, depot_tools_dir) + + # Fetch new sources. + run("%s fetch" % (git_exe), chromium_src_dir, depot_tools_dir) + # Also fetch tags, which are required for release branch builds. + run("%s fetch --tags" % (git_exe), chromium_src_dir, depot_tools_dir) + + # Checkout the requested branch. + run("%s checkout %s%s" % \ + (git_exe, ('--force ' if options.forceclean else ''), chromium_checkout), \ + chromium_src_dir, depot_tools_dir) + + # Patch the Chromium DEPS file if necessary. + apply_deps_patch() + + # Set the GYP_CHROMIUM_NO_ACTION value temporarily so that `gclient sync` does + # not run gyp. + os.environ['GYP_CHROMIUM_NO_ACTION'] = '1' + + # Update third-party dependencies including branch/tag information. + run("gclient sync %s--with_branch_heads --jobs 16" % \ + (('--reset ' if options.forceclean else '')), \ + chromium_dir, depot_tools_dir) + + # Clear the GYP_CHROMIUM_NO_ACTION value. + del os.environ['GYP_CHROMIUM_NO_ACTION'] + + # Delete the src/out directory created by `gclient sync`. + delete_directory(out_src_dir) + +# Restore the src/cef directory. +if os.path.exists(cef_dir) and not os.path.exists(cef_src_dir): + copy_directory(cef_dir, cef_src_dir) + +# Restore the src/out directory. +out_src_dir_exists = os.path.exists(out_src_dir) +if os.path.exists(out_dir) and not out_src_dir_exists: + move_directory(out_dir, out_src_dir) + out_src_dir_exists = True +elif not out_src_dir_exists: + create_directory(out_src_dir) + +# Write the config file for identifying the branch. +write_branch_config_file(out_src_dir, cef_branch) + + +## +# Build CEF. +## + +if not options.nobuild and (chromium_checkout_changed or \ + cef_checkout_changed or options.forcebuild or \ + not out_src_dir_exists): + # Building should also force a distribution. + options.forcedistrib = True + + # Set GYP environment variables. + os.environ['GYP_GENERATORS'] = 'ninja' + if gyp_needs_target_arch_x64: + if 'GYP_DEFINES' in os.environ.keys(): + os.environ['GYP_DEFINES'] = os.environ['GYP_DEFINES'] + ' ' + \ + 'target_arch=x64' + else: + os.environ['GYP_DEFINES'] = 'target_arch=x64' + + # Print all build-related environment variables including any that were set + # previously. + for key in os.environ.keys(): + if key.startswith('GYP_') or key.startswith('DEPOT_TOOLS_'): + msg('%s=%s' % (key, os.environ[key])) + + # Run the cef_create_projects script to generate project files. + path = os.path.join(cef_src_dir, 'cef_create_projects'+script_ext) + run(path, cef_src_dir, depot_tools_dir) + + # Build using Ninja. + command = 'ninja -C ' + if options.verbosebuild: + command = 'ninja -v -C' + + # -- CEF Python modification below + assert os.environ['CEFPYTHON_NINJA_JOBS'] + command = 'ninja -v -j' + os.environ['CEFPYTHON_NINJA_JOBS'] + ' -C' + # -- + + target = ' ' + options.buildtarget + if options.buildtests: + target = target + ' cef_unittests' + if platform == 'linux': + target = target + ' chrome_sandbox' + build_dir_suffix = '' + if platform == 'windows' and options.x64build: + build_dir_suffix = '_x64' + + if not options.nodebugbuild: + # Make a CEF Debug build. + run(command + os.path.join('out', 'Debug' + build_dir_suffix) + target, \ + chromium_src_dir, depot_tools_dir, + os.path.join(download_dir, 'build-%s-debug.log' % (cef_branch)) \ + if options.buildlogfile else None) + + if not options.noreleasebuild: + # Make a CEF Release build. + run(command + os.path.join('out', 'Release' + build_dir_suffix) + target, \ + chromium_src_dir, depot_tools_dir, + os.path.join(download_dir, 'build-%s-release.log' % (cef_branch)) \ + if options.buildlogfile else None) + +elif not options.nobuild: + msg('Not building. The source hashes have not changed and ' + + 'the output folder "%s" already exists' % (out_src_dir)) + + +## +# Create the CEF binary distribution. +## + +if not options.nodistrib and (chromium_checkout_changed or \ + cef_checkout_changed or options.forcedistrib): + if not options.forceclean and options.cleanartifacts: + # Clean the artifacts output directory. + artifacts_path = os.path.join(cef_src_dir, 'binary_distrib') + delete_directory(artifacts_path) + + # Determine the requested distribution types. + distrib_types = [] + if options.minimaldistribonly: + distrib_types.append('minimal') + elif options.clientdistribonly: + distrib_types.append('client') + else: + distrib_types.append('standard') + if options.minimaldistrib: + distrib_types.append('minimal') + if options.clientdistrib: + distrib_types.append('client') + + cef_tools_dir = os.path.join(cef_src_dir, 'tools') + + # Create the requested distribution types. + first_type = True + for type in distrib_types: + path = os.path.join(cef_tools_dir, 'make_distrib'+script_ext) + if options.nodebugbuild or options.noreleasebuild or type != 'standard': + path = path + ' --allow-partial' + path = path + ' --ninja-build' + if options.x64build: + path = path + ' --x64-build' + + if type == 'minimal': + path = path + ' --minimal' + elif type == 'client': + path = path + ' --client' + + if first_type: + if options.nodistribdocs: + path = path + ' --no-docs' + if options.nodistribarchive: + path = path + ' --no-archive' + first_type = False + else: + # Don't create the symbol archives or documentation more than once. + path = path + ' --no-symbols --no-docs' + + # Override the subdirectory name of binary_distrib if the caller requested. + if options.distribsubdir != '': + path = path + ' --distrib-subdir=' + options.distribsubdir + + # Create the distribution. + run(path, cef_tools_dir, depot_tools_dir) diff --git a/tools/automate-git.py.patch b/tools/automate-git.py.patch new file mode 100644 index 000000000..fcc93e7de --- /dev/null +++ b/tools/automate-git.py.patch @@ -0,0 +1,105 @@ +diff --git automate-git.py automate-git.py +index 1f0be0b..4b8da90 100644 +--- automate-git.py ++++ automate-git.py +@@ -1,3 +1,87 @@ ++""" This is a modified copy of automate-git.py from upstream CEF. ++ ++Some modifications were applied for CEF Python specific use case. ++There is a patch file with the same name as this script that contains ++differences from the original file. ++ ++Usage: automate-git.py [options] ++ ++ This utility implements automation for the download, update, build and ++distribution of CEF. ++ ++Options: ++ -h, --help show this help message and exit ++ --download-dir=DIR Download directory with no spaces [required]. ++ --depot-tools-dir=DIR ++ Download directory for depot_tools. ++ --depot-tools-archive=DEPOTTOOLSARCHIVE ++ Zip archive file that contains a single top-level ++ depot_tools directory. ++ --branch=BRANCH Branch of CEF to build (trunk, 1916, ...). This will ++ be used to name the CEF download directory and to ++ identify the correct URL if --url is not specified. ++ The default value is trunk. ++ --url=URL CEF download URL. If not specified the default URL ++ will be used. ++ --chromium-url=CHROMIUMURL ++ Chromium download URL. If not specified the default ++ URL will be used. ++ --checkout=CHECKOUT Version of CEF to checkout. If not specified the most ++ recent remote version of the branch will be used. ++ --chromium-checkout=CHROMIUMCHECKOUT ++ Version of Chromium to checkout (Git branch/hash/tag). ++ This overrides the value specified by CEF in ++ CHROMIUM_BUILD_COMPATIBILITY.txt. ++ --force-config Force creation of a new gclient config file. ++ --force-clean Force a clean checkout of Chromium and CEF. This will ++ trigger a new update, build and distribution. ++ --force-clean-deps Force a clean checkout of Chromium dependencies. Used ++ in combination with --force-clean. ++ --dry-run Output commands without executing them. ++ --dry-run-platform=DRYRUNPLATFORM ++ Simulate a dry run on the specified platform (windows, ++ macosx, linux). Must be used in combination with the ++ --dry-run flag. ++ --force-update Force a Chromium and CEF update. This will trigger a ++ new build and distribution. ++ --no-update Do not update Chromium or CEF. Pass --force-build or ++ --force-distrib if you desire a new build or ++ distribution. ++ --no-cef-update Do not update CEF. Pass --force-build or --force- ++ distrib if you desire a new build or distribution. ++ --no-chromium-update Do not update Chromium. ++ --no-depot-tools-update ++ Do not update depot_tools. ++ --force-build Force CEF debug and release builds. This builds ++ [build-target] on all platforms and chrome_sandbox on ++ Linux. ++ --no-build Do not build CEF. ++ --build-target=BUILDTARGET ++ Target name(s) to build (defaults to "cefclient"). ++ --build-tests Also build the cef_unittests target. ++ --no-debug-build Don't perform the CEF debug build. ++ --no-release-build Don't perform the CEF release build. ++ --verbose-build Show all command lines while building. ++ --build-log-file Write build logs to file. The file will be named ++ "build-[branch]-[debug|release].log" in the download ++ directory. ++ --x64-build Build for 64-bit systems (Windows and Mac OS X only). ++ --force-distrib Force creation of a CEF binary distribution. ++ --no-distrib Don't create a CEF binary distribution. ++ --minimal-distrib Create a minimal CEF binary distribution. ++ --minimal-distrib-only ++ Create a minimal CEF binary distribution only. ++ --client-distrib Create a client CEF binary distribution. ++ --client-distrib-only ++ Create a client CEF binary distribution only. ++ --no-distrib-docs Don't create CEF documentation. ++ --no-distrib-archive Don't create archives for output directories. ++ --clean-artifacts Clean the artifacts output directory. ++ --distrib-subdir=DISTRIBSUBDIR ++ CEF distrib dir name, child of ++ chromium/src/cef/binary_distrib ++""" ++ + # Copyright (c) 2014 The Chromium Embedded Framework Authors. All rights + # reserved. Use of this source code is governed by a BSD-style license that + # can be found in the LICENSE file. +@@ -888,6 +972,12 @@ if not options.nobuild and (chromium_checkout_changed or \ + command = 'ninja -C ' + if options.verbosebuild: + command = 'ninja -v -C' ++ ++ # -- CEF Python modification below ++ assert os.environ['CEFPYTHON_NINJA_JOBS'] ++ command = 'ninja -v -j' + os.environ['CEFPYTHON_NINJA_JOBS'] + ' -C' ++ # -- ++ + target = ' ' + options.buildtarget + if options.buildtests: + target = target + ' cef_unittests' diff --git a/tools/automate.py b/tools/automate.py new file mode 100644 index 000000000..d380a4d3f --- /dev/null +++ b/tools/automate.py @@ -0,0 +1,479 @@ +# Copyright (c) 2016 CEF Python, see the Authors file. All rights reserved. + +"""Build CEF Python and use prebuilt CEF binaries or build CEF from sources. + +Usage: + automate.py (--prebuilt-cef | --build-cef) + [--cef-branch BRANCH] [--cef-commit COMMIT] + [--build-dir BUILDDIR] [--cef-build-dir CEFBUILDDIR] + [--ninja-jobs JOBS] [--gyp-generators GENERATORS] + [--gyp-msvs-version MSVS] + automate.py (-h | --help) [type -h to show full description for options] + +Options: + -h --help Show this help message. + --prebuilt-cef Whether to use prebuilt CEF binaries. Prebuilt + binaries for Linux are built on Ubuntu. + --build-cef Whether to build CEF from sources with the cefpython + patches applied. + --cef-branch CEF branch. Defaults to CHROME_VERSION_BUILD from + "src/version/cef_version_{platform}.h" (TODO). + --cef-commit CEF revision. Defaults to CEF_COMMIT_HASH from + "src/version/cef_version_{platform}.h" (TODO). + --build-dir Build directory. + --cef-build-dir CEF build directory. By default same as --build-dir. + --ninja-jobs How many CEF jobs to run in parallel. To speed up + building set it to number of cores in your CPU. + By default set to cpu_count / 2. + --gyp-generators Set GYP_GENERATORS [default: ninja]. + --gyp-msvs-version Set GYP_MSVS_VERSION. + +""" + +import os +import sys +import shlex +import subprocess +import platform +import docopt +import struct +import re +import stat +import glob +import shutil +import multiprocessing + +# CONSTANTS +ARCH32 = (8 * struct.calcsize('P') == 32) +ARCH64 = (8 * struct.calcsize('P') == 64) +OS_POSTFIX = ("win" if platform.system() == "Windows" else + "linux" if platform.system() == "Linux" else + "mac" if platform.system() == "Darwin" else "unknown") +OS_POSTFIX2 = "unknown" +if OS_POSTFIX == "win": + OS_POSTFIX2 = "win32" if ARCH32 else "win64" +elif OS_POSTFIX == "mac": + OS_POSTFIX2 = "mac32" if ARCH32 else "mac64" +elif OS_POSTFIX == "linux": + OS_POSTFIX2 = "linux32" if ARCH32 else "linux64" + +CEF_GIT_URL = "https://bitbucket.org/chromiumembedded/cef.git" + +VS2015_VCVARS = "\"C:\Program Files (x86)\\Microsoft Visual Studio 14.0" \ + "\\VC\\bin\\vcvars32.bat\"" \ + if ARCH32 else \ + "\"C:\Program Files (x86)\\Microsoft Visual Studio 14.0" \ + "\\VC\\bin\\amd64\\vcvars64.bat\"" + +VS2013_VCVARS = "\"C:\Program Files (x86)\\Microsoft Visual Studio 12.0" \ + "\\VC\\bin\\vcvars32.bat\"" \ + if ARCH32 else \ + "\"C:\Program Files (x86)\\Microsoft Visual Studio 12.0" \ + "\\VC\\bin\\amd64\\vcvars64.bat\"" + +VS2008_VCVARS = "\"%LocalAppData%\\Programs\\Common\\Microsoft" \ + "\\Visual C++ for Python\\9.0\\vcvarsall.bat\" x86" \ + if ARCH32 else \ + "\"%LocalAppData%\\Programs\\Common\\Microsoft" \ + "\\Visual C++ for Python\\9.0\\vcvarsall.bat\" amd64" + + +class Options(object): + """Options from command-line and internal options.""" + + # From command-line + prebuilt_cef = False + build_cef = False + cef_branch = "" + cef_commit = "" + build_dir = "" + cef_build_dir = "" + ninja_jobs = None + gyp_generators = "ninja" + gyp_msvs_version = "" + + # Internal options + depot_tools_dir = "" + tools_dir = "" + cefpython_dir = "" + binary_distrib = "" + release_build = True + build_type = "" # Will be set according to "release_build" value + + +def main(): + """Main entry point.""" + setup_options(docopt.docopt(__doc__)) + + if Options.build_cef: + build_cef() + elif Options.prebuilt_cef: + prebuilt_cef() + + +def setup_options(docopt_args): + """Setup options from cmd-line and internal options.""" + + # Populate Options using command line arguments + usage = __doc__ + for key in docopt_args: + value = docopt_args[key] + if key.startswith("--"): + match = re.search(r"\[%s\s+([^\]]+)\]" % (re.escape(key),), + usage) + if match: + arg_key = match.group(1) + value = docopt_args[arg_key] + key2 = key.replace("--", "").replace("-", "_") + if hasattr(Options, key2) and value is not None: + setattr(Options, key2, value) + + Options.tools_dir = os.path.dirname(os.path.realpath(__file__)) + Options.cefpython_dir = os.path.dirname(Options.tools_dir) + + # --cef-branch + # TODO: by default use branch by calling cefpython_version() + if not Options.cef_branch: + print("[automate.py] ERROR: --cef-branch flag is required") + sys.exit(1) + + # --gyp-msvs-version + if not Options.gyp_msvs_version: + if int(Options.cef_branch) >= 2704: + Options.gyp_msvs_version = "2015" + else: + Options.gyp_msvs_version = "2013" + + # --build-dir + if Options.build_dir: + Options.build_dir = os.path.realpath(Options.build_dir) + else: + Options.build_dir = os.path.join(Options.cefpython_dir, "build") + if " " in Options.build_dir: + print("[automate.py] ERROR: Build dir cannot contain spaces") + print(">> " + Options.build_dir) + sys.exit(1) + + # --cef-build-dir + if Options.cef_build_dir: + Options.cef_build_dir = os.path.realpath(Options.cef_build_dir) + else: + Options.cef_build_dir = Options.build_dir + if " " in Options.cef_build_dir: + print("[automate.py] ERROR: CEF build dir cannot contain spaces") + print(">> " + Options.cef_build_dir) + sys.exit(1) + + # --depot-tools-dir + Options.depot_tools_dir = os.path.join(Options.cef_build_dir, + "depot_tools") + # binary_distrib + Options.binary_distrib = os.path.join(Options.cef_build_dir, "chromium", + "src", "cef", "binary_distrib") + + # build_type + Options.build_type = "Release" if Options.release_build else "Debug" + + # ninja_jobs + # cpu_count() returns number of CPU threads, not CPU cores. + # On i5 with 2 cores and 4 cpu threads the default of 4 ninja + # jobs slows down computer significantly. + Options.ninja_jobs = int(multiprocessing.cpu_count() / 2) + if Options.ninja_jobs < 1: + Options.ninja_jobs = 1 + + +def build_cef(): + """Build CEF from sources.""" + + # cef/ repo + create_cef_directories() + + # Delete binary_distrib + if os.path.exists(Options.binary_distrib): + delete_directory(Options.binary_distrib) + + # Run automate-git.py + run_automate_git() + + # Build cefclient, cefsimple, libcef_dll_wrapper + build_cef_projects() + + # TODO: Copy bin/lib and README.txt to build/win32/ + + +def create_cef_directories(): + """Create cef/ directories in cef_build_dir/ and in chromium/src/ .""" + cef_dir = os.path.join(Options.cef_build_dir, "cef") + src_dir = os.path.join(Options.cef_build_dir, "chromium", "src") + cef_dir2 = os.path.join(src_dir, "cef") + # Clone cef repo and checkout branch + if os.path.exists(cef_dir): + delete_directory(cef_dir) + run_git("clone %s cef" % CEF_GIT_URL, Options.cef_build_dir) + run_git("checkout %s" % Options.cef_branch, cef_dir) + if Options.cef_commit: + run_git("checkout %s" % Options.cef_commit, cef_dir) + # Update cef patches + update_cef_patches() + # Copy cef/ to chromium/src/ but only if chromium/src/ exists. + if os.path.exists(src_dir): + if os.path.exists(cef_dir2): + delete_directory(cef_dir2) + shutil.copytree(cef_dir, cef_dir2) + + +def update_cef_patches(): + """Update cef/patch/ directory with CEF Python patches. + Issue73 is applied in getenv() by setting appropriate env var. + + Note that this modifies only cef_build_dir/cef/ directory. If the + build was run previously then there is a copy of the cef/ directory + in the cef_build_dir/chromium/ directory which is not being updated. + """ + print("[automate.py] Updating CEF patches with CEF Python patches") + cef_dir = os.path.join(Options.cef_build_dir, "cef") + cef_patch_dir = os.path.join(cef_dir, "patch") + cef_patches_dir = os.path.join(cef_patch_dir, "patches") + + # Copy src/patches/*.patch to cef/patch/patches/ + cefpython_patches_dir = os.path.join(Options.cefpython_dir, "patches") + cefpython_patches = glob.glob(os.path.join(cefpython_patches_dir, + "*.patch")) + for file_ in cefpython_patches: + print("[automate.py] Copying %s to %s" + % (os.path.basename(file_), cef_patches_dir)) + shutil.copy(file_, cef_patches_dir) + + # Append cefpython/patches/patch.py to cef/patch/patch.cfg + cef_patch_cfg = os.path.join(cef_patch_dir, "patch.cfg") + print("[automate.py] Overwriting %s" % cef_patch_cfg) + with open(cef_patch_cfg, "rb") as fp: + cef_patch_cfg_contents = fp.read() + cef_patch_cfg_contents += "\n" + cefpython_patch_cfg = os.path.join(cefpython_patches_dir, "patch.py") + with open(cefpython_patch_cfg, "rb") as fp: + cefpython_patch_cfg_contents = fp.read() + with open(cef_patch_cfg, "wb") as fp: + cef_patch_cfg_contents = cef_patch_cfg_contents.replace("\r\n", "\n") + cefpython_patch_cfg_contents = cefpython_patch_cfg_contents.replace( + "\r\n", "\n") + new_contents = cef_patch_cfg_contents + cefpython_patch_cfg_contents + fp.write(new_contents) + + +def build_cef_projects(): + """Build cefclient, cefsimple, libcef_dll_wrapper.""" + print("[automate.py] Binary distrib created in %s" + % Options.binary_distrib) + print("[automate.py] Building cef projects...") + + # Find cef_binary directories and create the cef_binary/build/ dir + files = glob.glob(os.path.join(Options.binary_distrib, + "*_symbols")) + assert len(files) == 1, "More than one dir with release symbols found" + symbols = files[0] + if Options.release_build: + cef_binary = symbols.replace("_release_symbols", "") + else: + cef_binary = symbols.replace("_debug_symbols", "") + assert "symbols" not in os.path.basename(cef_binary) + build_cefclient = os.path.join(cef_binary, "build_cefclient") + build_wrapper_mt = os.path.join(cef_binary, "build_wrapper_mt") + build_wrapper_md = os.path.join(cef_binary, "build_wrapper_md") + os.makedirs(build_cefclient) + os.makedirs(build_wrapper_mt) + os.makedirs(build_wrapper_md) + + # Build cefclient and cefsimple + print("[automate.py] Building cefclient and cefsimple...") + command = "" + if platform.system() == "Windows": + if int(Options.cef_branch) >= 2704: + command += VS2015_VCVARS + " && " + else: + command += VS2013_VCVARS + " && " + command += "cmake -G \"Ninja\" -DCMAKE_BUILD_TYPE=%s .. && " \ + % Options.build_type + command += "ninja cefclient cefsimple" + run_command(command, build_cefclient) + print("[automate.py] OK") + if platform.system() == "Windows": + assert(os.path.exists(os.path.join(build_cefclient, "cefclient", + "cefclient.exe"))) + + # Command to build libcef_dll_wrapper + wrapper_command = "" + if platform.system() == "Windows": + wrapper_command += VS2008_VCVARS + " && " + wrapper_command += "cmake -G \"Ninja\" -DCMAKE_BUILD_TYPE=%s .. && " \ + % Options.build_type + wrapper_command += "ninja libcef_dll_wrapper" + + # Build libcef_dll_wrapper_mt.lib + print("[automate.py] Building libcef_dll_wrapper /MT") + old_gyp_msvs_version = Options.gyp_msvs_version + Options.gyp_msvs_version = get_msvs_for_python() + run_command(wrapper_command, build_wrapper_mt) + Options.gyp_msvs_version = old_gyp_msvs_version + print("[automate.py] OK") + if platform.system() == "Windows": + assert(os.path.exists(os.path.join(build_wrapper_mt, "libcef_dll", + "libcef_dll_wrapper.lib"))) + + # Build libcef_dll_wrapper_md.lib + print("[automate.py] Building libcef_dll_wrapper /MD") + old_gyp_msvs_version = Options.gyp_msvs_version + Options.gyp_msvs_version = get_msvs_for_python() + # Replace /MT with /MD /wd\"4275\" in CMakeLists.txt + # Warnings are treated as errors so this needs to be ignored: + # >> warning C4275: non dll-interface class 'stdext::exception' + # >> used as base for dll-interface class 'std::bad_cast' + # This warning occurs only in VS2008, in VS2013 not. + cmakelists = os.path.join(cef_binary, "CMakeLists.txt") + with open(cmakelists, "rb") as fp: + contents = fp.read() + contents = contents.replace(r"/MT ", r"/MD /wd\"4275\" ") + contents = contents.replace(r"/MTd ", r"/MDd /wd\"4275\" ") + with open(cmakelists, "wb") as fp: + fp.write(contents) + run_command(wrapper_command, build_wrapper_md) + Options.gyp_msvs_version = old_gyp_msvs_version + print("[automate.py] OK") + if platform.system() == "Windows": + assert(os.path.exists(os.path.join(build_wrapper_md, "libcef_dll", + "libcef_dll_wrapper.lib"))) + + +def get_msvs_for_python(): + """Get MSVS version (eg 2008) for current python running.""" + if sys.version_info[:2] == (2, 7): + return "2008" + elif sys.version_info[:2] == (3, 4): + return "2010" + elif sys.version_info[:2] == (3, 5): + return "2015" + else: + print("ERROR: This python version is not yet supported") + sys.exit(1) + + +def prebuilt_cef(): + """Download CEF prebuilt binaries from GitHub Releases, + eg tag 'upstream-cef47'.""" + pass + + +def getenv(): + """Env variables passed to shell when running commands.""" + env = os.environ + env["PATH"] = Options.depot_tools_dir + os.pathsep + env["PATH"] + env["GYP_GENERATORS"] = Options.gyp_generators + env["GYP_MSVS_VERSION"] = Options.gyp_msvs_version + # Issue73 patch applied + env["GYP_DEFINES"] = "use_allocator=none" + # To perform an official build set GYP_DEFINES=buildtype=Official. + # This will disable debugging code and enable additional link-time + # optimizations in Release builds. + if Options.release_build: + env["GYP_DEFINES"] += " buildtype=Official" + # Modifications to automate-git.py + env["CEFPYTHON_NINJA_JOBS"] = str(Options.ninja_jobs) + return env + + +def run_command(command_line, working_dir): + """Run command in a given directory with env variables set.""" + print("[automate.py] Running '"+command_line+"' in '" + + working_dir+"'...") + args = shlex.split(command_line.replace("\\", "\\\\")) + return subprocess.check_call(args, cwd=working_dir, env=getenv(), + shell=(platform.system() == "Windows")) + + +def run_python(command_line, working_dir): + """Run python script using depot_tools.""" + python = "python" + return run_command("%s %s" % (python, command_line), working_dir) + + +def run_git(command_line, working_dir): + """Run git command using depot_tools.""" + return run_command("git %s" % command_line, working_dir) + + +def run_automate_git(): + """Run CEF automate-git.py.""" + # TODO: run automate-git.py using Python 2.7 from depot_tools + script = os.path.join(Options.cefpython_dir, "tools", "automate-git.py") + """ + Example automate-git.py command: + C:\chromium>call python automate-git.py --download-dir=./test/ + --branch=2526 --no-debug-build --verbose-build + Run ninja build manually: + cd chromium/src + ninja -v -j2 -Cout\Release cefclient + """ + args = [] + if ARCH64: + args.append("--x64-build") + args.append("--download-dir=" + Options.cef_build_dir) + args.append("--branch=" + Options.cef_branch) + if Options.release_build: + args.append("--no-debug-build") + args.append("--verbose-build") + # --force-build sets --force-distrib by default + # ninja will only recompile files that changed + args.append("--force-build") + # We clone cef repository ourselves and update cef patches with ours, + # so don't fetch/update CEF repo. + args.append("--no-cef-update") + args.append("--no-distrib-archive") + + args = " ".join(args) + return run_python(script+" "+args, Options.cef_build_dir) + + +def delete_directory(path): + """Delete directory recursively.""" + if os.path.exists(path): + print("[automate.py] Deleting directory %s" % path) + shutil.rmtree(path, onerror=onerror) + + +def onerror(func, path, _): + """Fix file permission on error and retry operation.""" + if not os.access(path, os.W_OK): + os.chmod(path, stat.S_IWUSR) + func(path) + else: + raise + + +def cefpython_version(): + """Get CEF version from the 'src/version/' directory.""" + header_file = os.path.join(Options.cefpython_dir, "src", "version", + "cef_version_"+OS_POSTFIX+".h") + with open(header_file, "rU") as fp: + contents = fp.read() + ret = dict() + + # cef_branch + match = re.match(r"#define CHROME_VERSION_BUILD (\d+)", contents) + if not match: + print("[automate.py] CHROME_VERSION_BUILD not found in "+header_file) + sys.exit(1) + ret["cef_branch"] = match.group(1) + + # cef_commit + match = re.match(r"#define CEF_COMMIT_HASH \"(\w+)\"", contents) + if not match: + print("[automate.py] CEF_COMMIT_HASH not found in "+header_file) + sys.exit(1) + ret["cef_commit"] = match.group(1) + + return ret + + +if __name__ == "__main__": + main() diff --git a/tools/requirements.txt b/tools/requirements.txt new file mode 100644 index 000000000..a13f80a5e --- /dev/null +++ b/tools/requirements.txt @@ -0,0 +1,2 @@ +cython == 0.19.2 +docopt >= 0.6.2 diff --git a/tools/toc.py b/tools/toc.py new file mode 100644 index 000000000..4bfbd7c77 --- /dev/null +++ b/tools/toc.py @@ -0,0 +1,166 @@ +# Copyright (c) 2016 CEF Python, see the Authors file. All rights reserved. + +"""Create Table of contents (TOC) for a single .md file or for a directory. + +Usage: + toc.py FILE + toc.py DIR + +To ignore file when generating TOC, put an empty line just before H1. +""" + +import os +import sys +import re +import glob + + +def main(): + """Main entry point.""" + if (len(sys.argv) == 1 or + "-h" in sys.argv or + "--help" in sys.argv or + "/?" in sys.argv): + print(__doc__.strip()) + sys.exit(0) + arg1 = sys.argv[1] + if os.path.isdir(arg1): + (modified, warnings) = toc_dir(arg1) + if modified: + print("Done") + else: + print("No changes to TOCs. Files not modified.") + else: + (modified, warnings) = toc_file(arg1) + if modified: + print("Done") + else: + print("No changes to TOC. File not modified.") + if warnings: + print("Warnings: "+str(warnings)) + + +def toc_file(file_): + """A single file was passed to doctoc. Return bool whether modified + and the number of warnings.""" + with open(file_, "rb") as fo: + orig_contents = fo.read() + # Fix new lines just in case. Not using Python's "rU", + # it is causing strange issues. + orig_contents = re.sub(r"(\r\n|\r|\n)", os.linesep, orig_contents) + (tocsize, contents, warnings) = create_toc(orig_contents, file_) + if contents != orig_contents: + with open(file_, "wb") as fo: + fo.write(contents) + tocsize_str = ("TOC size: "+str(tocsize) if tocsize + else "TOC removed") + print("Modified: "+file_+" ("+tocsize_str+")") + return True, warnings + else: + return False, warnings + + +def toc_dir(dir_): + """A directory was passed to doctoc. Return bool whether any file was + modified and the number of warnings.""" + files = glob.glob(os.path.join(dir_, "*.md")) + modified_any = False + for file_ in files: + if "API-categories.md" in file_ or "API-index.md" in file_: + continue + (modified, warnings) = toc_file(file_) + if not modified_any: + modified_any = True if modified else False + return modified_any, warnings + + +def create_toc(contents, file_): + """Create or modify TOC for the document contents.""" + match = re.search(r"Table of contents:%s(\s*\* \[[^\]]+\]\([^)]+\)%s){2,}" + % (os.linesep, os.linesep), contents) + oldtoc = match.group(0) if match else None + (tocsize, toc, warnings) = parse_headings(contents, file_) + if oldtoc: + if not toc: + # If toc removed need to remove an additional new lines + # that was inserted after toc. + contents = contents.replace(oldtoc+os.linesep, toc) + else: + contents = contents.replace(oldtoc, toc) + elif tocsize: + # Insert after H1, but if there is text directly after H1 + # then insert after that text. + first_line = False + if not re.search(r"^#\s+", contents): + print("WARNING: missing H1 on first line. Ignoring file: "+file_) + return 0, contents, warnings+1 + lines = contents.splitlines() + contents = "" + toc_inserted = False + for line in lines: + if not first_line: + first_line = True + else: + if not toc_inserted and re.search(r"^(##|###)", line): + contents = contents[0:-len(os.linesep)] + contents += os.linesep + toc + os.linesep + os.linesep + toc_inserted = True + contents += line + os.linesep + return tocsize, contents, warnings + + +def parse_headings(raw_contents, file_): + """Parse contents looking for headings. Return a tuple with number + of TOC elements, the TOC fragment and the number of warnings.""" + # Remove code blocks + parsable_contents = re.sub(r"```[\s\S]+?```", "", raw_contents) + # Parse H1,H2,H3 + headings = re.findall(r"^(#|##|###)\s+(.*)", parsable_contents, + re.MULTILINE) + toc = "Table of contents:" + os.linesep + tocsize = 0 + warnings = 0 + count_h1 = 0 + count_h2 = 0 + for heading in headings: + level = heading[0] + level = (1 if level == "#" else + 2 if level == "##" else + 3 if level == "###" else None) + assert level is not None + title = heading[1].strip() + if level == 1: + count_h1 += 1 + if count_h1 > 1: + warnings += 1 + print("WARNING: found more than one H1 in "+file_) + continue + if level == 2: + count_h2 += 1 + hash_ = headinghash(title) + indent = "" + if level == 3: + if count_h2: + # If there was no H2 yet then H3 shouldn't have indent. + indent = " " * 2 + toc += indent + "* [%s](#%s)" % (title, hash_) + os.linesep + tocsize += 1 + if tocsize <= 1: + # If there is only one H2/H3 heading do not create TOC. + toc = "" + tocsize = 0 + return tocsize, toc, warnings + + +def headinghash(title): + """Get a link hash for a heading H1,H2,H3.""" + hash_ = title.lower() + hash_ = re.sub(r"[^a-z0-9_\- ]+", r"", hash_) + hash_ = hash_.replace(" ", "-") + hash_ = re.sub(r"[-]+", r"-", hash_) + hash_ = re.sub(r"-$", r"", hash_) + return hash_ + + +if __name__ == "__main__": + main() From 169a1b20d3cd09879070d41aab28cfa195d2a7d5 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 20 Jun 2016 09:57:48 +0200 Subject: [PATCH 051/557] Add docs/ directory and move api/ there. Add build instructions doc. --- README.md | 12 +- docs/Build-instructions.md | 122 ++++++++++++++++++ {api => docs/api}/API-categories.md | 0 {api => docs/api}/API-index.md | 0 {api => docs/api}/ApplicationSettings.md | 0 {api => docs/api}/Browser.md | 0 {api => docs/api}/BrowserSettings.md | 0 {api => docs/api}/Callback.md | 0 {api => docs/api}/CommandLineSwitches.md | 0 {api => docs/api}/Cookie.md | 0 {api => docs/api}/CookieManager.md | 0 {api => docs/api}/CookieVisitor.md | 0 {api => docs/api}/DisplayHandler.md | 0 {api => docs/api}/DownloadHandler.md | 0 {api => docs/api}/DpiAware.md | 0 {api => docs/api}/Frame.md | 0 {api => docs/api}/JavascriptBindings.md | 0 {api => docs/api}/JavascriptCallback.md | 0 {api => docs/api}/JavascriptContextHandler.md | 2 + {api => docs/api}/JavascriptDialogHandler.md | 0 {api => docs/api}/KeyboardHandler.md | 0 {api => docs/api}/LifespanHandler.md | 0 {api => docs/api}/LoadHandler.md | 0 {api => docs/api}/NetworkError.md | 0 {api => docs/api}/PaintBuffer.md | 0 {api => docs/api}/RenderHandler.md | 0 {api => docs/api}/Request.md | 12 +- {api => docs/api}/RequestHandler.md | 0 {api => docs/api}/ResourceHandler.md | 0 {api => docs/api}/Response.md | 0 {api => docs/api}/StringVisitor.md | 0 {api => docs/api}/VirtualKey.md | 0 {api => docs/api}/WebPluginInfo.md | 0 {api => docs/api}/WebRequest.md | 0 {api => docs/api}/WebRequestClient.md | 0 {api => docs/api}/WindowInfo.md | 0 {api => docs/api}/WindowUtils.md | 0 {api => docs/api}/cefpython.md | 0 38 files changed, 136 insertions(+), 12 deletions(-) create mode 100644 docs/Build-instructions.md rename {api => docs/api}/API-categories.md (100%) rename {api => docs/api}/API-index.md (100%) rename {api => docs/api}/ApplicationSettings.md (100%) rename {api => docs/api}/Browser.md (100%) rename {api => docs/api}/BrowserSettings.md (100%) rename {api => docs/api}/Callback.md (100%) rename {api => docs/api}/CommandLineSwitches.md (100%) rename {api => docs/api}/Cookie.md (100%) rename {api => docs/api}/CookieManager.md (100%) rename {api => docs/api}/CookieVisitor.md (100%) rename {api => docs/api}/DisplayHandler.md (100%) rename {api => docs/api}/DownloadHandler.md (100%) rename {api => docs/api}/DpiAware.md (100%) rename {api => docs/api}/Frame.md (100%) rename {api => docs/api}/JavascriptBindings.md (100%) rename {api => docs/api}/JavascriptCallback.md (100%) rename {api => docs/api}/JavascriptContextHandler.md (94%) rename {api => docs/api}/JavascriptDialogHandler.md (100%) rename {api => docs/api}/KeyboardHandler.md (100%) rename {api => docs/api}/LifespanHandler.md (100%) rename {api => docs/api}/LoadHandler.md (100%) rename {api => docs/api}/NetworkError.md (100%) rename {api => docs/api}/PaintBuffer.md (100%) rename {api => docs/api}/RenderHandler.md (100%) rename {api => docs/api}/Request.md (98%) rename {api => docs/api}/RequestHandler.md (100%) rename {api => docs/api}/ResourceHandler.md (100%) rename {api => docs/api}/Response.md (100%) rename {api => docs/api}/StringVisitor.md (100%) rename {api => docs/api}/VirtualKey.md (100%) rename {api => docs/api}/WebPluginInfo.md (100%) rename {api => docs/api}/WebRequest.md (100%) rename {api => docs/api}/WebRequestClient.md (100%) rename {api => docs/api}/WindowInfo.md (100%) rename {api => docs/api}/WindowUtils.md (100%) rename {api => docs/api}/cefpython.md (100%) diff --git a/README.md b/README.md index 4cca9dfd6..cdff22c3c 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![](https://img.shields.io/badge/pypi-v31.2-blue.png "PyPI latest release")](https://pypi.python.org/pypi/cefpython3/) [![](https://img.shields.io/badge/commits%20since-v31.2-lightgray.png "Commits since v31.2 release")](https://github.com/cztomczak/cefpython/compare/05366f2...master) -__NOTES__: +__NOTES__: * Repository rewritten on 2016-02-15 to reduce its size. Please clone it again. * Master branch is a work in progress. When building use the cefpython31 @@ -23,10 +23,10 @@ Table of contents: CEF Python is an open source project founded by [Czarek Tomczak](http://www.linkedin.com/in/czarektomczak) in 2012 to provide python bindings for the [Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef). See the growing list of [applications using CEF](http://en.wikipedia.org/wiki/Chromium_Embedded_Framework#Applications_using_CEF) on wikipedia. Examples of embedding CEF browser are available for many popular GUI toolkits including: [wxPython](../../wiki/wxPython), [PyGTK](../../wiki/PyGTK), [PyQt](../../wiki/PyQt), [PySide](../../wiki/PySide), [Kivy](../../wiki/Kivy), [Panda3D](../../wiki/Panda3D) and [PyWin32](src/windows/binaries_32bit/pywin32.py). -Some use cases for CEF: +Some use cases for CEF: * Embed a web browser control with great HTML5 support (based on Chromium) -* Use it to create a HTML5 based GUI in an application. This can act as a replacement for GUI toolkits like wxWidgets/Qt/Gtk. For native communication between javascript and python use [javascript bindings](../../wiki/JavascriptBindings). Another option is to run an internal python web server and use websockets/XMLHttpRequest for js<>python communication. This way you can write a desktop app in the same way you write web apps. +* Use it to create a HTML5 based GUI in an application. This can act as a replacement for GUI toolkits like wxWidgets/Qt/Gtk. For native communication between javascript and python use [javascript bindings](../../wiki/JavascriptBindings). Another option is to run an internal python web server and use websockets/XMLHttpRequest for js<>python communication. This way you can write a desktop app in the same way you write web apps. * Render web content off-screen in applications that use custom drawing frameworks. See the [Kivy](../../wiki/Kivy) and [Panda3D](../../wiki/Panda3D) examples. * Use it for automated testing of existing web applications. Use it for web scraping, or as a web crawler or other kind of internet bots. @@ -46,13 +46,13 @@ On Win/Mac you can install from PyPI using this command: * For Linux: see the [Download_CEF3_Linux](../../wiki/Download_CEF3_Linux) wiki page. * For Mac: see the [Download_CEF3_Mac](../../wiki/Download_CEF3_Mac) wiki page. -__New releases RSS/Atom feed__ +__New releases RSS/Atom feed__ To be notified of new releases subscribe to this [Atom feed](https://github.com/cztomczak/cefpython/releases.atom). ## Support -* API docs are in the [api/](api/) directory -* See [Wiki Pages](../../wiki) +* API docs are in the [docs/api/](docs/api/) directory +* See also [Wiki Pages](../../wiki) * Ask questions and report problems on the [Forum](https://groups.google.com/group/cefpython) * Please do not ask questions in the Issue Tracker diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md new file mode 100644 index 000000000..93d12d615 --- /dev/null +++ b/docs/Build-instructions.md @@ -0,0 +1,122 @@ +# Build instructions + +There are two types of builds you can perform. You can build +PyCEF using the prebuilt CEF binaries. Or you can build both +PyCEF and CEF from sources. Building CEF is a long process that +can take hours. In the tools/ directory there is the automate.py +script that automates building. However before you can run it +you must satisfy some requirements. + + +Table of contents: +* [Requirements](#requirements) +* [Build PyCEF using prebuilt CEF binaries](#build-pycef-using-prebuilt-cef-binaries) +* [Build both PyCEF and CEF from sources](#build-both-pycef-and-cef-from-sources) +* [Build CEF manually](#build-cef-manually) +* [How to patch](#how-to-patch) +* [Ninja build slows down computer](#ninja-build-slows-down-computer) + + +## Requirements + +Below are platform specific requirements. Do these first before +following instructions in the "All platforms" section that lists +requirements common for all platforms. + +__Windows__ + +* For Python 2.7 - VS2008 compiler is required: + http://www.microsoft.com/en-us/download/details.aspx?id=44266 +* For Python 3.4 - VS2010 compiler is required: + https://docs.python.org/3.4/using/windows.html#compiling-python-on-windows +* For Python 3.5 - VS2015 compiler is required: + https://docs.python.org/3.5/using/windows.html#compiling-python-on-windows +* To build CEF from sources: + * Use Win7 x64 or later. 32-bit OS'es are not supported. For more details see [here] + (https://www.chromium.org/developers/how-tos/build-instructions-windows). + * For CEF branch >= 2704 install VS2015 Update 2 or later + * For CEF branch < 2704 install VS2013 Update 4 or later + * Install [CMake](https://cmake.org/) 2.8.12.1 or newer and add cmake.exe + to PATH + * Install [ninja](http://martine.github.io/ninja/) and add ninja.exe + to PATH + * You need about 16 GB of RAM during linking. If there is an error + just add additional virtual memory. + * For Python 2.7 copy "pycef/src/windows/stdint.h" to + "%LocalAppData%\Programs\Common\Microsoft\Visual C++ for Python\9.0\VC\include\" + +__All platforms__ + +* Install dependencies for the automate.py tool by executing: + `cd tools/ && pip install -r requirements.txt`. This will install + some PyPI packages including Cython. On Windows installing Cython + requires a VS compiler - see instructions above for Windows. + + +## Build PyCEF using prebuilt CEF binaries + +Run the automate.py tool using the --prebuilt-cef flag: +``` +cd tools/ +python automate.py --prebuilt-cef +``` + +You should be fine by running it with the default options, but if you +need to customize the build then use the --help flag to see more. + + +## Build both PyCEF and CEF from sources + +Run the automate.py tool using the --build-cef flag: +``` +cd tools/ +python automate.py --build-cef --cef-branch 2526 +``` + +You should be fine by running it with the default options, but if you +need to customize the build then use the --help flag to see more. + + +## Build CEF manually + +CEF Python official binaries come with custom CEF binaries with +a few patches applied for our use case. These patches are in the +patches/ directory. + +On Linux before running any of CEF tools apply the issue73 patch +first. + +To build CEF follow the instructions on the Branches and +Building CEF wiki page: +https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding + +After it is successfully built - apply patches, rebuild and remake +distribs. + +Note that CEF patches must be applied in the "download_dir/chromium/src/cef/" +directory, not in the "download_dir/cef/" directory. + + +## How to patch + +Create a patch from unstaged changes in current directory: +``` +cd chromium/src/cef/ +git diff --no-prefix --relative > cef.gyp.patch +``` + +Apply a patch in current directory: +``` +cd chromium/src/cef/ +git apply cef.gyp.patch +``` + + +## Ninja build slows down computer + +If ninja slows down your computer too much (6 parallel jobs by default), +build manually with this command (where -j2 means to run 2 jobs in parallel): +``` +cd chromium/src +ninja -v -j2 -Cout\Release cefclient +``` diff --git a/api/API-categories.md b/docs/api/API-categories.md similarity index 100% rename from api/API-categories.md rename to docs/api/API-categories.md diff --git a/api/API-index.md b/docs/api/API-index.md similarity index 100% rename from api/API-index.md rename to docs/api/API-index.md diff --git a/api/ApplicationSettings.md b/docs/api/ApplicationSettings.md similarity index 100% rename from api/ApplicationSettings.md rename to docs/api/ApplicationSettings.md diff --git a/api/Browser.md b/docs/api/Browser.md similarity index 100% rename from api/Browser.md rename to docs/api/Browser.md diff --git a/api/BrowserSettings.md b/docs/api/BrowserSettings.md similarity index 100% rename from api/BrowserSettings.md rename to docs/api/BrowserSettings.md diff --git a/api/Callback.md b/docs/api/Callback.md similarity index 100% rename from api/Callback.md rename to docs/api/Callback.md diff --git a/api/CommandLineSwitches.md b/docs/api/CommandLineSwitches.md similarity index 100% rename from api/CommandLineSwitches.md rename to docs/api/CommandLineSwitches.md diff --git a/api/Cookie.md b/docs/api/Cookie.md similarity index 100% rename from api/Cookie.md rename to docs/api/Cookie.md diff --git a/api/CookieManager.md b/docs/api/CookieManager.md similarity index 100% rename from api/CookieManager.md rename to docs/api/CookieManager.md diff --git a/api/CookieVisitor.md b/docs/api/CookieVisitor.md similarity index 100% rename from api/CookieVisitor.md rename to docs/api/CookieVisitor.md diff --git a/api/DisplayHandler.md b/docs/api/DisplayHandler.md similarity index 100% rename from api/DisplayHandler.md rename to docs/api/DisplayHandler.md diff --git a/api/DownloadHandler.md b/docs/api/DownloadHandler.md similarity index 100% rename from api/DownloadHandler.md rename to docs/api/DownloadHandler.md diff --git a/api/DpiAware.md b/docs/api/DpiAware.md similarity index 100% rename from api/DpiAware.md rename to docs/api/DpiAware.md diff --git a/api/Frame.md b/docs/api/Frame.md similarity index 100% rename from api/Frame.md rename to docs/api/Frame.md diff --git a/api/JavascriptBindings.md b/docs/api/JavascriptBindings.md similarity index 100% rename from api/JavascriptBindings.md rename to docs/api/JavascriptBindings.md diff --git a/api/JavascriptCallback.md b/docs/api/JavascriptCallback.md similarity index 100% rename from api/JavascriptCallback.md rename to docs/api/JavascriptCallback.md diff --git a/api/JavascriptContextHandler.md b/docs/api/JavascriptContextHandler.md similarity index 94% rename from api/JavascriptContextHandler.md rename to docs/api/JavascriptContextHandler.md index 1adce1c18..a3dadb431 100644 --- a/api/JavascriptContextHandler.md +++ b/docs/api/JavascriptContextHandler.md @@ -24,6 +24,8 @@ Table of contents: Called shortly after (process message delay) the V8 context for a frame has been created. +If the page does not contain ` + + + +

      Main test

      +
      + + +""" +g_datauri = "data:text/html;base64,"+base64.b64encode(g_datauri_data.encode( + "utf-8", "replace")).decode("utf-8", "replace") + + +class MainTest_IsolatedTest(unittest.TestCase): + + def test_main(self): + """Main entry point.""" + # All this code must run inside one single test, otherwise strange + # things happen. + + # Test initialization of CEF + cef.Initialize({ + "debug": False, + "log_severity": cef.LOGSEVERITY_ERROR, + "log_file": "", + }) + + # Test global client callback + global g_client_handler + g_client_handler = ClientHandler(self) + cef.SetGlobalClientCallback("OnAfterCreated", + g_client_handler._OnAfterCreated) + + # Test creation of browser + global g_browser + g_browser = cef.CreateBrowserSync(url=g_datauri) + self.assertIsNotNone(g_browser, "Browser object") + + # Test client handler + g_browser.SetClientHandler(g_client_handler) + + # Test javascript bindings + global g_external + g_external = External(self) + bindings = cef.JavascriptBindings( + bindToFrames=False, bindToPopups=False) + bindings.SetFunction("test_function", g_external.test_function) + bindings.SetProperty("test_property1", g_external.test_property1) + bindings.SetProperty("test_property2", g_external.test_property2) + bindings.SetObject("external", g_external) + g_browser.SetJavascriptBindings(bindings) + + # Run message loop for 0.5 sec. + # noinspection PyTypeChecker + for i in range(MESSAGE_LOOP_RANGE): + cef.MessageLoopWork() + time.sleep(0.01) + + # Test browser closing. Remember to clean reference. + g_browser.CloseBrowser(True) + g_browser = None + + # Give it some time to close before calling shutdown. + # noinspection PyTypeChecker + for i in range(25): + cef.MessageLoopWork() + time.sleep(0.01) + + # Client handler asserts + self.assertTrue(g_client_handler.OnAfterCreated_called, + "OnAfterCreated() call") + self.assertTrue(g_client_handler.OnLoadStart_called, + "OnLoadStart() call") + self.assertTrue(g_client_handler.OnLoadEnd_called, + "OnLoadEnd() call") + self.assertTrue(g_client_handler.FrameSourceVisitor_called, + "FrameSourceVisitor.Visit() call") + self.assertEqual(g_client_handler.javascript_errors, 0, + "Javascript errors caught in OnConsoleMessage") + + # Javascript asserts + self.assertTrue(g_external.test_function_called, + "js test_function() call") + self.assertTrue(g_external.test_callbacks_called, + "js external.test_callbacks() call") + self.assertTrue(g_external.py_callback_called, + "py_callback() call from js external.test_callbacks()") + + # Test shutdown of CEF + cef.Shutdown() + + +class ClientHandler: + test_case = None + + OnAfterCreated_called = False + OnLoadStart_called = False + OnLoadEnd_called = False + + FrameSourceVisitor_called = False + frame_source_visitor = None + + javascript_errors = 0 + + def __init__(self, test_case): + self.test_case = test_case + + # noinspection PyUnusedLocal + def _OnAfterCreated(self, browser): + self.OnAfterCreated_called = True + + # noinspection PyUnusedLocal + def OnLoadStart(self, browser, frame): + self.test_case.assertEqual(browser.GetUrl(), g_datauri) + self.OnLoadStart_called = True + + # noinspection PyUnusedLocal + def OnLoadEnd(self, browser, frame, http_code): + self.test_case.assertEqual(http_code, 200) + self.frame_source_visitor = FrameSourceVisitor(self, self.test_case) + frame.GetSource(self.frame_source_visitor) + browser.ExecuteJavascript( + "print('ClientHandler.OnLoadEnd() ok')") + self.OnLoadEnd_called = True + + # noinspection PyUnusedLocal + def OnConsoleMessage(self, browser, message, source, line): + if "error" in message.lower() or "uncaught" in message.lower(): + self.javascript_errors += 1 + raise Exception(message) + + +class FrameSourceVisitor: + client_handler = None + test_case = None + + def __init__(self, client_handler, test_case): + self.client_handler = client_handler + self.test_case = test_case + + # noinspection PyUnusedLocal + def Visit(self, value): + self.test_case.assertIn("747ef3e6011b6a61e6b3c6e54bdd2dee", + g_datauri_data) + self.client_handler.FrameSourceVisitor_called = True + + +class External: + """Javascript 'window.external' object.""" + test_case = None + + # Test binding properties to the 'window' object. + test_property1 = "Test binding property to the 'window' object" + test_property2 = {"key1": test_property1, + "key2": ["Inside list", 1, 2]} + + test_function_called = False + test_callbacks_called = False + py_callback_called = False + + def __init__(self, test_case): + self.test_case = test_case + + def test_function(self): + """Test binding function to the 'window' object.""" + self.test_function_called = True + + def test_callbacks(self, js_callback): + """Test both javascript and python callbacks.""" + def py_callback(msg_from_js): + self.test_case.assertEqual(msg_from_js, + "String sent from Javascript") + self.py_callback_called = True + js_callback.Call("String sent from Python", py_callback) + self.test_callbacks_called = True + + +if __name__ == "__main__": + _runner.main(basename(__file__)) diff --git a/unittests/unittest_test.py b/unittests/unittest_test.py new file mode 100644 index 000000000..f504c1dcc --- /dev/null +++ b/unittests/unittest_test.py @@ -0,0 +1,60 @@ +"""Test the unittest itself.""" + +import unittest + +# Globals +g_count = 0 +g_setUpClass_count = 0 +g_tearDownClass_count = 0 +g_setUp_count = 0 +g_tearDown_count = 0 + + +class Test(unittest.TestCase): + count = 0 + + @classmethod + def setUpClass(cls): + global g_setUpClass_count + g_setUpClass_count += 1 + + @classmethod + def tearDownClass(cls): + global g_tearDownClass_count + g_tearDownClass_count += 1 + + def setUp(self): + global g_setUp_count + g_setUp_count += 1 + + def tearDown(self): + global g_tearDown_count + g_tearDown_count += 1 + + def test_unittest1(self): + global g_count + g_count += 1 + self.count += 1 + self.assertEqual(g_count, 1) + self.assertEqual(self.count, 1) + self.assertEqual(g_setUpClass_count, 1) + self.assertEqual(g_tearDownClass_count, 0) + + def test_unittest2(self): + global g_count + g_count += 1 + self.count += 1 + self.assertEqual(g_count, 2) + self.assertEqual(self.count, 1) + self.assertEqual(g_setUpClass_count, 1) + self.assertEqual(g_tearDownClass_count, 0) + + def test_unittest3(self): + self.assertEqual(g_setUp_count, 3) + self.assertEqual(g_tearDown_count, 2) + self.assertEqual(g_setUpClass_count, 1) + self.assertEqual(g_tearDownClass_count, 0) + + +if __name__ == "__main__": + unittest.main() From a6eb058216c230c586095315a8fd5bbccf5dbb69 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sun, 18 Sep 2016 17:10:55 +0200 Subject: [PATCH 096/557] Update requirements.txt --- tools/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/requirements.txt b/tools/requirements.txt index a13f80a5e..b3593e587 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -1,2 +1,2 @@ -cython == 0.19.2 +cython == 0.24.1 docopt >= 0.6.2 From eeed61c8152604ca7e86d90b83ab079486a334fd Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sun, 18 Sep 2016 17:13:38 +0200 Subject: [PATCH 097/557] Update Build-instructions.md - Cython version must match exactly --- docs/Build-instructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index 600957d7f..c5569b71f 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -44,7 +44,7 @@ binaries from GH releases. 4) Install python dependencies by executing: `cd cefpython/tools/ && sudo pip install -r requirements.txt` - (Cython 0.19.2 required - the version must match exactly) + (Cython version from requirements.txt must match exactly) 5) Download 64-bit Linux binaries and libraries from [GH releases](https://github.com/cztomczak/cefpython/releases) From 1aabf8eee182111f7731b5a65f713e2d4215464b Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sun, 18 Sep 2016 17:25:05 +0200 Subject: [PATCH 098/557] Update API-categories.md --- api/API-categories.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/api/API-categories.md b/api/API-categories.md index e553234fa..68f7e8c02 100644 --- a/api/API-categories.md +++ b/api/API-categories.md @@ -3,6 +3,11 @@ # API categories +### Modules + + * [cefpython](cefpython.md) module + + ### Settings * [ApplicationSettings](ApplicationSettings.md) dictionary @@ -17,6 +22,7 @@ * [Cookie](Cookie.md) class * [CookieManager](CookieManager.md) class * [DpiAware](DpiAware.md) class (Win) + * [DragData](DragData.md) object * [Frame](Frame.md) object * [JavascriptBindings](JavascriptBindings.md) class * [JavascriptCallback](JavascriptCallback.md) object @@ -42,7 +48,3 @@ * [RequestHandler](RequestHandler.md) * [ResourceHandler](ResourceHandler.md) - -### Modules - - * [cefpython](cefpython.md) module From 15fb9f8eaf61bc834a1a9f7797528d9262a5bed1 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 19 Sep 2016 08:47:01 +0200 Subject: [PATCH 099/557] Enhance unit tests (#59). Display summary with real number of tests ran including sub-tests in main_test. Ensure that messages are coming from Javascript in OnConsoleMessage. Automate checking for True/False asserts in ClientHandler and External. --- unittests/{_runner.py => _test_runner.py} | 15 +- unittests/isolated_test.py | 4 +- unittests/main_test.py | 164 +++++++++++++--------- 3 files changed, 108 insertions(+), 75 deletions(-) rename unittests/{_runner.py => _test_runner.py} (94%) diff --git a/unittests/_runner.py b/unittests/_test_runner.py similarity index 94% rename from unittests/_runner.py rename to unittests/_test_runner.py index e652258c8..af34519c6 100644 --- a/unittests/_runner.py +++ b/unittests/_test_runner.py @@ -3,7 +3,7 @@ """Run unit tests. With no arguments all tests are run. Read notes below. Usage: - _runner.py [FILE | _TESTCASE] + _test_runner.py [FILE | _TESTCASE] Options: FILE Run tests from single file @@ -83,7 +83,7 @@ def run_testcase(self, testcase): self._discover("[!_]*.py", testcase) assert not self._count_suites(self._isolated_suites) if not self._count_suites(self._suites): - print("[_runner.py] ERROR: test case not found") + print("[_test_runner.py] ERROR: test case not found") sys.exit(1) # Import errors found during discovery are ignored self._run_suites(self._suites) @@ -140,7 +140,7 @@ def _run_suites_in_isolation(self, suites): # Run test using new instance of Python interpreter try: output = subprocess.check_output( - ["python", "_runner.py", testcase_id], + ["python", "_test_runner.py", testcase_id], stderr=subprocess.STDOUT) exit_code = 0 except subprocess.CalledProcessError as exc: @@ -148,6 +148,9 @@ def _run_suites_in_isolation(self, suites): exit_code = exc.returncode if type(output) != str: output = output.decode("utf-8", errors="replace") + match = re.search(r"Ran (\d+) sub-tests in \w+", output) + if match: + self.ran += int(match.group(1)) sys.stdout.write(output) # If tests failed parse output for errors/failures if exit_code: @@ -228,9 +231,9 @@ def _print_summary(self): # type: () -> None """Print summary and exit.""" print("-"*70) - print("[_runner.py] Ran "+str(self.ran)+" tests in total") + print("[_test_runner.py] Ran "+str(self.ran)+" tests in total") if self.errors or self.failures: - failed_str = "[_runner.py] FAILED (" + failed_str = "[_test_runner.py] FAILED (" if self.failures: failed_str += ("failures="+str(self.failures)) if self.errors: @@ -240,7 +243,7 @@ def _print_summary(self): failed_str += ")" print(failed_str) else: - print("[_runner.py] OK") + print("[_test_runner.py] OK") self._exit() def _exit(self): diff --git a/unittests/isolated_test.py b/unittests/isolated_test.py index 2fccf4ded..1700145bb 100644 --- a/unittests/isolated_test.py +++ b/unittests/isolated_test.py @@ -6,7 +6,7 @@ import unittest # noinspection PyUnresolvedReferences -import _runner +import _test_runner from os.path import basename # Globals @@ -35,4 +35,4 @@ def test_isolated3(self): if __name__ == "__main__": - _runner.main(basename(__file__)) + _test_runner.main(basename(__file__)) diff --git a/unittests/main_test.py b/unittests/main_test.py index 0ad200caf..f7da66f1a 100644 --- a/unittests/main_test.py +++ b/unittests/main_test.py @@ -1,15 +1,16 @@ """General testing of CEF Python.""" -# To show the window for an extended period of time increase this number. -MESSAGE_LOOP_RANGE = 25 # each iteration is 0.01 sec - import unittest # noinspection PyUnresolvedReferences -import _runner +import _test_runner from os.path import basename from cefpython3 import cefpython as cef import time import base64 +import sys + +# To show the window for an extended period of time increase this number. +MESSAGE_LOOP_RANGE = 25 # each iteration is 0.01 sec g_browser = None g_client_handler = None @@ -27,6 +28,7 @@ - - - -

      Popup

      - - window.open('example.html') - - - -

      HTML5 video and accelerated content

      - -HTML 5 video
      - -Accelerated canvas
      - -Accelerated layers
      - - - -

      Advanced example

      - -See the wxpython.py script for an advanced usage of CEF Python 3 -features - including javascript bindings, js and python callbacks, -client handlers and others. - - -



      -



      -



      -



      - - - diff --git a/src/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.css b/src/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.css deleted file mode 100644 index 46ce5e40b..000000000 --- a/src/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.css +++ /dev/null @@ -1,186 +0,0 @@ -/* - IMPORTANT: - 1. DO NOT USE DOUBLE QUOTES HERE! - This file contents is included on page using document.write: - | (DQ = double quote) - | document.write(DQDQ); - 2. Each attribute must end with a semicolon, as newlines are removed - from this file. -*/ - -/* Dropdown control */ -.__kivy__selectBox-dropdown { - min-width: 150px; - position: relative; - border: solid 1px #BBB; - line-height: 1.5; - text-decoration: none; - text-align: left; - color: #000; - outline: none; - vertical-align: middle; - background: #F2F2F2; - background: -moz-linear-gradient(top, #F8F8F8 1%, #E1E1E1 100%); - background: -webkit-gradient(linear, left top, left bottom, color-stop(1%, #F8F8F8), color-stop(100%, #E1E1E1)); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F8F8F8', endColorstr='#E1E1E1', GradientType=0); - -moz-box-shadow: 0 1px 0 rgba(255, 255, 255, .75); - -webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, .75); - box-shadow: 0 1px 0 rgba(255, 255, 255, .75); - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - display: inline-block; - cursor: default; -} - -.__kivy__selectBox-dropdown:focus, -.__kivy__selectBox-dropdown:focus .__kivy__selectBox-arrow { - border-color: #666; -} - -.__kivy__selectBox-dropdown.__kivy__selectBox-menuShowing-bottom { - -moz-border-radius-bottomleft: 0; - -moz-border-radius-bottomright: 0; - -webkit-border-bottom-left-radius: 0; - -webkit-border-bottom-right-radius: 0; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; -} - -.__kivy__selectBox-dropdown.__kivy__selectBox-menuShowing-top { - -moz-border-radius-topleft: 0; - -moz-border-radius-topright: 0; - -webkit-border-top-left-radius: 0; - -webkit-border-top-right-radius: 0; - border-top-left-radius: 0; - border-top-right-radius: 0; -} - -.__kivy__selectBox-dropdown .__kivy__selectBox-label { - padding: 2px 8px; - display: inline-block; - white-space: nowrap; - overflow: hidden; -} - -.__kivy__selectBox-dropdown .__kivy__selectBox-arrow { - position: absolute; - top: 0; - right: 0; - width: 23px; - height: 100%; - background: url(data:image/gif;base64,R0lGODlhCQAOAIABAAAAAP///yH5BAEAAAEALAAAAAAJAA4AAAIXjAOnwIrcDJxvQoez3tUmn0jUEjmhUQAAOw==) 50% center no-repeat; - border-left: solid 1px #BBB; -} - -/* Dropdown menu */ -.__kivy__selectBox-dropdown-menu { - position: absolute; - z-index: 99999; - max-height: 200px; - min-height: 1em; - border: solid 1px #BBB; /* should be the same border width as .__kivy__selectBox-dropdown */ - background: #FFF; - -moz-box-shadow: 0 2px 6px rgba(0, 0, 0, .2); - -webkit-box-shadow: 0 2px 6px rgba(0, 0, 0, .2); - box-shadow: 0 2px 6px rgba(0, 0, 0, .2); - overflow: auto; - -webkit-overflow-scrolling: touch; -} - -/* Inline control */ -.__kivy__selectBox-inline { - min-width: 150px; - outline: none; - border: solid 1px #BBB; - background: #FFF; - display: inline-block; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - overflow: auto; -} - -.__kivy__selectBox-inline:focus { - border-color: #666; -} - -/* Options */ -.__kivy__selectBox-options, -.__kivy__selectBox-options LI, -.__kivy__selectBox-options LI A { - list-style: none; - display: block; - cursor: default; - padding: 0; - margin: 0; -} - -.__kivy__selectBox-options.__kivy__selectBox-options-top{ - border-bottom:none; - margin-top:1px; - -moz-border-radius-topleft: 5px; - -moz-border-radius-topright: 5px; - -webkit-border-top-left-radius: 5px; - -webkit-border-top-right-radius: 5px; - border-top-left-radius: 5px; - border-top-right-radius: 5px; -} -.__kivy__selectBox-options.__kivy__selectBox-options-bottom{ - border-top:none; - -moz-border-radius-bottomleft: 5px; - -moz-border-radius-bottomright: 5px; - -webkit-border-bottom-left-radius: 5px; - -webkit-border-bottom-right-radius: 5px; - border-bottom-left-radius: 5px; - border-bottom-right-radius: 5px; -} - -.__kivy__selectBox-options LI A { - line-height: 1.5; - padding: 0 .5em; - white-space: nowrap; - overflow: hidden; - background: 6px center no-repeat; -} - -.__kivy__selectBox-options LI.__kivy__selectBox-hover A { - background-color: #EEE; -} - -.__kivy__selectBox-options LI.__kivy__selectBox-disabled A { - color: #888; - background-color: transparent; -} - -.__kivy__selectBox-options LI.__kivy__selectBox-selected A { - background-color: #C8DEF4; -} - -.__kivy__selectBox-options .__kivy__selectBox-optgroup { - color: #666; - background: #EEE; - font-weight: bold; - line-height: 1.5; - padding: 0 .3em; - white-space: nowrap; -} - -/* Disabled state */ -.__kivy__selectBox.__kivy__selectBox-disabled { - color: #888 !important; -} - -.__kivy__selectBox-dropdown.__kivy__selectBox-disabled .__kivy__selectBox-arrow { - opacity: .5; - filter: alpha(opacity=50); - border-color: #666; -} - -.__kivy__selectBox-inline.__kivy__selectBox-disabled { - color: #888 !important; -} - -.__kivy__selectBox-inline.__kivy__selectBox-disabled .__kivy__selectBox-options A { - background-color: transparent !important; -} diff --git a/src/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.js b/src/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.js deleted file mode 100644 index a7d3d229c..000000000 --- a/src/linux/binaries_32bit/kivy-select-boxes/kivy-selectBox.js +++ /dev/null @@ -1,10420 +0,0 @@ -/*! - * __kivy__jQuery JavaScript Library v1.7.1 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Mon Nov 21 21:11:03 2011 -0500 - */ -(function( window, undefined ) { - -// Use the correct document accordingly with window argument (sandbox) -var document = window.document, - navigator = window.navigator, - location = window.location; -var __kivy__jQuery = (function() { - -// Define a local copy of __kivy__jQuery -var __kivy__jQuery = function( selector, context ) { - // The __kivy__jQuery object is actually just the init constructor 'enhanced' - return new __kivy__jQuery.fn.init( selector, context, root__kivy__jQuery ); - }, - - // Map over __kivy__jQuery in case of overwrite - ___kivy__jQuery = window.__kivy__jQuery, - - // Map over the $ in case of overwrite - __kivy___$ = window.__kivy__$, - - // A central reference to the root __kivy__jQuery(document) - root__kivy__jQuery, - - // A simple way to check for HTML strings or ID strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, - - // Check if a string has a non-whitespace character in it - rnotwhite = /\S/, - - // Used for trimming whitespace - trimLeft = /^\s+/, - trimRight = /\s+$/, - - // Match a standalone tag - rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, - - // JSON RegExp - rvalidchars = /^[\],:{}\s]*$/, - rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, - rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, - rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, - - // Useragent RegExp - rwebkit = /(webkit)[ \/]([\w.]+)/, - ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, - rmsie = /(msie) ([\w.]+)/, - rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, - - // Matches dashed string for camelizing - rdashAlpha = /-([a-z]|[0-9])/ig, - rmsPrefix = /^-ms-/, - - // Used by __kivy__jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return ( letter + "" ).toUpperCase(); - }, - - // Keep a UserAgent string for use with __kivy__jQuery.browser - userAgent = navigator.userAgent, - - // For matching the engine and version of the browser - browserMatch, - - // The deferred used on DOM ready - readyList, - - // The ready event handler - DOMContentLoaded, - - // Save a reference to some core methods - toString = Object.prototype.toString, - hasOwn = Object.prototype.hasOwnProperty, - push = Array.prototype.push, - slice = Array.prototype.slice, - trim = String.prototype.trim, - indexOf = Array.prototype.indexOf, - - // [[Class]] -> type pairs - class2type = {}; - -__kivy__jQuery.fn = __kivy__jQuery.prototype = { - constructor: __kivy__jQuery, - init: function( selector, context, root__kivy__jQuery ) { - var match, elem, ret, doc; - - // Handle $(""), $(null), or $(undefined) - if ( !selector ) { - return this; - } - - // Handle $(DOMElement) - if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - } - - // The body element only exists once, optimize finding it - if ( selector === "body" && !context && document.body ) { - this.context = document; - this[0] = document.body; - this.selector = selector; - this.length = 1; - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - // Are we dealing with HTML string or an ID? - if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = quickExpr.exec( selector ); - } - - // Verify a match, and that no context was specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof __kivy__jQuery ? context[0] : context; - doc = ( context ? context.ownerDocument || context : document ); - - // If a single string is passed in and it's a single tag - // just do a createElement and skip the rest - ret = rsingleTag.exec( selector ); - - if ( ret ) { - if ( __kivy__jQuery.isPlainObject( context ) ) { - selector = [ document.createElement( ret[1] ) ]; - __kivy__jQuery.fn.attr.call( selector, context, true ); - - } else { - selector = [ doc.createElement( ret[1] ) ]; - } - - } else { - ret = __kivy__jQuery.buildFragment( [ match[1] ], [ doc ] ); - selector = ( ret.cacheable ? __kivy__jQuery.clone(ret.fragment) : ret.fragment ).childNodes; - } - - return __kivy__jQuery.merge( this, selector ); - - // HANDLE: $("#id") - } else { - elem = document.getElementById( match[2] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id !== match[2] ) { - return root__kivy__jQuery.find( selector ); - } - - // Otherwise, we inject the element directly into the __kivy__jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.__kivy__jquery ) { - return ( context || root__kivy__jQuery ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( __kivy__jQuery.isFunction( selector ) ) { - return root__kivy__jQuery.ready( selector ); - } - - if ( selector.selector !== undefined ) { - this.selector = selector.selector; - this.context = selector.context; - } - - return __kivy__jQuery.makeArray( selector, this ); - }, - - // Start with an empty selector - selector: "", - - // The current version of __kivy__jQuery being used - __kivy__jquery: "1.7.1", - - // The default length of a __kivy__jQuery object is 0 - length: 0, - - // The number of elements contained in the matched element set - size: function() { - return this.length; - }, - - toArray: function() { - return slice.call( this, 0 ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num == null ? - - // Return a 'clean' array - this.toArray() : - - // Return just the object - ( num < 0 ? this[ this.length + num ] : this[ num ] ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems, name, selector ) { - // Build a new __kivy__jQuery matched element set - var ret = this.constructor(); - - if ( __kivy__jQuery.isArray( elems ) ) { - push.apply( ret, elems ); - - } else { - __kivy__jQuery.merge( ret, elems ); - } - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - ret.context = this.context; - - if ( name === "find" ) { - ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; - } else if ( name ) { - ret.selector = this.selector + "." + name + "(" + selector + ")"; - } - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return __kivy__jQuery.each( this, callback, args ); - }, - - ready: function( fn ) { - // Attach the listeners - __kivy__jQuery.bindReady(); - - // Add the callback - readyList.add( fn ); - - return this; - }, - - eq: function( i ) { - i = +i; - return i === -1 ? - this.slice( i ) : - this.slice( i, i + 1 ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ), - "slice", slice.call(arguments).join(",") ); - }, - - map: function( callback ) { - return this.pushStack( __kivy__jQuery.map(this, function( elem, i ) { - return callback.call( elem, i, elem ); - })); - }, - - end: function() { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a __kivy__jQuery method. - push: push, - sort: [].sort, - splice: [].splice -}; - -// Give the init function the __kivy__jQuery prototype for later instantiation -__kivy__jQuery.fn.init.prototype = __kivy__jQuery.fn; - -__kivy__jQuery.extend = __kivy__jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !__kivy__jQuery.isFunction(target) ) { - target = {}; - } - - // extend __kivy__jQuery itself if only one argument is passed - if ( length === i ) { - target = this; - --i; - } - - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( __kivy__jQuery.isPlainObject(copy) || (copyIsArray = __kivy__jQuery.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && __kivy__jQuery.isArray(src) ? src : []; - - } else { - clone = src && __kivy__jQuery.isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = __kivy__jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -__kivy__jQuery.extend({ - noConflict: function( deep ) { - if ( window.__kivy__$ === __kivy__jQuery ) { - window.__kivy__$ = __kivy___$; - } - - if ( deep && window.__kivy__jQuery === __kivy__jQuery ) { - window.__kivy__jQuery = ___kivy__jQuery; - } - - return __kivy__jQuery; - }, - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Hold (or release) the ready event - holdReady: function( hold ) { - if ( hold ) { - __kivy__jQuery.readyWait++; - } else { - __kivy__jQuery.ready( true ); - } - }, - - // Handle when the DOM is ready - ready: function( wait ) { - // Either a released hold or an DOMready/load event and not yet ready - if ( (wait === true && !--__kivy__jQuery.readyWait) || (wait !== true && !__kivy__jQuery.isReady) ) { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( !document.body ) { - return setTimeout( __kivy__jQuery.ready, 1 ); - } - - // Remember that the DOM is ready - __kivy__jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --__kivy__jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.fireWith( document, [ __kivy__jQuery ] ); - - // Trigger any bound ready events - if ( __kivy__jQuery.fn.trigger ) { - __kivy__jQuery( document ).trigger( "ready" ).off( "ready" ); - } - } - }, - - bindReady: function() { - if ( readyList ) { - return; - } - - readyList = __kivy__jQuery.Callbacks( "once memory" ); - - // Catch cases where $(document).ready() is called after the - // browser event has already occurred. - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - return setTimeout( __kivy__jQuery.ready, 1 ); - } - - // Mozilla, Opera and webkit nightlies currently support this event - if ( document.addEventListener ) { - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", __kivy__jQuery.ready, false ); - - // If IE event model is used - } else if ( document.attachEvent ) { - // ensure firing before onload, - // maybe late but safe also for iframes - document.attachEvent( "onreadystatechange", DOMContentLoaded ); - - // A fallback to window.onload, that will always work - window.attachEvent( "onload", __kivy__jQuery.ready ); - - // If IE and not a frame - // continually check to see if the document is ready - var toplevel = false; - - try { - toplevel = window.frameElement == null; - } catch(e) {} - - if ( document.documentElement.doScroll && toplevel ) { - doScrollCheck(); - } - } - }, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return __kivy__jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray || function( obj ) { - return __kivy__jQuery.type(obj) === "array"; - }, - - // A crude way of determining if an object is a window - isWindow: function( obj ) { - return obj && typeof obj === "object" && "setInterval" in obj; - }, - - isNumeric: function( obj ) { - return !isNaN( parseFloat(obj) ) && isFinite( obj ); - }, - - type: function( obj ) { - return obj == null ? - String( obj ) : - class2type[ toString.call(obj) ] || "object"; - }, - - isPlainObject: function( obj ) { - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if ( !obj || __kivy__jQuery.type(obj) !== "object" || obj.nodeType || __kivy__jQuery.isWindow( obj ) ) { - return false; - } - - try { - // Not own constructor property must be Object - if ( obj.constructor && - !hasOwn.call(obj, "constructor") && - !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { - return false; - } - } catch ( e ) { - // IE8,9 Will throw exceptions on certain host objects #9897 - return false; - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - - var key; - for ( key in obj ) {} - - return key === undefined || hasOwn.call( obj, key ); - }, - - isEmptyObject: function( obj ) { - for ( var name in obj ) { - return false; - } - return true; - }, - - error: function( msg ) { - throw new Error( msg ); - }, - - parseJSON: function( data ) { - if ( typeof data !== "string" || !data ) { - return null; - } - - // Make sure leading/trailing whitespace is removed (IE can't handle it) - data = __kivy__jQuery.trim( data ); - - // Attempt to parse using the native JSON parser first - if ( window.JSON && window.JSON.parse ) { - return window.JSON.parse( data ); - } - - // Make sure the incoming data is actual JSON - // Logic borrowed from http://json.org/json2.js - if ( rvalidchars.test( data.replace( rvalidescape, "@" ) - .replace( rvalidtokens, "]" ) - .replace( rvalidbraces, "")) ) { - - return ( new Function( "return " + data ) )(); - - } - __kivy__jQuery.error( "Invalid JSON: " + data ); - }, - - // Cross-browser xml parsing - parseXML: function( data ) { - var xml, tmp; - try { - if ( window.DOMParser ) { // Standard - tmp = new DOMParser(); - xml = tmp.parseFromString( data , "text/xml" ); - } else { // IE - xml = new ActiveXObject( "Microsoft.XMLDOM" ); - xml.async = "false"; - xml.loadXML( data ); - } - } catch( e ) { - xml = undefined; - } - if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { - __kivy__jQuery.error( "Invalid XML: " + data ); - } - return xml; - }, - - noop: function() {}, - - // Evaluates a script in a global context - // Workarounds based on findings by Jim Driscoll - // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context - globalEval: function( data ) { - if ( data && rnotwhite.test( data ) ) { - // We use execScript on Internet Explorer - // We use an anonymous function so that context is window - // rather than __kivy__jQuery in Firefox - ( window.execScript || function( data ) { - window[ "eval" ].call( window, data ); - } )( data ); - } - }, - - // Convert dashed to camelCase; used by the css and data modules - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); - }, - - // args is for internal usage only - each: function( object, callback, args ) { - var name, i = 0, - length = object.length, - isObj = length === undefined || __kivy__jQuery.isFunction( object ); - - if ( args ) { - if ( isObj ) { - for ( name in object ) { - if ( callback.apply( object[ name ], args ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.apply( object[ i++ ], args ) === false ) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if ( isObj ) { - for ( name in object ) { - if ( callback.call( object[ name ], name, object[ name ] ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { - break; - } - } - } - } - - return object; - }, - - // Use native String.trim function wherever possible - trim: trim ? - function( text ) { - return text == null ? - "" : - trim.call( text ); - } : - - // Otherwise use our own trimming functionality - function( text ) { - return text == null ? - "" : - text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); - }, - - // results is for internal usage only - makeArray: function( array, results ) { - var ret = results || []; - - if ( array != null ) { - // The window, strings (and functions) also have 'length' - // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 - var type = __kivy__jQuery.type( array ); - - if ( array.length == null || type === "string" || type === "function" || type === "regexp" || __kivy__jQuery.isWindow( array ) ) { - push.call( ret, array ); - } else { - __kivy__jQuery.merge( ret, array ); - } - } - - return ret; - }, - - inArray: function( elem, array, i ) { - var len; - - if ( array ) { - if ( indexOf ) { - return indexOf.call( array, elem, i ); - } - - len = array.length; - i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; - - for ( ; i < len; i++ ) { - // Skip accessing in sparse arrays - if ( i in array && array[ i ] === elem ) { - return i; - } - } - } - - return -1; - }, - - merge: function( first, second ) { - var i = first.length, - j = 0; - - if ( typeof second.length === "number" ) { - for ( var l = second.length; j < l; j++ ) { - first[ i++ ] = second[ j ]; - } - - } else { - while ( second[j] !== undefined ) { - first[ i++ ] = second[ j++ ]; - } - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, inv ) { - var ret = [], retVal; - inv = !!inv; - - // Go through the array, only saving the items - // that pass the validator function - for ( var i = 0, length = elems.length; i < length; i++ ) { - retVal = !!callback( elems[ i ], i ); - if ( inv !== retVal ) { - ret.push( elems[ i ] ); - } - } - - return ret; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var value, key, ret = [], - i = 0, - length = elems.length, - // jquery objects are treated as arrays - isArray = elems instanceof __kivy__jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || __kivy__jQuery.isArray( elems ) ) ; - - // Go through the array, translating each of the items to their - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - - // Go through every key on the object, - } else { - for ( key in elems ) { - value = callback( elems[ key ], key, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - } - - // Flatten any nested arrays - return ret.concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - if ( typeof context === "string" ) { - var tmp = fn[ context ]; - context = fn; - fn = tmp; - } - - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !__kivy__jQuery.isFunction( fn ) ) { - return undefined; - } - - // Simulated bind - var args = slice.call( arguments, 2 ), - proxy = function() { - return fn.apply( context, args.concat( slice.call( arguments ) ) ); - }; - - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || proxy.guid || __kivy__jQuery.guid++; - - return proxy; - }, - - // Mutifunctional method to get and set values to a collection - // The value/s can optionally be executed if it's a function - access: function( elems, key, value, exec, fn, pass ) { - var length = elems.length; - - // Setting many attributes - if ( typeof key === "object" ) { - for ( var k in key ) { - __kivy__jQuery.access( elems, k, key[k], exec, fn, value ); - } - return elems; - } - - // Setting one attribute - if ( value !== undefined ) { - // Optionally, function values get executed if exec is true - exec = !pass && exec && __kivy__jQuery.isFunction(value); - - for ( var i = 0; i < length; i++ ) { - fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); - } - - return elems; - } - - // Getting an attribute - return length ? fn( elems[0], key ) : undefined; - }, - - now: function() { - return ( new Date() ).getTime(); - }, - - // Use of __kivy__jQuery.browser is frowned upon. - // More details: http://docs.jquery.com/Utilities/__kivy__jQuery.browser - uaMatch: function( ua ) { - ua = ua.toLowerCase(); - - var match = rwebkit.exec( ua ) || - ropera.exec( ua ) || - rmsie.exec( ua ) || - ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || - []; - - return { browser: match[1] || "", version: match[2] || "0" }; - }, - - sub: function() { - function __kivy__jQuerySub( selector, context ) { - return new __kivy__jQuerySub.fn.init( selector, context ); - } - __kivy__jQuery.extend( true, __kivy__jQuerySub, this ); - __kivy__jQuerySub.superclass = this; - __kivy__jQuerySub.fn = __kivy__jQuerySub.prototype = this(); - __kivy__jQuerySub.fn.constructor = __kivy__jQuerySub; - __kivy__jQuerySub.sub = this.sub; - __kivy__jQuerySub.fn.init = function init( selector, context ) { - if ( context && context instanceof __kivy__jQuery && !(context instanceof __kivy__jQuerySub) ) { - context = __kivy__jQuerySub( context ); - } - - return __kivy__jQuery.fn.init.call( this, selector, context, root__kivy__jQuerySub ); - }; - __kivy__jQuerySub.fn.init.prototype = __kivy__jQuerySub.fn; - var root__kivy__jQuerySub = __kivy__jQuerySub(document); - return __kivy__jQuerySub; - }, - - browser: {} -}); - -// Populate the class2type map -__kivy__jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); - -browserMatch = __kivy__jQuery.uaMatch( userAgent ); -if ( browserMatch.browser ) { - __kivy__jQuery.browser[ browserMatch.browser ] = true; - __kivy__jQuery.browser.version = browserMatch.version; -} - -// Deprecated, use __kivy__jQuery.browser.webkit instead -if ( __kivy__jQuery.browser.webkit ) { - __kivy__jQuery.browser.safari = true; -} - -// IE doesn't match non-breaking spaces with \s -if ( rnotwhite.test( "\xA0" ) ) { - trimLeft = /^[\s\xA0]+/; - trimRight = /[\s\xA0]+$/; -} - -// All __kivy__jQuery objects should point back to these -root__kivy__jQuery = __kivy__jQuery(document); - -// Cleanup functions for the document ready method -if ( document.addEventListener ) { - DOMContentLoaded = function() { - document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - __kivy__jQuery.ready(); - }; - -} else if ( document.attachEvent ) { - DOMContentLoaded = function() { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( document.readyState === "complete" ) { - document.detachEvent( "onreadystatechange", DOMContentLoaded ); - __kivy__jQuery.ready(); - } - }; -} - -// The DOM ready check for Internet Explorer -function doScrollCheck() { - if ( __kivy__jQuery.isReady ) { - return; - } - - try { - // If IE is used, use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - document.documentElement.doScroll("left"); - } catch(e) { - setTimeout( doScrollCheck, 1 ); - return; - } - - // and execute any waiting functions - __kivy__jQuery.ready(); -} - -return __kivy__jQuery; - -})(); - - -// String to Object flags format cache -var flagsCache = {}; - -// Convert String-formatted flags into Object-formatted ones and store in cache -function createFlags( flags ) { - var object = flagsCache[ flags ] = {}, - i, length; - flags = flags.split( /\s+/ ); - for ( i = 0, length = flags.length; i < length; i++ ) { - object[ flags[i] ] = true; - } - return object; -} - -/* - * Create a callback list using the following parameters: - * - * flags: an optional list of space-separated flags that will change how - * the callback list behaves - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible flags: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -__kivy__jQuery.Callbacks = function( flags ) { - - // Convert flags from String-formatted to Object-formatted - // (we check in cache first) - flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; - - var // Actual callback list - list = [], - // Stack of fire calls for repeatable lists - stack = [], - // Last fire value (for non-forgettable lists) - memory, - // Flag to know if list is currently firing - firing, - // First callback to fire (used internally by add and fireWith) - firingStart, - // End of the loop when firing - firingLength, - // Index of currently firing callback (modified by remove if needed) - firingIndex, - // Add one or several callbacks to the list - add = function( args ) { - var i, - length, - elem, - type, - actual; - for ( i = 0, length = args.length; i < length; i++ ) { - elem = args[ i ]; - type = __kivy__jQuery.type( elem ); - if ( type === "array" ) { - // Inspect recursively - add( elem ); - } else if ( type === "function" ) { - // Add if not in unique mode and callback is not in - if ( !flags.unique || !self.has( elem ) ) { - list.push( elem ); - } - } - } - }, - // Fire callbacks - fire = function( context, args ) { - args = args || []; - memory = !flags.memory || [ context, args ]; - firing = true; - firingIndex = firingStart || 0; - firingStart = 0; - firingLength = list.length; - for ( ; list && firingIndex < firingLength; firingIndex++ ) { - if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { - memory = true; // Mark as halted - break; - } - } - firing = false; - if ( list ) { - if ( !flags.once ) { - if ( stack && stack.length ) { - memory = stack.shift(); - self.fireWith( memory[ 0 ], memory[ 1 ] ); - } - } else if ( memory === true ) { - self.disable(); - } else { - list = []; - } - } - }, - // Actual Callbacks object - self = { - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - var length = list.length; - add( arguments ); - // Do we need to add the callbacks to the - // current firing batch? - if ( firing ) { - firingLength = list.length; - // With memory, if we're not firing then - // we should call right away, unless previous - // firing was halted (stopOnFalse) - } else if ( memory && memory !== true ) { - firingStart = length; - fire( memory[ 0 ], memory[ 1 ] ); - } - } - return this; - }, - // Remove a callback from the list - remove: function() { - if ( list ) { - var args = arguments, - argIndex = 0, - argLength = args.length; - for ( ; argIndex < argLength ; argIndex++ ) { - for ( var i = 0; i < list.length; i++ ) { - if ( args[ argIndex ] === list[ i ] ) { - // Handle firingIndex and firingLength - if ( firing ) { - if ( i <= firingLength ) { - firingLength--; - if ( i <= firingIndex ) { - firingIndex--; - } - } - } - // Remove the element - list.splice( i--, 1 ); - // If we have some unicity property then - // we only need to do this once - if ( flags.unique ) { - break; - } - } - } - } - } - return this; - }, - // Control if a given callback is in the list - has: function( fn ) { - if ( list ) { - var i = 0, - length = list.length; - for ( ; i < length; i++ ) { - if ( fn === list[ i ] ) { - return true; - } - } - } - return false; - }, - // Remove all callbacks from the list - empty: function() { - list = []; - return this; - }, - // Have the list do nothing anymore - disable: function() { - list = stack = memory = undefined; - return this; - }, - // Is it disabled? - disabled: function() { - return !list; - }, - // Lock the list in its current state - lock: function() { - stack = undefined; - if ( !memory || memory === true ) { - self.disable(); - } - return this; - }, - // Is it locked? - locked: function() { - return !stack; - }, - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( stack ) { - if ( firing ) { - if ( !flags.once ) { - stack.push( [ context, args ] ); - } - } else if ( !( flags.once && memory ) ) { - fire( context, args ); - } - } - return this; - }, - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - // To know if the callbacks have already been called at least once - fired: function() { - return !!memory; - } - }; - - return self; -}; - - - - -var // Static reference to slice - sliceDeferred = [].slice; - -__kivy__jQuery.extend({ - - Deferred: function( func ) { - var doneList = __kivy__jQuery.Callbacks( "once memory" ), - failList = __kivy__jQuery.Callbacks( "once memory" ), - progressList = __kivy__jQuery.Callbacks( "memory" ), - state = "pending", - lists = { - resolve: doneList, - reject: failList, - notify: progressList - }, - promise = { - done: doneList.add, - fail: failList.add, - progress: progressList.add, - - state: function() { - return state; - }, - - // Deprecated - isResolved: doneList.fired, - isRejected: failList.fired, - - then: function( doneCallbacks, failCallbacks, progressCallbacks ) { - deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); - return this; - }, - always: function() { - deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); - return this; - }, - pipe: function( fnDone, fnFail, fnProgress ) { - return __kivy__jQuery.Deferred(function( newDefer ) { - __kivy__jQuery.each( { - done: [ fnDone, "resolve" ], - fail: [ fnFail, "reject" ], - progress: [ fnProgress, "notify" ] - }, function( handler, data ) { - var fn = data[ 0 ], - action = data[ 1 ], - returned; - if ( __kivy__jQuery.isFunction( fn ) ) { - deferred[ handler ](function() { - returned = fn.apply( this, arguments ); - if ( returned && __kivy__jQuery.isFunction( returned.promise ) ) { - returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); - } else { - newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); - } - }); - } else { - deferred[ handler ]( newDefer[ action ] ); - } - }); - }).promise(); - }, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - if ( obj == null ) { - obj = promise; - } else { - for ( var key in promise ) { - obj[ key ] = promise[ key ]; - } - } - return obj; - } - }, - deferred = promise.promise({}), - key; - - for ( key in lists ) { - deferred[ key ] = lists[ key ].fire; - deferred[ key + "With" ] = lists[ key ].fireWith; - } - - // Handle state - deferred.done( function() { - state = "resolved"; - }, failList.disable, progressList.lock ).fail( function() { - state = "rejected"; - }, doneList.disable, progressList.lock ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( firstParam ) { - var args = sliceDeferred.call( arguments, 0 ), - i = 0, - length = args.length, - pValues = new Array( length ), - count = length, - pCount = length, - deferred = length <= 1 && firstParam && __kivy__jQuery.isFunction( firstParam.promise ) ? - firstParam : - __kivy__jQuery.Deferred(), - promise = deferred.promise(); - function resolveFunc( i ) { - return function( value ) { - args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; - if ( !( --count ) ) { - deferred.resolveWith( deferred, args ); - } - }; - } - function progressFunc( i ) { - return function( value ) { - pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; - deferred.notifyWith( promise, pValues ); - }; - } - if ( length > 1 ) { - for ( ; i < length; i++ ) { - if ( args[ i ] && args[ i ].promise && __kivy__jQuery.isFunction( args[ i ].promise ) ) { - args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); - } else { - --count; - } - } - if ( !count ) { - deferred.resolveWith( deferred, args ); - } - } else if ( deferred !== firstParam ) { - deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); - } - return promise; - } -}); - - - - -__kivy__jQuery.support = (function() { - - var support, - all, - a, - select, - opt, - input, - marginDiv, - fragment, - tds, - events, - eventName, - i, - isSupported, - div = document.createElement( "div" ), - documentElement = document.documentElement; - - // Preliminary tests - div.setAttribute("className", "t"); - div.innerHTML = "
      a"; - - all = div.getElementsByTagName( "*" ); - a = div.getElementsByTagName( "a" )[ 0 ]; - - // Can't get basic test support - if ( !all || !all.length || !a ) { - return {}; - } - - // First batch of supports tests - select = document.createElement( "select" ); - opt = select.appendChild( document.createElement("option") ); - input = div.getElementsByTagName( "input" )[ 0 ]; - - support = { - // IE strips leading whitespace when .innerHTML is used - leadingWhitespace: ( div.firstChild.nodeType === 3 ), - - // Make sure that tbody elements aren't automatically inserted - // IE will insert them into empty tables - tbody: !div.getElementsByTagName("tbody").length, - - // Make sure that link elements get serialized correctly by innerHTML - // This requires a wrapper element in IE - htmlSerialize: !!div.getElementsByTagName("link").length, - - // Get the style information from getAttribute - // (IE uses .cssText instead) - style: /top/.test( a.getAttribute("style") ), - - // Make sure that URLs aren't manipulated - // (IE normalizes it by default) - hrefNormalized: ( a.getAttribute("href") === "/a" ), - - // Make sure that element opacity exists - // (IE uses filter instead) - // Use a regex to work around a WebKit issue. See #5145 - opacity: /^0.55/.test( a.style.opacity ), - - // Verify style float existence - // (IE uses styleFloat instead of cssFloat) - cssFloat: !!a.style.cssFloat, - - // Make sure that if no value is specified for a checkbox - // that it defaults to "on". - // (WebKit defaults to "" instead) - checkOn: ( input.value === "on" ), - - // Make sure that a selected-by-default option has a working selected property. - // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) - optSelected: opt.selected, - - // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) - getSetAttribute: div.className !== "t", - - // Tests for enctype support on a form(#6743) - enctype: !!document.createElement("form").enctype, - - // Makes sure cloning an html5 element does not cause problems - // Where outerHTML is undefined, this still works - html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", - - // Will be defined later - submitBubbles: true, - changeBubbles: true, - focusinBubbles: false, - deleteExpando: true, - noCloneEvent: true, - inlineBlockNeedsLayout: false, - shrinkWrapBlocks: false, - reliableMarginRight: true - }; - - // Make sure checked status is properly cloned - input.checked = true; - support.noCloneChecked = input.cloneNode( true ).checked; - - // Make sure that the options inside disabled selects aren't marked as disabled - // (WebKit marks them as disabled) - select.disabled = true; - support.optDisabled = !opt.disabled; - - // Test to see if it's possible to delete an expando from an element - // Fails in Internet Explorer - try { - delete div.test; - } catch( e ) { - support.deleteExpando = false; - } - - if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { - div.attachEvent( "onclick", function() { - // Cloning a node shouldn't copy over any - // bound event handlers (IE does this) - support.noCloneEvent = false; - }); - div.cloneNode( true ).fireEvent( "onclick" ); - } - - // Check if a radio maintains its value - // after being appended to the DOM - input = document.createElement("input"); - input.value = "t"; - input.setAttribute("type", "radio"); - support.radioValue = input.value === "t"; - - input.setAttribute("checked", "checked"); - div.appendChild( input ); - fragment = document.createDocumentFragment(); - fragment.appendChild( div.lastChild ); - - // WebKit doesn't clone checked state correctly in fragments - support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Check if a disconnected checkbox will retain its checked - // value of true after appended to the DOM (IE6/7) - support.appendChecked = input.checked; - - fragment.removeChild( input ); - fragment.appendChild( div ); - - div.innerHTML = ""; - - // Check if div with explicit width and no margin-right incorrectly - // gets computed margin-right based on width of container. For more - // info see bug #3333 - // Fails in WebKit before Feb 2011 nightlies - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - if ( window.getComputedStyle ) { - marginDiv = document.createElement( "div" ); - marginDiv.style.width = "0"; - marginDiv.style.marginRight = "0"; - div.style.width = "2px"; - div.appendChild( marginDiv ); - support.reliableMarginRight = - ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; - } - - // Technique from Juriy Zaytsev - // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ - // We only care about the case where non-standard event systems - // are used, namely in IE. Short-circuiting here helps us to - // avoid an eval call (in setAttribute) which can cause CSP - // to go haywire. See: https://developer.mozilla.org/en/Security/CSP - if ( div.attachEvent ) { - for( i in { - submit: 1, - change: 1, - focusin: 1 - }) { - eventName = "on" + i; - isSupported = ( eventName in div ); - if ( !isSupported ) { - div.setAttribute( eventName, "return;" ); - isSupported = ( typeof div[ eventName ] === "function" ); - } - support[ i + "Bubbles" ] = isSupported; - } - } - - fragment.removeChild( div ); - - // Null elements to avoid leaks in IE - fragment = select = opt = marginDiv = div = input = null; - - // Run tests that need a body at doc ready - __kivy__jQuery(function() { - var container, outer, inner, table, td, offsetSupport, - conMarginTop, ptlm, vb, style, html, - body = document.getElementsByTagName("body")[0]; - - if ( !body ) { - // Return for frameset docs that don't have a body - return; - } - - conMarginTop = 1; - ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;"; - vb = "visibility:hidden;border:0;"; - style = "style='" + ptlm + "border:5px solid #000;padding:0;'"; - html = "
      " + - "" + - "
      "; - - container = document.createElement("div"); - container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; - body.insertBefore( container, body.firstChild ); - - // Construct the test element - div = document.createElement("div"); - container.appendChild( div ); - - // Check if table cells still have offsetWidth/Height when they are set - // to display:none and there are still other visible table cells in a - // table row; if so, offsetWidth/Height are not reliable for use when - // determining if an element has been hidden directly using - // display:none (it is still safe to use offsets if a parent element is - // hidden; don safety goggles and see bug #4512 for more information). - // (only IE 8 fails this test) - div.innerHTML = "
      t
      "; - tds = div.getElementsByTagName( "td" ); - isSupported = ( tds[ 0 ].offsetHeight === 0 ); - - tds[ 0 ].style.display = ""; - tds[ 1 ].style.display = "none"; - - // Check if empty table cells still have offsetWidth/Height - // (IE <= 8 fail this test) - support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); - - // Figure out if the W3C box model works as expected - div.innerHTML = ""; - div.style.width = div.style.paddingLeft = "1px"; - __kivy__jQuery.boxModel = support.boxModel = div.offsetWidth === 2; - - if ( typeof div.style.zoom !== "undefined" ) { - // Check if natively block-level elements act like inline-block - // elements when setting their display to 'inline' and giving - // them layout - // (IE < 8 does this) - div.style.display = "inline"; - div.style.zoom = 1; - support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); - - // Check if elements with layout shrink-wrap their children - // (IE 6 does this) - div.style.display = ""; - div.innerHTML = "
      "; - support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); - } - - div.style.cssText = ptlm + vb; - div.innerHTML = html; - - outer = div.firstChild; - inner = outer.firstChild; - td = outer.nextSibling.firstChild.firstChild; - - offsetSupport = { - doesNotAddBorder: ( inner.offsetTop !== 5 ), - doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) - }; - - inner.style.position = "fixed"; - inner.style.top = "20px"; - - // safari subtracts parent border width here which is 5px - offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); - inner.style.position = inner.style.top = ""; - - outer.style.overflow = "hidden"; - outer.style.position = "relative"; - - offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); - offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); - - body.removeChild( container ); - div = container = null; - - __kivy__jQuery.extend( support, offsetSupport ); - }); - - return support; -})(); - - - - -var rbrace = /^(?:\{.*\}|\[.*\])$/, - rmultiDash = /([A-Z])/g; - -__kivy__jQuery.extend({ - cache: {}, - - // Please use with caution - uuid: 0, - - // Unique for each copy of __kivy__jQuery on the page - // Non-digits removed to match rinline__kivy__jQuery - expando: "__kivy__jQuery" + ( __kivy__jQuery.fn.__kivy__jquery + Math.random() ).replace( /\D/g, "" ), - - // The following elements throw uncatchable exceptions if you - // attempt to add expando properties to them. - noData: { - "embed": true, - // Ban all objects except for Flash (which handle expandos) - "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", - "applet": true - }, - - hasData: function( elem ) { - elem = elem.nodeType ? __kivy__jQuery.cache[ elem[__kivy__jQuery.expando] ] : elem[ __kivy__jQuery.expando ]; - return !!elem && !isEmptyDataObject( elem ); - }, - - data: function( elem, name, data, pvt /* Internal Use Only */ ) { - if ( !__kivy__jQuery.acceptData( elem ) ) { - return; - } - - var privateCache, thisCache, ret, - internalKey = __kivy__jQuery.expando, - getByName = typeof name === "string", - - // We have to handle DOM nodes and JS objects differently because IE6-7 - // can't GC object references properly across the DOM-JS boundary - isNode = elem.nodeType, - - // Only DOM nodes need the global __kivy__jQuery cache; JS object data is - // attached directly to the object so GC can occur automatically - cache = isNode ? __kivy__jQuery.cache : elem, - - // Only defining an ID for JS objects if its cache already exists allows - // the code to shortcut on the same path as a DOM node with no cache - id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, - isEvents = name === "events"; - - // Avoid doing any more work than we need to when trying to get data on an - // object that has no data at all - if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { - return; - } - - if ( !id ) { - // Only DOM nodes need a new unique ID for each element since their data - // ends up in the global cache - if ( isNode ) { - elem[ internalKey ] = id = ++__kivy__jQuery.uuid; - } else { - id = internalKey; - } - } - - if ( !cache[ id ] ) { - cache[ id ] = {}; - - // Avoids exposing __kivy__jQuery metadata on plain JS objects when the object - // is serialized using JSON.stringify - if ( !isNode ) { - cache[ id ].toJSON = __kivy__jQuery.noop; - } - } - - // An object can be passed to __kivy__jQuery.data instead of a key/value pair; this gets - // shallow copied over onto the existing cache - if ( typeof name === "object" || typeof name === "function" ) { - if ( pvt ) { - cache[ id ] = __kivy__jQuery.extend( cache[ id ], name ); - } else { - cache[ id ].data = __kivy__jQuery.extend( cache[ id ].data, name ); - } - } - - privateCache = thisCache = cache[ id ]; - - // __kivy__jQuery data() is stored in a separate object inside the object's internal data - // cache in order to avoid key collisions between internal data and user-defined - // data. - if ( !pvt ) { - if ( !thisCache.data ) { - thisCache.data = {}; - } - - thisCache = thisCache.data; - } - - if ( data !== undefined ) { - thisCache[ __kivy__jQuery.camelCase( name ) ] = data; - } - - // Users should not attempt to inspect the internal events object using __kivy__jQuery.data, - // it is undocumented and subject to change. But does anyone listen? No. - if ( isEvents && !thisCache[ name ] ) { - return privateCache.events; - } - - // Check for both converted-to-camel and non-converted data property names - // If a data property was specified - if ( getByName ) { - - // First Try to find as-is property data - ret = thisCache[ name ]; - - // Test for null|undefined property data - if ( ret == null ) { - - // Try to find the camelCased property - ret = thisCache[ __kivy__jQuery.camelCase( name ) ]; - } - } else { - ret = thisCache; - } - - return ret; - }, - - removeData: function( elem, name, pvt /* Internal Use Only */ ) { - if ( !__kivy__jQuery.acceptData( elem ) ) { - return; - } - - var thisCache, i, l, - - // Reference to internal data cache key - internalKey = __kivy__jQuery.expando, - - isNode = elem.nodeType, - - // See __kivy__jQuery.data for more information - cache = isNode ? __kivy__jQuery.cache : elem, - - // See __kivy__jQuery.data for more information - id = isNode ? elem[ internalKey ] : internalKey; - - // If there is already no cache entry for this object, there is no - // purpose in continuing - if ( !cache[ id ] ) { - return; - } - - if ( name ) { - - thisCache = pvt ? cache[ id ] : cache[ id ].data; - - if ( thisCache ) { - - // Support array or space separated string names for data keys - if ( !__kivy__jQuery.isArray( name ) ) { - - // try the string as a key before any manipulation - if ( name in thisCache ) { - name = [ name ]; - } else { - - // split the camel cased version by spaces unless a key with the spaces exists - name = __kivy__jQuery.camelCase( name ); - if ( name in thisCache ) { - name = [ name ]; - } else { - name = name.split( " " ); - } - } - } - - for ( i = 0, l = name.length; i < l; i++ ) { - delete thisCache[ name[i] ]; - } - - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if ( !( pvt ? isEmptyDataObject : __kivy__jQuery.isEmptyObject )( thisCache ) ) { - return; - } - } - } - - // See __kivy__jQuery.data for more information - if ( !pvt ) { - delete cache[ id ].data; - - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if ( !isEmptyDataObject(cache[ id ]) ) { - return; - } - } - - // Browsers that fail expando deletion also refuse to delete expandos on - // the window, but it will allow it on all other JS objects; other browsers - // don't care - // Ensure that `cache` is not a window object #10080 - if ( __kivy__jQuery.support.deleteExpando || !cache.setInterval ) { - delete cache[ id ]; - } else { - cache[ id ] = null; - } - - // We destroyed the cache and need to eliminate the expando on the node to avoid - // false lookups in the cache for entries that no longer exist - if ( isNode ) { - // IE does not allow us to delete expando properties from nodes, - // nor does it have a removeAttribute function on Document nodes; - // we must handle all of these cases - if ( __kivy__jQuery.support.deleteExpando ) { - delete elem[ internalKey ]; - } else if ( elem.removeAttribute ) { - elem.removeAttribute( internalKey ); - } else { - elem[ internalKey ] = null; - } - } - }, - - // For internal use only. - _data: function( elem, name, data ) { - return __kivy__jQuery.data( elem, name, data, true ); - }, - - // A method for determining if a DOM node can handle the data expando - acceptData: function( elem ) { - if ( elem.nodeName ) { - var match = __kivy__jQuery.noData[ elem.nodeName.toLowerCase() ]; - - if ( match ) { - return !(match === true || elem.getAttribute("classid") !== match); - } - } - - return true; - } -}); - -__kivy__jQuery.fn.extend({ - data: function( key, value ) { - var parts, attr, name, - data = null; - - if ( typeof key === "undefined" ) { - if ( this.length ) { - data = __kivy__jQuery.data( this[0] ); - - if ( this[0].nodeType === 1 && !__kivy__jQuery._data( this[0], "parsedAttrs" ) ) { - attr = this[0].attributes; - for ( var i = 0, l = attr.length; i < l; i++ ) { - name = attr[i].name; - - if ( name.indexOf( "data-" ) === 0 ) { - name = __kivy__jQuery.camelCase( name.substring(5) ); - - dataAttr( this[0], name, data[ name ] ); - } - } - __kivy__jQuery._data( this[0], "parsedAttrs", true ); - } - } - - return data; - - } else if ( typeof key === "object" ) { - return this.each(function() { - __kivy__jQuery.data( this, key ); - }); - } - - parts = key.split("."); - parts[1] = parts[1] ? "." + parts[1] : ""; - - if ( value === undefined ) { - data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); - - // Try to fetch any internally stored data first - if ( data === undefined && this.length ) { - data = __kivy__jQuery.data( this[0], key ); - data = dataAttr( this[0], key, data ); - } - - return data === undefined && parts[1] ? - this.data( parts[0] ) : - data; - - } else { - return this.each(function() { - var self = __kivy__jQuery( this ), - args = [ parts[0], value ]; - - self.triggerHandler( "setData" + parts[1] + "!", args ); - __kivy__jQuery.data( this, key, value ); - self.triggerHandler( "changeData" + parts[1] + "!", args ); - }); - } - }, - - removeData: function( key ) { - return this.each(function() { - __kivy__jQuery.removeData( this, key ); - }); - } -}); - -function dataAttr( elem, key, data ) { - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - - var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); - - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - __kivy__jQuery.isNumeric( data ) ? parseFloat( data ) : - rbrace.test( data ) ? __kivy__jQuery.parseJSON( data ) : - data; - } catch( e ) {} - - // Make sure we set the data so it isn't changed later - __kivy__jQuery.data( elem, key, data ); - - } else { - data = undefined; - } - } - - return data; -} - -// checks a cache object for emptiness -function isEmptyDataObject( obj ) { - for ( var name in obj ) { - - // if the public data object is empty, the private is still empty - if ( name === "data" && __kivy__jQuery.isEmptyObject( obj[name] ) ) { - continue; - } - if ( name !== "toJSON" ) { - return false; - } - } - - return true; -} - - - - -function handleQueueMarkDefer( elem, type, src ) { - var deferDataKey = type + "defer", - queueDataKey = type + "queue", - markDataKey = type + "mark", - defer = __kivy__jQuery._data( elem, deferDataKey ); - if ( defer && - ( src === "queue" || !__kivy__jQuery._data(elem, queueDataKey) ) && - ( src === "mark" || !__kivy__jQuery._data(elem, markDataKey) ) ) { - // Give room for hard-coded callbacks to fire first - // and eventually mark/queue something else on the element - setTimeout( function() { - if ( !__kivy__jQuery._data( elem, queueDataKey ) && - !__kivy__jQuery._data( elem, markDataKey ) ) { - __kivy__jQuery.removeData( elem, deferDataKey, true ); - defer.fire(); - } - }, 0 ); - } -} - -__kivy__jQuery.extend({ - - _mark: function( elem, type ) { - if ( elem ) { - type = ( type || "fx" ) + "mark"; - __kivy__jQuery._data( elem, type, (__kivy__jQuery._data( elem, type ) || 0) + 1 ); - } - }, - - _unmark: function( force, elem, type ) { - if ( force !== true ) { - type = elem; - elem = force; - force = false; - } - if ( elem ) { - type = type || "fx"; - var key = type + "mark", - count = force ? 0 : ( (__kivy__jQuery._data( elem, key ) || 1) - 1 ); - if ( count ) { - __kivy__jQuery._data( elem, key, count ); - } else { - __kivy__jQuery.removeData( elem, key, true ); - handleQueueMarkDefer( elem, type, "mark" ); - } - } - }, - - queue: function( elem, type, data ) { - var q; - if ( elem ) { - type = ( type || "fx" ) + "queue"; - q = __kivy__jQuery._data( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !q || __kivy__jQuery.isArray(data) ) { - q = __kivy__jQuery._data( elem, type, __kivy__jQuery.makeArray(data) ); - } else { - q.push( data ); - } - } - return q || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = __kivy__jQuery.queue( elem, type ), - fn = queue.shift(), - hooks = {}; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - } - - if ( fn ) { - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - __kivy__jQuery._data( elem, type + ".run", hooks ); - fn.call( elem, function() { - __kivy__jQuery.dequeue( elem, type ); - }, hooks ); - } - - if ( !queue.length ) { - __kivy__jQuery.removeData( elem, type + "queue " + type + ".run", true ); - handleQueueMarkDefer( elem, type, "queue" ); - } - } -}); - -__kivy__jQuery.fn.extend({ - queue: function( type, data ) { - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - } - - if ( data === undefined ) { - return __kivy__jQuery.queue( this[0], type ); - } - return this.each(function() { - var queue = __kivy__jQuery.queue( this, type, data ); - - if ( type === "fx" && queue[0] !== "inprogress" ) { - __kivy__jQuery.dequeue( this, type ); - } - }); - }, - dequeue: function( type ) { - return this.each(function() { - __kivy__jQuery.dequeue( this, type ); - }); - }, - // Based off of the plugin by Clint Helfers, with permission. - // http://blindsignals.com/index.php/2009/07/jquery-delay/ - delay: function( time, type ) { - time = __kivy__jQuery.fx ? __kivy__jQuery.fx.speeds[ time ] || time : time; - type = type || "fx"; - - return this.queue( type, function( next, hooks ) { - var timeout = setTimeout( next, time ); - hooks.stop = function() { - clearTimeout( timeout ); - }; - }); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, object ) { - if ( typeof type !== "string" ) { - object = type; - type = undefined; - } - type = type || "fx"; - var defer = __kivy__jQuery.Deferred(), - elements = this, - i = elements.length, - count = 1, - deferDataKey = type + "defer", - queueDataKey = type + "queue", - markDataKey = type + "mark", - tmp; - function resolve() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - } - while( i-- ) { - if (( tmp = __kivy__jQuery.data( elements[ i ], deferDataKey, undefined, true ) || - ( __kivy__jQuery.data( elements[ i ], queueDataKey, undefined, true ) || - __kivy__jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && - __kivy__jQuery.data( elements[ i ], deferDataKey, __kivy__jQuery.Callbacks( "once memory" ), true ) )) { - count++; - tmp.add( resolve ); - } - } - resolve(); - return defer.promise(); - } -}); - - - - -var rclass = /[\n\t\r]/g, - rspace = /\s+/, - rreturn = /\r/g, - rtype = /^(?:button|input)$/i, - rfocusable = /^(?:button|input|object|select|textarea)$/i, - rclickable = /^a(?:rea)?$/i, - rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, - getSetAttribute = __kivy__jQuery.support.getSetAttribute, - nodeHook, boolHook, fixSpecified; - -__kivy__jQuery.fn.extend({ - attr: function( name, value ) { - return __kivy__jQuery.access( this, name, value, true, __kivy__jQuery.attr ); - }, - - removeAttr: function( name ) { - return this.each(function() { - __kivy__jQuery.removeAttr( this, name ); - }); - }, - - prop: function( name, value ) { - return __kivy__jQuery.access( this, name, value, true, __kivy__jQuery.prop ); - }, - - removeProp: function( name ) { - name = __kivy__jQuery.propFix[ name ] || name; - return this.each(function() { - // try/catch handles cases where IE balks (such as removing a property on window) - try { - this[ name ] = undefined; - delete this[ name ]; - } catch( e ) {} - }); - }, - - addClass: function( value ) { - var classNames, i, l, elem, - setClass, c, cl; - - if ( __kivy__jQuery.isFunction( value ) ) { - return this.each(function( j ) { - __kivy__jQuery( this ).addClass( value.call(this, j, this.className) ); - }); - } - - if ( value && typeof value === "string" ) { - classNames = value.split( rspace ); - - for ( i = 0, l = this.length; i < l; i++ ) { - elem = this[ i ]; - - if ( elem.nodeType === 1 ) { - if ( !elem.className && classNames.length === 1 ) { - elem.className = value; - - } else { - setClass = " " + elem.className + " "; - - for ( c = 0, cl = classNames.length; c < cl; c++ ) { - if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { - setClass += classNames[ c ] + " "; - } - } - elem.className = __kivy__jQuery.trim( setClass ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - var classNames, i, l, elem, className, c, cl; - - if ( __kivy__jQuery.isFunction( value ) ) { - return this.each(function( j ) { - __kivy__jQuery( this ).removeClass( value.call(this, j, this.className) ); - }); - } - - if ( (value && typeof value === "string") || value === undefined ) { - classNames = ( value || "" ).split( rspace ); - - for ( i = 0, l = this.length; i < l; i++ ) { - elem = this[ i ]; - - if ( elem.nodeType === 1 && elem.className ) { - if ( value ) { - className = (" " + elem.className + " ").replace( rclass, " " ); - for ( c = 0, cl = classNames.length; c < cl; c++ ) { - className = className.replace(" " + classNames[ c ] + " ", " "); - } - elem.className = __kivy__jQuery.trim( className ); - - } else { - elem.className = ""; - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isBool = typeof stateVal === "boolean"; - - if ( __kivy__jQuery.isFunction( value ) ) { - return this.each(function( i ) { - __kivy__jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); - }); - } - - return this.each(function() { - if ( type === "string" ) { - // toggle individual class names - var className, - i = 0, - self = __kivy__jQuery( this ), - state = stateVal, - classNames = value.split( rspace ); - - while ( (className = classNames[ i++ ]) ) { - // check each className given, space seperated list - state = isBool ? state : !self.hasClass( className ); - self[ state ? "addClass" : "removeClass" ]( className ); - } - - } else if ( type === "undefined" || type === "boolean" ) { - if ( this.className ) { - // store className if set - __kivy__jQuery._data( this, "__className__", this.className ); - } - - // toggle whole className - this.className = this.className || value === false ? "" : __kivy__jQuery._data( this, "__className__" ) || ""; - } - }); - }, - - hasClass: function( selector ) { - var className = " " + selector + " ", - i = 0, - l = this.length; - for ( ; i < l; i++ ) { - if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { - return true; - } - } - - return false; - }, - - val: function( value ) { - var hooks, ret, isFunction, - elem = this[0]; - - if ( !arguments.length ) { - if ( elem ) { - hooks = __kivy__jQuery.valHooks[ elem.nodeName.toLowerCase() ] || __kivy__jQuery.valHooks[ elem.type ]; - - if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { - return ret; - } - - ret = elem.value; - - return typeof ret === "string" ? - // handle most common string cases - ret.replace(rreturn, "") : - // handle cases where value is null/undef or number - ret == null ? "" : ret; - } - - return; - } - - isFunction = __kivy__jQuery.isFunction( value ); - - return this.each(function( i ) { - var self = __kivy__jQuery(this), val; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( isFunction ) { - val = value.call( this, i, self.val() ); - } else { - val = value; - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - } else if ( typeof val === "number" ) { - val += ""; - } else if ( __kivy__jQuery.isArray( val ) ) { - val = __kivy__jQuery.map(val, function ( value ) { - return value == null ? "" : value + ""; - }); - } - - hooks = __kivy__jQuery.valHooks[ this.nodeName.toLowerCase() ] || __kivy__jQuery.valHooks[ this.type ]; - - // If set returns undefined, fall back to normal setting - if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { - this.value = val; - } - }); - } -}); - -__kivy__jQuery.extend({ - valHooks: { - option: { - get: function( elem ) { - // attributes.value is undefined in Blackberry 4.7 but - // uses .value. See #6932 - var val = elem.attributes.value; - return !val || val.specified ? elem.value : elem.text; - } - }, - select: { - get: function( elem ) { - var value, i, max, option, - index = elem.selectedIndex, - values = [], - options = elem.options, - one = elem.type === "select-one"; - - // Nothing was selected - if ( index < 0 ) { - return null; - } - - // Loop through all the selected options - i = one ? index : 0; - max = one ? index + 1 : options.length; - for ( ; i < max; i++ ) { - option = options[ i ]; - - // Don't return options that are disabled or in a disabled optgroup - if ( option.selected && (__kivy__jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && - (!option.parentNode.disabled || !__kivy__jQuery.nodeName( option.parentNode, "optgroup" )) ) { - - // Get the specific value for the option - value = __kivy__jQuery( option ).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - // Fixes Bug #2551 -- select.val() broken in IE after form.reset() - if ( one && !values.length && options.length ) { - return __kivy__jQuery( options[ index ] ).val(); - } - - return values; - }, - - set: function( elem, value ) { - var values = __kivy__jQuery.makeArray( value ); - - __kivy__jQuery(elem).find("option").each(function() { - this.selected = __kivy__jQuery.inArray( __kivy__jQuery(this).val(), values ) >= 0; - }); - - if ( !values.length ) { - elem.selectedIndex = -1; - } - return values; - } - } - }, - - attrFn: { - val: true, - css: true, - html: true, - text: true, - data: true, - width: true, - height: true, - offset: true - }, - - attr: function( elem, name, value, pass ) { - var ret, hooks, notxml, - nType = elem.nodeType; - - // don't get/set attributes on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - if ( pass && name in __kivy__jQuery.attrFn ) { - return __kivy__jQuery( elem )[ name ]( value ); - } - - // Fallback to prop when attributes are not supported - if ( typeof elem.getAttribute === "undefined" ) { - return __kivy__jQuery.prop( elem, name, value ); - } - - notxml = nType !== 1 || !__kivy__jQuery.isXMLDoc( elem ); - - // All attributes are lowercase - // Grab necessary hook if one is defined - if ( notxml ) { - name = name.toLowerCase(); - hooks = __kivy__jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); - } - - if ( value !== undefined ) { - - if ( value === null ) { - __kivy__jQuery.removeAttr( elem, name ); - return; - - } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - elem.setAttribute( name, "" + value ); - return value; - } - - } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - - ret = elem.getAttribute( name ); - - // Non-existent attributes return null, we normalize to undefined - return ret === null ? - undefined : - ret; - } - }, - - removeAttr: function( elem, value ) { - var propName, attrNames, name, l, - i = 0; - - if ( value && elem.nodeType === 1 ) { - attrNames = value.toLowerCase().split( rspace ); - l = attrNames.length; - - for ( ; i < l; i++ ) { - name = attrNames[ i ]; - - if ( name ) { - propName = __kivy__jQuery.propFix[ name ] || name; - - // See #9699 for explanation of this approach (setting first, then removal) - __kivy__jQuery.attr( elem, name, "" ); - elem.removeAttribute( getSetAttribute ? name : propName ); - - // Set corresponding property to false for boolean attributes - if ( rboolean.test( name ) && propName in elem ) { - elem[ propName ] = false; - } - } - } - } - }, - - attrHooks: { - type: { - set: function( elem, value ) { - // We can't allow the type property to be changed (since it causes problems in IE) - if ( rtype.test( elem.nodeName ) && elem.parentNode ) { - __kivy__jQuery.error( "type property can't be changed" ); - } else if ( !__kivy__jQuery.support.radioValue && value === "radio" && __kivy__jQuery.nodeName(elem, "input") ) { - // Setting the type on a radio button after the value resets the value in IE6-9 - // Reset value to it's default in case type is set after value - // This is for element creation - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - }, - // Use the value property for back compat - // Use the nodeHook for button elements in IE6/7 (#1954) - value: { - get: function( elem, name ) { - if ( nodeHook && __kivy__jQuery.nodeName( elem, "button" ) ) { - return nodeHook.get( elem, name ); - } - return name in elem ? - elem.value : - null; - }, - set: function( elem, value, name ) { - if ( nodeHook && __kivy__jQuery.nodeName( elem, "button" ) ) { - return nodeHook.set( elem, value, name ); - } - // Does not return so that setAttribute is also used - elem.value = value; - } - } - }, - - propFix: { - tabindex: "tabIndex", - readonly: "readOnly", - "for": "htmlFor", - "class": "className", - maxlength: "maxLength", - cellspacing: "cellSpacing", - cellpadding: "cellPadding", - rowspan: "rowSpan", - colspan: "colSpan", - usemap: "useMap", - frameborder: "frameBorder", - contenteditable: "contentEditable" - }, - - prop: function( elem, name, value ) { - var ret, hooks, notxml, - nType = elem.nodeType; - - // don't get/set properties on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - notxml = nType !== 1 || !__kivy__jQuery.isXMLDoc( elem ); - - if ( notxml ) { - // Fix name and attach hooks - name = __kivy__jQuery.propFix[ name ] || name; - hooks = __kivy__jQuery.propHooks[ name ]; - } - - if ( value !== undefined ) { - if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - return ( elem[ name ] = value ); - } - - } else { - if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - return elem[ name ]; - } - } - }, - - propHooks: { - tabIndex: { - get: function( elem ) { - // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set - // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - var attributeNode = elem.getAttributeNode("tabindex"); - - return attributeNode && attributeNode.specified ? - parseInt( attributeNode.value, 10 ) : - rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? - 0 : - undefined; - } - } - } -}); - -// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) -__kivy__jQuery.attrHooks.tabindex = __kivy__jQuery.propHooks.tabIndex; - -// Hook for boolean attributes -boolHook = { - get: function( elem, name ) { - // Align boolean attributes with corresponding properties - // Fall back to attribute presence where some booleans are not supported - var attrNode, - property = __kivy__jQuery.prop( elem, name ); - return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? - name.toLowerCase() : - undefined; - }, - set: function( elem, value, name ) { - var propName; - if ( value === false ) { - // Remove boolean attributes when set to false - __kivy__jQuery.removeAttr( elem, name ); - } else { - // value is true since we know at this point it's type boolean and not false - // Set boolean attributes to the same name and set the DOM property - propName = __kivy__jQuery.propFix[ name ] || name; - if ( propName in elem ) { - // Only set the IDL specifically if it already exists on the element - elem[ propName ] = true; - } - - elem.setAttribute( name, name.toLowerCase() ); - } - return name; - } -}; - -// IE6/7 do not support getting/setting some attributes with get/setAttribute -if ( !getSetAttribute ) { - - fixSpecified = { - name: true, - id: true - }; - - // Use this for any attribute in IE6/7 - // This fixes almost every IE6/7 issue - nodeHook = __kivy__jQuery.valHooks.button = { - get: function( elem, name ) { - var ret; - ret = elem.getAttributeNode( name ); - return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? - ret.nodeValue : - undefined; - }, - set: function( elem, value, name ) { - // Set the existing or create a new attribute node - var ret = elem.getAttributeNode( name ); - if ( !ret ) { - ret = document.createAttribute( name ); - elem.setAttributeNode( ret ); - } - return ( ret.nodeValue = value + "" ); - } - }; - - // Apply the nodeHook to tabindex - __kivy__jQuery.attrHooks.tabindex.set = nodeHook.set; - - // Set width and height to auto instead of 0 on empty string( Bug #8150 ) - // This is for removals - __kivy__jQuery.each([ "width", "height" ], function( i, name ) { - __kivy__jQuery.attrHooks[ name ] = __kivy__jQuery.extend( __kivy__jQuery.attrHooks[ name ], { - set: function( elem, value ) { - if ( value === "" ) { - elem.setAttribute( name, "auto" ); - return value; - } - } - }); - }); - - // Set contenteditable to false on removals(#10429) - // Setting to empty string throws an error as an invalid value - __kivy__jQuery.attrHooks.contenteditable = { - get: nodeHook.get, - set: function( elem, value, name ) { - if ( value === "" ) { - value = "false"; - } - nodeHook.set( elem, value, name ); - } - }; -} - - -// Some attributes require a special call on IE -if ( !__kivy__jQuery.support.hrefNormalized ) { - __kivy__jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { - __kivy__jQuery.attrHooks[ name ] = __kivy__jQuery.extend( __kivy__jQuery.attrHooks[ name ], { - get: function( elem ) { - var ret = elem.getAttribute( name, 2 ); - return ret === null ? undefined : ret; - } - }); - }); -} - -if ( !__kivy__jQuery.support.style ) { - __kivy__jQuery.attrHooks.style = { - get: function( elem ) { - // Return undefined in the case of empty string - // Normalize to lowercase since IE uppercases css property names - return elem.style.cssText.toLowerCase() || undefined; - }, - set: function( elem, value ) { - return ( elem.style.cssText = "" + value ); - } - }; -} - -// Safari mis-reports the default selected property of an option -// Accessing the parent's selectedIndex property fixes it -if ( !__kivy__jQuery.support.optSelected ) { - __kivy__jQuery.propHooks.selected = __kivy__jQuery.extend( __kivy__jQuery.propHooks.selected, { - get: function( elem ) { - var parent = elem.parentNode; - - if ( parent ) { - parent.selectedIndex; - - // Make sure that it also works with optgroups, see #5701 - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - return null; - } - }); -} - -// IE6/7 call enctype encoding -if ( !__kivy__jQuery.support.enctype ) { - __kivy__jQuery.propFix.enctype = "encoding"; -} - -// Radios and checkboxes getter/setter -if ( !__kivy__jQuery.support.checkOn ) { - __kivy__jQuery.each([ "radio", "checkbox" ], function() { - __kivy__jQuery.valHooks[ this ] = { - get: function( elem ) { - // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified - return elem.getAttribute("value") === null ? "on" : elem.value; - } - }; - }); -} -__kivy__jQuery.each([ "radio", "checkbox" ], function() { - __kivy__jQuery.valHooks[ this ] = __kivy__jQuery.extend( __kivy__jQuery.valHooks[ this ], { - set: function( elem, value ) { - if ( __kivy__jQuery.isArray( value ) ) { - return ( elem.checked = __kivy__jQuery.inArray( __kivy__jQuery(elem).val(), value ) >= 0 ); - } - } - }); -}); - - - - -var rformElems = /^(?:textarea|input|select)$/i, - rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, - rhoverHack = /\bhover(\.\S+)?\b/, - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|contextmenu)|click/, - rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, - quickParse = function( selector ) { - var quick = rquickIs.exec( selector ); - if ( quick ) { - // 0 1 2 3 - // [ _, tag, id, class ] - quick[1] = ( quick[1] || "" ).toLowerCase(); - quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); - } - return quick; - }, - quickIs = function( elem, m ) { - var attrs = elem.attributes || {}; - return ( - (!m[1] || elem.nodeName.toLowerCase() === m[1]) && - (!m[2] || (attrs.id || {}).value === m[2]) && - (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) - ); - }, - hoverHack = function( events ) { - return __kivy__jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); - }; - -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -__kivy__jQuery.event = { - - add: function( elem, types, handler, data, selector ) { - - var elemData, eventHandle, events, - t, tns, type, namespaces, handleObj, - handleObjIn, quick, handlers, special; - - // Don't attach events to noData or text/comment nodes (allow plain objects tho) - if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = __kivy__jQuery._data( elem )) ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = __kivy__jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - events = elemData.events; - if ( !events ) { - elemData.events = events = {}; - } - eventHandle = elemData.handle; - if ( !eventHandle ) { - elemData.handle = eventHandle = function( e ) { - // Discard the second event of a __kivy__jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof __kivy__jQuery !== "undefined" && (!e || __kivy__jQuery.event.triggered !== e.type) ? - __kivy__jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : - undefined; - }; - // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events - eventHandle.elem = elem; - } - - // Handle multiple events separated by a space - // __kivy__jQuery(...).bind("mouseover mouseout", fn); - types = __kivy__jQuery.trim( hoverHack(types) ).split( " " ); - for ( t = 0; t < types.length; t++ ) { - - tns = rtypenamespace.exec( types[t] ) || []; - type = tns[1]; - namespaces = ( tns[2] || "" ).split( "." ).sort(); - - // If event changes its type, use the special event handlers for the changed type - special = __kivy__jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = __kivy__jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = __kivy__jQuery.extend({ - type: type, - origType: tns[1], - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - quick: quickParse( selector ), - namespace: namespaces.join(".") - }, handleObjIn ); - - // Init the event handler queue if we're the first - handlers = events[ type ]; - if ( !handlers ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener/attachEvent if the special events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - // Bind the global event handler to the element - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - - } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - __kivy__jQuery.event.global[ type ] = true; - } - - // Nullify elem to prevent memory leaks in IE - elem = null; - }, - - global: {}, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - - var elemData = __kivy__jQuery.hasData( elem ) && __kivy__jQuery._data( elem ), - t, tns, type, origType, namespaces, origCount, - j, events, special, handle, eventType, handleObj; - - if ( !elemData || !(events = elemData.events) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = __kivy__jQuery.trim( hoverHack( types || "" ) ).split(" "); - for ( t = 0; t < types.length; t++ ) { - tns = rtypenamespace.exec( types[t] ) || []; - type = origType = tns[1]; - namespaces = tns[2]; - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - __kivy__jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = __kivy__jQuery.event.special[ type ] || {}; - type = ( selector? special.delegateType : special.bindType ) || type; - eventType = events[ type ] || []; - origCount = eventType.length; - namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; - - // Remove matching events - for ( j = 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !namespaces || namespaces.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { - eventType.splice( j--, 1 ); - - if ( handleObj.selector ) { - eventType.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( eventType.length === 0 && origCount !== eventType.length ) { - if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { - __kivy__jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( __kivy__jQuery.isEmptyObject( events ) ) { - handle = elemData.handle; - if ( handle ) { - handle.elem = null; - } - - // removeData also checks for emptiness and clears the expando if empty - // so use it instead of delete - __kivy__jQuery.removeData( elem, [ "events", "handle" ], true ); - } - }, - - // Events that are safe to short-circuit if no handlers are attached. - // Native DOM events should not be added, they may have inline handlers. - customEvent: { - "getData": true, - "setData": true, - "changeData": true - }, - - trigger: function( event, data, elem, onlyHandlers ) { - // Don't do events on text and comment nodes - if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { - return; - } - - // Event object or event type - var type = event.type || event, - namespaces = [], - cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + __kivy__jQuery.event.triggered ) ) { - return; - } - - if ( type.indexOf( "!" ) >= 0 ) { - // Exclusive events trigger only for the exact event (no namespaces) - type = type.slice(0, -1); - exclusive = true; - } - - if ( type.indexOf( "." ) >= 0 ) { - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); - type = namespaces.shift(); - namespaces.sort(); - } - - if ( (!elem || __kivy__jQuery.event.customEvent[ type ]) && !__kivy__jQuery.event.global[ type ] ) { - // No __kivy__jQuery handlers for this event type, and it can't have inline handlers - return; - } - - // Caller can pass in an Event, Object, or just an event type string - event = typeof event === "object" ? - // __kivy__jQuery.Event object - event[ __kivy__jQuery.expando ] ? event : - // Object literal - new __kivy__jQuery.Event( type, event ) : - // Just the event type (string) - new __kivy__jQuery.Event( type ); - - event.type = type; - event.isTrigger = true; - event.exclusive = exclusive; - event.namespace = namespaces.join( "." ); - event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; - ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; - - // Handle a global trigger - if ( !elem ) { - - // TODO: Stop taunting the data cache; remove global events and always attach to document - cache = __kivy__jQuery.cache; - for ( i in cache ) { - if ( cache[ i ].events && cache[ i ].events[ type ] ) { - __kivy__jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); - } - } - return; - } - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data != null ? __kivy__jQuery.makeArray( data ) : []; - data.unshift( event ); - - // Allow special events to draw outside the lines - special = __kivy__jQuery.event.special[ type ] || {}; - if ( special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - eventPath = [[ elem, special.bindType || type ]]; - if ( !onlyHandlers && !special.noBubble && !__kivy__jQuery.isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; - old = null; - for ( ; cur; cur = cur.parentNode ) { - eventPath.push([ cur, bubbleType ]); - old = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( old && old === elem.ownerDocument ) { - eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); - } - } - - // Fire handlers on the event path - for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { - - cur = eventPath[i][0]; - event.type = eventPath[i][1]; - - handle = ( __kivy__jQuery._data( cur, "events" ) || {} )[ event.type ] && __kivy__jQuery._data( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - // Note that this is a bare JS function and not a __kivy__jQuery handler - handle = ontype && cur[ ontype ]; - if ( handle && __kivy__jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { - event.preventDefault(); - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { - - if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && - !(type === "click" && __kivy__jQuery.nodeName( elem, "a" )) && __kivy__jQuery.acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name name as the event. - // Can't use an .isFunction() check here because IE6/7 fails that test. - // Don't do default actions on window, that's where global variables be (#6170) - // IE<9 dies on focus/blur to hidden element (#1486) - if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !__kivy__jQuery.isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - old = elem[ ontype ]; - - if ( old ) { - elem[ ontype ] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - __kivy__jQuery.event.triggered = type; - elem[ type ](); - __kivy__jQuery.event.triggered = undefined; - - if ( old ) { - elem[ ontype ] = old; - } - } - } - } - - return event.result; - }, - - dispatch: function( event ) { - - // Make a writable __kivy__jQuery.Event from the native event object - event = __kivy__jQuery.event.fix( event || window.event ); - - var handlers = ( (__kivy__jQuery._data( this, "events" ) || {} )[ event.type ] || []), - delegateCount = handlers.delegateCount, - args = [].slice.call( arguments, 0 ), - run_all = !event.exclusive && !event.namespace, - handlerQueue = [], - i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; - - // Use the fix-ed __kivy__jQuery.Event rather than the (read-only) native event - args[0] = event; - event.delegateTarget = this; - - // Determine handlers that should run if there are delegated events - // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861) - if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) { - - // Pregenerate a single __kivy__jQuery object for reuse with .is() - jqcur = __kivy__jQuery(this); - jqcur.context = this.ownerDocument || this; - - for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { - selMatch = {}; - matches = []; - jqcur[0] = cur; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - sel = handleObj.selector; - - if ( selMatch[ sel ] === undefined ) { - selMatch[ sel ] = ( - handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) - ); - } - if ( selMatch[ sel ] ) { - matches.push( handleObj ); - } - } - if ( matches.length ) { - handlerQueue.push({ elem: cur, matches: matches }); - } - } - } - - // Add the remaining (directly-bound) handlers - if ( handlers.length > delegateCount ) { - handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); - } - - // Run delegates first; they may want to stop propagation beneath us - for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { - matched = handlerQueue[ i ]; - event.currentTarget = matched.elem; - - for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { - handleObj = matched.matches[ j ]; - - // Triggered event must either 1) be non-exclusive and have no namespace, or - // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). - if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { - - event.data = handleObj.data; - event.handleObj = handleObj; - - ret = ( (__kivy__jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) - .apply( matched.elem, args ); - - if ( ret !== undefined ) { - event.result = ret; - if ( ret === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - return event.result; - }, - - // Includes some event props shared by KeyEvent and MouseEvent - // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** - props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), - - fixHooks: {}, - - keyHooks: { - props: "char charCode key keyCode".split(" "), - filter: function( event, original ) { - - // Add which for key events - if ( event.which == null ) { - event.which = original.charCode != null ? original.charCode : original.keyCode; - } - - return event; - } - }, - - mouseHooks: { - props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), - filter: function( event, original ) { - var eventDoc, doc, body, - button = original.button, - fromElement = original.fromElement; - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && original.clientX != null ) { - eventDoc = event.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - - event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); - event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); - } - - // Add relatedTarget, if necessary - if ( !event.relatedTarget && fromElement ) { - event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && button !== undefined ) { - event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); - } - - return event; - } - }, - - fix: function( event ) { - if ( event[ __kivy__jQuery.expando ] ) { - return event; - } - - // Create a writable copy of the event object and normalize some properties - var i, prop, - originalEvent = event, - fixHook = __kivy__jQuery.event.fixHooks[ event.type ] || {}, - copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; - - event = __kivy__jQuery.Event( originalEvent ); - - for ( i = copy.length; i; ) { - prop = copy[ --i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) - if ( !event.target ) { - event.target = originalEvent.srcElement || document; - } - - // Target should not be a text node (#504, Safari) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) - if ( event.metaKey === undefined ) { - event.metaKey = event.ctrlKey; - } - - return fixHook.filter? fixHook.filter( event, originalEvent ) : event; - }, - - special: { - ready: { - // Make sure the ready event is setup - setup: __kivy__jQuery.bindReady - }, - - load: { - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - - focus: { - delegateType: "focusin" - }, - blur: { - delegateType: "focusout" - }, - - beforeunload: { - setup: function( data, namespaces, eventHandle ) { - // We only want to do this special case on windows - if ( __kivy__jQuery.isWindow( this ) ) { - this.onbeforeunload = eventHandle; - } - }, - - teardown: function( namespaces, eventHandle ) { - if ( this.onbeforeunload === eventHandle ) { - this.onbeforeunload = null; - } - } - } - }, - - simulate: function( type, elem, event, bubble ) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - var e = __kivy__jQuery.extend( - new __kivy__jQuery.Event(), - event, - { type: type, - isSimulated: true, - originalEvent: {} - } - ); - if ( bubble ) { - __kivy__jQuery.event.trigger( e, null, elem ); - } else { - __kivy__jQuery.event.dispatch.call( elem, e ); - } - if ( e.isDefaultPrevented() ) { - event.preventDefault(); - } - } -}; - -// Some plugins are using, but it's undocumented/deprecated and will be removed. -// The 1.7 special event interface should provide all the hooks needed now. -__kivy__jQuery.event.handle = __kivy__jQuery.event.dispatch; - -__kivy__jQuery.removeEvent = document.removeEventListener ? - function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); - } - } : - function( elem, type, handle ) { - if ( elem.detachEvent ) { - elem.detachEvent( "on" + type, handle ); - } - }; - -__kivy__jQuery.Event = function( src, props ) { - // Allow instantiation without the 'new' keyword - if ( !(this instanceof __kivy__jQuery.Event) ) { - return new __kivy__jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || - src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - __kivy__jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || __kivy__jQuery.now(); - - // Mark it as fixed - this[ __kivy__jQuery.expando ] = true; -}; - -function returnFalse() { - return false; -} -function returnTrue() { - return true; -} - -// __kivy__jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -__kivy__jQuery.Event.prototype = { - preventDefault: function() { - this.isDefaultPrevented = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - - // if preventDefault exists run it on the original event - if ( e.preventDefault ) { - e.preventDefault(); - - // otherwise set the returnValue property of the original event to false (IE) - } else { - e.returnValue = false; - } - }, - stopPropagation: function() { - this.isPropagationStopped = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - // if stopPropagation exists run it on the original event - if ( e.stopPropagation ) { - e.stopPropagation(); - } - // otherwise set the cancelBubble property of the original event to true (IE) - e.cancelBubble = true; - }, - stopImmediatePropagation: function() { - this.isImmediatePropagationStopped = returnTrue; - this.stopPropagation(); - }, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse -}; - -// Create mouseenter/leave events using mouseover/out and event-time checks -__kivy__jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout" -}, function( orig, fix ) { - __kivy__jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var target = this, - related = event.relatedTarget, - handleObj = event.handleObj, - selector = handleObj.selector, - ret; - - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || (related !== target && !__kivy__jQuery.contains( target, related )) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -}); - -// IE submit delegation -if ( !__kivy__jQuery.support.submitBubbles ) { - - __kivy__jQuery.event.special.submit = { - setup: function() { - // Only need this for delegated form submit events - if ( __kivy__jQuery.nodeName( this, "form" ) ) { - return false; - } - - // Lazy-add a submit handler when a descendant form may potentially be submitted - __kivy__jQuery.event.add( this, "click._submit keypress._submit", function( e ) { - // Node name check avoids a VML-related crash in IE (#9807) - var elem = e.target, - form = __kivy__jQuery.nodeName( elem, "input" ) || __kivy__jQuery.nodeName( elem, "button" ) ? elem.form : undefined; - if ( form && !form._submit_attached ) { - __kivy__jQuery.event.add( form, "submit._submit", function( event ) { - // If form was submitted by the user, bubble the event up the tree - if ( this.parentNode && !event.isTrigger ) { - __kivy__jQuery.event.simulate( "submit", this.parentNode, event, true ); - } - }); - form._submit_attached = true; - } - }); - // return undefined since we don't need an event listener - }, - - teardown: function() { - // Only need this for delegated form submit events - if ( __kivy__jQuery.nodeName( this, "form" ) ) { - return false; - } - - // Remove delegated handlers; cleanData eventually reaps submit handlers attached above - __kivy__jQuery.event.remove( this, "._submit" ); - } - }; -} - -// IE change delegation and checkbox/radio fix -if ( !__kivy__jQuery.support.changeBubbles ) { - - __kivy__jQuery.event.special.change = { - - setup: function() { - - if ( rformElems.test( this.nodeName ) ) { - // IE doesn't fire change on a check/radio until blur; trigger it on click - // after a propertychange. Eat the blur-change in special.change.handle. - // This still fires onchange a second time for check/radio after blur. - if ( this.type === "checkbox" || this.type === "radio" ) { - __kivy__jQuery.event.add( this, "propertychange._change", function( event ) { - if ( event.originalEvent.propertyName === "checked" ) { - this._just_changed = true; - } - }); - __kivy__jQuery.event.add( this, "click._change", function( event ) { - if ( this._just_changed && !event.isTrigger ) { - this._just_changed = false; - __kivy__jQuery.event.simulate( "change", this, event, true ); - } - }); - } - return false; - } - // Delegated event; lazy-add a change handler on descendant inputs - __kivy__jQuery.event.add( this, "beforeactivate._change", function( e ) { - var elem = e.target; - - if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { - __kivy__jQuery.event.add( elem, "change._change", function( event ) { - if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { - __kivy__jQuery.event.simulate( "change", this.parentNode, event, true ); - } - }); - elem._change_attached = true; - } - }); - }, - - handle: function( event ) { - var elem = event.target; - - // Swallow native change events from checkbox/radio, we already triggered them above - if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { - return event.handleObj.handler.apply( this, arguments ); - } - }, - - teardown: function() { - __kivy__jQuery.event.remove( this, "._change" ); - - return rformElems.test( this.nodeName ); - } - }; -} - -// Create "bubbling" focus and blur events -if ( !__kivy__jQuery.support.focusinBubbles ) { - __kivy__jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler while someone wants focusin/focusout - var attaches = 0, - handler = function( event ) { - __kivy__jQuery.event.simulate( fix, event.target, __kivy__jQuery.event.fix( event ), true ); - }; - - __kivy__jQuery.event.special[ fix ] = { - setup: function() { - if ( attaches++ === 0 ) { - document.addEventListener( orig, handler, true ); - } - }, - teardown: function() { - if ( --attaches === 0 ) { - document.removeEventListener( orig, handler, true ); - } - } - }; - }); -} - -__kivy__jQuery.fn.extend({ - - on: function( types, selector, data, fn, /*INTERNAL*/ one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { - // ( types-Object, data ) - data = selector; - selector = undefined; - } - for ( type in types ) { - this.on( type, selector, data, types[ type ], one ); - } - return this; - } - - if ( data == null && fn == null ) { - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return this; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - // Can use an empty set, since event contains the info - __kivy__jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = __kivy__jQuery.guid++ ); - } - return this.each( function() { - __kivy__jQuery.event.add( this, types, fn, data, selector ); - }); - }, - one: function( types, selector, data, fn ) { - return this.on.call( this, types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - if ( types && types.preventDefault && types.handleObj ) { - // ( event ) dispatched __kivy__jQuery.Event - var handleObj = types.handleObj; - __kivy__jQuery( types.delegateTarget ).off( - handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - // ( types-object [, selector] ) - for ( var type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each(function() { - __kivy__jQuery.event.remove( this, types, fn, selector ); - }); - }, - - bind: function( types, data, fn ) { - return this.on( types, null, data, fn ); - }, - unbind: function( types, fn ) { - return this.off( types, null, fn ); - }, - - live: function( types, data, fn ) { - __kivy__jQuery( this.context ).on( types, this.selector, data, fn ); - return this; - }, - die: function( types, fn ) { - __kivy__jQuery( this.context ).off( types, this.selector || "**", fn ); - return this; - }, - - delegate: function( selector, types, data, fn ) { - return this.on( types, selector, data, fn ); - }, - undelegate: function( selector, types, fn ) { - // ( namespace ) or ( selector, types [, fn] ) - return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); - }, - - trigger: function( type, data ) { - return this.each(function() { - __kivy__jQuery.event.trigger( type, data, this ); - }); - }, - triggerHandler: function( type, data ) { - if ( this[0] ) { - return __kivy__jQuery.event.trigger( type, data, this[0], true ); - } - }, - - toggle: function( fn ) { - // Save reference to arguments for access in closure - var args = arguments, - guid = fn.guid || __kivy__jQuery.guid++, - i = 0, - toggler = function( event ) { - // Figure out which function to execute - var lastToggle = ( __kivy__jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; - __kivy__jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); - - // Make sure that clicks stop - event.preventDefault(); - - // and execute the function - return args[ lastToggle ].apply( this, arguments ) || false; - }; - - // link all the functions, so any of them can unbind this click handler - toggler.guid = guid; - while ( i < args.length ) { - args[ i++ ].guid = guid; - } - - return this.click( toggler ); - }, - - hover: function( fnOver, fnOut ) { - return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); - } -}); - -__kivy__jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { - - // Handle event binding - __kivy__jQuery.fn[ name ] = function( data, fn ) { - if ( fn == null ) { - fn = data; - data = null; - } - - return arguments.length > 0 ? - this.on( name, null, data, fn ) : - this.trigger( name ); - }; - - if ( __kivy__jQuery.attrFn ) { - __kivy__jQuery.attrFn[ name ] = true; - } - - if ( rkeyEvent.test( name ) ) { - __kivy__jQuery.event.fixHooks[ name ] = __kivy__jQuery.event.keyHooks; - } - - if ( rmouseEvent.test( name ) ) { - __kivy__jQuery.event.fixHooks[ name ] = __kivy__jQuery.event.mouseHooks; - } -}); - - - -/*! - * Sizzle CSS Selector Engine - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){ - -var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, - expando = "sizcache" + (Math.random() + '').replace('.', ''), - done = 0, - toString = Object.prototype.toString, - hasDuplicate = false, - baseHasDuplicate = true, - rBackslash = /\\/g, - rReturn = /\r\n/g, - rNonWord = /\W/; - -// Here we check if the JavaScript engine is using some sort of -// optimization where it does not always call our comparision -// function. If that is the case, discard the hasDuplicate value. -// Thus far that includes Google Chrome. -[0, 0].sort(function() { - baseHasDuplicate = false; - return 0; -}); - -var Sizzle = function( selector, context, results, seed ) { - results = results || []; - context = context || document; - - var origContext = context; - - if ( context.nodeType !== 1 && context.nodeType !== 9 ) { - return []; - } - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - var m, set, checkSet, extra, ret, cur, pop, i, - prune = true, - contextXML = Sizzle.isXML( context ), - parts = [], - soFar = selector; - - // Reset the position of the chunker regexp (start from head) - do { - chunker.exec( "" ); - m = chunker.exec( soFar ); - - if ( m ) { - soFar = m[3]; - - parts.push( m[1] ); - - if ( m[2] ) { - extra = m[3]; - break; - } - } - } while ( m ); - - if ( parts.length > 1 && origPOS.exec( selector ) ) { - - if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { - set = posProcess( parts[0] + parts[1], context, seed ); - - } else { - set = Expr.relative[ parts[0] ] ? - [ context ] : - Sizzle( parts.shift(), context ); - - while ( parts.length ) { - selector = parts.shift(); - - if ( Expr.relative[ selector ] ) { - selector += parts.shift(); - } - - set = posProcess( selector, set, seed ); - } - } - - } else { - // Take a shortcut and set the context if the root selector is an ID - // (but not if it'll be faster if the inner selector is an ID) - if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && - Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { - - ret = Sizzle.find( parts.shift(), context, contextXML ); - context = ret.expr ? - Sizzle.filter( ret.expr, ret.set )[0] : - ret.set[0]; - } - - if ( context ) { - ret = seed ? - { expr: parts.pop(), set: makeArray(seed) } : - Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); - - set = ret.expr ? - Sizzle.filter( ret.expr, ret.set ) : - ret.set; - - if ( parts.length > 0 ) { - checkSet = makeArray( set ); - - } else { - prune = false; - } - - while ( parts.length ) { - cur = parts.pop(); - pop = cur; - - if ( !Expr.relative[ cur ] ) { - cur = ""; - } else { - pop = parts.pop(); - } - - if ( pop == null ) { - pop = context; - } - - Expr.relative[ cur ]( checkSet, pop, contextXML ); - } - - } else { - checkSet = parts = []; - } - } - - if ( !checkSet ) { - checkSet = set; - } - - if ( !checkSet ) { - Sizzle.error( cur || selector ); - } - - if ( toString.call(checkSet) === "[object Array]" ) { - if ( !prune ) { - results.push.apply( results, checkSet ); - - } else if ( context && context.nodeType === 1 ) { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { - results.push( set[i] ); - } - } - - } else { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && checkSet[i].nodeType === 1 ) { - results.push( set[i] ); - } - } - } - - } else { - makeArray( checkSet, results ); - } - - if ( extra ) { - Sizzle( extra, origContext, results, seed ); - Sizzle.uniqueSort( results ); - } - - return results; -}; - -Sizzle.uniqueSort = function( results ) { - if ( sortOrder ) { - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( var i = 1; i < results.length; i++ ) { - if ( results[i] === results[ i - 1 ] ) { - results.splice( i--, 1 ); - } - } - } - } - - return results; -}; - -Sizzle.matches = function( expr, set ) { - return Sizzle( expr, null, null, set ); -}; - -Sizzle.matchesSelector = function( node, expr ) { - return Sizzle( expr, null, null, [node] ).length > 0; -}; - -Sizzle.find = function( expr, context, isXML ) { - var set, i, len, match, type, left; - - if ( !expr ) { - return []; - } - - for ( i = 0, len = Expr.order.length; i < len; i++ ) { - type = Expr.order[i]; - - if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { - left = match[1]; - match.splice( 1, 1 ); - - if ( left.substr( left.length - 1 ) !== "\\" ) { - match[1] = (match[1] || "").replace( rBackslash, "" ); - set = Expr.find[ type ]( match, context, isXML ); - - if ( set != null ) { - expr = expr.replace( Expr.match[ type ], "" ); - break; - } - } - } - } - - if ( !set ) { - set = typeof context.getElementsByTagName !== "undefined" ? - context.getElementsByTagName( "*" ) : - []; - } - - return { set: set, expr: expr }; -}; - -Sizzle.filter = function( expr, set, inplace, not ) { - var match, anyFound, - type, found, item, filter, left, - i, pass, - old = expr, - result = [], - curLoop = set, - isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); - - while ( expr && set.length ) { - for ( type in Expr.filter ) { - if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { - filter = Expr.filter[ type ]; - left = match[1]; - - anyFound = false; - - match.splice(1,1); - - if ( left.substr( left.length - 1 ) === "\\" ) { - continue; - } - - if ( curLoop === result ) { - result = []; - } - - if ( Expr.preFilter[ type ] ) { - match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); - - if ( !match ) { - anyFound = found = true; - - } else if ( match === true ) { - continue; - } - } - - if ( match ) { - for ( i = 0; (item = curLoop[i]) != null; i++ ) { - if ( item ) { - found = filter( item, match, i, curLoop ); - pass = not ^ found; - - if ( inplace && found != null ) { - if ( pass ) { - anyFound = true; - - } else { - curLoop[i] = false; - } - - } else if ( pass ) { - result.push( item ); - anyFound = true; - } - } - } - } - - if ( found !== undefined ) { - if ( !inplace ) { - curLoop = result; - } - - expr = expr.replace( Expr.match[ type ], "" ); - - if ( !anyFound ) { - return []; - } - - break; - } - } - } - - // Improper expression - if ( expr === old ) { - if ( anyFound == null ) { - Sizzle.error( expr ); - - } else { - break; - } - } - - old = expr; - } - - return curLoop; -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -/** - * Utility function for retreiving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -var getText = Sizzle.getText = function( elem ) { - var i, node, - nodeType = elem.nodeType, - ret = ""; - - if ( nodeType ) { - if ( nodeType === 1 || nodeType === 9 ) { - // Use textContent || innerText for elements - if ( typeof elem.textContent === 'string' ) { - return elem.textContent; - } else if ( typeof elem.innerText === 'string' ) { - // Replace IE's carriage returns - return elem.innerText.replace( rReturn, '' ); - } else { - // Traverse it's children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - } else { - - // If no nodeType, this is expected to be an array - for ( i = 0; (node = elem[i]); i++ ) { - // Do not traverse comment nodes - if ( node.nodeType !== 8 ) { - ret += getText( node ); - } - } - } - return ret; -}; - -var Expr = Sizzle.selectors = { - order: [ "ID", "NAME", "TAG" ], - - match: { - ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, - ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, - TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, - CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, - POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, - PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ - }, - - leftMatch: {}, - - attrMap: { - "class": "className", - "for": "htmlFor" - }, - - attrHandle: { - href: function( elem ) { - return elem.getAttribute( "href" ); - }, - type: function( elem ) { - return elem.getAttribute( "type" ); - } - }, - - relative: { - "+": function(checkSet, part){ - var isPartStr = typeof part === "string", - isTag = isPartStr && !rNonWord.test( part ), - isPartStrNotTag = isPartStr && !isTag; - - if ( isTag ) { - part = part.toLowerCase(); - } - - for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { - if ( (elem = checkSet[i]) ) { - while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} - - checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? - elem || false : - elem === part; - } - } - - if ( isPartStrNotTag ) { - Sizzle.filter( part, checkSet, true ); - } - }, - - ">": function( checkSet, part ) { - var elem, - isPartStr = typeof part === "string", - i = 0, - l = checkSet.length; - - if ( isPartStr && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - var parent = elem.parentNode; - checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; - } - } - - } else { - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - checkSet[i] = isPartStr ? - elem.parentNode : - elem.parentNode === part; - } - } - - if ( isPartStr ) { - Sizzle.filter( part, checkSet, true ); - } - } - }, - - "": function(checkSet, part, isXML){ - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); - }, - - "~": function( checkSet, part, isXML ) { - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); - } - }, - - find: { - ID: function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - }, - - NAME: function( match, context ) { - if ( typeof context.getElementsByName !== "undefined" ) { - var ret = [], - results = context.getElementsByName( match[1] ); - - for ( var i = 0, l = results.length; i < l; i++ ) { - if ( results[i].getAttribute("name") === match[1] ) { - ret.push( results[i] ); - } - } - - return ret.length === 0 ? null : ret; - } - }, - - TAG: function( match, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( match[1] ); - } - } - }, - preFilter: { - CLASS: function( match, curLoop, inplace, result, not, isXML ) { - match = " " + match[1].replace( rBackslash, "" ) + " "; - - if ( isXML ) { - return match; - } - - for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { - if ( elem ) { - if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { - if ( !inplace ) { - result.push( elem ); - } - - } else if ( inplace ) { - curLoop[i] = false; - } - } - } - - return false; - }, - - ID: function( match ) { - return match[1].replace( rBackslash, "" ); - }, - - TAG: function( match, curLoop ) { - return match[1].replace( rBackslash, "" ).toLowerCase(); - }, - - CHILD: function( match ) { - if ( match[1] === "nth" ) { - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - match[2] = match[2].replace(/^\+|\s*/g, ''); - - // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' - var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( - match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || - !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); - - // calculate the numbers (first)n+(last) including if they are negative - match[2] = (test[1] + (test[2] || 1)) - 0; - match[3] = test[3] - 0; - } - else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - // TODO: Move to normal caching system - match[0] = done++; - - return match; - }, - - ATTR: function( match, curLoop, inplace, result, not, isXML ) { - var name = match[1] = match[1].replace( rBackslash, "" ); - - if ( !isXML && Expr.attrMap[name] ) { - match[1] = Expr.attrMap[name]; - } - - // Handle if an un-quoted value was used - match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); - - if ( match[2] === "~=" ) { - match[4] = " " + match[4] + " "; - } - - return match; - }, - - PSEUDO: function( match, curLoop, inplace, result, not ) { - if ( match[1] === "not" ) { - // If we're dealing with a complex expression, or a simple one - if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { - match[3] = Sizzle(match[3], null, null, curLoop); - - } else { - var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); - - if ( !inplace ) { - result.push.apply( result, ret ); - } - - return false; - } - - } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { - return true; - } - - return match; - }, - - POS: function( match ) { - match.unshift( true ); - - return match; - } - }, - - filters: { - enabled: function( elem ) { - return elem.disabled === false && elem.type !== "hidden"; - }, - - disabled: function( elem ) { - return elem.disabled === true; - }, - - checked: function( elem ) { - return elem.checked === true; - }, - - selected: function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - parent: function( elem ) { - return !!elem.firstChild; - }, - - empty: function( elem ) { - return !elem.firstChild; - }, - - has: function( elem, i, match ) { - return !!Sizzle( match[3], elem ).length; - }, - - header: function( elem ) { - return (/h\d/i).test( elem.nodeName ); - }, - - text: function( elem ) { - var attr = elem.getAttribute( "type" ), type = elem.type; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) - // use getAttribute instead to test this case - return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); - }, - - radio: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; - }, - - checkbox: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; - }, - - file: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; - }, - - password: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; - }, - - submit: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && "submit" === elem.type; - }, - - image: function( elem ) { - return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; - }, - - reset: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && "reset" === elem.type; - }, - - button: function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && "button" === elem.type || name === "button"; - }, - - input: function( elem ) { - return (/input|select|textarea|button/i).test( elem.nodeName ); - }, - - focus: function( elem ) { - return elem === elem.ownerDocument.activeElement; - } - }, - setFilters: { - first: function( elem, i ) { - return i === 0; - }, - - last: function( elem, i, match, array ) { - return i === array.length - 1; - }, - - even: function( elem, i ) { - return i % 2 === 0; - }, - - odd: function( elem, i ) { - return i % 2 === 1; - }, - - lt: function( elem, i, match ) { - return i < match[3] - 0; - }, - - gt: function( elem, i, match ) { - return i > match[3] - 0; - }, - - nth: function( elem, i, match ) { - return match[3] - 0 === i; - }, - - eq: function( elem, i, match ) { - return match[3] - 0 === i; - } - }, - filter: { - PSEUDO: function( elem, match, i, array ) { - var name = match[1], - filter = Expr.filters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - - } else if ( name === "contains" ) { - return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; - - } else if ( name === "not" ) { - var not = match[3]; - - for ( var j = 0, l = not.length; j < l; j++ ) { - if ( not[j] === elem ) { - return false; - } - } - - return true; - - } else { - Sizzle.error( name ); - } - }, - - CHILD: function( elem, match ) { - var first, last, - doneName, parent, cache, - count, diff, - type = match[1], - node = elem; - - switch ( type ) { - case "only": - case "first": - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - if ( type === "first" ) { - return true; - } - - node = elem; - - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - - case "nth": - first = match[2]; - last = match[3]; - - if ( first === 1 && last === 0 ) { - return true; - } - - doneName = match[0]; - parent = elem.parentNode; - - if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { - count = 0; - - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - node.nodeIndex = ++count; - } - } - - parent[ expando ] = doneName; - } - - diff = elem.nodeIndex - last; - - if ( first === 0 ) { - return diff === 0; - - } else { - return ( diff % first === 0 && diff / first >= 0 ); - } - } - }, - - ID: function( elem, match ) { - return elem.nodeType === 1 && elem.getAttribute("id") === match; - }, - - TAG: function( elem, match ) { - return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; - }, - - CLASS: function( elem, match ) { - return (" " + (elem.className || elem.getAttribute("class")) + " ") - .indexOf( match ) > -1; - }, - - ATTR: function( elem, match ) { - var name = match[1], - result = Sizzle.attr ? - Sizzle.attr( elem, name ) : - Expr.attrHandle[ name ] ? - Expr.attrHandle[ name ]( elem ) : - elem[ name ] != null ? - elem[ name ] : - elem.getAttribute( name ), - value = result + "", - type = match[2], - check = match[4]; - - return result == null ? - type === "!=" : - !type && Sizzle.attr ? - result != null : - type === "=" ? - value === check : - type === "*=" ? - value.indexOf(check) >= 0 : - type === "~=" ? - (" " + value + " ").indexOf(check) >= 0 : - !check ? - value && result !== false : - type === "!=" ? - value !== check : - type === "^=" ? - value.indexOf(check) === 0 : - type === "$=" ? - value.substr(value.length - check.length) === check : - type === "|=" ? - value === check || value.substr(0, check.length + 1) === check + "-" : - false; - }, - - POS: function( elem, match, i, array ) { - var name = match[2], - filter = Expr.setFilters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - } - } - } -}; - -var origPOS = Expr.match.POS, - fescape = function(all, num){ - return "\\" + (num - 0 + 1); - }; - -for ( var type in Expr.match ) { - Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); - Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); -} - -var makeArray = function( array, results ) { - array = Array.prototype.slice.call( array, 0 ); - - if ( results ) { - results.push.apply( results, array ); - return results; - } - - return array; -}; - -// Perform a simple check to determine if the browser is capable of -// converting a NodeList to an array using builtin methods. -// Also verifies that the returned array holds DOM nodes -// (which is not the case in the Blackberry browser) -try { - Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; - -// Provide a fallback method if it does not work -} catch( e ) { - makeArray = function( array, results ) { - var i = 0, - ret = results || []; - - if ( toString.call(array) === "[object Array]" ) { - Array.prototype.push.apply( ret, array ); - - } else { - if ( typeof array.length === "number" ) { - for ( var l = array.length; i < l; i++ ) { - ret.push( array[i] ); - } - - } else { - for ( ; array[i]; i++ ) { - ret.push( array[i] ); - } - } - } - - return ret; - }; -} - -var sortOrder, siblingCheck; - -if ( document.documentElement.compareDocumentPosition ) { - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { - return a.compareDocumentPosition ? -1 : 1; - } - - return a.compareDocumentPosition(b) & 4 ? -1 : 1; - }; - -} else { - sortOrder = function( a, b ) { - // The nodes are identical, we can exit early - if ( a === b ) { - hasDuplicate = true; - return 0; - - // Fallback to using sourceIndex (in IE) if it's available on both nodes - } else if ( a.sourceIndex && b.sourceIndex ) { - return a.sourceIndex - b.sourceIndex; - } - - var al, bl, - ap = [], - bp = [], - aup = a.parentNode, - bup = b.parentNode, - cur = aup; - - // If the nodes are siblings (or identical) we can do a quick check - if ( aup === bup ) { - return siblingCheck( a, b ); - - // If no parents were found then the nodes are disconnected - } else if ( !aup ) { - return -1; - - } else if ( !bup ) { - return 1; - } - - // Otherwise they're somewhere else in the tree so we need - // to build up a full list of the parentNodes for comparison - while ( cur ) { - ap.unshift( cur ); - cur = cur.parentNode; - } - - cur = bup; - - while ( cur ) { - bp.unshift( cur ); - cur = cur.parentNode; - } - - al = ap.length; - bl = bp.length; - - // Start walking down the tree looking for a discrepancy - for ( var i = 0; i < al && i < bl; i++ ) { - if ( ap[i] !== bp[i] ) { - return siblingCheck( ap[i], bp[i] ); - } - } - - // We ended someplace up the tree so do a sibling check - return i === al ? - siblingCheck( a, bp[i], -1 ) : - siblingCheck( ap[i], b, 1 ); - }; - - siblingCheck = function( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; - }; -} - -// Check to see if the browser returns elements by name when -// querying by getElementById (and provide a workaround) -(function(){ - // We're going to inject a fake input element with a specified name - var form = document.createElement("div"), - id = "script" + (new Date()).getTime(), - root = document.documentElement; - - form.innerHTML = ""; - - // Inject it into the root element, check its status, and remove it quickly - root.insertBefore( form, root.firstChild ); - - // The workaround has to do additional checks after a getElementById - // Which slows things down for other browsers (hence the branching) - if ( document.getElementById( id ) ) { - Expr.find.ID = function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - - return m ? - m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? - [m] : - undefined : - []; - } - }; - - Expr.filter.ID = function( elem, match ) { - var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); - - return elem.nodeType === 1 && node && node.nodeValue === match; - }; - } - - root.removeChild( form ); - - // release memory in IE - root = form = null; -})(); - -(function(){ - // Check to see if the browser returns only elements - // when doing getElementsByTagName("*") - - // Create a fake element - var div = document.createElement("div"); - div.appendChild( document.createComment("") ); - - // Make sure no comments are found - if ( div.getElementsByTagName("*").length > 0 ) { - Expr.find.TAG = function( match, context ) { - var results = context.getElementsByTagName( match[1] ); - - // Filter out possible comments - if ( match[1] === "*" ) { - var tmp = []; - - for ( var i = 0; results[i]; i++ ) { - if ( results[i].nodeType === 1 ) { - tmp.push( results[i] ); - } - } - - results = tmp; - } - - return results; - }; - } - - // Check to see if an attribute returns normalized href attributes - div.innerHTML = ""; - - if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && - div.firstChild.getAttribute("href") !== "#" ) { - - Expr.attrHandle.href = function( elem ) { - return elem.getAttribute( "href", 2 ); - }; - } - - // release memory in IE - div = null; -})(); - -if ( document.querySelectorAll ) { - (function(){ - var oldSizzle = Sizzle, - div = document.createElement("div"), - id = "__sizzle__"; - - div.innerHTML = "

      "; - - // Safari can't handle uppercase or unicode characters when - // in quirks mode. - if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { - return; - } - - Sizzle = function( query, context, extra, seed ) { - context = context || document; - - // Only use querySelectorAll on non-XML documents - // (ID selectors don't work in non-HTML documents) - if ( !seed && !Sizzle.isXML(context) ) { - // See if we find a selector to speed up - var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - - if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { - // Speed-up: Sizzle("TAG") - if ( match[1] ) { - return makeArray( context.getElementsByTagName( query ), extra ); - - // Speed-up: Sizzle(".CLASS") - } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { - return makeArray( context.getElementsByClassName( match[2] ), extra ); - } - } - - if ( context.nodeType === 9 ) { - // Speed-up: Sizzle("body") - // The body element only exists once, optimize finding it - if ( query === "body" && context.body ) { - return makeArray( [ context.body ], extra ); - - // Speed-up: Sizzle("#ID") - } else if ( match && match[3] ) { - var elem = context.getElementById( match[3] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id === match[3] ) { - return makeArray( [ elem ], extra ); - } - - } else { - return makeArray( [], extra ); - } - } - - try { - return makeArray( context.querySelectorAll(query), extra ); - } catch(qsaError) {} - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - var oldContext = context, - old = context.getAttribute( "id" ), - nid = old || id, - hasParent = context.parentNode, - relativeHierarchySelector = /^\s*[+~]/.test( query ); - - if ( !old ) { - context.setAttribute( "id", nid ); - } else { - nid = nid.replace( /'/g, "\\$&" ); - } - if ( relativeHierarchySelector && hasParent ) { - context = context.parentNode; - } - - try { - if ( !relativeHierarchySelector || hasParent ) { - return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); - } - - } catch(pseudoError) { - } finally { - if ( !old ) { - oldContext.removeAttribute( "id" ); - } - } - } - } - - return oldSizzle(query, context, extra, seed); - }; - - for ( var prop in oldSizzle ) { - Sizzle[ prop ] = oldSizzle[ prop ]; - } - - // release memory in IE - div = null; - })(); -} - -(function(){ - var html = document.documentElement, - matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; - - if ( matches ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9 fails this) - var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), - pseudoWorks = false; - - try { - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( document.documentElement, "[test!='']:sizzle" ); - - } catch( pseudoError ) { - pseudoWorks = true; - } - - Sizzle.matchesSelector = function( node, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); - - if ( !Sizzle.isXML( node ) ) { - try { - if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { - var ret = matches.call( node, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || !disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9, so check for that - node.document && node.document.nodeType !== 11 ) { - return ret; - } - } - } catch(e) {} - } - - return Sizzle(expr, null, null, [node]).length > 0; - }; - } -})(); - -(function(){ - var div = document.createElement("div"); - - div.innerHTML = "
      "; - - // Opera can't find a second classname (in 9.6) - // Also, make sure that getElementsByClassName actually exists - if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { - return; - } - - // Safari caches class attributes, doesn't catch changes (in 3.2) - div.lastChild.className = "e"; - - if ( div.getElementsByClassName("e").length === 1 ) { - return; - } - - Expr.order.splice(1, 0, "CLASS"); - Expr.find.CLASS = function( match, context, isXML ) { - if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { - return context.getElementsByClassName(match[1]); - } - }; - - // release memory in IE - div = null; -})(); - -function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem[ expando ] === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 && !isXML ){ - elem[ expando ] = doneName; - elem.sizset = i; - } - - if ( elem.nodeName.toLowerCase() === cur ) { - match = elem; - break; - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem[ expando ] === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 ) { - if ( !isXML ) { - elem[ expando ] = doneName; - elem.sizset = i; - } - - if ( typeof cur !== "string" ) { - if ( elem === cur ) { - match = true; - break; - } - - } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { - match = elem; - break; - } - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -if ( document.documentElement.contains ) { - Sizzle.contains = function( a, b ) { - return a !== b && (a.contains ? a.contains(b) : true); - }; - -} else if ( document.documentElement.compareDocumentPosition ) { - Sizzle.contains = function( a, b ) { - return !!(a.compareDocumentPosition(b) & 16); - }; - -} else { - Sizzle.contains = function() { - return false; - }; -} - -Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; - - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -var posProcess = function( selector, context, seed ) { - var match, - tmpSet = [], - later = "", - root = context.nodeType ? [context] : context; - - // Position selectors must be done after the filter - // And so must :not(positional) so we move all PSEUDOs to the end - while ( (match = Expr.match.PSEUDO.exec( selector )) ) { - later += match[0]; - selector = selector.replace( Expr.match.PSEUDO, "" ); - } - - selector = Expr.relative[selector] ? selector + "*" : selector; - - for ( var i = 0, l = root.length; i < l; i++ ) { - Sizzle( selector, root[i], tmpSet, seed ); - } - - return Sizzle.filter( later, tmpSet ); -}; - -// EXPOSE -// Override sizzle attribute retrieval -Sizzle.attr = __kivy__jQuery.attr; -Sizzle.selectors.attrMap = {}; -__kivy__jQuery.find = Sizzle; -__kivy__jQuery.expr = Sizzle.selectors; -__kivy__jQuery.expr[":"] = __kivy__jQuery.expr.filters; -__kivy__jQuery.unique = Sizzle.uniqueSort; -__kivy__jQuery.text = Sizzle.getText; -__kivy__jQuery.isXMLDoc = Sizzle.isXML; -__kivy__jQuery.contains = Sizzle.contains; - - -})(); - - -var runtil = /Until$/, - rparentsprev = /^(?:parents|prevUntil|prevAll)/, - // Note: This RegExp should be improved, or likely pulled from Sizzle - rmultiselector = /,/, - isSimple = /^.[^:#\[\.,]*$/, - slice = Array.prototype.slice, - POS = __kivy__jQuery.expr.match.POS, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -__kivy__jQuery.fn.extend({ - find: function( selector ) { - var self = this, - i, l; - - if ( typeof selector !== "string" ) { - return __kivy__jQuery( selector ).filter(function() { - for ( i = 0, l = self.length; i < l; i++ ) { - if ( __kivy__jQuery.contains( self[ i ], this ) ) { - return true; - } - } - }); - } - - var ret = this.pushStack( "", "find", selector ), - length, n, r; - - for ( i = 0, l = this.length; i < l; i++ ) { - length = ret.length; - __kivy__jQuery.find( selector, this[i], ret ); - - if ( i > 0 ) { - // Make sure that the results are unique - for ( n = length; n < ret.length; n++ ) { - for ( r = 0; r < length; r++ ) { - if ( ret[r] === ret[n] ) { - ret.splice(n--, 1); - break; - } - } - } - } - } - - return ret; - }, - - has: function( target ) { - var targets = __kivy__jQuery( target ); - return this.filter(function() { - for ( var i = 0, l = targets.length; i < l; i++ ) { - if ( __kivy__jQuery.contains( this, targets[i] ) ) { - return true; - } - } - }); - }, - - not: function( selector ) { - return this.pushStack( winnow(this, selector, false), "not", selector); - }, - - filter: function( selector ) { - return this.pushStack( winnow(this, selector, true), "filter", selector ); - }, - - is: function( selector ) { - return !!selector && ( - typeof selector === "string" ? - // If this is a positional selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - POS.test( selector ) ? - __kivy__jQuery( selector, this.context ).index( this[0] ) >= 0 : - __kivy__jQuery.filter( selector, this ).length > 0 : - this.filter( selector ).length > 0 ); - }, - - closest: function( selectors, context ) { - var ret = [], i, l, cur = this[0]; - - // Array (deprecated as of __kivy__jQuery 1.7) - if ( __kivy__jQuery.isArray( selectors ) ) { - var level = 1; - - while ( cur && cur.ownerDocument && cur !== context ) { - for ( i = 0; i < selectors.length; i++ ) { - - if ( __kivy__jQuery( cur ).is( selectors[ i ] ) ) { - ret.push({ selector: selectors[ i ], elem: cur, level: level }); - } - } - - cur = cur.parentNode; - level++; - } - - return ret; - } - - // String - var pos = POS.test( selectors ) || typeof selectors !== "string" ? - __kivy__jQuery( selectors, context || this.context ) : - 0; - - for ( i = 0, l = this.length; i < l; i++ ) { - cur = this[i]; - - while ( cur ) { - if ( pos ? pos.index(cur) > -1 : __kivy__jQuery.find.matchesSelector(cur, selectors) ) { - ret.push( cur ); - break; - - } else { - cur = cur.parentNode; - if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { - break; - } - } - } - } - - ret = ret.length > 1 ? __kivy__jQuery.unique( ret ) : ret; - - return this.pushStack( ret, "closest", selectors ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; - } - - // index in selector - if ( typeof elem === "string" ) { - return __kivy__jQuery.inArray( this[0], __kivy__jQuery( elem ) ); - } - - // Locate the position of the desired element - return __kivy__jQuery.inArray( - // If it receives a __kivy__jQuery object, the first element is used - elem.__kivy__jquery ? elem[0] : elem, this ); - }, - - add: function( selector, context ) { - var set = typeof selector === "string" ? - __kivy__jQuery( selector, context ) : - __kivy__jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), - all = __kivy__jQuery.merge( this.get(), set ); - - return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? - all : - __kivy__jQuery.unique( all ) ); - }, - - andSelf: function() { - return this.add( this.prevObject ); - } -}); - -// A painfully simple check to see if an element is disconnected -// from a document (should be improved, where feasible). -function isDisconnected( node ) { - return !node || !node.parentNode || node.parentNode.nodeType === 11; -} - -__kivy__jQuery.each({ - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return __kivy__jQuery.dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return __kivy__jQuery.dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return __kivy__jQuery.nth( elem, 2, "nextSibling" ); - }, - prev: function( elem ) { - return __kivy__jQuery.nth( elem, 2, "previousSibling" ); - }, - nextAll: function( elem ) { - return __kivy__jQuery.dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return __kivy__jQuery.dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return __kivy__jQuery.dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return __kivy__jQuery.dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return __kivy__jQuery.sibling( elem.parentNode.firstChild, elem ); - }, - children: function( elem ) { - return __kivy__jQuery.sibling( elem.firstChild ); - }, - contents: function( elem ) { - return __kivy__jQuery.nodeName( elem, "iframe" ) ? - elem.contentDocument || elem.contentWindow.document : - __kivy__jQuery.makeArray( elem.childNodes ); - } -}, function( name, fn ) { - __kivy__jQuery.fn[ name ] = function( until, selector ) { - var ret = __kivy__jQuery.map( this, fn, until ); - - if ( !runtil.test( name ) ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - ret = __kivy__jQuery.filter( selector, ret ); - } - - ret = this.length > 1 && !guaranteedUnique[ name ] ? __kivy__jQuery.unique( ret ) : ret; - - if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { - ret = ret.reverse(); - } - - return this.pushStack( ret, name, slice.call( arguments ).join(",") ); - }; -}); - -__kivy__jQuery.extend({ - filter: function( expr, elems, not ) { - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 ? - __kivy__jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : - __kivy__jQuery.find.matches(expr, elems); - }, - - dir: function( elem, dir, until ) { - var matched = [], - cur = elem[ dir ]; - - while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !__kivy__jQuery( cur ).is( until )) ) { - if ( cur.nodeType === 1 ) { - matched.push( cur ); - } - cur = cur[dir]; - } - return matched; - }, - - nth: function( cur, result, dir, elem ) { - result = result || 1; - var num = 0; - - for ( ; cur; cur = cur[dir] ) { - if ( cur.nodeType === 1 && ++num === result ) { - break; - } - } - - return cur; - }, - - sibling: function( n, elem ) { - var r = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - r.push( n ); - } - } - - return r; - } -}); - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, keep ) { - - // Can't pass null or undefined to indexOf in Firefox 4 - // Set to 0 to skip string check - qualifier = qualifier || 0; - - if ( __kivy__jQuery.isFunction( qualifier ) ) { - return __kivy__jQuery.grep(elements, function( elem, i ) { - var retVal = !!qualifier.call( elem, i, elem ); - return retVal === keep; - }); - - } else if ( qualifier.nodeType ) { - return __kivy__jQuery.grep(elements, function( elem, i ) { - return ( elem === qualifier ) === keep; - }); - - } else if ( typeof qualifier === "string" ) { - var filtered = __kivy__jQuery.grep(elements, function( elem ) { - return elem.nodeType === 1; - }); - - if ( isSimple.test( qualifier ) ) { - return __kivy__jQuery.filter(qualifier, filtered, !keep); - } else { - qualifier = __kivy__jQuery.filter( qualifier, filtered ); - } - } - - return __kivy__jQuery.grep(elements, function( elem, i ) { - return ( __kivy__jQuery.inArray( elem, qualifier ) >= 0 ) === keep; - }); -} - - - - -function createSafeFragment( document ) { - var list = nodeNames.split( "|" ), - safeFrag = document.createDocumentFragment(); - - if ( safeFrag.createElement ) { - while ( list.length ) { - safeFrag.createElement( - list.pop() - ); - } - } - return safeFrag; -} - -var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" + - "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", - rinline__kivy__jQuery = / __kivy__jQuery\d+="(?:\d+|null)"/g, - rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, - rtagName = /<([\w:]+)/, - rtbody = /", "" ], - legend: [ 1, "
      ", "
      " ], - thead: [ 1, "", "
      " ], - tr: [ 2, "", "
      " ], - td: [ 3, "", "
      " ], - col: [ 2, "", "
      " ], - area: [ 1, "", "" ], - _default: [ 0, "", "" ] - }, - safeFragment = createSafeFragment( document ); - -wrapMap.optgroup = wrapMap.option; -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// IE can't serialize and - - - - -Some <select> element from JIRA:
      -(click submit to test the post data sent)

      - - -
      - - - - - -
      - -

      With Fixed as "selected":

      - - - -

      Add new <select> element dynamically on a page:
      - (select boxes are checked every second on a page,
      - you should see a normal select element transforming
      - into js select box a moment after you click the button)

      - - - - - -
      - -

      - - - -

      Test interaction with other webpages that already use some other
      - javascript boxes library. -

      - -

      These links need to be opened in the kivy_.py example:

      - - - -

      Some libraries that are not well-designed will display
      - the select element twice, take a look at this for example:

      - - - http://adam.co/lab/jquery/customselect/ (open in kivy_.py example) - -

      -Although, it will still be functional, just with a display glitch. -

      - -

      The following code was added to the - SelectBox library to transform <select> element into - js box only if it's visible on a webpage:

      - -
      -    // This should fix interaction with other js boxes libraries,
      -    // so that the select element does not appear twice.
      -    if (!$(select).is(":visible")) {
      -        return;
      -    }
      -
      - -Also this code gives one second to other select box libraries
      -to do their stuff, before we start ours: - -
      -    __kivy__jQuery(document).ready(function() {
      -    // Transform select elements only after a second,
      -    // this will give time other select boxes libraries
      -    // included on a webpage to their stuff first.
      -    window.setInterval(function(){
      -        __kivy__jQuery(document).ready(function() { 
      -            __kivy__jQuery("select").__kivy__selectBox(); 
      -        });
      -    }, 1000);
      -});
      -
      - - - - \ No newline at end of file diff --git a/src/linux/binaries_32bit/kivy-select-boxes/readme.md b/src/linux/binaries_32bit/kivy-select-boxes/readme.md deleted file mode 100644 index ad45aa7f8..000000000 --- a/src/linux/binaries_32bit/kivy-select-boxes/readme.md +++ /dev/null @@ -1,156 +0,0 @@ -# jQuery selectBox: A styleable replacement for SELECT elements - -_Licensed under the MIT license: http://opensource.org/licenses/MIT_ - -## Features - -* Supports OPTGROUPS -* Supports standard dropdown controls -* Supports multi-select controls (i.e. multiple="multiple") -* Supports inline controls (i.e. size="5") -* Fully accessible via keyboard -* Shift + click (or shift + enter) to select a range of options in multi-select controls -* Type to search when the control has focus -* Auto-height based on the size attribute (to use, omit the height property in your CSS!) -* Tested in IE7-IE9, Firefox 3-4, recent WebKit browsers, and Opera - - -## Usage - -Link to the JS file: - -```html - -``` - -Add the CSS file (or append contents to your own stylesheet): - -```html - -``` - -To initialize: - -```javascript -// default -$('select').selectBox(); - -// or with custom settings -$('select').selectBox({ - mobile: true, - menuSpeed: 'fast' -}); -``` - -## Settings - -| Key | Default | Values | Description | -| ---------------|:-------------:|---------------------------:|-------------------------------------------------:| -| mobile | `false` | Boolean | Disables the widget for mobile devices | -| menuTransition | `default` | `default`, `slide`, `fade` | The show/hide transition for dropdown menus | -| menuSpeed | `normal` | `slow`, `normal`, `fast` | The show/hide transition speed | -| loopOptions | `false` | Boolean | Flag to allow arrow keys to loop through options | - - -To specify settings after the init, use this syntax: - -```javascript -$('select').selectBox('settings', {settingName: value, ... }); -``` - -## Methods - -To call a method use this syntax: - -```javascript -$('select').selectBox('methodName', [option]); -``` - -### Available methods - - -| Key | Description | -| ---------------|-----------------------------------------------------------------------------------------------| -| create | Creates the control (default) | -| destroy | Destroys the selectBox control and reverts back to the original form control | -| disable | Disables the control (i.e. disabled="disabled") | -| enable | Enables the control | -| value | If passed with a value, sets the control to that value; otherwise returns the current value | -| options | If passed either a string of HTML or a JSON object, replaces the existing options; otherwise Returns the options container element as a jQuery object | -| control | Returns the selectBox control element (an anchor tag) for working with directly | -| refresh | Updates the selectBox control's options based on the original controls options | -| instance | Returns the SelectBox instance, where you have more methods available (only in v1.2.0-dev | - | available) as in the `SelectBox` class below. | - -## API `SelectBox` - -You can instantiate the selectBox also through a classic OOP way: - -```javascript -var selectBox = new SelectBox($('#mySelectBox'), settings = {}); -selectBox.showMenu(); -``` - -The public methods are: - -```javascript -refresh() -destroy() -disable() -enable() - -getLabelClass() -getLabelText() -getSelectElement() -getOptions(String type = 'inline'|'dropdown') - -hideMenus() -showMenu() - -setLabel() -setOptions(Object options) -setValue(String value) - -removeHover(HTMLElement li) -addHover(HTMLElement li) - -disableSelection(HTMLElement selector) -generateOptions(jQuery self, jQuery options) -handleKeyDown(event) -handleKeyPress(event) -init(options) -keepOptionInView(jQuery li, Boolean center) -refresh() -removeHover(HTMLElement li) -selectOption(HTMLElement li, event) -``` - -## Events - -Events are fired on the original select element. You can bind events like this: - -```javascript -$('select').selectBox().change(function () { - alert($(this).val()); -}); -``` - -### Available events - -| Key | Description | -| ---------------|-----------------------------------------------------------------------------------------------| -| focus | Fired when the control gains focus | -| blur | Fired when the control loses focus | -| change | Fired when the value of a control changes | -| beforeopen | Fired before a dropdown menu opens (cancelable) | -| open | Fired after a dropdown menu opens (not cancelable) | -| beforeclose | Fired before a dropdown menu closes (cancelable) | -| close | Fired after a dropdown menu closes (not cancelable) | - -### Known Issues - -* The blur and focus callbacks are not very reliable in IE7. The change callback works fine. - -## Credits - -Original plugin by Cory LaViska of A Beautiful Site, LLC. (http://www.abeautifulsite.net/) \ No newline at end of file diff --git a/src/linux/binaries_32bit/kivy_.py b/src/linux/binaries_32bit/kivy_.py deleted file mode 100644 index 258e09699..000000000 --- a/src/linux/binaries_32bit/kivy_.py +++ /dev/null @@ -1,677 +0,0 @@ -# An example of embedding CEF browser in the Kivy framework. -# The browser is embedded using off-screen rendering mode. - -# Tested using Kivy 1.7.2 stable on Ubuntu 12.04 64-bit. - -# In this example kivy-lang is used to declare the layout which -# contains two buttons (back, forward) and the browser view. - -# The official CEF Python binaries come with tcmalloc hook -# disabled. But if you've built custom binaries and kept tcmalloc -# hook enabled, then be aware that in such case it is required -# for the cefpython module to be the very first import in -# python scripts. See Issue 73 in the CEF Python Issue Tracker -# for more details. - -import ctypes, os, sys -libcef_so = os.path.join(os.path.dirname( - os.path.abspath(__file__)), 'libcef.so') -if os.path.exists(libcef_so): - # Import local module - ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import from package - from cefpython3 import cefpython - -from kivy.app import App -from kivy.uix.widget import Widget -from kivy.graphics import Color, Rectangle, GraphicException -from kivy.clock import Clock -from kivy.graphics.texture import Texture -from kivy.core.window import Window -from kivy.lang import Builder -from kivy.uix.boxlayout import BoxLayout -from kivy.base import EventLoop - -####Kivy APP #### -Builder.load_string(""" - -: - orientation: 'vertical' - BoxLayout: - size_hint_y: None - width: 80 - Button: - text: "Back" - on_press: browser.go_back() - Button: - text: "Forward" - on_press: browser.go_forward() - CefBrowser: - id: browser - -""") - - - -class BrowserLayout(BoxLayout): - - def __init__(self, **kwargs): - super(BrowserLayout, self).__init__(**kwargs) - - - -class CefBrowser(Widget): - - # Keyboard mode: "global" or "local". - # 1. Global mode forwards keys to CEF all the time. - # 2. Local mode forwards keys to CEF only when an editable - # control is focused (input type=text|password or textarea). - keyboard_mode = "global" - - '''Represent a browser widget for kivy, which can be used like a normal widget. - ''' - def __init__(self, start_url='http://www.google.com/', **kwargs): - super(CefBrowser, self).__init__(**kwargs) - - self.start_url = start_url - - #Workaround for flexible size: - #start browser when the height has changed (done by layout) - #This has to be done like this because I wasn't able to change - #the texture size - #until runtime without core-dump. - self.bind(size = self.size_changed) - - - starting = True - def size_changed(self, *kwargs): - '''When the height of the cefbrowser widget got changed, create the browser - ''' - if self.starting: - if self.height != 100: - self.start_cef() - self.starting = False - else: - self.texture = Texture.create( - size=self.size, colorfmt='rgba', bufferfmt='ubyte') - self.texture.flip_vertical() - with self.canvas: - Color(1, 1, 1) - # This will cause segmentation fault: - # | self.rect = Rectangle(size=self.size, texture=self.texture) - # Update only the size: - self.rect.size = self.size - self.browser.WasResized() - - - def _cef_mes(self, *kwargs): - '''Get called every frame. - ''' - cefpython.MessageLoopWork() - - - def _update_rect(self, *kwargs): - '''Get called whenever the texture got updated. - => we need to reset the texture for the rectangle - ''' - self.rect.texture = self.texture - - - def start_cef(self): - '''Starts CEF. - ''' - # create texture & add it to canvas - self.texture = Texture.create( - size=self.size, colorfmt='rgba', bufferfmt='ubyte') - self.texture.flip_vertical() - with self.canvas: - Color(1, 1, 1) - self.rect = Rectangle(size=self.size, texture=self.texture) - - #configure cef - settings = { - "debug": True, # cefpython debug messages in console and in log_file - "log_severity": cefpython.LOGSEVERITY_INFO, - "log_file": "debug.log", - # This directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory(), - "browser_subprocess_path": "%s/%s" % (cefpython.GetModuleDirectory(), "subprocess")} - - #start idle - Clock.schedule_interval(self._cef_mes, 0) - - #init CEF - cefpython.Initialize(settings) - - #WindowInfo offscreen flag - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsOffscreen(0) - - #Create Broswer and naviagte to empty page <= OnPaint won't get called yet - browserSettings = {} - # The render handler callbacks are not yet set, thus an - # error report will be thrown in the console (when release - # DCHECKS are enabled), however don't worry, it is harmless. - # This is happening because calling GetViewRect will return - # false. That's why it is initially navigating to "about:blank". - # Later, a real url will be loaded using the LoadUrl() method - # and the GetViewRect will be called again. This time the render - # handler callbacks will be available, it will work fine from - # this point. - # -- - # Do not use "about:blank" as navigateUrl - this will cause - # the GoBack() and GoForward() methods to not work. - self.browser = cefpython.CreateBrowserSync(windowInfo, browserSettings, - navigateUrl=self.start_url) - - #set focus - self.browser.SendFocusEvent(True) - - self._client_handler = ClientHandler(self) - self.browser.SetClientHandler(self._client_handler) - self.set_js_bindings() - - #Call WasResized() => force cef to call GetViewRect() and OnPaint afterwards - self.browser.WasResized() - - # The browserWidget instance is required in OnLoadingStateChange(). - self.browser.SetUserData("browserWidget", self) - - if self.keyboard_mode == "global": - self.request_keyboard() - - # Clock.schedule_once(self.change_url, 5) - - - _client_handler = None - _js_bindings = None - - def set_js_bindings(self): - if not self._js_bindings: - self._js_bindings = cefpython.JavascriptBindings( - bindToFrames=True, bindToPopups=True) - self._js_bindings.SetFunction("__kivy__request_keyboard", - self.request_keyboard) - self._js_bindings.SetFunction("__kivy__release_keyboard", - self.release_keyboard) - self.browser.SetJavascriptBindings(self._js_bindings) - - - def change_url(self, *kwargs): - # Doing a javascript redirect instead of Navigate() - # solves the js bindings error. The url here need to - # be preceded with "http://". Calling StopLoad() - # might be a good idea before making the js navigation. - - self.browser.StopLoad() - self.browser.GetMainFrame().ExecuteJavascript( - "window.location='http://www.youtube.com/'") - - # Do not use Navigate() or GetMainFrame()->LoadURL(), - # as it causes the js bindings to be removed. There is - # a bug in CEF, that happens after a call to Navigate(). - # The OnBrowserDestroyed() callback is fired and causes - # the js bindings to be removed. See this topic for more - # details: - # http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=11009 - - # OFF: - # | self.browser.Navigate("http://www.youtube.com/") - - _keyboard = None - - def request_keyboard(self): - print("request_keyboard()") - self._keyboard = EventLoop.window.request_keyboard( - self.release_keyboard, self) - self._keyboard.bind(on_key_down=self.on_key_down) - self._keyboard.bind(on_key_up=self.on_key_up) - self.is_shift1 = False - self.is_shift2 = False - self.is_ctrl1 = False - self.is_ctrl2 = False - self.is_alt1 = False - self.is_alt2 = False - # Not sure if it is still required to send the focus - # (some earlier bug), but it shouldn't hurt to call it. - self.browser.SendFocusEvent(True) - - - def release_keyboard(self): - # When using local keyboard mode, do all the request - # and releases of the keyboard through js bindings, - # otherwise some focus problems arise. - self.is_shift1 = False - self.is_shift2 = False - self.is_ctrl1 = False - self.is_ctrl2 = False - self.is_alt1 = False - self.is_alt2 = False - if not self._keyboard: - return - print("release_keyboard()") - self._keyboard.unbind(on_key_down=self.on_key_down) - self._keyboard.unbind(on_key_up=self.on_key_up) - self._keyboard.release() - - # Kivy does not provide modifiers in on_key_up, but these - # must be sent to CEF as well. - is_shift1 = False - is_shift2 = False - is_ctrl1 = False - is_ctrl2 = False - is_alt1 = False - is_alt2 = False - - def on_key_down(self, keyboard, keycode, text, modifiers): - # Notes: - # - right alt modifier is not sent by Kivy through modifiers param. - # print("on_key_down(): keycode = %s, text = %s, modifiers = %s" % ( - # keycode, text, modifiers)) - if keycode[0] == 27: - # On escape release the keyboard, see the injected - # javascript in OnLoadStart(). - self.browser.GetFocusedFrame().ExecuteJavascript( - "__kivy__on_escape()") - return - cefModifiers = cefpython.EVENTFLAG_NONE - if "shift" in modifiers: - cefModifiers |= cefpython.EVENTFLAG_SHIFT_DOWN - if "ctrl" in modifiers: - cefModifiers |= cefpython.EVENTFLAG_CONTROL_DOWN - if "alt" in modifiers: - cefModifiers |= cefpython.EVENTFLAG_ALT_DOWN - if "capslock" in modifiers: - cefModifiers |= cefpython.EVENTFLAG_CAPS_LOCK_ON - # print("on_key_down(): cefModifiers = %s" % cefModifiers) - cef_keycode = self.translate_to_cef_keycode(keycode[0]) - keyEvent = { - "type": cefpython.KEYEVENT_RAWKEYDOWN, - "native_key_code": cef_keycode, - "modifiers": cefModifiers - } - # print("keydown keyEvent: %s" % keyEvent) - self.browser.SendKeyEvent(keyEvent) - if keycode[0] == 304: - self.is_shift1 = True - elif keycode[0] == 303: - self.is_shift2 = True - elif keycode[0] == 306: - self.is_ctrl1 = True - elif keycode[0] == 305: - self.is_ctrl2 = True - elif keycode[0] == 308: - self.is_alt1 = True - elif keycode[0] == 313: - self.is_alt2 = True - - - def on_key_up(self, keyboard, keycode): - # print("on_key_up(): keycode = %s" % (keycode,)) - cefModifiers = cefpython.EVENTFLAG_NONE - if self.is_shift1 or self.is_shift2: - cefModifiers |= cefpython.EVENTFLAG_SHIFT_DOWN - if self.is_ctrl1 or self.is_ctrl2: - cefModifiers |= cefpython.EVENTFLAG_CONTROL_DOWN - if self.is_alt1: - cefModifiers |= cefpython.EVENTFLAG_ALT_DOWN - # Capslock todo. - cef_keycode = self.translate_to_cef_keycode(keycode[0]) - keyEvent = { - "type": cefpython.KEYEVENT_KEYUP, - "native_key_code": cef_keycode, - "modifiers": cefModifiers - } - # print("keyup keyEvent: %s" % keyEvent) - self.browser.SendKeyEvent(keyEvent) - keyEvent = { - "type": cefpython.KEYEVENT_CHAR, - "native_key_code": cef_keycode, - "modifiers": cefModifiers - } - # print("char keyEvent: %s" % keyEvent) - self.browser.SendKeyEvent(keyEvent) - if keycode[0] == 304: - self.is_shift1 = False - elif keycode[0] == 303: - self.is_shift2 = False - elif keycode[0] == 306: - self.is_ctrl1 = False - elif keycode[0] == 305: - self.is_ctrl2 = False - elif keycode[0] == 308: - self.is_alt1 = False - elif keycode[0] == 313: - self.is_alt2 = False - - - def translate_to_cef_keycode(self, keycode): - # TODO: this works on Linux, but on Windows the key - # mappings will probably be different. - # TODO: what if the Kivy keyboard layout is changed - # from qwerty to azerty? (F1 > options..) - cef_keycode = keycode - if self.is_alt2: - # The key mappings here for right alt were tested - # with the utf-8 charset on a webpage. If the charset - # is different there is a chance they won't work correctly. - alt2_map = { - # tilde - "96":172, - # 0-9 (48..57) - "48":125, "49":185, "50":178, "51":179, "52":188, - "53":189, "54":190, "55":123, "56":91, "57":93, - # minus - "45":92, - # a-z (97..122) - "97":433, "98":2771, "99":486, "100":240, "101":490, - "102":496, "103":959, "104":689, "105":2301, "106":65121, - "107":930, "108":435, "109":181, "110":497, "111":243, - "112":254, "113":64, "114":182, "115":438, "116":956, - "117":2302, "118":2770, "119":435, "120":444, "121":2299, - "122":447, - } - if str(keycode) in alt2_map: - cef_keycode = alt2_map[str(keycode)] - else: - print("Kivy to CEF key mapping not found (right alt), " \ - "key code = %s" % keycode) - shift_alt2_map = { - # tilde - "96":172, - # 0-9 (48..57) - "48":176, "49":161, "50":2755, "51":163, "52":36, - "53":2756, "54":2757, "55":2758, "56":2761, "57":177, - # minus - "45":191, - # A-Z (97..122) - "97":417, "98":2769, "99":454, "100":208, "101":458, - "102":170, "103":957, "104":673, "105":697, "106":65122, - "107":38, "108":419, "109":186, "110":465, "111":211, - "112":222, "113":2009, "114":174, "115":422, "116":940, - "117":2300, "118":2768, "119":419, "120":428, "121":165, - "122":431, - # special: <>? :" {} - "44":215, "46":247, "47":65110, - "59":65113, "39":65114, - "91":65112, "93":65108, - } - if self.is_shift1 or self.is_shift2: - if str(keycode) in shift_alt2_map: - cef_keycode = shift_alt2_map[str(keycode)] - else: - print("Kivy to CEF key mapping not found " \ - "(shift + right alt), key code = %s" % keycode) - elif self.is_shift1 or self.is_shift2: - shift_map = { - # tilde - "96":126, - # 0-9 (48..57) - "48":41, "49":33, "50":64, "51":35, "52":36, "53":37, - "54":94, "55":38, "56":42, "57":40, - # minus, plus - "45":95, "61":43, - # a-z (97..122) - "97":65, "98":66, "99":67, "100":68, "101":69, "102":70, - "103":71, "104":72, "105":73, "106":74, "107":75, "108":76, - "109":77, "110":78, "111":79, "112":80, "113":81, "114":82, - "115":83, "116":84, "117":85, "118":86, "119":87, "120":88, - "121":89, "122":90, - # special: <>? :" {} - "44":60, "46":62, "47":63, - "59":58, "39":34, - "91":123, "93":125, - } - if str(keycode) in shift_map: - cef_keycode = shift_map[str(keycode)] - # Other keys: - other_keys_map = { - # Escape - "27":65307, - # F1-F12 - "282":65470, "283":65471, "284":65472, "285":65473, - "286":65474, "287":65475, "288":65476, "289":65477, - "290":65478, "291":65479, "292":65480, "293":65481, - # Tab - "9":65289, - # Left Shift, Right Shift - "304":65505, "303":65506, - # Left Ctrl, Right Ctrl - "306":65507, "305": 65508, - # Left Alt, Right Alt - "308":65513, "313":65027, - # Backspace - "8":65288, - # Enter - "13":65293, - # PrScr, ScrLck, Pause - "316":65377, "302":65300, "19":65299, - # Insert, Delete, - # Home, End, - # Pgup, Pgdn - "277":65379, "127":65535, - "278":65360, "279":65367, - "280":65365, "281":65366, - # Arrows (left, up, right, down) - "276":65361, "273":65362, "275":65363, "274":65364, - } - if str(keycode) in other_keys_map: - cef_keycode = other_keys_map[str(keycode)] - return cef_keycode - - - def go_forward(self): - '''Going to forward in browser history - ''' - print "go forward" - self.browser.GoForward() - - - def go_back(self): - '''Going back in browser history - ''' - print "go back" - self.browser.GoBack() - - - def on_touch_down(self, touch, *kwargs): - if not self.collide_point(*touch.pos): - return - touch.grab(self) - - y = self.height-touch.pos[1] - self.browser.SendMouseClickEvent(touch.x, y, cefpython.MOUSEBUTTON_LEFT, - mouseUp=False, clickCount=1) - - - def on_touch_move(self, touch, *kwargs): - if touch.grab_current is not self: - return - - y = self.height-touch.pos[1] - self.browser.SendMouseMoveEvent(touch.x, y, mouseLeave=False) - - - def on_touch_up(self, touch, *kwargs): - if touch.grab_current is not self: - return - - y = self.height-touch.pos[1] - self.browser.SendMouseClickEvent(touch.x, y, cefpython.MOUSEBUTTON_LEFT, - mouseUp=True, clickCount=1) - touch.ungrab(self) - - -class ClientHandler: - - def __init__(self, browserWidget): - self.browserWidget = browserWidget - - - def _fix_select_boxes(self, frame): - # This is just a temporary fix, until proper Popup widgets - # painting is implemented (PET_POPUP in OnPaint). Currently - # there is no way to obtain a native window handle (GtkWindow - # pointer) in Kivy, and this may cause things like context menus, - # select boxes and plugins not to display correctly. Although, - # this needs to be tested. The popup widget buffers are - # available in a separate paint buffer, so they could positioned - # freely so that it doesn't go out of the window. So the native - # window handle might not necessarily be required to make it work - # in most cases (99.9%). Though, this still needs testing to confirm. - # -- - # See this topic on the CEF Forum regarding the NULL window handle: - # http://www.magpcss.org/ceforum/viewtopic.php?f=6&t=10851 - # -- - # See also a related topic on the Kivy-users group: - # https://groups.google.com/d/topic/kivy-users/WdEQyHI5vTs/discussion - # -- - # The javascript select boxes library used: - # http://marcj.github.io/jquery-selectBox/ - # -- - # Cannot use "file://" urls to load local resources, error: - # | Not allowed to load local resource - print("_fix_select_boxes()") - resources_dir = os.path.join( - os.path.dirname(os.path.abspath(__file__)), - "kivy-select-boxes") - if not os.path.exists(resources_dir): - print("The kivy-select-boxes directory does not exist, " \ - "select boxes fix won't be applied.") - return - js_file = os.path.join(resources_dir, "kivy-selectBox.js") - js_content = "" - with open(js_file, "r") as myfile: - js_content = myfile.read() - css_file = os.path.join(resources_dir, "kivy-selectBox.css") - css_content = "" - with open(css_file, "r") as myfile: - css_content = myfile.read() - css_content = css_content.replace("\r", "") - css_content = css_content.replace("\n", "") - jsCode = """ - %(js_content)s - var __kivy_temp_head = document.getElementsByTagName('head')[0]; - var __kivy_temp_style = document.createElement('style'); - __kivy_temp_style.type = 'text/css'; - __kivy_temp_style.appendChild(document.createTextNode("%(css_content)s")); - __kivy_temp_head.appendChild(__kivy_temp_style); - """ % locals() - frame.ExecuteJavascript(jsCode, - "kivy_.py > ClientHandler > OnLoadStart > _fix_select_boxes()") - - - def OnLoadStart(self, browser, frame): - self._fix_select_boxes(frame); - browserWidget = browser.GetUserData("browserWidget") - if browserWidget and browserWidget.keyboard_mode == "local": - print("OnLoadStart(): injecting focus listeners for text controls") - # The logic is similar to the one found in kivy-berkelium: - # https://github.com/kivy/kivy-berkelium/blob/master/berkelium/__init__.py - jsCode = """ - var __kivy__keyboard_requested = false; - function __kivy__keyboard_interval() { - var element = document.activeElement; - if (!element) { - return; - } - var tag = element.tagName; - var type = element.type; - if (tag == "INPUT" && (type == "" || type == "text" - || type == "password") || tag == "TEXTAREA") { - if (!__kivy__keyboard_requested) { - __kivy__request_keyboard(); - __kivy__keyboard_requested = true; - } - return; - } - if (__kivy__keyboard_requested) { - __kivy__release_keyboard(); - __kivy__keyboard_requested = false; - } - } - function __kivy__on_escape() { - if (document.activeElement) { - document.activeElement.blur(); - } - if (__kivy__keyboard_requested) { - __kivy__release_keyboard(); - __kivy__keyboard_requested = false; - } - } - setInterval(__kivy__keyboard_interval, 100); - """ - frame.ExecuteJavascript(jsCode, - "kivy_.py > ClientHandler > OnLoadStart") - - - def OnLoadEnd(self, browser, frame, httpStatusCode): - # Browser lost its focus after the LoadURL() and the - # OnBrowserDestroyed() callback bug. When keyboard mode - # is local the fix is in the request_keyboard() method. - # Call it from OnLoadEnd only when keyboard mode is global. - browserWidget = browser.GetUserData("browserWidget") - if browserWidget and browserWidget.keyboard_mode == "global": - browser.SendFocusEvent(True) - - - def OnLoadingStateChange(self, browser, isLoading, canGoBack, - canGoForward): - print("OnLoadingStateChange(): isLoading = %s" % isLoading) - browserWidget = browser.GetUserData("browserWidget") - - - def OnPaint(self, browser, paintElementType, dirtyRects, buffer, width, - height): - # print "OnPaint()" - if paintElementType != cefpython.PET_VIEW: - print "Popups aren't implemented yet" - return - - #update buffer - buffer = buffer.GetString(mode="bgra", origin="top-left") - - #update texture of canvas rectangle - self.browserWidget.texture.blit_buffer(buffer, colorfmt='bgra', - bufferfmt='ubyte') - self.browserWidget._update_rect() - - return True - - - def GetViewRect(self, browser, rect): - width, height = self.browserWidget.texture.size - rect.append(0) - rect.append(0) - rect.append(width) - rect.append(height) - # print("GetViewRect(): %s x %s" % (width, height)) - return True - - - def OnJavascriptDialog(self, browser, originUrl, dialogType, - messageText, defaultPromptText, callback, - suppressMessage): - suppressMessage[0] = True - return False - - - def OnBeforeUnloadJavascriptDialog(self, browser, messageText, isReload, - callback): - callback.Continue(allow=True, userInput="") - return True - - -if __name__ == '__main__': - class CefBrowserApp(App): - def build(self): - return BrowserLayout() - CefBrowserApp().run() - - cefpython.Shutdown() diff --git a/src/linux/binaries_32bit/pygtk_.py b/src/linux/binaries_32bit/pygtk_.py deleted file mode 100644 index 3cb7b58fc..000000000 --- a/src/linux/binaries_32bit/pygtk_.py +++ /dev/null @@ -1,199 +0,0 @@ -# An example of embedding the CEF browser in PyGTK on Linux. -# Tested with GTK "2.24.10". - -# The official CEF Python binaries come with tcmalloc hook -# disabled. But if you've built custom binaries and kept tcmalloc -# hook enabled, then be aware that in such case it is required -# for the cefpython module to be the very first import in -# python scripts. See Issue 73 in the CEF Python Issue Tracker -# for more details. - -import ctypes, os, sys -libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)),\ - 'libcef.so') -if os.path.exists(libcef_so): - # Import local module - ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import from package - from cefpython3 import cefpython - -import pygtk -pygtk.require('2.0') -import gtk -import gobject -import re - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("[pygtk_.py]: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class PyGTKExample: - mainWindow = None - container = None - browser = None - exiting = None - searchEntry = None - vbox = None - - def __init__(self): - self.mainWindow = gtk.Window(gtk.WINDOW_TOPLEVEL) - self.mainWindow.connect('destroy', self.OnExit) - self.mainWindow.set_size_request(width=800, height=600) - self.mainWindow.set_title('PyGTK CEF example') - self.mainWindow.realize() - - self.vbox = gtk.VBox(False, 0) - self.vbox.pack_start(self.CreateMenu(), False, False, 0) - self.mainWindow.add(self.vbox) - - m = re.search("GtkVBox at 0x(\w+)", str(self.vbox)) - hexID = m.group(1) - windowID = int(hexID, 16) - - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(windowID) - # Linux requires adding "file://" for local files, - # otherwise /home/some will be replaced as http://home/some - self.browser = cefpython.CreateBrowserSync( - windowInfo, - browserSettings={}, - navigateUrl="file://"+GetApplicationPath("example.html")) - - self.vbox.show() - self.mainWindow.show() - gobject.timeout_add(10, self.OnTimer) - - def CreateMenu(self): - file = gtk.MenuItem('File') - file.show() - filemenu = gtk.Menu() - item = gtk.MenuItem('Open') - filemenu.append(item) - item.show() - item = gtk.MenuItem('Exit') - filemenu.append(item) - item.show() - file.set_submenu(filemenu) - - about = gtk.MenuItem('About') - about.show() - aboutmenu = gtk.Menu() - item = gtk.MenuItem('CEF Python') - aboutmenu.append(item) - item.show() - about.set_submenu(aboutmenu) - - menubar = gtk.MenuBar() - menubar.append(file) - menubar.append(about) - menubar.show() - - return menubar - - def OnWidgetClick(self, widget, data): - self.mainWindow.get_window().focus() - - def OnTimer(self): - if self.exiting: - return False - cefpython.MessageLoopWork() - return True - - def OnFocusIn(self, widget, data): - # This function is currently not called by any of code, - # but if you would like for browser to have automatic focus - # add such line: - # self.mainWindow.connect('focus-in-event', self.OnFocusIn) - self.browser.SetFocus(True) - - def OnExit(self, widget, data=None): - self.exiting = True - gtk.main_quit() - -if __name__ == '__main__': - version = '.'.join(map(str, list(gtk.gtk_version))) - print('[pygtk_.py] GTK version: %s' % version) - - # Intercept python exceptions. Exit app immediately when exception - # happens on any of the threads. - sys.excepthook = ExceptHook - - # Application settings - settings = { - "debug": True, # cefpython debug messages in console and in log_file - "log_severity": cefpython.LOGSEVERITY_INFO, # LOGSEVERITY_VERBOSE - "log_file": GetApplicationPath("debug.log"), # Set to "" to disable - # This directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory(), - "browser_subprocess_path": "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess"), - } - - cefpython.Initialize(settings) - - gobject.threads_init() # Timer for the message loop - PyGTKExample() - gtk.main() - - cefpython.Shutdown() diff --git a/src/linux/binaries_32bit/pyqt.py b/src/linux/binaries_32bit/pyqt.py deleted file mode 100644 index 1326946ce..000000000 --- a/src/linux/binaries_32bit/pyqt.py +++ /dev/null @@ -1,238 +0,0 @@ -# An example of embedding the CEF browser in a PyQt4 application. -# Tested with PyQt "4.9.1". -# Command for installing PyQt4: "sudo apt-get install python-qt4". - -# The official CEF Python binaries come with tcmalloc hook -# disabled. But if you've built custom binaries and kept tcmalloc -# hook enabled, then be aware that in such case it is required -# for the cefpython module to be the very first import in -# python scripts. See Issue 73 in the CEF Python Issue Tracker -# for more details. - -import ctypes, os, sys -libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)),\ - 'libcef.so') -if os.path.exists(libcef_so): - # Import local module - ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import from package - from cefpython3 import cefpython - -from PyQt4 import QtGui -from PyQt4 import QtCore - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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" (os._exit()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("[pyqt.py] WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainWindow(QtGui.QMainWindow): - mainFrame = None - - def __init__(self): - super(MainWindow, self).__init__(None) - self.createMenu() - self.mainFrame = MainFrame(self) - self.setCentralWidget(self.mainFrame) - self.resize(1024, 768) - self.setWindowTitle('PyQT CEF 3 example') - self.setFocusPolicy(QtCore.Qt.StrongFocus) - - def createMenu(self): - menubar = self.menuBar() - filemenu = menubar.addMenu("&File") - filemenu.addAction(QtGui.QAction("Open", self)) - filemenu.addAction(QtGui.QAction("Exit", self)) - aboutmenu = menubar.addMenu("&About") - - def focusInEvent(self, event): - # cefpython.WindowUtils.OnSetFocus( - # int(self.centralWidget().winId()), 0, 0, 0) - pass - - def closeEvent(self, event): - self.mainFrame.browser.CloseBrowser() - -class MainFrame(QtGui.QX11EmbedContainer): - browser = None - plug = None - - def __init__(self, parent=None): - super(MainFrame, self).__init__(parent) - - # QX11EmbedContainer provides an X11 window. The CEF - # browser can be embedded only by providing a GtkWidget - # pointer. So we're embedding a GtkPlug inside the X11 - # window. In latest CEF trunk it is possible to embed - # the CEF browser by providing X11 window id. So it will - # be possible to remove the GTK dependency from CEF - # Python in the future. - gtkPlugPtr = cefpython.WindowUtils.gtk_plug_new(\ - int(self.winId())) - print("[pyqt.py] MainFrame: GDK Native Window id: "+str(self.winId())) - print("[pyqt.py] MainFrame: GTK Plug ptr: "+str(gtkPlugPtr)) - - """ - Embedding GtkPlug is also possible with the pygtk module. - --------------------------------------------------------- - self.plug = gtk.Plug(self.winId()) - import re - m = re.search("GtkPlug at 0x(\w+)", str(self.plug)) - hexId = m.group(1) - gtkPlugPtr = int(hexId, 16) - ... - plug.show() - self.show() - --------------------------------------------------------- - """ - - windowInfo = cefpython.WindowInfo() - # Need to pass to CEF the GtkWidget* pointer - windowInfo.SetAsChild(gtkPlugPtr) - # Linux requires adding "file://" for local files, - # otherwise /home/some will be replaced as http://home/some - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings={}, - navigateUrl="file://"+GetApplicationPath("example.html")) - - cefpython.WindowUtils.gtk_widget_show(gtkPlugPtr) - self.show() - - def moveEvent(self, event): - # cefpython.WindowUtils.OnSize(int(self.winId()), 0, 0, 0) - pass - - def resizeEvent(self, event): - # cefpython.WindowUtils.OnSize(int(self.winId()), 0, 0, 0) - pass - -class CefApplication(QtGui.QApplication): - timer = None - - def __init__(self, args): - super(CefApplication, self).__init__(args) - self.createTimer() - - def createTimer(self): - self.timer = QtCore.QTimer() - self.timer.timeout.connect(self.onTimer) - self.timer.start(10) - - def onTimer(self): - # The proper way of doing message loop should be: - # 1. In createTimer() call self.timer.start(0) - # 2. In onTimer() call MessageLoopWork() only when - # QtGui.QApplication.instance()->hasPendingEvents() - # returns False. - # But there is a bug in Qt, hasPendingEvents() returns - # always true. - # (The behavior described above was tested on Windows - # with pyqt 4.8, maybe this is not true anymore, - # test it TODO) - cefpython.MessageLoopWork() - - def stopTimer(self): - # Stop the timer after Qt message loop ended, calls to - # MessageLoopWork() should not happen anymore. - self.timer.stop() - -if __name__ == '__main__': - print("[pyqt.py] PyQt version: %s" % QtCore.PYQT_VERSION_STR) - print("[pyqt.py] QtCore version: %s" % QtCore.qVersion()) - - # Intercept python exceptions. Exit app immediately when exception - # happens on any of the threads. - sys.excepthook = ExceptHook - - # Application settings - settings = { - "debug": True, # cefpython debug messages in console and in log_file - "log_severity": cefpython.LOGSEVERITY_INFO, # LOGSEVERITY_VERBOSE - "log_file": GetApplicationPath("debug.log"), # Set to "" to disable. - # This directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory(), - "browser_subprocess_path": "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess"), - } - - # Command line switches set programmatically - switches = { - # "proxy-server": "socks5://127.0.0.1:8888", - # "enable-media-stream": "", - # "--invalid-switch": "" -> Invalid switch name - } - - cefpython.Initialize(settings, switches) - - app = CefApplication(sys.argv) - mainWindow = MainWindow() - mainWindow.show() - app.exec_() - app.stopTimer() - - # Need to destroy QApplication(), otherwise Shutdown() fails. - # Unset main window also just to be safe. - del mainWindow - del app - - cefpython.Shutdown() diff --git a/src/linux/binaries_32bit/wxpython-response.py b/src/linux/binaries_32bit/wxpython-response.py deleted file mode 100644 index 8992e14a2..000000000 --- a/src/linux/binaries_32bit/wxpython-response.py +++ /dev/null @@ -1,452 +0,0 @@ -# An example of embedding CEF browser in wxPython on Linux. -# Tested with wxPython 2.8.12.1 (gtk2-unicode). -# To install wxPython type "sudo apt-get install python-wxtools". - -# This example implements a custom "_OnResourceResponse" callback -# that emulates reading response by utilizing Resourcehandler -# and WebRequest. - -FIX_ENCODING_BUG = True -BROWSER_DEFAULT_ENCODING = "utf-8" - -# The official CEF Python binaries come with tcmalloc hook -# disabled. But if you've built custom binaries and kept tcmalloc -# hook enabled, then be aware that in such case it is required -# for the cefpython module to be the very first import in -# python scripts. See Issue 73 in the CEF Python Issue Tracker -# for more details. - -import ctypes, os, sys -libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'libcef.so') -if os.path.exists(libcef_so): - # Import local module - ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import from package - from cefpython3 import cefpython - -import wx -import time -import re -import uuid -import platform -import shutil - -class ClientHandler: - - # RequestHandler.GetResourceHandler() - def GetResourceHandler(self, browser, frame, request): - # Called on the IO thread before a resource is loaded. - # To allow the resource to load normally return None. - print("GetResourceHandler(): url = %s" % request.GetUrl()) - resHandler = ResourceHandler() - resHandler._clientHandler = self - resHandler._browser = browser - resHandler._frame = frame - resHandler._request = request - self._AddStrongReference(resHandler) - return resHandler - - def _OnResourceResponse(self, browser, frame, request, requestStatus, - requestError, response, data): - # This callback is emulated through ResourceHandler - # and WebRequest. Real "OnResourceResponse" is not yet - # available in CEF 3 (as of CEF revision 1450). See - # issue 515 in the CEF Issue Tracker: - # https://code.google.com/p/chromiumembedded/issues/detail?id=515 - # ---- - # requestStatus => cefpython.WebRequest.Status - # {"Unknown", "Success", "Pending", "Canceled", "Failed"} - # For "file://" requests the status will be "Unknown". - # requestError => see the NetworkError wiki page - # response.GetStatus() => http status code - print("_OnResourceResponse()") - print("data length = %s" % len(data)) - # Return the new data - you can modify it. - if request.GetUrl().startswith("file://") \ - and request.GetUrl().endswith("example.html"): - data = "This text was inserted through " \ - + "_OnResourceResponse()
      " + data - # Non-english characters are not displaying correctly. - # This is a bug in CEF. A quick fix is to get the charset - # from response headers and insert into - # the html page. - # Bug reported on the CEF C++ Forum: - # http://www.magpcss.org/ceforum/viewtopic.php?p=18401#p18401 - if FIX_ENCODING_BUG: - contentType = response.GetHeader("Content-Type") - if contentType: - contentType = contentType.lower() - isHtml = False - headerCharset = "" - if contentType and "text/html" in contentType: - isHtml = True - if contentType and "charset" in contentType: - match = re.search(r"charset\s*=\s*([^\s]+)", contentType) - if match and match.group(1): - headerCharset = match.group(1).lower() - if isHtml and headerCharset \ - and headerCharset != BROWSER_DEFAULT_ENCODING.lower(): - if not re.search(r"]+charset\s*=", data, \ - re.IGNORECASE): - # Only apply the fix if there is no - # available on a page. - data = ("" % headerCharset) + data - return data - - # A strong reference to ResourceHandler must be kept - # during the request. Some helper functions for that. - # 1. Add reference in GetResourceHandler() - # 2. Release reference in ResourceHandler.ReadResponse() - # after request is completed. - - _resourceHandlers = {} - _resourceHandlerMaxId = 0 - - def _AddStrongReference(self, resHandler): - self._resourceHandlerMaxId += 1 - resHandler._resourceHandlerId = self._resourceHandlerMaxId - self._resourceHandlers[resHandler._resourceHandlerId] = resHandler - - def _ReleaseStrongReference(self, resHandler): - if resHandler._resourceHandlerId in self._resourceHandlers: - del self._resourceHandlers[resHandler._resourceHandlerId] - else: - print("_ReleaseStrongReference() FAILED: resource handler " \ - "not found, id = %s" % (resHandler._resourceHandlerId)) - -class ResourceHandler: - - # The methods of this class will always be called - # on the IO thread. - - _resourceHandlerId = None - _clientHandler = None - _browser = None - _frame = None - _request = None - _responseHeadersReadyCallback = None - _webRequest = None - _webRequestClient = None - _offsetRead = 0 - - def ProcessRequest(self, request, callback): - print("ProcessRequest()") - # 1. Start the request using WebRequest - # 2. Return True to handle the request - # 3. Once response headers are ready call - # callback.Continue() - self._responseHeadersReadyCallback = callback - self._webRequestClient = WebRequestClient() - self._webRequestClient._resourceHandler = self - # Need to set AllowCacheCredentials and AllowCookies for - # the cookies to work during POST requests (Issue 127). - # To skip cache set the SkipCache request flag. - request.SetFlags(cefpython.Request.Flags["AllowCachedCredentials"]\ - | cefpython.Request.Flags["AllowCookies"]) - # A strong reference to the WebRequest object must kept. - self._webRequest = cefpython.WebRequest.Create( - request, self._webRequestClient) - return True - - def GetResponseHeaders(self, response, responseLengthOut, redirectUrlOut): - print("GetResponseHeaders()") - # 1. If the response length is not known set - # responseLengthOut[0] to -1 and ReadResponse() - # will be called until it returns False. - # 2. If the response length is known set - # responseLengthOut[0] to a positive value - # and ReadResponse() will be called until it - # returns False or the specified number of bytes - # have been read. - # 3. Use the |response| object to set the mime type, - # http status code and other optional header values. - # 4. To redirect the request to a new URL set - # redirectUrlOut[0] to the new url. - assert self._webRequestClient._response, "Response object empty" - wrcResponse = self._webRequestClient._response - response.SetStatus(wrcResponse.GetStatus()) - response.SetStatusText(wrcResponse.GetStatusText()) - response.SetMimeType(wrcResponse.GetMimeType()) - if wrcResponse.GetHeaderMultimap(): - response.SetHeaderMultimap(wrcResponse.GetHeaderMultimap()) - print("headers: ") - print(wrcResponse.GetHeaderMap()) - responseLengthOut[0] = self._webRequestClient._dataLength - if not responseLengthOut[0]: - # Probably a cached page? Or a redirect? - pass - - def ReadResponse(self, dataOut, bytesToRead, bytesReadOut, callback): - # print("ReadResponse()") - # 1. If data is available immediately copy up to - # bytesToRead bytes into dataOut[0], set - # bytesReadOut[0] to the number of bytes copied, - # and return true. - # 2. To read the data at a later time set - # bytesReadOut[0] to 0, return true and call - # callback.Continue() when the data is available. - # 3. To indicate response completion return false. - if self._offsetRead < self._webRequestClient._dataLength: - dataChunk = self._webRequestClient._data[\ - self._offsetRead:(self._offsetRead + bytesToRead)] - self._offsetRead += len(dataChunk) - dataOut[0] = dataChunk - bytesReadOut[0] = len(dataChunk) - return True - self._clientHandler._ReleaseStrongReference(self) - print("no more data, return False") - return False - - def CanGetCookie(self, cookie): - # Return true if the specified cookie can be sent - # with the request or false otherwise. If false - # is returned for any cookie then no cookies will - # be sent with the request. - return True - - def CanSetCookie(self, cookie): - # Return true if the specified cookie returned - # with the response can be set or false otherwise. - return True - - def Cancel(self): - # Request processing has been canceled. - pass - -class WebRequestClient: - - _resourceHandler = None - _data = "" - _dataLength = -1 - _response = None - - def OnUploadProgress(self, webRequest, current, total): - pass - - def OnDownloadProgress(self, webRequest, current, total): - pass - - def OnDownloadData(self, webRequest, data): - # print("OnDownloadData()") - self._data += data - - def OnRequestComplete(self, webRequest): - print("OnRequestComplete()") - # cefpython.WebRequest.Status = {"Unknown", "Success", - # "Pending", "Canceled", "Failed"} - statusText = "Unknown" - if webRequest.GetRequestStatus() in cefpython.WebRequest.Status: - statusText = cefpython.WebRequest.Status[\ - webRequest.GetRequestStatus()] - print("status = %s" % statusText) - print("error code = %s" % webRequest.GetRequestError()) - # Emulate OnResourceResponse() in ClientHandler: - self._response = webRequest.GetResponse() - # Are webRequest.GetRequest() and - # self._resourceHandler._request the same? What if - # there was a redirect, what will GetUrl() return - # for both of them? - self._data = self._resourceHandler._clientHandler._OnResourceResponse( - self._resourceHandler._browser, - self._resourceHandler._frame, - webRequest.GetRequest(), - webRequest.GetRequestStatus(), - webRequest.GetRequestError(), - webRequest.GetResponse(), - self._data) - self._dataLength = len(self._data) - # ResourceHandler.GetResponseHeaders() will get called - # after _responseHeadersReadyCallback.Continue() is called. - self._resourceHandler._responseHeadersReadyCallback.Continue() - -# Which method to use for message loop processing. -# EVT_IDLE - wx application has priority (default) -# EVT_TIMER - cef browser has priority -# It seems that Flash content behaves better when using a timer. -# IMPORTANT! On Linux EVT_IDLE does not work, the events seems to -# be propagated only when you move your mouse, which is not the -# expected behavior, it is recommended to use EVT_TIMER on Linux, -# so set this value to False. -USE_EVT_IDLE = False - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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" (os._exit()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("cefpython: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainFrame(wx.Frame): - browser = None - mainPanel = None - - def __init__(self): - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, - title='wxPython CEF 3 example', size=(800,600)) - self.CreateMenu() - - # Cannot attach browser to the main frame as this will cause - # the menu not to work. - # -- - # You also have to set the wx.WANTS_CHARS style for - # all parent panels/controls, if it's deeply embedded. - self.mainPanel = wx.Panel(self, style=wx.WANTS_CHARS) - - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(self.mainPanel.GetGtkWidget()) - # Linux requires adding "file://" for local files, - # otherwise /home/some will be replaced as http://home/some - self.browser = cefpython.CreateBrowserSync( - windowInfo, - # If there are problems with Flash you can disable it here, - # by disabling all plugins. - browserSettings={"plugins_disabled": False, - "default_encoding": BROWSER_DEFAULT_ENCODING}, - navigateUrl="file://"+GetApplicationPath("example.html")) - - clientHandler = ClientHandler() - self.browser.SetClientHandler(clientHandler) - - self.Bind(wx.EVT_CLOSE, self.OnClose) - if USE_EVT_IDLE: - # Bind EVT_IDLE only for the main application frame. - self.Bind(wx.EVT_IDLE, self.OnIdle) - - def CreateMenu(self): - filemenu = wx.Menu() - filemenu.Append(1, "Open") - exit = filemenu.Append(2, "Exit") - self.Bind(wx.EVT_MENU, self.OnClose, exit) - aboutmenu = wx.Menu() - aboutmenu.Append(1, "CEF Python") - menubar = wx.MenuBar() - menubar.Append(filemenu,"&File") - menubar.Append(aboutmenu, "&About") - self.SetMenuBar(menubar) - - def OnClose(self, event): - # In wx.chromectrl calling browser.CloseBrowser() and/or - # self.Destroy() in OnClose is causing crashes when embedding - # multiple browser tabs. The solution is to call only - # browser.ParentWindowWillClose. Behavior of this example - # seems different as it extends wx.Frame, while ChromeWindow - # from chromectrl extends wx.Window. Calling CloseBrowser - # and Destroy does not cause crashes, but is not recommended. - # Call ParentWindowWillClose and event.Skip() instead. See - # also Issue 107. - self.browser.ParentWindowWillClose() - event.Skip() - - def OnIdle(self, event): - cefpython.MessageLoopWork() - -class MyApp(wx.App): - timer = None - timerID = 1 - timerCount = 0 - - def OnInit(self): - if not USE_EVT_IDLE: - self.CreateTimer() - frame = MainFrame() - self.SetTopWindow(frame) - frame.Show() - return True - - def CreateTimer(self): - # See "Making a render loop": - # http://wiki.wxwidgets.org/Making_a_render_loop - # Another approach is to use EVT_IDLE in MainFrame, - # see which one fits you better. - self.timer = wx.Timer(self, self.timerID) - self.timer.Start(10) # 10ms - wx.EVT_TIMER(self, self.timerID, self.OnTimer) - - def OnTimer(self, event): - self.timerCount += 1 - # print("wxpython.py: OnTimer() %d" % self.timerCount) - cefpython.MessageLoopWork() - - def OnExit(self): - # When app.MainLoop() returns, MessageLoopWork() should - # not be called anymore. - if not USE_EVT_IDLE: - self.timer.Stop() - -if __name__ == '__main__': - sys.excepthook = ExceptHook - settings = { - "debug": False, # cefpython debug messages in console and in log_file - "log_severity": cefpython.LOGSEVERITY_INFO, # LOGSEVERITY_VERBOSE - "log_file": GetApplicationPath("debug.log"), # Set to "" to disable. - # This directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory(), - "browser_subprocess_path": "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess") - } - # print("browser_subprocess_path="+settings["browser_subprocess_path"]) - cefpython.Initialize(settings) - print('wx.version=%s' % wx.version()) - app = MyApp(False) - app.MainLoop() - # Let wx.App destructor do the cleanup before calling cefpython.Shutdown(). - del app - cefpython.Shutdown() diff --git a/src/linux/binaries_32bit/wxpython.html b/src/linux/binaries_32bit/wxpython.html deleted file mode 100644 index caf056ff9..000000000 --- a/src/linux/binaries_32bit/wxpython.html +++ /dev/null @@ -1,707 +0,0 @@ - - - - - wxPython CEF 3 example (utf-8: ąś) - - - - - - -Use the mouse context menu to go Back/Forward in history navigation. - -

      Table of contents

      -
        -
      1. Google search
      2. -
      3. User agent
      4. -
      5. Popups
      6. -
      7. HTML 5 video
      8. -
      9. Developer Tools
      10. -
      11. Downloads
      12. -
      13. HTML controls
      14. -
      15. Browser object
      16. -
      17. Frame object
      18. -
      19. Javascript bindings
      20. -
      21. Javascript callbacks
      22. -
      23. Python callbacks
      24. -
      25. Display handler
      26. -
      27. Keyboard handler
      28. -
      29. Request handler
      30. -
      31. Cookie tests
      32. -
      33. Load handler
      34. -
      35. Javascript Dialog handler
      36. -
      37. Other tests
      38. -
      - - - - - - -

      Google search

      - -http://www.google.com/ - - - - - - - -

      User agent

      - - - - - - - - - -

      Popups

      - -
        -
      1. - window.open('wxpython.html') -
      2. -
      3. - target=_blank href="wxpython.html" -
      4. -
      - -

      CreateAnotherBrowser

      - -This will create a window on its own and embed browser in it. -When using "window.open" the window is created implicitilly -by CEF. You can intercept such popup creation using the -OnBeforePopup callback in LifespanHandler. You can return -True in OnBeforePopup and create popup window on your own -using the CreateAnotherBrowser function. - - - - external.CreateAnotherBrowser() - - - - - - - -

      HTML5 video and accelerated content

      - - -HTML 5 video
      - - -Accelerated canvas
      - - -Accelerated layers
      - - - - - - -

      Developer Tools

      - -You can open devtools popup window in a few different ways: -
        -
      1. Call Browser.ShowDevTools() method: - - external.ShowDevTools()
      2. -
      3. Through mouse context menu
      4. -
      5. Through F12 key which is handled in KeyboardHandler.OnKeyEvent
      6. -
      - - - - - - -

      Downloads

      - -Download sample Ubuntu wallpapers:
      - - https://cefpython.googlecode.com/files/ubuntu-wallpapers2.zip - -

      -Notes: On Linux it seems that OnLoadError with errorCode = ERR_ABORTED -is called even for successful downloads, you can ignore this behavior. -The proper console messages about successful/aborted download originate -from C++ Browser process code, these are: -

      - -
      Browser: About to download file: ubuntu-wallpapers2.zip
      -Browser: Download completed, saved to: /Downloads/ubuntu-wallpapers2.zip
      -
      - -If download was aborted the messages will be: - -
      Browser: About to download file: ubuntu-wallpapers2.zip
      -Browser: Download was cancelled
      -
      - -

      -Additionally on Linux there are more errors reported by Chromium -about org.gnome.SessionManager.inhibit. These can be safely ignored as well. -

      - -A download handler with callbacks like `OnBeforeDownload` and -`OnDownloadUpdated` may be exposed to CEF Python in the future. - - - - - - -

      HTML controls

      - -

      Textarea

      - -
      - -

      Inputs

      -Text:
      -Password:
      - -

      Select

      - - -

      Buttons

      -Submit:
      -Button:
      - - - - - - -

      Browser object

      - -Tests for the Browser object methods. - -

      GoBack

      - -external.GoBack() - -

      GoForward

      - -external.GoForward() - -

      LoadUrl, GetUrl

      - - - window.open('data:text/html,Test#Browser.LoadUrl') - -

      ReloadIgnoreCache, StopLoad

      -Press F5 to reload page and ignore cache.
      -Press Esc during webpage loading to abort.
      - -Also, when Esc is pressed OnLoadError may get called. See how abort -of page loading or file download is handled: - - - - - - - -

      Frame object

      - -Tests for the Frame object methods. TODO. - - - - - - -

      Javascript bindings

      - -

      PyPrint

      - - - window.PyPrint('printing in python console from js') -
      - -

      Window properties

      - -
      jsBindings.SetProperty("pyProperty", "This was set in Python")
      -jsBindings.SetProperty("pyConfig", ["This was set in Python",
      -        {"name": "Nested dictionary", "isNested": True},
      -        [1,"2", None]])
      -
      - - - window.alert(window.pyProperty)
      - - window.alert(JSON.stringify(window.pyConfig)) -
      - -

      Print

      - - - - external.Print('printing again from js') -
      - -

      TestAllTypes

      - - - - external.TestAllTypes - (undefined, null, true, 1, - ((1<<31)>>>0), 2.14, 'Date not yet supported', 'string', - {key1: 1, key2: 2}, {key1: {'key1.1': 'nested object'}, 'key1.2': [1]}, - [1, 2], [1, [2.1, 'nested array']], [{key1: [{}]}]) -
      - -

      ExecuteFunction

      - - - -
      <script>
      -function JavascriptAlert(message) { window.alert(message); }
      -</script>
      -
      - - - - external.ExecuteFunction('JavascriptAlert', - 'python called from js and then js called from python') -
      - -

      GetSource, GetText

      - - - - - - - external.GetSource() -
      - - external.GetText() - - - - - - -

      Javascript callbacks

      - -

      TestJSCallback

      - - - -
      <script>
      -function JSCallback(arg1) {
      -    window.alert(arg1)
      -}
      -</script>
      -
      - - - - external.TestJSCallback(JSCallback) - -

      TestJSCallbackComplexArguments

      - - - -
      <script>
      -function JSCallback2() {
      -    window.alert(JSON.stringify(arguments))
      -}
      -</script>
      -
      - - - - external.TestJSCallbackComplexArguments({"myCallback": JSCallback2}) - - - - - - - -

      Python callbacks

      - -

      TestPythonCallback

      - - - -
      <script>
      -function JSCallback3(pyCallback) {
      -    pyCallback(1, 2.14, "string", [1, [2, {"key": "value"}]], {"list": [1,2]});
      -}
      -</script>
      -
      - - - - - - external.TestPythonCallback(JSCallback3) - - - - - - -

      Display handler

      - -

      OnAddressChange

      - -See messages in the console during loading of a webpage. - -

      OnTitleChange

      - -See messages in the console during loading of a webpage. - -

      OnTooltip

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

      OnStatusMessage

      - -See messages in the console when hovering over links. - -

      OnConsoleMessage

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

      Keyboard handler

      - -

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

      - - - - - - - - - -

      Request handler

      - -

      OnBeforeResourceLoad

      - -See messages in the console. - -

      OnResourceRedirect

      - -Try this: - - http://tinyurl.com/google404redirect - -

      GetAuthCredentials

      - -Try this: - - http://browserspy.dk/password-ok.php - -

      OnQuotaRequest

      - - - - -
      <script>
      -function DoRequestQuota() {
      -    // Request Quota (only for File System API)  
      -    try {
      -        navigator.webkitPersistentStorage.requestQuota(PERSISTENT, 1024*1024,
      -                function(bytes){ window.alert("Granted bytes: "+bytes);},
      -                function(error){ window.alert(error); });
      -    } catch(e) {
      -        navigator.webkitPersistentStorage.requestQuota(1024*1024,
      -                function(bytes){ window.alert("Granted bytes: "+bytes);},
      -                function(error){ window.alert(error); });
      -    }
      -}
      -</script>
      -
      - -Try this: - - https://googledrive.com/host/0B1di2XiBBfacMnhRRkI1YlotUEk/requestquota.html - -

      OnProtocolExecution

      - -Try this: - - magnet:?xt=urn:btih:a4224b45b27f436374391379cc5c7e629e2e5189 - -

      _OnBeforePluginLoad

      - -Try OnBeforePluginLoad() with Flash: - - http://www.adobe.com/software/flash/about/ - -

      _OnCertificateError

      - - -The url below won't be allowed. Click twice "Back" from context menu to return back -here after visiting the url:
      - - https://tv.eurosport.com/do-not-allow -
      - -This url will be allowed:
      - - https://tv.eurosport.com/ - -

      OnRendererProcessTerminated

      - -Try to terminate the "subprocess.exe" renderer process through -task manager. - -

      OnPluginCrashed

      - -No test for that yet. - - - - - - -

      Cookie tests

      - -See messages in the console. - -

      GetCookieManager

      - - - -RequestHandler.GetCookieManager() - an example of having an unique -cookie manager for each browser. -
        -
      1. Visit the url below and set some cookies. Use "Back" from - context menu to get back here (you might have to click "Back" - multiple times).
        - Visit it in the current browser:
        - - http://www.html-kit.com/tools/cookietester/ -
        - Or visit it in a js popup:
        - - javascript:window.open('http://www.html-kit.com/tools/cookietester/') -
      2. -
      3. Open cookietester in a popup:
        - - javascript:external.CreateAnotherBrowser('http://www.html-kit.com/tools/cookietester/') -
      4. -
      - -

      -Popup browsers created javascript's window.open share -the same renderer process and request context. If you want -to have separate cookie managers for popups created using -window.open then you have to implement the -LifespanHandler.`OnBeforePopup` callback. Return True in that -callback to cancel popup creation and instead create the -window on your own and embed browser in it. The CreateAnotherBrowser() -function from the wxpython example does that. -

      - -

      VisitAllCookies

      - -Visit all cookies: -external.VisitAllCookies() -

      - -Note: visit some http:// webpage first, otherwise cookie manager is not -yet created. -
      - -

      VisitUrlCookies

      - -Visit a subset of cookies for the given url: - - external.VisitUrlCookies("http://www.html-kit.com/tools/cookietester/") -
      - -

      SetCookie

      - -Set a cookie: -external.SetCookie() -
      - -

      DeleteCookies

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

      Load Handler

      - -See messages in the console during loading of a webpage. - -

      OnLoadingStateChange

      - - -

      OnLoadStart

      - - -

      OnLoadEnd

      - - -

      OnLoadError

      - -Try this: - - http://www.non-existent.nono/ -

      - -Note: after you see the custom error message you have to hit -twice the Back from the context menu, to get back to this page. - - - - - - -

      Javascript Dialog Handler

      - -See messages in the console. - -

      OnJavascriptDialog

      - - - alert('Test js dialog handler') - - -

      OnBeforeUnloadJavascriptDialog

      - - - -
      <script>
      -function TestOnBeforeUnloadJavascriptDialog() {
      -    window.onbeforeunload = function() {
      -        return 'Testing the OnBeforeUnloadJavascriptDialog() callback';
      -    }
      -    location.href = "wxpython.html";
      -}
      -</script>
      -
      - - - TestOnBeforeUnloadJavascriptDialog() - - -

      OnResetJavascriptDialogState

      - - -

      OnJavascriptDialogClosed

      - - - - - - - -

      Other tests

      - -

      HTTPS caching with SSL certificate errors

      -Set ApplicationSettings["ignore_certificate_errors"] to True. - - - - - - - - - - - - - diff --git a/src/linux/binaries_32bit/wxpython.py b/src/linux/binaries_32bit/wxpython.py deleted file mode 100644 index 212132d8f..000000000 --- a/src/linux/binaries_32bit/wxpython.py +++ /dev/null @@ -1,782 +0,0 @@ -# An example of embedding CEF browser in wxPython on Linux. -# Tested with wxPython 2.8.12.1 (gtk2-unicode). -# To install wxPython type "sudo apt-get install python-wxtools". - -# The official CEF Python binaries come with tcmalloc hook -# disabled. But if you've built custom binaries and kept tcmalloc -# hook enabled, then be aware that in such case it is required -# for the cefpython module to be the very first import in -# python scripts. See Issue 73 in the CEF Python Issue Tracker -# for more details. - -import ctypes, os, sys -libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)),\ - 'libcef.so') -if os.path.exists(libcef_so): - # Import a local module - ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import an installed package - from cefpython3 import cefpython - -import wx -import time -import re -import uuid -import platform -import inspect - -g_browserSettings = None - -# Which method to use for message loop processing. -# EVT_IDLE - wx application has priority (default) -# EVT_TIMER - cef browser has priority -# It seems that Flash content behaves better when using a timer. -# IMPORTANT! On Linux EVT_IDLE does not work, the events seems to -# be propagated only when you move your mouse, which is not the -# expected behavior, it is recommended to use EVT_TIMER on Linux, -# so set this value to False. -USE_EVT_IDLE = False - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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" (os._exit()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("[wxpython.py] WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainFrame(wx.Frame): - browser = None - mainPanel = None - - def __init__(self, url=None): - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, - title='wxPython CEF 3 example', size=(1024,768)) - if not url: - url = "file://"+GetApplicationPath("wxpython.html") - # Test hash in url. - # url += "#test-hash" - - self.CreateMenu() - - # Cannot attach browser to the main frame as this will cause - # the menu not to work. - # -- - # You also have to set the wx.WANTS_CHARS style for - # all parent panels/controls, if it's deeply embedded. - self.mainPanel = wx.Panel(self, style=wx.WANTS_CHARS) - - # Global client callbacks must be set before browser is created. - clientHandler = ClientHandler() - cefpython.SetGlobalClientCallback("OnCertificateError", - clientHandler._OnCertificateError) - cefpython.SetGlobalClientCallback("OnBeforePluginLoad", - clientHandler._OnBeforePluginLoad) - cefpython.SetGlobalClientCallback("OnAfterCreated", - clientHandler._OnAfterCreated) - - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(self.mainPanel.GetGtkWidget()) - # Linux requires adding "file://" for local files, - # otherwise /home/some will be replaced as http://home/some - self.browser = cefpython.CreateBrowserSync( - windowInfo, - # If there are problems with Flash you can disable it here, - # by disabling all plugins. - browserSettings=g_browserSettings, - navigateUrl=url) - - clientHandler.mainBrowser = self.browser - self.browser.SetClientHandler(clientHandler) - - jsBindings = cefpython.JavascriptBindings( - bindToFrames=False, bindToPopups=True) - jsBindings.SetFunction("PyPrint", PyPrint) - jsBindings.SetProperty("pyProperty", "This was set in Python") - jsBindings.SetProperty("pyConfig", ["This was set in Python", - {"name": "Nested dictionary", "isNested": True}, - [1,"2", None]]) - jsBindings.SetObject("external", JavascriptExternal(self.browser)) - jsBindings.SetProperty("sources", GetSources()) - self.browser.SetJavascriptBindings(jsBindings) - - self.Bind(wx.EVT_CLOSE, self.OnClose) - if USE_EVT_IDLE: - # Bind EVT_IDLE only for the main application frame. - self.Bind(wx.EVT_IDLE, self.OnIdle) - - def CreateMenu(self): - filemenu = wx.Menu() - filemenu.Append(1, "Open") - exit = filemenu.Append(2, "Exit") - self.Bind(wx.EVT_MENU, self.OnClose, exit) - aboutmenu = wx.Menu() - aboutmenu.Append(1, "CEF Python") - menubar = wx.MenuBar() - menubar.Append(filemenu,"&File") - menubar.Append(aboutmenu, "&About") - self.SetMenuBar(menubar) - - def OnClose(self, event): - # In wx.chromectrl calling browser.CloseBrowser() and/or - # self.Destroy() in OnClose is causing crashes when embedding - # multiple browser tabs. The solution is to call only - # browser.ParentWindowWillClose. Behavior of this example - # seems different as it extends wx.Frame, while ChromeWindow - # from chromectrl extends wx.Window. Calling CloseBrowser - # and Destroy does not cause crashes, but is not recommended. - # Call ParentWindowWillClose and event.Skip() instead. See - # also Issue 107. - self.browser.ParentWindowWillClose() - event.Skip() - - def OnIdle(self, event): - cefpython.MessageLoopWork() - -def PyPrint(message): - print("[wxpython.py] PyPrint: "+message) - -class JavascriptExternal: - mainBrowser = None - stringVisitor = None - - def __init__(self, mainBrowser): - self.mainBrowser = mainBrowser - - def GoBack(self): - self.mainBrowser.GoBack() - - def GoForward(self): - self.mainBrowser.GoForward() - - def CreateAnotherBrowser(self, url=None): - """ - TODO: There are errors in the console when closing the window: - >> Check failed: window - >> Gdk: _gdk_window_destroy_hierarchy: assertion `GDK_IS_WINDOW\ - >> (window)' failed - >> GLib-GObject: g_object_unref: assertion `G_IS_OBJECT (object)' failed - """ - frame = MainFrame(url=url) - frame.Show() - - def Print(self, message): - print("[wxpython.py] Print: "+message) - - def TestAllTypes(self, *args): - print("[wxpython.py] TestAllTypes: "+str(args)) - - def ExecuteFunction(self, *args): - self.mainBrowser.GetMainFrame().ExecuteFunction(*args) - - def TestJSCallback(self, jsCallback): - print("[wxpython.py] jsCallback.GetFunctionName() = %s"\ - % jsCallback.GetFunctionName()) - print("[wxpython.py] jsCallback.GetFrame().GetIdentifier() = %s" % \ - jsCallback.GetFrame().GetIdentifier()) - jsCallback.Call("This message was sent from python using js callback") - - def TestJSCallbackComplexArguments(self, jsObject): - jsCallback = jsObject["myCallback"]; - jsCallback.Call(1, None, 2.14, "string", ["list", ["nested list", \ - {"nested object":None}]], \ - {"nested list next":[{"deeply nested object":1}]}) - - def TestPythonCallback(self, jsCallback): - jsCallback.Call(self.PyCallback) - - def PyCallback(self, *args): - message = "PyCallback() was executed successfully! "\ - "Arguments: %s" % str(args) - print("[wxpython.py] "+message) - self.mainBrowser.GetMainFrame().ExecuteJavascript( - "window.alert(\"%s\")" % message) - - def GetSource(self): - # Must keep a strong reference to the StringVisitor object - # during the visit. - self.stringVisitor = StringVisitor() - self.mainBrowser.GetMainFrame().GetSource(self.stringVisitor) - - def GetText(self): - # Must keep a strong reference to the StringVisitor object - # during the visit. - self.stringVisitor = StringVisitor() - self.mainBrowser.GetMainFrame().GetText(self.stringVisitor) - - def ShowDevTools(self): - print("[wxpython.py] external.ShowDevTools called") - self.mainBrowser.ShowDevTools() - - # ------------------------------------------------------------------------- - # Cookies - # ------------------------------------------------------------------------- - cookieVisitor = None - - def VisitAllCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.VisitAllCookies(self.cookieVisitor) - - def VisitUrlCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.VisitUrlCookies( - "http://www.html-kit.com/tools/cookietester/", - False, self.cookieVisitor) - # .www.html-kit.com - - def SetCookie(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - "the cookietester website first and create some cookies") - return - cookie = cefpython.Cookie() - cookie.SetName("Created_Via_Python") - cookie.SetValue("yeah really") - cookieManager.SetCookie("http://www.html-kit.com/tools/cookietester/", - cookie) - print("\n[wxpython.py] Cookie created! Visit html-kit cookietester to"\ - " see it") - - def DeleteCookies(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.DeleteCookies( - "http://www.html-kit.com/tools/cookietester/", - "Created_Via_Python") - print("\n[wxpython.py] Cookie deleted! Visit html-kit cookietester "\ - "to see the result") - -class StringVisitor: - def Visit(self, string): - print("\n[wxpython.py] StringVisitor.Visit(): string:") - print("--------------------------------") - print(string) - print("--------------------------------") - -class CookieVisitor: - def Visit(self, cookie, count, total, deleteCookie): - if count == 0: - print("\n[wxpython.py] CookieVisitor.Visit(): total cookies: %s"\ - % total) - print("\n[wxpython.py] CookieVisitor.Visit(): cookie:") - print(" "+str(cookie.Get())) - # True to continue visiting cookies - return True - -class ClientHandler: - mainBrowser = None # May be None for global client callbacks. - - def __init__(self): - pass - - # ------------------------------------------------------------------------- - # DisplayHandler - # ------------------------------------------------------------------------- - - def OnAddressChange(self, browser, frame, url): - print("[wxpython.py] DisplayHandler::OnAddressChange()") - print(" url = %s" % url) - - def OnTitleChange(self, browser, title): - print("[wxpython.py] DisplayHandler::OnTitleChange()") - print(" title = %s" % title) - - def OnTooltip(self, browser, textOut): - # OnTooltip not yet implemented (both Linux and Windows), - # will be fixed in next CEF release, see Issue 783: - # https://code.google.com/p/chromiumembedded/issues/detail?id=783 - print("[wxpython.py] DisplayHandler::OnTooltip()") - print(" text = %s" % textOut[0]) - - statusMessageCount = 0 - def OnStatusMessage(self, browser, value): - if not value: - # Do not notify in the console about empty statuses. - return - self.statusMessageCount += 1 - if self.statusMessageCount > 3: - # Do not spam too much. - return - print("[wxpython.py] DisplayHandler::OnStatusMessage()") - print(" value = %s" % value) - - def OnConsoleMessage(self, browser, message, source, line): - print("[wxpython.py] DisplayHandler::OnConsoleMessage()") - print(" message = %s" % message) - print(" source = %s" % source) - print(" line = %s" % line) - - # ------------------------------------------------------------------------- - # KeyboardHandler - # ------------------------------------------------------------------------- - - def OnPreKeyEvent(self, browser, event, eventHandle, - isKeyboardShortcutOut): - print("[wxpython.py] KeyboardHandler::OnPreKeyEvent()") - - def OnKeyEvent(self, browser, event, eventHandle): - if event["type"] == cefpython.KEYEVENT_KEYUP: - # OnKeyEvent is called twice for F5/Esc keys, with event - # type KEYEVENT_RAWKEYDOWN and KEYEVENT_KEYUP. - # Normal characters a-z should have KEYEVENT_CHAR. - return False - print("[wxpython.py] KeyboardHandler::OnKeyEvent()") - print(" type=%s" % event["type"]) - print(" modifiers=%s" % event["modifiers"]) - print(" windows_key_code=%s" % event["windows_key_code"]) - print(" native_key_code=%s" % event["native_key_code"]) - print(" is_system_key=%s" % event["is_system_key"]) - print(" character=%s" % event["character"]) - print(" unmodified_character=%s" % event["unmodified_character"]) - print(" focus_on_editable_field=%s"\ - % event["focus_on_editable_field"]) - if platform.system() == "Linux": - # F5 - if event["native_key_code"] == 71: - print("[wxpython.py] F5 pressed, calling"\ - " browser.ReloadIgnoreCache()") - browser.ReloadIgnoreCache() - return True - # Escape - if event["native_key_code"] == 9: - print("[wxpython.py] Esc pressed, calling browser.StopLoad()") - browser.StopLoad() - return True - # F12 - if event["native_key_code"] == 96: - print("[wxpython.py] F12 pressed, calling"\ - " browser.ShowDevTools()") - browser.ShowDevTools() - return True - elif platform.system() == "Windows": - # F5 todo - # Escape todo - pass - return False - - # ------------------------------------------------------------------------- - # RequestHandler - # ------------------------------------------------------------------------- - - def OnBeforeBrowse(self, browser, frame, request, isRedirect): - print("[wxpython.py] RequestHandler::OnBeforeBrowse()") - print(" url = %s" % request.GetUrl()[:100]) - return False - - def OnBeforeResourceLoad(self, browser, frame, request): - print("[wxpython.py] RequestHandler::OnBeforeResourceLoad()") - print(" url = %s" % request.GetUrl()[:100]) - return False - - def OnResourceRedirect(self, browser, frame, oldUrl, newUrlOut, request): - print("[wxpython.py] RequestHandler::OnResourceRedirect()") - print(" old url = %s" % oldUrl[:100]) - print(" new url = %s" % newUrlOut[0][:100]) - - def GetAuthCredentials(self, browser, frame, isProxy, host, port, realm, - scheme, callback): - # This callback is called on the IO thread, thus print messages - # may not be visible. - print("[wxpython.py] RequestHandler::GetAuthCredentials()") - print(" host = %s" % host) - print(" realm = %s" % realm) - callback.Continue(username="test", password="test") - return True - - def OnQuotaRequest(self, browser, originUrl, newSize, callback): - print("[wxpython.py] RequestHandler::OnQuotaRequest()") - print(" origin url = %s" % originUrl) - print(" new size = %s" % newSize) - callback.Continue(True) - return True - - def GetCookieManager(self, browser, mainUrl): - # Create unique cookie manager for each browser. - # You must set the "unique_request_context_per_browser" - # application setting to True for the cookie manager - # to work. - # Return None to have one global cookie manager for - # all CEF browsers. - if not browser: - # The browser param may be empty in some exceptional - # case, see docs. - return None - cookieManager = browser.GetUserData("cookieManager") - if cookieManager: - return cookieManager - else: - print("[wxpython.py] RequestHandler::GetCookieManager():"\ - " created cookie manager") - cookieManager = cefpython.CookieManager.CreateManager("") - browser.SetUserData("cookieManager", cookieManager) - return cookieManager - - def OnProtocolExecution(self, browser, url, allowExecutionOut): - # There's no default implementation for OnProtocolExecution on Linux, - # you have to make OS system call on your own. You probably also need - # to use LoadHandler::OnLoadError() when implementing this on Linux. - print("[wxpython.py] RequestHandler::OnProtocolExecution()") - print(" url = %s" % url) - if url.startswith("magnet:"): - print("[wxpython.py] Magnet link allowed!") - allowExecutionOut[0] = True - - def _OnBeforePluginLoad(self, browser, mimeType, pluginUrl, topOriginUrl, - info): - # This is a global callback set using SetGlobalClientCallback(). - # Plugins are loaded on demand, only when website requires it, - # the same plugin may be called multiple times. - # This callback is called on various threads, thus print messages - # may not be visible. - print("[wxpython.py] RequestHandler::_OnBeforePluginLoad()") - print(" mimeType = %s" % mimeType) - print(" pluginUrl = %s" % pluginUrl) - print(" topOriginUrl = %s" % topOriginUrl) - print(" info.GetName() = %s" % info.GetName()) - print(" info.GetPath() = %s" % info.GetPath()) - print(" info.GetVersion() = %s" % info.GetVersion()) - print(" info.GetDescription() = %s" % info.GetDescription()) - # False to allow, True to block plugin. - return False - - def _OnCertificateError(self, certError, requestUrl, callback): - # This is a global callback set using SetGlobalClientCallback(). - print("[wxpython.py] RequestHandler::_OnCertificateError()") - print(" certError = %s" % certError) - print(" requestUrl = %s" % requestUrl) - if requestUrl.startswith( - "https://tv.eurosport.com/do-not-allow"): - print(" Not allowed!") - return False - if requestUrl.startswith( - "https://tv.eurosport.com/"): - print(" Allowed!") - callback.Continue(True) - return True - return False - - def OnRendererProcessTerminated(self, browser, status): - print("[wxpython.py] RequestHandler::OnRendererProcessTerminated()") - statuses = { - cefpython.TS_ABNORMAL_TERMINATION: "TS_ABNORMAL_TERMINATION", - cefpython.TS_PROCESS_WAS_KILLED: "TS_PROCESS_WAS_KILLED", - cefpython.TS_PROCESS_CRASHED: "TS_PROCESS_CRASHED" - } - statusName = "Unknown" - if status in statuses: - statusName = statuses[status] - print(" status = %s" % statusName) - - def OnPluginCrashed(self, browser, pluginPath): - print("[wxpython.py] RequestHandler::OnPluginCrashed()") - print(" plugin path = %s" % pluginPath) - - # ------------------------------------------------------------------------- - # LoadHandler - # ------------------------------------------------------------------------- - - def OnLoadingStateChange(self, browser, isLoading, canGoBack, - canGoForward): - print("[wxpython.py] LoadHandler::OnLoadingStateChange()") - print(" isLoading = %s, canGoBack = %s, canGoForward = %s" \ - % (isLoading, canGoBack, canGoForward)) - - def OnLoadStart(self, browser, frame): - print("[wxpython.py] LoadHandler::OnLoadStart()") - print(" frame url = %s" % frame.GetUrl()[:100]) - - def OnLoadEnd(self, browser, frame, httpStatusCode): - print("[wxpython.py] LoadHandler::OnLoadEnd()") - print(" frame url = %s" % frame.GetUrl()[:100]) - # For file:// urls the status code = 0 - print(" http status code = %s" % httpStatusCode) - # Tests for the Browser object methods - self._Browser_LoadUrl(browser) - - def _Browser_LoadUrl(self, browser): - if browser.GetUrl() == "data:text/html,Test#Browser.LoadUrl": - browser.LoadUrl("file://"+GetApplicationPath("wxpython.html")) - - def OnLoadError(self, browser, frame, errorCode, errorTextList, failedUrl): - print("[wxpython.py] LoadHandler::OnLoadError()") - print(" frame url = %s" % frame.GetUrl()[:100]) - print(" error code = %s" % errorCode) - print(" error text = %s" % errorTextList[0]) - print(" failed url = %s" % failedUrl) - # Handle ERR_ABORTED error code, to handle the following cases: - # 1. Esc key was pressed which calls browser.StopLoad() in OnKeyEvent - # 2. Download of a file was aborted - if errorCode == cefpython.ERR_ABORTED: - print("[wxpython.py] LoadHandler::OnLoadError(): Ignoring load"\ - " error: Esc was pressed or file download was aborted") - return; - customErrorMessage = "My custom error message!" - frame.LoadUrl("data:text/html,%s" % customErrorMessage) - - # ------------------------------------------------------------------------- - # LifespanHandler - # ------------------------------------------------------------------------- - - # ** This callback is executed on the IO thread ** - # Empty place-holders: popupFeatures, client. - def OnBeforePopup(self, browser, frame, targetUrl, targetFrameName, - targetDisposition, userGesture, - popupFeatures, windowInfo, client, browserSettings, - noJavascriptAccess): - print("[wxpython.py] LifespanHandler::OnBeforePopup()") - print(" targetUrl = %s" % targetUrl) - # Custom browser settings for popups: - # > browserSettings[0] = {"plugins_disabled": True} - # Set WindowInfo object: - # > windowInfo[0] = cefpython.WindowInfo() - allowPopups = True - return not allowPopups - - def _OnAfterCreated(self, browser): - # This is a global callback set using SetGlobalClientCallback(). - print("[wxpython.py] LifespanHandler::_OnAfterCreated()") - print(" browserId=%s" % browser.GetIdentifier()) - - def DoClose(self, browser): - print("[wxpython.py] LifespanHandler::DoClose()") - print(" browserId=%s" % browser.GetIdentifier()) - - def OnBeforeClose(self, browser): - print("[wxpython.py] LifespanHandler::OnBeforeClose") - print(" browserId=%s" % browser.GetIdentifier()) - - # ------------------------------------------------------------------------- - # JavascriptDialogHandler - # ------------------------------------------------------------------------- - - def OnJavascriptDialog(self, browser, originUrl, dialogType, - messageText, defaultPromptText, callback, - suppressMessage): - print("[wxpython.py] JavascriptDialogHandler::OnJavascriptDialog()") - print(" originUrl="+originUrl) - print(" dialogType="+str(dialogType)) - print(" messageText="+messageText) - print(" defaultPromptText="+defaultPromptText) - # If you want to suppress the javascript dialog: - # suppressMessage[0] = True - return False - - def OnBeforeUnloadJavascriptDialog(self, browser, messageText, isReload, - callback): - print("[wxpython.py] OnBeforeUnloadJavascriptDialog()") - print(" messageText="+messageText) - print(" isReload="+str(isReload)) - # Return True if the application will use a custom dialog: - # callback.Continue(allow=True, userInput="") - # return True - return False - - def OnResetJavascriptDialogState(self, browser): - print("[wxpython.py] OnResetDialogState()") - - def OnJavascriptDialogClosed(self, browser): - print("[wxpython.py] OnDialogClosed()") - - -class MyApp(wx.App): - timer = None - timerID = 1 - timerCount = 0 - - def OnInit(self): - if not USE_EVT_IDLE: - self.CreateTimer() - frame = MainFrame() - self.SetTopWindow(frame) - frame.Show() - return True - - def CreateTimer(self): - # See "Making a render loop": - # http://wiki.wxwidgets.org/Making_a_render_loop - # Another approach is to use EVT_IDLE in MainFrame, - # see which one fits you better. - self.timer = wx.Timer(self, self.timerID) - self.timer.Start(10) # 10ms - wx.EVT_TIMER(self, self.timerID, self.OnTimer) - - def OnTimer(self, event): - self.timerCount += 1 - # print("[wxpython.py] OnTimer() %d" % self.timerCount) - cefpython.MessageLoopWork() - - def OnExit(self): - # When app.MainLoop() returns, MessageLoopWork() should - # not be called anymore. - if not USE_EVT_IDLE: - self.timer.Stop() - -def GetSources(): - # Get sources of all python functions and methods from this file. - # This is to provide sources preview to wxpython.html. - # The dictionary of functions is binded to "window.sources". - thisModule = sys.modules[__name__] - functions = inspect.getmembers(thisModule, inspect.isfunction) - classes = inspect.getmembers(thisModule, inspect.isclass) - sources = {} - for funcTuple in functions: - sources[funcTuple[0]] = inspect.getsource(funcTuple[1]) - for classTuple in classes: - className = classTuple[0] - classObject = classTuple[1] - methods = inspect.getmembers(classObject) - for methodTuple in methods: - try: - sources[methodTuple[0]] = inspect.getsource(\ - methodTuple[1]) - except: - pass - return sources - -if __name__ == '__main__': - print('[wxpython.py] wx.version=%s' % wx.version()) - - # Intercept python exceptions. Exit app immediately when exception - # happens on any of the threads. - sys.excepthook = ExceptHook - - # Application settings - settings = { - # CEF Python debug messages in console and in log_file - "debug": True, - # Set it to LOGSEVERITY_VERBOSE for more details - "log_severity": cefpython.LOGSEVERITY_INFO, - # Set to "" to disable logging to a file - "log_file": GetApplicationPath("debug.log"), - # These directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory(), - # The "subprocess" executable that launches the Renderer - # and GPU processes among others. You may rename that - # executable if you like. - "browser_subprocess_path": "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess"), - # This option is required for the GetCookieManager callback - # to work. It affects renderer processes, when this option - # is set to True. It will force a separate renderer process - # for each browser created using CreateBrowserSync. - "unique_request_context_per_browser": True, - # Downloads are handled automatically. A default SaveAs file - # dialog provided by OS will be displayed. - "downloads_enabled": True, - # Remote debugging port, required for Developer Tools support. - # A value of 0 will generate a random port. To disable devtools - # support set it to -1. - "remote_debugging_port": 0, - # Mouse context menu - "context_menu": { - "enabled": True, - "navigation": True, # Back, Forward, Reload - "print": True, - "view_source": True, - "external_browser": True, # Open in external browser - "devtools": True, # Developer Tools - }, - # See also OnCertificateError which allows you to ignore - # certificate errors for specific websites. - "ignore_certificate_errors": False, - } - - # Browser settings. You may have different settings for each - # browser, see the call to CreateBrowserSync. - g_browserSettings = { - # "plugins_disabled": True, - # "file_access_from_file_urls_allowed": True, - # "universal_access_from_file_urls_allowed": True, - } - - # Command line switches set programmatically - switches = { - # "proxy-server": "socks5://127.0.0.1:8888", - # "no-proxy-server": "", - # "enable-media-stream": "", - # "remote-debugging-port": "12345", - # "disable-gpu": "", - # "--invalid-switch": "" -> Invalid switch name - } - - cefpython.Initialize(settings, switches) - - app = MyApp(False) - app.MainLoop() - # Let wx.App destructor do the cleanup before calling cefpython.Shutdown(). - del app - - cefpython.Shutdown() diff --git a/src/linux/compile.py b/src/linux/compile.py index 623c3b07c..16acf092d 100644 --- a/src/linux/compile.py +++ b/src/linux/compile.py @@ -300,7 +300,7 @@ def check_cython_version(): # Make installer, install, run examples and unit tests, # and return to src/linux/ dir. if KIVY_FLAG: - run_examples = " && {python} ../src/linux/binaries_64bit/kivy_.py" + run_examples = " && {python} ../src/linux/deprecated_64bit/kivy_.py" else: run_examples = (" && {python} hello_world.py" " && {python} wxpython.py" @@ -310,7 +310,7 @@ def check_cython_version(): " && {python} tkinter_.py" " && {python} qt.py pyqt" " && {python} qt.py pyside" - " && {python} ../src/linux/binaries_64bit/kivy_.py") + " && {python} ../src/linux/deprecated_64bit/kivy_.py") commands = ("cd ./installer/" " && {python} make-setup.py --version {ver}" " && cd cefpython3-{ver}-*-setup/" diff --git a/src/linux/rebuild.sh b/src/linux/rebuild.sh deleted file mode 100644 index f703ba9c2..000000000 --- a/src/linux/rebuild.sh +++ /dev/null @@ -1 +0,0 @@ -python compile.py diff --git a/src/linux/wxpython.sh b/src/linux/wxpython.sh deleted file mode 100644 index f28b13c11..000000000 --- a/src/linux/wxpython.sh +++ /dev/null @@ -1,2 +0,0 @@ -cd binaries_64bit -python wxpython.py diff --git a/src/mac/.gitignore b/src/mac/.gitignore deleted file mode 100644 index af654df08..000000000 --- a/src/mac/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -Resources/ -*.dylib -*.so -subprocess -webcache/ diff --git a/src/mac/binaries_64bit/prism.css b/src/mac/binaries_64bit/prism.css deleted file mode 100644 index f94cca7c0..000000000 --- a/src/mac/binaries_64bit/prism.css +++ /dev/null @@ -1,130 +0,0 @@ -/* http://prismjs.com/download.html?themes=prism&languages=clike+javascript+python */ -/** - * prism.js default theme for JavaScript, CSS and HTML - * Based on dabblet (http://dabblet.com) - * @author Lea Verou - */ - -code[class*="language-"], -pre[class*="language-"] { - color: black; - text-shadow: 0 1px white; - font-family: Consolas, Monaco, 'Andale Mono', monospace; - direction: ltr; - text-align: left; - white-space: pre; - word-spacing: normal; - word-break: normal; - - - -moz-tab-size: 4; - -o-tab-size: 4; - tab-size: 4; - - -webkit-hyphens: none; - -moz-hyphens: none; - -ms-hyphens: none; - hyphens: none; -} - -pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, -code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { - text-shadow: none; - background: #b3d4fc; -} - -pre[class*="language-"]::selection, pre[class*="language-"] ::selection, -code[class*="language-"]::selection, code[class*="language-"] ::selection { - text-shadow: none; - background: #b3d4fc; -} - -@media print { - code[class*="language-"], - pre[class*="language-"] { - text-shadow: none; - } -} - -/* Code blocks */ -pre[class*="language-"] { - padding: 1em; - margin: .5em 0; - overflow: auto; -} - -:not(pre) > code[class*="language-"], -pre[class*="language-"] { - background: #f5f2f0; -} - -/* Inline code */ -:not(pre) > code[class*="language-"] { - padding: .1em; - border-radius: .3em; -} - -.token.comment, -.token.prolog, -.token.doctype, -.token.cdata { - color: slategray; -} - -.token.punctuation { - color: #999; -} - -.namespace { - opacity: .7; -} - -.token.property, -.token.tag, -.token.boolean, -.token.number, -.token.constant, -.token.symbol { - color: #905; -} - -.token.selector, -.token.attr-name, -.token.string, -.token.builtin { - color: #690; -} - -.token.operator, -.token.entity, -.token.url, -.language-css .token.string, -.style .token.string, -.token.variable { - color: #a67f59; - background: hsla(0,0%,100%,.5); -} - -.token.atrule, -.token.attr-value, -.token.keyword { - color: #07a; -} - -.token.function { - color: #DD4A68; -} - -.token.regex, -.token.important { - color: #e90; -} - -.token.important { - font-weight: bold; -} - -.token.entity { - cursor: help; -} - diff --git a/src/mac/binaries_64bit/prism.js b/src/mac/binaries_64bit/prism.js deleted file mode 100644 index ebaa4b428..000000000 --- a/src/mac/binaries_64bit/prism.js +++ /dev/null @@ -1,5 +0,0 @@ -/* http://prismjs.com/download.html?themes=prism&languages=clike+javascript+python */ -self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{};var Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content)):"Array"===t.util.type(e)?e.map(t.util.encode):e.replace(/&/g,"&").replace(/e.length)break e;if(!(f instanceof r)){l.lastIndex=0;var h=l.exec(f);if(h){c&&(g=h[1].length);var d=h.index-1+g,h=h[0].slice(g),p=h.length,m=d+p,v=f.slice(0,d+1),y=f.slice(m+1),k=[u,1];v&&k.push(v);var b=new r(o,s?t.tokenize(h,s):h);k.push(b),y&&k.push(y),Array.prototype.splice.apply(a,k)}}}}return a},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[],r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(r&&r.length)for(var a,i=0;a=r[i++];)a(n)}}},n=t.Token=function(e,t){this.type=e,this.content=t};if(n.stringify=function(e,r,a){if("string"==typeof e)return e;if("[object Array]"==Object.prototype.toString.call(e))return e.map(function(t){return n.stringify(t,r,e)}).join("");var i={type:e.type,content:n.stringify(e.content,r,a),tag:"span",classes:["token",e.type],attributes:{},language:r,parent:a};"comment"==i.type&&(i.attributes.spellcheck="true"),t.hooks.run("wrap",i);var o="";for(var l in i.attributes)o+=l+'="'+(i.attributes[l]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+o+">"+i.content+""},!self.document)return self.addEventListener?(self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,a=n.code;self.postMessage(JSON.stringify(t.tokenize(a,t.languages[r]))),self.close()},!1),self.Prism):self.Prism;var r=document.getElementsByTagName("script");return r=r[r.length-1],r&&(t.filename=r.src,document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)),self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism);; -Prism.languages.clike={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,lookbehind:!0},string:/("|')(\\?.)*?\1/g,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/gi,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g,"boolean":/\b(true|false)\b/g,"function":{pattern:/[a-z0-9_]+\(/gi,inside:{punctuation:/\(/}},number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,operator:/[-+]{1,2}|!|<=?|>=?|={1,3}|&{1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};; -Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|function|get|if|implements|import|in|instanceof|interface|let|new|null|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,lookbehind:!0}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/[\w\W]*?<\/script>/gi,inside:{tag:{pattern:/|<\/script>/gi,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}});; -Prism.languages.python={comment:{pattern:/(^|[^\\])#.*?(\r?\n|$)/g,lookbehind:!0},string:/"""[\s\S]+?"""|("|')(\\?.)*?\1/g,keyword:/\b(as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/g,"boolean":/\b(True|False)\b/g,number:/\b-?(0x)?\d*\.?[\da-f]+\b/g,operator:/[-+]{1,2}|=?<|=?>|!|={1,2}|(&){1,2}|(&){1,2}|\|?\||\?|\*|\/|~|\^|%|\b(or|and|not)\b/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};; diff --git a/src/mac/binaries_64bit/wxpython.html b/src/mac/binaries_64bit/wxpython.html deleted file mode 100644 index c23b384f0..000000000 --- a/src/mac/binaries_64bit/wxpython.html +++ /dev/null @@ -1,708 +0,0 @@ - - - - - wxPython CEF 3 example (utf-8: ąś) - - - - - - -Use mouse context menu to go Back/Forward in navigation history.
      - -

      Table of contents

      -
        -
      1. Google search
      2. -
      3. User agent
      4. -
      5. Popups
      6. -
      7. HTML 5 video
      8. -
      9. Developer Tools
      10. -
      11. Downloads
      12. -
      13. HTML controls
      14. -
      15. Browser object
      16. -
      17. Frame object
      18. -
      19. Javascript bindings
      20. -
      21. Javascript callbacks
      22. -
      23. Python callbacks
      24. -
      25. Display handler
      26. -
      27. Keyboard handler
      28. -
      29. Request handler
      30. -
      31. Cookie tests
      32. -
      33. Load handler
      34. -
      35. Javascript Dialog handler
      36. -
      37. Other tests
      38. -
      - - - - - - -

      Google search

      - -http://www.google.com/ - - - - - - - -

      User agent

      - - - - - - - - - -

      Popups

      - -
        -
      1. - window.open('wxpython.html') -
      2. -
      3. - target=_blank href="wxpython.html" -
      4. -
      - -

      CreateAnotherBrowser

      - -This will create a window on its own and embed browser in it. -When using "window.open" the window is created implicitilly -by CEF. You can intercept such popup creation using the -OnBeforePopup callback in LifespanHandler. You can return -True in OnBeforePopup and create popup window on your own -using the CreateAnotherBrowser function. - - - - external.CreateAnotherBrowser() - - - - - - - -

      HTML5 video and accelerated content

      - - -HTML 5 video
      - - -Accelerated canvas
      - - -Accelerated layers
      - - - - - - -

      Developer Tools

      - -You can open devtools popup window in a few different ways: -
        -
      1. Call Browser.ShowDevTools() method: - - external.ShowDevTools()
      2. -
      3. Through mouse context menu
      4. -
      5. Through F12 key (on Mac: Cmd+Opt+I) which is handled in - KeyboardHandler.OnKeyEvent.
      6. -
      - - - - - - -

      Downloads

      - -Download sample Ubuntu wallpapers:
      - - https://cefpython.googlecode.com/files/ubuntu-wallpapers2.zip - -

      -Notes: On Linux it seems that OnLoadError with errorCode = ERR_ABORTED -is called even for successful downloads, you can ignore this behavior. -The proper console messages about successful/aborted download originate -from C++ Browser process code, these are: -

      - -
      Browser: About to download file: ubuntu-wallpapers2.zip
      -Browser: Download completed, saved to: /Downloads/ubuntu-wallpapers2.zip
      -
      - -If download was aborted the messages will be: - -
      Browser: About to download file: ubuntu-wallpapers2.zip
      -Browser: Download was cancelled
      -
      - -

      -Additionally on Linux there are more errors reported by Chromium -about org.gnome.SessionManager.inhibit. These can be safely ignored as well. -

      - -A download handler with callbacks like `OnBeforeDownload` and -`OnDownloadUpdated` may be exposed to CEF Python in the future. - - - - - - -

      HTML controls

      - -

      Textarea

      - -
      - -

      Inputs

      -Text:
      -Password:
      - -

      Select

      - - -

      Buttons

      -Submit:
      -Button:
      - - - - - - -

      Browser object

      - -Tests for the Browser object methods. - -

      GoBack

      - -external.GoBack() - -

      GoForward

      - -external.GoForward() - -

      LoadUrl, GetUrl

      - - - window.open('data:text/html,Test#Browser.LoadUrl') - -

      ReloadIgnoreCache, StopLoad

      -Press F5 to reload page and ignore cache.
      -Press Esc during webpage loading to abort.
      - -Also, when Esc is pressed OnLoadError may get called. See how abort -of page loading or file download is handled: - - - - - - - -

      Frame object

      - -Tests for the Frame object methods. TODO. - - - - - - -

      Javascript bindings

      - -

      PyPrint

      - - - window.PyPrint('printing in python console from js') -
      - -

      Window properties

      - -
      jsBindings.SetProperty("pyProperty", "This was set in Python")
      -jsBindings.SetProperty("pyConfig", ["This was set in Python",
      -        {"name": "Nested dictionary", "isNested": True},
      -        [1,"2", None]])
      -
      - - - window.alert(window.pyProperty)
      - - window.alert(JSON.stringify(window.pyConfig)) -
      - -

      Print

      - - - - external.Print('printing again from js') -
      - -

      TestAllTypes

      - - - - external.TestAllTypes - (undefined, null, true, 1, - ((1<<31)>>>0), 2.14, 'Date not yet supported', 'string', - {key1: 1, key2: 2}, {key1: {'key1.1': 'nested object'}, 'key1.2': [1]}, - [1, 2], [1, [2.1, 'nested array']], [{key1: [{}]}]) -
      - -

      ExecuteFunction

      - - - -
      <script>
      -function JavascriptAlert(message) { window.alert(message); }
      -</script>
      -
      - - - - external.ExecuteFunction('JavascriptAlert', - 'python called from js and then js called from python') -
      - -

      GetSource, GetText

      - - - - - - - external.GetSource() -
      - - external.GetText() - - - - - - -

      Javascript callbacks

      - -

      TestJSCallback

      - - - -
      <script>
      -function JSCallback(arg1) {
      -    window.alert(arg1)
      -}
      -</script>
      -
      - - - - external.TestJSCallback(JSCallback) - -

      TestJSCallbackComplexArguments

      - - - -
      <script>
      -function JSCallback2() {
      -    window.alert(JSON.stringify(arguments))
      -}
      -</script>
      -
      - - - - external.TestJSCallbackComplexArguments({"myCallback": JSCallback2}) - - - - - - - -

      Python callbacks

      - -

      TestPythonCallback

      - - - -
      <script>
      -function JSCallback3(pyCallback) {
      -    pyCallback(1, 2.14, "string", [1, [2, {"key": "value"}]], {"list": [1,2]});
      -}
      -</script>
      -
      - - - - - - external.TestPythonCallback(JSCallback3) - - - - - - -

      Display handler

      - -

      OnAddressChange

      - -See messages in the console during loading of a webpage. - -

      OnTitleChange

      - -See messages in the console during loading of a webpage. - -

      OnTooltip

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

      OnStatusMessage

      - -See messages in the console when hovering over links. - -

      OnConsoleMessage

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

      Keyboard handler

      - -

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

      - - - - - - - - - -

      Request handler

      - -

      OnBeforeResourceLoad

      - -See messages in the console. - -

      OnResourceRedirect

      - -Try this: - - http://tinyurl.com/google404redirect - -

      GetAuthCredentials

      - -Try this: - - http://browserspy.dk/password-ok.php - -

      OnQuotaRequest

      - - - - -
      <script>
      -function DoRequestQuota() {
      -    // Request Quota (only for File System API)
      -    try {
      -        navigator.webkitPersistentStorage.requestQuota(PERSISTENT, 1024*1024,
      -                function(bytes){ window.alert("Granted bytes: "+bytes);},
      -                function(error){ window.alert(error); });
      -    } catch(e) {
      -        navigator.webkitPersistentStorage.requestQuota(1024*1024,
      -                function(bytes){ window.alert("Granted bytes: "+bytes);},
      -                function(error){ window.alert(error); });
      -    }
      -}
      -</script>
      -
      - -Try this: - - https://googledrive.com/host/0B1di2XiBBfacMnhRRkI1YlotUEk/requestquota.html - -

      OnProtocolExecution

      - -Try this: - - magnet:?xt=urn:btih:a4224b45b27f436374391379cc5c7e629e2e5189 - -

      _OnBeforePluginLoad

      - -Try OnBeforePluginLoad() with Flash: - - http://www.adobe.com/software/flash/about/ - -

      _OnCertificateError

      - - -The url below won't be allowed. Click twice "Back" from context menu to return back -here after visiting the url:
      - - https://tv.eurosport.com/do-not-allow -
      - -This url will be allowed:
      - - https://tv.eurosport.com/ - -

      OnRendererProcessTerminated

      - -Try to terminate the "subprocess.exe" renderer process through -task manager. - -

      OnPluginCrashed

      - -No test for that yet. - - - - - - -

      Cookie tests

      - -See messages in the console. - -

      GetCookieManager

      - - - -RequestHandler.GetCookieManager() - an example of having an unique -cookie manager for each browser. -
        -
      1. Visit the url below and set some cookies. Use "Back" from - context menu to get back here (you might have to click "Back" - multiple times).
        - Visit it in the current browser:
        - - http://www.html-kit.com/tools/cookietester/ -
        - Or visit it in a js popup:
        - - javascript:window.open('http://www.html-kit.com/tools/cookietester/') -
      2. -
      3. Open cookietester in a popup:
        - - javascript:external.CreateAnotherBrowser('http://www.html-kit.com/tools/cookietester/') -
      4. -
      - -

      -Popup browsers created javascript's window.open share -the same renderer process and request context. If you want -to have separate cookie managers for popups created using -window.open then you have to implement the -LifespanHandler.`OnBeforePopup` callback. Return True in that -callback to cancel popup creation and instead create the -window on your own and embed browser in it. The CreateAnotherBrowser() -function from the wxpython example does that. -

      - -

      VisitAllCookies

      - -Visit all cookies: -external.VisitAllCookies() -

      - -Note: visit some http:// webpage first, otherwise cookie manager is not -yet created. -
      - -

      VisitUrlCookies

      - -Visit a subset of cookies for the given url: - - external.VisitUrlCookies("http://www.html-kit.com/tools/cookietester/") -
      - -

      SetCookie

      - -Set a cookie: -external.SetCookie() -
      - -

      DeleteCookies

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

      Load Handler

      - -See messages in the console during loading of a webpage. - -

      OnLoadingStateChange

      - - -

      OnLoadStart

      - - -

      OnLoadEnd

      - - -

      OnLoadError

      - -Try this: - - http://www.non-existent.nono/ -

      - -Note: after you see the custom error message you have to hit -twice the Back from the context menu, to get back to this page. - - - - - - -

      Javascript Dialog Handler

      - -See messages in the console. - -

      OnJavascriptDialog

      - - - alert('Test js dialog handler') - - -

      OnBeforeUnloadJavascriptDialog

      - - - -
      <script>
      -function TestOnBeforeUnloadJavascriptDialog() {
      -    window.onbeforeunload = function() {
      -        return 'Testing the OnBeforeUnloadJavascriptDialog() callback';
      -    }
      -    location.href = "wxpython.html";
      -}
      -</script>
      -
      - - - TestOnBeforeUnloadJavascriptDialog() - - -

      OnResetJavascriptDialogState

      - - -

      OnJavascriptDialogClosed

      - - - - - - - -

      Other tests

      - -

      HTTPS caching with SSL certificate errors

      -Set ApplicationSettings["ignore_certificate_errors"] to True. - - - - - - - - - - - - - diff --git a/src/mac/binaries_64bit/wxpython.py b/src/mac/binaries_64bit/wxpython.py deleted file mode 100644 index bdcca1ce3..000000000 --- a/src/mac/binaries_64bit/wxpython.py +++ /dev/null @@ -1,851 +0,0 @@ -# An example of embedding CEF browser in wxPython on Mac. -# Tested with wxPython3.0-osx-3.0.2.0-cocoa-py2.7.dmg which -# was downloaded from the wxpython.org website. - -# IMPORTANT - importing CEF Python -# -------------------------------------------------------------- -# The cefpython library must be the very first library imported. -# This is because CEF was compiled with the tcmalloc memory -# allocator which hooks globally and replaces the default -# malloc allocator. If memory was allocated using malloc and -# then freed using tcmalloc then this would result in random -# segmentation faults in an application. See Issue 155 which -# is to provide CEF builds on Mac with tcmalloc disabled: -# https://github.com/cztomczak/cefpython/issues/155 - -import ctypes, os, sys -libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)),\ - 'libcef.dylib') -if os.path.exists(libcef_so): - # Import a local module - ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import an installed package - from cefpython3 import cefpython - -import wx -import time -import re -import uuid -import platform -import inspect -import struct - -g_applicationSettings = None -g_browserSettings = None -g_switches = None -g_countWindows = 0 - -# Which method to use for message loop processing. -# EVT_IDLE - wx application has priority (default) -# EVT_TIMER - cef browser has priority -# It seems that Flash content behaves better when using a timer. -# IMPORTANT! On Linux EVT_IDLE does not work, the events seems to -# be propagated only when you move your mouse, which is not the -# expected behavior, it is recommended to use EVT_TIMER on Linux, -# so set this value to False. -USE_EVT_IDLE = False - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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" (os._exit()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("[wxpython.py] WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainFrame(wx.Frame): - browser = None - mainPanel = None - clientHandler = None - javascriptExternal = None - - def __init__(self, url=None): - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, - title='wxPython CEF 3 example', size=(800,600)) - - global g_countWindows - g_countWindows += 1 - - if not url: - url = "file://"+GetApplicationPath("wxpython.html") - # Test hash in url. - # url += "#test-hash" - - self.CreateMenu() - - # Cannot attach browser to the main frame as this will cause - # the menu not to work. - # -- - # You also have to set the wx.WANTS_CHARS style for - # all parent panels/controls, if it's deeply embedded. - self.mainPanel = wx.Panel(self, style=wx.WANTS_CHARS) - - # Global client callbacks must be set before browser is created. - self.clientHandler = ClientHandler() - cefpython.SetGlobalClientCallback("OnCertificateError", - self.clientHandler._OnCertificateError) - cefpython.SetGlobalClientCallback("OnBeforePluginLoad", - self.clientHandler._OnBeforePluginLoad) - cefpython.SetGlobalClientCallback("OnAfterCreated", - self.clientHandler._OnAfterCreated) - - windowInfo = cefpython.WindowInfo() - (width, height) = self.mainPanel.GetClientSizeTuple() - windowInfo.SetAsChild(self.mainPanel.GetHandle(), - [0, 0, width, height]) - # Linux requires adding "file://" for local files, - # otherwise /home/some will be replaced as http://home/some - self.browser = cefpython.CreateBrowserSync( - windowInfo, - # If there are problems with Flash you can disable it here, - # by disabling all plugins. - browserSettings=g_browserSettings, - navigateUrl=url) - - self.clientHandler.mainBrowser = self.browser - self.browser.SetClientHandler(self.clientHandler) - - jsBindings = cefpython.JavascriptBindings( - bindToFrames=False, bindToPopups=True) - jsBindings.SetFunction("PyPrint", PyPrint) - jsBindings.SetProperty("pyProperty", "This was set in Python") - jsBindings.SetProperty("pyConfig", ["This was set in Python", - {"name": "Nested dictionary", "isNested": True}, - [1,"2", None]]) - self.javascriptExternal = JavascriptExternal(self.browser) - jsBindings.SetObject("external", self.javascriptExternal) - jsBindings.SetProperty("sources", GetSources()) - self.browser.SetJavascriptBindings(jsBindings) - - self.Bind(wx.EVT_CLOSE, self.OnClose) - if USE_EVT_IDLE: - # Bind EVT_IDLE only for the main application frame. - self.Bind(wx.EVT_IDLE, self.OnIdle) - - def CreateMenu(self): - filemenu = wx.Menu() - filemenu.Append(1, "Open") - exit = filemenu.Append(2, "Exit") - self.Bind(wx.EVT_MENU, self.OnClose, exit) - aboutmenu = wx.Menu() - aboutmenu.Append(1, "CEF Python") - menubar = wx.MenuBar() - menubar.Append(filemenu,"&File") - menubar.Append(aboutmenu, "&About") - self.SetMenuBar(menubar) - - def OnClose(self, event): - # Remove all CEF browser references so that browser is closed - # cleanly. Otherwise there may be issues for example with cookies - # not being flushed to disk when closing app immediately - # (Issue 158). - del self.javascriptExternal.mainBrowser - del self.clientHandler.mainBrowser - del self.browser - - # Destroy wx frame, this will complete the destruction of CEF browser - self.Destroy() - - # In wx.chromectrl calling browser.CloseBrowser and/or self.Destroy - # may cause crashes when embedding multiple browsers in tab - # (Issue 107). In such case instead of calling CloseBrowser/Destroy - # try this code: - # | self.browser.ParentWindowWillClose() - # | event.Skip() - - global g_countWindows - g_countWindows -= 1 - if g_countWindows == 0: - # On Win/Linux the call to cefpython.Shutdown() is after - # app.MainLoop() returns, but on Mac it needs to be here. - cefpython.Shutdown() - print("[wxpython.py] OnClose: Exiting") - wx.GetApp().Exit() - - def OnIdle(self, event): - cefpython.MessageLoopWork() - -def PyPrint(message): - print("[wxpython.py] PyPrint: "+message) - -class JavascriptExternal: - mainBrowser = None - stringVisitor = None - - def __init__(self, mainBrowser): - self.mainBrowser = mainBrowser - - def GoBack(self): - self.mainBrowser.GoBack() - - def GoForward(self): - self.mainBrowser.GoForward() - - def CreateAnotherBrowser(self, url=None): - """ - TODO: There are errors in the console when closing the window: - >> Check failed: window - >> Gdk: _gdk_window_destroy_hierarchy: assertion `GDK_IS_WINDOW\ - >> (window)' failed - >> GLib-GObject: g_object_unref: assertion `G_IS_OBJECT (object)' failed - """ - frame = MainFrame(url=url) - frame.Show() - - def Print(self, message): - print("[wxpython.py] Print: "+message) - - def TestAllTypes(self, *args): - print("[wxpython.py] TestAllTypes: "+str(args)) - - def ExecuteFunction(self, *args): - self.mainBrowser.GetMainFrame().ExecuteFunction(*args) - - def TestJSCallback(self, jsCallback): - print("[wxpython.py] jsCallback.GetFunctionName() = %s"\ - % jsCallback.GetFunctionName()) - print("[wxpython.py] jsCallback.GetFrame().GetIdentifier() = %s" % \ - jsCallback.GetFrame().GetIdentifier()) - jsCallback.Call("This message was sent from python using js callback") - - def TestJSCallbackComplexArguments(self, jsObject): - jsCallback = jsObject["myCallback"]; - jsCallback.Call(1, None, 2.14, "string", ["list", ["nested list", \ - {"nested object":None}]], \ - {"nested list next":[{"deeply nested object":1}]}) - - def TestPythonCallback(self, jsCallback): - jsCallback.Call(self.PyCallback) - - def PyCallback(self, *args): - message = "PyCallback() was executed successfully! "\ - "Arguments: %s" % str(args) - print("[wxpython.py] "+message) - self.mainBrowser.GetMainFrame().ExecuteJavascript( - "window.alert(\"%s\")" % message) - - def GetSource(self): - # Must keep a strong reference to the StringVisitor object - # during the visit. - self.stringVisitor = StringVisitor() - self.mainBrowser.GetMainFrame().GetSource(self.stringVisitor) - - def GetText(self): - # Must keep a strong reference to the StringVisitor object - # during the visit. - self.stringVisitor = StringVisitor() - self.mainBrowser.GetMainFrame().GetText(self.stringVisitor) - - def ShowDevTools(self): - print("[wxpython.py] external.ShowDevTools called") - self.mainBrowser.ShowDevTools() - - # ------------------------------------------------------------------------- - # Cookies - # ------------------------------------------------------------------------- - cookieVisitor = None - - def VisitAllCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.VisitAllCookies(self.cookieVisitor) - - def VisitUrlCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.VisitUrlCookies( - "http://www.html-kit.com/tools/cookietester/", - False, self.cookieVisitor) - # .www.html-kit.com - - def SetCookie(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - "the cookietester website first and create some cookies") - return - cookie = cefpython.Cookie() - cookie.SetName("Created_Via_Python") - cookie.SetValue("yeah really") - cookieManager.SetCookie("http://www.html-kit.com/tools/cookietester/", - cookie) - print("\n[wxpython.py] Cookie created! Visit html-kit cookietester to"\ - " see it") - - def DeleteCookies(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.DeleteCookies( - "http://www.html-kit.com/tools/cookietester/", - "Created_Via_Python") - print("\n[wxpython.py] Cookie deleted! Visit html-kit cookietester "\ - "to see the result") - -class StringVisitor: - def Visit(self, string): - print("\n[wxpython.py] StringVisitor.Visit(): string:") - print("--------------------------------") - print(string) - print("--------------------------------") - -class CookieVisitor: - def Visit(self, cookie, count, total, deleteCookie): - if count == 0: - print("\n[wxpython.py] CookieVisitor.Visit(): total cookies: %s"\ - % total) - print("\n[wxpython.py] CookieVisitor.Visit(): cookie:") - print(" "+str(cookie.Get())) - # True to continue visiting cookies - return True - -class ClientHandler: - mainBrowser = None # May be None for global client callbacks. - - def __init__(self): - pass - - # ------------------------------------------------------------------------- - # DisplayHandler - # ------------------------------------------------------------------------- - - def OnAddressChange(self, browser, frame, url): - print("[wxpython.py] DisplayHandler::OnAddressChange()") - print(" url = %s" % url) - - def OnTitleChange(self, browser, title): - print("[wxpython.py] DisplayHandler::OnTitleChange()") - print(" title = %s" % title) - - def OnTooltip(self, browser, textOut): - # OnTooltip not yet implemented (both Linux and Windows), - # will be fixed in next CEF release, see Issue 783: - # https://code.google.com/p/chromiumembedded/issues/detail?id=783 - print("[wxpython.py] DisplayHandler::OnTooltip()") - print(" text = %s" % textOut[0]) - - statusMessageCount = 0 - def OnStatusMessage(self, browser, value): - if not value: - # Do not notify in the console about empty statuses. - return - self.statusMessageCount += 1 - if self.statusMessageCount > 3: - # Do not spam too much. - return - print("[wxpython.py] DisplayHandler::OnStatusMessage()") - print(" value = %s" % value) - - def OnConsoleMessage(self, browser, message, source, line): - print("[wxpython.py] DisplayHandler::OnConsoleMessage()") - print(" message = %s" % message) - print(" source = %s" % source) - print(" line = %s" % line) - - # ------------------------------------------------------------------------- - # KeyboardHandler - # ------------------------------------------------------------------------- - - def OnPreKeyEvent(self, browser, event, eventHandle, - isKeyboardShortcutOut): - print("[wxpython.py] KeyboardHandler::OnPreKeyEvent()") - - def OnKeyEvent(self, browser, event, eventHandle): - if event["type"] == cefpython.KEYEVENT_KEYUP: - # OnKeyEvent is called twice for F5/Esc keys, with event - # type KEYEVENT_RAWKEYDOWN and KEYEVENT_KEYUP. - # Normal characters a-z should have KEYEVENT_CHAR. - return False - print("[wxpython.py] KeyboardHandler::OnKeyEvent()") - print(" type=%s" % event["type"]) - print(" modifiers=%s" % event["modifiers"]) - print(" windows_key_code=%s" % event["windows_key_code"]) - print(" native_key_code=%s" % event["native_key_code"]) - print(" is_system_key=%s" % event["is_system_key"]) - print(" character=%s" % event["character"]) - print(" unmodified_character=%s" % event["unmodified_character"]) - print(" focus_on_editable_field=%s"\ - % event["focus_on_editable_field"]) - if platform.system() == "Linux": - # F5 - if event["native_key_code"] == 71: - print("[wxpython.py] F5 pressed, calling"\ - " browser.ReloadIgnoreCache()") - browser.ReloadIgnoreCache() - return True - # Escape - if event["native_key_code"] == 9: - print("[wxpython.py] Esc pressed, calling browser.StopLoad()") - browser.StopLoad() - return True - # F12 - if event["native_key_code"] == 96: - print("[wxpython.py] F12 pressed, calling"\ - " browser.ShowDevTools()") - browser.ShowDevTools() - return True - elif platform.system() == "Windows": - # F5 todo - # Escape todo - pass - elif platform.system() == "Darwin": - # Cmd+Opt+I - if event["modifiers"] == 136 and event["character"] == 94: - browser.ShowDevTools() - return True - # F5 - if event["modifiers"] == 0 and event["character"] == 63240: - browser.ReloadIgnoreCache() - return True - # Esc - if event["modifiers"] == 0 and event["character"] == 27: - browser.StopLoad() - return True - return False - - # ------------------------------------------------------------------------- - # RequestHandler - # ------------------------------------------------------------------------- - - def OnBeforeBrowse(self, browser, frame, request, isRedirect): - print("[wxpython.py] RequestHandler::OnBeforeBrowse()") - print(" url = %s" % request.GetUrl()[:100]) - return False - - def OnBeforeResourceLoad(self, browser, frame, request): - print("[wxpython.py] RequestHandler::OnBeforeResourceLoad()") - print(" url = %s" % request.GetUrl()[:100]) - return False - - def OnResourceRedirect(self, browser, frame, oldUrl, newUrlOut, request): - print("[wxpython.py] RequestHandler::OnResourceRedirect()") - print(" old url = %s" % oldUrl[:100]) - print(" new url = %s" % newUrlOut[0][:100]) - - def GetAuthCredentials(self, browser, frame, isProxy, host, port, realm, - scheme, callback): - # This callback is called on the IO thread, thus print messages - # may not be visible. - print("[wxpython.py] RequestHandler::GetAuthCredentials()") - print(" host = %s" % host) - print(" realm = %s" % realm) - callback.Continue(username="test", password="test") - return True - - def OnQuotaRequest(self, browser, originUrl, newSize, callback): - print("[wxpython.py] RequestHandler::OnQuotaRequest()") - print(" origin url = %s" % originUrl) - print(" new size = %s" % newSize) - callback.Continue(True) - return True - - def GetCookieManager(self, browser, mainUrl): - # Create unique cookie manager for each browser. - # You must set the "unique_request_context_per_browser" - # application setting to True for the cookie manager - # to work. - # Return None to have one global cookie manager for - # all CEF browsers. - if not browser: - # The browser param may be empty in some exceptional - # case, see docs. - return None - cookieManager = browser.GetUserData("cookieManager") - if cookieManager: - return cookieManager - else: - print("[wxpython.py] RequestHandler::GetCookieManager():"\ - " created cookie manager") - cookieManager = cefpython.CookieManager.CreateManager("") - if "cache_path" in g_applicationSettings: - path = g_applicationSettings["cache_path"] - # path = os.path.join(path, "cookies_browser_{}".format( - # browser.GetIdentifier())) - cookieManager.SetStoragePath(path) - browser.SetUserData("cookieManager", cookieManager) - return cookieManager - - def OnProtocolExecution(self, browser, url, allowExecutionOut): - # There's no default implementation for OnProtocolExecution on Linux, - # you have to make OS system call on your own. You probably also need - # to use LoadHandler::OnLoadError() when implementing this on Linux. - print("[wxpython.py] RequestHandler::OnProtocolExecution()") - print(" url = %s" % url) - if url.startswith("magnet:"): - print("[wxpython.py] Magnet link allowed!") - allowExecutionOut[0] = True - - def _OnBeforePluginLoad(self, browser, mimeType, pluginUrl, topOriginUrl, - info): - # This is a global callback set using SetGlobalClientCallback(). - # Plugins are loaded on demand, only when website requires it, - # the same plugin may be called multiple times. - # This callback is called on various threads, thus print messages - # may not be visible. - print("[wxpython.py] RequestHandler::_OnBeforePluginLoad()") - print(" mimeType = %s" % mimeType) - print(" pluginUrl = %s" % pluginUrl) - print(" topOriginUrl = %s" % topOriginUrl) - print(" info.GetName() = %s" % info.GetName()) - print(" info.GetPath() = %s" % info.GetPath()) - print(" info.GetVersion() = %s" % info.GetVersion()) - print(" info.GetDescription() = %s" % info.GetDescription()) - # False to allow, True to block plugin. - return False - - def _OnCertificateError(self, certError, requestUrl, callback): - # This is a global callback set using SetGlobalClientCallback(). - print("[wxpython.py] RequestHandler::_OnCertificateError()") - print(" certError = %s" % certError) - print(" requestUrl = %s" % requestUrl) - if requestUrl.startswith( - "https://tv.eurosport.com/do-not-allow"): - print(" Not allowed!") - return False - if requestUrl.startswith( - "https://tv.eurosport.com/"): - print(" Allowed!") - callback.Continue(True) - return True - return False - - def OnRendererProcessTerminated(self, browser, status): - print("[wxpython.py] RequestHandler::OnRendererProcessTerminated()") - statuses = { - cefpython.TS_ABNORMAL_TERMINATION: "TS_ABNORMAL_TERMINATION", - cefpython.TS_PROCESS_WAS_KILLED: "TS_PROCESS_WAS_KILLED", - cefpython.TS_PROCESS_CRASHED: "TS_PROCESS_CRASHED" - } - statusName = "Unknown" - if status in statuses: - statusName = statuses[status] - print(" status = %s" % statusName) - - def OnPluginCrashed(self, browser, pluginPath): - print("[wxpython.py] RequestHandler::OnPluginCrashed()") - print(" plugin path = %s" % pluginPath) - - # ------------------------------------------------------------------------- - # LoadHandler - # ------------------------------------------------------------------------- - - def OnLoadingStateChange(self, browser, isLoading, canGoBack, - canGoForward): - print("[wxpython.py] LoadHandler::OnLoadingStateChange()") - print(" isLoading = %s, canGoBack = %s, canGoForward = %s" \ - % (isLoading, canGoBack, canGoForward)) - - def OnLoadStart(self, browser, frame): - print("[wxpython.py] LoadHandler::OnLoadStart()") - print(" frame url = %s" % frame.GetUrl()[:100]) - - def OnLoadEnd(self, browser, frame, httpStatusCode): - print("[wxpython.py] LoadHandler::OnLoadEnd()") - print(" frame url = %s" % frame.GetUrl()[:100]) - # For file:// urls the status code = 0 - print(" http status code = %s" % httpStatusCode) - # Tests for the Browser object methods - self._Browser_LoadUrl(browser) - - def _Browser_LoadUrl(self, browser): - if browser.GetUrl() == "data:text/html,Test#Browser.LoadUrl": - browser.LoadUrl("file://"+GetApplicationPath("wxpython.html")) - - def OnLoadError(self, browser, frame, errorCode, errorTextList, failedUrl): - print("[wxpython.py] LoadHandler::OnLoadError()") - print(" frame url = %s" % frame.GetUrl()[:100]) - print(" error code = %s" % errorCode) - print(" error text = %s" % errorTextList[0]) - print(" failed url = %s" % failedUrl) - # Handle ERR_ABORTED error code, to handle the following cases: - # 1. Esc key was pressed which calls browser.StopLoad() in OnKeyEvent - # 2. Download of a file was aborted - if errorCode == cefpython.ERR_ABORTED: - print("[wxpython.py] LoadHandler::OnLoadError(): Ignoring load"\ - " error: Esc was pressed or file download was aborted") - return; - customErrorMessage = "My custom error message!" - frame.LoadUrl("data:text/html,%s" % customErrorMessage) - - # ------------------------------------------------------------------------- - # LifespanHandler - # ------------------------------------------------------------------------- - - # ** This callback is executed on the IO thread ** - # Empty place-holders: popupFeatures, client. - def OnBeforePopup(self, browser, frame, targetUrl, targetFrameName, - targetDisposition, userGesture, - popupFeatures, windowInfo, client, browserSettings, - noJavascriptAccess): - print("[wxpython.py] LifespanHandler::OnBeforePopup()") - print(" targetUrl = %s" % targetUrl) - # Custom browser settings for popups: - # > browserSettings[0] = {"plugins_disabled": True} - # Set WindowInfo object: - # > windowInfo[0] = cefpython.WindowInfo() - allowPopups = True - return not allowPopups - - def _OnAfterCreated(self, browser): - # This is a global callback set using SetGlobalClientCallback(). - print("[wxpython.py] LifespanHandler::_OnAfterCreated()") - print(" browserId=%s" % browser.GetIdentifier()) - - def DoClose(self, browser): - print("[wxpython.py] LifespanHandler::DoClose()") - print(" browserId=%s" % browser.GetIdentifier()) - - def OnBeforeClose(self, browser): - print("[wxpython.py] LifespanHandler::OnBeforeClose") - print(" browserId=%s" % browser.GetIdentifier()) - - # ------------------------------------------------------------------------- - # JavascriptDialogHandler - # ------------------------------------------------------------------------- - - def OnJavascriptDialog(self, browser, originUrl, dialogType, - messageText, defaultPromptText, callback, - suppressMessage): - print("[wxpython.py] JavascriptDialogHandler::OnJavascriptDialog()") - print(" originUrl="+originUrl) - print(" dialogType="+str(dialogType)) - print(" messageText="+messageText) - print(" defaultPromptText="+defaultPromptText) - # If you want to suppress the javascript dialog: - # suppressMessage[0] = True - return False - - def OnBeforeUnloadJavascriptDialog(self, browser, messageText, isReload, - callback): - print("[wxpython.py] OnBeforeUnloadJavascriptDialog()") - print(" messageText="+messageText) - print(" isReload="+str(isReload)) - # Return True if the application will use a custom dialog: - # callback.Continue(allow=True, userInput="") - # return True - return False - - def OnResetJavascriptDialogState(self, browser): - print("[wxpython.py] OnResetDialogState()") - - def OnJavascriptDialogClosed(self, browser): - print("[wxpython.py] OnDialogClosed()") - - -class MyApp(wx.App): - timer = None - timerID = 1 - timerCount = 0 - - def OnInit(self): - if not USE_EVT_IDLE: - self.CreateTimer() - frame = MainFrame() - self.SetTopWindow(frame) - frame.Show() - return True - - def CreateTimer(self): - # See "Making a render loop": - # http://wiki.wxwidgets.org/Making_a_render_loop - # Another approach is to use EVT_IDLE in MainFrame, - # see which one fits you better. - self.timer = wx.Timer(self, self.timerID) - self.timer.Start(10) # 10ms - wx.EVT_TIMER(self, self.timerID, self.OnTimer) - - def OnTimer(self, event): - self.timerCount += 1 - # print("[wxpython.py] OnTimer() %d" % self.timerCount) - cefpython.MessageLoopWork() - - def OnExit(self): - # When app.MainLoop() returns, MessageLoopWork() should - # not be called anymore. - if not USE_EVT_IDLE: - self.timer.Stop() - -def GetSources(): - # Get sources of all python functions and methods from this file. - # This is to provide sources preview to wxpython.html. - # The dictionary of functions is binded to "window.sources". - thisModule = sys.modules[__name__] - functions = inspect.getmembers(thisModule, inspect.isfunction) - classes = inspect.getmembers(thisModule, inspect.isclass) - sources = {} - for funcTuple in functions: - sources[funcTuple[0]] = inspect.getsource(funcTuple[1]) - for classTuple in classes: - className = classTuple[0] - classObject = classTuple[1] - methods = inspect.getmembers(classObject) - for methodTuple in methods: - try: - sources[methodTuple[0]] = inspect.getsource(\ - methodTuple[1]) - except: - pass - return sources - -if __name__ == '__main__': - print('[wxpython.py] architecture=%s-bit' % (8 * struct.calcsize("P"))) - print('[wxpython.py] wx.version=%s' % wx.version()) - - # Intercept python exceptions. Exit app immediately when exception - # happens on any of the threads. - sys.excepthook = ExceptHook - - # Application settings - g_applicationSettings = { - # Disk cache - # "cache_path": "webcache/", - - # CEF Python debug messages in console and in log_file - "debug": True, - # Set it to LOGSEVERITY_VERBOSE for more details - "log_severity": cefpython.LOGSEVERITY_INFO, - # Set to "" to disable logging to a file - "log_file": GetApplicationPath("debug.log"), - - # "resources_dir_path" must be set on Mac, "locales_dir_path" not. - # You must also set "locale_pak" using command line switch. - "resources_dir_path": cefpython.GetModuleDirectory()+"/Resources", - # The "subprocess" executable that launches the Renderer - # and GPU processes among others. You may rename that - # executable if you like. - "browser_subprocess_path": "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess"), - - # This option is required for the GetCookieManager callback - # to work. It affects renderer processes, when this option - # is set to True. It will force a separate renderer process - # for each browser created using CreateBrowserSync. - "unique_request_context_per_browser": True, - - # Downloads are handled automatically. A default SaveAs file - # dialog provided by OS will be displayed. - "downloads_enabled": True, - - # Remote debugging port, required for Developer Tools support. - # A value of 0 will generate a random port. To disable devtools - # support set it to -1. - "remote_debugging_port": 0, - - # Mouse context menu - "context_menu": { - "enabled": True, - "navigation": True, # Back, Forward, Reload - "print": True, - "view_source": True, - "external_browser": True, # Open in external browser - "devtools": True, # Developer Tools - }, - - # See also OnCertificateError which allows you to ignore - # certificate errors for specific websites. - "ignore_certificate_errors": False, - } - - # Browser settings. You may have different settings for each - # browser, see the call to CreateBrowserSync. - g_browserSettings = { - # "plugins_disabled": True, - # "file_access_from_file_urls_allowed": True, - # "universal_access_from_file_urls_allowed": True, - } - - # Command line switches set programmatically - g_switches = { - # On Mac it is required to provide path to a specific - # locale.pak file. On Win/Linux you only specify the - # ApplicationSettings.locales_dir_path option. - "locale_pak": cefpython.GetModuleDirectory() - +"/Resources/en.lproj/locale.pak", - - # "proxy-server": "socks5://127.0.0.1:8888", - # "no-proxy-server": "", - # "enable-media-stream": "", - # "remote-debugging-port": "12345", - # "disable-gpu": "", - # "--invalid-switch": "" -> Invalid switch name - } - - cefpython.Initialize(g_applicationSettings, g_switches) - - app = MyApp(False) - app.MainLoop() - - # Let wx.App destructor do the cleanup before calling - # cefpython.Shutdown(). This is to ensure reliable CEF shutdown. - del app - - # On Mac cefpython.Shutdown() is called in MainFrame.OnClose, - # followed by wx.GetApp.Exit(). diff --git a/src/mac/compile.py b/src/mac/compile.py deleted file mode 100644 index 2d8a048d7..000000000 --- a/src/mac/compile.py +++ /dev/null @@ -1,181 +0,0 @@ -import sys -import os -import glob -import shutil -import subprocess -import platform -import stat -import re - -# This will not show "Segmentation fault" error message: -# | subprocess.call(["python", "./wxpython.py"]) -# You need to call it with shell=True for this kind of -# error message to be shown: -# | subprocess.call("python wxpython.py", shell=True) - -# How to debug: -# 1. Install "python-dbg" package -# 2. Install "python-wxgtk2.8-dbg" package -# 3. Run "python compile.py debug" -# 4. In cygdb type "cy run" -# 5. To display debug backtrace type "cy bt" -# 6. More commands: http://docs.cython.org/src/userguide/debugging.html - -if len(sys.argv) > 1 and "--debug" in sys.argv: - DEBUG = True - print("DEBUG mode On") -else: - DEBUG = False - -if len(sys.argv) > 1 and re.search(r"^\d+\.\d+$", sys.argv[1]): - VERSION = sys.argv[1] -else: - print("[compile.py] ERROR: expected first argument to be version number") - print(" Allowed version format: \\d+\.\\d+") - sys.exit(1) - -print("VERSION=%s"%VERSION) - -BITS = platform.architecture()[0] -assert (BITS == "32bit" or BITS == "64bit") -PYTHON_CMD = "python" -if sys.maxint == 2147483647: - BITS = "32bit" - PYTHON_CMD = "arch -i386 python" - -if BITS == "32bit": - if "i386" not in os.getenv("ARCHFLAGS", ""): - raise Exception("Detected Python 32bit, but ARCHFLAGS is not i386") - if "i386" not in os.getenv("CEF_CCFLAGS", ""): - raise Exception("Detected Python 32bit, but CEF_CCFLAGS is not i386") -elif BITS == "64bit": - if "x86_64" not in os.getenv("ARCHFLAGS", ""): - raise Exception("Detected Python 64bit, but ARCHFLAGS is not x86_64") - if "x86_64" not in os.getenv("CEF_CCFLAGS", ""): - raise Exception("Detected Python 64bit, but CEF_CCFLAGS is not x86_64") - -PYVERSION = str(sys.version_info[0])+str(sys.version_info[1]) -print("PYVERSION = %s" % PYVERSION) -print("BITS = %s" % BITS) - -os.environ["CC"] = "gcc" -os.environ["CXX"] = "g++" - -print("Compiling C++ projects") - -# Need to allow continuing even when make fails, as it may -# fail because the "public" function declaration is not yet -# in "cefpython.h", but for it to be generated we need to run -# cython compiling, so in this case you continue even when make -# fails and then run the compile.py script again and this time -# make should succeed. - -os.chdir("./../cpp_utils/") -subprocess.call("rm -f *.o *.a", shell=True) - -ret = subprocess.call("make -f Makefile", shell=True) -if ret != 0: - what = raw_input("make failed, press 'y' to continue, 'n' to stop: ") - if what != "y": - sys.exit(1) - -os.chdir("./../client_handler/") -subprocess.call("rm -f *.o *.a", shell=True) - -ret = subprocess.call("make -f Makefile", shell=True) -if ret != 0: - what = raw_input("make failed, press 'y' to continue, 'n' to stop: ") - if what != "y": - sys.exit(1) - -os.chdir("./../subprocess/") -subprocess.call("rm -f *.o *.a", shell=True) -subprocess.call("rm -f subprocess", shell=True) - -ret = subprocess.call("make -f Makefile-libcefpythonapp", shell=True) -if ret != 0: - what = raw_input("make failed, press 'y' to continue, 'n' to stop: ") - if what != "y": - sys.exit(1) - -ret = subprocess.call("make -f Makefile", shell=True) -if ret != 0: - what = raw_input("make failed, press 'y' to continue, 'n' to stop: ") - if what != "y": - sys.exit(1) -subprocess_exe = "./../mac/binaries_%s/subprocess" % (BITS) -if os.path.exists("./subprocess"): - # .copy() will also copy Permission bits - shutil.copy("./subprocess", subprocess_exe) - -# os.chdir("./../v8function_handler/") -# ret = subprocess.call("make -f Makefile", shell=True) -# if ret != 0: -# what = raw_input("make failed, press 'y' to continue, 'n' to stop: ") -# if what != "y": -# sys.exit(1) - -os.chdir("./../mac/") - -try: - os.remove("./binaries_%s/cefpython_py%s.so" % (BITS, PYVERSION)) -except OSError: - pass - -os.system("rm ./setup/cefpython_py*.so") - -pyx_files = glob.glob("./setup/*.pyx") -for f in pyx_files: - os.remove(f) - -try: - shutil.rmtree("./setup/build") -except OSError: - pass - -os.chdir("./setup") - -ret = subprocess.call(PYTHON_CMD+" fix_pyx_files.py", shell=True) -if ret != 0: - sys.exit("ERROR") - -# Create __version__.pyx after fix_pyx_files.py was called, -# as that script deletes old pyx files before copying new ones. -print("Creating __version__.pyx file") -with open("__version__.pyx", "w") as fo: - fo.write('__version__ = "{}"\n'.format(VERSION)) - -if DEBUG: - ret = subprocess.call(PYTHON_CMD+"-dbg setup.py build_ext --inplace" - " --cython-gdb", shell=True) -else: - ret = subprocess.call(PYTHON_CMD+" setup.py build_ext --inplace", shell=True) - -if DEBUG: - shutil.rmtree("./../binaries_%s/cython_debug/" % BITS, ignore_errors=True) - shutil.copytree("./cython_debug/", "./../binaries_%s/cython_debug/" % BITS) - -os.chdir("../") - -oldpyxfiles = glob.glob("./setup/*.pyx") -print("Removing old pyx files in /setup/: %s" % oldpyxfiles) -for pyxfile in oldpyxfiles: - if os.path.exists(pyxfile): - os.remove(pyxfile) - -if ret != 0: - sys.exit("ERROR") - -exitcode = os.system("mv ./setup/cefpython_py{0}*.so" - " ./binaries_{1}/cefpython_py{0}.so" - .format(PYVERSION, BITS)) -if exitcode: - raise RuntimeError("Failed to move the cefpython module") - -print("DONE") - -os.chdir("./binaries_%s" % BITS) -if DEBUG: - subprocess.call("cygdb . --args python-dbg wxpython.py", shell=True) -else: - subprocess.call(PYTHON_CMD+" wxpython.py", shell=True) diff --git a/src/linux/binaries_32bit/prism.css b/src/mac/deprecated_64bit/prism.css similarity index 100% rename from src/linux/binaries_32bit/prism.css rename to src/mac/deprecated_64bit/prism.css diff --git a/src/linux/binaries_32bit/prism.js b/src/mac/deprecated_64bit/prism.js similarity index 100% rename from src/linux/binaries_32bit/prism.js rename to src/mac/deprecated_64bit/prism.js diff --git a/src/mac/binaries_32bit/wxpython.html b/src/mac/deprecated_64bit/wxpython.html similarity index 100% rename from src/mac/binaries_32bit/wxpython.html rename to src/mac/deprecated_64bit/wxpython.html diff --git a/src/mac/binaries_32bit/wxpython.py b/src/mac/deprecated_64bit/wxpython.py similarity index 100% rename from src/mac/binaries_32bit/wxpython.py rename to src/mac/deprecated_64bit/wxpython.py diff --git a/src/mac/installer/make-setup.py b/src/mac/installer/make-setup.py index 81a70825e..61a7e5932 100644 --- a/src/mac/installer/make-setup.py +++ b/src/mac/installer/make-setup.py @@ -101,8 +101,8 @@ def main(): f.write(SETUP_CONTENT) # Create fat binaries if both 32bit and 64bit are available - b32 = os.path.abspath(installer_dir+"/../binaries_32bit/") - b64 = os.path.abspath(installer_dir+"/../binaries_64bit/") + b32 = os.path.abspath(installer_dir+"/../deprecated_32bit/") + b64 = os.path.abspath(installer_dir+"/../deprecated_64bit/") bfat = os.path.abspath(installer_dir+"/binaries_fat/") binaries_dir = get_binaries_dir(b32, b64, bfat) print("Copying binaries to package dir") diff --git a/src/mac/mac32.sh b/src/mac/mac32.sh deleted file mode 100644 index 4d8b17092..000000000 --- a/src/mac/mac32.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -PATH=/usr/local/bin:$PATH -export PATH -alias python="arch -i386 python" - -CEF_CCFLAGS="-arch i386" -export CEF_CCFLAGS - -ARCHFLAGS="-arch i386" -export ARCHFLAGS - -export CC=gcc -export CXX=g++ diff --git a/src/mac/setup/.gitignore b/src/mac/setup/.gitignore deleted file mode 100644 index 67f1cf10a..000000000 --- a/src/mac/setup/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -build/ -cefpython.cpp -cython_debug/ -*.pyx -*.cpp -*.a diff --git a/src/mac/setup/cefpython.h b/src/mac/setup/cefpython.h deleted file mode 100644 index 2495aabbf..000000000 --- a/src/mac/setup/cefpython.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef __PYX_HAVE__cefpython_py27 -#define __PYX_HAVE__cefpython_py27 - - -#ifndef __PYX_HAVE_API__cefpython_py27 - -#ifndef __PYX_EXTERN_C - #ifdef __cplusplus - #define __PYX_EXTERN_C extern "C" - #else - #define __PYX_EXTERN_C extern - #endif -#endif - -__PYX_EXTERN_C DL_IMPORT(void) PyBrowser_ShowDevTools(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) PyTaskRunnable(int); -__PYX_EXTERN_C DL_IMPORT(void) V8ContextHandler_OnContextCreated(CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) V8ContextHandler_OnContextReleased(int, int64); -__PYX_EXTERN_C DL_IMPORT(void) V8FunctionHandler_Execute(CefRefPtr, CefRefPtr, CefString &, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) RemovePythonCallbacksForFrame(int); -__PYX_EXTERN_C DL_IMPORT(bool) ExecutePythonCallback(CefRefPtr, int, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) LifespanHandler_OnBeforePopup(CefRefPtr, CefRefPtr, CefString const &, CefString const &, int const , CefWindowInfo &, CefRefPtr &, CefBrowserSettings &, bool *); -__PYX_EXTERN_C DL_IMPORT(void) LifespanHandler_OnAfterCreated(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) LifespanHandler_DoClose(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) LifespanHandler_OnBeforeClose(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnAddressChange(CefRefPtr, CefRefPtr, CefString const &); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnTitleChange(CefRefPtr, CefString const &); -__PYX_EXTERN_C DL_IMPORT(bool) DisplayHandler_OnTooltip(CefRefPtr, CefString &); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnStatusMessage(CefRefPtr, CefString const &); -__PYX_EXTERN_C DL_IMPORT(bool) DisplayHandler_OnConsoleMessage(CefRefPtr, CefString const &, CefString const &, int); -__PYX_EXTERN_C DL_IMPORT(bool) KeyboardHandler_OnPreKeyEvent(CefRefPtr, CefKeyEvent const &, CefEventHandle, bool *); -__PYX_EXTERN_C DL_IMPORT(bool) KeyboardHandler_OnKeyEvent(CefRefPtr, CefKeyEvent const &, CefEventHandle); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnBeforeResourceLoad(CefRefPtr, CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnBeforeBrowse(CefRefPtr, CefRefPtr, CefRefPtr, bool); -__PYX_EXTERN_C DL_IMPORT(CefRefPtr) RequestHandler_GetResourceHandler(CefRefPtr, CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) RequestHandler_OnResourceRedirect(CefRefPtr, CefRefPtr, CefString const &, CefString &); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_GetAuthCredentials(CefRefPtr, CefRefPtr, bool, CefString const &, int, CefString const &, CefString const &, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnQuotaRequest(CefRefPtr, CefString const &, int64, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(CefRefPtr) RequestHandler_GetCookieManager(CefRefPtr, CefString const &); -__PYX_EXTERN_C DL_IMPORT(void) RequestHandler_OnProtocolExecution(CefRefPtr, CefString const &, bool &); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnBeforePluginLoad(CefRefPtr, CefString const &, CefString const &, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnCertificateError(int, CefString const &, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) RequestHandler_OnRendererProcessTerminated(CefRefPtr, enum cef_termination_status_t); -__PYX_EXTERN_C DL_IMPORT(void) RequestHandler_OnPluginCrashed(CefRefPtr, CefString const &); -__PYX_EXTERN_C DL_IMPORT(bool) CookieVisitor_Visit(int, CefCookie const &, int, int, bool &); -__PYX_EXTERN_C DL_IMPORT(void) StringVisitor_Visit(int, CefString const &); -__PYX_EXTERN_C DL_IMPORT(void) LoadHandler_OnLoadingStateChange(CefRefPtr, bool, bool, bool); -__PYX_EXTERN_C DL_IMPORT(void) LoadHandler_OnLoadStart(CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) LoadHandler_OnLoadEnd(CefRefPtr, CefRefPtr, int); -__PYX_EXTERN_C DL_IMPORT(void) LoadHandler_OnLoadError(CefRefPtr, CefRefPtr, enum cef_errorcode_t, CefString const &, CefString const &); -__PYX_EXTERN_C DL_IMPORT(void) BrowserProcessHandler_OnRenderProcessThreadCreated(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) BrowserProcessHandler_OnBeforeChildProcessLaunch(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetRootScreenRect(CefRefPtr, CefRect &); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetViewRect(CefRefPtr, CefRect &); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetScreenRect(CefRefPtr, CefRect &); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetScreenPoint(CefRefPtr, int, int, int &, int &); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetScreenInfo(CefRefPtr, CefScreenInfo &); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnPopupShow(CefRefPtr, bool); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnPopupSize(CefRefPtr, CefRect const &); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnPaint(CefRefPtr, cef_paint_element_type_t, std::vector &, void const *, int, int); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnCursorChange(CefRefPtr, CefCursorHandle); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnScrollOffsetChanged(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) ResourceHandler_ProcessRequest(int, CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) ResourceHandler_GetResponseHeaders(int, CefRefPtr, int64 &, CefString &); -__PYX_EXTERN_C DL_IMPORT(bool) ResourceHandler_ReadResponse(int, void *, int, int &, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) ResourceHandler_CanGetCookie(int, CefCookie const &); -__PYX_EXTERN_C DL_IMPORT(bool) ResourceHandler_CanSetCookie(int, CefCookie const &); -__PYX_EXTERN_C DL_IMPORT(void) ResourceHandler_Cancel(int); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnUploadProgress(int, CefRefPtr, uint64, uint64); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnDownloadProgress(int, CefRefPtr, uint64, uint64); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnDownloadData(int, CefRefPtr, void const *, size_t); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnRequestComplete(int, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) App_OnBeforeCommandLineProcessing_BrowserProcess(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) JavascriptDialogHandler_OnJavascriptDialog(CefRefPtr, CefString const &, CefString const &, enum cef_jsdialog_type_t, CefString const &, CefString const &, CefRefPtr, bool &); -__PYX_EXTERN_C DL_IMPORT(bool) JavascriptDialogHandler_OnBeforeUnloadJavascriptDialog(CefRefPtr, CefString const &, bool, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) JavascriptDialogHandler_OnResetJavascriptDialogState(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) JavascriptDialogHandler_OnJavascriptDialogClosed(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) cefpython_GetDebugOptions(bool *, std::string *); -__PYX_EXTERN_C DL_IMPORT(bool) ApplicationSettings_GetBool(char const *); -__PYX_EXTERN_C DL_IMPORT(bool) ApplicationSettings_GetBoolFromDict(char const *, char const *); -__PYX_EXTERN_C DL_IMPORT(std::string) ApplicationSettings_GetString(char const *); -__PYX_EXTERN_C DL_IMPORT(int) CommandLineSwitches_GetInt(char const *); - -#endif /* !__PYX_HAVE_API__cefpython_py27 */ - -#if PY_MAJOR_VERSION < 3 -PyMODINIT_FUNC initcefpython_py27(void); -#else -PyMODINIT_FUNC PyInit_cefpython_py27(void); -#endif - -#endif /* !__PYX_HAVE__cefpython_py27 */ diff --git a/src/mac/setup/fix_pyx_files.py b/src/mac/setup/fix_pyx_files.py deleted file mode 100644 index 0c91e336d..000000000 --- a/src/mac/setup/fix_pyx_files.py +++ /dev/null @@ -1,109 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -# First, it copies all .pyx files from upper directory to setup/. -# Then, fixes repeating of "include" statements in pyx files. - -# Only the mainfile needs to have "include" statements, -# but we're using PyCharm and to get rid of "unresolved references" -# and other errors displayed in pycharm we are adding "include" -# statements in all of the pyx files. - -# I'm not 100% sure how includes work in Cython, but I suspect that -# a few includes of the same file will include the same content more -# than once, it should work, but function and variable definitions are -# duplicated, it is some kind of overhead and it could lead to some -# problems in the future, better to fix it now. - -# It also checks cdef & cpdef functions whether they are not missing "except *", -# it is required to add it when returning non-python type. - -import glob -import os -import re -import shutil -import sys - -def ExceptAllMissing(content): - - # This is not perfect, won't detect C++ custom types, but will find - # the built-in types, templates and pointers. - patterns = [] - patterns.append( - r"\bcp?def\s+" - "((int|short|long|double|char|unsigned|float|double|cpp_bool" - "|cpp_string|cpp_wstring|uint64_t|uintptr_t|void" - "|CefString)\s+)+" - "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") - patterns.append( - r"\bcp?def\s+" - # A template ends with bracket: CefRefPtr[CefBrowser] - # or a pointer ends with asterisk: CefBrowser* - "[^\s]+[\]*]\s+" - "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") - patterns.append( - r"\bcp?def\s+" - # A reference, eg. CefString& - "[^\s]+&\s+" - "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") - - for pattern in patterns: - match = re.search(pattern, content) - if match: break - - if match: - lineNumber = (content.count("\n", 0, match.start()) + 1) - return lineNumber - -print("\n") -mainfile = "cefpython.pyx" - -pyxfiles = glob.glob("../../*.pyx") -if not len(pyxfiles): - sys.exit(1) -pyxfiles = [file for file in pyxfiles if file.find(mainfile) == -1] -# Now, pyxfiles contains all pyx files except the mainfile (cefpython.pyx), -# we do not fix includes in mainfile. - -# So that this is the right directory we're in. -if os.path.exists("setup"): - print("Wrong directory, we should be inside setup!") - sys.exit(1) - -# Remove old pyx files in setup directory. -oldpyxfiles = glob.glob("./*.pyx") -print("Removing old pyx files in /setup/: %s" % oldpyxfiles) -for pyxfile in oldpyxfiles: - if os.path.exists(pyxfile): - os.remove(pyxfile) - -# Copying pyxfiles and reading its contents. - -print("Copying .pyx files to /setup/: %s" % pyxfiles) -shutil.copy("../../%s" % mainfile, "./%s" % mainfile) -# Rest of the files will be copied in for loop below. - -print("Fixing includes in .pyx files:") -for pyxfile in pyxfiles: - newfile = "./%s" % os.path.basename(pyxfile) - shutil.copy(pyxfile, newfile) - pyxfile = newfile - with open(pyxfile, "r") as pyxfileopened: - content = pyxfileopened.read() - lineNumber = ExceptAllMissing(content) - if lineNumber: - print("WARNING: 'except *' missing in a cdef/cpdef function, " - "in file %s on line %d" % (os.path.basename(pyxfile), lineNumber)) - sys.exit(1) - # Do not remove the newline - so that line numbers are exact with originals. - (content, subs) = re.subn(r"^include[\t ]+[\"'][^\"'\n\r]+[\"'][\t ]*", "", content, flags=re.MULTILINE) - if subs: - print("%s includes removed in: %s" % (subs, os.path.basename(pyxfile))) - # Reading and writing with the same handle using "r+" mode doesn't work, - # you need to seek(0) and write the same amount of bytes that was in the - # file, otherwise old data from the end of file stays. - with open(pyxfile, "w") as pyxfileopened: - pyxfileopened.write(content) - -print("\n") diff --git a/src/mac/setup/lib_32bit/README b/src/mac/setup/lib_32bit/README deleted file mode 100644 index 623f03245..000000000 --- a/src/mac/setup/lib_32bit/README +++ /dev/null @@ -1 +0,0 @@ -Put libcef_dll_wrapper.a here diff --git a/src/mac/setup/lib_64bit/README b/src/mac/setup/lib_64bit/README deleted file mode 100644 index 623f03245..000000000 --- a/src/mac/setup/lib_64bit/README +++ /dev/null @@ -1 +0,0 @@ -Put libcef_dll_wrapper.a here diff --git a/src/mac/setup/setup.py b/src/mac/setup/setup.py deleted file mode 100644 index 36f8dc5f9..000000000 --- a/src/mac/setup/setup.py +++ /dev/null @@ -1,110 +0,0 @@ -from distutils.core import setup -# Use "Extension" from Cython.Distutils so that "cython_directives" works. -# from distutils.extension import Extension -from Cython.Distutils import build_ext, Extension -import sys -import os -import platform -from Cython.Compiler import Options -import Cython - -print("Cython version: %s" % Cython.__version__) - -BITS = platform.architecture()[0] -assert (BITS == "32bit" or BITS == "64bit") -if sys.maxint == 2147483647: - BITS = "32bit" - -print("BITS=%s" % BITS) - -os.environ["CC"] = "gcc" -os.environ["CXX"] = "g++" - -# Stop on first error, otherwise hundreds of errors appear in the console. -Options.fast_fail = True - -# Python version string: "27" or "32". -PYTHON_VERSION = str(sys.version_info.major) + str(sys.version_info.minor) - -def CompileTimeConstants(): - - print("Generating: compile_time_constants.pxi") - with open("./../../compile_time_constants.pxi", "w") as fd: - fd.write('# This file was generated by setup.py\n') - # A way around Python 3.2 bug: UNAME_SYSNAME is not set. - fd.write('DEF UNAME_SYSNAME = "%s"\n' % platform.uname()[0]) - fd.write('DEF PY_MAJOR_VERSION = %s\n' % sys.version_info.major) - -CompileTimeConstants() - -ext_modules = [Extension( - - "cefpython_py%s" % PYTHON_VERSION, - ["cefpython.pyx"], - - # Ignore the warning in the console: - # > C:\Python27\lib\distutils\extension.py:133: UserWarning: - # > Unknown Extension options: 'cython_directives' warnings.warn(msg) - cython_directives={ - # Any conversion to unicode must be explicit using .decode(). - "c_string_type": "bytes", - "c_string_encoding": "utf-8", - }, - - language='c++', - include_dirs=[ - r'./../', - r'./../../', - r'./../../extern/', - r'./../../extern/cef/', - '/usr/include/gtk-2.0', - '/usr/include/glib-2.0', - '/usr/include/cairo', - '/usr/include/pango-1.0', - '/usr/include/gdk-pixbuf-2.0', - '/usr/include/atk-1.0', - # Ubuntu - '/usr/lib/x86_64-linux-gnu/glib-2.0/include', - '/usr/lib/x86_64-linux-gnu/gtk-2.0/include', - '/usr/lib/i386-linux-gnu/gtk-2.0/include', - '/usr/lib/i386-linux-gnu/glib-2.0/include', - # Fedora - '/usr/lib64/glib-2.0/include', - '/usr/lib64/gtk-2.0/include', - '/usr/lib/glib-2.0/include', - '/usr/lib/gtk-2.0/include', - ], - - # http_authentication not implemented on Linux. - library_dirs=[ - r'./lib_%s' % BITS, - r'./../../client_handler/', - r'./../../subprocess/', # libcefpythonapp - r'./../../cpp_utils/' - ], - - libraries=[ - 'client_handler', - 'cef_dll_wrapper', - 'cefpythonapp', - 'cpp_utils' - ], - - # Loading libcef.so will only work when running scripts from the same - # directory that libcef.so resides in when you put "./" in here. - # runtime_library_dirs=[ - # './' - #], - - extra_compile_args=[], - extra_link_args=[], - - # Defining macros: - # define_macros = [("UNICODE","1"), ("_UNICODE","1"), ] -)] - -setup( - name = 'cefpython_py%s' % PYTHON_VERSION, - cmdclass = {'build_ext': build_ext}, - ext_modules = ext_modules -) diff --git a/src/subprocess/libcefpythonapp_py27_64bit.vcproj b/src/subprocess/deprecated_libcefpythonapp_py27_64bit.vcproj similarity index 100% rename from src/subprocess/libcefpythonapp_py27_64bit.vcproj rename to src/subprocess/deprecated_libcefpythonapp_py27_64bit.vcproj diff --git a/src/subprocess/libcefpythonapp_py34_32bit.vcproj b/src/subprocess/deprecated_libcefpythonapp_py34_32bit.vcproj similarity index 100% rename from src/subprocess/libcefpythonapp_py34_32bit.vcproj rename to src/subprocess/deprecated_libcefpythonapp_py34_32bit.vcproj diff --git a/src/subprocess/subprocess_64bit.vcproj b/src/subprocess/deprecated_subprocess_64bit.vcproj similarity index 100% rename from src/subprocess/subprocess_64bit.vcproj rename to src/subprocess/deprecated_subprocess_64bit.vcproj diff --git a/src/subprocess/libcefpythonapp_py27_32bit.vcproj b/src/subprocess/libcefpythonapp_py27_32bit.vcproj index 6bea39c10..a08ddafce 100644 --- a/src/subprocess/libcefpythonapp_py27_32bit.vcproj +++ b/src/subprocess/libcefpythonapp_py27_32bit.vcproj @@ -2,41 +2,29 @@ - + - - - - - + + + + + - - - - - - - - - + + + + + + + + + @@ -85,22 +55,10 @@ Filter="h;hpp;hxx;hm;inl;inc;xsd" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > - - - - - - - - + + + + - - - - - - - - + + + + diff --git a/src/subprocess/subprocess_32bit.vcproj b/src/subprocess/subprocess_32bit.vcproj index fd1d9930a..d5cf7d4ac 100644 --- a/src/subprocess/subprocess_32bit.vcproj +++ b/src/subprocess/subprocess_32bit.vcproj @@ -1,162 +1,103 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="9.00" + Name="subprocess_win32" + RootNamespace="subprocess_win32" + ProjectGUID="{0EB22FA5-229C-4FCF-BC1E-325CA1CB7637}" + Keyword="Win32Proj" + TargetFrameworkVersion="196613" + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/version/cef_version_win.h b/src/version/cef_version_win.h new file mode 100644 index 000000000..3a20c3f43 --- /dev/null +++ b/src/version/cef_version_win.h @@ -0,0 +1,102 @@ +// Copyright (c) 2017 Marshall A. Greenblatt. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the name Chromium Embedded +// Framework nor the names of its contributors may be used to endorse +// or promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// --------------------------------------------------------------------------- +// +// This file is generated by the make_version_header.py tool. +// + +#ifndef CEF_INCLUDE_CEF_VERSION_H_ +#define CEF_INCLUDE_CEF_VERSION_H_ + +#define CEF_VERSION "3.2883.1553.g80bd606" +#define CEF_VERSION_MAJOR 3 +#define CEF_COMMIT_NUMBER 1553 +#define CEF_COMMIT_HASH "80bd6062d7ac4c5fd1d7bc7ee78e8e59d4a040aa" +#define COPYRIGHT_YEAR 2017 + +#define CHROME_VERSION_MAJOR 55 +#define CHROME_VERSION_MINOR 0 +#define CHROME_VERSION_BUILD 2883 +#define CHROME_VERSION_PATCH 87 + +#define DO_MAKE_STRING(p) #p +#define MAKE_STRING(p) DO_MAKE_STRING(p) + +#ifndef APSTUDIO_HIDDEN_SYMBOLS + +#include "include/internal/cef_export.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// The API hash is created by analyzing CEF header files for C API type +// definitions. The hash value will change when header files are modified +// in a way that may cause binary incompatibility with other builds. The +// universal hash value will change if any platform is affected whereas the +// platform hash values will change only if that particular platform is +// affected. +#define CEF_API_HASH_UNIVERSAL "87b7eefcb86c87b28f86bfd7919f7d7a6cffc0d8" +#if defined(OS_WIN) +#define CEF_API_HASH_PLATFORM "00823905486d7b7222da5654fe35d2d15f65543a" +#elif defined(OS_MACOSX) +#define CEF_API_HASH_PLATFORM "f0180f006643782254250f34e858b98110a40e6e" +#elif defined(OS_LINUX) +#define CEF_API_HASH_PLATFORM "14b19454a4231fa10a77b8955954dc95f073af6b" +#endif + +// Returns CEF version information for the libcef library. The |entry| +// parameter describes which version component will be returned: +// 0 - CEF_VERSION_MAJOR +// 1 - CEF_COMMIT_NUMBER +// 2 - CHROME_VERSION_MAJOR +// 3 - CHROME_VERSION_MINOR +// 4 - CHROME_VERSION_BUILD +// 5 - CHROME_VERSION_PATCH +/// +CEF_EXPORT int cef_version_info(int entry); + +/// +// Returns CEF API hashes for the libcef library. The returned string is owned +// by the library and should not be freed. The |entry| parameter describes which +// hash value will be returned: +// 0 - CEF_API_HASH_PLATFORM +// 1 - CEF_API_HASH_UNIVERSAL +// 2 - CEF_COMMIT_HASH +/// +CEF_EXPORT const char* cef_api_hash(int entry); + +#ifdef __cplusplus +} +#endif + +#endif // APSTUDIO_HIDDEN_SYMBOLS + +#endif // CEF_INCLUDE_CEF_VERSION_H_ diff --git a/src/window_info.pyx b/src/window_info.pyx index eb9b5fb17..c3bef3226 100644 --- a/src/window_info.pyx +++ b/src/window_info.pyx @@ -63,7 +63,7 @@ cdef void SetCefWindowInfo( windowInfo.parentWindowHandle, windowName) - cdef cpp_bool transparent = windowInfo.transparentPainting + cdef cpp_bool transparent = bool(windowInfo.transparentPainting) if windowInfo.windowType == "offscreen": cefWindowInfo.SetAsWindowless( windowInfo.parentWindowHandle, diff --git a/src/window_utils_win.pyx b/src/window_utils_win.pyx index 912ead1e8..81d80143b 100644 --- a/src/window_utils_win.pyx +++ b/src/window_utils_win.pyx @@ -102,7 +102,7 @@ class WindowUtils: iconSmall = SendMessage( windowHandle, WM_GETICON, ICON_SMALL, 0) - cdef int parentWindowHandle + cdef long long parentWindowHandle if not iconBig and not iconSmall: parentWindowHandle = pyBrowser.GetOpenerWindowHandle() diff --git a/src/windows/.gitignore b/src/windows/.gitignore deleted file mode 100644 index fb779dfc0..000000000 --- a/src/windows/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*.exe -*.dll -*.pak -*.lib - -!msvcr90.dll -!msvcp90.dll -!msvcm90.dll diff --git a/src/windows/binaries_32bit/prism.css b/src/windows/binaries_32bit/prism.css deleted file mode 100644 index f94cca7c0..000000000 --- a/src/windows/binaries_32bit/prism.css +++ /dev/null @@ -1,130 +0,0 @@ -/* http://prismjs.com/download.html?themes=prism&languages=clike+javascript+python */ -/** - * prism.js default theme for JavaScript, CSS and HTML - * Based on dabblet (http://dabblet.com) - * @author Lea Verou - */ - -code[class*="language-"], -pre[class*="language-"] { - color: black; - text-shadow: 0 1px white; - font-family: Consolas, Monaco, 'Andale Mono', monospace; - direction: ltr; - text-align: left; - white-space: pre; - word-spacing: normal; - word-break: normal; - - - -moz-tab-size: 4; - -o-tab-size: 4; - tab-size: 4; - - -webkit-hyphens: none; - -moz-hyphens: none; - -ms-hyphens: none; - hyphens: none; -} - -pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, -code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { - text-shadow: none; - background: #b3d4fc; -} - -pre[class*="language-"]::selection, pre[class*="language-"] ::selection, -code[class*="language-"]::selection, code[class*="language-"] ::selection { - text-shadow: none; - background: #b3d4fc; -} - -@media print { - code[class*="language-"], - pre[class*="language-"] { - text-shadow: none; - } -} - -/* Code blocks */ -pre[class*="language-"] { - padding: 1em; - margin: .5em 0; - overflow: auto; -} - -:not(pre) > code[class*="language-"], -pre[class*="language-"] { - background: #f5f2f0; -} - -/* Inline code */ -:not(pre) > code[class*="language-"] { - padding: .1em; - border-radius: .3em; -} - -.token.comment, -.token.prolog, -.token.doctype, -.token.cdata { - color: slategray; -} - -.token.punctuation { - color: #999; -} - -.namespace { - opacity: .7; -} - -.token.property, -.token.tag, -.token.boolean, -.token.number, -.token.constant, -.token.symbol { - color: #905; -} - -.token.selector, -.token.attr-name, -.token.string, -.token.builtin { - color: #690; -} - -.token.operator, -.token.entity, -.token.url, -.language-css .token.string, -.style .token.string, -.token.variable { - color: #a67f59; - background: hsla(0,0%,100%,.5); -} - -.token.atrule, -.token.attr-value, -.token.keyword { - color: #07a; -} - -.token.function { - color: #DD4A68; -} - -.token.regex, -.token.important { - color: #e90; -} - -.token.important { - font-weight: bold; -} - -.token.entity { - cursor: help; -} - diff --git a/src/windows/binaries_32bit/prism.js b/src/windows/binaries_32bit/prism.js deleted file mode 100644 index ebaa4b428..000000000 --- a/src/windows/binaries_32bit/prism.js +++ /dev/null @@ -1,5 +0,0 @@ -/* http://prismjs.com/download.html?themes=prism&languages=clike+javascript+python */ -self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{};var Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content)):"Array"===t.util.type(e)?e.map(t.util.encode):e.replace(/&/g,"&").replace(/e.length)break e;if(!(f instanceof r)){l.lastIndex=0;var h=l.exec(f);if(h){c&&(g=h[1].length);var d=h.index-1+g,h=h[0].slice(g),p=h.length,m=d+p,v=f.slice(0,d+1),y=f.slice(m+1),k=[u,1];v&&k.push(v);var b=new r(o,s?t.tokenize(h,s):h);k.push(b),y&&k.push(y),Array.prototype.splice.apply(a,k)}}}}return a},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[],r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(r&&r.length)for(var a,i=0;a=r[i++];)a(n)}}},n=t.Token=function(e,t){this.type=e,this.content=t};if(n.stringify=function(e,r,a){if("string"==typeof e)return e;if("[object Array]"==Object.prototype.toString.call(e))return e.map(function(t){return n.stringify(t,r,e)}).join("");var i={type:e.type,content:n.stringify(e.content,r,a),tag:"span",classes:["token",e.type],attributes:{},language:r,parent:a};"comment"==i.type&&(i.attributes.spellcheck="true"),t.hooks.run("wrap",i);var o="";for(var l in i.attributes)o+=l+'="'+(i.attributes[l]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+o+">"+i.content+""},!self.document)return self.addEventListener?(self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,a=n.code;self.postMessage(JSON.stringify(t.tokenize(a,t.languages[r]))),self.close()},!1),self.Prism):self.Prism;var r=document.getElementsByTagName("script");return r=r[r.length-1],r&&(t.filename=r.src,document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)),self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism);; -Prism.languages.clike={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,lookbehind:!0},string:/("|')(\\?.)*?\1/g,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/gi,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g,"boolean":/\b(true|false)\b/g,"function":{pattern:/[a-z0-9_]+\(/gi,inside:{punctuation:/\(/}},number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,operator:/[-+]{1,2}|!|<=?|>=?|={1,3}|&{1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};; -Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|function|get|if|implements|import|in|instanceof|interface|let|new|null|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,lookbehind:!0}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/[\w\W]*?<\/script>/gi,inside:{tag:{pattern:/|<\/script>/gi,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}});; -Prism.languages.python={comment:{pattern:/(^|[^\\])#.*?(\r?\n|$)/g,lookbehind:!0},string:/"""[\s\S]+?"""|("|')(\\?.)*?\1/g,keyword:/\b(as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/g,"boolean":/\b(True|False)\b/g,number:/\b-?(0x)?\d*\.?[\da-f]+\b/g,operator:/[-+]{1,2}|=?<|=?>|!|={1,2}|(&){1,2}|(&){1,2}|\|?\||\?|\*|\/|~|\^|%|\b(or|and|not)\b/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};; diff --git a/src/windows/binaries_64bit/LICENSE.txt b/src/windows/binaries_64bit/LICENSE.txt deleted file mode 100644 index 45e6f23ea..000000000 --- a/src/windows/binaries_64bit/LICENSE.txt +++ /dev/null @@ -1,39 +0,0 @@ -Copyright (c) 2012 The CEF Python authors. All rights -reserved. Website: http://code.google.com/p/cefpython/ - -This product includes the following third party libraries: -* Chromium Embedded Framework licensed under the BSD 3-clause - license. Website: http://code.google.com/p/chromiumembedded/ - -Redistribution and use in source and binary forms, with -or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of Google Inc. nor the name Chromium - Embedded Framework nor the name of CEF Python nor the - names of its contributors may be used to endorse or - promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/windows/binaries_64bit/README.txt b/src/windows/binaries_64bit/README.txt deleted file mode 100644 index 3158cb804..000000000 --- a/src/windows/binaries_64bit/README.txt +++ /dev/null @@ -1,119 +0,0 @@ -Chromium Embedded Framework (CEF) Standard Binary Distribution for Windows -------------------------------------------------------------------------------- - -Date: March 14, 2014 - -CEF Version: 3.1650.1639 -CEF URL: http://chromiumembedded.googlecode.com/svn/branches/1650/cef3@1639 - -Chromium Verison: 31.0.1650.57 -Chromium URL: http://src.chromium.org/svn/branches/1650/src@235101 - -This distribution contains all components necessary to build and distribute an -application using CEF on the Windows platform. Please see the LICENSING -section of this document for licensing terms and conditions. - - -CONTENTS --------- - -cefclient Contains the cefclient sample application configured to build - using the files in this distribution. - -Debug Contains libcef.dll, libcef.lib and other components required to - build and run the debug version of CEF-based applications. By - default these files should be placed in the same directory as the - executable and will be copied there as part of the build process. - -include Contains all required CEF header files. - -libcef_dll Contains the source code for the libcef_dll_wrapper static library - that all applications using the CEF C++ API must link against. - -Release Contains libcef.dll, libcef.lib and other components required to - build and run the release version of CEF-based applications. By - default these files should be placed in the same directory as the - executable and will be copied there as part of the build process. - -Resources Contains resources required by libcef.dll. By default these files - should be placed in the same directory as libcef.dll. By default - these files should be placed in the same directory as libcef.dll - and will be copied there as part of the build process. - - -USAGE ------ - -Visual Studio 2012 and Visual Studio 2010: - Open the cefclient2010.sln solution in Visual Studio and build. - -Visual Studio 2008: - Open the cefclient2008.sln solution in Visual Studio and build. - -Visual Studio 2005: - 1. Open the cefclient.vcproj and libcef_dll_wrapper.vcproj files in a text - editor. Change Version="9.00" to Version="8.00". - 2. Open the cefclient2005.sln file in a text editor. Change "Version 9.00" to - "Version 8.00". - 3. Open the cefclient2005.sln solution in Visual Studio and build. - -Please visit the CEF Website for additional usage information. - -http://code.google.com/p/chromiumembedded - - -REDISTRIBUTION --------------- - -This binary distribution contains the below components. Components listed under -the "required" section must be redistributed with all applications using CEF. -Components listed under the "optional" section may be excluded if the related -features will not be used. - -Required components: - -* CEF core library - libcef.dll - -* Unicode support - icudt.dll - -Optional components: - -* Localized resources - locales/ - Note: Contains localized strings for WebKit UI controls. A .pak file is loaded - from this folder based on the CefSettings.locale value. Only configured - locales need to be distributed. If no locale is configured the default locale - of "en-US" will be used. Locale file loading can be disabled completely using - CefSettings.pack_loading_disabled. The locales folder path can be customized - using CefSettings.locales_dir_path. - -* Other resources - cef.pak - devtools_resources.pak - Note: Contains WebKit image and inspector resources. Pack file loading can be - disabled completely using CefSettings.pack_loading_disabled. The resources - directory path can be customized using CefSettings.resources_dir_path. - -* FFmpeg audio and video support - ffmpegsumo.dll - Note: Without this component HTML5 audio and video will not function. - -* Angle and Direct3D support - d3dcompiler_43.dll (required for Windows XP) - d3dcompiler_46.dll (required for Windows Vista and newer) - libEGL.dll - libGLESv2.dll - Note: Without these components HTML5 accelerated content like 2D canvas, 3D - CSS and WebGL will not function. - - -LICENSING ---------- - -The CEF project is BSD licensed. Please read the LICENSE.txt file included with -this binary distribution for licensing terms and conditions. Other software -included in this distribution is provided under other licenses. Please visit -"about:credits" in a CEF-based application for complete Chromium and third-party -licensing information. diff --git a/src/windows/binaries_64bit/cefwindow.py b/src/windows/binaries_64bit/cefwindow.py deleted file mode 100644 index fd0ac73ea..000000000 --- a/src/windows/binaries_64bit/cefwindow.py +++ /dev/null @@ -1,205 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -import win32gui -import win32con -import win32api -import time -import math -import os -import sys -import re - -if sys.version_info.major == 2: - from urllib import pathname2url as urllib_pathname2url -else: - from urllib.request import pathname2url as urllib_pathname2url - -g_debug = False -g_windows = {} # windowID(int): className -g_registeredClasses = {} - -def Debug(msg): - - if not g_debug: - return - msg = "cefwindow: "+str(msg) - print(msg) - with open(GetRealPath("debug.log"), "a") as file: - file.write(msg+"\n") - -def GetRealPath(file=None, encodeURL=False): - - # This function is defined in 2 files: cefpython.pyx and cefwindow.py, if you make changes edit both files. - # If file is None return current directory, without trailing slash. - - # encodeURL param - will call urllib.pathname2url(), only when file is empty (current dir) - # or is relative path ("test.html", "some/test.html"), we need to encode it before passing - # to CreateBrowser(), otherwise it is encoded by CEF internally and becomes (chinese characters): - # >> %EF%BF%97%EF%BF%80%EF%BF%83%EF%BF%A6 - # but should be: - # >> %E6%A1%8C%E9%9D%A2 - - if file is None: file = "" - if file.find("/") != 0 and file.find("\\") != 0 and not re.search(r"^[a-zA-Z]+:[/\\]?", file): - # Execute this block only when relative path ("test.html", "some\test.html") or file is empty (current dir). - # 1. find != 0 >> not starting with / or \ (/ - linux absolute path, \ - just to be sure) - # 2. not re.search >> not (D:\\ or D:/ or D: or http:// or ftp:// or file://), - # "D:" is also valid absolute path ("D:cefpython" in chrome becomes "file:///D:/cefpython/") - if hasattr(sys, "frozen"): path = os.path.dirname(sys.executable) - elif "__file__" in globals(): path = os.path.dirname(os.path.realpath(__file__)) - else: path = os.getcwd() - path = path + os.sep + file - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) # directory without trailing slash. - if encodeURL: - return urllib_pathname2url(path) - else: - return path - return file - -def CreateWindow(title, className, width, height, xpos=None, ypos=None, icon=None, windowProc=None): - - """ - for key in g_windows: - if g_windows[key] == className: - raise Exception("There was already created a window with that className: %s." - "Each created window must have an unique className." % className) - """ - - if not windowProc: - windowProc = {win32con.WM_CLOSE: WM_CLOSE} - - bigIcon = "" - smallIcon = "" - - if icon: - icon = GetRealPath(icon) - - # Load small and big icon. - # WNDCLASSEX (along with hIconSm) is not supported by pywin32, - # we need to use WM_SETICON message after window creation. - - # http://stackoverflow.com/questions/2234988/how-to-set-hicon-on-a-window-ico-with-multiple-sizes - # http://blog.barthe.ph/2009/07/17/wmseticon/ - - bigX = win32api.GetSystemMetrics(win32con.SM_CXICON) - bigY = win32api.GetSystemMetrics(win32con.SM_CYICON) - bigIcon = win32gui.LoadImage(0, icon, win32con.IMAGE_ICON, bigX, bigY, win32con.LR_LOADFROMFILE) - smallX = win32api.GetSystemMetrics(win32con.SM_CXSMICON) - smallY = win32api.GetSystemMetrics(win32con.SM_CYSMICON) - smallIcon = win32gui.LoadImage(0, icon, win32con.IMAGE_ICON, smallX, smallY, win32con.LR_LOADFROMFILE) - - wndclass = win32gui.WNDCLASS() - wndclass.hInstance = win32api.GetModuleHandle(None) - wndclass.lpszClassName = className - wndclass.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW - # win32con.CS_GLOBALCLASS - wndclass.hbrBackground = win32con.COLOR_WINDOW - wndclass.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW) - wndclass.lpfnWndProc = windowProc - - #noinspection PyUnusedLocal - global g_registeredClasses - if not className in g_registeredClasses: - g_registeredClasses[className] = True - atomclass = win32gui.RegisterClass(wndclass) - Debug("win32gui.RegisterClass(%s)" % className) - - if xpos is None or ypos is None: - # Center window on the screen. - Debug("Centering window on the screen.") - screenx = win32api.GetSystemMetrics(win32con.SM_CXSCREEN) - screeny = win32api.GetSystemMetrics(win32con.SM_CYSCREEN) - xpos = int(math.floor((screenx - width) / 2)) - ypos = int(math.floor((screeny - height) / 2)) - if xpos < 0: xpos = 0 - if ypos < 0: ypos = 0 - - windowID = win32gui.CreateWindow(className, title, - win32con.WS_OVERLAPPEDWINDOW | win32con.WS_CLIPCHILDREN | win32con.WS_VISIBLE, - xpos, ypos, width, height, # xpos, ypos, width, height - 0, 0, wndclass.hInstance, None) - g_windows[windowID] = className - - if icon: - if bigIcon: - win32api.SendMessage(windowID, win32con.WM_SETICON, win32con.ICON_BIG, bigIcon) - if smallIcon: - win32api.SendMessage(windowID, win32con.WM_SETICON, win32con.ICON_SMALL, smallIcon) - - Debug("windowID = %s" % windowID) - return windowID - - -# Memory error when calling win32gui.DestroyWindow() -# after we called cefpython.CloseBrowser() - -def DestroyWindow(windowID): - - win32gui.DestroyWindow(windowID) - #className = GetWindowClassName(windowID) - #win32gui.UnregisterClass(className, None) - #del g_windows[windowID] # Let window with this className be created again. - - -def GetWindowClassName(windowID): - - for key in g_windows: - if key == windowID: - return g_windows[key] - -def MoveWindow(windowID, xpos=None, ypos=None, width=None, height=None, center=None): - - (left, top, right, bottom) = win32gui.GetWindowRect(windowID) - if xpos is None and ypos is None: - xpos = left - ypos = top - if width is None and height is None: - width = right - left - height = bottom - top - # Case: only ypos provided - if xpos is None and ypos is not None: - xpos = left - if ypos is None and xpos is not None: - ypos = top - # Case: only height provided - if not width: - width = right - left - if not height: - height = bottom - top - if center: - screenx = win32api.GetSystemMetrics(win32con.SM_CXSCREEN) - screeny = win32api.GetSystemMetrics(win32con.SM_CYSCREEN) - xpos = int(math.floor((screenx - width) / 2)) - ypos = int(math.floor((screeny - height) / 2)) - if xpos < 0: xpos = 0 - if ypos < 0: ypos = 0 - win32gui.MoveWindow(windowID, xpos, ypos, width, height, 1) - - -#noinspection PyUnusedLocal -def WM_CLOSE(windowID, msg, wparam, lparam): - - DestroyWindow(windowID) - win32gui.PostQuitMessage(0) - - -def GetLastError(): - - code = win32api.GetLastError() - return "(%d) %s" % (code, win32api.FormatMessage(code)) - -#noinspection PyUnusedLocal -def MessageLoop(className): - - while not win32gui.PumpWaitingMessages(): - time.sleep(0.001) - - -if __name__ == "__main__": - - g_debug = True - hwnd = CreateWindow("Test window", "testwindow", 800, 600) - MessageLoop("testwindow") \ No newline at end of file diff --git a/src/windows/binaries_64bit/example.html b/src/windows/binaries_64bit/example.html deleted file mode 100644 index 96bbac9b3..000000000 --- a/src/windows/binaries_64bit/example.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - - CEF Python 3 example (utf-8: ąś) - - - - - - -

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

      - - - -

      Google Search

      -https://www.google.com/ - - - -

      User agent

      - - - - -

      Popup

      - - window.open('example.html') - - - -

      HTML5 video and accelerated content

      - -HTML 5 video
      - -Accelerated canvas
      - -Accelerated layers
      - - - -

      Advanced example

      - -See the wxpython.py script for an advanced usage of CEF Python 3 -features - including javascript bindings, js and python callbacks, -client handlers and others. - - -



      -



      -



      -



      - - - diff --git a/src/windows/binaries_64bit/icon.ico b/src/windows/binaries_64bit/icon.ico deleted file mode 100644 index 435045aec271dc2677d61810be947aa2420cd76d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 198275 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 Jm0$eg{{a!zwfz79 diff --git a/src/windows/binaries_64bit/prism.css b/src/windows/binaries_64bit/prism.css deleted file mode 100644 index f94cca7c0..000000000 --- a/src/windows/binaries_64bit/prism.css +++ /dev/null @@ -1,130 +0,0 @@ -/* http://prismjs.com/download.html?themes=prism&languages=clike+javascript+python */ -/** - * prism.js default theme for JavaScript, CSS and HTML - * Based on dabblet (http://dabblet.com) - * @author Lea Verou - */ - -code[class*="language-"], -pre[class*="language-"] { - color: black; - text-shadow: 0 1px white; - font-family: Consolas, Monaco, 'Andale Mono', monospace; - direction: ltr; - text-align: left; - white-space: pre; - word-spacing: normal; - word-break: normal; - - - -moz-tab-size: 4; - -o-tab-size: 4; - tab-size: 4; - - -webkit-hyphens: none; - -moz-hyphens: none; - -ms-hyphens: none; - hyphens: none; -} - -pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, -code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { - text-shadow: none; - background: #b3d4fc; -} - -pre[class*="language-"]::selection, pre[class*="language-"] ::selection, -code[class*="language-"]::selection, code[class*="language-"] ::selection { - text-shadow: none; - background: #b3d4fc; -} - -@media print { - code[class*="language-"], - pre[class*="language-"] { - text-shadow: none; - } -} - -/* Code blocks */ -pre[class*="language-"] { - padding: 1em; - margin: .5em 0; - overflow: auto; -} - -:not(pre) > code[class*="language-"], -pre[class*="language-"] { - background: #f5f2f0; -} - -/* Inline code */ -:not(pre) > code[class*="language-"] { - padding: .1em; - border-radius: .3em; -} - -.token.comment, -.token.prolog, -.token.doctype, -.token.cdata { - color: slategray; -} - -.token.punctuation { - color: #999; -} - -.namespace { - opacity: .7; -} - -.token.property, -.token.tag, -.token.boolean, -.token.number, -.token.constant, -.token.symbol { - color: #905; -} - -.token.selector, -.token.attr-name, -.token.string, -.token.builtin { - color: #690; -} - -.token.operator, -.token.entity, -.token.url, -.language-css .token.string, -.style .token.string, -.token.variable { - color: #a67f59; - background: hsla(0,0%,100%,.5); -} - -.token.atrule, -.token.attr-value, -.token.keyword { - color: #07a; -} - -.token.function { - color: #DD4A68; -} - -.token.regex, -.token.important { - color: #e90; -} - -.token.important { - font-weight: bold; -} - -.token.entity { - cursor: help; -} - diff --git a/src/windows/binaries_64bit/prism.js b/src/windows/binaries_64bit/prism.js deleted file mode 100644 index ebaa4b428..000000000 --- a/src/windows/binaries_64bit/prism.js +++ /dev/null @@ -1,5 +0,0 @@ -/* http://prismjs.com/download.html?themes=prism&languages=clike+javascript+python */ -self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{};var Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content)):"Array"===t.util.type(e)?e.map(t.util.encode):e.replace(/&/g,"&").replace(/e.length)break e;if(!(f instanceof r)){l.lastIndex=0;var h=l.exec(f);if(h){c&&(g=h[1].length);var d=h.index-1+g,h=h[0].slice(g),p=h.length,m=d+p,v=f.slice(0,d+1),y=f.slice(m+1),k=[u,1];v&&k.push(v);var b=new r(o,s?t.tokenize(h,s):h);k.push(b),y&&k.push(y),Array.prototype.splice.apply(a,k)}}}}return a},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[],r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(r&&r.length)for(var a,i=0;a=r[i++];)a(n)}}},n=t.Token=function(e,t){this.type=e,this.content=t};if(n.stringify=function(e,r,a){if("string"==typeof e)return e;if("[object Array]"==Object.prototype.toString.call(e))return e.map(function(t){return n.stringify(t,r,e)}).join("");var i={type:e.type,content:n.stringify(e.content,r,a),tag:"span",classes:["token",e.type],attributes:{},language:r,parent:a};"comment"==i.type&&(i.attributes.spellcheck="true"),t.hooks.run("wrap",i);var o="";for(var l in i.attributes)o+=l+'="'+(i.attributes[l]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+o+">"+i.content+""},!self.document)return self.addEventListener?(self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,a=n.code;self.postMessage(JSON.stringify(t.tokenize(a,t.languages[r]))),self.close()},!1),self.Prism):self.Prism;var r=document.getElementsByTagName("script");return r=r[r.length-1],r&&(t.filename=r.src,document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)),self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism);; -Prism.languages.clike={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,lookbehind:!0},string:/("|')(\\?.)*?\1/g,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/gi,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g,"boolean":/\b(true|false)\b/g,"function":{pattern:/[a-z0-9_]+\(/gi,inside:{punctuation:/\(/}},number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,operator:/[-+]{1,2}|!|<=?|>=?|={1,3}|&{1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};; -Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|function|get|if|implements|import|in|instanceof|interface|let|new|null|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,lookbehind:!0}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/[\w\W]*?<\/script>/gi,inside:{tag:{pattern:/|<\/script>/gi,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}});; -Prism.languages.python={comment:{pattern:/(^|[^\\])#.*?(\r?\n|$)/g,lookbehind:!0},string:/"""[\s\S]+?"""|("|')(\\?.)*?\1/g,keyword:/\b(as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/g,"boolean":/\b(True|False)\b/g,number:/\b-?(0x)?\d*\.?[\da-f]+\b/g,operator:/[-+]{1,2}|=?<|=?>|!|={1,2}|(&){1,2}|(&){1,2}|\|?\||\?|\*|\/|~|\^|%|\b(or|and|not)\b/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};; diff --git a/src/windows/binaries_64bit/pygtk_.py b/src/windows/binaries_64bit/pygtk_.py deleted file mode 100644 index 85e4d4f75..000000000 --- a/src/windows/binaries_64bit/pygtk_.py +++ /dev/null @@ -1,196 +0,0 @@ -# An example of embedding CEF browser in PyGTK on Windows. -# Tested with PyGTK 2.24.10 - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import a local module - if (2,7) <= sys.version_info < (2,8): - import cefpython_py27 as cefpython - elif (3,4) <= sys.version_info < (3,4): - import cefpython_py34 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import an installed package - from cefpython3 import cefpython - -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("[pygtk_.py]: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class PyGTKExample: - mainWindow = None - container = None - browser = None - exiting = None - searchEntry = None - - def __init__(self): - gobject.timeout_add(10, self.OnTimer) - - self.mainWindow = gtk.Window(gtk.WINDOW_TOPLEVEL) - self.mainWindow.connect('destroy', self.OnExit) - self.mainWindow.set_size_request(width=1024, height=768) - self.mainWindow.set_title('PyGTK CEF 3 example') - self.mainWindow.realize() - - self.container = gtk.DrawingArea() - self.container.set_property('can-focus', True) - self.container.connect('size-allocate', self.OnSize) - self.container.show() - - self.searchEntry = gtk.Entry() - # By default, clicking a GTK widget doesn't grab the focus away from a native Win32 control (browser). - self.searchEntry.connect('button-press-event', self.OnWidgetClick) - self.searchEntry.show() - - table = gtk.Table(3, 1, homogeneous=False) - self.mainWindow.add(table) - table.attach(self.CreateMenu(), 0, 1, 0, 1, yoptions=gtk.SHRINK) - table.attach(self.searchEntry, 0, 1, 1, 2, yoptions=gtk.SHRINK) - table.attach(self.container, 0, 1, 2, 3) - table.show() - - windowID = self.container.get_window().handle - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(windowID) - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings={}, - navigateUrl=GetApplicationPath('example.html')) - - self.mainWindow.show() - - # Browser took focus, we need to get it back and give to searchEntry. - self.mainWindow.get_window().focus() - self.searchEntry.grab_focus() - - def CreateMenu(self): - file = gtk.MenuItem('File') - file.show() - filemenu = gtk.Menu() - item = gtk.MenuItem('Open') - filemenu.append(item) - item.show() - item = gtk.MenuItem('Exit') - filemenu.append(item) - item.show() - file.set_submenu(filemenu) - about = gtk.MenuItem('About') - about.show() - menubar = gtk.MenuBar() - menubar.append(file) - menubar.append(about) - menubar.show() - return menubar - - def OnWidgetClick(self, widget, data): - self.mainWindow.get_window().focus() - - def OnTimer(self): - if self.exiting: - return False - cefpython.MessageLoopWork() - return True - - def OnFocusIn(self, widget, data): - # This function is currently not called by any of code, but if you would like - # for browser to have automatic focus add such line: - # self.mainWindow.connect('focus-in-event', self.OnFocusIn) - cefpython.WindowUtils.OnSetFocus(self.container.get_window().handle, 0, 0, 0) - - def OnSize(self, widget, sizeAlloc): - cefpython.WindowUtils.OnSize(self.container.get_window().handle, 0, 0, 0) - - def OnExit(self, widget, data=None): - self.exiting = True - gtk.main_quit() - -if __name__ == '__main__': - version = '.'.join(map(str, list(gtk.gtk_version))) - print('[pygtk_.py] GTK version: %s' % version) - - # Intercept python exceptions. Exit app immediately when exception - # happens on any of the threads. - sys.excepthook = ExceptHook - - # Application settings - settings = { - "debug": True, # cefpython debug messages in console and in log_file - "log_severity": cefpython.LOGSEVERITY_INFO, # LOGSEVERITY_VERBOSE - "log_file": GetApplicationPath("debug.log"), # Set to "" to disable - # This directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory(), - "browser_subprocess_path": "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess"), - } - - cefpython.Initialize(settings) - - gobject.threads_init() # Timer for the message loop - PyGTKExample() - gtk.main() - - cefpython.Shutdown() diff --git a/src/windows/binaries_64bit/pyqt.py b/src/windows/binaries_64bit/pyqt.py deleted file mode 100644 index ae7d7a850..000000000 --- a/src/windows/binaries_64bit/pyqt.py +++ /dev/null @@ -1,190 +0,0 @@ -# An example of embedding CEF browser in a PyQt4 application. -# Tested with PyQt 4.10.3 (Qt 4.8.5). - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import a local module - if (2,7) <= sys.version_info < (2,8): - import cefpython_py27 as cefpython - elif (3,4) <= sys.version_info < (3,4): - import cefpython_py34 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import an installed package - from cefpython3 import cefpython - -from PyQt4 import QtGui -from PyQt4 import QtCore - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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" (os._exit()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("[pyqt.py] WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainWindow(QtGui.QMainWindow): - mainFrame = None - - def __init__(self): - super(MainWindow, self).__init__(None) - self.createMenu() - self.mainFrame = MainFrame(self) - self.setCentralWidget(self.mainFrame) - self.resize(1024, 768) - self.setWindowTitle('PyQT CEF 3 example') - self.setFocusPolicy(QtCore.Qt.StrongFocus) - - def createMenu(self): - menubar = self.menuBar() - filemenu = menubar.addMenu("&File") - filemenu.addAction(QtGui.QAction("Open", self)) - filemenu.addAction(QtGui.QAction("Exit", self)) - aboutmenu = menubar.addMenu("&About") - - def focusInEvent(self, event): - cefpython.WindowUtils.OnSetFocus(int(self.centralWidget().winId()), 0, 0, 0) - - def closeEvent(self, event): - self.mainFrame.browser.CloseBrowser() - -class MainFrame(QtGui.QWidget): - browser = None - - def __init__(self, parent=None): - super(MainFrame, self).__init__(parent) - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(int(self.winId())) - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings={}, - navigateUrl=GetApplicationPath("example.html")) - self.show() - - def moveEvent(self, event): - cefpython.WindowUtils.OnSize(int(self.winId()), 0, 0, 0) - - def resizeEvent(self, event): - cefpython.WindowUtils.OnSize(int(self.winId()), 0, 0, 0) - -class CefApplication(QtGui.QApplication): - timer = None - - def __init__(self, args): - super(CefApplication, self).__init__(args) - self.createTimer() - - def createTimer(self): - self.timer = QtCore.QTimer() - self.timer.timeout.connect(self.onTimer) - self.timer.start(10) - - def onTimer(self): - # The proper way of doing message loop should be: - # 1. In createTimer() call self.timer.start(0) - # 2. In onTimer() call MessageLoopWork() only when - # QtGui.QApplication.instance()->hasPendingEvents() returns False. - # But... there is a bug in Qt, hasPendingEvents() returns always true. - cefpython.MessageLoopWork() - - def stopTimer(self): - # Stop the timer after Qt message loop ended, calls to MessageLoopWork() - # should not happen anymore. - self.timer.stop() - -if __name__ == '__main__': - print("[pyqt.py] PyQt version: %s" % QtCore.PYQT_VERSION_STR) - print("[pyqt.py] QtCore version: %s" % QtCore.qVersion()) - - # Intercept python exceptions. Exit app immediately when exception - # happens on any of the threads. - sys.excepthook = ExceptHook - - # Application settings - settings = { - # "cache_path": "webcache/", # Disk cache - "debug": True, # cefpython debug messages in console and in log_file - "log_severity": cefpython.LOGSEVERITY_INFO, # LOGSEVERITY_VERBOSE - "log_file": GetApplicationPath("debug.log"), # Set to "" to disable. - # This directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory(), - "browser_subprocess_path": "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess") - } - - # Command line switches set programmatically - switches = { - # "proxy-server": "socks5://127.0.0.1:8888", - # "enable-media-stream": "", - # "--invalid-switch": "" -> Invalid switch name - } - - cefpython.Initialize(settings, switches) - - app = CefApplication(sys.argv) - mainWindow = MainWindow() - mainWindow.show() - app.exec_() - app.stopTimer() - - # Need to destroy QApplication(), otherwise Shutdown() fails. - # Unset main window also just to be safe. - del mainWindow - del app - - cefpython.Shutdown() diff --git a/src/windows/binaries_64bit/pyside.py b/src/windows/binaries_64bit/pyside.py deleted file mode 100644 index 9a5f68fe0..000000000 --- a/src/windows/binaries_64bit/pyside.py +++ /dev/null @@ -1,188 +0,0 @@ -# An example of embedding CEF Python in PySide application. - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import a local module - if (2,7) <= sys.version_info < (2,8): - import cefpython_py27 as cefpython - elif (3,4) <= sys.version_info < (3,4): - import cefpython_py34 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import an installed package - from cefpython3 import cefpython - -import PySide -from PySide import QtGui -from PySide import QtCore -import ctypes - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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" (os._exit()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("cefpython: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainWindow(QtGui.QMainWindow): - mainFrame = None - - def __init__(self): - super(MainWindow, self).__init__(None) - self.createMenu() - self.mainFrame = MainFrame(self) - self.setCentralWidget(self.mainFrame) - self.resize(1024, 768) - self.setWindowTitle('PySide example') - self.setFocusPolicy(QtCore.Qt.StrongFocus) - - def createMenu(self): - menubar = self.menuBar() - filemenu = menubar.addMenu("&File") - filemenu.addAction(QtGui.QAction("Open", self)) - filemenu.addAction(QtGui.QAction("Exit", self)) - aboutmenu = menubar.addMenu("&About") - - def focusInEvent(self, event): - cefpython.WindowUtils.OnSetFocus(int(self.centralWidget().winIdFixed()), 0, 0, 0) - - def closeEvent(self, event): - self.mainFrame.browser.CloseBrowser() - -class MainFrame(QtGui.QWidget): - browser = None - - def __init__(self, parent=None): - super(MainFrame, self).__init__(parent) - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(int(self.winIdFixed())) - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings={}, - navigateUrl=GetApplicationPath("example.html")) - self.show() - - def winIdFixed(self): - # PySide bug: QWidget.winId() returns , - # there is no easy way to convert it to int. - try: - return int(self.winId()) - except: - if sys.version_info[0] == 2: - ctypes.pythonapi.PyCObject_AsVoidPtr.restype = ctypes.c_void_p - ctypes.pythonapi.PyCObject_AsVoidPtr.argtypes = [ctypes.py_object] - return ctypes.pythonapi.PyCObject_AsVoidPtr(self.winId()) - elif sys.version_info[0] == 3: - ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p - ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object] - return ctypes.pythonapi.PyCapsule_GetPointer(self.winId(), None) - - def moveEvent(self, event): - cefpython.WindowUtils.OnSize(int(self.winIdFixed()), 0, 0, 0) - - def resizeEvent(self, event): - cefpython.WindowUtils.OnSize(int(self.winIdFixed()), 0, 0, 0) - -class CefApplication(QtGui.QApplication): - timer = None - - def __init__(self, args): - super(CefApplication, self).__init__(args) - self.createTimer() - - def createTimer(self): - self.timer = QtCore.QTimer() - self.timer.timeout.connect(self.onTimer) - self.timer.start(10) - - def onTimer(self): - # The proper way of doing message loop should be: - # 1. In createTimer() call self.timer.start(0) - # 2. In onTimer() call MessageLoopWork() only when - # QtGui.QApplication.instance()->hasPendingEvents() returns False. - # But... there is a bug in Qt, hasPendingEvents() returns always true. - cefpython.MessageLoopWork() - - def stopTimer(self): - # Stop the timer after Qt message loop ended, calls to MessageLoopWork() - # should not happen anymore. - self.timer.stop() - -if __name__ == '__main__': - print("PySide version: %s" % PySide.__version__) - print("QtCore version: %s" % QtCore.__version__) - - sys.excepthook = ExceptHook - settings = {} - settings["log_file"] = GetApplicationPath("debug.log") - settings["log_severity"] = cefpython.LOGSEVERITY_INFO - settings["browser_subprocess_path"] = "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess") - cefpython.Initialize(settings) - - app = CefApplication(sys.argv) - mainWindow = MainWindow() - mainWindow.show() - app.exec_() - app.stopTimer() - - # Need to destroy QApplication(), otherwise Shutdown() fails. - # Unset main window also just to be safe. - del mainWindow - del app - - cefpython.Shutdown() diff --git a/src/windows/binaries_64bit/pywin32.py b/src/windows/binaries_64bit/pywin32.py deleted file mode 100644 index 747762696..000000000 --- a/src/windows/binaries_64bit/pywin32.py +++ /dev/null @@ -1,151 +0,0 @@ -# Example of embedding CEF browser using the PyWin32 extension. -# Tested with pywin32 version 218. - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import a local module - if (2,7) <= sys.version_info < (2,8): - import cefpython_py27 as cefpython - elif (3,4) <= sys.version_info < (3,4): - import cefpython_py34 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import an installed package - from cefpython3 import cefpython - -import cefwindow -import win32con -import win32gui -import win32api -import time - -DEBUG = True - -# ----------------------------------------------------------------------------- -# Helper functions. - -def Log(msg): - print("[pywin32.py] %s" % str(msg)) - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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" (os._exit()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("[pywin32.py] WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -# ----------------------------------------------------------------------------- - -def CefAdvanced(): - sys.excepthook = ExceptHook - - appSettings = dict() - # appSettings["cache_path"] = "webcache/" # Disk cache - if DEBUG: - # cefpython debug messages in console and in log_file - appSettings["debug"] = True - cefwindow.g_debug = True - appSettings["log_file"] = GetApplicationPath("debug.log") - appSettings["log_severity"] = cefpython.LOGSEVERITY_INFO - appSettings["browser_subprocess_path"] = "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess") - cefpython.Initialize(appSettings) - - wndproc = { - win32con.WM_CLOSE: CloseWindow, - win32con.WM_DESTROY: QuitApplication, - win32con.WM_SIZE: cefpython.WindowUtils.OnSize, - win32con.WM_SETFOCUS: cefpython.WindowUtils.OnSetFocus, - win32con.WM_ERASEBKGND: cefpython.WindowUtils.OnEraseBackground - } - - browserSettings = dict() - browserSettings["universal_access_from_file_urls_allowed"] = True - browserSettings["file_access_from_file_urls_allowed"] = True - - if os.path.exists("icon.ico"): - icon = os.path.abspath("icon.ico") - else: - icon = "" - - windowHandle = cefwindow.CreateWindow(title="pywin32 example", - className="cefpython3_example", width=1024, height=768, - icon=icon, windowProc=wndproc) - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(windowHandle) - browser = cefpython.CreateBrowserSync(windowInfo, browserSettings, - navigateUrl=GetApplicationPath("example.html")) - cefpython.MessageLoop() - cefpython.Shutdown() - -def CloseWindow(windowHandle, message, wparam, lparam): - browser = cefpython.GetBrowserByWindowHandle(windowHandle) - browser.CloseBrowser() - return win32gui.DefWindowProc(windowHandle, message, wparam, lparam) - -def QuitApplication(windowHandle, message, wparam, lparam): - win32gui.PostQuitMessage(0) - return 0 - -def GetPywin32Version(): - fixed_file_info = win32api.GetFileVersionInfo(win32api.__file__, '\\') - return fixed_file_info['FileVersionLS'] >> 16 - -if __name__ == "__main__": - Log("pywin32 version = %s" % GetPywin32Version()) - CefAdvanced() diff --git a/src/windows/binaries_64bit/smoke.css b/src/windows/binaries_64bit/smoke.css deleted file mode 100644 index 2936c818a..000000000 --- a/src/windows/binaries_64bit/smoke.css +++ /dev/null @@ -1,110 +0,0 @@ -.smoke-base { - position: fixed; - top: 0; - left: 0; - bottom: 0; - right: 0; - visibility: hidden; - opacity: 0; -} - -.smoke-base.smoke-visible { - opacity: 1; - visibility: visible; -} - -.smokebg { - position: fixed; - top: 0; - left: 0; - bottom: 0; - right: 0; -} - -.smoke-base .dialog { - position: absolute; -} - -.dialog-prompt { - margin-top: 15px; - text-align: center; -} - -.dialog-buttons { - margin: 20px 0 5px 0 -} - -.smoke { -} - -.dialog-buttons button { - display: inline-block; - vertical-align: baseline; - cursor: pointer; - font-family: Menlo, 'Andale Mono', monospace; - font-style: normal; - text-decoration: none; - border: 0; - outline: 0; - margin: 0 5px; - -webkit-background-clip: padding-box; - font-size: 13px; - line-height: 13px; - font-weight: normal; - padding: 9px 12px; -} - -.dialog-prompt input { - margin: 0; - border: 0; - font-family: sans-serif; - outline: none; - font-family: Menlo, 'Andale Mono', monospace; - border: 1px solid #aaa; - width: 75%; - display: inline-block; - background-color: transparent; - font-size: 16px; - padding: 8px; -} - -.smoke-base { - background: rgba(0,0,0,.3); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#90000000,endColorstr=#900000000); -} - -.smoke-base .dialog { - top: 25%; - width: 40%; - left: 50%; - margin-left: -20%; -} - -.smoke-base .dialog-inner { - padding: 15px; - - color:#202020; -} - -.smoke { - background-color: rgba(255,255,255,0.95); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ffffff,endColorstr=#ffffff); - box-shadow: 0 2px 8px #666; -} - - -.dialog-buttons button { - background-color: rgba(0,0,0,.85); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#222222,endColorstr=#222222); - border-radius: 0; - color: #fff; -} - -button.cancel { - background-color: rgba(0,0,0,.40); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#444444,endColorstr=#444444); -} - -.queue{ - display:none; -} diff --git a/src/windows/binaries_64bit/smoke.min.js b/src/windows/binaries_64bit/smoke.min.js deleted file mode 100644 index 61fb4f0c0..000000000 --- a/src/windows/binaries_64bit/smoke.min.js +++ /dev/null @@ -1 +0,0 @@ -(function(e,t){var n={smoketimeout:[],init:false,zindex:1e3,i:0,bodyload:function(e){var r=t.createElement("div");r.setAttribute("id","smoke-out-"+e);r.className="smoke-base";r.style.zIndex=n.zindex;n.zindex++;t.body.appendChild(r)},newdialog:function(){var t=(new Date).getTime();t=Math.random(1,99)+t;if(!n.init){n.listen(e,"load",function(){n.bodyload(t)})}else{n.bodyload(t)}return t},forceload:function(){},build:function(t,r){n.i++;r.stack=n.i;t=t.replace(/\n/g,"
      ");t=t.replace(/\r/g,"
      ");var i="",s="OK",o="Cancel",u="",a="",f;if(r.type==="prompt"){i='

      "}if(r.params.ok){s=r.params.ok}if(r.params.cancel){o=r.params.cancel}if(r.params.classname){u=r.params.classname}if(r.type!=="signal"){a='
      ';if(r.type==="alert"){a+='"}else if(r.type==="quiz"){if(r.params.button_1){a+='"}if(r.params.button_2){a+='"}if(r.params.button_3){a+='"}if(r.params.button_cancel){a+='"}}else if(r.type==="prompt"||r.type==="confirm"){if(r.params.reverseButtons){a+='"+'"}else{a+='"+'"}}a+="
      "}f='
      '+'
      '+'
      '+t+i+a+"
      "+"
      ";if(!n.init){n.listen(e,"load",function(){n.finishbuild(t,r,f)})}else{n.finishbuild(t,r,f)}},finishbuild:function(e,r,i){var s=t.getElementById("smoke-out-"+r.newid);s.className="smoke-base smoke-visible smoke-"+r.type;s.innerHTML=i;while(s.innerHTML===""){s.innerHTML=i}if(n.smoketimeout[r.newid]){clearTimeout(n.smoketimeout[r.newid])}n.listen(t.getElementById("smoke-bg-"+r.newid),"click",function(){n.destroy(r.type,r.newid);if(r.type==="prompt"||r.type==="confirm"||r.type==="quiz"){r.callback(false)}else if(r.type==="alert"&&typeof r.callback!=="undefined"){r.callback()}});switch(r.type){case"alert":n.finishbuildAlert(e,r,i);break;case"confirm":n.finishbuildConfirm(e,r,i);break;case"quiz":n.finishbuildQuiz(e,r,i);break;case"prompt":n.finishbuildPrompt(e,r,i);break;case"signal":n.finishbuildSignal(e,r,i);break;default:throw"Unknown type: "+r.type}},finishbuildAlert:function(r,i,s){n.listen(t.getElementById("alert-ok-"+i.newid),"click",function(){n.destroy(i.type,i.newid);if(typeof i.callback!=="undefined"){i.callback()}});t.onkeyup=function(t){if(!t){t=e.event}if(t.keyCode===13||t.keyCode===32||t.keyCode===27){n.destroy(i.type,i.newid);if(typeof i.callback!=="undefined"){i.callback()}}}},finishbuildConfirm:function(r,i,s){n.listen(t.getElementById("confirm-cancel-"+i.newid),"click",function(){n.destroy(i.type,i.newid);i.callback(false)});n.listen(t.getElementById("confirm-ok-"+i.newid),"click",function(){n.destroy(i.type,i.newid);i.callback(true)});t.onkeyup=function(t){if(!t){t=e.event}if(t.keyCode===13||t.keyCode===32){n.destroy(i.type,i.newid);i.callback(true)}else if(t.keyCode===27){n.destroy(i.type,i.newid);i.callback(false)}}},finishbuildQuiz:function(r,i,s){var o,u,a;n.listen(t.getElementById("quiz-cancel-"+i.newid),"click",function(){n.destroy(i.type,i.newid);i.callback(false)});if(o=t.getElementById("quiz-ok1-"+i.newid))n.listen(o,"click",function(){n.destroy(i.type,i.newid);i.callback(o.innerHTML)});if(u=t.getElementById("quiz-ok2-"+i.newid))n.listen(u,"click",function(){n.destroy(i.type,i.newid);i.callback(u.innerHTML)});if(a=t.getElementById("quiz-ok3-"+i.newid))n.listen(a,"click",function(){n.destroy(i.type,i.newid);i.callback(a.innerHTML)});t.onkeyup=function(t){if(!t){t=e.event}if(t.keyCode===27){n.destroy(i.type,i.newid);i.callback(false)}}},finishbuildPrompt:function(r,i,s){var o=t.getElementById("dialog-input-"+i.newid);setTimeout(function(){o.focus();o.select()},100);n.listen(t.getElementById("prompt-cancel-"+i.newid),"click",function(){n.destroy(i.type,i.newid);i.callback(false)});n.listen(t.getElementById("prompt-ok-"+i.newid),"click",function(){n.destroy(i.type,i.newid);i.callback(o.value)});t.onkeyup=function(t){if(!t){t=e.event}if(t.keyCode===13){n.destroy(i.type,i.newid);i.callback(o.value)}else if(t.keyCode===27){n.destroy(i.type,i.newid);i.callback(false)}}},finishbuildSignal:function(r,i,s){t.onkeyup=function(t){if(!t){t=e.event}if(t.keyCode===27){n.destroy(i.type,i.newid);if(typeof i.callback!=="undefined"){i.callback()}}};n.smoketimeout[i.newid]=setTimeout(function(){n.destroy(i.type,i.newid);if(typeof i.callback!=="undefined"){i.callback()}},i.timeout)},destroy:function(e,r){var i=t.getElementById("smoke-out-"+r);if(e!=="quiz"){var s=t.getElementById(e+"-ok-"+r)}var o=t.getElementById(e+"-cancel-"+r);i.className="smoke-base";if(s){n.stoplistening(s,"click",function(){});t.onkeyup=null}if(e==="quiz"){var u=t.getElementsByClassName("quiz-button");for(var a=0;a - - - - wxPython CEF 3 example (utf-8: ąś) - - - - - - - - - -Use the mouse context menu to go Back/Forward in history navigation. - -

      Table of contents

      -
        -
      1. Google search
      2. -
      3. User agent
      4. -
      5. Popups
      6. -
      7. HTML 5 video
      8. -
      9. Developer Tools
      10. -
      11. Downloads
      12. -
      13. HTML controls
      14. -
      15. Browser object
      16. -
      17. Frame object
      18. -
      19. Javascript bindings
      20. -
      21. Javascript callbacks
      22. -
      23. Python callbacks
      24. -
      25. Display handler
      26. -
      27. Keyboard handler
      28. -
      29. Request handler
      30. -
      31. Cookie tests
      32. -
      33. Load handler
      34. -
      35. Javascript Dialog handler
      36. -
      37. Other tests
      38. -
      - - - - - - -

      Google search

      - -http://www.google.com/ - - - - - - - -

      User agent

      - - - - - - - - - -

      Popups

      - -
        -
      1. - window.open('wxpython.html') -
      2. -
      3. - target=_blank href="wxpython.html" -
      4. -
      5. - window.open('https://www.google.com/') -
      6. -
      - -There are problems with keyboard in wxPython when popup windows are created -by CEF ( -Issue 80). To create the popup window of our own, the -LifespanHandler::OnBeforePopup callback was implemented. Note that this has -its implications, the popup window and parent window will not be able to -script each other. There will be no "window.opener" property available -in the popup window. - -See its source: - - - - -

      CreateAnotherBrowser

      - -This will create a window on its own and embed browser in it. -When using "window.open" the window is created implicitilly -by CEF. You can intercept such popup creation using the -OnBeforePopup callback in LifespanHandler. You can return -True in OnBeforePopup and create popup window on your own -using the CreateAnotherBrowser function. - - - - external.CreateAnotherBrowser() - - - - - - - -

      HTML5 video and accelerated content

      - - -HTML 5 video
      - - -Accelerated canvas
      - - -Accelerated layers
      - - - - - - -

      Developer Tools

      - -You can open devtools popup window in a few different ways: -
        -
      1. Call Browser.ShowDevTools() method: - - external.ShowDevTools()
      2. -
      3. Through mouse context menu
      4. -
      5. Through F12 key which is handled in KeyboardHandler.OnKeyEvent
      6. -
      - - - - - - -

      Downloads

      - -Download sample Ubuntu wallpapers:
      - - https://cefpython.googlecode.com/files/ubuntu-wallpapers2.zip - -

      -Notes: On Linux it seems that OnLoadError with errorCode = ERR_ABORTED -is called even for successful downloads, you can ignore this behavior. -The proper console messages about successful/aborted download originate -from C++ Browser process code, these are: -

      - -
      Browser: About to download file: ubuntu-wallpapers2.zip
      -Browser: Download completed, saved to: /Downloads/ubuntu-wallpapers2.zip
      -
      - -If download was aborted the messages will be: - -
      Browser: About to download file: ubuntu-wallpapers2.zip
      -Browser: Download was cancelled
      -
      - -

      -Additionally on Linux there are more errors reported by Chromium -about org.gnome.SessionManager.inhibit. These can be safely ignored as well. -

      - -A download handler with callbacks like `OnBeforeDownload` and -`OnDownloadUpdated` may be exposed to CEF Python in the future. - - - - - - -

      HTML controls

      - -

      Textarea

      - -
      - -

      Inputs

      -Text:
      -Password:
      - -

      Select

      - - -

      Buttons

      -Submit:
      -Button:
      - - - - - - -

      Browser object

      - -Tests for the Browser object methods. - -

      GoBack

      - -external.GoBack() - -

      GoForward

      - -external.GoForward() - -

      LoadUrl, GetUrl

      - - - window.open('data:text/html,Test#Browser.LoadUrl') - -

      SetZoomLevel

      -(You must set ApplicationSettings.auto_zooming = "" for SetZoomLevel calls -to work)
      -external.SetZoomLevel(2.0)
      -external.SetZoomLevel(1.0) - -

      ReloadIgnoreCache, StopLoad

      -Press F5 to reload page and ignore cache.
      -Press Esc during webpage loading to abort.
      - -Also, when Esc is pressed OnLoadError may get called. See how abort -of page loading or file download is handled: - - - - - - - -

      Frame object

      - -Tests for the Frame object methods. TODO. - - - - - - -

      Javascript bindings

      - -

      PyPrint

      - - - window.PyPrint('printing in python console from js') -
      - -

      Window properties

      - -
      jsBindings.SetProperty("pyProperty", "This was set in Python")
      -jsBindings.SetProperty("pyConfig", ["This was set in Python",
      -        {"name": "Nested dictionary", "isNested": True},
      -        [1,"2", None]])
      -
      - - - window.alert(window.pyProperty)
      - - window.alert(JSON.stringify(window.pyConfig)) -
      - -

      Print

      - - - - external.Print('printing again from js') -
      - -

      TestAllTypes

      - - - - external.TestAllTypes - (undefined, null, true, 1, - ((1<<31)>>>0), 2.14, 'Date not yet supported', 'string', - {key1: 1, key2: 2}, {key1: {'key1.1': 'nested object'}, 'key1.2': [1]}, - [1, 2], [1, [2.1, 'nested array']], [{key1: [{}]}]) -
      - -

      ExecuteFunction

      - - - -
      <script>
      -function JavascriptAlert(message) { window.alert(message); }
      -</script>
      -
      - - - - external.ExecuteFunction('JavascriptAlert', - 'python called from js and then js called from python', 0, [1,2]) -
      - -

      GetSource, GetText

      - - - - - - - external.GetSource() -
      - - external.GetText() - - - - - - -

      Javascript callbacks

      - -

      TestJSCallback

      - - - -
      <script>
      -function JSCallback(arg1) {
      -    window.alert(arg1)
      -}
      -</script>
      -
      - - - - external.TestJSCallback(JSCallback) - -

      TestJSCallbackComplexArguments

      - - - -
      <script>
      -function JSCallback2() {
      -    window.alert(JSON.stringify(arguments))
      -}
      -</script>
      -
      - - - - external.TestJSCallbackComplexArguments({"myCallback": JSCallback2}) - - - - - - - -

      Python callbacks

      - -

      TestPythonCallback

      - - - -
      <script>
      -function JSCallback3(pyCallback) {
      -    pyCallback(1, 2.14, "string", [1, [2, {"key": "value"}]], {"list": [1,2]});
      -}
      -</script>
      -
      - - - - - - external.TestPythonCallback(JSCallback3) - - - - - - -

      Display handler

      - -

      OnAddressChange

      - -See messages in the console during loading of a webpage. - -

      OnTitleChange

      - -See messages in the console during loading of a webpage. - -

      OnTooltip

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

      OnStatusMessage

      - -See messages in the console when hovering over links. - -

      OnConsoleMessage

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

      Keyboard handler

      - -

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

      - - - - - - - - - -

      Request handler

      - -

      OnBeforeResourceLoad

      - -See messages in the console. - -

      OnResourceRedirect

      - -Try this: - - http://tinyurl.com/google404redirect - -

      GetAuthCredentials

      - -Try this: - - http://browserspy.dk/password-ok.php - -

      OnQuotaRequest

      - - - - -
      <script>
      -function DoRequestQuota() {
      -    // Request Quota (only for File System API)
      -    try {
      -        navigator.webkitPersistentStorage.requestQuota(PERSISTENT, 1024*1024,
      -                function(bytes){ window.alert("Granted bytes: "+bytes);},
      -                function(error){ window.alert(error); });
      -    } catch(e) {
      -        navigator.webkitPersistentStorage.requestQuota(1024*1024,
      -                function(bytes){ window.alert("Granted bytes: "+bytes);},
      -                function(error){ window.alert(error); });
      -    }
      -}
      -</script>
      -
      - -Try this: - - https://googledrive.com/host/0B1di2XiBBfacMnhRRkI1YlotUEk/requestquota.html - -

      OnProtocolExecution

      - - -Try magnet link to download a torrent: - - magnet:?xt=urn:btih:a4224b45b27f436374391379cc5c7e629e2e5189 - -

      _OnBeforePluginLoad

      - -Try OnBeforePluginLoad() with Flash: - - http://www.adobe.com/software/flash/about/ - -

      _OnCertificateError

      - - -The url below won't be allowed. Click twice "Back" from context menu -to return back here after visiting that url:
      - - https://testssl-expire.disig.sk/index.en.html -
      - -This url will be allowed:
      - - https://testssl-expire.disig.sk/index.en.html?allow=1 -
      -After you've clicked the second url, the first one will now be allowed, -as this is the same domain and it's cached now. - -

      OnRendererProcessTerminated

      - -Try to terminate the "subprocess.exe" renderer process through -task manager. - -

      OnPluginCrashed

      - -No test for that yet. - - - - - - -

      Cookie tests

      - -See messages in the console. - -

      GetCookieManager

      - - - -RequestHandler.GetCookieManager() - an example of having an unique -cookie manager for each browser. -
        -
      1. Visit the url below and set some cookies. Use "Back" from - context menu to get back here (you might have to click "Back" - multiple times).
        - Visit it in the current browser:
        - - http://www.html-kit.com/tools/cookietester/ -
      2. -
      3. Open cookietester in a popup - a separate cookie manager is used:
        - - javascript:external.CreateAnotherBrowser('http://www.html-kit.com/tools/cookietester/') -
      4. -
      - -

      -Popup browsers created javascript's window.open share -the same renderer process and request context. If you want -to have separate cookie managers for popups created using -window.open then you have to implement the -LifespanHandler.`OnBeforePopup` callback. Return True in that -callback to cancel popup creation and instead create the -window on your own and embed browser in it. The CreateAnotherBrowser() -function from the wxpython example does that. -

      - -

      VisitAllCookies

      - -Visit all cookies: -external.VisitAllCookies() -

      - -Note: visit some http:// webpage first, otherwise cookie manager is not -yet created. -
      - -

      VisitUrlCookies

      - -Visit a subset of cookies for the given url: - - external.VisitUrlCookies("http://www.html-kit.com/tools/cookietester/") -
      - -

      SetCookie

      - -Set a cookie on html-kit.com: -external.SetCookie() -
      -Go see the cookie that was created: - - http://www.html-kit.com/tools/cookietester/ - -

      DeleteCookies

      - -Delete the single cookie previously created via SetCookie(): - - external.DeleteCookies() -
      -Go check if cookie was deleted: - - http://www.html-kit.com/tools/cookietester/ - - - - - - -

      Load Handler

      - -See messages in the console during loading of a webpage. - -

      OnLoadingStateChange

      - - -

      OnLoadStart

      - - -

      OnLoadEnd

      - - -

      OnLoadError

      - -After you see the custom error message you have to hit -twice the Back from the context menu, to get back to this page. -
      -Try this: - - http://www.non-existent.nono/ -
      - - - - - - - - -

      Javascript Dialog Handler

      - -See messages in the console. - -

      OnJavascriptDialog

      - - - window.alert('Test js dialog handler') - - -

      OnBeforeUnloadJavascriptDialog

      - - - -
      <script>
      -function TestOnBeforeUnloadJavascriptDialog() {
      -    window.onbeforeunload = function() {
      -        return 'Testing the OnBeforeUnloadJavascriptDialog() callback';
      -    }
      -    location.href = "wxpython.html";
      -}
      -</script>
      -
      - - - TestOnBeforeUnloadJavascriptDialog() - - -

      OnResetJavascriptDialogState

      - - -

      OnJavascriptDialogClosed

      - - - - - - - -

      Other tests

      - -

      HTTPS caching with SSL certificate errors

      -Set ApplicationSettings["ignore_certificate_errors"] to True. - - - - - - - - - - - - - diff --git a/src/windows/binaries_64bit/wxpython.py b/src/windows/binaries_64bit/wxpython.py deleted file mode 100644 index ed6bb44bd..000000000 --- a/src/windows/binaries_64bit/wxpython.py +++ /dev/null @@ -1,906 +0,0 @@ -# An example of embedding CEF browser in wxPython on Windows. -# Tested with wxPython 2.8.12.1 and 3.0.2.0. - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import a local module - if (2,7) <= sys.version_info < (2,8): - import cefpython_py27 as cefpython - elif (3,4) <= sys.version_info < (3,4): - import cefpython_py34 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import an installed package - from cefpython3 import cefpython - -import wx -import time -import re -import uuid -import platform -import inspect -import struct - -# ----------------------------------------------------------------------------- -# Globals - -g_applicationSettings = None -g_browserSettings = None -g_commandLineSwitches = None - -# Which method to use for message loop processing. -# EVT_IDLE - wx application has priority -# EVT_TIMER - cef browser has priority (default) -# It seems that Flash content behaves better when using a timer. -# Not sure if using EVT_IDLE is correct, it doesn't work on Linux, -# on Windows it works fine. See also the post by Robin Dunn: -# https://groups.google.com/d/msg/wxpython-users/hcNdMEx8u48/MD5Jgbm_k1kJ -USE_EVT_IDLE = False # If False then Timer will be used - -TEST_EMBEDDING_IN_PANEL = True - -# ----------------------------------------------------------------------------- - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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" (os._exit()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("[wxpython.py] WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainFrame(wx.Frame): - browser = None - mainPanel = None - - def GetHandleForBrowser(self): - if self.mainPanel: - return self.mainPanel.GetHandle() - else: - return self.GetHandle() - - def __init__(self, url=None, popup=False): - if popup: - title = "wxPython Popup" - else: - title = "wxPython CEF 3 example" - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, - title=title) - size=(800,600) - - # This is an optional code to enable High DPI support. - if "auto_zooming" in g_applicationSettings \ - and g_applicationSettings["auto_zooming"] == "system_dpi": - # This utility function will adjust width/height using - # OS DPI settings. For 800/600 with Win7 DPI settings - # being set to "Larger 150%" will return 1200/900. - size = cefpython.DpiAware.CalculateWindowSize(size[0], size[1]) - - self.SetSize(size) - - if not url: - url = "file://"+GetApplicationPath("wxpython.html") - # Test hash in url. - # url += "#test-hash" - - self.CreateMenu() - - if TEST_EMBEDDING_IN_PANEL: - print("Embedding in a wx.Panel!") - # You also have to set the wx.WANTS_CHARS style for - # all parent panels/controls, if it's deeply embedded. - self.mainPanel = wx.Panel(self, style=wx.WANTS_CHARS) - - # Global client callbacks must be set before browser is created. - self.clientHandler = ClientHandler() - cefpython.SetGlobalClientCallback("OnCertificateError", - self.clientHandler._OnCertificateError) - cefpython.SetGlobalClientCallback("OnBeforePluginLoad", - self.clientHandler._OnBeforePluginLoad) - cefpython.SetGlobalClientCallback("OnAfterCreated", - self.clientHandler._OnAfterCreated) - - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(self.GetHandleForBrowser()) - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings=g_browserSettings, - navigateUrl=url) - - self.clientHandler.mainBrowser = self.browser - self.browser.SetClientHandler(self.clientHandler) - - jsBindings = cefpython.JavascriptBindings( - bindToFrames=False, bindToPopups=True) - jsBindings.SetFunction("PyPrint", PyPrint) - jsBindings.SetProperty("pyProperty", "This was set in Python") - jsBindings.SetProperty("pyConfig", ["This was set in Python", - {"name": "Nested dictionary", "isNested": True}, - [1,"2", None]]) - self.javascriptExternal = JavascriptExternal(self.browser) - jsBindings.SetObject("external", self.javascriptExternal) - jsBindings.SetProperty("sources", GetSources()) - self.browser.SetJavascriptBindings(jsBindings) - - if self.mainPanel: - self.mainPanel.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) - self.mainPanel.Bind(wx.EVT_SIZE, self.OnSize) - else: - self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) - self.Bind(wx.EVT_SIZE, self.OnSize) - - self.Bind(wx.EVT_CLOSE, self.OnClose) - if USE_EVT_IDLE and not popup: - # Bind EVT_IDLE only for the main application frame. - print("Using EVT_IDLE to execute the CEF message loop work") - self.Bind(wx.EVT_IDLE, self.OnIdle) - - def CreateMenu(self): - filemenu = wx.Menu() - filemenu.Append(1, "Open") - exit = filemenu.Append(2, "Exit") - self.Bind(wx.EVT_MENU, self.OnClose, exit) - aboutmenu = wx.Menu() - aboutmenu.Append(1, "CEF Python") - menubar = wx.MenuBar() - menubar.Append(filemenu,"&File") - menubar.Append(aboutmenu, "&About") - self.SetMenuBar(menubar) - - def OnSetFocus(self, event): - cefpython.WindowUtils.OnSetFocus(self.GetHandleForBrowser(), 0, 0, 0) - - def OnSize(self, event): - cefpython.WindowUtils.OnSize(self.GetHandleForBrowser(), 0, 0, 0) - - def OnClose(self, event): - # Remove all CEF browser references so that browser is closed - # cleanly. Otherwise there may be issues for example with cookies - # not being flushed to disk when closing app immediately - # (Issue 158). - del self.javascriptExternal.mainBrowser - del self.clientHandler.mainBrowser - del self.browser - - # Destroy wx frame, this will complete the destruction of CEF browser - self.Destroy() - - # In wx.chromectrl calling browser.CloseBrowser and/or self.Destroy - # may cause crashes when embedding multiple browsers in tab - # (Issue 107). In such case instead of calling CloseBrowser/Destroy - # try this code: - # | self.browser.ParentWindowWillClose() - # | event.Skip() - - def OnIdle(self, event): - cefpython.MessageLoopWork() - -def PyPrint(message): - print("[wxpython.py] PyPrint: "+message) - -class JavascriptExternal: - mainBrowser = None - stringVisitor = None - - def __init__(self, mainBrowser): - self.mainBrowser = mainBrowser - - def GoBack(self): - self.mainBrowser.GoBack() - - def GoForward(self): - self.mainBrowser.GoForward() - - def SetZoomLevel(self, zoomLevel): - self.mainBrowser.SetZoomLevel(zoomLevel) - - def CreateAnotherBrowser(self, url=None): - frame = MainFrame(url=url) - frame.Show() - - def Print(self, message): - print("[wxpython.py] Print: "+message) - - def TestAllTypes(self, *args): - print("[wxpython.py] TestAllTypes: "+str(args)) - - def ExecuteFunction(self, *args): - self.mainBrowser.ExecuteFunction(*args) - - def TestJSCallback(self, jsCallback): - print("[wxpython.py] jsCallback.GetFunctionName() = %s"\ - % jsCallback.GetFunctionName()) - print("[wxpython.py] jsCallback.GetFrame().GetIdentifier() = %s" % \ - jsCallback.GetFrame().GetIdentifier()) - jsCallback.Call("This message was sent from python using js callback") - - def TestJSCallbackComplexArguments(self, jsObject): - jsCallback = jsObject["myCallback"]; - jsCallback.Call(1, None, 2.14, "string", ["list", ["nested list", \ - {"nested object":None}]], \ - {"nested list next":[{"deeply nested object":1}]}) - - def TestPythonCallback(self, jsCallback): - jsCallback.Call(self.PyCallback) - - def PyCallback(self, *args): - message = "PyCallback() was executed successfully! "\ - "Arguments: %s" % str(args) - print("[wxpython.py] "+message) - self.mainBrowser.GetMainFrame().ExecuteJavascript( - "window.alert(\"%s\")" % message) - - def GetSource(self): - # Must keep a strong reference to the StringVisitor object - # during the visit. - self.stringVisitor = StringVisitor() - self.mainBrowser.GetMainFrame().GetSource(self.stringVisitor) - - def GetText(self): - # Must keep a strong reference to the StringVisitor object - # during the visit. - self.stringVisitor = StringVisitor() - self.mainBrowser.GetMainFrame().GetText(self.stringVisitor) - - def ShowDevTools(self): - print("[wxpython.py] external.ShowDevTools called") - self.mainBrowser.ShowDevTools() - - # ------------------------------------------------------------------------- - # Cookies - # ------------------------------------------------------------------------- - cookieVisitor = None - - def VisitAllCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.VisitAllCookies(self.cookieVisitor) - - def VisitUrlCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.VisitUrlCookies( - "http://www.html-kit.com/tools/cookietester/", - False, self.cookieVisitor) - # .www.html-kit.com - - def SetCookie(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - "the cookietester website first and create some cookies") - return - cookie = cefpython.Cookie() - cookie.SetName("Created_Via_Python") - cookie.SetValue("yeah really") - cookieManager.SetCookie("http://www.html-kit.com/tools/cookietester/", - cookie) - print("\n[wxpython.py] Cookie created! Visit html-kit cookietester to"\ - " see it") - - def DeleteCookies(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.DeleteCookies( - "http://www.html-kit.com/tools/cookietester/", - "Created_Via_Python") - print("\n[wxpython.py] Cookie deleted! Visit html-kit cookietester "\ - "to see the result") - -class StringVisitor: - def Visit(self, string): - print("\n[wxpython.py] StringVisitor.Visit(): string:") - print("--------------------------------") - print(string) - print("--------------------------------") - -class CookieVisitor: - def Visit(self, cookie, count, total, deleteCookie): - if count == 0: - print("\n[wxpython.py] CookieVisitor.Visit(): total cookies: %s"\ - % total) - print("\n[wxpython.py] CookieVisitor.Visit(): cookie:") - print(" "+str(cookie.Get())) - # True to continue visiting cookies - return True - -class ClientHandler: - mainBrowser = None # May be None for global client callbacks. - - def __init__(self): - pass - - # ------------------------------------------------------------------------- - # DisplayHandler - # ------------------------------------------------------------------------- - - def OnAddressChange(self, browser, frame, url): - print("[wxpython.py] DisplayHandler::OnAddressChange()") - print(" url = %s" % url) - - def OnTitleChange(self, browser, title): - print("[wxpython.py] DisplayHandler::OnTitleChange()") - print(" title = %s" % title) - - def OnTooltip(self, browser, textOut): - # OnTooltip not yet implemented (both Linux and Windows), - # will be fixed in next CEF release, see Issue 783: - # https://code.google.com/p/chromiumembedded/issues/detail?id=783 - print("[wxpython.py] DisplayHandler::OnTooltip()") - print(" text = %s" % textOut[0]) - - statusMessageCount = 0 - def OnStatusMessage(self, browser, value): - if not value: - # Do not notify in the console about empty statuses. - return - self.statusMessageCount += 1 - if self.statusMessageCount > 3: - # Do not spam too much. - return - print("[wxpython.py] DisplayHandler::OnStatusMessage()") - print(" value = %s" % value) - - def OnConsoleMessage(self, browser, message, source, line): - print("[wxpython.py] DisplayHandler::OnConsoleMessage()") - print(" message = %s" % message) - print(" source = %s" % source) - print(" line = %s" % line) - - # ------------------------------------------------------------------------- - # KeyboardHandler - # ------------------------------------------------------------------------- - - def OnPreKeyEvent(self, browser, event, eventHandle, - isKeyboardShortcutOut): - print("[wxpython.py] KeyboardHandler::OnPreKeyEvent()") - - def OnKeyEvent(self, browser, event, eventHandle): - if event["type"] == cefpython.KEYEVENT_KEYUP: - # OnKeyEvent is called twice for F5/Esc keys, with event - # type KEYEVENT_RAWKEYDOWN and KEYEVENT_KEYUP. - # Normal characters a-z should have KEYEVENT_CHAR. - return False - print("[wxpython.py] KeyboardHandler::OnKeyEvent()") - print(" type=%s" % event["type"]) - print(" modifiers=%s" % event["modifiers"]) - print(" windows_key_code=%s" % event["windows_key_code"]) - print(" native_key_code=%s" % event["native_key_code"]) - print(" is_system_key=%s" % event["is_system_key"]) - print(" character=%s" % event["character"]) - print(" unmodified_character=%s" % event["unmodified_character"]) - print(" focus_on_editable_field=%s" \ - % event["focus_on_editable_field"]) - linux = (platform.system() == "Linux") - windows = (platform.system() == "Windows") - # F5 - if (linux and event["native_key_code"] == 71) \ - or (windows and event["windows_key_code"] == 116): - print("[wxpython.py] F5 pressed, calling" - " browser.ReloadIgnoreCache()") - browser.ReloadIgnoreCache() - return True - # Escape - if (linux and event["native_key_code"] == 9) \ - or (windows and event["windows_key_code"] == 27): - print("[wxpython.py] Esc pressed, calling browser.StopLoad()") - browser.StopLoad() - return True - # F12 - if (linux and event["native_key_code"] == 96) \ - or (windows and event["windows_key_code"] == 123): - print("[wxpython.py] F12 pressed, calling" - " browser.ShowDevTools()") - browser.ShowDevTools() - return True - return False - - # ------------------------------------------------------------------------- - # RequestHandler - # ------------------------------------------------------------------------- - - def OnBeforeBrowse(self, browser, frame, request, isRedirect): - print("[wxpython.py] RequestHandler::OnBeforeBrowse()") - print(" url = %s" % request.GetUrl()[:100]) - # Handle "magnet:" links. - if request.GetUrl().startswith("magnet:"): - print("[wxpython.p] RequestHandler::OnBeforeBrowse(): " - "magnet link clicked, cancelling browse request") - return True - return False - - def OnBeforeResourceLoad(self, browser, frame, request): - print("[wxpython.py] RequestHandler::OnBeforeResourceLoad()") - print(" url = %s" % request.GetUrl()[:100]) - return False - - def OnResourceRedirect(self, browser, frame, oldUrl, newUrlOut, request): - print("[wxpython.py] RequestHandler::OnResourceRedirect()") - print(" old url = %s" % oldUrl[:100]) - print(" new url = %s" % newUrlOut[0][:100]) - - def GetAuthCredentials(self, browser, frame, isProxy, host, port, realm, - scheme, callback): - # This callback is called on the IO thread, thus print messages - # may not be visible. - print("[wxpython.py] RequestHandler::GetAuthCredentials()") - print(" host = %s" % host) - print(" realm = %s" % realm) - callback.Continue(username="test", password="test") - return True - - def OnQuotaRequest(self, browser, originUrl, newSize, callback): - print("[wxpython.py] RequestHandler::OnQuotaRequest()") - print(" origin url = %s" % originUrl) - print(" new size = %s" % newSize) - callback.Continue(True) - return True - - def GetCookieManager(self, browser, mainUrl): - # Create unique cookie manager for each browser. - # You must set the "unique_request_context_per_browser" - # application setting to True for the cookie manager - # to work. - # Return None to have one global cookie manager for - # all CEF browsers. - if not browser: - # The browser param may be empty in some exceptional - # case, see docs. - return None - cookieManager = browser.GetUserData("cookieManager") - if cookieManager: - return cookieManager - else: - print("[wxpython.py] RequestHandler::GetCookieManager():"\ - " created cookie manager") - cookieManager = cefpython.CookieManager.CreateManager("") - if "cache_path" in g_applicationSettings: - path = g_applicationSettings["cache_path"] - # path = os.path.join(path, "cookies_browser_{}".format( - # browser.GetIdentifier())) - cookieManager.SetStoragePath(path) - browser.SetUserData("cookieManager", cookieManager) - return cookieManager - - def OnProtocolExecution(self, browser, url, allowExecutionOut): - # There's no default implementation for OnProtocolExecution on Linux, - # you have to make OS system call on your own. You probably also need - # to use LoadHandler::OnLoadError() when implementing this on Linux. - print("[wxpython.py] RequestHandler::OnProtocolExecution()") - print(" url = %s" % url) - if url.startswith("magnet:"): - print("[wxpython.py] Magnet link allowed!") - allowExecutionOut[0] = True - - def _OnBeforePluginLoad(self, browser, mimeType, pluginUrl, topOriginUrl, - info): - # This is a global callback set using SetGlobalClientCallback(). - # Plugins are loaded on demand, only when website requires it, - # the same plugin may be called multiple times. - # This callback is called on various threads, thus print messages - # may not be visible. - print("[wxpython.py] RequestHandler::_OnBeforePluginLoad()") - print(" mimeType = %s" % mimeType) - print(" pluginUrl = %s" % pluginUrl) - print(" topOriginUrl = %s" % topOriginUrl) - print(" info.GetName() = %s" % info.GetName()) - print(" info.GetPath() = %s" % info.GetPath()) - print(" info.GetVersion() = %s" % info.GetVersion()) - print(" info.GetDescription() = %s" % info.GetDescription()) - # False to allow, True to block plugin. - return False - - def _OnCertificateError(self, certError, requestUrl, callback): - # This is a global callback set using SetGlobalClientCallback(). - print("[wxpython.py] RequestHandler::_OnCertificateError()") - print(" certError = %s" % certError) - print(" requestUrl = %s" % requestUrl) - if requestUrl == "https://testssl-expire.disig.sk/index.en.html": - print(" Not allowed!") - return False - if requestUrl \ - == "https://testssl-expire.disig.sk/index.en.html?allow=1": - print(" Allowed!") - callback.Continue(True) - return True - return False - - def OnRendererProcessTerminated(self, browser, status): - print("[wxpython.py] RequestHandler::OnRendererProcessTerminated()") - statuses = { - cefpython.TS_ABNORMAL_TERMINATION: "TS_ABNORMAL_TERMINATION", - cefpython.TS_PROCESS_WAS_KILLED: "TS_PROCESS_WAS_KILLED", - cefpython.TS_PROCESS_CRASHED: "TS_PROCESS_CRASHED" - } - statusName = "Unknown" - if status in statuses: - statusName = statuses[status] - print(" status = %s" % statusName) - - def OnPluginCrashed(self, browser, pluginPath): - print("[wxpython.py] RequestHandler::OnPluginCrashed()") - print(" plugin path = %s" % pluginPath) - - # ------------------------------------------------------------------------- - # LoadHandler - # ------------------------------------------------------------------------- - - def OnLoadingStateChange(self, browser, isLoading, canGoBack, - canGoForward): - print("[wxpython.py] LoadHandler::OnLoadingStateChange()") - print(" isLoading = %s, canGoBack = %s, canGoForward = %s" \ - % (isLoading, canGoBack, canGoForward)) - - def OnLoadStart(self, browser, frame): - print("[wxpython.py] LoadHandler::OnLoadStart()") - print(" frame url = %s" % frame.GetUrl()[:100]) - - def OnLoadEnd(self, browser, frame, httpStatusCode): - print("[wxpython.py] LoadHandler::OnLoadEnd()") - print(" frame url = %s" % frame.GetUrl()[:100]) - # For file:// urls the status code = 0 - print(" http status code = %s" % httpStatusCode) - # Tests for the Browser object methods - self._Browser_LoadUrl(browser) - - def _Browser_LoadUrl(self, browser): - if browser.GetUrl() == "data:text/html,Test#Browser.LoadUrl": - browser.LoadUrl("file://"+GetApplicationPath("wxpython.html")) - - def OnLoadError(self, browser, frame, errorCode, errorTextList, failedUrl): - print("[wxpython.py] LoadHandler::OnLoadError()") - print(" frame url = %s" % frame.GetUrl()[:100]) - print(" error code = %s" % errorCode) - print(" error text = %s" % errorTextList[0]) - print(" failed url = %s" % failedUrl) - # Handle ERR_ABORTED error code, to handle the following cases: - # 1. Esc key was pressed which calls browser.StopLoad() in OnKeyEvent - # 2. Download of a file was aborted - # 3. Certificate error - if errorCode == cefpython.ERR_ABORTED: - print("[wxpython.py] LoadHandler::OnLoadError(): Ignoring load " - "error: Esc was pressed or file download was aborted, " - "or there was certificate error") - return; - customErrorMessage = "My custom error message!" - frame.LoadUrl("data:text/html,%s" % customErrorMessage) - - # ------------------------------------------------------------------------- - # LifespanHandler - # ------------------------------------------------------------------------- - - # ** This callback is executed on the IO thread ** - # Empty place-holders: popupFeatures, client. - def OnBeforePopup(self, browser, frame, targetUrl, targetFrameName, - targetDisposition, userGesture, - popupFeatures, windowInfo, client, browserSettings, - noJavascriptAccess): - print("[wxpython.py] LifespanHandler::OnBeforePopup()") - print(" targetUrl = %s" % targetUrl) - - # Custom browser settings for popups: - # > browserSettings[0] = {"plugins_disabled": True} - - # Set WindowInfo object: - # > windowInfo[0] = cefpython.WindowInfo() - - # On Windows there are keyboard problems in popups, when popup - # is created using "window.open" or "target=blank". This issue - # occurs only in wxPython. PyGTK or PyQt do not require this fix. - # The solution is to create window explicitilly, and not depend - # on CEF to create window internally. See Issue 80 for details: - # https://github.com/cztomczak/cefpython/issues/80 - - # If you set allowPopups=True then CEF will create popup window. - # The wx.Frame cannot be created here, as this callback is - # executed on the IO thread. Window should be created on the UI - # thread. One solution is to call cefpython.CreateBrowser() - # which runs asynchronously and can be called on any thread. - # The other solution is to post a task on the UI thread, so - # that cefpython.CreateBrowserSync() can be used. - - # Note that if you return True and create the popup window yourself, - # then the popup window and parent window will not be able to script - # each other. There will be no "window.opener" property available - # in the popup window. - - cefpython.PostTask(cefpython.TID_UI, self._CreatePopup, targetUrl) - - allowPopups = False - return not allowPopups - - def _CreatePopup(self, url): - frame = MainFrame(url=url, popup=True) - frame.Show() - - def _OnAfterCreated(self, browser): - # This is a global callback set using SetGlobalClientCallback(). - print("[wxpython.py] LifespanHandler::_OnAfterCreated()") - print(" browserId=%s" % browser.GetIdentifier()) - - def DoClose(self, browser): - print("[wxpython.py] LifespanHandler::DoClose()") - print(" browserId=%s" % browser.GetIdentifier()) - - def OnBeforeClose(self, browser): - print("[wxpython.py] LifespanHandler::OnBeforeClose") - print(" browserId=%s" % browser.GetIdentifier()) - - # ------------------------------------------------------------------------- - # JavascriptDialogHandler - # ------------------------------------------------------------------------- - - def OnJavascriptDialog(self, browser, originUrl, dialogType, - messageText, defaultPromptText, callback, - suppressMessage): - print("[wxpython.py] JavascriptDialogHandler::OnJavascriptDialog()") - print(" originUrl="+originUrl) - print(" dialogType="+str(dialogType)) - print(" messageText="+messageText) - print(" defaultPromptText="+defaultPromptText) - # If you want to suppress the javascript dialog: - # suppressMessage[0] = True - return False - - def OnBeforeUnloadJavascriptDialog(self, browser, messageText, isReload, - callback): - print("[wxpython.py] OnBeforeUnloadJavascriptDialog()") - print(" messageText="+messageText) - print(" isReload="+str(isReload)) - # Return True if the application will use a custom dialog: - # callback.Continue(allow=True, userInput="") - # return True - return False - - def OnResetJavascriptDialogState(self, browser): - print("[wxpython.py] OnResetDialogState()") - - def OnJavascriptDialogClosed(self, browser): - print("[wxpython.py] OnDialogClosed()") - - -class MyApp(wx.App): - timer = None - timerID = 1 - mainFrame = None - - def OnInit(self): - if not USE_EVT_IDLE: - print("[wxpython.py] Using TIMER to run CEF message loop") - self.CreateTimer() - self.mainFrame = MainFrame() - self.SetTopWindow(self.mainFrame) - self.mainFrame.Show() - return True - - def CreateTimer(self): - # See "Making a render loop": - # http://wiki.wxwidgets.org/Making_a_render_loop - # Another approach is to use EVT_IDLE in MainFrame, - # see which one fits you better. - self.timer = wx.Timer(self, self.timerID) - self.timer.Start(10) # 10ms - wx.EVT_TIMER(self, self.timerID, self.OnTimer) - - def OnTimer(self, event): - cefpython.MessageLoopWork() - - def OnExit(self): - # When app.MainLoop() returns, MessageLoopWork() should - # not be called anymore. - print("[wxpython.py] MyApp.OnExit") - if not USE_EVT_IDLE: - self.timer.Stop() - - -def GetSources(): - # Get sources of all python functions and methods from this file. - # This is to provide sources preview to wxpython.html. - # The dictionary of functions is binded to "window.sources". - thisModule = sys.modules[__name__] - functions = inspect.getmembers(thisModule, inspect.isfunction) - classes = inspect.getmembers(thisModule, inspect.isclass) - sources = {} - for funcTuple in functions: - sources[funcTuple[0]] = inspect.getsource(funcTuple[1]) - for classTuple in classes: - className = classTuple[0] - classObject = classTuple[1] - methods = inspect.getmembers(classObject) - for methodTuple in methods: - try: - sources[methodTuple[0]] = inspect.getsource(\ - methodTuple[1]) - except: - pass - return sources - - -if __name__ == '__main__': - print('[wxpython.py] architecture=%s-bit' % (8 * struct.calcsize("P"))) - print('[wxpython.py] wx.version=%s' % wx.version()) - - # Intercept python exceptions. Exit app immediately when exception - # happens on any of the threads. - sys.excepthook = ExceptHook - - # Application settings - g_applicationSettings = { - # Disk cache - # "cache_path": "webcache/", - - # CEF Python debug messages in console and in log_file - "debug": True, - # Set it to LOGSEVERITY_VERBOSE for more details - "log_severity": cefpython.LOGSEVERITY_INFO, - # Set to "" to disable logging to a file - "log_file": GetApplicationPath("debug.log"), - - # These directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory(), - # The "subprocess" executable that launches the Renderer - # and GPU processes among others. You may rename that - # executable if you like. - "browser_subprocess_path": "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess"), - - # This option is required for the GetCookieManager callback - # to work. It affects renderer processes, when this option - # is set to True. It will force a separate renderer process - # for each browser created using CreateBrowserSync. - "unique_request_context_per_browser": True, - # Downloads are handled automatically. A default SaveAs file - # dialog provided by OS will be displayed. - - "downloads_enabled": True, - # Remote debugging port, required for Developer Tools support. - # A value of 0 will generate a random port. To disable devtools - # support set it to -1. - "remote_debugging_port": 0, - # Mouse context menu - "context_menu": { - "enabled": True, - "navigation": True, # Back, Forward, Reload - "print": True, - "view_source": True, - "external_browser": True, # Open in external browser - "devtools": True, # Developer Tools - }, - - # See also OnCertificateError which allows you to ignore - # certificate errors for specific websites. - "ignore_certificate_errors": True, - } - - # You can comment out the code below if you do not want High - # DPI support. If you disable it text will look fuzzy on - # high DPI displays. - # - # Enabling High DPI support in app can be done by - # embedding a DPI awareness xml manifest in executable - # (see Issue 112 comment #2), or by calling SetProcessDpiAware - # function. Embedding xml manifest is the most reliable method. - # The downside of calling SetProcessDpiAware is that scrollbar - # in CEF browser is smaller than it should be. This is because - # DPI awareness was set too late, after the CEF dll was loaded. - # To fix that embed DPI awareness xml manifest in the .exe file. - # - # There is one bug when enabling High DPI support - fonts in - # javascript dialogs (alert) are tiny. However, you can implement - # custom javascript dialogs using JavascriptDialogHandler. - # - # Additionally you have to set "auto_zomming" application - # setting. High DPI support is available only on Windows. - # You may set auto_zooming to "system_dpi" and browser - # contents will be zoomed using OS DPI settings. On Win7 - # these can be set in: Control Panel > Appearance and - # Personalization > Display. - # - # Example values for auto_zooming are: - # "system_dpi", "0.0" (96 DPI), "1.0" (120 DPI), - # "2.0" (144 DPI), "-1.0" (72 DPI) - # Numeric value means a zoom level. - # Example values that can be set in Win7 DPI settings: - # Smaller 100% (Default) = 96 DPI = 0.0 zoom level - # Medium 125% = 120 DPI = 1.0 zoom level - # Larger 150% = 144 DPI = 2.0 zoom level - # Custom 75% = 72 DPI = -1.0 zoom level - g_applicationSettings["auto_zooming"] = "system_dpi" - print("[wxpython.py] Calling SetProcessDpiAware") - cefpython.DpiAware.SetProcessDpiAware() - - # Browser settings. You may have different settings for each - # browser, see the call to CreateBrowserSync. - g_browserSettings = { - # "plugins_disabled": True, - # "file_access_from_file_urls_allowed": True, - # "universal_access_from_file_urls_allowed": True, - } - - # Command line switches set programmatically - g_commandLineSwitches = { - # "proxy-server": "socks5://127.0.0.1:8888", - # "no-proxy-server": "", - # "enable-media-stream": "", - # "disable-gpu": "", - - } - - cefpython.Initialize(g_applicationSettings, g_commandLineSwitches) - - app = MyApp(False) - app.MainLoop() - - # Let wx.App destructor do the cleanup before calling - # cefpython.Shutdown(). This is to ensure reliable CEF shutdown. - del app - - cefpython.Shutdown() - diff --git a/src/windows/cefpython.rc b/src/windows/cefpython.rc deleted file mode 100644 index feb9c0a56..000000000 --- a/src/windows/cefpython.rc +++ /dev/null @@ -1,31 +0,0 @@ -1 VERSIONINFO -FILEVERSION 31,2,0,0 -PRODUCTVERSION 31,2,0,0 -FILEFLAGSMASK 0x3FL -FILEFLAGS 0x0L -FILEOS 0x4L -FILETYPE 0x2L -FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - BEGIN - VALUE "CompanyName", "CEF Python" - VALUE "FileDescription", "CEF Python DLL" - VALUE "FileVersion", "31.2.0.0" - VALUE "InternalName", "cefpython" - VALUE "LegalCopyright", "(c) 2012 The CEF Python authors" - VALUE "LegalTrademarks", "" - VALUE "OriginalFilename", "cefpython_py27.pyd" - VALUE "ProductName", "CEF Python 3" - VALUE "ProductVersion", "31.2.0.0" - VALUE "Comments", "Licensed under the BSD 3-clause license" - VALUE "Aditional Notes", "" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END -END diff --git a/src/windows/compile.cmd b/src/windows/compile.cmd deleted file mode 100644 index 1e7613c05..000000000 --- a/src/windows/compile.cmd +++ /dev/null @@ -1 +0,0 @@ -cmd.exe /K compile.bat 99.99 diff --git a/src/windows/binaries_32bit/LICENSE.txt b/src/windows/deprecated_32bit/LICENSE.txt similarity index 100% rename from src/windows/binaries_32bit/LICENSE.txt rename to src/windows/deprecated_32bit/LICENSE.txt diff --git a/src/windows/binaries_32bit/README.txt b/src/windows/deprecated_32bit/README.txt similarity index 100% rename from src/windows/binaries_32bit/README.txt rename to src/windows/deprecated_32bit/README.txt diff --git a/src/windows/binaries_32bit/cefwindow.py b/src/windows/deprecated_32bit/cefwindow.py similarity index 100% rename from src/windows/binaries_32bit/cefwindow.py rename to src/windows/deprecated_32bit/cefwindow.py diff --git a/src/windows/binaries_32bit/example.html b/src/windows/deprecated_32bit/example.html similarity index 100% rename from src/windows/binaries_32bit/example.html rename to src/windows/deprecated_32bit/example.html diff --git a/src/windows/binaries_32bit/icon.ico b/src/windows/deprecated_32bit/icon.ico similarity index 100% rename from src/windows/binaries_32bit/icon.ico rename to src/windows/deprecated_32bit/icon.ico diff --git a/src/mac/binaries_32bit/prism.css b/src/windows/deprecated_32bit/prism.css similarity index 100% rename from src/mac/binaries_32bit/prism.css rename to src/windows/deprecated_32bit/prism.css diff --git a/src/mac/binaries_32bit/prism.js b/src/windows/deprecated_32bit/prism.js similarity index 100% rename from src/mac/binaries_32bit/prism.js rename to src/windows/deprecated_32bit/prism.js diff --git a/src/windows/binaries_32bit/pygtk_.py b/src/windows/deprecated_32bit/pygtk_.py similarity index 100% rename from src/windows/binaries_32bit/pygtk_.py rename to src/windows/deprecated_32bit/pygtk_.py diff --git a/src/windows/binaries_32bit/pyqt.py b/src/windows/deprecated_32bit/pyqt.py similarity index 100% rename from src/windows/binaries_32bit/pyqt.py rename to src/windows/deprecated_32bit/pyqt.py diff --git a/src/windows/binaries_32bit/pyside.py b/src/windows/deprecated_32bit/pyside.py similarity index 100% rename from src/windows/binaries_32bit/pyside.py rename to src/windows/deprecated_32bit/pyside.py diff --git a/src/windows/binaries_32bit/pywin32.py b/src/windows/deprecated_32bit/pywin32.py similarity index 100% rename from src/windows/binaries_32bit/pywin32.py rename to src/windows/deprecated_32bit/pywin32.py diff --git a/src/windows/binaries_32bit/smoke.css b/src/windows/deprecated_32bit/smoke.css similarity index 100% rename from src/windows/binaries_32bit/smoke.css rename to src/windows/deprecated_32bit/smoke.css diff --git a/src/windows/binaries_32bit/smoke.min.js b/src/windows/deprecated_32bit/smoke.min.js similarity index 100% rename from src/windows/binaries_32bit/smoke.min.js rename to src/windows/deprecated_32bit/smoke.min.js diff --git a/src/windows/binaries_32bit/wxpython.html b/src/windows/deprecated_32bit/wxpython.html similarity index 100% rename from src/windows/binaries_32bit/wxpython.html rename to src/windows/deprecated_32bit/wxpython.html diff --git a/src/windows/binaries_32bit/wxpython.py b/src/windows/deprecated_32bit/wxpython.py similarity index 100% rename from src/windows/binaries_32bit/wxpython.py rename to src/windows/deprecated_32bit/wxpython.py diff --git a/src/windows/setup/.gitignore b/src/windows/setup/.gitignore deleted file mode 100644 index d4b2c081e..000000000 --- a/src/windows/setup/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.cpp -*.pyx - diff --git a/src/windows/setup/cefpython.h b/src/windows/setup/cefpython.h deleted file mode 100644 index 180a379bd..000000000 --- a/src/windows/setup/cefpython.h +++ /dev/null @@ -1,94 +0,0 @@ -#pragma warning(disable:4190) - -#ifndef __PYX_HAVE__cefpython_py27 -#define __PYX_HAVE__cefpython_py27 - - -#ifndef __PYX_HAVE_API__cefpython_py27 - -#ifndef __PYX_EXTERN_C - #ifdef __cplusplus - #define __PYX_EXTERN_C extern "C" - #else - #define __PYX_EXTERN_C extern - #endif -#endif - -__PYX_EXTERN_C DL_IMPORT(void) PyBrowser_ShowDevTools(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) PyTaskRunnable(int); -__PYX_EXTERN_C DL_IMPORT(void) V8ContextHandler_OnContextCreated(CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) V8ContextHandler_OnContextReleased(int, int64); -__PYX_EXTERN_C DL_IMPORT(void) V8FunctionHandler_Execute(CefRefPtr, CefRefPtr, CefString &, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) RemovePythonCallbacksForFrame(int); -__PYX_EXTERN_C DL_IMPORT(bool) ExecutePythonCallback(CefRefPtr, int, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) LifespanHandler_OnBeforePopup(CefRefPtr, CefRefPtr, CefString const &, CefString const &, int const , CefWindowInfo &, CefRefPtr &, CefBrowserSettings &, bool *); -__PYX_EXTERN_C DL_IMPORT(void) LifespanHandler_OnAfterCreated(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) LifespanHandler_DoClose(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) LifespanHandler_OnBeforeClose(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnAddressChange(CefRefPtr, CefRefPtr, CefString const &); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnTitleChange(CefRefPtr, CefString const &); -__PYX_EXTERN_C DL_IMPORT(bool) DisplayHandler_OnTooltip(CefRefPtr, CefString &); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnStatusMessage(CefRefPtr, CefString const &); -__PYX_EXTERN_C DL_IMPORT(bool) DisplayHandler_OnConsoleMessage(CefRefPtr, CefString const &, CefString const &, int); -__PYX_EXTERN_C DL_IMPORT(bool) KeyboardHandler_OnPreKeyEvent(CefRefPtr, CefKeyEvent const &, CefEventHandle, bool *); -__PYX_EXTERN_C DL_IMPORT(bool) KeyboardHandler_OnKeyEvent(CefRefPtr, CefKeyEvent const &, CefEventHandle); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnBeforeResourceLoad(CefRefPtr, CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnBeforeBrowse(CefRefPtr, CefRefPtr, CefRefPtr, bool); -__PYX_EXTERN_C DL_IMPORT(CefRefPtr) RequestHandler_GetResourceHandler(CefRefPtr, CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) RequestHandler_OnResourceRedirect(CefRefPtr, CefRefPtr, CefString const &, CefString &); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_GetAuthCredentials(CefRefPtr, CefRefPtr, bool, CefString const &, int, CefString const &, CefString const &, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnQuotaRequest(CefRefPtr, CefString const &, int64, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(CefRefPtr) RequestHandler_GetCookieManager(CefRefPtr, CefString const &); -__PYX_EXTERN_C DL_IMPORT(void) RequestHandler_OnProtocolExecution(CefRefPtr, CefString const &, bool &); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnBeforePluginLoad(CefRefPtr, CefString const &, CefString const &, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnCertificateError(int, CefString const &, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) RequestHandler_OnRendererProcessTerminated(CefRefPtr, enum cef_termination_status_t); -__PYX_EXTERN_C DL_IMPORT(void) RequestHandler_OnPluginCrashed(CefRefPtr, CefString const &); -__PYX_EXTERN_C DL_IMPORT(bool) CookieVisitor_Visit(int, CefCookie const &, int, int, bool &); -__PYX_EXTERN_C DL_IMPORT(void) StringVisitor_Visit(int, CefString const &); -__PYX_EXTERN_C DL_IMPORT(void) LoadHandler_OnLoadingStateChange(CefRefPtr, bool, bool, bool); -__PYX_EXTERN_C DL_IMPORT(void) LoadHandler_OnLoadStart(CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) LoadHandler_OnLoadEnd(CefRefPtr, CefRefPtr, int); -__PYX_EXTERN_C DL_IMPORT(void) LoadHandler_OnLoadError(CefRefPtr, CefRefPtr, enum cef_errorcode_t, CefString const &, CefString const &); -__PYX_EXTERN_C DL_IMPORT(void) BrowserProcessHandler_OnRenderProcessThreadCreated(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) BrowserProcessHandler_OnBeforeChildProcessLaunch(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetRootScreenRect(CefRefPtr, CefRect &); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetViewRect(CefRefPtr, CefRect &); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetScreenRect(CefRefPtr, CefRect &); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetScreenPoint(CefRefPtr, int, int, int &, int &); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetScreenInfo(CefRefPtr, CefScreenInfo &); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnPopupShow(CefRefPtr, bool); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnPopupSize(CefRefPtr, CefRect const &); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnPaint(CefRefPtr, cef_paint_element_type_t, std::vector &, void const *, int, int); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnCursorChange(CefRefPtr, CefCursorHandle); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnScrollOffsetChanged(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) ResourceHandler_ProcessRequest(int, CefRefPtr, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) ResourceHandler_GetResponseHeaders(int, CefRefPtr, int64 &, CefString &); -__PYX_EXTERN_C DL_IMPORT(bool) ResourceHandler_ReadResponse(int, void *, int, int &, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) ResourceHandler_CanGetCookie(int, CefCookie const &); -__PYX_EXTERN_C DL_IMPORT(bool) ResourceHandler_CanSetCookie(int, CefCookie const &); -__PYX_EXTERN_C DL_IMPORT(void) ResourceHandler_Cancel(int); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnUploadProgress(int, CefRefPtr, uint64, uint64); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnDownloadProgress(int, CefRefPtr, uint64, uint64); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnDownloadData(int, CefRefPtr, void const *, size_t); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnRequestComplete(int, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) App_OnBeforeCommandLineProcessing_BrowserProcess(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(bool) JavascriptDialogHandler_OnJavascriptDialog(CefRefPtr, CefString const &, CefString const &, enum cef_jsdialog_type_t, CefString const &, CefString const &, CefRefPtr, bool &); -__PYX_EXTERN_C DL_IMPORT(bool) JavascriptDialogHandler_OnBeforeUnloadJavascriptDialog(CefRefPtr, CefString const &, bool, CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) JavascriptDialogHandler_OnResetJavascriptDialogState(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) JavascriptDialogHandler_OnJavascriptDialogClosed(CefRefPtr); -__PYX_EXTERN_C DL_IMPORT(void) cefpython_GetDebugOptions(bool *, std::string *); -__PYX_EXTERN_C DL_IMPORT(bool) ApplicationSettings_GetBool(char const *); -__PYX_EXTERN_C DL_IMPORT(bool) ApplicationSettings_GetBoolFromDict(char const *, char const *); -__PYX_EXTERN_C DL_IMPORT(std::string) ApplicationSettings_GetString(char const *); -__PYX_EXTERN_C DL_IMPORT(int) CommandLineSwitches_GetInt(char const *); - -#endif /* !__PYX_HAVE_API__cefpython_py27 */ - -#if PY_MAJOR_VERSION < 3 -PyMODINIT_FUNC initcefpython_py27(void); -#else -PyMODINIT_FUNC PyInit_cefpython_py27(void); -#endif - -#endif /* !__PYX_HAVE__cefpython_py27 */ diff --git a/src/windows/setup/compile_rc.py b/src/windows/setup/compile_rc.py deleted file mode 100644 index 8d53d8e26..000000000 --- a/src/windows/setup/compile_rc.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -# Compile cefptython.rc to a .res object. -# In setup.py the .res object is added to Extension."extra_objects". - -import os -import sys -import re -import subprocess -import shutil - -PYVERSION = str(sys.version_info[0])+str(sys.version_info[1]) # eg. "27" -RC_EXE = r"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\rc.exe" -RC_FILE = os.path.abspath(r"../cefpython.rc") -RES_FILE_OUT = os.path.abspath(r"../cefpython.res") -RES_FILE_MOVE = os.path.abspath(r"./cefpython.res") -RC_PYD_NAME = r"cefpython_py27.pyd" - -def log(msg): - print("[compile_rc.py] %s" % str(msg)) - -def main(): - # Arguments - if len(sys.argv) == 3 \ - and sys.argv[1] == "-v" \ - and re.search(r"^\d+\.\d+$", sys.argv[2]): - version = sys.argv[2] - else: - log("Invalid version string or missing. Usage: compile_rc.py -v 31.0") - exit(1) - - # Print paths - log("version="+version) - log("PYVERSION="+PYVERSION) - log("RC_EXE="+RC_EXE) - log("RC_FILE="+RC_FILE) - log("RES_FILE_OUT="+RES_FILE_OUT) - log("RES_FILE_MOVE="+RES_FILE_MOVE) - log("RC_PYD_NAME="+RC_PYD_NAME) - - # Check paths - assert os.path.exists(RC_EXE) - assert os.path.exists(RC_FILE) - - # Change version numbers in .rc file - with open(RC_FILE, "r") as f: - contents = f.read() - # FILEVERSION 31,1,0,0 - # "FileVersion", "31.1.0.0" - (contents, subn) = re.subn( - r"\d+\.\d+\.\d+\.\d+", - r"%s.0.0" % version, - contents) - assert subn == 2, "Replacing dots versions failed (rc file)" - version_commas = re.sub(r"\.", r",", version) - (contents, subn) = re.subn( - r"\d+,\d+,\d+,\d+", - r"%s,0,0" % version_commas, - contents) - assert subn == 2, "Replacing commas verions failed (rc file)" - - # Change pyd module name in .rc - assert contents.find(RC_PYD_NAME) != -1, "pyd file name not found in .rc" - assert RC_PYD_NAME.find("py27") != -1, "invalid pyd file name defined" - new_pyd_name = RC_PYD_NAME.replace("py27", "py"+PYVERSION) - contents = contents.replace(RC_PYD_NAME, new_pyd_name) - - # Save modified .rc file - log("Saving modified %s" % RC_FILE) - with open(RC_FILE, "w") as f: - f.write(contents) - - log("Calling rc.exe to compile .rc file") - # rc.exe usage: rc.exe /x file.rc - # /x - ignore INCLUDE environment variable - exit_status = subprocess.call([ - RC_EXE, - "/x", - RC_FILE, - ], shell=True) - if exit_status != 0: - raise Exception("Calling rc.exe failed") - - log("Moving .res object to setup/") - shutil.move(RES_FILE_OUT, RES_FILE_MOVE) - - -if __name__ == '__main__': - main() diff --git a/src/windows/setup/delete_pyx_files.bat b/src/windows/setup/delete_pyx_files.bat deleted file mode 100644 index ae1c5fbd1..000000000 --- a/src/windows/setup/delete_pyx_files.bat +++ /dev/null @@ -1,2 +0,0 @@ -for /R %~dp0 %%f in (*.pyx) do del "%%f" -pause \ No newline at end of file diff --git a/src/windows/setup/fix_cefpython_h.py b/src/windows/setup/fix_cefpython_h.py deleted file mode 100644 index dbcb535ec..000000000 --- a/src/windows/setup/fix_cefpython_h.py +++ /dev/null @@ -1,29 +0,0 @@ -""" -Get rid of warnings like this: - - cefpython.h(36) : warning C4190: 'RequestHandler_GetResourceHandler' - has C-linkage specified, but returns UDT 'CefRefPtr' which is - incompatible with C -""" - -import os - - -def main(): - if not os.path.exists("cefpython.h"): - print("[fix_cefpython_h.py] cefpython.h was not yet generated") - return - with open("cefpython.h", "r") as fo: - content = fo.read() - pragma = "#pragma warning(disable:4190)" - if pragma in content: - print("[fix_cefpython_h.py] cefpython.h is already fixed") - return - content = ("%s\n\n" % (pragma)) + content - with open("cefpython.h", "w") as fo: - fo.write(content) - print("[fix_cefpython_h.py] Saved cefpthon.h") - - -if __name__ == '__main__': - main() diff --git a/src/windows/setup/fix_pyx_files.py b/src/windows/setup/fix_pyx_files.py deleted file mode 100644 index 86ba1dbcb..000000000 --- a/src/windows/setup/fix_pyx_files.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -# First, it copies all .pyx files from upper directory to setup/. -# Then, fixes repeating of "include" statements in pyx files. - -# Only the mainfile needs to have "include" statements, -# but we're using PyCharm and to get rid of "unresolved references" -# and other errors displayed in pycharm we are adding "include" -# statements in all of the pyx files. - -# I'm not 100% sure how includes work in Cython, but I suspect that -# a few includes of the same file will include the same content more -# than once, it should work, but function and variable definitions are -# duplicated, it is some kind of overhead and it could lead to some -# problems in the future, better to fix it now. - -# It also checks cdef & cpdef functions whether they are not missing "except *", -# it is required to add it when returning non-python type. - -import glob -import os -import re -import shutil -import sys - -def ExceptAllMissing(content): - - # This is not perfect, won't detect C++ custom types, but will find - # the built-in types, templates and pointers. - patterns = [] - patterns.append( - r"\bcp?def\s+" - "((int|short|long|double|char|unsigned|float|double)\s+)+" - "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") - patterns.append( - r"\bcp?def\s+" - # A template ends with bracket: CefRefPtr[CefBrowser] - # or a pointer ends with asterisk: CefBrowser* - "[^\s]+[\]*]\s+" - "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") - patterns.append( - r"\bcp?def\s+" - # A reference, eg. CefString& - "[^\s]+&\s+" - "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") - - for pattern in patterns: - match = re.search(pattern, content) - if match: break - - if match: - lineNumber = (content.count("\n", 0, match.start()) + 1) - return lineNumber - -print("\n") -mainfile = "cefpython.pyx" - -pyxfiles = glob.glob("../../*.pyx") -if not len(pyxfiles): - sys.exit(1) -pyxfiles = [file for file in pyxfiles if file.find(mainfile) == -1] -# Now, pyxfiles contains all pyx files except the mainfile (cefpython.pyx), -# we do not fix includes in mainfile. - -# So that this is the right directory we're in. -if os.path.exists("setup"): - print("Wrong directory, we should be inside setup!") - sys.exit(1) - -# Remove old pyx files in setup directory. -oldpyxfiles = glob.glob("./*.pyx") -print("Removing old pyx files in /setup/: %s" % oldpyxfiles) -for pyxfile in oldpyxfiles: - if os.path.exists(pyxfile): - os.remove(pyxfile) - -# Copying pyxfiles and reading its contents. - -print("Copying .pyx files to /setup/: %s" % pyxfiles) -shutil.copy("../../%s" % mainfile, "./%s" % mainfile) -# Rest of the files will be copied in for loop below. - -print("Fixing includes in .pyx files:") -for pyxfile in pyxfiles: - newfile = "./%s" % os.path.basename(pyxfile) - shutil.copy(pyxfile, newfile) - pyxfile = newfile - with open(pyxfile, "r") as pyxfileopened: - content = pyxfileopened.read() - lineNumber = ExceptAllMissing(content) - if lineNumber: - print("WARNING: 'except *' missing in a cdef/cpdef function, " - "in file %s on line %d" % (os.path.basename(pyxfile), lineNumber)) - sys.exit(1) - # Do not remove the newline - so that line numbers are exact with originals. - (content, subs) = re.subn(r"^include[\t ]+[\"'][^\"'\n\r]+[\"'][\t ]*", "", content, flags=re.MULTILINE) - if subs: - print("%s includes removed in: %s" % (subs, os.path.basename(pyxfile))) - # Reading and writing with the same handle using "r+" mode doesn't work, - # you need to seek(0) and write the same amount of bytes that was in the - # file, otherwise old data from the end of file stays. - with open(pyxfile, "w") as pyxfileopened: - pyxfileopened.write(content) - -print("\n") diff --git a/src/windows/setup/lib_32bit/README b/src/windows/setup/lib_32bit/README deleted file mode 100644 index 72d1c6078..000000000 --- a/src/windows/setup/lib_32bit/README +++ /dev/null @@ -1 +0,0 @@ -Put libcef.lib and libcef_dll_wrapper.lib here. diff --git a/src/windows/setup/lib_64bit/README b/src/windows/setup/lib_64bit/README deleted file mode 100644 index 72d1c6078..000000000 --- a/src/windows/setup/lib_64bit/README +++ /dev/null @@ -1 +0,0 @@ -Put libcef.lib and libcef_dll_wrapper.lib here. diff --git a/src/windows/setup/setup.py b/src/windows/setup/setup.py deleted file mode 100644 index d40442155..000000000 --- a/src/windows/setup/setup.py +++ /dev/null @@ -1,115 +0,0 @@ -from distutils.core import setup -from distutils.extension import Extension - -from Cython.Distutils import build_ext -from Cython.Compiler import Options -import Cython - -import sys -import platform -import struct -import os - -BITS = str(8 * struct.calcsize('P')) + "bit" - -print("[setup.py] Python architecture: %s" % BITS) -print("[setup.py] Cython version: %s" % Cython.__version__) - -# Stop on first error, otherwise hundreds of errors appear in the console. -Options.fast_fail = True - -# Python version string: "27" or "32". -PYVER = str(sys.version_info.major) + str(sys.version_info.minor) - -# Generate compile_time_constants.pxi -def CompileTimeConstants(): - print("[setup.py] Generating: compile_time_constants.pxi") - with open("../../compile_time_constants.pxi", "w") as fd: - fd.write('# This file was generated by setup.py\n') - # A way around Python 3.2 bug: UNAME_SYSNAME is not set. - fd.write('DEF UNAME_SYSNAME = "%s"\n' % platform.uname()[0]) - fd.write('DEF PY_MAJOR_VERSION = %s\n' % sys.version_info.major) -CompileTimeConstants() - -# Windows SDK Lib directory. -# It's also hardcoded in compile.bat -if BITS == "32bit": - winsdk_lib = r"C:\Program Files\Microsoft SDKs\Windows\v7.0\Lib" -elif BITS == "64bit": - winsdk_lib = r"C:\Program Files\Microsoft SDKs\Windows\v7.0\Lib\x64" -if not os.path.exists(winsdk_lib): - raise Exception("Windows SDK Lib directory not found: %s" % winsdk_lib) - -ext_modules = [Extension( - - "cefpython_py%s" % PYVER, - ["cefpython.pyx"], - - # Ignore the warning in the console: - # > C:\Python27\lib\distutils\extension.py:133: UserWarning: - # > Unknown Extension options: 'cython_directives' warnings.warn(msg) - cython_directives={ - # Any conversion to unicode must be explicit using .decode(). - "c_string_type": "bytes", - "c_string_encoding": "utf-8", - }, - - language='c++', - - include_dirs=[ - r'./../', - r'./../../', - r'./../../extern/', - r'./../../extern/cef/', - ], - - library_dirs=[ - winsdk_lib, - r'./', - r'./lib_%s' % (BITS), - r'./../../client_handler/Release_py%s_%s/' % (PYVER, BITS), - r'./../../subprocess/Release_py%s_%s/' % (PYVER, BITS), - r'./../../cpp_utils/Release_%s/' % (BITS), - ], - - libraries=[ - 'libcef', - 'libcef_dll_wrapper_md', - 'User32', - 'client_handler_py%s_%s' % (PYVER, BITS), - 'libcefpythonapp_py%s_%s' % (PYVER, BITS), - 'cpp_utils_%s' % (BITS), - ], - - extra_objects=[ - "cefpython.res" - ], - - # /EHsc - using STL string, multimap and others that use C++ exceptions. - # - # /ignore:4217 - disable warnings such as this: - # - # client_handler_py27_32bit.lib(client_handler.obj) : warning LNK4217: - # locally defined symbol _RemovePythonCallbacksForFrame imported in - # function "public: virtual bool __thiscall - # ClientHandler::OnProcessMessageReceived - # - # The above warning LNK4217 is caused by the warning below which occurs - # when building the client_handler.lib static library: - # - # cefpython.h(36) : warning C4190: 'RequestHandler_GetResourceHandler' - # has C-linkage specified, but returns UDT 'CefRefPtr' which is - # incompatible with C - # - # The C4190 warning is disabled with pragma in cefpython.h, see the - # fix_cefpython_h.py script. - - extra_compile_args=['/EHsc'], - extra_link_args=['/ignore:4217'] -)] - -setup( - name = 'cefpython_py%s' % PYVER, - cmdclass = {'build_ext': build_ext}, - ext_modules = ext_modules -) diff --git a/src/windows/wxpython.bat b/src/windows/wxpython.bat deleted file mode 100644 index a5b131aa8..000000000 --- a/src/windows/wxpython.bat +++ /dev/null @@ -1,3 +0,0 @@ -cd binaries -call python "wxpython.py" -cd %~dp0 diff --git a/tools/automate.py b/tools/automate.py index 5b5a06673..4da35108a 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -36,46 +36,31 @@ """ +from common import * import os import sys import shlex import subprocess import platform import docopt -import struct -import re import stat import glob import shutil import multiprocessing -# CONSTANTS -ARCH32 = (8 * struct.calcsize('P') == 32) -ARCH64 = (8 * struct.calcsize('P') == 64) -OS_POSTFIX = ("win" if platform.system() == "Windows" else - "linux" if platform.system() == "Linux" else - "mac" if platform.system() == "Darwin" else "unknown") -OS_POSTFIX2 = "unknown" -if OS_POSTFIX == "win": - OS_POSTFIX2 = "win32" if ARCH32 else "win64" -elif OS_POSTFIX == "mac": - OS_POSTFIX2 = "mac32" if ARCH32 else "mac64" -elif OS_POSTFIX == "linux": - OS_POSTFIX2 = "linux32" if ARCH32 else "linux64" - CEF_GIT_URL = "https://bitbucket.org/chromiumembedded/cef.git" VS2015_VCVARS = "\"C:\Program Files (x86)\\Microsoft Visual Studio 14.0" \ - "\\VC\\bin\\vcvars32.bat\"" \ + "\\VC\\vcvarsall.bat\" x86" \ if ARCH32 else \ "\"C:\Program Files (x86)\\Microsoft Visual Studio 14.0" \ - "\\VC\\bin\\amd64\\vcvars64.bat\"" + "\\VC\\vcvarsall.bat\" amd64" VS2013_VCVARS = "\"C:\Program Files (x86)\\Microsoft Visual Studio 12.0" \ - "\\VC\\bin\\vcvars32.bat\"" \ + "\\VC\\vcvarsall.bat\" x86" \ if ARCH32 else \ "\"C:\Program Files (x86)\\Microsoft Visual Studio 12.0" \ - "\\VC\\bin\\amd64\\vcvars64.bat\"" + "\\VC\\cvarsall.bat\" amd64" VS2008_VCVARS = "\"%LocalAppData%\\Programs\\Common\\Microsoft" \ "\\Visual C++ for Python\\9.0\\vcvarsall.bat\" x86" \ @@ -94,11 +79,12 @@ class Options(object): no_cef_update = False cef_branch = "" cef_commit = "" + cef_version = "" build_dir = "" cef_build_dir = "" ninja_jobs = None - gyp_generators = "ninja" - gyp_msvs_version = "" + gyp_generators = "ninja" # Even though CEF uses now GN, still some GYP + gyp_msvs_version = "" # env variables are being used. # Internal options depot_tools_dir = "" @@ -122,6 +108,8 @@ def main(): if Options.build_cef: build_cef() + # Build cefclient, cefsimple, ceftests, libcef_dll_wrapper + build_cef_projects() create_prebuilt_binaries() elif Options.prebuilt_cef: prebuilt_cef() @@ -146,6 +134,7 @@ def setup_options(docopt_args): # Use branch/commit from the src/version/cef_version_*.h file Options.cef_branch = get_cefpython_version()["CHROME_VERSION_BUILD"] Options.cef_commit = get_cefpython_version()["CEF_COMMIT_HASH"] + Options.cef_version = get_cefpython_version()["CEF_VERSION"] # --gyp-msvs-version if not Options.gyp_msvs_version: @@ -210,9 +199,37 @@ def build_cef(): # Run automate-git.py run_automate_git() + print("[automate.py] Binary distrib created in %s" + % Options.binary_distrib) + + +def prebuilt_cef(): + """Use prebuilt binaries.""" + + # TODO: Option to download CEF prebuilt binaries from GitHub Releases, + # eg. tag 'upstream-cef47'. + + # Find cef_binary directory in the build directory + if Options.cef_version: + cef_binary = os.path.join(Options.build_dir, + "cef_binary_{cef_version}_*{sep}" + .format(cef_version=Options.cef_version, + sep=os.sep)) + else: + cef_binary = os.path.join(Options.build_dir, + "cef_binary_3.{cef_branch}.*{sep}" + .format(cef_branch=Options.cef_branch, + sep=os.sep)) + dirs = glob.glob(cef_binary) + if len(dirs) == 1: + Options.cef_binary = dirs[0] + else: + print("ERROR: Could not find prebuilt binaries in the build dir.") + print(" Eg. cef_binary_3.2883.1553.g80bd606_windows32/") + sys.exit(1) - # Build cefclient, cefsimple, ceftests, libcef_dll_wrapper build_cef_projects() + create_prebuilt_binaries() def create_cef_directories(): @@ -282,113 +299,168 @@ def update_cef_patches(): def build_cef_projects(): """Build cefclient, cefsimple, ceftests, libcef_dll_wrapper.""" - print("[automate.py] Binary distrib created in %s" - % Options.binary_distrib) print("[automate.py] Building cef projects...") + fix_cef_include_files() + # Find cef_binary directories and create the cef_binary/build/ dir - if platform.system() == "Windows": - files = glob.glob(os.path.join(Options.binary_distrib, - "cef_binary_*_symbols")) - assert len(files) == 1, "More than one dir with release symbols found" - symbols = files[0] - if Options.release_build: - cef_binary = symbols.replace("_release_symbols", "") + if not Options.cef_binary: + if platform.system() == "Windows": + files = glob.glob(os.path.join(Options.binary_distrib, + "cef_binary_*_symbols")) + assert len(files) == 1, ("More than one dir with release" + " symbols found") + symbols = files[0] + if Options.release_build: + cef_binary = symbols.replace("_release_symbols", "") + else: + cef_binary = symbols.replace("_debug_symbols", "") + assert "symbols" not in os.path.basename(cef_binary) else: - cef_binary = symbols.replace("_debug_symbols", "") - assert "symbols" not in os.path.basename(cef_binary) + files = glob.glob(os.path.join(Options.binary_distrib, + "cef_binary_*_"+OS_POSTFIX2)) + assert len(files) == 1, "Error finding binary distrib" + cef_binary = files[0] + assert os.path.exists(cef_binary) + Options.cef_binary = cef_binary + + print("[automate.py] Creating build_cefclient dir in cef_binary dir") + build_cefclient = os.path.join(Options.cef_binary, "build_cefclient") + already_built = False + if os.path.exists(build_cefclient): + already_built = True else: - files = glob.glob(os.path.join(Options.binary_distrib, - "cef_binary_*_"+OS_POSTFIX2)) - assert len(files) == 1, "Error finding binary distrib" - cef_binary = files[0] - assert os.path.exists(cef_binary) - Options.cef_binary = cef_binary - build_cefclient = os.path.join(cef_binary, "build_cefclient") - os.makedirs(build_cefclient) + os.makedirs(build_cefclient) # Build cefclient, cefsimple, ceftests - print("[automate.py] Building cefclient, cefsimple, ceftests ...") - command = "" - if platform.system() == "Windows": - if int(Options.cef_branch) >= 2704: - command += VS2015_VCVARS + " && " - else: - command += VS2013_VCVARS + " && " - command += "cmake -G \"Ninja\" -DCMAKE_BUILD_TYPE=%s .." \ - % Options.build_type - run_command(command, build_cefclient) - print("[automate.py] OK") - # On Linux cannot pass "&&" and run two commands using run_command() - command = "ninja cefclient cefsimple ceftests" - run_command(command, build_cefclient) - print("[automate.py] OK") - if platform.system() == "Windows": - assert(os.path.exists(os.path.join(build_cefclient, - "tests", - "cefclient", - Options.build_type, - "cefclient.exe"))) + if already_built: + print("[automate.py] Already built: cefclient, cefsimple, ceftests") else: - assert (os.path.exists(os.path.join(build_cefclient, - "tests", - "cefclient", - Options.build_type, - "cefclient"))) + print("[automate.py] Building cefclient, cefsimple, ceftests ...") + command = prepare_build_command() + command += "cmake -G \"Ninja\" -DCMAKE_BUILD_TYPE=%s .." \ + % Options.build_type + run_command(command, build_cefclient) + print("[automate.py] OK") + # On Linux cannot pass "&&" and run two commands using run_command() + command = prepare_build_command() + command += "ninja cefclient cefsimple ceftests" + run_command(command, build_cefclient) + print("[automate.py] OK") + if platform.system() == "Windows": + assert(os.path.exists(os.path.join(build_cefclient, + "tests", + "cefclient", + Options.build_type, + "cefclient.exe"))) + else: + assert (os.path.exists(os.path.join(build_cefclient, + "tests", + "cefclient", + Options.build_type, + "cefclient"))) # Build libcef_dll_wrapper libs if platform.system() == "Windows": - build_wrapper_windows(cef_binary) + build_wrapper_windows(Options.cef_binary) -def build_wrapper_windows(cef_binary): - # Directories - build_wrapper_mt = os.path.join(cef_binary, "build_wrapper_mt") - build_wrapper_md = os.path.join(cef_binary, "build_wrapper_md") - os.makedirs(build_wrapper_mt) - os.makedirs(build_wrapper_md) +def prepare_build_command(build_lib=False): + """On Windows VS env variables must be set up by calling vcvarsall.bat""" + command = "" + if platform.system() == "Windows": + if build_lib: + msvs = get_msvs_for_python() + command = globals()["VS"+msvs+"_VCVARS"] + " && " + else: + if int(Options.cef_branch) >= 2704: + command = VS2015_VCVARS + " && " + else: + command = VS2013_VCVARS + " && " + return command + +def build_wrapper_windows(cef_binary): # Command to build libcef_dll_wrapper - wrapper_cmake = "" - wrapper_cmake += VS2008_VCVARS + " && " + wrapper_cmake = prepare_build_command(build_lib=True) wrapper_cmake += "cmake -G \"Ninja\" -DCMAKE_BUILD_TYPE=%s .." \ % Options.build_type # Build libcef_dll_wrapper_mt.lib - print("[automate.py] Building libcef_dll_wrapper /MT") - old_gyp_msvs_version = Options.gyp_msvs_version - Options.gyp_msvs_version = get_msvs_for_python() - run_command(wrapper_cmake, build_wrapper_mt) - Options.gyp_msvs_version = old_gyp_msvs_version - print("[automate.py] cmake OK") - run_command("ninja libcef_dll_wrapper", build_wrapper_mt) - print("[automate.py] ninja OK") - assert(os.path.exists(os.path.join(build_wrapper_mt, "libcef_dll", - "libcef_dll_wrapper.lib"))) + build_wrapper_mt = os.path.join(cef_binary, "build_wrapper_mt") + mt_already_built = False + if os.path.exists(build_wrapper_mt): + mt_already_built = True + else: + os.makedirs(build_wrapper_mt) + if mt_already_built: + print("[automate.py] Already built: libcef_dll_wrapper /MT") + else: + print("[automate.py] Building libcef_dll_wrapper /MT") + old_gyp_msvs_version = Options.gyp_msvs_version + Options.gyp_msvs_version = get_msvs_for_python() + run_command(wrapper_cmake, build_wrapper_mt) + Options.gyp_msvs_version = old_gyp_msvs_version + print("[automate.py] cmake OK") + ninja_wrapper = prepare_build_command(build_lib=True) + ninja_wrapper += "ninja libcef_dll_wrapper" + run_command(ninja_wrapper, build_wrapper_mt) + print("[automate.py] ninja OK") + assert(os.path.exists(os.path.join(build_wrapper_mt, + "libcef_dll_wrapper", + "libcef_dll_wrapper.lib"))) # Build libcef_dll_wrapper_md.lib - print("[automate.py] Building libcef_dll_wrapper /MD") - old_gyp_msvs_version = Options.gyp_msvs_version - Options.gyp_msvs_version = get_msvs_for_python() - # Replace /MT with /MD /wd\"4275\" in CMakeLists.txt - # Warnings are treated as errors so this needs to be ignored: - # >> warning C4275: non dll-interface class 'stdext::exception' - # >> used as base for dll-interface class 'std::bad_cast' - # This warning occurs only in VS2008, in VS2013 not. - cmakelists = os.path.join(cef_binary, "CMakeLists.txt") - with open(cmakelists, "rb") as fp: - contents = fp.read() - contents = contents.replace(r"/MT ", r"/MD /wd\"4275\" ") - contents = contents.replace(r"/MTd ", r"/MDd /wd\"4275\" ") - with open(cmakelists, "wb") as fp: - fp.write(contents) - run_command(wrapper_cmake, build_wrapper_md) - Options.gyp_msvs_version = old_gyp_msvs_version - print("[automate.py] cmake OK") - run_command("ninja libcef_dll_wrapper", build_wrapper_md) - print("[automate.py] ninja OK") - assert(os.path.exists(os.path.join(build_wrapper_md, "libcef_dll", - "libcef_dll_wrapper.lib"))) + build_wrapper_md = os.path.join(cef_binary, "build_wrapper_md") + md_already_built = False + if os.path.exists(build_wrapper_md): + md_already_built = True + else: + os.makedirs(build_wrapper_md) + if md_already_built: + print("[automate.py] Already built: libcef_dll_wrapper /MD") + else: + print("[automate.py] Building libcef_dll_wrapper /MD") + old_gyp_msvs_version = Options.gyp_msvs_version + Options.gyp_msvs_version = get_msvs_for_python() + # Replace /MT with /MD /wd\"4275\" in CMakeLists.txt + # Warnings are treated as errors so this needs to be ignored: + # >> warning C4275: non dll-interface class 'stdext::exception' + # >> used as base for dll-interface class 'std::bad_cast' + # This warning occurs only in VS2008, in VS2013 not. + cmakelists = os.path.join(cef_binary, "CMakeLists.txt") + with open(cmakelists, "rb") as fp: + contents = fp.read() + contents = contents.replace(r"/MT ", r"/MD /wd\"4275\" ") + contents = contents.replace(r"/MTd ", r"/MDd /wd\"4275\" ") + with open(cmakelists, "wb") as fp: + fp.write(contents) + run_command(wrapper_cmake, build_wrapper_md) + Options.gyp_msvs_version = old_gyp_msvs_version + print("[automate.py] cmake OK") + ninja_wrapper = prepare_build_command(build_lib=True) + ninja_wrapper += "ninja libcef_dll_wrapper" + run_command(ninja_wrapper, build_wrapper_md) + print("[automate.py] ninja OK") + assert(os.path.exists(os.path.join(build_wrapper_md, + "libcef_dll_wrapper", + "libcef_dll_wrapper.lib"))) + + +def fix_cef_include_files(): + """Fixes to CEF include header files for eg. VS2008 on Windows.""" + if platform.system() == "Windows" and get_msvs_for_python() == "2008": + print("[automate.py] Fixing CEF include/ files") + # cef_types_wrappers.h + cef_types_wrappers = os.path.join(Options.cef_binary, "include", + "internal", "cef_types_wrappers.h") + with open(cef_types_wrappers, "rb") as fp: + contents = fp.read() + # error C2059: syntax error : '{' + contents = contents.replace("s->range = {0, 0};", + "s->range.from = 0; s->range.to = 0;") + with open(cef_types_wrappers, "wb") as fp: + fp.write(contents) def create_prebuilt_binaries(): @@ -417,12 +489,14 @@ def create_prebuilt_binaries(): "build_cefclient", "tests", "cefclient", Options.build_type, "cefclient") - cefclient_files = os.path.join( - src, - "build_cefclient", "tests", "cefclient", - Options.build_type, - "cefclient_files") - cpdir(cefclient_files, os.path.join(bindir, "cefclient_files")) + if platform.system() != "Windows": + # On Windows resources/*.html files are embedded inside exe + cefclient_files = os.path.join( + src, + "build_cefclient", "tests", "cefclient", + Options.build_type, + "cefclient_files") + cpdir(cefclient_files, os.path.join(bindir, "cefclient_files")) # cefsimple cefsimple = os.path.join( @@ -437,12 +511,14 @@ def create_prebuilt_binaries(): "build_cefclient", "tests", "ceftests", Options.build_type, "ceftests") - ceftests_files = os.path.join( - src, - "build_cefclient", "tests", "ceftests", - Options.build_type, - "ceftests_files") - cpdir(ceftests_files, os.path.join(bindir, "ceftests_files")) + if platform.system() != "Windows": + # On Windows resources/*.html files are embedded inside exe + ceftests_files = os.path.join( + src, + "build_cefclient", "tests", "ceftests", + Options.build_type, + "ceftests_files") + cpdir(ceftests_files, os.path.join(bindir, "ceftests_files")) if platform.system() == "Windows": cefclient += ".exe" @@ -460,19 +536,29 @@ def create_prebuilt_binaries(): # libcef.lib and cef_sandbox.lib mvfiles(bindir, libdir, ".lib") # MT lib - libsrc = os.path.join(src, "build_wrapper_mt", "libcef_dll", + libsrc = os.path.join(src, "build_wrapper_mt", "libcef_dll_wrapper", "libcef_dll_wrapper.lib") - libdst = os.path.join(libdir, "licef_dll_wrapper_mt.lib") + libdst = os.path.join(libdir, "libcef_dll_wrapper_mt.lib") shutil.copy(libsrc, libdst) # MD lib - libsrc = os.path.join(src, "build_wrapper_md", "libcef_dll", + libsrc = os.path.join(src, "build_wrapper_md", "libcef_dll_wrapper", "libcef_dll_wrapper.lib") - libdst = os.path.join(libdir, "licef_dll_wrapper_md.lib") + libdst = os.path.join(libdir, "libcef_dll_wrapper_md.lib") shutil.copy(libsrc, libdst) elif platform.system() == "Linux": cpdir(os.path.join(src, "build_cefclient", "libcef_dll_wrapper"), libdir) + # Remove .lib files from bin/ only after libraries were copied + libs = glob.glob(os.path.join(bindir, "*.lib")) + for lib in libs: + os.remove(lib) + + # Remove cef_sandbox.lib (huge file) + cef_sandbox = os.path.join(libdir, "cef_sandbox.lib") + if os.path.exists(cef_sandbox): + os.remove(cef_sandbox) + # Copy README.txt and LICENSE.txt shutil.copy(os.path.join(src, "README.txt"), dst) shutil.copy(os.path.join(src, "LICENSE.txt"), dst) @@ -493,12 +579,6 @@ def get_msvs_for_python(): sys.exit(1) -def prebuilt_cef(): - """Download CEF prebuilt binaries from GitHub Releases, - eg tag 'upstream-cef47'.""" - pass - - def getenv(): """Env variables passed to shell when running commands.""" env = os.environ @@ -623,24 +703,6 @@ def onerror(func, path, _): raise Exception("Not a file permission error, dunno what to do") -def get_cefpython_version(): - """Get CEF version from the 'src/version/' directory.""" - header_file = os.path.join(Options.cefpython_dir, "src", "version", - "cef_version_"+OS_POSTFIX+".h") - return get_version_from_file(header_file) - - -def get_version_from_file(header_file): - with open(header_file, "rU") as fp: - contents = fp.read() - ret = dict() - matches = re.findall(r'^#define (\w+) "?([^\s"]+)"?', contents, - re.MULTILINE) - for match in matches: - ret[match[0]] = match[1] - return ret - - def get_prebuilt_name(header_file=""): if header_file: version = get_version_from_file(header_file) diff --git a/tools/build.py b/tools/build.py new file mode 100644 index 000000000..48c138748 --- /dev/null +++ b/tools/build.py @@ -0,0 +1,638 @@ +""" +Build the cefpython module, install package and run example. + +Usage: + build.py VERSION [--debug] [--fast] + +Options: + VERSION Version in format xx.xx + --debug Debug mode + --fast Fast mode, don't delete C++ .o .a files, nor the setup/build/ + directory, and disable optimization flags when building + the so/pyd module. + --kivy Run Kivy example +""" + +# How to debug on Linux: +# 1. Install "python-dbg" package +# 2. Install "python-wxgtk2.8-dbg" package +# 3. Run "python compile.py debug" +# 4. In cygdb type "cy run" +# 5. To display debug backtrace type "cy bt" +# 6. More commands: http://docs.cython.org/src/userguide/debugging.html + +# This will not show "Segmentation fault" error message: +# | subprocess.call(["python", "./wxpython.py"]) +# You need to call it with shell=True for this kind of +# error message to be shown: +# | subprocess.call("python wxpython.py", shell=True) + +from common import * +import sys +import os +import glob +import shutil +import subprocess +import re + +# raw_input() was renamed to input() in Python 3 +try: + # noinspection PyUnresolvedReferences + # noinspection PyShadowingBuiltins + input = raw_input +except NameError: + pass + +# Command line args variables +DEBUG_FLAG = False +FAST_FLAG = False +KIVY_FLAG = False +REBUILD_CPP = False +VERSION = "" + +# Module extension +if WINDOWS: + MODULE_EXT = "pyd" +else: + MODULE_EXT = "so" + +# Compiler options +if MAC: + os.environ["PATH"] = "/usr/local/bin:"+os.environ["PATH"] + os.environ["CC"] = "gcc" + os.environ["CXX"] = "g++" + os.environ["CEF_CCFLAGS"] = "-arch x86_64" + os.environ["ARCHFLAGS"] = "-arch x86_64" + if ARCH32: + raise Exception("Python 32bit is not supported on Mac") + + +def main(): + print("[build.py] PYVERSION = %s" % PYVERSION) + print("[build.py] OS_POSTFIX2 = %s" % OS_POSTFIX2) + setup_environ_path() + check_cython_version() + command_line_args() + check_directories() + fix_cefpython_h() + if WINDOWS: + compile_cpp_projects_windows() + elif MAC or LINUX: + compile_cpp_projects_unix() + clear_cache() + copy_and_fix_pyx_files() + create_version_pyx_file() + build_cefpython_module() + fix_cefpython_h() + install_and_run() + + +def setup_environ_path(): + print("[build.py] Setup environment PATH") + if not WINDOWS: + return + if ARCH32: + os.environ["PATH"] = ("C:\\Windows\\system32;C:\\Windows;" + "C:\\Windows\\System32\\Wbem;C:\\Python27") + else: + raise Exception("Only 32-bit is currently supported") + + print("[build.py] PATH: {path}".format(path=os.environ["PATH"])) + + """ + set PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem; + C:\Python27_x64;C:\Python27_amd64;C:\Python27_64 + + set PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem; + C:\Python34 + + set PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem; + C:\Python34_x64;C:\Python34_amd64;C:\Python34_64 + """ + + +def check_cython_version(): + print("[build.py] Check Cython version") + with open(os.path.join(TOOLS_DIR, "requirements.txt"), "r") as fileobj: + contents = fileobj.read() + match = re.search(r"cython\s*==\s*([\d.]+)", contents, + flags=re.IGNORECASE) + assert match, "cython package not found in requirements.txt" + require_version = match.group(1) + try: + import Cython + version = Cython.__version__ + except ImportError: + # noinspection PyUnusedLocal + Cython = None + print("[build.py] ERROR: Cython is not installed ({0} required)" + .format(require_version)) + sys.exit(1) + if version != require_version: + print("[build.py] ERROR: Wrong Cython version: {0}. Required: {1}" + .format(version, require_version)) + sys.exit(1) + print("[build.py] Cython version: {0}".format(version)) + + +def command_line_args(): + global DEBUG_FLAG, FAST_FLAG, KIVY_FLAG, REBUILD_CPP, VERSION + + print("[build.py] Parse command line arguments") + + # -- debug flag + if len(sys.argv) > 1 and "--debug" in sys.argv: + DEBUG_FLAG = True + print("[build.py] DEBUG mode On") + + # --fast flag + if len(sys.argv) > 1 and "--fast" in sys.argv: + # Fast mode doesn't delete C++ .o .a files. + # Fast mode also disables optimization flags in setup/setup.py . + FAST_FLAG = True + print("[build.py] FAST mode On") + + # --kivy flag + if len(sys.argv) > 1 and "--kivy" in sys.argv: + KIVY_FLAG = True + print("[build.py] KIVY mode enabled") + + # --rebuild-cpp flag + # Rebuild c++ projects + if len(sys.argv) > 1 and "--rebuild-cpp" in sys.argv: + REBUILD_CPP = True + print("[build.py] REBUILD_CPP mode enabled") + + # version arg + if len(sys.argv) > 1 and re.search(r"^\d+\.\d+$", sys.argv[1]): + VERSION = sys.argv[1] + else: + print("[build.py] ERROR: expected first arg to be a version number") + print(" Allowed version format: \\d+\.\\d+") + sys.exit(1) + + print("[build.py] VERSION=%s" % VERSION) + + +def check_directories(): + print("[build.py] Check directories") + # Create directories if necessary + if not os.path.exists(CEFPYTHON_BINARY): + os.makedirs(CEFPYTHON_BINARY) + if not os.path.exists(BUILD_CEFPYTHON): + os.makedirs(BUILD_CEFPYTHON) + + # Check directories exist + assert os.path.exists(BUILD_DIR) + assert os.path.exists(BUILD_CEFPYTHON) + assert os.path.exists(CEF_BINARY) + assert os.path.exists(CEFPYTHON_BINARY) + + +def fix_cefpython_h(): + os.chdir(BUILD_CEFPYTHON) + print("[build.py] Fix cefpython.h to disable warnings") + if not os.path.exists("cefpython.h"): + print("[build.py] cefpython.h was not yet generated") + return + with open("cefpython.h", "r") as fo: + content = fo.read() + pragma = "#pragma warning(disable:4190)" + if pragma in content: + print("[build.py] cefpython.h is already fixed") + return + content = ("%s\n\n" % pragma) + content + with open("cefpython.h", "w") as fo: + fo.write(content) + print("[build.py] Saved cefpython.h") + + +def compile_cpp_projects_windows(): + print("[build.py] Compile C++ projects") + + print("[build.py] Build client_handler vcproj") + vcproj = ("client_handler_py{pyver}_{os}.vcproj" + .format(pyver=PYVERSION, os=OS_POSTFIX2)) + vcproj = os.path.join(SRC_DIR, "client_handler", vcproj) + build_vcproj(vcproj) + + print("[build.py] Build libcefpythonapp vcproj") + vcproj = ("libcefpythonapp_py{pyver}_{os}.vcproj" + .format(pyver=PYVERSION, os=OS_POSTFIX2)) + vcproj = os.path.join(SRC_DIR, "subprocess", vcproj) + build_vcproj(vcproj) + + print("[build.py] Build subprocess vcproj") + vcproj = ("subprocess_{os}.vcproj" + .format(os=OS_POSTFIX2)) + vcproj = os.path.join(SRC_DIR, "subprocess", vcproj) + build_vcproj(vcproj) + + print("[build.py] Build cpp_utils vcproj") + vcproj = ("cpp_utils_{os}.vcproj" + .format(os=OS_POSTFIX2)) + vcproj = os.path.join(SRC_DIR, "cpp_utils", vcproj) + build_vcproj(vcproj) + + +def build_vcproj(vcproj): + if PYVERSION == "27": + args = list() + args.append("%LocalAppData%\\Programs\\Common\\" + "Microsoft\\Visual C++ for Python\\9.0\\" + "VC\\bin\\amd64\\vcbuild.exe") + args.append("/nocolor") + args.append("/nologo") + args.append("/nohtmllog") + if REBUILD_CPP: + args.append("/rebuild") + args.append(vcproj) + ret = subprocess.call(args, shell=True) + if ret != 0: + compile_ask_to_continue() + else: + raise Exception("Only Python 2.7 32-bit is currently supported") + + """ + In VS2010 vcbuild was replaced by msbuild.exe. + /clp:disableconsolecolor + msbuild /p:BuildProjectReferences=false project.proj + MSBuild.exe MyProject.proj /t:build + """ + + +def compile_ask_to_continue(): + print("[build.py] **INFO**: On first run you should continue despite" + " errors and after completion re-run the build.py script again") + # noinspection PyUnboundLocalVariable + what = input("[build.py] make failed, 'y' to continue, Enter to stop: ") + if what != "y": + sys.exit(1) + + +def compile_cpp_projects_unix(): + print("[build.py] Compile C++ projects") + + # Need to allow continuing even when make fails, as it may + # fail because the "public" function declaration is not yet + # in "cefpython.h", but for it to be generated we need to run + # cython compiling, so in this case you continue even when make + # fails and then run the compile.py script again and this time + # make should succeed. + + # -------- CPP_UTILS_DIR + + os.chdir(CPP_UTILS_DIR) + if not FAST_FLAG: + subprocess.call("rm -f *.o *.a", shell=True) + + ret = subprocess.call("make -f Makefile", shell=True) + if ret != 0: + compile_ask_to_continue() + + # -------- CLIENT_HANDLER_DIR + + os.chdir(CLIENT_HANDLER_DIR) + if not FAST_FLAG: + subprocess.call("rm -f *.o *.a", shell=True) + + ret = subprocess.call("make -f Makefile", shell=True) + if ret != 0: + compile_ask_to_continue() + + # -------- SUBPROCESS_DIR + + os.chdir(SUBPROCESS_DIR) + if not FAST_FLAG: + subprocess.call("rm -f *.o *.a", shell=True) + subprocess.call("rm -f subprocess", shell=True) + + ret = subprocess.call("make -f Makefile-libcefpythonapp", shell=True) + if ret != 0: + compile_ask_to_continue() + + ret = subprocess.call("make -f Makefile", shell=True) + if ret != 0: + compile_ask_to_continue() + + subprocess_exe = os.path.join(CEFPYTHON_BINARY, "subprocess") + if os.path.exists("./subprocess"): + # .copy() will also copy Permission bits + shutil.copy("./subprocess", subprocess_exe) + + +def clear_cache(): + print("[build.py] Clean build cache") + # Cache in CEFPYTHON_BINARY directory (eg. cefpython_linux64/) + os.chdir(CEFPYTHON_BINARY) + delete_files_by_pattern("./cefpython_py*.{ext}".format(ext=MODULE_EXT)) + + # Cache in build_cefpython/ directory + os.chdir(BUILD_CEFPYTHON) + + delete_files_by_pattern("./cefpython_py*.{ext}".format(ext=MODULE_EXT)) + delete_files_by_pattern("./*.pyx") + + try: + if not FAST_FLAG: + # Cython's internal build/ directory + shutil.rmtree(os.path.join(BUILD_CEFPYTHON, "build")) + except OSError: + pass + + +def copy_and_fix_pyx_files(): + print("[build.py] Copy and fix pyx files") + # First, it copies all .pyx files from upper directory to setup/. + # Then, fixes repeating of "include" statements in pyx files. + + # Only the mainfile needs to have "include" statements, + # but we're using PyCharm and to get rid of "unresolved references" + # and other errors displayed in pycharm we are adding "include" + # statements in all of the pyx files. + + # I'm not 100% sure how includes work in Cython, but I suspect that + # a few includes of the same file will include the same content more + # than once, it should work, but function and variable definitions are + # duplicated, it is some kind of overhead and it could lead to some + # problems in the future, better to fix it now. + + # It also checks cdef & cpdef functions whether they are not missing + # "except *", it is required to add it when returning non-python type. + + os.chdir(BUILD_CEFPYTHON) + print("\n") + mainfile = "cefpython.pyx" + + pyxfiles = glob.glob("../../src/*.pyx") + if not len(pyxfiles): + print("[build.py] ERROR: no .pyx files found in root") + sys.exit(1) + pyxfiles = [f for f in pyxfiles if f.find(mainfile) == -1] + # Now, pyxfiles contains all pyx files except the mainfile (cefpython.pyx), + # we do not fix includes in mainfile. + + pyxfiles2 = glob.glob("../../src/handlers/*.pyx") + if not len(pyxfiles2): + print("[build.py] ERROR: no .pyx files found in handlers/") + sys.exit(1) + + pyxfiles = pyxfiles + pyxfiles2 + + # Remove old pyx files + oldpyxfiles = glob.glob("./*.pyx") + print("[build.py] Clean pyx files in build_cefpython/") + for pyxfile in oldpyxfiles: + if os.path.exists(pyxfile): + os.remove(pyxfile) + + # Copying pyxfiles and reading its contents. + print("[build.py] Copying pyx files to build_cefpython/: %s" % pyxfiles) + + # Copy cefpython.pyx and fix includes in cefpython.pyx, eg.: + # include "handlers/focus_handler.pyx" becomes include "focus_handler.pyx" + shutil.copy("../../src/%s" % mainfile, "./%s" % mainfile) + with open("./%s" % mainfile, "r") as fo: + content = fo.read() + (content, subs) = re.subn(r"^include \"handlers/", + "include \"", + content, + flags=re.MULTILINE) + with open("./%s" % mainfile, "w") as fo: + fo.write(content) + print("[build.py] %s includes fixed in %s" % (subs, mainfile)) + + # Copy the rest of the files + print("[build.py] Fixing includes in .pyx files:") + for pyxfile in pyxfiles: + newfile = "./%s" % os.path.basename(pyxfile) + shutil.copy(pyxfile, newfile) + pyxfile = newfile + with open(pyxfile, "r") as pyxfileopened: + content = pyxfileopened.read() + lineNumber = except_all_missing(content) + if lineNumber: + print("[build.py] WARNING: 'except *' missing" + " in a cdef/cpdef function," + " in file %s on line %d" + % (os.path.basename(pyxfile), lineNumber)) + sys.exit(1) + # Do not remove the newline - so that line numbers + # are exact with originals. + (content, subs) = re.subn( + r"^include[\t ]+[\"'][^\"'\n\r]+[\"'][\t ]*", + "", + content, + flags=re.MULTILINE) + if subs: + print("[build.py] %s includes removed in: %s" + % (subs, os.path.basename(pyxfile))) + with open(pyxfile, "w") as pyxfileopened: + pyxfileopened.write(content) + + print("\n") + + +def except_all_missing(content): + # This is not perfect, won't detect C++ custom types, but will find + # the built-in types, templates and pointers. + patterns = list() + patterns.append( + r"\bcp?def\s+" + "((int|short|long|double|char|unsigned|float|double|cpp_bool" + "|cpp_string|cpp_wstring|uint64_t|uintptr_t|void" + "|CefString)\s+)+" + "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") + patterns.append( + r"\bcp?def\s+" + # A template ends with bracket: CefRefPtr[CefBrowser] + # or a pointer ends with asterisk: CefBrowser* + "[^\s]+[\]*]\s+" + "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") + patterns.append( + r"\bcp?def\s+" + # A reference, eg. CefString& + "[^\s]+&\s+" + "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") + + match = None + for pattern in patterns: + match = re.search(pattern, content) + if match: + break + + if match: + lineNumber = (content.count("\n", 0, match.start()) + 1) + return lineNumber + + +def create_version_pyx_file(): + os.chdir(BUILD_CEFPYTHON) + print("[build.py] Create __version__.pyx file") + with open("__version__.pyx", "w") as fo: + fo.write('__version__ = "{}"\n'.format(VERSION)) + + +def build_cefpython_module(): + os.chdir(BUILD_CEFPYTHON) + # if DEBUG_FLAG: + # ret = subprocess.call("python-dbg setup.py build_ext --inplace" + # " --cython-gdb", shell=True) + + print("[build.py] Execute build_module.py script") + print("") + if FAST_FLAG: + ret = subprocess.call([sys.executable, + "{tools_dir}/build_module.py" + .format(tools_dir=TOOLS_DIR), + "build_ext", "--inplace", "--fast"], + shell=True) + else: + ret = subprocess.call([sys.executable, + "{tools_dir}/build_module.py" + .format(tools_dir=TOOLS_DIR), + "build_ext", "--inplace"], + shell=True) + + # if DEBUG_FLAG: + # shutil.rmtree("./../binaries_%s/cython_debug/" % BITS, + # ignore_errors=True) + # shutil.copytree("./cython_debug/", + # "./../binaries_%s/cython_debug/" % BITS) + + # Remove .pyx files + oldpyxfiles = glob.glob("./*.pyx") + print("") + print("[build.py] Cleanup: remove pyx files in build_cefpython/") + for pyxfile in oldpyxfiles: + if os.path.exists(pyxfile): + os.remove(pyxfile) + + # Check if built succeeded after pyx files were removed + if ret != 0: + print("[build.py] FAILED to build the cefpython module") + sys.exit(1) + + # Move the cefpython module + move_file_by_pattern("./cefpython_py{pyver}*.{ext}" + .format(pyver=PYVERSION, ext=MODULE_EXT), + os.path.join(CEFPYTHON_BINARY, + "cefpython_py{pyver}.{ext}" + .format(pyver=PYVERSION, + ext=MODULE_EXT))) + + print("[build.py] Done building the cefpython module") + + +def move_file_by_pattern(pattern, move_to): + assert len(pattern) > 2 + print("[build.py] Move file: {pattern} to {move_to}" + .format(pattern=pattern, move_to=move_to)) + files = glob.glob(pattern) + assert(len(files) == 1) + os.rename(files[0], move_to) + + +def delete_files_by_pattern(pattern): + assert len(pattern) > 2 + print("[build.py] Delete files by pattern: {pattern}" + .format(pattern=pattern)) + files = glob.glob(pattern) + for f in files: + os.remove(f) + + +def delete_directories_by_pattern(pattern): + assert len(pattern) > 2 + print("[build.py] Delete directories by pattern: {pattern}" + .format(pattern=pattern)) + paths = glob.glob(pattern) + for path in paths: + if os.path.isdir(path): + shutil.rmtree(path) + + +def install_and_run(): + os.chdir(BUILD_CEFPYTHON) + + # if DEBUG_FLAG: + # os.chdir("./binaries_%s" % BITS) + # subprocess.call("cygdb . --args python-dbg wxpython.py", shell=True) + + print("[build.py] Install and run...") + + # Clean installer directory from previous run + try: + delete_directories_by_pattern("./cefpython3-{ver}-*-setup/" + .format(ver=VERSION)) + except: + if LINUX: + os.system("sudo rm -rf ./cefpython3-{ver}-*-setup/" + .format(ver=VERSION)) + else: + raise + + # System python requires sudo when installing package + if sys.executable in ["/usr/bin/python", "/usr/bin/python3"]: + sudo = "sudo" + else: + sudo = "" + + os.chdir(BUILD_CEFPYTHON) + + # Make setup installer + print("[build.py] Make setup installer") + os.system("{python} ../../tools/setup/make.py --version {ver}" + .format(python=sys.executable, ver=VERSION)) + + # Enter setup installer directory + os.chdir("cefpython3-{ver}-{os_postfix2}-setup/" + .format(ver=VERSION, os_postfix2=OS_POSTFIX2)) + + # Install + print("[build.py] Install the cefpython package") + os.system("{sudo} {python} setup.py install" + .format(sudo=sudo, python=sys.executable)) + + # Delete setup installer directory + print("[build.py] Delete the setup installer directory") + if WINDOWS: + shutil.rmtree("./cefpython3-{ver}-{os_postfix2}-setup/" + .format(ver=VERSION, os_postfix2=OS_POSTFIX2)) + else: + os.system("{sudo} rm -rf ./cefpython3-{ver}-*-setup/" + .format(sudo=sudo, ver=VERSION)) + + # Run unittests + print("[build.py] Run unittests") + os.system("cd {unittests_dir} && {python} _test_runner.py" + .format(unittests_dir=UNITTESTS_DIR, python=sys.executable)) + + # Run examples + print("[build.py] Run examples") + if KIVY_FLAG: + run_examples = "{python} {linux_dir}/deprecated_64bit/kivy_.py" + else: + run_examples = ("cd {examples_dir}" + " && {python} hello_world.py" + " && {python} wxpython.py" + " && {python} gtk2.py" + " && {python} gtk2.py --message-loop-timer" + # " && {python} gtk3.py" + " && {python} tkinter_.py" + " && {python} qt.py pyqt" + " && {python} qt.py pyside") + if LINUX: + run_examples += (" && {python}" + " {linux_dir}/deprecated_64bit/kivy_.py") + run_examples.format(linux_dir=LINUX_DIR, examples_dir=EXAMPLES_DIR) + os.system(run_examples) + + # Enter tools dir + os.system("cd {tools_dir}".format(tools_dir=TOOLS_DIR)) + + print("[build.py] DONE") + + +if __name__ == "__main__": + main() diff --git a/tools/build_module.py b/tools/build_module.py new file mode 100644 index 000000000..bb99eb2fb --- /dev/null +++ b/tools/build_module.py @@ -0,0 +1,299 @@ +# For internal use only - called by build.py. +# This is Cython's setup for building the cefpython module. + +# Use setuptools so that "Visual C++ compiler for Python 2.7" tools +# can be used. Otherwise "Unable to find vcvarsall.bat" error occurs. +try: + from setuptools import setup + from setuptools import Extension +except ImportError: + from distutils.core import setup + from distutils.extension import Extension + +# Use "Extension" from Cython.Distutils so that "cython_directives" works +from Cython.Distutils import build_ext, Extension +from Cython.Compiler import Options +from common import * +import sys +import platform +import Cython +import os + +# Cython options. Stop on first error, otherwise hundreds +# of errors appear in the console. +Options.fast_fail = True + + +def get_winsdk_lib(): + print("[build_module.py] Detect Windows SDK library directory") + ret = "" + if WINDOWS: + if ARCH32: + winsdk_libs = [ + r"C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Lib", + r"C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0\\Lib", + ] + elif ARCH64: + winsdk_libs = [ + r"C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Lib\\x64", + r"C:\\Program Files\\Microsoft SDKs\\Windows\\v7.0\\Lib\\x64", + ] + else: + raise Exception("Unknown architecture") + for lib in winsdk_libs: + if os.path.exists(lib): + ret = lib + break + if not ret: + ret = winsdk_libs[0] + if not os.path.exists(ret): + raise Exception("Windows SDK Lib directory not found: %s" + % ret) + return ret + + +def set_compiler_options(options): + """Extends options and also sets environment variables.""" + print("[build_module.py] Set compiler options") + + extra_compile_args = list() + extra_link_args = list() + + if WINDOWS: + # /EHsc - using STL string, multimap and others that use + # C++ exceptions. + # + # /ignore:4217 - disable warnings such as this: + # + # client_handler_py27_32bit.lib(client_handler.obj): warning LNK4217: + # locally defined symbol _RemovePythonCallbacksForFrame imported in + # function "public: virtual bool __thiscall + # ClientHandler::OnProcessMessageReceived + # + # The above warning LNK4217 is caused by the warning below which occurs + # when building the client_handler.lib static library: + # + # cefpython.h(36): warning C4190: 'RequestHandler_GetResourceHandler' + # has C-linkage specified, but returns UDT 'CefRefPtr' which is + # incompatible with C + # + # The C4190 warning is disabled with pragma in cefpython.h, see the + # fix_cefpython_h() in the build.py script. + extra_compile_args.extend(['/EHsc']) + extra_link_args.extend(['/ignore:4217']) + + if LINUX: + if len(sys.argv) > 1 and "--fast" in sys.argv: + sys.argv.remove("--fast") + # Fast mode disables optimization flags + print("[build_module.py] FAST mode On") + extra_compile_args.extend(['-flto', '-std=gnu++11']) + extra_link_args.extend(['-flto']) + else: + # Fix "ImportError ... undefined symbol ..." caused by CEF's + # include/base/ headers by adding the -flto flag (Issue #230). + # Unfortunately -flto prolongs compilation time significantly. + # More on the other flags: https://stackoverflow.com/questions/ + # 6687630/ . + extra_compile_args.extend(['-flto', '-fdata-sections', + '-ffunction-sections', '-std=gnu++11']) + extra_link_args.extend(['-flto', '-Wl,--gc-sections']) + + if MAC: + os.environ["CC"] = "gcc" + os.environ["CXX"] = "g++" + + options["extra_compile_args"] = extra_compile_args + options["extra_link_args"] = extra_link_args + + +def get_include_dirs(): + print("[build_module.py] Prepare include directories") + include_dirs = list() + common_include_dirs = [ + SRC_DIR, + os.path.join(SRC_DIR, "common"), + os.path.join(SRC_DIR, "extern"), + os.path.join(SRC_DIR, "extern", "cef") + ] + if WINDOWS: + include_dirs.extend([WINDOWS_DIR]) + include_dirs.extend(common_include_dirs) + elif MAC: + include_dirs.extend([MAC_DIR]) + include_dirs.extend(common_include_dirs) + # TODO: Check these directories, are these really required on Mac? + include_dirs.extend([ + '/usr/include/gtk-2.0', + '/usr/include/glib-2.0', + '/usr/include/gtk-unix-print-2.0', + '/usr/include/cairo', + '/usr/include/pango-1.0', + '/usr/include/gdk-pixbuf-2.0', + '/usr/include/atk-1.0', + # Fedora + '/usr/lib64/gtk-2.0/include', + '/usr/lib64/gtk-unix-print-2.0', + '/usr/lib64/glib-2.0/include', + '/usr/lib/gtk-2.0/include', + '/usr/lib/gtk-2.0/gtk-unix-print-2.0', + '/usr/lib/glib-2.0/include', + ]) + elif LINUX: + include_dirs.extend([LINUX_DIR]) + include_dirs.extend(common_include_dirs) + include_dirs.extend([ + '/usr/include/gtk-2.0', + '/usr/include/glib-2.0', + '/usr/include/gtk-unix-print-2.0', + '/usr/include/cairo', + '/usr/include/pango-1.0', + '/usr/include/gdk-pixbuf-2.0', + '/usr/include/atk-1.0', + # Ubuntu + '/usr/lib/x86_64-linux-gnu/gtk-2.0/include', + '/usr/lib/x86_64-linux-gnu/gtk-unix-print-2.0', + '/usr/lib/x86_64-linux-gnu/glib-2.0/include', + '/usr/lib/i386-linux-gnu/gtk-2.0/include', + '/usr/lib/i386-linux-gnu/gtk-unix-print-2.0', + '/usr/lib/i386-linux-gnu/glib-2.0/include', + # Fedora + '/usr/lib64/gtk-2.0/include', + '/usr/lib64/gtk-unix-print-2.0', + '/usr/lib64/glib-2.0/include', + '/usr/lib/gtk-2.0/include', + '/usr/lib/gtk-2.0/gtk-unix-print-2.0', + '/usr/lib/glib-2.0/include', + ]) + return include_dirs + + +def get_library_dirs(): + print("[build_module.py] Prepare library directories") + library_dirs = [ + os.path.join(CEF_BINARY, "lib"), + ] + if WINDOWS: + library_dirs.extend([ + get_winsdk_lib(), + os.path.join(SRC_DIR, "client_handler", + "Release_py{pyver}_{os}" + .format(pyver=PYVERSION, os=OS_POSTFIX2)), + os.path.join(SRC_DIR, "subprocess", + "Release_{os}" + .format(os=OS_POSTFIX2)), + os.path.join(SRC_DIR, "cpp_utils", + "Release_py{os}" + .format(os=OS_POSTFIX2)) + ]) + if MAC or LINUX: + library_dirs.extend([ + os.path.join(SRC_DIR, "client_handler"), + os.path.join(SRC_DIR, "subprocess"), # libcefpythonapp + os.path.join(SRC_DIR, "cpp_utils"), + ]) + return library_dirs + + +def get_libraries(): + print("[build_module.py] Prepare libraries") + libraries = list() + if WINDOWS: + libraries.extend([ + "libcef", + "libcef_dll_wrapper_md", + "User32", + "client_handler_py{pyver}_{os}".format( + pyver=PYVERSION, os=OS_POSTFIX2), + "libcefpythonapp_py{pyver}_{os}".format( + pyver=PYVERSION, os=OS_POSTFIX2), + "cpp_utils_{os}".format( + os=OS_POSTFIX2), + ]) + elif MAC: + libraries.extend([ + 'client_handler', + 'cef_dll_wrapper', + 'cefpythonapp', + 'cpp_utils' + ]) + elif LINUX: + libraries.extend([ + "X11", + "gobject-2.0", + "glib-2.0", + "gtk-x11-2.0", + # CEF and CEF Python libraries + "cef_dll_wrapper", + "cefpythonapp", + "client_handler", + "cpp_utils", + ]) + return libraries + + +def get_ext_modules(options): + ext_modules = [Extension( + "cefpython_py%s" % PYVERSION, + ["cefpython.pyx"], + + # Ignore the warning in the console: + # > C:\Python27\lib\distutils\extension.py:133: UserWarning: + # > Unknown Extension options: 'cython_directives' warnings.warn(msg) + cython_directives={ + # Any conversion to unicode must be explicit using .decode(). + "c_string_type": "bytes", + "c_string_encoding": "utf-8", + }, + + language='c++', + + include_dirs=options["include_dirs"], + library_dirs=options["library_dirs"], + + # Static libraries only. Order is important, if library A depends on B, + # then B must be included before A. + libraries=options["libraries"], + + # When you put "./" in here, loading of libcef.so will only work when + # running scripts from the same directory that libcef.so resides in. + # runtime_library_dirs=[ + # './' + # ], + + extra_compile_args=options["extra_compile_args"], + extra_link_args=options["extra_link_args"], + + # Defining macros: + # define_macros = [("UNICODE","1"), ("_UNICODE","1"), ] + )] + return ext_modules + + +def compile_time_constants(): + print("[build_module.py] Generate compile_time_constants.pxi") + with open(os.path.join(SRC_DIR, "compile_time_constants.pxi"), "w") as fd: + fd.write('# This file was generated by setup.py\n') + # A way around Python 3.2 bug: UNAME_SYSNAME is not set + fd.write('DEF UNAME_SYSNAME = "%s"\n' % platform.uname()[0]) + fd.write('DEF PY_MAJOR_VERSION = %s\n' % sys.version_info.major) + + +def main(): + print("[build_module.py] Cython version: %s" % Cython.__version__) + compile_time_constants() + options = dict() + set_compiler_options(options) + options["include_dirs"] = get_include_dirs() + options["library_dirs"] = get_library_dirs() + options["libraries"] = get_libraries() + print("[build_module.py] Execute setup()") + setup( + name='cefpython_py%s' % PYVERSION, + cmdclass={'build_ext': build_ext}, + ext_modules=get_ext_modules(options) + ) + + +if __name__ == "__main__": + main() diff --git a/tools/common.py b/tools/common.py new file mode 100644 index 000000000..f42a2667d --- /dev/null +++ b/tools/common.py @@ -0,0 +1,91 @@ +# Common stuff for tools: automate.py, build.py, build_module.py + +import struct +import platform +import sys +import os +import glob +import re + +# Architecture and OS postfixes +ARCH32 = (8 * struct.calcsize('P') == 32) +ARCH64 = (8 * struct.calcsize('P') == 64) +OS_POSTFIX = ("win" if platform.system() == "Windows" else + "linux" if platform.system() == "Linux" else + "mac" if platform.system() == "Darwin" else "unknown") +OS_POSTFIX2 = "unknown" +if OS_POSTFIX == "win": + OS_POSTFIX2 = "win32" if ARCH32 else "win64" +elif OS_POSTFIX == "mac": + OS_POSTFIX2 = "mac32" if ARCH32 else "mac64" +elif OS_POSTFIX == "linux": + OS_POSTFIX2 = "linux32" if ARCH32 else "linux64" + +# Platforms +LINUX = (platform.system() == "Linux") +WINDOWS = (platform.system() == "Windows") +MAC = (platform.system() == "Darwin") + +# Python version eg. 27 +PYVERSION = str(sys.version_info[0])+str(sys.version_info[1]) + +# Directories +TOOLS_DIR = os.path.abspath(os.path.dirname(__file__)) +SRC_DIR = os.path.abspath(os.path.join(TOOLS_DIR, "../src")) +WINDOWS_DIR = os.path.abspath(os.path.join(SRC_DIR, "windows")) +MAC_DIR = os.path.abspath(os.path.join(SRC_DIR, "mac")) +LINUX_DIR = os.path.abspath(os.path.join(SRC_DIR, "linux")) +CPP_UTILS_DIR = os.path.abspath(os.path.join(SRC_DIR, "cpp_utils")) +CLIENT_HANDLER_DIR = os.path.abspath(os.path.join(SRC_DIR, "client_handler")) +SUBPROCESS_DIR = os.path.abspath(os.path.join(SRC_DIR, "subprocess")) +CEFPYTHON_DIR = os.path.abspath(os.path.join(SRC_DIR, "..")) +EXAMPLES_DIR = os.path.abspath(os.path.join(CEFPYTHON_DIR, "examples")) +UNITTESTS_DIR = os.path.abspath(os.path.join(CEFPYTHON_DIR, "unittests")) +BUILD_DIR = os.path.abspath(os.path.join(CEFPYTHON_DIR, "build")) +BUILD_CEFPYTHON = os.path.abspath(os.path.join(BUILD_DIR, "build_cefpython")) +# CEF_BINARY may be auto-overwritten through detect_cef_binary_directory() +CEF_BINARY = os.path.abspath(os.path.join(BUILD_DIR, "cef_"+OS_POSTFIX2)) +CEFPYTHON_BINARY = os.path.abspath(os.path.join(BUILD_DIR, + "cefpython_"+OS_POSTFIX2)) + + +def detect_cef_binary_directory(): + # Detect cef binary directory created by automate.py + # eg. build/cef55_3.2883.1553.g80bd606_win32/ + # and set CEF_BINARY to it. Otherwise CEF_BINARY will + # indicate to build/cef_{os_postfix2}/. + if not os.path.exists(CEF_BINARY): + version = get_cefpython_version() + dirs = glob.glob(os.path.join( + BUILD_DIR, + "cef{major}_{cef_version}_{os}{sep}" + .format(major=version["CHROME_VERSION_MAJOR"], + cef_version=version["CEF_VERSION"], + os=OS_POSTFIX2, + sep=os.sep))) + if len(dirs) == 1: + print("[common.py] Auto detected CEF_BINARY directory: {dir}" + .format(dir=dirs[0])) + global CEF_BINARY + CEF_BINARY = dirs[0] + + +def get_cefpython_version(): + """Get CEF version from the 'src/version/' directory.""" + header_file = os.path.join(SRC_DIR, "version", + "cef_version_"+OS_POSTFIX+".h") + return get_version_from_file(header_file) + + +def get_version_from_file(header_file): + with open(header_file, "rU") as fp: + contents = fp.read() + ret = dict() + matches = re.findall(r'^#define (\w+) "?([^\s"]+)"?', contents, + re.MULTILINE) + for match in matches: + ret[match[0]] = match[1] + return ret + + +detect_cef_binary_directory() From 60ebfb8f9d3b5f0d299148594123f8d9e1234a04 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 20 Feb 2017 17:23:10 +0100 Subject: [PATCH 131/557] Build v55 on Windows PART 2 (#294)... There are still issues with unittests and examples. Tkinter example launches fine, but crashes sometimes. Update vcproj files and other fixes. Add additional linker flag /LARGEADDRESSAWARE to Allow 32-bit processes to access 3GB of RAM. Set UNICODE for subprocess. Update build tools. Update module comments with great details on how these tools work. Refactor make-setup.py and make it work cross-platform (#299). Moved to tools/installer/make.py . Update docs. Update requirements.txt. Update tkinter example on Windows, doesn't support PNG images. --- api/ApplicationSettings.md | 2 + docs/Build-instructions.md | 3 + examples/resources/back.gif | Bin 0 -> 1145 bytes examples/resources/forward.gif | Bin 0 -> 1141 bytes examples/resources/reload.gif | Bin 0 -> 1177 bytes examples/resources/tkinter.gif | Bin 0 -> 5661 bytes examples/resources/tkinter.png | Bin 6265 -> 6294 bytes examples/tkinter_.py | 18 +- examples/wxpython.py | 1 + .../client_handler_py27_win32.vcproj | 4 +- src/client_handler/lifespan_handler.cpp | 2 + src/cpp_utils/cpp_utils_win32.vcproj | 1 + .../installer/build-n-run-wx-chromectrl.sh | 7 - src/mac/installer/.gitignore | 3 - src/mac/installer/__init__.py.template | 28 -- src/mac/installer/build_all.sh | 47 --- src/mac/installer/build_run_chromectrl.sh | 31 -- src/mac/installer/make-setup.py | 172 ---------- src/mac/installer/setup.py.template | 79 ----- ...proj => libcefpythonapp_py27_win32.vcproj} | 9 +- src/subprocess/main.cpp | 11 +- .../main_message_loop_external_pump_win.cpp | 9 +- src/subprocess/main_message_loop/util_win.cpp | 13 +- src/subprocess/main_message_loop/util_win.h | 3 +- ...s_32bit.vcproj => subprocess_win32.vcproj} | 9 +- src/window_info.pyx | 18 +- src/windows/compile.bat | 235 ------------- src/windows/installer/.gitignore | 3 - src/windows/installer/README.txt | 18 - src/windows/installer/__init__.py.template | 12 - src/windows/installer/build_all.bat | 213 ------------ src/windows/installer/innosetup.template | 165 ---------- src/windows/installer/make-installer.py | 93 ------ src/windows/installer/make-setup.py | 178 ---------- src/windows/installer/setup.cfg.template | 2 - src/windows/installer/setup.py.template | 68 ---- tools/automate.py | 301 +++++++++++------ tools/build.py | 306 ++++++++++------- tools/build_module.py | 19 +- tools/common.py | 95 ++++-- tools/installer/cefpython3.README.txt | 13 + tools/installer/cefpython3.__init__.py | 62 ++++ tools/installer/cefpython3.setup.py | 225 +++++++++++++ tools/make_installer.py | 309 ++++++++++++++++++ tools/requirements.txt | 4 +- unittests/_test_runner.py | 16 +- unittests/main_test.py | 8 +- 47 files changed, 1178 insertions(+), 1637 deletions(-) create mode 100644 examples/resources/back.gif create mode 100644 examples/resources/forward.gif create mode 100644 examples/resources/reload.gif create mode 100644 examples/resources/tkinter.gif delete mode 100644 src/linux/installer/build-n-run-wx-chromectrl.sh delete mode 100644 src/mac/installer/.gitignore delete mode 100644 src/mac/installer/__init__.py.template delete mode 100644 src/mac/installer/build_all.sh delete mode 100644 src/mac/installer/build_run_chromectrl.sh delete mode 100644 src/mac/installer/make-setup.py delete mode 100644 src/mac/installer/setup.py.template rename src/subprocess/{libcefpythonapp_py27_32bit.vcproj => libcefpythonapp_py27_win32.vcproj} (83%) rename src/subprocess/{subprocess_32bit.vcproj => subprocess_win32.vcproj} (88%) delete mode 100644 src/windows/compile.bat delete mode 100644 src/windows/installer/.gitignore delete mode 100644 src/windows/installer/README.txt delete mode 100644 src/windows/installer/__init__.py.template delete mode 100644 src/windows/installer/build_all.bat delete mode 100644 src/windows/installer/innosetup.template delete mode 100644 src/windows/installer/make-installer.py delete mode 100644 src/windows/installer/make-setup.py delete mode 100644 src/windows/installer/setup.cfg.template delete mode 100644 src/windows/installer/setup.py.template create mode 100644 tools/installer/cefpython3.README.txt create mode 100644 tools/installer/cefpython3.__init__.py create mode 100644 tools/installer/cefpython3.setup.py create mode 100644 tools/make_installer.py diff --git a/api/ApplicationSettings.md b/api/ApplicationSettings.md index b0ec2d089..fba94f943 100644 --- a/api/ApplicationSettings.md +++ b/api/ApplicationSettings.md @@ -216,6 +216,8 @@ Custom flags that will be used when initializing the V8 Javascript engine. The consequences of using custom flags may not be well tested. Also configurable using the --js-flags switch. +To enable WebAssembly support set the `--expose-wasm` flag. + ### locale diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index 1693e39f4..b0c4a0495 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -69,6 +69,9 @@ __Windows__ * Install an appropriate MS compiler for a specific Python version: https://wiki.python.org/moin/WindowsCompilers +* When using "Visual C++ compiler for Python 2.7" you have to install + "Microsoft Visual C++ 2008 Redistributable Package (x64)" from + [here](https://www.microsoft.com/en-us/download/details.aspx?id=15336) * To build CEF from sources: * Use Win7 x64 or later. 32-bit OS'es are not supported. For more details see [here](https://www.chromium.org/developers/how-tos/build-instructions-windows). diff --git a/examples/resources/back.gif b/examples/resources/back.gif new file mode 100644 index 0000000000000000000000000000000000000000..92362f5eecd32aac8d7bc190b3a8aad1f75215d1 GIT binary patch literal 1145 zcmZ?wbhEHb6k`x$_`a6GIQ5WO+5w}q<0k1xOwx~;q#rj*J7JW5(kT6uQTl14j8jG# zr;RgCn`E3a$po^`7-gQbEjVwKdBG_2qEQx*ykwMh*);p2N%m#aoJ%G-myNQo8s}U! z%DHZof6t=urcLn;`|`U+`47yCAK8^Zuq%IPR{7Pu>WgL7N6WfDR`q|a>;Kx+|8Xoj z>ri^ltLl2aP-Z#Q}1@1e!t_) zyPap=uQ~Q@%gGPB&wbc;;nU&EACF!8c(vKeuRZ*F z9f%$Q(YKqAzutQC?f#4J_g?*f@Z$U9*FT=T{_*t9&*yJ{K7ar3<@;anKLgS47a#t= z{`Bwdr$28$|NZ#o_s6flKYay~e?NZx_xbz3Z$JP4`u*?spMQV;{sV&l|Nk?LNTB$W zg^___9fJr^zJBsd;wX6N9HdJ&M+KFy-wfWpMagAOj7 zN{bjKUFj5A890?Km2u;P1ua6^B8i8-EPLkTGwH*T29JOycGE5e)2il`Q&*VxDsa{^ zAA0P-=g%VQ^krGl>ea!5ie4@n-ffNiPG>$UbG*D7Hv1pPr^D0E&z4|evAdAyetx#g z%5`D47B7E4*VuQ`f`VTTUT2-sgRjQKTxRPPwXyUuJgoly=IL#)$;m5a z*TSKgl;YCRC|RU)Q!cGiJNWkDaQ%}XOCK%`o$RbE4AuZQGX6mT literal 0 HcmV?d00001 diff --git a/examples/resources/forward.gif b/examples/resources/forward.gif new file mode 100644 index 0000000000000000000000000000000000000000..1032b9bee62df9f265de766f81bfdb252e9c5461 GIT binary patch literal 1141 zcmd^;|5K6&0LI@+oy^vB=ghfwXB%Cu^LFhOQ>GcBz4@g!&bGGevZ7Ogz*)M^jddy@ zC~C?Vca@sMn$9^jwK6@sCd4Aq48I`Sup?6;z}Snz3&P7g`aAaA=RWuR`uy-5&VUk# z)CeE~K>C2#JjMR}5inmxpeYHoM+BM*%zq5hMnReyq>X`eHAo+erH>KlY68RG$3e!# zf%8v6h6ZFzg6I660?$pyF((Pk={VLDfi(>>wXrNM$kKs@&l4`pCl${fELi{x4e`Z` z$t8y5k{A1ba>TROiENly>iwb&O)Nu`%DgE>Pe>PMGucyLmd--#d5En~|M^*BIhMr1 z4sfw#F7|DOj@|svQNHCU-+H{pmQ%k9RX9mJER~OvDll?|kL))eg9P66DsM)WH>(=U zu5o17I!@HXlp0r#7(OL|PfOq&vHes7LKPVct{TsZUr{Bi%qyniYcGnMjK$5SAN*W5 zU2HL*k-`NnNNyu`Nw&ytTjRE^aNAdS?JL!t%fdg6b=}LgT}Iv?HbIx|a<@r*%hWWm z+<4b`{hqO*-z>eodhM>c>7G^4wx<8;P~sIaoha~+l>*VO9^*9a(1Y&;fa4AXzUNC;lH(h z?2mQ!QJwwi0x~j-Dd(`sh4rcD4z0nVTlC|cf9ZI(>b9+I*w#F-!((@N zU?;lf^dfH5;l>cR581%n8>riZZg^0S*XQ$L{s8}*>~sfg0)T!X=FQ?ap8$e=Kpt*K zdaq2*>&Nd|I+LQ{1qS0zm?+%J?Fog77%@jqO2d8JvCmGZZW#Tle(+K`okGUNT_y21 z$8~CdrL-oYLV1xa;9bVP3sLG%kH<8n8OuXSB3}4m=?$nLZ)OFbDH_a;bVa8%r`ClE z`I+iHod+wo4hd68hAkhJ2E5;x6(6Sk?l<5Nm8-bf_0~7~@V(4Cz0~Z}^o}2+HQZl7 z>DH{z^y&P!ahr+jBk!4Javye^^%SbSTa3>zSx2S6*D=55yET!kh#VIURe4>l9}0Kf zW`D1bKC7^C!yw7--9<06S$arR8*DhHl3M1T>@{<9RI{9rlgEzClUv3jj`T(3eg0Qo zbqEl+eFXTVJ^6#!B6H2oEkO{E_s;$Efl&cH907-Z5>^0VxX?}8h%$N54*F7gYQW4P WyaotL(2zs6MT%Ml_^9wuAn`wRlK$lY literal 0 HcmV?d00001 diff --git a/examples/resources/reload.gif b/examples/resources/reload.gif new file mode 100644 index 0000000000000000000000000000000000000000..ef96a429162f6f778d74e4ee6cb47ab5db2061e8 GIT binary patch literal 1177 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 M07*qoM6N<$f{d~iSpWb4 literal 6265 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 diff --git a/examples/tkinter_.py b/examples/tkinter_.py index 40acfd0f9..c83859920 100644 --- a/examples/tkinter_.py +++ b/examples/tkinter_.py @@ -14,10 +14,13 @@ import Tkinter as tk import sys import os +import platform import logging as _logging # Globals logger = _logging.getLogger("tkinter_.py") +# Python 2.7 on Windows comes with Tk 8.5 which doesn't support PNG images +IMAGE_EXT = ".gif" if platform.system() == "Windows" else ".png" def main(): @@ -112,7 +115,7 @@ def get_browser_frame(self): def setup_icon(self): resources = os.path.join(os.path.dirname(__file__), "resources") - icon_path = os.path.join(resources, "tkinter.png") + icon_path = os.path.join(resources, "tkinter"+IMAGE_EXT) if os.path.exists(icon_path): self.icon = tk.PhotoImage(file=icon_path) # noinspection PyProtectedMember @@ -132,7 +135,7 @@ def __init__(self, master): resources = os.path.join(os.path.dirname(__file__), "resources") # Back button - back_png = os.path.join(resources, "back.png") + back_png = os.path.join(resources, "back"+IMAGE_EXT) if os.path.exists(back_png): self.back_image = tk.PhotoImage(file=back_png) self.back_button = tk.Button(self, image=self.back_image, @@ -140,7 +143,7 @@ def __init__(self, master): self.back_button.grid(row=0, column=0) # Forward button - forward_png = os.path.join(resources, "forward.png") + forward_png = os.path.join(resources, "forward"+IMAGE_EXT) if os.path.exists(forward_png): self.forward_image = tk.PhotoImage(file=forward_png) self.forward_button = tk.Button(self, image=self.forward_image, @@ -148,7 +151,7 @@ def __init__(self, master): self.forward_button.grid(row=0, column=1) # Reload button - reload_png = os.path.join(resources, "reload.png") + reload_png = os.path.join(resources, "reload"+IMAGE_EXT) if os.path.exists(reload_png): self.reload_image = tk.PhotoImage(file=reload_png) self.reload_button = tk.Button(self, image=self.reload_image, @@ -255,6 +258,7 @@ def embed_browser(self): window_info.SetAsChild(self.winfo_id()) self.browser = cef.CreateBrowserSync(window_info, url="https://www.google.com/") + assert self.browser self.browser.SetClientHandler(LoadHandler(self)) self.browser.SetClientHandler(FocusHandler(self)) self.message_loop_work() @@ -274,7 +278,11 @@ def on_root_configure(self): def on_mainframe_configure(self, width, height): if self.browser: - self.browser.SetBounds(0, 0, width, height) + if platform.system() == "Windows": + # noinspection PyUnresolvedReferences + cef.WindowUtils.OnSize(self.winfo_id(), 0, 0, 0) + elif platform.system() == "Linux": + self.browser.SetBounds(0, 0, width, height) self.browser.NotifyMoveOrResizeStarted() def on_focus_in(self, _): diff --git a/examples/wxpython.py b/examples/wxpython.py index d4a0a5e15..2de7a7520 100644 --- a/examples/wxpython.py +++ b/examples/wxpython.py @@ -111,6 +111,7 @@ def OnSize(self, _): (width, height) = self.browser_panel.GetSizeTuple() # noinspection PyUnresolvedReferences self.browser.SetBounds(x, y, width, height) + self.browser.NotifyMoveOrResizeStarted() def OnClose(self, event): # In cefpython3.wx.chromectrl example calling browser.CloseBrowser() diff --git a/src/client_handler/client_handler_py27_win32.vcproj b/src/client_handler/client_handler_py27_win32.vcproj index 51670b21f..07e4fbb17 100644 --- a/src/client_handler/client_handler_py27_win32.vcproj +++ b/src/client_handler/client_handler_py27_win32.vcproj @@ -4,7 +4,7 @@ Version="9.00" Name="client_handler_py27_win32" RootNamespace="client_handler_py27_win32" - ProjectGUID="{15AD928F-FFD0-4FA5-B469-E42ABB0B4196}" + ProjectGUID="{15AD928F-FFD0-4FA5-B469-E42AAA0B4196}" Keyword="Win32Proj" TargetFrameworkVersion="0" > @@ -27,7 +27,7 @@ browser, diff --git a/src/cpp_utils/cpp_utils_win32.vcproj b/src/cpp_utils/cpp_utils_win32.vcproj index cc2349da5..e0f49c2f9 100644 --- a/src/cpp_utils/cpp_utils_win32.vcproj +++ b/src/cpp_utils/cpp_utils_win32.vcproj @@ -27,6 +27,7 @@ @@ -27,7 +27,7 @@ + + + + + diff --git a/src/subprocess/main.cpp b/src/subprocess/main.cpp index fbf2d5bf1..1192f4a84 100644 --- a/src/subprocess/main.cpp +++ b/src/subprocess/main.cpp @@ -8,22 +8,21 @@ #include int APIENTRY wWinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPTSTR lpCmdLine, - int nCmdShow) - + HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, + int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); CefMainArgs mainArgs(hInstance); -#else // Mac, Linux +#else // defined(OS_WIN) int main(int argc, char **argv) { CefMainArgs mainArgs(argc, argv); -#endif +#endif // Mac, Linux CefRefPtr app(new CefPythonApp); int exitCode = CefExecuteProcess(mainArgs, app.get(), NULL); diff --git a/src/subprocess/main_message_loop/main_message_loop_external_pump_win.cpp b/src/subprocess/main_message_loop/main_message_loop_external_pump_win.cpp index 0de7ebf8a..4ba8575b5 100644 --- a/src/subprocess/main_message_loop/main_message_loop_external_pump_win.cpp +++ b/src/subprocess/main_message_loop/main_message_loop_external_pump_win.cpp @@ -1,4 +1,5 @@ // Copied from upstream cefclient with minor modifications. +// Windows UNICODE API calls were converted to ANSI or commented out. // Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights // reserved. Use of this source code is governed by a BSD-style license that @@ -50,7 +51,7 @@ MainMessageLoopExternalPumpWin::MainMessageLoopExternalPumpWin() : timer_pending_(false), main_thread_target_(NULL) { HINSTANCE hInstance = GetModuleHandle(NULL); - const wchar_t* const kClassName = L"CEFMainTargetHWND"; + const char* const kClassName = "CEFMainTargetHWND"; WNDCLASSEX wcex = {}; wcex.cbSize = sizeof(WNDCLASSEX); @@ -60,7 +61,7 @@ MainMessageLoopExternalPumpWin::MainMessageLoopExternalPumpWin() RegisterClassEx(&wcex); // Create the message handling window. - main_thread_target_ = CreateWindowW(kClassName, NULL, WS_OVERLAPPEDWINDOW, + main_thread_target_ = CreateWindowA(kClassName, NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, HWND_MESSAGE , NULL, hInstance, NULL); DCHECK(main_thread_target_); SetUserDataPtr(main_thread_target_, this); @@ -140,8 +141,8 @@ LRESULT CALLBACK MainMessageLoopExternalPumpWin::WndProc( } // namespace // static -scoped_ptr>MainMessageLoopExternalPump> +scoped_ptr MainMessageLoopExternalPump::Create() { - return scoped_ptr>MainMessageLoopExternalPump>( + return scoped_ptr( new MainMessageLoopExternalPumpWin()); } diff --git a/src/subprocess/main_message_loop/util_win.cpp b/src/subprocess/main_message_loop/util_win.cpp index 3dbb4c316..bc1f0965c 100644 --- a/src/subprocess/main_message_loop/util_win.cpp +++ b/src/subprocess/main_message_loop/util_win.cpp @@ -1,4 +1,5 @@ // Copied from upstream cefclient with minor modifications. +// Windows UNICODE API calls were converted to ANSI or commented out. // Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights // reserved. Use of this source code is governed by a BSD-style license that @@ -25,12 +26,12 @@ WNDPROC SetWndProcPtr(HWND hWnd, WNDPROC wndProc) { return old; } -std::wstring GetResourceString(UINT id) { - #define MAX_LOADSTRING 100 - TCHAR buff[MAX_LOADSTRING] = {0}; - LoadString(::GetModuleHandle(NULL), id, buff, MAX_LOADSTRING); - return buff; -} +//std::wstring GetResourceString(UINT id) { +// #define MAX_LOADSTRING 100 +// TCHAR buff[MAX_LOADSTRING] = {0}; +// LoadString(::GetModuleHandle(NULL), id, buff, MAX_LOADSTRING); +// return buff; +//} int GetCefMouseModifiers(WPARAM wparam) { int modifiers = 0; diff --git a/src/subprocess/main_message_loop/util_win.h b/src/subprocess/main_message_loop/util_win.h index 0f806ba5b..39870204b 100644 --- a/src/subprocess/main_message_loop/util_win.h +++ b/src/subprocess/main_message_loop/util_win.h @@ -1,4 +1,5 @@ // Copied from upstream cefclient with minor modifications. +// Windows UNICODE API calls were converted to ANSI or commented out. // Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights // reserved. Use of this source code is governed by a BSD-style license that @@ -26,7 +27,7 @@ T GetUserDataPtr(HWND hWnd) { WNDPROC SetWndProcPtr(HWND hWnd, WNDPROC wndProc); // Return the resource string with the specified id. -std::wstring GetResourceString(UINT id); +//std::wstring GetResourceString(UINT id); int GetCefMouseModifiers(WPARAM wparam); int GetCefKeyboardModifiers(WPARAM wparam, LPARAM lparam); diff --git a/src/subprocess/subprocess_32bit.vcproj b/src/subprocess/subprocess_win32.vcproj similarity index 88% rename from src/subprocess/subprocess_32bit.vcproj rename to src/subprocess/subprocess_win32.vcproj index d5cf7d4ac..18cff5e78 100644 --- a/src/subprocess/subprocess_32bit.vcproj +++ b/src/subprocess/subprocess_win32.vcproj @@ -31,8 +31,8 @@ Name="VCCLCompilerTool" Optimization="2" EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories="../" - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;RENDERER_PROCESS;" + AdditionalIncludeDirectories="$(INCLUDE);..\;..\common" + PreprocessorDefinitions="WIN32;_WIN32;_WINDOWS;WINVER=0x0601;_WIN32_WINNT=0x0601;UNICODE;_UNICODE;NOMINMAX;WIN32_LEAN_AND_MEAN;_HAS_EXCEPTIONS=0;NDEBUG;_NDEBUG;_CRT_SECURE_NO_WARNINGS;RENDERER_PROCESS;" ExceptionHandling="1" RuntimeLibrary="0" EnableFunctionLevelLinking="true" @@ -48,9 +48,10 @@ IgnoreImportLibrary="false" LinkLibraryDependencies="true" AdditionalDependencies="libcef.lib libcef_dll_wrapper_mt.lib" + AdditionalOptions="/MANIFEST:NO /LARGEADDRESSAWARE" LinkIncremental="1" - AdditionalLibraryDirectories="../../build/cef_win32/lib" - GenerateManifest="true" + AdditionalLibraryDirectories="$(AdditionalLibraryDirectories);$(LIB)" + GenerateManifest="false" IgnoreAllDefaultLibraries="false" GenerateDebugInformation="true" SubSystem="2" diff --git a/src/window_info.pyx b/src/window_info.pyx index c3bef3226..988c665e4 100644 --- a/src/window_info.pyx +++ b/src/window_info.pyx @@ -81,7 +81,16 @@ cdef class WindowInfo: cpdef py_void SetAsChild(self, WindowHandle parentWindowHandle, list windowRect=None): - if not WindowUtils.IsWindowHandle(parentWindowHandle): + # Allow parent window handle to be 0, in such case CEF will + # create top window automatically as in hello_world.py example. + IF UNAME_SYSNAME == "Windows": + # On Windows when parent window handle is 0 then SetAsPopup() + # must be called instead. + if parentWindowHandle == 0: + self.SetAsPopup(parentWindowHandle, "Popup") + return + if parentWindowHandle != 0\ + and not WindowUtils.IsWindowHandle(parentWindowHandle): raise Exception("Invalid parentWindowHandle: %s"\ % parentWindowHandle) self.windowType = "child" @@ -100,7 +109,10 @@ cdef class WindowInfo: IF UNAME_SYSNAME == "Windows": cpdef py_void SetAsPopup(self, WindowHandle parentWindowHandle, py_string windowName): - if not WindowUtils.IsWindowHandle(parentWindowHandle): + # Allow parent window handle to be 0, in such case CEF will + # create top window automatically as in hello_world.py example. + if parentWindowHandle != 0\ + and not WindowUtils.IsWindowHandle(parentWindowHandle): raise Exception("Invalid parentWindowHandle: %s"\ % parentWindowHandle) self.parentWindowHandle = parentWindowHandle @@ -109,7 +121,7 @@ cdef class WindowInfo: cpdef py_void SetAsOffscreen(self, WindowHandle parentWindowHandle): - # It is allowed to pass 0 as parentWindowHandle. + # It is allowed to pass 0 as parentWindowHandle in OSR mode if parentWindowHandle and \ not WindowUtils.IsWindowHandle(parentWindowHandle): raise Exception("Invalid parentWindowHandle: %s" \ diff --git a/src/windows/compile.bat b/src/windows/compile.bat deleted file mode 100644 index eacaee713..000000000 --- a/src/windows/compile.bat +++ /dev/null @@ -1,235 +0,0 @@ -@echo off - -:: It's best to always call with a flag that specifies python -:: version and architecture (eg. --py27-32bit). This will ensure -:: that PATH contains only minimum set of directories and will -:: allow to detect possible issues early. - -:: Arguments -if [%1] == [] ( - echo [compile.bat] Version number not provided. Usage: compile.bat 31.0 - echo [compile.bat] Opt: --rebuild --py27-32bit --py27-64bit --py34-32bit - echo --py34-64bit - exit /B 1 -) - -:: --rebuild flag to rebuild all vcproj builds -set rebuild_flag=0 -echo.%*|findstr /C:"--rebuild" >nul 2>&1 -if %errorlevel% equ 0 ( - set rebuild_flag=1 -) - -:: Add only Python/ to PATH. -:: --py27-32bit flag -echo.%*|findstr /C:"--py27-32bit" >nul 2>&1 -if %errorlevel% equ 0 ( - set PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Python27 -) -:: --py27-64bit flag -echo.%*|findstr /C:"--py27-64bit" >nul 2>&1 -if %errorlevel% equ 0 ( - set PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Python27_x64;C:\Python27_amd64;C:\Python27_64 -) -:: --py34-32bit flag -echo.%*|findstr /C:"--py34-32bit" >nul 2>&1 -if %errorlevel% equ 0 ( - set PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Python34 -) -:: --py34-64bit flag -echo.%*|findstr /C:"--py34-64bit" >nul 2>&1 -if %errorlevel% equ 0 ( - set PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Python34_x64;C:\Python34_amd64;C:\Python34_64 -) -:: PATH -echo [compile.bat] PATH: %PATH% - -:: Version number -set version=%1 -echo [compile.bat] Version argument: %version% - -:: Python architecture. %bits%=="32bit" or "64bit" -FOR /F "delims=" %%i IN ('python -c "import struct, sys; sys.stdout.write(str(8 * struct.calcsize('P')) + 'bit');"') do set bits=%%i -echo [compile.bat] Python architecture: %bits% - -:: Cython version -FOR /F "delims=" %%i IN ('python -c "import sys, Cython; sys.stdout.write(Cython.__version__);"') do set cython_version=%%i -echo [compile.bat] Cython version: %cython_version% - -:: Python version -for /F %%i in ('python -c "import sys; sys.stdout.write(str(sys.version_info[0])+str(sys.version_info[1]));"') do set pyver=%%i -echo [compile.bat] Python version: py%pyver% - -:: Binaries directory -set binaries=%~dp0binaries_%bits% -echo [compile.bat] Binaries directory: %binaries% - -:: Setup directory -set setup=%~dp0setup -echo [compile.bat] Setup directory: %setup% - -:: Delete .pyd files -echo [compile.bat] Cleaning cython build files from previous run -del "%binaries%\cefpython_py%pyver%.pyd" -del "%setup%\cefpython_py%pyver%.pyd" -for /R %setup% %%f in (*.pyx) do del "%%f" -rmdir /S /Q "%setup%\build\" - -:: Fix cefpython.h -echo [compile.bat] Fixing cefpython.h -cd %setup% -python fix_cefpython_h.py -if %errorlevel% neq 0 ( - echo [compile.bat] ERROR: failed to fix cefpython.h - cd ../ - exit /B 1 -) -cd ../ - -:: Compile VS projects: client_handler, libcefpythonapp, subprocess, cpp_utils - -:: client_handler paths -set client_handler_dir=%~dp0..\client_handler -set client_handler_vcproj=%client_handler_dir%\client_handler_py%pyver%_%bits%.vcproj - -set subprocess_dir=%~dp0..\subprocess - -:: libcefpythonapp paths -set libcefpythonapp_vcproj=%subprocess_dir%\libcefpythonapp_py%pyver%_%bits%.vcproj - -:: subprocess paths -set subprocess_vcproj=%subprocess_dir%\subprocess_%bits%.vcproj - -:: cpp_utils paths -set cpp_utils_dir=%~dp0..\..\cpp_utils -set cpp_utils_vcproj=%cpp_utils_dir%\cpp_utils_%bits%.vcproj - -set success=0 -if "%pyver%"=="27" ( - if "%bits%"=="32bit" ( - set "vcbuild=C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcpackages\vcbuild.exe" - set success=1 - ) - if "%bits%"=="64bit" ( - REM :: The same vcbuild.exe 32-bit for building x64 - set "vcbuild=C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcpackages\vcbuild.exe" - set success=1 - ) - set "vcoptions=/nocolor /nologo /nohtmllog" - if %rebuild_flag% equ 1 ( - set "vcoptions=%vcoptions% /rebuild" - ) -) -if "%pyver%"=="34" ( - :: In VS2010 vcbuild was replaced by msbuild.exe. - :: /clp:disableconsolecolor - :: msbuild /p:BuildProjectReferences=false project.proj - :: MSBuild.exe MyProject.proj /t:build -) - -if %success% neq 1 ( - echo [compile.bat] ERROR: failed determining tool to build vcproj files - exit /B 1 -) - -echo [compile.bat] Building client_handler vcproj -"%vcbuild%" %vcoptions% %client_handler_vcproj% -if %errorlevel% neq 0 ( - echo [compile.bat] ERROR: building client_handler vcproj failed - exit /B 1 -) - -echo [compile.bat] Building libcefpythonapp vcproj -"%vcbuild%" %vcoptions% %libcefpythonapp_vcproj% -if %errorlevel% neq 0 ( - echo [compile.bat] ERROR: building libcefpythonapp vcproj failed - exit /B 1 -) - -echo [compile.bat] Building subprocess vcproj -"%vcbuild%" %vcoptions% %subprocess_vcproj% -if %errorlevel% neq 0 ( - echo [compile.bat] ERROR: building subprocess vcproj failed - exit /B 1 -) - -echo [compile.bat] Building cpp_utils vcproj -"%vcbuild%" %vcoptions% %cpp_utils_vcproj% -if %errorlevel% neq 0 ( - echo [compile.bat] ERROR: building cpp_utils vcproj failed - exit /B 1 -) - -:: Do not clean VS build files, as this would slow down the process -:: of recompiling. - -:: Compile .rc file to a .res object. -echo [compile.bat] Compiling cefpython.rc file to a .res object -cd %setup%\ -python compile_rc.py -v %version% -if %errorlevel% neq 0 ( - echo [compile.bat] ERROR: compiling .rc file failed - exit /B 1 -) - -echo [compile.bat] Entering setup/ directory -cd %setup% - -echo [compile.bat] Copying .pyx files to setup/ directory and fixing includes -python fix_pyx_files.py -if %errorlevel% neq 0 ( - echo [compile.bat] ERROR: running fix_pyx_files.py failed - exit /B 1 -) - -:: __version__.pyx must be generated after running fix_pyx_files.py, -:: as that script deletes old pyx files before copying new ones. -echo [compile.bat] Creating __version__.pyx file -echo __version__ = "%version%">>__version__.pyx -if %errorlevel% neq 0 ( - echo [compile.bat] ERROR: writing __version__.pyx failed - exit /B 1 -) - -echo [compile.bat] Running the cython setup.py script -python setup.py build_ext --inplace -if %errorlevel% neq 0 ( - echo [compile.bat] ERROR: the cython setup.py script failed - :: Clean files from the build that failed - for /R %setup% %%f in (*.pyx) do del "%%f" - for /R %setup% %%f in (*.res) do del "%%f" - rmdir /S /Q "%setup%\build\" - cd ../ - exit /B 1 -) - -echo [compile.bat] Fixing cefpython.h -python fix_cefpython_h.py -if %errorlevel% neq 0 ( - echo [compile.bat] ERROR: failed to fix cefpython.h - exit /B 1 -) - -echo [compile.bat] Cleaning files from the build -for /R %setup% %%f in (*.pyx) do del "%%f" -for /R %setup% %%f in (*.res) do del "%%f" -rmdir /S /Q "%setup%\build\" - -echo [compile.bat] Moving the pyd module to the binaries directory -move "%setup%\cefpython_py%pyver%.pyd" "%binaries%/cefpython_py%pyver%.pyd" -if %errorlevel% neq 0 ( - echo [compile.bat] ERROR: Moving the pyd module failed - exit /B 1 -) - -echo [compile.bat] Copying subprocess.exe to the binaries directory -copy "%~dp0..\subprocess\Release_%bits%\subprocess_%bits%.exe" "%binaries%\subprocess.exe" -if %errorlevel% neq 0 ( - echo [compile.bat] ERROR: Copying subprocess.exe failed - exit /B 1 -) - -echo [compile.bat] Everything went OK. Running the wxpython.py example.. - -cd %binaries% -python wxpython.py & cd ../ diff --git a/src/windows/installer/.gitignore b/src/windows/installer/.gitignore deleted file mode 100644 index 0dc5ef2a0..000000000 --- a/src/windows/installer/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -cefpython3-*/ -Output/ -dist/ diff --git a/src/windows/installer/README.txt b/src/windows/installer/README.txt deleted file mode 100644 index 2325940fc..000000000 --- a/src/windows/installer/README.txt +++ /dev/null @@ -1,18 +0,0 @@ -1. To install CEF Python 3 type: - - python setup.py install - -2. In the same directory that setup.py resides there is - an examples/ directory, run some example scripts from there: - - cd examples/ - python wxpython.py - python pyqt.py - python pyside.py - python pygtk_.py - python pywin32.py - - cd wx/ - python sample1.py - python sample2.py - python sample3.py diff --git a/src/windows/installer/__init__.py.template b/src/windows/installer/__init__.py.template deleted file mode 100644 index 94ef341b7..000000000 --- a/src/windows/installer/__init__.py.template +++ /dev/null @@ -1,12 +0,0 @@ -__all__ = ["cefpython", "wx"] -__version__ = "%(APP_VERSION)s" -__author__ = "The CEF Python authors" - -import sys - -if 0x02070000 <= sys.hexversion < 0x03000000: - from . import cefpython_py27 as cefpython -elif 0x03000000 <= sys.hexversion < 0x04000000: - from . import cefpython_py32 as cefpython -else: - raise Exception("Unsupported python version: " + sys.version) diff --git a/src/windows/installer/build_all.bat b/src/windows/installer/build_all.bat deleted file mode 100644 index 3c2dfdea5..000000000 --- a/src/windows/installer/build_all.bat +++ /dev/null @@ -1,213 +0,0 @@ -@echo off -setlocal ENABLEDELAYEDEXPANSION - -:: It's best to always call with a flag that specifies python -:: version and architecture (eg. --py27-32bit). This will ensure -:: that PATH contains only minimum set of directories and will -:: allow to detect possible issues early. - -if "%1"=="" goto usage -if "%2"=="" goto usage - -set version=%1 - -:: Add only Python/ and Python/Scripts/ to PATH. -:: --py27-32bit flag -echo.%*|findstr /C:"--py27-32bit" >nul 2>&1 -if %errorlevel% equ 0 ( - set PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Python27;C:\Python27\Scripts -) -:: --py27-64bit flag -echo.%*|findstr /C:"--py27-64bit" >nul 2>&1 -if %errorlevel% equ 0 ( - set PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Python27_x64;C:\Python27_amd64;C:\Python27_64;C:\Python27_x64\Scripts;C:\Python27_amd64\Scripts;C:\Python27_64\Scripts -) -:: --py34-32bit flag -echo.%*|findstr /C:"--py34-32bit" >nul 2>&1 -if %errorlevel% equ 0 ( - set PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Python34;C:\Python34\Scripts -) -:: --py34-64bit flag -echo.%*|findstr /C:"--py34-64bit" >nul 2>&1 -if %errorlevel% equ 0 ( - set PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Python34_x64;C:\Python34_amd64;C:\Python34_64;C:\Python34_x64\Scripts;C:\Python34_amd64\Scripts;C:\Python34_64\Scripts -) -:: PATH -echo [compile.bat] PATH: %PATH% - -:: Python architecture. %bits%=="32bit" or "64bit" -FOR /F "delims=" %%i IN ('python -c "import struct, sys; sys.stdout.write(str(8 * struct.calcsize('P')) + 'bit');"') do set bits=%%i -echo [compile.bat] Python architecture: %bits% -set success=0 -if "%bits%"=="32bit" ( - set platform=win32 - set success=1 -) -if "%bits%"=="64bit" ( - set platform=win-amd64 - set success=1 -) -if %success% neq 1 ( - echo [build_all.bat] ERROR: invalid architecture: %bits% - exit /B 1 -) - -echo [build_all.bat] PLATFORM: %platform% -echo [build_all.bat] VERSION: %version% - -:: Python version -for /F %%i in ('python -c "import sys; sys.stdout.write(str(sys.version_info[0]) + '.' + str(sys.version_info[1]));"') do set pyverdot=%%i -echo [build_all.bat] Python version: py%pyverdot% - -:: --disable-inno-setup flag -set DISABLE_INNO_SETUP=0 -echo.%*|findstr /C:"--disable-inno-setup" >nul 2>&1 -if %errorlevel% equ 0 ( - set DISABLE_INNO_SETUP=1 -) - -:: Clean directories from previous run -rmdir /s /q Output -for /f "tokens=*" %%f in ('dir .\cefpython3*setup /ad/b') do rmdir /s /q %%f -rmdir /s /q dist - -mkdir dist - -echo [build_all.bat] Installing setuptools and wheel -pip install setuptools wheel -if %errorlevel% neq 0 ( - echo [build_all.bat] ERROR: pip install setuptools wheel - exit /B 1 -) - -if %DISABLE_INNO_SETUP% equ 0 ( - echo [build_all.bat] Creating Inno Setup intaller - python make-installer.py -v %version% - if !errorlevel! equ 0 ( - for /f "tokens=*" %%f in ('dir .\Output\*.exe /b') do ( - move .\Output\%%f dist/%%f - if !errorlevel! neq 0 ( - echo [build_all.bat] ERROR: moving inno setup installer failed - exit /B 1 - ) - ) - rmdir Output - if !errorlevel! neq 0 ( - echo [build_all.bat] ERROR: deleting Output/ directory failed - exit /B 1 - ) - ) - if !errorlevel! neq 0 ( - echo [build_all.bat] ERROR: creating Inno Setup installer failed - exit /B 1 - ) -) - -echo [build_all.bat] Creating Distutils setup -python make-setup.py -v %version% -if %errorlevel% neq 0 ( - echo [build_all.bat] ERROR: creating Distutils setup - exit /B 1 -) - -:: Enter the setup directory -for /f "tokens=*" %%f in ('dir .\cefpython3*setup /ad/b') do cd %%f - -echo [build_all.bat] Creating Distutils source package -python setup.py sdist -if %errorlevel% neq 0 ( - echo [build_all.bat] ERROR: creating Distutils source package - exit /B 1 -) - -echo [build_all.bat] Creating Python Egg -python setup.py bdist_egg -if %errorlevel% neq 0 ( - echo [build_all.bat] ERROR: creating Python Egg failed - exit /B 1 -) - -echo [build_all.bat] Creating Python Wheel -python setup.py bdist_wheel -if %errorlevel% neq 0 ( - echo [build_all.bat] ERROR: creating Python Wheel failed - exit /B 1 -) - -echo [build_all.bat] Creating MSI installer -python setup.py bdist_msi -if %errorlevel% neq 0 ( - echo [build_all.bat] ERROR: creating MSI installer failed - exit /B 1 -) - -echo [build_all.bat] Creating EXE installer -python setup.py bdist_wininst -if %errorlevel% neq 0 ( - echo [build_all.bat] ERROR: creating EXE installer failed - exit /B 1 -) - -echo [build_all.bat] Moving all packages to the dist/ directory -set success=0 -for /f "tokens=*" %%f in ('dir .\dist\*.* /b') do ( - move .\dist\%%f .\..\dist\%%f - if !errorlevel! neq 0 ( - echo [build_all.bat] ERROR: moving setup dist/ packages failed - exit /B 1 - ) - if !errorlevel! equ 0 ( - set success=1 - ) -) -if %success% neq 1 ( - echo [build_all.bat] ERROR: moving setup dist/ packages failed - exit /B 1 -) - -:: Up to the installer/ directory -cd ../ - -echo [build_all.bat] Deleting the Distutils setup directory -for /f "tokens=*" %%f in ('dir .\cefpython3*setup /ad/b') do rmdir /s /q %%f -if %errorlevel% neq 0 ( - echo [build_all.bat] ERROR: failed deleting the Distutils setup directory - exit /B 1 -) - -cd dist/ - -echo [build_all.bat] Renaming some of the packages to include platform tag -for /R %%i in (*) do ( - set oldfile=%%i - set newfile=!oldfile:.egg=-%platform%.egg! - if "!oldfile!" neq "!newfile!" ( - move !oldfile! !newfile! - ) - set oldfile=%%i - set newfile=!oldfile:.zip=-py%pyverdot%-%platform%.zip! - if "!oldfile!" neq "!newfile!" ( - move !oldfile! !newfile! - ) - set oldfile=%%i - set newfile=!oldfile:%platform%.exe=py%pyverdot%-%platform%.exe! - if "!oldfile!" neq "!newfile!" ( - move !oldfile! !newfile! - ) - set oldfile=%%i - set newfile=!oldfile:%platform%.msi=py%pyverdot%-%platform%.msi! - if "!oldfile!" neq "!newfile!" ( - move !oldfile! !newfile! - ) -) - -echo [build_all.bat] Packages in the dist/ directory: -dir - -echo OK - -goto :eof -:usage -@echo [build_all.bat] ERROR: platform or version arguments missing or invalid -@echo [build_all.bat] ERROR: example usage: build_all.bat win32 31.2 -exit /B 1 diff --git a/src/windows/installer/innosetup.template b/src/windows/installer/innosetup.template deleted file mode 100644 index e3a9a51e5..000000000 --- a/src/windows/installer/innosetup.template +++ /dev/null @@ -1,165 +0,0 @@ -; Parts of this code was taken from wxPython/distrib/make_installer.py - -[Setup] - -AppName = CEF Python 3 for Python %(PYTHON_VERSION)s %(APP_NAME_BITS)s -AppVersion = %(APP_VERSION)s -AppVerName = CEF Python 3 version %(APP_VERSION)s for Python %(PYTHON_VERSION)s %(PYTHON_ARCHITECTURE)s - -AppPublisher = Czarek Tomczak -AppPublisherURL = http://code.google.com/cefpython/ -AppSupportURL = https://groups.google.com/group/cefpython?hl=en -AppUpdatesURL = http://code.google.com/cefpython/ -AppCopyright = Copyright 2012-2013 Czarek Tomczak - -DefaultDirName = {code:GetInstallDir|c:\Python} - -DefaultGroupName = CEF Python 3 for Python %(PYTHON_VERSION)s %(APP_NAME_BITS)s -PrivilegesRequired = none -DisableStartupPrompt = yes -Compression = zip -DirExistsWarning = no -DisableReadyMemo = yes -DisableReadyPage = yes -DisableDirPage = no -DisableProgramGroupPage = no -UsePreviousAppDir = yes -UsePreviousGroup = yes - -SourceDir = %(BINARIES_DIR)s -OutputDir = %(INSTALLER_DIR)s\Output -OutputBaseFilename = %(PACKAGE_NAME)s-%(APP_VERSION)s.%(PLATFORM)s-py%(PYTHON_VERSION)s-innosetup - -UninstallFilesDir = {app}\%(PACKAGE_NAME)s -LicenseFile = %(BINARIES_DIR)s\LICENSE.txt - -[Icons] - -Name: "{group}\Examples"; Filename: "{app}\%(PACKAGE_NAME)s\examples"; -Name: "{group}\Uninstall Package"; Filename: "{uninstallexe}"; - -[Run] - -Filename: "{app}\%(PACKAGE_NAME)s\examples"; Flags: postinstall skipifsilent shellexec; - -[Files] - -Source: "*.dll"; DestDir: "{app}\%(PACKAGE_NAME)s"; Flags: ignoreversion; -Source: "*.pak"; DestDir: "{app}\%(PACKAGE_NAME)s"; Flags: ignoreversion; -Source: "locales\*.pak"; DestDir: "{app}\%(PACKAGE_NAME)s\locales"; Flags: ignoreversion; -Source: "%(INSTALLER_DIR)s\__init__.py.generated"; DestDir: "{app}\%(PACKAGE_NAME)s"; DestName: "__init__.py"; Flags: ignoreversion; -Source: "cefclient.exe"; DestDir: "{app}\%(PACKAGE_NAME)s"; Flags: ignoreversion; -Source: "cefpython_py%(PYTHON_VERSION_NODOT)s.pyd"; DestDir: "{app}\%(PACKAGE_NAME)s"; Flags: ignoreversion; -Source: "LICENSE.txt"; DestDir: "{app}\%(PACKAGE_NAME)s"; Flags: ignoreversion; -Source: "README.txt"; DestDir: "{app}\%(PACKAGE_NAME)s"; Flags: ignoreversion; -Source: "subprocess.exe"; DestDir: "{app}\%(PACKAGE_NAME)s"; Flags: ignoreversion; - -; ------------------------------------------------------------------------------ -; wx subpackage -; ------------------------------------------------------------------------------ - -Source: "%(WX_SUBPACKAGE_DIR)s\*.py"; DestDir: "{app}\%(PACKAGE_NAME)s\wx"; Flags: ignoreversion; -Source: "%(WX_SUBPACKAGE_DIR)s\*.txt"; DestDir: "{app}\%(PACKAGE_NAME)s\wx"; Flags: ignoreversion; -Source: "%(WX_SUBPACKAGE_DIR)s\images\*.png"; DestDir: "{app}\%(PACKAGE_NAME)s\wx\images"; Flags: ignoreversion; - -; ------------------------------------------------------------------------------ -; wx examples -; ------------------------------------------------------------------------------ - -Source: "%(WX_SUBPACKAGE_DIR)s\examples\*.py"; DestDir: "{app}\%(PACKAGE_NAME)s\examples\wx"; Flags: ignoreversion; -Source: "%(WX_SUBPACKAGE_DIR)s\examples\*.html"; DestDir: "{app}\%(PACKAGE_NAME)s\examples\wx"; Flags: ignoreversion; -Source: "%(WX_SUBPACKAGE_DIR)s\examples\*.png"; DestDir: "{app}\%(PACKAGE_NAME)s\examples\wx"; Flags: ignoreversion; - -; ------------------------------------------------------------------------------ -; examples -; ------------------------------------------------------------------------------ - -Source: "*.py"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; -Source: "*.html"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; -Source: "*.css"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; -Source: "*.js"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; -Source: "*.ico"; DestDir: "{app}\%(PACKAGE_NAME)s\examples"; Flags: ignoreversion; - -[UninstallDelete] - -Type: files; Name: "{app}\%(PACKAGE_NAME)s\*.pyc"; -Type: files; Name: "{app}\%(PACKAGE_NAME)s\*.log"; -Type: filesandordirs; Name: "{app}\%(PACKAGE_NAME)s\__pycache__" - -Type: files; Name: "{app}\%(PACKAGE_NAME)s\examples\*.pyc"; -Type: files; Name: "{app}\%(PACKAGE_NAME)s\examples\*.log"; -Type: filesandordirs; Name: "{app}\%(PACKAGE_NAME)s\examples\__pycache__" - -Type: files; Name: "{app}\%(PACKAGE_NAME)s\examples\wx\*.pyc"; -Type: files; Name: "{app}\%(PACKAGE_NAME)s\examples\wx\*.log"; -Type: filesandordirs; Name: "{app}\%(PACKAGE_NAME)s\examples\wx\__pycache__" - -Type: files; Name: "{app}\%(PACKAGE_NAME)s\wx\*.pyc"; -Type: files; Name: "{app}\%(PACKAGE_NAME)s\wx\*.log"; -Type: filesandordirs; Name: "{app}\%(PACKAGE_NAME)s\wx\__pycache__" - -[Code] - -program Setup; -var - PythonDir : String; - InstallDir : String; - -function InitializeSetup(): Boolean; -begin - - if not RegQueryStringValue(%(HKEY_CURRENT_USER)s, - 'Software\Python\PythonCore\%(PYTHON_VERSION)s\InstallPath', - '', PythonDir) then begin - - if not RegQueryStringValue(%(HKEY_LOCAL_MACHINE)s, - 'Software\Python\PythonCore\%(PYTHON_VERSION)s\InstallPath', - '', PythonDir) then begin - - if not RegQueryStringValue(%(HKEY_CURRENT_USER)s, - 'Software\Wow6432Node\Python\PythonCore\%(PYTHON_VERSION)s\InstallPath', - '', PythonDir) then begin - - if not RegQueryStringValue(%(HKEY_LOCAL_MACHINE)s, - 'Software\Wow6432Node\Python\PythonCore\%(PYTHON_VERSION)s\InstallPath', - '', PythonDir) then begin - - MsgBox('No installation of Python %(PYTHON_VERSION)s ' - + 'found in registry.' + #13 + 'Be sure to enter ' - + 'a pathname that places Python on the ' - + 'PYTHONPATH', - mbConfirmation, MB_OK); - PythonDir := 'C:\Python'; - end; - end; - end; - end; - - InstallDir := PythonDir + '\Lib\site-packages'; - Result := True; -end; - -function GetInstallDir(Default: String): String; -begin - Result := InstallDir; -end; - -function UninstallOld(FileName: String): Boolean; -var - ResultCode: Integer; -begin - Result := False; - if FileExists(FileName) then begin - Result := True; - Exec(FileName, '/SILENT', WizardDirValue(), SW_SHOWNORMAL, - ewWaitUntilTerminated, ResultCode); - end; -end; - -function NextButtonClick(CurPage: Integer): Boolean; -begin - Result := True; - if CurPage <> wpSelectDir then Exit; - UninstallOld(WizardDirValue() + '\%(PACKAGE_NAME)s\unins001.exe') - UninstallOld(WizardDirValue() + '\%(PACKAGE_NAME)s\unins000.exe') -end; diff --git a/src/windows/installer/make-installer.py b/src/windows/installer/make-installer.py deleted file mode 100644 index ab31d5365..000000000 --- a/src/windows/installer/make-installer.py +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -# Create a Windows package installer. - -import sys -import os -import platform -import argparse -import re -import struct -import sysconfig - -BITS = str(8 * struct.calcsize('P')) + 'bit' -assert (BITS == "32bit" or BITS == "64bit") - -ISCC = r"c:\Program Files (x86)\Inno Setup 5\ISCC.exe" -if "INNO5" in os.environ: - ISCC = os.environ["INNO5"] - -TEMPLATE_FILE = os.getcwd()+r"\innosetup.template" -ISS_FILE = os.getcwd()+r"\innosetup.generated" - -def main(): - parser = argparse.ArgumentParser(usage="%(prog)s [options]") - parser.add_argument("-v", "--version", help="cefpython version", - required=True) - args = parser.parse_args() - assert re.search(r"^\d+\.\d+$", args.version), "Invalid version string" - - vars = {} - vars["PACKAGE_NAME"] = "cefpython3" - vars["APP_VERSION"] = args.version - vars["PYTHON_VERSION"] = (str(sys.version_info.major) + "." - + str(sys.version_info.minor)) - vars["PYTHON_VERSION_NODOT"] = (str(sys.version_info.major) + "" - + str(sys.version_info.minor)) - vars["PYTHON_ARCHITECTURE"] = platform.architecture()[0] - vars["BINARIES_DIR"] = os.path.realpath( - os.getcwd() + r"\..\binaries_%s" % BITS) - vars["PYD_FILE"] = (vars["BINARIES_DIR"]+r"\cefpython_py" - + str(sys.version_info.major) + str(sys.version_info.minor) - + ".pyd") - vars["INSTALLER_DIR"] = os.getcwd() - vars["WX_SUBPACKAGE_DIR"] = os.path.realpath(os.getcwd()+r"\..\..\wx") - vars["PLATFORM"] = sysconfig.get_platform() - - if BITS == "32bit": - # We must keep compatibility, 32bit installers didn't contain - # architecture information in AppName. So make it an empty string. - vars["APP_NAME_BITS"] = "" - vars["HKEY_CURRENT_USER"] = "HKEY_CURRENT_USER" - vars["HKEY_LOCAL_MACHINE"] = "HKEY_LOCAL_MACHINE" - elif BITS == "64bit": - vars["APP_NAME_BITS"] = "64bit" - # Inno setup installer is a 32bit application. To query 64bit - # registry from within 32bit application you need to add _64 - # postfix. - vars["HKEY_CURRENT_USER"] = "HKEY_CURRENT_USER_64" - vars["HKEY_LOCAL_MACHINE"] = "HKEY_LOCAL_MACHINE_64" - - print("Reading template: %s" % TEMPLATE_FILE) - - f = open(TEMPLATE_FILE) - template = f.read() - f.close() - - f = open(ISS_FILE, "w") - f.write(template % vars) - f.close() - - print("Saved: %s" % ISS_FILE) - - initPyTemplate = os.getcwd()+r"\__init__.py.template" - initPyInstall = os.getcwd()+r"\__init__.py.generated" - - f = open(initPyTemplate) - initPyTemplateCode = f.read() - f.close() - - f = open(initPyInstall, "w") - f.write(initPyTemplateCode % vars) - f.close() - print("Saved: %s" % initPyInstall) - - iscc_command = '"'+ ISCC + '" ' + ISS_FILE - print("Running ISCC: %s" % iscc_command) - exit_code = os.system(iscc_command) - sys.exit(exit_code) - -if __name__ == "__main__": - main() diff --git a/src/windows/installer/make-setup.py b/src/windows/installer/make-setup.py deleted file mode 100644 index 27d521e30..000000000 --- a/src/windows/installer/make-setup.py +++ /dev/null @@ -1,178 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -# Create a setup package. - -import sys -import os -import platform -import argparse -import re -import platform -import shutil -import glob -import shutil -import sysconfig - -BITS = platform.architecture()[0] -assert (BITS == "32bit" or BITS == "64bit") - -PACKAGE_NAME = "cefpython3" - -README_FILE = os.getcwd()+r"/README.txt" -INIT_TEMPLATE = os.getcwd()+r"/__init__.py.template" -SETUP_TEMPLATE = os.getcwd()+r"/setup.py.template" -SETUP_CFG_TEMPLATE = os.getcwd()+r"/setup.cfg.template" - -def glob_remove(pathname): - filelist = glob.glob(pathname) - for f in filelist: - os.remove(f) - -def glob_copy(src_glob, dst_folder): - for fname in glob.iglob(src_glob): - print("Copying %s to %s" % (fname, dst_folder)) - if os.path.isdir(fname): - shutil.copytree(fname, - os.path.join(dst_folder, os.path.basename(fname))) - else: - shutil.copy(fname, - os.path.join(dst_folder, os.path.basename(fname))) - -def glob_move(src_glob, dst_folder): - if not os.path.exists(dst_folder): - os.mkdir(dst_folder) - for fname in glob.iglob(src_glob): - shutil.move(fname, - os.path.join(dst_folder, os.path.basename(fname))) - -def str_format(string, dictionary): - orig_string = string - for key, value in dictionary.iteritems(): - string = string.replace("%("+key+")s", value) - if string == orig_string: - raise Exception("Nothing to format") - if re.search(r"%\([a-zA-Z0-9_]+\)s", string): - raise Exception("Not all strings formatted") - return string - -def main(): - parser = argparse.ArgumentParser(usage="%(prog)s [options]") - parser.add_argument("-v", "--version", help="cefpython version", - required=True) - args = parser.parse_args() - assert re.search(r"^\d+\.\d+$", args.version), ( - "Invalid version string") - - vars = {} - vars["APP_VERSION"] = args.version - vars["PLATFORM"] = sysconfig.get_platform() - vars["PY_VERSION_DIGITS_ONLY"] = (str(sys.version_info.major) + "" - + str(sys.version_info.minor)) # "27" or "34" - - print("Reading template: %s" % README_FILE) - f = open(README_FILE) - README_CONTENT = f.read() - f.close() - - print("Reading template: %s" % INIT_TEMPLATE) - f = open(INIT_TEMPLATE) - INIT_CONTENT = str_format(f.read(), vars) - f.close() - - print("Reading template: %s" % SETUP_TEMPLATE) - f = open(SETUP_TEMPLATE) - SETUP_CONTENT = str_format(f.read(), vars) - f.close() - - print("Reading template: %s" % SETUP_CFG_TEMPLATE) - f = open(SETUP_CFG_TEMPLATE) - SETUP_CFG_CONTENT = str_format(f.read(), vars) - f.close() - - installer_dir = os.path.dirname(os.path.abspath(__file__)) - - pyVersion = str(sys.version_info.major) +"."+ str(sys.version_info.minor) - setup_dir = installer_dir+"/"+PACKAGE_NAME+"-"+vars["APP_VERSION"]\ - +"."+BITS+"-py"+pyVersion+"-setup" - print("Creating setup dir: "+setup_dir) - os.mkdir(setup_dir) - - package_dir = setup_dir+"/"+PACKAGE_NAME - #print("Creating package dir") - #os.mkdir(package_dir) - - print("Creating README.txt from template") - with open(setup_dir+"/README.txt", "w") as f: - f.write(README_CONTENT) - - print("Creating setup.py from template") - with open(setup_dir+"/setup.py", "w") as f: - f.write(SETUP_CONTENT) - - print("Creating setup.cfg from template") - with open(setup_dir+"/setup.cfg", "w") as f: - f.write(SETUP_CFG_CONTENT) - - binaries_dir = os.path.abspath(installer_dir+"/../binaries_"+BITS+"/") - print("Copying binaries to package dir") - shutil.copytree(binaries_dir, package_dir) - - os.chdir(package_dir) - print("Removing .log .pyc .pdb files from the package dir") - glob_remove("*.log") - glob_remove("*.pyc") - glob_remove("*.pdb") - - os.chdir(installer_dir) - - print("Creating __init__.py from template") - with open(package_dir+"/__init__.py", "w") as f: - f.write(INIT_CONTENT) - - print("Creating examples dir in package dir") - os.mkdir(package_dir+"/examples/") - - print("Creating wx dir in package dir") - os.mkdir(package_dir+"/wx/") - - print("Moving example scripts from package dir to examples dir") - examples = glob.glob(package_dir+"/*.py") - for example in examples: - # Ignore: cefpython_py27.py - dummy API script - if os.path.basename(example).startswith("cefpython_"): - continue - # Ignore: __init__.py - if os.path.basename(example).startswith("__"): - continue - os.rename(example, package_dir+"/examples/"+os.path.basename(example)) - glob_move(package_dir+"/*.html", package_dir+"/examples/") - glob_move(package_dir+"/*.css", package_dir+"/examples/") - glob_move(package_dir+"/*.js", package_dir+"/examples/") - - print("Copying wx/ to package dir") - wx_subpackage_dir = os.path.abspath(installer_dir+"/../../wx/") - glob_copy(wx_subpackage_dir+"/*", package_dir+"/wx/") - - print("Moving wx examples from wx/examples to examples/wx") - glob_move(package_dir+"/wx/examples/*", package_dir+"/examples/wx/") - os.rmdir(package_dir+"/wx/examples/") - - print("Copying package dir examples to setup dir") - glob_copy(package_dir+"/examples/", setup_dir+"/examples/") - - # Create empty debug.log files so that package uninstalls cleanly - # in case examples were launched. Issue 149. - debug_log_dirs = [package_dir, - package_dir+"/examples/", - package_dir+"/examples/wx/"] - for dir in debug_log_dirs: - print("Creating empty debug.log in %s" % dir) - with open(dir+"/debug.log", "w") as f: - f.write("") - - print("Setup Package created successfully.") - -if __name__ == "__main__": - main() diff --git a/src/windows/installer/setup.cfg.template b/src/windows/installer/setup.cfg.template deleted file mode 100644 index 067dcbfda..000000000 --- a/src/windows/installer/setup.cfg.template +++ /dev/null @@ -1,2 +0,0 @@ -[bdist_wheel] -python-tag=cp%(PY_VERSION_DIGITS_ONLY)s diff --git a/src/windows/installer/setup.py.template b/src/windows/installer/setup.py.template deleted file mode 100644 index 36fb2809a..000000000 --- a/src/windows/installer/setup.py.template +++ /dev/null @@ -1,68 +0,0 @@ -try: - # The setuptools package is not installed by default - # on a clean Ubuntu. Might be also a case on Windows. - # Python Eggs and Wheels can be created only with setuptools. - from setuptools import setup - from setuptools.command.install import install as _install - from setuptools.dist import Distribution - print("[setup.py] Using setuptools") -except: - from distutils.core import setup - from distutils.command.install import install as _install - from distutils.dist import Distribution - print("[setup.py] Using distutils") - -import sys -import os -import subprocess - -def post_install(): - """ Post install tasks """ - print("[setup.py] post_install()") - # Nothing extra is required to do on Windows. - -class install(_install): - def run(self): - _install.run(self) - post_install() - -class BinaryDistribution(Distribution): - def is_pure(self): - return False - -setup( - distclass=BinaryDistribution, - cmdclass={'install': install}, - name='cefpython3', # No spaces here, so that it works with deb packages. - version='%(APP_VERSION)s', - description='Python bindings for the Chromium Embedded Framework', - license='BSD 3-Clause', - author='Czarek Tomczak', - author_email='czarek.tomczak@gmail.com', - url='http://code.google.com/p/cefpython/', - platforms=['%(PLATFORM)s'], - packages=['cefpython3', 'cefpython3.wx'], - package_data={'cefpython3': [ - 'examples/*.py', - 'examples/*.html', - 'examples/*.js', - 'examples/*.css', - 'examples/wx/*.py', - 'examples/wx/*.html', - 'examples/wx/*.js', - 'examples/wx/*.css', - 'examples/wx/*.png', - 'locales/*.pak', - 'wx/*.txt', - 'wx/images/*.png', - '*.txt', - 'cefclient.exe', - 'subprocess.exe', - '*.pyd', - '*.dll', - '*.pak', - 'debug.log', - 'examples/debug.log', - 'examples/wx/debug.log', - ]} -) diff --git a/tools/automate.py b/tools/automate.py index 4da35108a..0d9660673 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -1,6 +1,22 @@ # Copyright (c) 2016 CEF Python, see the Authors file. All rights reserved. -"""Automates building CEF from sources with CEF Python patches applied. +""" +Prepares CEF binaries and libraries for work with the build.py tool. + +Option 1 is to build CEF from sources with the CEF Python patches applied +using the --build-cef flag. + +Option 2 is to use CEF binaries from Spotify Automated Builds using +the --prebuilt-cef flag. In such case check the cefpython/src/version/ +directory to know which version of CEF to download from Spotify: +http://opensource.spotify.com/cefbuilds/index.html +Download and extract it so that for example you have such a directory: +cefpython/build/cef_binary_3.2883.1553.g80bd606_windows32/ . + +This tool generates CEF binaries and libraries that are ready for work +with cefpython, with the build.py script. When automate.py tool completes +job you should see a new subdirectory in the build/ directory, for example: +cefpython/build/cef55_3.2883.1553.g80bd606_win32/ . Usage: automate.py (--prebuilt-cef | --build-cef) @@ -50,24 +66,6 @@ CEF_GIT_URL = "https://bitbucket.org/chromiumembedded/cef.git" -VS2015_VCVARS = "\"C:\Program Files (x86)\\Microsoft Visual Studio 14.0" \ - "\\VC\\vcvarsall.bat\" x86" \ - if ARCH32 else \ - "\"C:\Program Files (x86)\\Microsoft Visual Studio 14.0" \ - "\\VC\\vcvarsall.bat\" amd64" - -VS2013_VCVARS = "\"C:\Program Files (x86)\\Microsoft Visual Studio 12.0" \ - "\\VC\\vcvarsall.bat\" x86" \ - if ARCH32 else \ - "\"C:\Program Files (x86)\\Microsoft Visual Studio 12.0" \ - "\\VC\\cvarsall.bat\" amd64" - -VS2008_VCVARS = "\"%LocalAppData%\\Programs\\Common\\Microsoft" \ - "\\Visual C++ for Python\\9.0\\vcvarsall.bat\" x86" \ - if ARCH32 else \ - "\"%LocalAppData%\\Programs\\Common\\Microsoft" \ - "\\Visual C++ for Python\\9.0\\vcvarsall.bat\" amd64" - class Options(object): """Options from command-line and internal options.""" @@ -94,6 +92,9 @@ class Options(object): release_build = True build_type = "" # Will be set according to "release_build" value cef_binary = "" + build_cefclient_dir = "" + build_wrapper_mt_dir = "" + build_wrapper_md_dir = "" def main(): @@ -104,6 +105,10 @@ def main(): print(" automate-git.py works only with that version.") sys.exit(1) + if len(sys.argv) <= 1: + print(__doc__) + sys.exit(1) + setup_options(docopt.docopt(__doc__)) if Options.build_cef: @@ -303,7 +308,7 @@ def build_cef_projects(): fix_cef_include_files() - # Find cef_binary directories and create the cef_binary/build/ dir + # Find cef_binary directory if not Options.cef_binary: if platform.system() == "Windows": files = glob.glob(os.path.join(Options.binary_distrib, @@ -324,127 +329,224 @@ def build_cef_projects(): assert os.path.exists(cef_binary) Options.cef_binary = cef_binary + # Set build directory + Options.build_cefclient_dir = os.path.join(Options.cef_binary, + "build_cefclient") + print("[automate.py] Creating build_cefclient dir in cef_binary dir") - build_cefclient = os.path.join(Options.cef_binary, "build_cefclient") + + # Check whether already built already_built = False - if os.path.exists(build_cefclient): + if build_cefclient_succeeded(): already_built = True + elif os.path.exists(Options.build_cefclient_dir): + # Last build failed, clean directory + assert Options.build_cefclient_dir + shutil.rmtree(Options.build_cefclient_dir) + os.makedirs(Options.build_cefclient_dir) else: - os.makedirs(build_cefclient) + os.makedirs(Options.build_cefclient_dir) # Build cefclient, cefsimple, ceftests if already_built: print("[automate.py] Already built: cefclient, cefsimple, ceftests") else: - print("[automate.py] Building cefclient, cefsimple, ceftests ...") + print("[automate.py] Build cefclient, cefsimple, ceftests") + # Cmake command = prepare_build_command() - command += "cmake -G \"Ninja\" -DCMAKE_BUILD_TYPE=%s .." \ - % Options.build_type - run_command(command, build_cefclient) + command.extend(["cmake", "-G", "Ninja", + "-DCMAKE_BUILD_TYPE="+Options.build_type, ".."]) + run_command(command, Options.build_cefclient_dir) print("[automate.py] OK") - # On Linux cannot pass "&&" and run two commands using run_command() + # Ninja command = prepare_build_command() - command += "ninja cefclient cefsimple ceftests" - run_command(command, build_cefclient) + command.extend(["ninja", "cefclient", "cefsimple", "ceftests"]) + run_command(command, Options.build_cefclient_dir) print("[automate.py] OK") - if platform.system() == "Windows": - assert(os.path.exists(os.path.join(build_cefclient, - "tests", - "cefclient", - Options.build_type, - "cefclient.exe"))) - else: - assert (os.path.exists(os.path.join(build_cefclient, - "tests", - "cefclient", - Options.build_type, - "cefclient"))) + assert build_cefclient_succeeded() # Build libcef_dll_wrapper libs if platform.system() == "Windows": - build_wrapper_windows(Options.cef_binary) + build_wrapper_windows() -def prepare_build_command(build_lib=False): - """On Windows VS env variables must be set up by calling vcvarsall.bat""" - command = "" - if platform.system() == "Windows": - if build_lib: - msvs = get_msvs_for_python() - command = globals()["VS"+msvs+"_VCVARS"] + " && " - else: - if int(Options.cef_branch) >= 2704: - command = VS2015_VCVARS + " && " - else: - command = VS2013_VCVARS + " && " - return command +def build_wrapper_windows(): + # When building library cmake variables file is being modified + # for the /MD build. If the build fails and variables aren't + # restored then the next /MT build would be broken. Make sure + # that original contents of cmake variables files is always + # restored. + fix_cmake_variables_for_md_library(try_undo=True) - -def build_wrapper_windows(cef_binary): # Command to build libcef_dll_wrapper - wrapper_cmake = prepare_build_command(build_lib=True) - wrapper_cmake += "cmake -G \"Ninja\" -DCMAKE_BUILD_TYPE=%s .." \ - % Options.build_type + cmake_wrapper = prepare_build_command(build_lib=True) + cmake_wrapper.extend(["cmake", "-G", "Ninja", + "-DCMAKE_BUILD_TYPE="+Options.build_type, ".."]) + + # Set build directory for /MT lib. + Options.build_wrapper_mt_dir = os.path.join(Options.cef_binary, + "build_wrapper_mt") - # Build libcef_dll_wrapper_mt.lib - build_wrapper_mt = os.path.join(cef_binary, "build_wrapper_mt") + # Check whether already built mt_already_built = False - if os.path.exists(build_wrapper_mt): + if build_wrapper_mt_succeeded(): mt_already_built = True + elif os.path.exists(Options.build_wrapper_mt_dir): + # Last build failed, clean directory + assert Options.build_wrapper_mt_dir + shutil.rmtree(Options.build_wrapper_mt_dir) + os.makedirs(Options.build_wrapper_mt_dir) else: - os.makedirs(build_wrapper_mt) + os.makedirs(Options.build_wrapper_mt_dir) + + # Build /MT lib. if mt_already_built: print("[automate.py] Already built: libcef_dll_wrapper /MT") else: - print("[automate.py] Building libcef_dll_wrapper /MT") + print("[automate.py] Build libcef_dll_wrapper /MT") old_gyp_msvs_version = Options.gyp_msvs_version Options.gyp_msvs_version = get_msvs_for_python() - run_command(wrapper_cmake, build_wrapper_mt) + # Cmake + run_command(cmake_wrapper, Options.build_wrapper_mt_dir) Options.gyp_msvs_version = old_gyp_msvs_version print("[automate.py] cmake OK") + # Ninja ninja_wrapper = prepare_build_command(build_lib=True) - ninja_wrapper += "ninja libcef_dll_wrapper" - run_command(ninja_wrapper, build_wrapper_mt) + ninja_wrapper.extend(["ninja", "libcef_dll_wrapper"]) + run_command(ninja_wrapper, Options.build_wrapper_mt_dir) print("[automate.py] ninja OK") - assert(os.path.exists(os.path.join(build_wrapper_mt, - "libcef_dll_wrapper", - "libcef_dll_wrapper.lib"))) + assert build_wrapper_mt_succeeded() - # Build libcef_dll_wrapper_md.lib - build_wrapper_md = os.path.join(cef_binary, "build_wrapper_md") + # Set build directory for /MD lib. + Options.build_wrapper_md_dir = os.path.join(Options.cef_binary, + "build_wrapper_md") + + # Check whether already built md_already_built = False - if os.path.exists(build_wrapper_md): + if build_wrapper_md_succeeded(): md_already_built = True + elif os.path.exists(Options.build_wrapper_md_dir): + # Last build failed, clean directory + assert Options.build_wrapper_md_dir + shutil.rmtree(Options.build_wrapper_md_dir) + os.makedirs(Options.build_wrapper_md_dir) else: - os.makedirs(build_wrapper_md) + os.makedirs(Options.build_wrapper_md_dir) + + # Build /MD lib. if md_already_built: print("[automate.py] Already built: libcef_dll_wrapper /MD") else: - print("[automate.py] Building libcef_dll_wrapper /MD") + print("[automate.py] Build libcef_dll_wrapper /MD") old_gyp_msvs_version = Options.gyp_msvs_version Options.gyp_msvs_version = get_msvs_for_python() - # Replace /MT with /MD /wd\"4275\" in CMakeLists.txt - # Warnings are treated as errors so this needs to be ignored: - # >> warning C4275: non dll-interface class 'stdext::exception' - # >> used as base for dll-interface class 'std::bad_cast' - # This warning occurs only in VS2008, in VS2013 not. - cmakelists = os.path.join(cef_binary, "CMakeLists.txt") - with open(cmakelists, "rb") as fp: - contents = fp.read() - contents = contents.replace(r"/MT ", r"/MD /wd\"4275\" ") - contents = contents.replace(r"/MTd ", r"/MDd /wd\"4275\" ") - with open(cmakelists, "wb") as fp: - fp.write(contents) - run_command(wrapper_cmake, build_wrapper_md) + # Fix cmake variables + # Cmake + fix_cmake_variables_for_md_library() + run_command(cmake_wrapper, Options.build_wrapper_md_dir) Options.gyp_msvs_version = old_gyp_msvs_version + fix_cmake_variables_for_md_library(undo=True) print("[automate.py] cmake OK") + # Ninja ninja_wrapper = prepare_build_command(build_lib=True) - ninja_wrapper += "ninja libcef_dll_wrapper" - run_command(ninja_wrapper, build_wrapper_md) + ninja_wrapper.extend(["ninja", "libcef_dll_wrapper"]) + run_command(ninja_wrapper, Options.build_wrapper_md_dir) print("[automate.py] ninja OK") - assert(os.path.exists(os.path.join(build_wrapper_md, - "libcef_dll_wrapper", - "libcef_dll_wrapper.lib"))) + assert build_wrapper_md_succeeded() + + +def fix_cmake_variables_for_md_library(undo=False, try_undo=False): + """Fix cmake variables or undo it. The try_undo param is + for a case when want to be sure that the file wasn't modified, + for example in case the last build failed.""" + + # Replace /MT with /MD /wd4275 in cef/cmake/cef_variables.cmake + # Warnings are treated as errors so this needs to be ignored: + # >> warning C4275: non dll-interface class 'stdext::exception' + # >> used as base for dll-interface class 'std::bad_cast' + # This warning occurs only in VS2008, in VS2013 not. + # This replacements must be unique for the undo operation + # to be reliable. + + mt_find = r"/MT " + mt_replace = r"/MD /wd4275 " + + mtd_find = r"/MTd " + mtd_replace = r"/MDd /wd4275 " + + cmake_variables = os.path.join(Options.cef_binary, "cmake", + "cef_variables.cmake") + with open(cmake_variables, "rb") as fp: + contents = fp.read() + + if try_undo: + matches1 = re.findall(re.escape(mt_replace), contents) + matches2 = re.findall(re.escape(mtd_replace), contents) + if len(matches1) or len(matches2): + undo = True + else: + return + + if undo: + (contents, count) = re.subn(re.escape(mt_replace), mt_find, + contents) + assert count == 2 + (contents, count) = re.subn(re.escape(mtd_replace), mtd_find, + contents) + assert count == 1 + else: + (contents, count) = re.subn(re.escape(mt_find), mt_replace, + contents) + assert count == 2 + (contents, count) = re.subn(re.escape(mtd_find), mtd_replace, + contents) + assert count == 1 + + with open(cmake_variables, "wb") as fp: + fp.write(contents) + + +def build_cefclient_succeeded(): + """Whether building cefclient/cefsimple/ceftests succeeded.""" + assert Options.build_cefclient_dir + cefclient_exe = "cefclient.exe" if WINDOWS else "cefclient" + return os.path.exists(os.path.join(Options.build_cefclient_dir, + "tests", + "cefclient", + Options.build_type, + cefclient_exe)) + + +def build_wrapper_mt_succeeded(): + """Whether building /MT library succeeded (Windows-only).""" + assert Options.build_wrapper_mt_dir + return os.path.exists(os.path.join(Options.build_wrapper_mt_dir, + "libcef_dll_wrapper", + "libcef_dll_wrapper.lib")) + + +def build_wrapper_md_succeeded(): + """Whether building /MD library succeeded (Windows-only).""" + assert Options.build_wrapper_md_dir + return os.path.exists(os.path.join(Options.build_wrapper_md_dir, + "libcef_dll_wrapper", + "libcef_dll_wrapper.lib")) + + +def prepare_build_command(build_lib=False): + """On Windows VS env variables must be set up by calling vcvarsall.bat""" + command = list() + if platform.system() == "Windows": + if build_lib: + msvs = get_msvs_for_python() + command.append(globals()["VS"+msvs+"_VCVARS"]) + else: + if int(Options.cef_branch) >= 2704: + command.append(VS2015_VCVARS) + else: + command.append(VS2013_VCVARS) + command.append("&&") + return command def fix_cef_include_files(): @@ -600,13 +702,16 @@ def getenv(): return env -def run_command(command_line, working_dir): +def run_command(command, working_dir): """Run command in a given directory with env variables set. On Linux multiple commands on one line with the use of && are not allowed. """ - print("[automate.py] Running '"+command_line+"' in '" + + print("[automate.py] Running '"+" ".join(command)+"' in '" + working_dir+"'...") - args = shlex.split(command_line.replace("\\", "\\\\")) + if isinstance(command, str): + args = shlex.split(command.replace("\\", "\\\\")) + else: + args = command return subprocess.check_call(args, cwd=working_dir, env=getenv(), shell=(platform.system() == "Windows")) diff --git a/tools/build.py b/tools/build.py index 48c138748..6c424a784 100644 --- a/tools/build.py +++ b/tools/build.py @@ -1,16 +1,29 @@ +# Copyright (c) 2017 The CEF Python authors. All rights reserved. +# Licensed under the BSD 3-clause license. + """ Build the cefpython module, install package and run example. +Before running you must first put cefpython ready CEF binaries and +libraries in the cefpython/build/ directory (create if doesn't exist). +You have two options for obtaining these binaries and libraries. + +Option 1: Download upstream CEF binaries and libraries from cefpython +GitHub Releases page. These binaries are tagged eg. "v55-upstream". +Extract the archive so that for example you have such a directory: +cefpython/build/cef55_3.2883.1553.g80bd606_win32/ . + +Option 2: Use the automate.py tool. With this tool you can build CEF +from sources or use ready binaries from Spotify Automated Builds. + Usage: - build.py VERSION [--debug] [--fast] + build.py VERSION [--rebuild-cpp] [--fast] [--kivy] Options: - VERSION Version in format xx.xx - --debug Debug mode - --fast Fast mode, don't delete C++ .o .a files, nor the setup/build/ - directory, and disable optimization flags when building - the so/pyd module. - --kivy Run Kivy example + VERSION Version in format xx.xx + --rebuild-cpp Force rebuild of C++ projects + --fast Fast mode + --kivy Run only Kivy example """ # How to debug on Linux: @@ -56,21 +69,18 @@ else: MODULE_EXT = "so" -# Compiler options -if MAC: - os.environ["PATH"] = "/usr/local/bin:"+os.environ["PATH"] - os.environ["CC"] = "gcc" - os.environ["CXX"] = "g++" - os.environ["CEF_CCFLAGS"] = "-arch x86_64" - os.environ["ARCHFLAGS"] = "-arch x86_64" - if ARCH32: - raise Exception("Python 32bit is not supported on Mac") +# First run +FIRST_RUN = False +CEFPYTHON_H = os.path.join(BUILD_CEFPYTHON, "cefpython.h") def main(): + if len(sys.argv) <= 1: + print(__doc__) + sys.exit(1) print("[build.py] PYVERSION = %s" % PYVERSION) print("[build.py] OS_POSTFIX2 = %s" % OS_POSTFIX2) - setup_environ_path() + setup_environ() check_cython_version() command_line_args() check_directories() @@ -87,28 +97,57 @@ def main(): install_and_run() -def setup_environ_path(): - print("[build.py] Setup environment PATH") +def setup_environ(): + """Set environment variables. Set PATH so that it contains only + minimum set of directories,to avoid any possible issues. Set Python + include path. Set Mac compiler options. Etc.""" + print("[build.py] Setup environment variables") + if not WINDOWS: return - if ARCH32: - os.environ["PATH"] = ("C:\\Windows\\system32;C:\\Windows;" - "C:\\Windows\\System32\\Wbem;C:\\Python27") - else: - raise Exception("Only 32-bit is currently supported") - print("[build.py] PATH: {path}".format(path=os.environ["PATH"])) + # PATH + if WINDOWS: + path = [ + "C:\\Windows\\system32", + "C:\\Windows", + "C:\\Windows\\System32\\Wbem", + get_python_path(), + ] + os.environ["PATH"] = os.pathsep.join(path) + print("[build.py] environ PATH: {path}" + .format(path=os.environ["PATH"])) + + # INCLUDE env for vcproj build + if WINDOWS: + if "INCLUDE" not in os.environ: + os.environ["INCLUDE"] = "" + os.environ["INCLUDE"] += os.pathsep + os.path.join(get_python_path(), + "include") + print("[build.py] environ INCLUDE: {include}" + .format(include=os.environ["INCLUDE"])) + + # LIB env for vcproj build + if WINDOWS: + os.environ["AdditionalLibraryDirectories"] = os.path.join( + CEF_BINARIES_LIBRARIES, "lib") + print("[build.py] environ AdditionalLibraryDirectories: {lib}" + .format(lib=os.environ["AdditionalLibraryDirectories"])) - """ - set PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem; - C:\Python27_x64;C:\Python27_amd64;C:\Python27_64 + # Mac compiler options + if MAC: + os.environ["PATH"] = "/usr/local/bin:"+os.environ["PATH"] + os.environ["CC"] = "gcc" + os.environ["CXX"] = "g++" + os.environ["CEF_CCFLAGS"] = "-arch x86_64" + os.environ["ARCHFLAGS"] = "-arch x86_64" + if ARCH32: + raise Exception("Python 32-bit is not supported on Mac") - set PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem; - C:\Python34 - set PATH=C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem; - C:\Python34_x64;C:\Python34_amd64;C:\Python34_64 - """ +def get_python_path(): + """Get Python path.""" + return os.path.dirname(sys.executable) def check_cython_version(): @@ -185,7 +224,7 @@ def check_directories(): # Check directories exist assert os.path.exists(BUILD_DIR) assert os.path.exists(BUILD_CEFPYTHON) - assert os.path.exists(CEF_BINARY) + assert os.path.exists(CEF_BINARIES_LIBRARIES) assert os.path.exists(CEFPYTHON_BINARY) @@ -204,31 +243,44 @@ def fix_cefpython_h(): content = ("%s\n\n" % pragma) + content with open("cefpython.h", "w") as fo: fo.write(content) - print("[build.py] Saved cefpython.h") + print("[build.py] Save build_cefpython/cefpython.h") def compile_cpp_projects_windows(): print("[build.py] Compile C++ projects") - print("[build.py] Build client_handler vcproj") + print("[build.py] ~~ Build CLIENT_HANDLER vcproj") vcproj = ("client_handler_py{pyver}_{os}.vcproj" .format(pyver=PYVERSION, os=OS_POSTFIX2)) vcproj = os.path.join(SRC_DIR, "client_handler", vcproj) build_vcproj(vcproj) - print("[build.py] Build libcefpythonapp vcproj") + print("[build.py] ~~ Build LIBCEFPYTHONAPP vcproj") vcproj = ("libcefpythonapp_py{pyver}_{os}.vcproj" .format(pyver=PYVERSION, os=OS_POSTFIX2)) vcproj = os.path.join(SRC_DIR, "subprocess", vcproj) build_vcproj(vcproj) - print("[build.py] Build subprocess vcproj") + print("[build.py] ~~ Build SUBPROCESS vcproj") vcproj = ("subprocess_{os}.vcproj" .format(os=OS_POSTFIX2)) vcproj = os.path.join(SRC_DIR, "subprocess", vcproj) - build_vcproj(vcproj) - - print("[build.py] Build cpp_utils vcproj") + ret = build_vcproj(vcproj) + + # Copy subprocess executable + subprocess_from = os.path.join( + SUBPROCESS_DIR, + "Release_{os}".format(os=OS_POSTFIX2), + "subprocess_{os}.exe".format(os=OS_POSTFIX2)) + subprocess_to = os.path.join(CEFPYTHON_BINARY, "subprocess.exe") + if os.path.exists(subprocess_to): + os.remove(subprocess_to) + if ret == 0: + print("[build.py] Copy subprocess executable") + # shutil.copy() will also copy Permission bits + shutil.copy(subprocess_from, subprocess_to) + + print("[build.py] ~~ Build CPP_UTILS vcproj") vcproj = ("cpp_utils_{os}.vcproj" .format(os=OS_POSTFIX2)) vcproj = os.path.join(SRC_DIR, "cpp_utils", vcproj) @@ -236,11 +288,19 @@ def compile_cpp_projects_windows(): def build_vcproj(vcproj): + if not os.path.exists(CEFPYTHON_H): + print("[build.py] INFO: Looks like first run, as cefpython.h" + " is missing. Skip building C++ project.") + global FIRST_RUN + FIRST_RUN = True + return + if PYVERSION == "27": args = list() - args.append("%LocalAppData%\\Programs\\Common\\" - "Microsoft\\Visual C++ for Python\\9.0\\" - "VC\\bin\\amd64\\vcbuild.exe") + args.append(VS2008_VCVARS) + args.append(VS_PLATFORM_ARG) + args.append("&&") + args.append(VS2008_BUILD) args.append("/nocolor") args.append("/nologo") args.append("/nohtmllog") @@ -250,20 +310,17 @@ def build_vcproj(vcproj): ret = subprocess.call(args, shell=True) if ret != 0: compile_ask_to_continue() + return ret else: raise Exception("Only Python 2.7 32-bit is currently supported") - """ - In VS2010 vcbuild was replaced by msbuild.exe. - /clp:disableconsolecolor - msbuild /p:BuildProjectReferences=false project.proj - MSBuild.exe MyProject.proj /t:build - """ + # In VS2010 vcbuild was replaced by msbuild.exe. + # /clp:disableconsolecolor + # msbuild /p:BuildProjectReferences=false project.proj + # MSBuild.exe MyProject.proj /t:build def compile_ask_to_continue(): - print("[build.py] **INFO**: On first run you should continue despite" - " errors and after completion re-run the build.py script again") # noinspection PyUnboundLocalVariable what = input("[build.py] make failed, 'y' to continue, Enter to stop: ") if what != "y": @@ -280,17 +337,8 @@ def compile_cpp_projects_unix(): # fails and then run the compile.py script again and this time # make should succeed. - # -------- CPP_UTILS_DIR - - os.chdir(CPP_UTILS_DIR) - if not FAST_FLAG: - subprocess.call("rm -f *.o *.a", shell=True) - - ret = subprocess.call("make -f Makefile", shell=True) - if ret != 0: - compile_ask_to_continue() - - # -------- CLIENT_HANDLER_DIR + # -- CLIENT_HANDLER + print("[build.py] ~~ Build CLIENT_HANDLER project") os.chdir(CLIENT_HANDLER_DIR) if not FAST_FLAG: @@ -300,7 +348,8 @@ def compile_cpp_projects_unix(): if ret != 0: compile_ask_to_continue() - # -------- SUBPROCESS_DIR + # -- LIBCEFPYTHONAPP + print("[build.py] ~~ Build LIBCEFPYTHONAPP project") os.chdir(SUBPROCESS_DIR) if not FAST_FLAG: @@ -311,14 +360,29 @@ def compile_cpp_projects_unix(): if ret != 0: compile_ask_to_continue() + # -- SUBPROCESS + print("[build.py] ~~ Build SUBPROCESS project") ret = subprocess.call("make -f Makefile", shell=True) if ret != 0: compile_ask_to_continue() - subprocess_exe = os.path.join(CEFPYTHON_BINARY, "subprocess") - if os.path.exists("./subprocess"): - # .copy() will also copy Permission bits - shutil.copy("./subprocess", subprocess_exe) + # Copy subprocess executable + subprocess_from = os.path.join(SUBPROCESS_DIR, "subprocess") + subprocess_to = os.path.join(CEFPYTHON_BINARY, "subprocess") + if os.path.exists(subprocess_from): + # shutil.copy() will also copy Permission bits + shutil.copy(subprocess_from, subprocess_to) + + # -- CPP_UTILS + print("[build.py] ~~ Build CPP_UTILS project") + + os.chdir(CPP_UTILS_DIR) + if not FAST_FLAG: + subprocess.call("rm -f *.o *.a", shell=True) + + ret = subprocess.call("make -f Makefile", shell=True) + if ret != 0: + compile_ask_to_continue() def clear_cache(): @@ -510,7 +574,19 @@ def build_cefpython_module(): # Check if built succeeded after pyx files were removed if ret != 0: - print("[build.py] FAILED to build the cefpython module") + if FIRST_RUN and os.path.exists(CEFPYTHON_H): + print("[build.py] INFO: looks like this was first run and" + " linking is expected to fail in such case. Will re-run" + " the build.py script programmatically now.") + args = list() + args.append(sys.executable) + args.append(os.path.join(TOOLS_DIR, os.path.basename(__file__))) + assert __file__ in sys.argv[0] + args.extend(sys.argv[1:]) + ret = subprocess.call(args, shell=True) + sys.exit(ret) + else: + print("[build.py] ERROR: failed to build the cefpython module") sys.exit(1) # Move the cefpython module @@ -521,7 +597,7 @@ def build_cefpython_module(): .format(pyver=PYVERSION, ext=MODULE_EXT))) - print("[build.py] Done building the cefpython module") + print("[build.py] DONE building the cefpython module") def move_file_by_pattern(pattern, move_to): @@ -553,60 +629,44 @@ def delete_directories_by_pattern(pattern): def install_and_run(): - os.chdir(BUILD_CEFPYTHON) - # if DEBUG_FLAG: # os.chdir("./binaries_%s" % BITS) # subprocess.call("cygdb . --args python-dbg wxpython.py", shell=True) print("[build.py] Install and run...") + os.chdir(BUILD_DIR) - # Clean installer directory from previous run - try: - delete_directories_by_pattern("./cefpython3-{ver}-*-setup/" - .format(ver=VERSION)) - except: - if LINUX: - os.system("sudo rm -rf ./cefpython3-{ver}-*-setup/" - .format(ver=VERSION)) - else: - raise + # Setup installer directory + setup_installer_dir = ("./cefpython3-{version}-{os}-setup/" + .format(version=VERSION, os=OS_POSTFIX2)) + setup_installer_dir = os.path.join(BUILD_DIR, setup_installer_dir) - # System python requires sudo when installing package - if sys.executable in ["/usr/bin/python", "/usr/bin/python3"]: - sudo = "sudo" - else: - sudo = "" - - os.chdir(BUILD_CEFPYTHON) + # Delete setup installer directory if exists + if os.path.exists(setup_installer_dir): + delete_directory_reliably(setup_installer_dir) # Make setup installer print("[build.py] Make setup installer") - os.system("{python} ../../tools/setup/make.py --version {ver}" - .format(python=sys.executable, ver=VERSION)) - - # Enter setup installer directory - os.chdir("cefpython3-{ver}-{os_postfix2}-setup/" - .format(ver=VERSION, os_postfix2=OS_POSTFIX2)) + make_tool = os.path.join(TOOLS_DIR, "make_installer.py") + os.system("{python} {make_tool} --version {version}" + .format(python=sys.executable, + make_tool=make_tool, + version=VERSION)) # Install print("[build.py] Install the cefpython package") + os.chdir(setup_installer_dir) os.system("{sudo} {python} setup.py install" - .format(sudo=sudo, python=sys.executable)) - - # Delete setup installer directory - print("[build.py] Delete the setup installer directory") - if WINDOWS: - shutil.rmtree("./cefpython3-{ver}-{os_postfix2}-setup/" - .format(ver=VERSION, os_postfix2=OS_POSTFIX2)) - else: - os.system("{sudo} rm -rf ./cefpython3-{ver}-*-setup/" - .format(sudo=sudo, ver=VERSION)) + .format(sudo=get_sudo(), python=sys.executable)) + os.chdir(BUILD_DIR) # Run unittests print("[build.py] Run unittests") - os.system("cd {unittests_dir} && {python} _test_runner.py" - .format(unittests_dir=UNITTESTS_DIR, python=sys.executable)) + test_runner = os.path.join(UNITTESTS_DIR, "_test_runner.py") + ret = os.system("{python} {test_runner}" + .format(python=sys.executable, test_runner=test_runner)) + if ret != 0: + sys.exit(ret) # Run examples print("[build.py] Run examples") @@ -625,14 +685,38 @@ def install_and_run(): if LINUX: run_examples += (" && {python}" " {linux_dir}/deprecated_64bit/kivy_.py") - run_examples.format(linux_dir=LINUX_DIR, examples_dir=EXAMPLES_DIR) + run_examples.format( + python=sys.executable, + linux_dir=LINUX_DIR, + examples_dir=EXAMPLES_DIR) os.system(run_examples) - # Enter tools dir - os.system("cd {tools_dir}".format(tools_dir=TOOLS_DIR)) - print("[build.py] DONE") +def get_sudo(): + # System Python requires sudo when installing package + if sys.executable in ["/usr/bin/python", "/usr/bin/python3"]: + sudo = "sudo" + else: + sudo = "" + return sudo + + +def delete_directory_reliably(adir): + assert len(adir) > 2 + assert os.path.isdir(adir) + print("[build.py] Delete directory: {dir}" + .format(dir=adir.replace(ROOT_DIR, ""))) + if WINDOWS: + shutil.rmtree(adir) + else: + # On Linux sudo might be required to delete directory, as this + # might be a setup installer directory with package installed + # using sudo and in such case files were created with sudo. + os.system("{sudo} rm -rf {dir}" + .format(sudo=get_sudo(), dir=adir)) + + if __name__ == "__main__": main() diff --git a/tools/build_module.py b/tools/build_module.py index bb99eb2fb..0d1524df6 100644 --- a/tools/build_module.py +++ b/tools/build_module.py @@ -1,5 +1,10 @@ -# For internal use only - called by build.py. -# This is Cython's setup for building the cefpython module. +# Copyright (c) 2017 The CEF Python authors. All rights reserved. +# Licensed under the BSD 3-clause license. + +""" +build_module.py is for internal use only - called by build.py. +This is Cython's setup for building the cefpython module +""" # Use setuptools so that "Visual C++ compiler for Python 2.7" tools # can be used. Otherwise "Unable to find vcvarsall.bat" error occurs. @@ -171,7 +176,7 @@ def get_include_dirs(): def get_library_dirs(): print("[build_module.py] Prepare library directories") library_dirs = [ - os.path.join(CEF_BINARY, "lib"), + os.path.join(CEF_BINARIES_LIBRARIES, "lib"), ] if WINDOWS: library_dirs.extend([ @@ -182,8 +187,11 @@ def get_library_dirs(): os.path.join(SRC_DIR, "subprocess", "Release_{os}" .format(os=OS_POSTFIX2)), + os.path.join(SRC_DIR, "subprocess", + "Release_py{pyver}_{os}" + .format(pyver=PYVERSION, os=OS_POSTFIX2)), os.path.join(SRC_DIR, "cpp_utils", - "Release_py{os}" + "Release_{os}" .format(os=OS_POSTFIX2)) ]) if MAC or LINUX: @@ -280,6 +288,9 @@ def compile_time_constants(): def main(): + if len(sys.argv) <= 1: + print(__doc__) + sys.exit(1) print("[build_module.py] Cython version: %s" % Cython.__version__) compile_time_constants() options = dict() diff --git a/tools/common.py b/tools/common.py index f42a2667d..fb0a733bb 100644 --- a/tools/common.py +++ b/tools/common.py @@ -29,32 +29,55 @@ # Python version eg. 27 PYVERSION = str(sys.version_info[0])+str(sys.version_info[1]) -# Directories -TOOLS_DIR = os.path.abspath(os.path.dirname(__file__)) -SRC_DIR = os.path.abspath(os.path.join(TOOLS_DIR, "../src")) -WINDOWS_DIR = os.path.abspath(os.path.join(SRC_DIR, "windows")) -MAC_DIR = os.path.abspath(os.path.join(SRC_DIR, "mac")) -LINUX_DIR = os.path.abspath(os.path.join(SRC_DIR, "linux")) -CPP_UTILS_DIR = os.path.abspath(os.path.join(SRC_DIR, "cpp_utils")) -CLIENT_HANDLER_DIR = os.path.abspath(os.path.join(SRC_DIR, "client_handler")) -SUBPROCESS_DIR = os.path.abspath(os.path.join(SRC_DIR, "subprocess")) -CEFPYTHON_DIR = os.path.abspath(os.path.join(SRC_DIR, "..")) -EXAMPLES_DIR = os.path.abspath(os.path.join(CEFPYTHON_DIR, "examples")) -UNITTESTS_DIR = os.path.abspath(os.path.join(CEFPYTHON_DIR, "unittests")) -BUILD_DIR = os.path.abspath(os.path.join(CEFPYTHON_DIR, "build")) -BUILD_CEFPYTHON = os.path.abspath(os.path.join(BUILD_DIR, "build_cefpython")) -# CEF_BINARY may be auto-overwritten through detect_cef_binary_directory() -CEF_BINARY = os.path.abspath(os.path.join(BUILD_DIR, "cef_"+OS_POSTFIX2)) -CEFPYTHON_BINARY = os.path.abspath(os.path.join(BUILD_DIR, - "cefpython_"+OS_POSTFIX2)) - - -def detect_cef_binary_directory(): - # Detect cef binary directory created by automate.py - # eg. build/cef55_3.2883.1553.g80bd606_win32/ - # and set CEF_BINARY to it. Otherwise CEF_BINARY will - # indicate to build/cef_{os_postfix2}/. - if not os.path.exists(CEF_BINARY): +# Root directory +assert __file__ +ROOT_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + +# Other directories +BUILD_DIR = os.path.join(ROOT_DIR, "build") +if BUILD_DIR: + BUILD_CEFPYTHON = os.path.join(BUILD_DIR, "build_cefpython") + # -- Auto-detected directories. + # May be auto-overwritten through detect_cef_binaries_libraries_dir() + CEF_BINARIES_LIBRARIES = os.path.join(BUILD_DIR, "cef_"+OS_POSTFIX2) + # Will be overwritten through detect_cefpython_binary_dir() + CEFPYTHON_BINARY = "CEFPYTHON_BINARY" +EXAMPLES_DIR = os.path.join(ROOT_DIR, "examples") +SRC_DIR = os.path.join(ROOT_DIR, "src") +if SRC_DIR: + CLIENT_HANDLER_DIR = os.path.join(SRC_DIR, "client_handler") + CPP_UTILS_DIR = os.path.join(SRC_DIR, "cpp_utils") + LINUX_DIR = os.path.join(SRC_DIR, "linux") + MAC_DIR = os.path.join(SRC_DIR, "mac") + SUBPROCESS_DIR = os.path.join(SRC_DIR, "subprocess") + WINDOWS_DIR = os.path.abspath(os.path.join(SRC_DIR, "windows")) +TOOLS_DIR = os.path.join(ROOT_DIR, "tools") +if TOOLS_DIR: + INSTALLER_DIR = os.path.join(TOOLS_DIR, "installer") +UNITTESTS_DIR = os.path.abspath(os.path.join(ROOT_DIR, "unittests")) + +# Visual Studio constants +VS_PLATFORM_ARG = "x86" if ARCH32 else "amd64" +VS2015_VCVARS = ("C:\\Program Files (x86)\\Microsoft Visual Studio 14.0" + "\\VC\\vcvarsall.bat") +VS2015_BUILD = "" # TODO +VS2013_VCVARS = ("C:\\Program Files (x86)\\Microsoft Visual Studio 12.0" + "\\VC\\vcvarsall.bat") +VS2013_BUILD = "" # TODO +VS2008_VCVARS = ("%LocalAppData%\\Programs\\Common\\Microsoft" + "\\Visual C++ for Python\\9.0\\vcvarsall.bat") +VS2008_BUILD = ("%LocalAppData%\\Programs\\Common\\" + "Microsoft\\Visual C++ for Python\\9.0\\" + "VC\\bin\\amd64\\vcbuild.exe") + + +def detect_cef_binaries_libraries_dir(): + """Detect cef binary directory created by automate.py + eg. build/cef55_3.2883.1553.g80bd606_win32/ + and set CEF_BINARIES_LIBRARIES to it, otherwise it will + point to eg. build/cef_win32/ .""" + global CEF_BINARIES_LIBRARIES + if not os.path.exists(CEF_BINARIES_LIBRARIES): version = get_cefpython_version() dirs = glob.glob(os.path.join( BUILD_DIR, @@ -64,10 +87,19 @@ def detect_cef_binary_directory(): os=OS_POSTFIX2, sep=os.sep))) if len(dirs) == 1: - print("[common.py] Auto detected CEF_BINARY directory: {dir}" - .format(dir=dirs[0])) - global CEF_BINARY - CEF_BINARY = dirs[0] + CEF_BINARIES_LIBRARIES = os.path.normpath(dirs[0]) + + +def detect_cefpython_binary_dir(): + """Detect cefpython binary directory where cefpython modules + will be put. Eg. buil/cefpython55_win32/.""" + version = get_cefpython_version() + binary_dir = "cefpython{major}_{os}".format( + major=version["CHROME_VERSION_MAJOR"], + os=OS_POSTFIX2) + binary_dir = os.path.join(BUILD_DIR, binary_dir) + global CEFPYTHON_BINARY + CEFPYTHON_BINARY = binary_dir def get_cefpython_version(): @@ -88,4 +120,5 @@ def get_version_from_file(header_file): return ret -detect_cef_binary_directory() +detect_cef_binaries_libraries_dir() +detect_cefpython_binary_dir() diff --git a/tools/installer/cefpython3.README.txt b/tools/installer/cefpython3.README.txt new file mode 100644 index 000000000..d23dea09d --- /dev/null +++ b/tools/installer/cefpython3.README.txt @@ -0,0 +1,13 @@ +1. To install CEF Python 3 package type: + + python setup.py install + + On Linux/Mac if using system Python then you need to add sudo: + + sudo python setup.py install + +2. To run examples enter the examples/ directory, + start with the hello_world.py example: + + cd examples/ + python hello_world.py diff --git a/tools/installer/cefpython3.__init__.py b/tools/installer/cefpython3.__init__.py new file mode 100644 index 000000000..ca54b44b5 --- /dev/null +++ b/tools/installer/cefpython3.__init__.py @@ -0,0 +1,62 @@ +# Copyright (c) 2017 The CEF Python authors. All rights reserved. +# Licensed under BSD 3-clause license. + +# NOTE: Template variables like {{VERSION}} are replaced with actual +# values when make.py tool generates this package installer. + +import os +import sys +import ctypes +import platform + +__all__ = ["cefpython", "wx"] +__version__ = "{{VERSION}}" +__author__ = "The CEF Python authors" + +# If package was installed using PIP or setup.py then package +# dir is here: +# /usr/local/lib/python2.7/dist-packages/cefpython3/ + +# If this is a debian package then package_dir returns: +# /usr/lib/pymodules/python2.7/cefpython3 +# The above path consists of symbolic links to the real directory: +# /usr/share/pyshared/cefpython3 + +package_dir = os.path.dirname(os.path.abspath(__file__)) + +# This loads the libcef.so library for the subprocess executable. +# On Mac it works without setting library paths, but let's set it +# just to be sure. +os.environ["LD_LIBRARY_PATH"] = package_dir +os.environ["DYLD_LIBRARY_PATH"] = package_dir + +# This env variable will be returned by cefpython.GetModuleDirectory(). +os.environ["CEFPYTHON3_PATH"] = package_dir + +# This loads the libcef library for the main python executable. +# This is required only on linux and Mac. +# The libffmpegsumo.so library does not need to be loaded here, +# it may cause issues to load it here in the browser process. +libcef = None +if platform.system() == "Darwin": + libcef = os.path.join(package_dir, "libcef.dylib") +elif platform.system() == "Linux": + libcef = os.path.join(package_dir, "libcef.so") +if libcef: + ctypes.CDLL(libcef, ctypes.RTLD_GLOBAL) + +# Load the cefpython module for proper Python version +if (2, 7) <= sys.version_info < (2, 8): + # noinspection PyUnresolvedReferences + from . import cefpython_py27 as cefpython +elif (3, 4) <= sys.version_info < (3, 5): + # noinspection PyUnresolvedReferences + from . import cefpython_py34 as cefpython +elif (3, 5) <= sys.version_info < (3, 6): + # noinspection PyUnresolvedReferences + from . import cefpython_py35 as cefpython +elif (3, 6) <= sys.version_info < (3, 7): + # noinspection PyUnresolvedReferences + from . import cefpython_py36 as cefpython +else: + raise Exception("Python version not supported: " + sys.version) diff --git a/tools/installer/cefpython3.setup.py b/tools/installer/cefpython3.setup.py new file mode 100644 index 000000000..646c5fb3d --- /dev/null +++ b/tools/installer/cefpython3.setup.py @@ -0,0 +1,225 @@ +# Copyright (c) 2017 The CEF Python authors. All rights reserved. +# Licensed under BSD 3-clause license. + +""" +cefpython3 package setup.py file. + +Usage: + setup.py install + setup.py bdist_wheel [--universal] + +Options: + install Install package + bdist_wheel Generate wheel package. Use the --universal flag when + you have built cefpython modules for multiple Python + versions. +""" + +# NOTE: Template variables like {{VERSION}} are replaced with actual +# values when make.py tool generates this package installer. + +import copy +import os +import platform +import subprocess +import sys + +# The setuptools package is not installed by default on a clean +# Ubuntu. Might be also a case on Windows. Also Python Eggs +# and Wheels can be created only with setuptools. +try: + from setuptools import setup + from setuptools.command.install import install + from setuptools.dist import Distribution + print("[setup.py] Using setuptools") +except ImportError: + from distutils.core import setup + from distutils.command.install import install + from distutils.dist import Distribution + print("[setup.py] Using distutils") + if "bdist_wheel" in sys.argv: + print("[setup.py] ERROR: You must install setuptools package using" + " pip tool to be able to create a wheel package. Type" + " 'pip install setuptools'.") + sys.exit(1) + + +# Need to know which files are executables to set appropriate execute +# permissions during post_install_hook. On Windows .exe postfix will +# be added to these automatically. +EXECUTABLES_NOEXT = [ + "cefclient", + "cefsimple", + "ceftests", + "subprocess", +] + + +class custom_install(install): + def __init__(self, *args, **kwargs): + install.__init__(self, *args, **kwargs) + + def run(self): + install.run(self) + post_install_hook() + + +class BinaryDistribution(Distribution): + def is_pure(self): + return False + + +# Provide a custom install command +print("[setup.py] Overload install command to enable execution of" + " post install hook") +cmdclass = {"install": custom_install} + +# Set custom platform tags on Mac when generating wheel package. See: +# http://lepture.com/en/2014/python-on-a-hard-wheel +if platform.system() == "Darwin" and "bdist_wheel" in sys.argv: + print("[setup.py] Overload bdist_wheel command to add custom" + " platform tags") + from wheel.bdist_wheel import bdist_wheel + + class custom_bdist_wheel(bdist_wheel): + def get_tag(self): + tag = bdist_wheel.get_tag(self) + platform_tag = ("macosx_10_6_intel" + ".macosx_10_9_intel.macosx_10_9_x86_64" + ".macosx_10_10_intel.macosx_10_10_x86_64") + tag = (tag[0], tag[1], platform_tag) + return tag + + cmdclass["bdist_wheel"] = custom_bdist_wheel + + +def main(): + setup( + distclass=BinaryDistribution, + cmdclass=cmdclass, + name="cefpython3", # No spaces here, so that it works with deb pkg + version="{{VERSION}}", + description="GUI toolkit for embedding a Chromium widget" + " in desktop applications", + license="BSD 3-clause", + author="Czarek Tomczak", + author_email="czarek.tomczak@@gmail.com", + url="https://github.com/cztomczak/cefpython", + download_url="https://github.com/cztomczak/cefpython/releases", + platforms=["{{SYSCONFIG_PLATFORM}}"], + packages=["cefpython3"], # Disabled: "cefpython3.wx" + package_data=get_package_data(), + classifiers=[ + "Development Status :: 6 - Mature", + "Intended Audience :: Developers", + "License :: OSI Approved :: BSD License", + "Natural Language :: English", + "Operating System :: MacOS :: MacOS X", + "Operating System :: Microsoft :: Windows", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Topic :: Desktop Environment", + "Topic :: Internet", + "Topic :: Internet :: WWW/HTTP", + "Topic :: Internet :: WWW/HTTP :: Browsers", + "Topic :: Multimedia", + ("Topic :: Software Development :: Libraries" + ":: Application Frameworks"), + "Topic :: Software Development :: User Interfaces", + ], + ) + print("[setup.py] OK installed") + + +def get_package_data(): + package_data = {"cefpython3": get_package_files()} + return package_data + + +def get_package_files(relative_dir=".", recursive=False): + """Finds files recursively in the cefpython3/ local directory. + Includes only files and their paths are relative to the cefpython3/ + local directory. Empty directories are not included.""" + old_dir = None + if not recursive: + old_dir = os.getcwd() + setup_dir = os.path.abspath(os.path.dirname(__file__)) + local_pkg_dir = os.path.join(setup_dir, "cefpython3") + os.chdir(local_pkg_dir) + files = os.listdir(relative_dir) + ret = list() + for fpath in files: + fpath = os.path.join(relative_dir, fpath) + if os.path.isdir(fpath): + ret.extend(get_package_files(relative_dir=fpath, recursive=True)) + else: + ret.append(fpath) + if not recursive: + os.chdir(old_dir) + return ret + + +def get_executables(): + data = copy.copy(EXECUTABLES_NOEXT) + if platform.system() == "Windows": + for key, executable in enumerate(data): + data[key] += ".exe" + return data + + +def post_install_hook(): + """Post install hook to chmod files on Linux and Mac.""" + + # Nothing extra required to do on Windows + if platform.system() == "Windows": + print("[setup.py] post_install_hook is ignored on Windows") + return + + # If this a wheel package generation then do not execute the hook + if "bdist_wheel" in sys.argv: + print("[setup.py] Ignoring post_install_hook as this is bdist_wheel") + return + + print("[setup.py] Execute post_install_hook") + + # Find the installed package directory. Do not import from + # the local cefpython3/ directory. + print("[setup.py] Overload sys.path to facilitate finding correct" + " directory for the installed package") + del sys.path[0] + sys.path.append("") + import cefpython3 + installed_package_dir = os.path.dirname(cefpython3.__file__) + + # Make sure that the imported package wasn't the local cefptyhon3/ + # directory. + print("[setup.py] Installed package directory: {dir}" + .format(dir=installed_package_dir)) + assert not installed_package_dir.startswith( + os.path.dirname(os.path.abspath(__file__))) + + # Set permissions on executables + print("[setup.py] Set execute permissions on executables") + for executable in get_executables(): + executable = os.path.join(installed_package_dir, executable) + command = "chmod +x {executable}".format(executable=executable) + print("[setup.py] {command}".format(command=command)) + subprocess.call(command, shell=True) + + # Set write permissions on log files + print("[setup.py] Set write permissions on log files") + package_data = get_package_data() + for pkgfile in package_data: + if not pkgfile.endswith(".log"): + continue + logfile = os.path.join(installed_package_dir, pkgfile) + command = "chmod 666 {logfile}".format(logfile=logfile) + print("[setup.py] {command}".format(command=command)) + subprocess.call(command, shell=True) + + +if __name__ == "__main__": + main() diff --git a/tools/make_installer.py b/tools/make_installer.py new file mode 100644 index 000000000..87f1a12de --- /dev/null +++ b/tools/make_installer.py @@ -0,0 +1,309 @@ +# Copyright (c) 2017 The CEF Python authors. All rights reserved. +# Licensed under BSD 3-clause license. + +""" +Create setup.py package installer. + +Usage: + make.py VERSION + +Options: + VERSION Version number eg. 50.0 +""" + +from common import * + +import glob +import os +import re +import shutil +import subprocess +import sys +import sysconfig + +# Command line args +VERSION = "" + +# Globals +SETUP_DIR = "" +PKG_DIR = "" + +# Config +IGNORE_EXT = [".log", ".pyc", ".pdb", ] +IGNORE_DIRS = ["__pycache__"] + + +def main(): + command_line_args() + + # Setup and package directories + global SETUP_DIR, PKG_DIR + setup_dir_name = ("cefpython3-{version}-{os}-setup" + .format(version=VERSION, os=OS_POSTFIX2)) + SETUP_DIR = os.path.join(BUILD_DIR, setup_dir_name) + PKG_DIR = os.path.join(SETUP_DIR, "cefpython3") + + # Print src and dest for file operations + print("[make_installer.py] Src: {src}".format(src=ROOT_DIR)) + print("[make_installer.py] Dst: {dst}".format(dst=SETUP_DIR)) + + # Make directories + if os.path.exists(SETUP_DIR): + print("[make_installer.py] Delete: {dir}" + .format(dir=SETUP_DIR.replace(ROOT_DIR, ""))) + shutil.rmtree(SETUP_DIR) + os.makedirs(SETUP_DIR) + os.makedirs(os.path.join(SETUP_DIR, "examples/")) + os.makedirs(PKG_DIR) + os.makedirs(os.path.join(PKG_DIR, "examples/")) + + # Copy files from tools/installer/ + copy_tools_installer_files(SETUP_DIR, PKG_DIR) + + # Multiple copy operations using glob patterns + copy_operations = [ + (ROOT_DIR, "License"), (PKG_DIR,), + (CEF_BINARIES_LIBRARIES, "*.txt"), (PKG_DIR,), + (CEF_BINARIES_LIBRARIES, "bin/*"), (PKG_DIR,), + (CEFPYTHON_BINARY, "*"), (PKG_DIR,), + (EXAMPLES_DIR, "*"), (PKG_DIR, "examples/"), + (EXAMPLES_DIR, "*"), (SETUP_DIR, "examples/"), + ] + perform_copy_operations(copy_operations) + + # Linux only operations + if LINUX: + copy_operations_linux = [ + (LINUX_DIR, "binaries_64bit/kivy_.py"), + (PKG_DIR, "examples/"), + (LINUX_DIR, "binaries_64bit/kivy-select-boxes/*"), + (PKG_DIR, "examples/") + ] + perform_copy_operations(copy_operations_linux) + + # Create empty debug.log files so that package uninstalls cleanly + # in case examples or CEF tests were launched. See Issue #149. + create_empty_log_file(os.path.join(PKG_DIR, "debug.log")) + create_empty_log_file(os.path.join(PKG_DIR, "examples/debug.log")) + + print("[make_installer.py] DONE. Installer package created: {setup_dir}" + .format(setup_dir=SETUP_DIR)) + + +def command_line_args(): + args = " ".join(sys.argv) + match = re.search(r"\d+\.\d+", args) + if match: + global VERSION + VERSION = match.group(0) + else: + print(__doc__) + sys.exit(1) + + +def copy_tools_installer_files(setup_dir, pkg_dir): + variables = dict() + variables["VERSION"] = VERSION + variables["SYSCONFIG_PLATFORM"] = sysconfig.get_platform() + + shutil.copy( + os.path.join(INSTALLER_DIR, "cefpython3.README.txt"), + os.path.join(setup_dir, "README.txt")) + + copy_template_file( + os.path.join(INSTALLER_DIR, "cefpython3.setup.py"), + os.path.join(setup_dir, "setup.py"), + variables) + + copy_template_file( + os.path.join(INSTALLER_DIR, "cefpython3.__init__.py"), + os.path.join(pkg_dir, "__init__.py"), + variables) + + +def copy_template_file(src, dst, variables): + """Copy file and replaces template variables in that file.""" + print("[make_installer.py] Copy_t: {src} ==> {dst}" + .format(src=short_src_path(src), dst=short_dst_path(dst))) + with open(src, "rb") as fo: + contents = fo.read() + contents = replace_template_vars(contents, variables) + with open(dst, "wb") as fo: + fo.write(contents) + return contents + + +def replace_template_vars(string, dictionary): + """Replaces template variables like {{SOME}} in the string + using the dictionary values.""" + orig_string = string + for key, value in dictionary.items(): + string = string.replace("{{"+key+"}}", value) + if string == orig_string: + raise Exception("Nothing to format") + if re.search(r"\{\{[a-zA-Z0-9_]+\}\}", string): + raise Exception("Not all strings were formatted") + return string + + +def perform_copy_operations(operations): + assert len(operations) % 2 == 0 + count_ops = int(len(operations) / 2) + for op_i in range(count_ops): + # Refer to values by index + pattern = operations[op_i*2] + dst_dir = operations[op_i*2+1] + # Convert tuples to lists + pattern = list(pattern) + dst_dir = list(dst_dir) + # Join paths + pattern = os.path.join(*pattern) + dst_dir = os.path.join(*dst_dir) + dst_dir = os.path.abspath(dst_dir) + # Normalize unix slashes on Windows + pattern = pattern.replace("/", os.path.sep) + # dst_dir must be a directory + if not os.path.isdir(dst_dir): + raise Exception("Not a directory: {dst_dir}" + .format(dst_dir=dst_dir)) + # Is pattern a file or a directory + if os.path.isfile(pattern): + if is_ignored_path(pattern): + raise Exception("Copy operation pattern is in ignore list:" + " {pattern}".format(pattern=pattern)) + print("[make_installer.py] Copy: {file} ==> {dir}" + .format(file=short_src_path(pattern), + dir=short_dst_path(dst_dir))) + # Destination file must not exist + assert not os.path.exists(os.path.join(dst_dir, + os.path.basename(pattern))) + shutil.copy(pattern, dst_dir) + else: + # pattern is a glob pattern + base_dir = os.path.dirname(pattern) + assert base_dir + assert base_dir == os.path.abspath(base_dir) + paths = glob.glob(pattern) + if not len(paths): + raise Exception("No paths found in: {pattern}" + .format(pattern=pattern)) + for path in paths: + # "path" variable contains absolute path + assert path == os.path.abspath(path) + if os.path.isfile(path): + if is_ignored_path(path): + continue + print("[make_installer.py] Copy: {file} ==> {dir}" + .format(file=short_src_path(path), + dir=short_dst_path(dst_dir))) + # Destination file must not exist + assert not os.path.exists( + os.path.join(dst_dir, os.path.basename(path))) + shutil.copy(path, dst_dir) + elif os.path.isdir(path): + if is_ignored_path(path): + continue + relative_dir = path.replace(base_dir, "") + assert relative_dir[0] == os.path.sep + relative_dir = relative_dir[1:] + perform_copy_recursively(base_dir, relative_dir, dst_dir) + else: + raise Exception("Unknown path: {path}".format(path=path)) + + +def perform_copy_recursively(base_dir, relative_dir, new_dir): + real_dir = os.path.join(base_dir, relative_dir) + assert os.path.exists(real_dir) and os.path.isdir(real_dir) + assert os.path.exists(new_dir) and os.path.isdir(new_dir) + + # Create subdirectory + new_subdir = os.path.join(new_dir, relative_dir) + if not os.path.exists(new_subdir): + print("[make_installer.py] Create: {dir}" + .format(dir=short_dst_path(new_subdir))) + os.makedirs(new_subdir) + + # List directory + paths = os.listdir(real_dir) + for path in paths: + # "path" variable contains relative path + real_path = os.path.join(real_dir, path) + path = os.path.join(relative_dir, path) + if os.path.isdir(real_path): + if is_ignored_path(real_path): + continue + perform_copy_recursively(base_dir, path, new_dir) + elif os.path.isfile(real_path): + if is_ignored_path(real_path): + continue + new_file = os.path.join(new_dir, path) + new_subdir = os.path.dirname(new_file) + if os.path.exists(new_file): + raise Exception("Path aready exists: {new_file}" + .format(new_file=short_dst_path(new_file))) + print("[make_installer.py] Copy: {file} ==> {dir}" + .format(file=short_src_path(real_path), + dir=short_dst_path(new_subdir))) + shutil.copy(real_path, new_subdir) + else: + raise Exception("Unknown path: {path}".format(path=real_path)) + + +def is_ignored_path(path): + basename = os.path.basename(path) + if basename in IGNORE_DIRS: + print("[make_installer.py] Ignore: {dir}" + .format(dir=short_src_path(path))) + return True + for ext in IGNORE_EXT: + if path.endswith(ext): + print("[make_installer.py] Ignore: {file}" + .format(file=short_src_path(path))) + return True + return False + + +def delete_files_by_pattern(pattern): + assert len(pattern) > 2 + # Normalize unix slashes on Windows + pattern = pattern.replace("/", os.path.sep) + print("[make_installer.py] Delete: {pattern}" + .format(pattern=short_dst_path(pattern))) + files = glob.glob(pattern) + for f in files: + os.remove(f) + + +def create_empty_log_file(log_file): + # Normalize unix slashes on Windows + log_file = log_file.replace("/", os.path.sep) + print("[make_installer.py] Create: {file}" + .format(file=short_dst_path(log_file))) + with open(log_file, "wb") as fo: + fo.write("") + # On Linux and Mac chmod so that for cases when package is + # installed using sudo. When wheel package is created it + # will remember file permissions set. + if LINUX or MAC: + command = "chmod 666 {file}".format(file=log_file) + print("[make_installer.py] {command}" + .format(command=command.replace(SETUP_DIR, ""))) + subprocess.call(command, shell=True) + + +def short_src_path(path): + # Very long: \build\cef55_3.2883.1553.g80bd606_win32\ + find = os.path.basename(CEF_BINARIES_LIBRARIES) + if len(find) > 12: + path = path.replace(find, find[:12] + "*") + path = path.replace(ROOT_DIR, "") + return path + + +def short_dst_path(path): + path = path.replace(SETUP_DIR, "") + return path + + +if __name__ == "__main__": + main() diff --git a/tools/requirements.txt b/tools/requirements.txt index c5ba053db..abdc18283 100644 --- a/tools/requirements.txt +++ b/tools/requirements.txt @@ -1,2 +1,4 @@ -cython == 0.25.2 +Cython == 0.25.2 docopt >= 0.6.2 +setuptools +wheel diff --git a/unittests/_test_runner.py b/unittests/_test_runner.py index f25f48cbb..8b970acaf 100644 --- a/unittests/_test_runner.py +++ b/unittests/_test_runner.py @@ -3,9 +3,10 @@ """Run unit tests. With no arguments all tests are run. Read notes below. Usage: - _test_runner.py [FILE | _TESTCASE] + _test_runner.py [--debug] [FILE | _TESTCASE] Options: + --debug Enable debug info FILE Run tests from single file _TESTCASE Test cases matching pattern to run eg "file.TestCase". Calling with this argument is for internal use only. @@ -27,6 +28,9 @@ import re import subprocess +# Command line args +CUSTOM_CMDLINE_ARG = "" + def main(file_arg=""): # type: (str) -> None @@ -37,7 +41,12 @@ def main(file_arg=""): # Script arguments testcase_arg = "" - if len(sys.argv) > 1: + if len(sys.argv) > 1 and sys.argv[1].startswith("--"): + # Will allow to pass custom args like --debug to isolated tests + # (main_test.py for example). + global CUSTOM_CMDLINE_ARG + CUSTOM_CMDLINE_ARG = sys.argv[1] + elif len(sys.argv) > 1: if ".py" in sys.argv[1]: file_arg = sys.argv[1] else: @@ -141,7 +150,8 @@ def _run_suites_in_isolation(self, suites): # Run test using new instance of Python interpreter try: output = subprocess.check_output( - [sys.executable, "_test_runner.py", testcase_id], + [sys.executable, "_test_runner.py", testcase_id, + CUSTOM_CMDLINE_ARG], stderr=subprocess.STDOUT) exit_code = 0 except subprocess.CalledProcessError as exc: diff --git a/unittests/main_test.py b/unittests/main_test.py index a20af1da9..05f341589 100644 --- a/unittests/main_test.py +++ b/unittests/main_test.py @@ -101,11 +101,15 @@ def test_main(self): print("Python {ver}".format(ver=sys.version[:6])) # Test initialization of CEF - cef.Initialize({ + settings = { "debug": False, "log_severity": cef.LOGSEVERITY_ERROR, "log_file": "", - }) + } + if "--debug" in sys.argv: + settings["debug"] = True + settings["log_severity"] = cef.LOGSEVERITY_INFO + cef.Initialize(settings) subtest_message("cef.Initialize() ok") # Test global handler From 97712b3a213b591b63c2f230f3af158f626b3b0d Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 20 Feb 2017 21:11:31 +0100 Subject: [PATCH 132/557] Fix crashes in unit tests and examples on Windows with v55+ (#294)... Fixes to wxpython.py example, works great. The hello_world.py example also works good. Unit tests are working fine now. When not providing parent window handle (NULL) during browser creation, so that CEF creates top-level window itself, in such case must call SetAsPopup on Windows. Fixes to build.py tool to run all examples smoothly. --- examples/wxpython.py | 34 +++++++------ src/window_info.pyx | 2 +- tools/build.py | 66 +++++++++++++++----------- tools/installer/cefpython3.__init__.py | 3 +- tools/installer/cefpython3.setup.py | 3 +- tools/make_installer.py | 2 +- 6 files changed, 63 insertions(+), 47 deletions(-) diff --git a/examples/wxpython.py b/examples/wxpython.py index 2de7a7520..8e7026fc7 100644 --- a/examples/wxpython.py +++ b/examples/wxpython.py @@ -3,8 +3,11 @@ # To install wxPython on Linux type "sudo apt-get install python-wxtools". -# Tested with wxPython 2.8 on Linux, wxPython 3.0 on Windows/Mac -# and CEF Python v55.3+. +# Tested configurations: +# - wxPython 2.8 on Linux +# - wxPython 3.0.2.0 msw (classic) on Windows +# - wxPython 3.0 on Mac +# - CEF Python v55.3+ import wx from cefpython3 import cefpython as cef @@ -28,7 +31,7 @@ def main(): settings["auto_zooming"] = "system_dpi" # Embed DPI awareness xml manifest inside .exe (recommended, # most reliable) or call the SetProcessDpiAware function. - # noinspection PyUnresolvedReferences + # noinspection PyUnresolvedReferences, PyArgumentList cef.DpiAware.SetProcessDpiAware() cef.Initialize(settings=settings) app = CefApp(False) @@ -40,7 +43,7 @@ def main(): def check_versions(): print("[wxpython.py] CEF Python {ver}".format(ver=cef.__version__)) print("[wxpython.py] Python {ver}".format(ver=sys.version[:6])) - print("[wxpython.py] wx {ver}".format(ver=wx.version())) + print("[wxpython.py] wxPython {ver}".format(ver=wx.version())) # CEF Python version requirement assert cef.__version__ >= "55.3", "CEF Python v55.3+ required to run this" @@ -75,11 +78,10 @@ def setup_icon(self): def create_menu(self): filemenu = wx.Menu() - filemenu.Append(1, "Open") - exit_ = filemenu.Append(2, "Exit") - self.Bind(wx.EVT_MENU, self.OnClose, exit_) + filemenu.Append(1, "Some option") + exit_ = filemenu.Append(2, "Another option") aboutmenu = wx.Menu() - aboutmenu.Append(1, "CEF Python") + aboutmenu.Append(1, "Yet another option") menubar = wx.MenuBar() menubar.Append(filemenu, "&File") menubar.Append(aboutmenu, "&About") @@ -93,11 +95,12 @@ def embed_browser(self): self.browser.SetClientHandler(FocusHandler()) def OnSetFocus(self, _): - if not self.brower: + if not self.browser: return if WINDOWS: # noinspection PyUnresolvedReferences - cef.WindowUtils.OnSetFocus(self.GetHandleForBrowser(), 0, 0, 0) + cef.WindowUtils.OnSetFocus(self.browser_panel.GetHandle(), + 0, 0, 0) self.browser.SetFocus(True) def OnSize(self, _): @@ -105,11 +108,11 @@ def OnSize(self, _): return if WINDOWS: # noinspection PyUnresolvedReferences - cef.WindowUtils.OnSize(self.GetHandleForBrowser(), 0, 0, 0) + cef.WindowUtils.OnSize(self.browser_panel.GetHandle(), + 0, 0, 0) elif LINUX: (x, y) = (0, 0) (width, height) = self.browser_panel.GetSizeTuple() - # noinspection PyUnresolvedReferences self.browser.SetBounds(x, y, width, height) self.browser.NotifyMoveOrResizeStarted() @@ -154,9 +157,10 @@ def OnGotFocus(self, browser, **_): # window (alt+tab) and then back to this example, keyboard # focus becomes broken, you can't type anything, even # though a type cursor blinks in web view. - print("[wxpython.py] FocusHandler.OnGotFocus:" - " keyboard focus fix (#284)") - browser.SetFocus(True) + if LINUX: + print("[wxpython.py] FocusHandler.OnGotFocus:" + " keyboard focus fix (#284)") + browser.SetFocus(True) class CefApp(wx.App): diff --git a/src/window_info.pyx b/src/window_info.pyx index 988c665e4..27c6cf165 100644 --- a/src/window_info.pyx +++ b/src/window_info.pyx @@ -87,7 +87,7 @@ cdef class WindowInfo: # On Windows when parent window handle is 0 then SetAsPopup() # must be called instead. if parentWindowHandle == 0: - self.SetAsPopup(parentWindowHandle, "Popup") + self.SetAsPopup(parentWindowHandle, "") return if parentWindowHandle != 0\ and not WindowUtils.IsWindowHandle(parentWindowHandle): diff --git a/tools/build.py b/tools/build.py index 6c424a784..525518379 100644 --- a/tools/build.py +++ b/tools/build.py @@ -648,16 +648,22 @@ def install_and_run(): # Make setup installer print("[build.py] Make setup installer") make_tool = os.path.join(TOOLS_DIR, "make_installer.py") - os.system("{python} {make_tool} --version {version}" - .format(python=sys.executable, - make_tool=make_tool, - version=VERSION)) + ret = os.system("{python} {make_tool} --version {version}" + .format(python=sys.executable, + make_tool=make_tool, + version=VERSION)) + if ret != 0: + print("[build.py] ERROR while making installer package") + sys.exit(ret) # Install print("[build.py] Install the cefpython package") os.chdir(setup_installer_dir) - os.system("{sudo} {python} setup.py install" - .format(sudo=get_sudo(), python=sys.executable)) + ret = os.system("{sudo} {python} setup.py install" + .format(sudo=get_sudo(), python=sys.executable)) + if ret != 0: + print("[build.py] ERROR while installing package") + sys.exit(ret) os.chdir(BUILD_DIR) # Run unittests @@ -666,32 +672,36 @@ def install_and_run(): ret = os.system("{python} {test_runner}" .format(python=sys.executable, test_runner=test_runner)) if ret != 0: + print("[build.py] ERROR while running unit tests") sys.exit(ret) # Run examples print("[build.py] Run examples") - if KIVY_FLAG: - run_examples = "{python} {linux_dir}/deprecated_64bit/kivy_.py" - else: - run_examples = ("cd {examples_dir}" - " && {python} hello_world.py" - " && {python} wxpython.py" - " && {python} gtk2.py" - " && {python} gtk2.py --message-loop-timer" - # " && {python} gtk3.py" - " && {python} tkinter_.py" - " && {python} qt.py pyqt" - " && {python} qt.py pyside") - if LINUX: - run_examples += (" && {python}" - " {linux_dir}/deprecated_64bit/kivy_.py") - run_examples.format( - python=sys.executable, - linux_dir=LINUX_DIR, - examples_dir=EXAMPLES_DIR) - os.system(run_examples) - - print("[build.py] DONE") + os.chdir(EXAMPLES_DIR) + examples = list() + if not KIVY_FLAG: + examples.extend([ + "hello_world.py", + "wxpython.py", + "gtk2.py", + "gtk2.py --message-loop-timer", + "gtk3.py", + "tkinter_.py", + "qt.py pyqt", + "qt.py pyside", + ]) + if LINUX: + examples.append("{linux_dir}/deprecated_64bit/kivy_.py" + .format(linux_dir=LINUX_DIR)) + for example in examples: + ret = os.system("{python} {example}" + .format(python=sys.executable, example=example)) + if ret != 0: + print("[build.py] ERROR while running example: {example}" + .format(example=example)) + sys.exit(1) + + print("[build.py] Everything OK") def get_sudo(): diff --git a/tools/installer/cefpython3.__init__.py b/tools/installer/cefpython3.__init__.py index ca54b44b5..5e794a0aa 100644 --- a/tools/installer/cefpython3.__init__.py +++ b/tools/installer/cefpython3.__init__.py @@ -2,7 +2,8 @@ # Licensed under BSD 3-clause license. # NOTE: Template variables like {{VERSION}} are replaced with actual -# values when make.py tool generates this package installer. +# values when make_installer.py tool generates this package +# installer. import os import sys diff --git a/tools/installer/cefpython3.setup.py b/tools/installer/cefpython3.setup.py index 646c5fb3d..292b2ee36 100644 --- a/tools/installer/cefpython3.setup.py +++ b/tools/installer/cefpython3.setup.py @@ -16,7 +16,8 @@ """ # NOTE: Template variables like {{VERSION}} are replaced with actual -# values when make.py tool generates this package installer. +# values when make_installer.py tool generates this package +# installer. import copy import os diff --git a/tools/make_installer.py b/tools/make_installer.py index 87f1a12de..5d4f7501a 100644 --- a/tools/make_installer.py +++ b/tools/make_installer.py @@ -5,7 +5,7 @@ Create setup.py package installer. Usage: - make.py VERSION + make_installer.py VERSION Options: VERSION Version number eg. 50.0 From 9bd3accd5eee4411dd8b74bf5ff7b1520bf4b4b7 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Tue, 21 Feb 2017 15:21:55 +0100 Subject: [PATCH 133/557] Fix issues with examples on Windows with v55+ (#294)... All examples do run fine on Windows now. Add run_examples.py tool to run all examples that can be run on current configuration. --- examples/gtk2.py | 60 ++++++++++----- examples/gtk3.py | 59 +++++++++++++-- examples/hello_world.py | 2 +- examples/qt.py | 104 ++++++++++++++++++-------- examples/tkinter_.py | 21 ++++-- examples/wxpython.py | 27 ++++--- src/window_utils_linux.pyx | 19 +++++ src/window_utils_mac.pyx | 19 +++++ src/window_utils_win.pyx | 14 ++-- tools/build.py | 28 ++----- tools/common.py | 2 +- tools/run_examples.py | 147 +++++++++++++++++++++++++++++++++++++ 12 files changed, 396 insertions(+), 106 deletions(-) create mode 100644 tools/run_examples.py diff --git a/examples/gtk2.py b/examples/gtk2.py index 092c82c87..c7b4c84b6 100644 --- a/examples/gtk2.py +++ b/examples/gtk2.py @@ -1,5 +1,5 @@ # Example of embedding CEF Python browser using PyGTK library (GTK 2). -# Tested with GTK 2.24 and CEF Python v55.3+, only on Linux. +# Tested with GTK 2.24 and CEF Python v55.3+, on Windows/Linux. # Known issue on Linux: Keyboard focus problem (Issue #284). from cefpython3 import cefpython as cef @@ -8,16 +8,25 @@ import gobject import sys import os +import platform + +# Fix for PyCharm hints warnings +WindowUtils = cef.WindowUtils() + +# Platforms +WINDOWS = (platform.system() == "Windows") +LINUX = (platform.system() == "Linux") +MAC = (platform.system() == "Darwin") # In CEF you can run message loop in two ways (see API docs for more details): -# 1. By calling cef.MessageLoop() instead of an application-provided +# 1. By calling cef.MessageLoopWork() in a timer - each call performs +# a single iteration of CEF message loop processing. +# 2. By calling cef.MessageLoop() instead of an application-provided # message loop to get the best balance between performance and CPU # usage. This function will block until a quit message is received by -# the system. -# 2. By calling cef.MessageLoopWork() in a timer - each call performs -# a single iteration of CEF message loop processing. -MESSAGE_LOOP_BEST = 1 -MESSAGE_LOOP_TIMER = 2 # Pass --message-loop-timer flag to script to use this +# the system. This seem to work only on Linux in GTK example. +MESSAGE_LOOP_TIMER = 1 +MESSAGE_LOOP_CEF = 2 # Pass --message-loop-cef flag to script on Linux g_message_loop = None @@ -28,7 +37,7 @@ def main(): cef.Initialize() gobject.threads_init() Gtk2Example() - if g_message_loop == MESSAGE_LOOP_BEST: + if g_message_loop == MESSAGE_LOOP_CEF: cef.MessageLoop() else: gtk.main() @@ -46,13 +55,13 @@ def check_versions(): def configure_message_loop(): global g_message_loop - if "--message-loop-timer" in sys.argv: + if "--message-loop-cef" in sys.argv: + print("[gkt2.py] Message loop mode: CEF (best performance)") + g_message_loop = MESSAGE_LOOP_CEF + sys.argv.remove("--message-loop-cef") + else: print("[gkt2.py] Message loop mode: TIMER") g_message_loop = MESSAGE_LOOP_TIMER - sys.argv.remove("--message-loop-timer") - else: - print("[gkt2.py] Message loop mode: BEST") - g_message_loop = MESSAGE_LOOP_BEST if len(sys.argv) > 1: print("[gkt2.py] ERROR: unknown argument passed") sys.exit(1) @@ -83,7 +92,7 @@ def __init__(self): self.main_window.add(self.vbox) windowInfo = cef.WindowInfo() - windowInfo.SetAsChild(self.main_window.window.xid) + windowInfo.SetAsChild(self.get_handle()) self.browser = cef.CreateBrowserSync(windowInfo, settings={}, url="https://www.google.com/") self.browser.SetClientHandler(LoadHandler()) @@ -95,6 +104,12 @@ def __init__(self): if g_message_loop == MESSAGE_LOOP_TIMER: gobject.timeout_add(10, self.on_timer) + def get_handle(self): + if LINUX: + return self.main_window.window.xid + else: + return self.main_window.window.handle + def create_menu(self): item1 = gtk.MenuItem('MenuBar') item1.show() @@ -131,16 +146,22 @@ def on_vbox_size_allocate(self, _, data): y = data.y + self.menubar_height width = data.width height = data.height - self.menubar_height - self.browser.SetBounds(x, y, width, height) + if WINDOWS: + WindowUtils.OnSize(self.get_handle(), 0, 0, 0) + elif LINUX: + self.browser.SetBounds(x, y, width, height) def on_menubar_size_allocate(self, _, data): self.menubar_height = data.height def on_exit(self, *_): + if self.exiting: + print("[gtk2.py] on_exit() called, but already exiting") + return self.exiting = True self.browser.CloseBrowser(True) self.browser = None - if g_message_loop == MESSAGE_LOOP_BEST: + if g_message_loop == MESSAGE_LOOP_CEF: cef.QuitMessageLoop() else: gtk.main_quit() @@ -158,9 +179,10 @@ def OnLoadStart(self, browser, **_): # sometimes during initial loading, keyboard focus may # break and it is not possible to type anything, even # though a type cursor blinks in web view. - print("[gtk2.py] LoadHandler.OnLoadStart:" - " keyboard focus fix (#284)") - browser.SetFocus(True) + if LINUX: + print("[gtk2.py] LoadHandler.OnLoadStart:" + " keyboard focus fix (#284)") + browser.SetFocus(True) self.initial_app_loading = False diff --git a/examples/gtk3.py b/examples/gtk3.py index 5820dcd78..2223362b0 100644 --- a/examples/gtk3.py +++ b/examples/gtk3.py @@ -1,12 +1,33 @@ -# ! CURRENTLY BROKEN ! with v54+ (Issue #261). -# Example of embedding CEF Python browser using PyGObject library (GTK 3). -# Tested with GTK 3.10 and CEF Python v53.1+, only on Linux. +# Example of embedding CEF Python browser using PyGObject/PyGI (GTK 3). + +# Linux note: This example is currently broken in v54+ on Linux (Issue #261). +# It works fine with cefpython v53. + +# Tested configurations: +# - GTK 3.18 on Windows +# - GTK 3.10 on Linux +# - CEF Python v53.1+ from cefpython3 import cefpython as cef +import ctypes # noinspection PyUnresolvedReferences -from gi.repository import GdkX11, Gtk, GObject, GdkPixbuf +from gi.repository import Gtk, GObject, Gdk, GdkPixbuf import sys import os +import platform + +# Fix for PyCharm hints warnings +WindowUtils = cef.WindowUtils() + +# Platforms +WINDOWS = (platform.system() == "Windows") +LINUX = (platform.system() == "Linux") +MAC = (platform.system() == "Darwin") + +# Linux imports +if LINUX: + # noinspection PyUnresolvedReferences + from gi.repository import GdkX11 def main(): @@ -25,9 +46,10 @@ def main(): class Gtk3Example(Gtk.Application): def __init__(self): - super(Gtk3Example, self).__init__(application_id='cefpython.gtk') + super(Gtk3Example, self).__init__(application_id='cefpython.gtk3') self.browser = None self.window = None + self.win32_handle = None def run(self, argv): GObject.threads_init() @@ -36,6 +58,22 @@ def run(self, argv): self.connect("shutdown", self.on_shutdown) return super(Gtk3Example, self).run(argv) + def get_handle(self): + if LINUX: + return self.window.get_property("window").get_xid() + elif WINDOWS: + Gdk.threads_enter() + ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p + ctypes.pythonapi.PyCapsule_GetPointer.argtypes = \ + [ctypes.py_object] + gpointer = ctypes.pythonapi.PyCapsule_GetPointer( + self.window.get_property("window").__gpointer__, None) + gdk_dll = ctypes.CDLL("libgdk-3-0.dll") + self.win32_handle = gdk_dll.gdk_win32_window_get_handle( + gpointer) + Gdk.threads_leave() + return self.win32_handle + def on_timer(self): cef.MessageLoopWork() return True @@ -51,10 +89,13 @@ def on_activate(self, *_): self.setup_icon() self.window.realize() window_info = cef.WindowInfo() - window_info.SetAsChild(self.window.get_property("window").get_xid()) + window_info.SetAsChild(self.get_handle()) self.browser = cef.CreateBrowserSync(window_info, url="https://www.google.com/") self.window.show_all() + # Must set size of the window again after it was shown, + # otherwise browser occupies only part of the window area. + self.window.resize(*self.window.get_default_size()) def on_configure(self, *_): if self.browser: @@ -63,7 +104,11 @@ def on_configure(self, *_): def on_size_allocate(self, _, data): if self.browser: - self.browser.SetBounds(data.x, data.y, data.width, data.height) + if WINDOWS: + WindowUtils.OnSize(self.win32_handle, 0, 0, 0) + elif LINUX: + self.browser.SetBounds(data.x, data.y, + data.width, data.height) def on_focus_in(self, *_): if self.browser: diff --git a/examples/hello_world.py b/examples/hello_world.py index 5417bcfdb..0c64ab843 100644 --- a/examples/hello_world.py +++ b/examples/hello_world.py @@ -1,5 +1,5 @@ # Hello world example. Doesn't depend on any third party GUI framework. -# Tested with CEF Python v55.3+, only on Linux. +# Tested with CEF Python v55.3+. from cefpython3 import cefpython as cef import sys diff --git a/examples/qt.py b/examples/qt.py index 1877272f6..995f637fa 100644 --- a/examples/qt.py +++ b/examples/qt.py @@ -1,21 +1,30 @@ # Example of embedding CEF Python browser using PyQt/PySide libraries. # This example has two widgets: a navigation bar and a browser. # -# Tested with PyQt 4.10.4 (4.8.6), PySide 1.2.1 (4.8.6) -# and CEF Python v55.3+, only on Linux. +# Tested configurations: +# - PyQt 4.11.4 (4.8.7) on Windows +# - PySide 1.2.4 (4.8.7) on Windows +# - PyQt 4.10.4 (4.8.6) on Linux +# - PySide 1.2.1 (4.8.6) on Linux +# - CEF Python v55.4+ +from cefpython3 import cefpython as cef +import ctypes import os -import sys import platform -from cefpython3 import cefpython as cef +import sys # PyQt imports if "pyqt" in sys.argv: + # noinspection PyUnresolvedReferences from PyQt4.QtGui import * + # noinspection PyUnresolvedReferences from PyQt4.QtCore import * # PySide imports elif "pyside" in sys.argv: + # noinspection PyUnresolvedReferences import PySide + # noinspection PyUnresolvedReferences from PySide import QtCore # noinspection PyUnresolvedReferences from PySide.QtGui import * @@ -27,9 +36,15 @@ print(" qt.py pyside") sys.exit(1) -# Constants -LINUX = (platform.system() == "Linux") +# Fix for PyCharm hints warnings +WindowUtils = cef.WindowUtils() + +# Platforms WINDOWS = (platform.system() == "Windows") +LINUX = (platform.system() == "Linux") +MAC = (platform.system() == "Darwin") + +# Configuration WIDTH = 800 HEIGHT = 600 @@ -59,6 +74,7 @@ def check_versions(): print("[qt.py] Python {ver}".format(ver=sys.version[:6])) # PyQt version if "pyqt" in sys.argv: + # noinspection PyUnresolvedReferences print("[qt.py] PyQt {v1} ({v2})".format( v1=PYQT_VERSION_STR, v2=qVersion())) # PySide version @@ -91,6 +107,8 @@ def setupLayout(self): layout.addWidget(self.cef_widget, 1, 0) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) + layout.setRowStretch(0, 0) + layout.setRowStretch(1, 1) frame = QFrame() frame.setLayout(layout) self.setCentralWidget(frame) @@ -98,20 +116,20 @@ def setupLayout(self): self.cef_widget.embedBrowser() def focusInEvent(self, event): - # This event seems to never get called, as CEF is stealing all - # focus due to Issue #284. - if WINDOWS: - # noinspection PyUnresolvedReferences - cef.WindowUtils.OnSetFocus(int(self.centralWidget().winId()), - 0, 0, 0) - print("[qt.py] focusInEvent") + # This event seems to never get called on Linux, as CEF is + # stealing all focus due to Issue #284. + # print("[qt.py] focusInEvent") if self.cef_widget.browser: + if WINDOWS: + WindowUtils.OnSetFocus(self.cef_widget.getHandle(), + 0, 0, 0) self.cef_widget.browser.SetFocus(True) def focusOutEvent(self, event): - # This event seems to never get called, as CEF is stealing all - # focus due to Issue #284. - print("[qt.py] focusOutEvent") + # This event seems to never get called on Linux, as CEF is + # stealing all focus due to Issue #284. + # print("[qt.py] focusOutEvent") + pass def closeEvent(self, event): # Close browser (force=True) and free CEF reference @@ -212,12 +230,34 @@ def embedBrowser(self): self.width = 0 self.height = 0 window_info = cef.WindowInfo() - window_info.SetAsChild(int(self.winId())) + window_info.SetAsChild(self.getHandle()) self.browser = cef.CreateBrowserSync(window_info, url="https://www.google.com/") self.browser.SetClientHandler(LoadHandler(self.parent.navigation_bar)) self.browser.SetClientHandler(FocusHandler()) + def getHandle(self): + # PySide bug: QWidget.winId() returns + # There is no easy way to convert it to int. + try: + return int(self.winId()) + except: + if sys.version_info[0] == 2: + # Python 2 + ctypes.pythonapi.PyCObject_AsVoidPtr.restype = ( + ctypes.c_void_p) + ctypes.pythonapi.PyCObject_AsVoidPtr.argtypes = ( + [ctypes.py_object]) + return ctypes.pythonapi.PyCObject_AsVoidPtr(self.winId()) + else: + # Python 3 + ctypes.pythonapi.PyCapsule_GetPointer.restype = ( + ctypes.c_void_p) + ctypes.pythonapi.PyCapsule_GetPointer.argtypes = ( + [ctypes.py_object]) + return ctypes.pythonapi.PyCapsule_GetPointer( + self.winId(), None) + def moveEvent(self, _): # pos = event.pos() # self.x = pos.x() @@ -226,11 +266,11 @@ def moveEvent(self, _): self.y = 0 if self.browser: if WINDOWS: - # noinspection PyUnresolvedReferences - cef.WindowUtils.OnSize(int(self.winId()), 0, 0, 0) + WindowUtils.OnSize(self.getHandle(), 0, 0, 0) elif LINUX: - # noinspection PyUnresolvedReferences - self.browser.SetBounds(self.x, self.y, self.width, self.height) + self.browser.SetBounds(self.x, self.y, + self.width, self.height) + self.browser.NotifyMoveOrResizeStarted() def resizeEvent(self, event): size = event.size() @@ -238,11 +278,11 @@ def resizeEvent(self, event): self.height = size.height() if self.browser: if WINDOWS: - # noinspection PyUnresolvedReferences - cef.WindowUtils.OnSize(int(self.winId()), 0, 0, 0) + WindowUtils.OnSize(self.getHandle(), 0, 0, 0) elif LINUX: - # noinspection PyUnresolvedReferences - self.browser.SetBounds(self.x, self.y, self.width, self.height) + self.browser.SetBounds(self.x, self.y, + self.width, self.height) + self.browser.NotifyMoveOrResizeStarted() class CefApplication(QApplication): @@ -298,9 +338,10 @@ def OnLoadStart(self, browser, **_): # sometimes during initial loading, keyboard focus may # break and it is not possible to type anything, even # though a type cursor blinks in web view. - print("[qt.py] LoadHandler.OnLoadStart:" - " keyboard focus fix no. 2 (#284)") - browser.SetFocus(True) + if LINUX: + print("[qt.py] LoadHandler.OnLoadStart:" + " keyboard focus fix no. 2 (#284)") + browser.SetFocus(True) self.initial_app_loading = False @@ -328,9 +369,10 @@ def OnGotFocus(self, browser, **_): # window (alt+tab) and then back to this example, keyboard # focus becomes broken, you can't type anything, even # though a type cursor blinks in web view. - print("[qt.py] FocusHandler.OnGotFocus:" - " keyboard focus fix no. 1 (#284)") - browser.SetFocus(True) + if LINUX: + print("[qt.py] FocusHandler.OnGotFocus:" + " keyboard focus fix no. 1 (#284)") + browser.SetFocus(True) if __name__ == '__main__': diff --git a/examples/tkinter_.py b/examples/tkinter_.py index c83859920..dc5abf246 100644 --- a/examples/tkinter_.py +++ b/examples/tkinter_.py @@ -1,7 +1,9 @@ # Example of embedding CEF Python browser using Tkinter toolkit. # This example has two widgets: a navigation bar and a browser. # -# Tested with Tk 8.6 and CEF Python v55.3+, only on Linux. +# Tested configurations: +# - Tk 8.6 and CEF Python v55.3+ on Linux +# - Tk 8.5 and CEF Python v55.4+ on Windows # # Known issue on Linux: When typing url, mouse must be over url # entry widget otherwise keyboard focus is lost (Issue #255 @@ -17,10 +19,18 @@ import platform import logging as _logging +# Fix for PyCharm hints warnings +WindowUtils = cef.WindowUtils() + +# Platforms +WINDOWS = (platform.system() == "Windows") +LINUX = (platform.system() == "Linux") +MAC = (platform.system() == "Darwin") + # Globals logger = _logging.getLogger("tkinter_.py") # Python 2.7 on Windows comes with Tk 8.5 which doesn't support PNG images -IMAGE_EXT = ".gif" if platform.system() == "Windows" else ".png" +IMAGE_EXT = ".gif" if WINDOWS else ".png" def main(): @@ -278,10 +288,9 @@ def on_root_configure(self): def on_mainframe_configure(self, width, height): if self.browser: - if platform.system() == "Windows": - # noinspection PyUnresolvedReferences - cef.WindowUtils.OnSize(self.winfo_id(), 0, 0, 0) - elif platform.system() == "Linux": + if WINDOWS: + WindowUtils.OnSize(self.winfo_id(), 0, 0, 0) + elif LINUX: self.browser.SetBounds(0, 0, width, height) self.browser.NotifyMoveOrResizeStarted() diff --git a/examples/wxpython.py b/examples/wxpython.py index 8e7026fc7..226642c2d 100644 --- a/examples/wxpython.py +++ b/examples/wxpython.py @@ -5,9 +5,8 @@ # Tested configurations: # - wxPython 2.8 on Linux -# - wxPython 3.0.2.0 msw (classic) on Windows -# - wxPython 3.0 on Mac -# - CEF Python v55.3+ +# - wxPython 3.0 on Windows +# - CEF Python v55.4+ import wx from cefpython3 import cefpython as cef @@ -15,9 +14,15 @@ import sys import os -# Constants -LINUX = (platform.system() == "Linux") +# Fix for PyCharm hints warnings +WindowUtils = cef.WindowUtils() + +# Platforms WINDOWS = (platform.system() == "Windows") +LINUX = (platform.system() == "Linux") +MAC = (platform.system() == "Darwin") + +# Configuration WIDTH = 800 HEIGHT = 600 @@ -79,7 +84,7 @@ def setup_icon(self): def create_menu(self): filemenu = wx.Menu() filemenu.Append(1, "Some option") - exit_ = filemenu.Append(2, "Another option") + filemenu.Append(2, "Another option") aboutmenu = wx.Menu() aboutmenu.Append(1, "Yet another option") menubar = wx.MenuBar() @@ -98,18 +103,16 @@ def OnSetFocus(self, _): if not self.browser: return if WINDOWS: - # noinspection PyUnresolvedReferences - cef.WindowUtils.OnSetFocus(self.browser_panel.GetHandle(), - 0, 0, 0) + WindowUtils.OnSetFocus(self.browser_panel.GetHandle(), + 0, 0, 0) self.browser.SetFocus(True) def OnSize(self, _): if not self.browser: return if WINDOWS: - # noinspection PyUnresolvedReferences - cef.WindowUtils.OnSize(self.browser_panel.GetHandle(), - 0, 0, 0) + WindowUtils.OnSize(self.browser_panel.GetHandle(), + 0, 0, 0) elif LINUX: (x, y) = (0, 0) (width, height) = self.browser_panel.GetSizeTuple() diff --git a/src/window_utils_linux.pyx b/src/window_utils_linux.pyx index 885f82f85..da4030cc2 100644 --- a/src/window_utils_linux.pyx +++ b/src/window_utils_linux.pyx @@ -11,6 +11,25 @@ class WindowUtils: # You have to overwrite this class and provide implementations # for these methods. + @staticmethod + def OnSetFocus(long windowHandle, long msg, long wparam, long lparam): + # Available only on Windows, but have it available on other + # platforms so that PyCharm doesn't warn about unresolved reference. + pass + + @staticmethod + def OnSize(long windowHandle, long msg, long wparam, long lparam): + # Available only on Windows, but have it available on other + # platforms so that PyCharm doesn't warn about unresolved reference. + pass + + @staticmethod + def OnEraseBackground(long windowHandle, long msg, long wparam, + long lparam): + # Available only on Windows, but have it available on other + # platforms so that PyCharm doesn't warn about unresolved reference. + pass + @staticmethod def GetParentHandle(WindowHandle windowHandle): Debug("WindowUtils::GetParentHandle() not implemented (returns 0)") diff --git a/src/window_utils_mac.pyx b/src/window_utils_mac.pyx index 742a9b8f2..08eb7b85c 100644 --- a/src/window_utils_mac.pyx +++ b/src/window_utils_mac.pyx @@ -8,6 +8,25 @@ class WindowUtils: # You have to overwrite this class and provide implementations # for these methods. + @staticmethod + def OnSetFocus(long windowHandle, long msg, long wparam, long lparam): + # Available only on Windows, but have it available on other + # platforms so that PyCharm doesn't warn about unresolved reference. + pass + + @staticmethod + def OnSize(long windowHandle, long msg, long wparam, long lparam): + # Available only on Windows, but have it available on other + # platforms so that PyCharm doesn't warn about unresolved reference. + pass + + @staticmethod + def OnEraseBackground(long windowHandle, long msg, long wparam, + long lparam): + # Available only on Windows, but have it available on other + # platforms so that PyCharm doesn't warn about unresolved reference. + pass + @staticmethod def GetParentHandle(WindowHandle windowHandle): Debug("WindowUtils::GetParentHandle() not implemented (returns 0)") diff --git a/src/window_utils_win.pyx b/src/window_utils_win.pyx index 81d80143b..c40bd3831 100644 --- a/src/window_utils_win.pyx +++ b/src/window_utils_win.pyx @@ -4,10 +4,10 @@ include "cefpython.pyx" -class WindowUtils: +class WindowUtils(object): @staticmethod - def OnSetFocus(int windowHandle, long msg, long wparam, long lparam): + def OnSetFocus(long windowHandle, long msg, long wparam, long lparam): cdef PyBrowser pyBrowser = GetBrowserByWindowHandle(windowHandle) if not pyBrowser: return 0 @@ -15,7 +15,7 @@ class WindowUtils: return 0 @staticmethod - def OnSize(int windowHandle, long msg, long wparam, long lparam): + def OnSize(long windowHandle, long msg, long wparam, long lparam): cdef PyBrowser pyBrowser = GetBrowserByWindowHandle(windowHandle) if not pyBrowser: return DefWindowProc(windowHandle, msg, wparam, lparam) @@ -35,7 +35,7 @@ class WindowUtils: return DefWindowProc(windowHandle, msg, wparam, lparam) @staticmethod - def OnEraseBackground(int windowHandle, long msg, long wparam, + def OnEraseBackground(long windowHandle, long msg, long wparam, long lparam): cdef PyBrowser pyBrowser = GetBrowserByWindowHandle(windowHandle) if not pyBrowser: @@ -134,11 +134,11 @@ class WindowUtils: ICON_SMALL, parentIconSmall) @staticmethod - def GetParentHandle(int windowHandle): - return GetParent(windowHandle) + def GetParentHandle(long windowHandle): + return GetParent(windowHandle) @staticmethod - def IsWindowHandle(int windowHandle): + def IsWindowHandle(long windowHandle): IF UNAME_SYSNAME == "Windows": return bool(IsWindow(windowHandle)) ELSE: diff --git a/tools/build.py b/tools/build.py index 525518379..c7d742eca 100644 --- a/tools/build.py +++ b/tools/build.py @@ -678,28 +678,12 @@ def install_and_run(): # Run examples print("[build.py] Run examples") os.chdir(EXAMPLES_DIR) - examples = list() - if not KIVY_FLAG: - examples.extend([ - "hello_world.py", - "wxpython.py", - "gtk2.py", - "gtk2.py --message-loop-timer", - "gtk3.py", - "tkinter_.py", - "qt.py pyqt", - "qt.py pyside", - ]) - if LINUX: - examples.append("{linux_dir}/deprecated_64bit/kivy_.py" - .format(linux_dir=LINUX_DIR)) - for example in examples: - ret = os.system("{python} {example}" - .format(python=sys.executable, example=example)) - if ret != 0: - print("[build.py] ERROR while running example: {example}" - .format(example=example)) - sys.exit(1) + run_examples = os.path.join(TOOLS_DIR, "run_examples.py") + ret = os.system("{python} {run_examples}" + .format(python=sys.executable, run_examples=run_examples)) + if ret != 0: + print("[build.py] ERROR while running examples") + sys.exit(1) print("[build.py] Everything OK") diff --git a/tools/common.py b/tools/common.py index fb0a733bb..9a5c5b617 100644 --- a/tools/common.py +++ b/tools/common.py @@ -22,8 +22,8 @@ OS_POSTFIX2 = "linux32" if ARCH32 else "linux64" # Platforms -LINUX = (platform.system() == "Linux") WINDOWS = (platform.system() == "Windows") +LINUX = (platform.system() == "Linux") MAC = (platform.system() == "Darwin") # Python version eg. 27 diff --git a/tools/run_examples.py b/tools/run_examples.py new file mode 100644 index 000000000..a89084e71 --- /dev/null +++ b/tools/run_examples.py @@ -0,0 +1,147 @@ +""" +Run all examples that can be run on current configuration. + +Note on GTK 2 / GTK 3 on Windows: + Installing both PyGTK and PyGI on Windows will cause errors. + You can install only one of these packages. +""" + +from common import * + +import importlib +import os +import sys + + +def main(): + os.chdir(EXAMPLES_DIR) + + packages = check_installed_packages() + examples = list() + examples.append("hello_world.py") + succeeded = list() + failed = list() + passed = list() + + # wxpython + if packages["wx"]: + examples.append("wxpython.py") + else: + print("[run_examples.py] PASS: wxpython.py (wxPython not installed)") + passed.append("wxpython.py") + + # gtk2 + if packages["gtk"]: + examples.append("gtk2.py") + if LINUX: + examples.append("gtk2.py --message-loop-cef") + else: + print("[run_examples.py] PASS: gtk2.py (Gtk 2 not installed") + passed.append("gtk2.py") + + # gtk3 + if packages["gi"]: + if not LINUX: + examples.append("gtk3.py") + else: + # Gtk 3 example is currently broken on Linux (Issue #261) + print("[run_examples.py] PASS: gtk3.py (Issue #261)") + passed.append("gtk3.py") + else: + print("[run_examples.py] PASS: gtk3.py (Gtk 3 not installed)") + passed.append("gtk3.py") + + # pyqt + if packages["PyQt4"]: + examples.append("qt.py pyqt") + else: + print("[run_examples.py] PASS: qt.py pyqt (PyQt4 not installed)") + passed.append("qt.py pyqt") + + # pyside + if packages["PySide"]: + examples.append("qt.py pyside") + else: + print("[run_examples.py] PASS: qt.py pyside (PySide not installed)") + passed.append("qt.py pyside") + + # tkinter + if packages["tkinter"] or packages["Tkinter"]: + examples.append("tkinter_.py") + else: + print(["run_examples.py] PASS: tkinter_.py (tkinter not installed)"]) + passed.append("tkinter_.py") + + # kivy + if LINUX and packages["kivy"] and packages["gtk"]: + if "--kivy" in sys.argv: + # When --kivy flag passed run only Kivy example + examples = list() + passed = list() + examples.append("{linux_dir}/binaries_64bit/kivy_.py" + .format(linux_dir=LINUX_DIR)) + + # Run all + for example in examples: + print("[run_examples.py] Running '{example}'..." + .format(example=example)) + ret = os.system("{python} {example}" + .format(python=sys.executable, example=example)) + if ret == 0: + succeeded.append(example) + else: + print("[run_examples.py] ERROR while running example: {example}" + .format(example=example)) + failed.append(example) + + # Summary + summary = "" + for example in succeeded: + summary += " OK {example}{nl}"\ + .format(example=example, nl=os.linesep) + for example in failed: + summary += " ERROR {example}{nl}"\ + .format(example=example, nl=os.linesep) + for example in passed: + summary += " PASS {example}{nl}"\ + .format(example=example, nl=os.linesep) + summary = summary[:-(len(os.linesep))] + print("[run_examples.py] SUMMARY:") + print(summary.format()) + + # OK or error message + passed_msg = "" + if passed: + passed_msg = ". Passed: {passed}.".format(passed=len(passed)) + if len(failed): + print("[run_examples.py] ERRORS({failed}) while running examples" + "{passed_msg}" + .format(failed=len(failed), passed_msg=passed_msg)) + sys.exit(1) + else: + print("[run_examples.py] OK({succeeded}){passed_msg}" + .format(succeeded=len(succeeded), passed_msg=passed_msg)) + + +def check_installed_packages(): + packages = { + "gtk": False, + "gi": False, + "kivy": False, + "PyQt4": False, + "PySide": False, + "tkinter": False, + "Tkinter": False, + "wx": False, + } + for package in packages: + try: + importlib.import_module(package) + packages[package] = True + except ImportError: + packages[package] = False + return packages + + +if __name__ == "__main__": + main() From 6f7c52da12704313009b834e086f0cd102b3d450 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Tue, 21 Feb 2017 16:59:14 +0100 Subject: [PATCH 134/557] Update installer to include platform tag when generating .whl file. --- tools/build.py | 7 +++++-- tools/installer/cefpython3.setup.py | 21 ++++++++++++++++++++- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/tools/build.py b/tools/build.py index c7d742eca..0c2a84a48 100644 --- a/tools/build.py +++ b/tools/build.py @@ -678,9 +678,12 @@ def install_and_run(): # Run examples print("[build.py] Run examples") os.chdir(EXAMPLES_DIR) + kivy_flag = "--kivy" if KIVY_FLAG else "" run_examples = os.path.join(TOOLS_DIR, "run_examples.py") - ret = os.system("{python} {run_examples}" - .format(python=sys.executable, run_examples=run_examples)) + ret = os.system("{python} {run_examples} {kivy_flag}" + .format(python=sys.executable, + run_examples=run_examples, + kivy_flag=kivy_flag)) if ret != 0: print("[build.py] ERROR while running examples") sys.exit(1) diff --git a/tools/installer/cefpython3.setup.py b/tools/installer/cefpython3.setup.py index 292b2ee36..bfdc570d7 100644 --- a/tools/installer/cefpython3.setup.py +++ b/tools/installer/cefpython3.setup.py @@ -24,6 +24,7 @@ import platform import subprocess import sys +import sysconfig # The setuptools package is not installed by default on a clean # Ubuntu. Might be also a case on Windows. Also Python Eggs @@ -92,6 +93,19 @@ def get_tag(self): return tag cmdclass["bdist_wheel"] = custom_bdist_wheel +elif platform.system() in ["Windows", "Linux"] and "bdist_wheel" in sys.argv: + # On Windows and Linux platform tag is always "any". + print("[setup.py] Overload bdist_wheel command to fix platform tag") + from wheel.bdist_wheel import bdist_wheel + + class custom_bdist_wheel(bdist_wheel): + def get_tag(self): + tag = bdist_wheel.get_tag(self) + platform_tag = sysconfig.get_platform() + tag = (tag[0], tag[1], platform_tag) + return tag + + cmdclass["bdist_wheel"] = custom_bdist_wheel def main(): @@ -132,7 +146,12 @@ def main(): "Topic :: Software Development :: User Interfaces", ], ) - print("[setup.py] OK installed") + if "install" in sys.argv: + print("[setup.py] OK installed") + elif "bdist_wheel" in sys.argv: + print("[setup.py] OK created wheel package in dist/ directory") + else: + print("[setup.py] Unknown command line arguments") def get_package_data(): From 5ce5c368abaf973d0c65fad4d7f136c18cb06279 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 22 Feb 2017 12:36:24 +0100 Subject: [PATCH 135/557] Fix DevTools window not showing on Windows (#303)... Add "Quick build instructions for Windows" section indocs/Build-instructions. Fix invalid types for window handles on Windows 64-bit (#302). Also fix long long for other pointers such as in PaintBuffer. Also fix long long for uint types. Get rid of invalid/unnecessary long conversions eg. from int64 type. --- docs/Build-instructions.md | 82 +++++++++++++++++++++------ docs/Tutorial.md | 8 +++ src/browser.pyx | 31 ++++++---- src/cefpython.pyx | 15 +++-- src/client_handler/render_handler.cpp | 4 +- src/extern/cef/cef_types.pxd | 11 ++-- src/frame.pyx | 3 +- src/handlers/render_handler.pyx | 4 +- src/handlers/request_handler.pyx | 2 +- src/handlers/resource_handler.pyx | 2 +- src/paint_buffer.pyx | 4 +- src/process_message_utils.pyx | 8 +-- src/utils.pyx | 4 +- src/web_request.pyx | 8 +-- src/window_utils_linux.pyx | 13 +++-- src/window_utils_mac.pyx | 7 ++- src/window_utils_win.pyx | 17 +++--- tools/build.py | 4 +- unittests/_test_runner.py | 2 +- 19 files changed, 152 insertions(+), 77 deletions(-) diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index b0c4a0495..179a970d0 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -1,27 +1,33 @@ # Build instructions -__IMPORTANT NOTE__: These instructions are for the new releases of CEF Python -(Chrome v51 and later). Currently only Linux platform is being tested. -For the old v31 release that is supported on all platforms, see build -instructions on the wiki pages. +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. + +If you would like to quickly build cefpython then see the +[Quick build instructions for Windows](#quick-build-instructions-for-windows) +and [Quick build instructions for Linux](#quick-build-instructions-for-linux) +sections for complete instructions. There are several types of builds you can perform: -1. You can build CEF Python using prebuilt CEF binaries that were - uploaded to GH releases (tagged eg. v51-upstream) -2. You can build both CEF Python and CEF from sources, but note +1. You can build CEF Python using prebuilt CEF binaries and libraries + that were uploaded to GH releases (tagged eg. v55-upstream) +2. You can build CEF Python using prebuilt CEF binaries from + Spotify Automated Builds. +3. You can build both CEF and CEF Python from sources, but note that Building CEF is a long process that can take hours. - In the tools/ directory there is the automate.py script that - automates building CEF. -3. You may also use prebuilt binaries from Spotify automated builds, - see the CEF automated builds section. -Before you can build CEF Python or CEF you must satisfy requirements -listed on this page. +Detailed instructions for building can be found in module doc comments +in the `automate.py` and `build.py` tools (the tools/ directory). + +Before you can build CEF Python or CEF you must satisfy some +[requirements](#requirements) listed on this page. Table of contents: -* [Build CEF Python on Linux](#build-cef-python-on-linux) +* [Quick build instructions for Windows](#quick-build-instructions-for-windows) +* [Quick build instructions for Linux](#quick-build-instructions-for-linux) * [Requirements](#requirements) * [Build CEF Python using prebuilt CEF binaries](#build-cef-python-using-prebuilt-cef-binaries) * [Build both CEF Python and CEF from sources](#build-both-cef-python-and-cef-from-sources) @@ -30,7 +36,44 @@ Table of contents: * [How to patch](#how-to-patch) -## Build CEF Python on Linux +## Quick build instructions for Windows + +Complete steps for building CEF Python v50+ using prebuilt binaries +and libraries from GitHub releases: + +1) Tested and works fine on Windows 7 64-bit + +2) Download [ninja](https://github.com/ninja-build/ninja) 1.7.2 or later + and add it to PATH. + +3) Download [cmake](https://cmake.org/download/) 3.7.2 or later and add + it to PATH. + +4) For Python 2.7 Install "Visual C++ Compiler for Python 2.7" + from [here](https://www.microsoft.com/en-us/download/details.aspx?id=44266) + +5) For Python 2.7 and when using using "Visual C++ compiler for Python 2.7" + you have to install "Visual C++ 2008 Redistributable Package (x64)" + from [here](https://www.microsoft.com/en-us/download/details.aspx?id=15336) + +6) Install python dependencies by running: + `cd cefpython/tools/ && pip install -r requirements.txt` + (Cython version from requirements.txt must match exactly) + +7) Download 32-bit Windows binaries and libraries from + [GH releases](https://github.com/cztomczak/cefpython/tags) + tagged e.g. 'v55-upstream' when building v55. + +8) Extract the archive it in the "cefpython/build/" directory. + +9) Build cefpython and run examples (xx.x is version number eg. 55.4): +``` +cd cefpython/build/ +python ../tools/build.py xx.x +``` + + +## Quick build instructions for Linux Complete steps for building CEF Python v50+ using prebuilt binaries from GitHub releases: @@ -47,18 +90,19 @@ binaries from GitHub releases: (Cython version from requirements.txt must match exactly) 5) Download 64-bit Linux binaries and libraries from - [GH releases](https://github.com/cztomczak/cefpython/releases) - tagged e.g. 'v50-upstream' when building v50. + [GH releases](https://github.com/cztomczak/cefpython/tags) + tagged e.g. 'v55-upstream' when building v55. 6) Extract it in the cefpython/build/ directory and rename the extracted directory to "cef_linux64". -8) Build cefpython and run examples (xx.x is version e.g. 50.0): +7) Build cefpython and run examples (xx.x is version e.g. 50.0): ``` cd cefpython/src/linux/ python compile.py xx.x ``` + ## Requirements Below are platform specific requirements. Do these first before @@ -69,6 +113,8 @@ __Windows__ * Install an appropriate MS compiler for a specific Python version: https://wiki.python.org/moin/WindowsCompilers +* For Python 2.7 install "Microsoft Visual C++ Compiler for Python 2.7" + from [here](https://www.microsoft.com/en-us/download/details.aspx?id=44266) * When using "Visual C++ compiler for Python 2.7" you have to install "Microsoft Visual C++ 2008 Redistributable Package (x64)" from [here](https://www.microsoft.com/en-us/download/details.aspx?id=15336) diff --git a/docs/Tutorial.md b/docs/Tutorial.md index 04ecf74e7..e659b2632 100644 --- a/docs/Tutorial.md +++ b/docs/Tutorial.md @@ -9,6 +9,14 @@ Table of contents: * [Hello world](#hello-world) * [CEF's multiprocess architecture](#cefs-multiprocess-architecture) * [Handling Python exceptions](#handling-python-exceptions) +* [Message loop](#message-loop) +* [Settings](#settings) +* [Handlers](#handlers) +* [Javascript integration](#javascript-integration) +* [Plugins](#plugins) +* [Helper functions](#helper-functions) +* [Build executable](#build-executable) +* [What's next?](#whats-next) ## Install and download examples diff --git a/src/browser.pyx b/src/browser.pyx index 5907dd721..4a38f0d8e 100644 --- a/src/browser.pyx +++ b/src/browser.pyx @@ -107,7 +107,7 @@ cpdef PyBrowser GetBrowserByWindowHandle(WindowHandle windowHandle): for browserId in g_pyBrowsers: pyBrowser = g_pyBrowsers[browserId] if (pyBrowser.GetWindowHandle() == windowHandle or - pyBrowser.GetUserData("__outerWindowHandle") == long(windowHandle)): + pyBrowser.GetUserData("__outerWindowHandle") == windowHandle): return pyBrowser return None @@ -312,7 +312,7 @@ cdef class PyBrowser: cpdef object GetFrameByIdentifier(self, object identifier): return GetPyFrame(self.GetCefBrowser().get().GetFrame( - long(identifier))) + identifier)) cpdef list GetFrameNames(self): assert IsThread(TID_UI), ( @@ -418,7 +418,7 @@ cdef class PyBrowser: IF UNAME_SYSNAME == "Linux": x11.SetX11WindowBounds(self.GetCefBrowser(), x, y, width, height) ELSE: - raise Exception("SetBounds() not implemented on this platform") + NonCriticalError("SetBounds() not implemented on this platform") cpdef py_void SetFocus(self, enable): self.GetCefBrowserHost().get().SetFocus(bool(enable)) @@ -430,13 +430,19 @@ cdef class PyBrowser: self.GetCefBrowserHost().get().SetZoomLevel(zoomLevel) cpdef py_void ShowDevTools(self): - cdef CefWindowInfo windowInfo - cdef CefRefPtr[ClientHandler] clientHandler =\ + cdef CefWindowInfo window_info + IF UNAME_SYSNAME == "Windows": + # On Windows with empty window_info structure the devtools + # window doesn't appear. + window_info.SetAsPopup( + self.GetOpenerWindowHandle(), + PyToCefStringValue("DevTools")) + cdef CefRefPtr[ClientHandler] client_handler =\ new ClientHandler() cdef CefBrowserSettings settings cdef CefPoint inspect_element_at self.GetCefBrowserHost().get().ShowDevTools( - windowInfo, clientHandler, settings, + window_info, client_handler, settings, inspect_element_at) cpdef py_void StopLoad(self): @@ -454,7 +460,8 @@ cdef class PyBrowser: cpdef py_void ToggleFullscreen_Windows(self): cdef WindowHandle windowHandle if self.GetUserData("__outerWindowHandle"): - windowHandle = self.GetUserData("__outerWindowHandle") + windowHandle = \ + self.GetUserData("__outerWindowHandle") else: windowHandle = self.GetWindowHandle() @@ -463,7 +470,7 @@ cdef class PyBrowser: "Browser.ToggleFullscreen() failed: no window handle " "found") - cdef HWND hwnd = int(windowHandle) + cdef HWND hwnd = windowHandle cdef RECT rect cdef HMONITOR monitor cdef MONITORINFO monitorInfo @@ -533,7 +540,7 @@ cdef class PyBrowser: if "type" in pyEvent: cefEvent.type = int(pyEvent["type"]) if "modifiers" in pyEvent: - cefEvent.modifiers = long(pyEvent["modifiers"]) + cefEvent.modifiers = pyEvent["modifiers"] # Always set CefKeyEvent.windows_key_code in SendKeyEvent, even on # Linux. When sending key event for 'backspace' on Linux and setting # "native_key_code", "character", "unmodified_character" it doesn't @@ -639,7 +646,7 @@ cdef class PyBrowser: # ------------------------------------------------------------------------- cpdef py_void DragTargetDragEnter(self, DragData drag_data, int x, int y, - long long allowed_ops): + uint32 allowed_ops): cdef CefMouseEvent mouse_event mouse_event.x = x mouse_event.y = y @@ -647,7 +654,7 @@ cdef class PyBrowser: drag_data.cef_drag_data, mouse_event, allowed_ops) - cpdef py_void DragTargetDragOver(self, int x, int y, long long allowed_ops): + cpdef py_void DragTargetDragOver(self, int x, int y, uint32 allowed_ops): cdef CefMouseEvent mouse_event mouse_event.x = x mouse_event.y = y @@ -663,7 +670,7 @@ cdef class PyBrowser: mouse_event.y = y self.GetCefBrowserHost().get().DragTargetDrop(mouse_event) - cpdef py_void DragSourceEndedAt(self, int x, int y, long long operation): + cpdef py_void DragSourceEndedAt(self, int x, int y, uint32 operation): self.GetCefBrowserHost().get().DragSourceEndedAt( x, y, operation) diff --git a/src/cefpython.pyx b/src/cefpython.pyx index 634a99302..ffbcde969 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -312,11 +312,11 @@ import weakref # would be a bad idea. ctypedef object py_string -# You can't use "void" along with cpdef function returning None, it is planned to be -# added to Cython in the future, creating this virtual type temporarily. If you -# change it later to "void" then don't forget to add "except *". +# You can't use "void" along with cpdef function returning None, it is +# planned to be added to Cython in the future, creating this virtual +# type temporarily. If you change it later to "void" then don't forget +# to add "except *". ctypedef object py_void -ctypedef long long WindowHandle # noinspection PyUnresolvedReferences from cpython cimport PyLong_FromVoidPtr @@ -363,6 +363,9 @@ from libc.stdint cimport uint64_t # noinspection PyUnresolvedReferences from libc.stdint cimport uintptr_t +# noinspection PyUnresolvedReferences +ctypedef uintptr_t WindowHandle + # noinspection PyUnresolvedReferences cimport ctime @@ -388,6 +391,7 @@ from cef_types cimport ( CefSettings, CefBrowserSettings, CefRect, CefPoint, CefKeyEvent, CefMouseEvent, CefScreenInfo, PathKey, PK_DIR_EXE, PK_DIR_MODULE, + int32, uint32, int64, uint64, ) from cef_task cimport * @@ -938,7 +942,8 @@ def Shutdown(): # If the the two code blocks above, that tried to close browsers # and free CEF references, failed, then display an error about it! if len(g_pyBrowsers): - Error("Shutdown called, but there are still browser references alive!") + NonCriticalError("Shutdown called, but there are still browser" + " references alive") Debug("Shutdown()") with nogil: diff --git a/src/client_handler/render_handler.cpp b/src/client_handler/render_handler.cpp index 812f2ce9e..fcbbbfeb9 100644 --- a/src/client_handler/render_handler.cpp +++ b/src/client_handler/render_handler.cpp @@ -94,7 +94,7 @@ bool RenderHandler::StartDragging(CefRefPtr browser, { REQUIRE_UI_THREAD(); return RenderHandler_StartDragging(browser, drag_data, - static_cast(allowed_ops), x, y); + allowed_ops, x, y); } @@ -102,5 +102,5 @@ void RenderHandler::UpdateDragCursor(CefRefPtr browser, DragOperation operation) { REQUIRE_UI_THREAD(); - RenderHandler_UpdateDragCursor(browser, static_cast(operation)); + RenderHandler_UpdateDragCursor(browser, operation); } diff --git a/src/extern/cef/cef_types.pxd b/src/extern/cef/cef_types.pxd index 9769e0b6f..1b2445210 100644 --- a/src/extern/cef/cef_types.pxd +++ b/src/extern/cef/cef_types.pxd @@ -7,16 +7,19 @@ include "compile_time_constants.pxi" from libcpp cimport bool as cpp_bool # noinspection PyUnresolvedReferences from libc.stddef cimport wchar_t +# noinspection PyUnresolvedReferences +from libc.stdint cimport int32_t, uint32_t, int64_t, uint64_t from cef_string cimport cef_string_t # noinspection PyUnresolvedReferences from libc.limits cimport UINT_MAX cdef extern from "include/internal/cef_types.h": - ctypedef unsigned int uint32 - ctypedef int int32 - ctypedef long long int64 - ctypedef unsigned long long uint64 + ctypedef int32_t int32 + ctypedef uint32_t uint32 + ctypedef int64_t int64 + ctypedef uint64_t uint64 + IF UNAME_SYSNAME == "Windows": # noinspection PyUnresolvedReferences ctypedef wchar_t char16 diff --git a/src/frame.pyx b/src/frame.pyx index a85024271..ab22ba4fb 100644 --- a/src/frame.pyx +++ b/src/frame.pyx @@ -21,8 +21,7 @@ cdef PyFrame GetPyFrame(CefRefPtr[CefFrame] cefFrame): Debug("GetPyFrame(): returning None") return cdef PyFrame pyFrame - # long long - cdef object frameId = cefFrame.get().GetIdentifier() + cdef object frameId = cefFrame.get().GetIdentifier() # int64 cdef int browserId = cefFrame.get().GetBrowser().get().GetIdentifier() assert (frameId and browserId), "frameId or browserId empty" cdef object uniqueFrameId = GetUniqueFrameId(browserId, frameId) diff --git a/src/handlers/render_handler.pyx b/src/handlers/render_handler.pyx index a332ff181..3204ca3b7 100644 --- a/src/handlers/render_handler.pyx +++ b/src/handlers/render_handler.pyx @@ -247,7 +247,7 @@ cdef public void RenderHandler_OnScrollOffsetChanged( cdef public cpp_bool RenderHandler_StartDragging( CefRefPtr[CefBrowser] cef_browser, CefRefPtr[CefDragData] cef_drag_data, - long long allowed_ops, + uint32 allowed_ops, int x, int y ) except * with gil: cdef PyBrowser browser @@ -276,7 +276,7 @@ cdef public cpp_bool RenderHandler_StartDragging( cdef public void RenderHandler_UpdateDragCursor( CefRefPtr[CefBrowser] cef_browser, - long long operation, + uint32 operation, ) except * with gil: cdef PyBrowser browser try: diff --git a/src/handlers/request_handler.pyx b/src/handlers/request_handler.pyx index 74b3c23d8..a4709d98c 100644 --- a/src/handlers/request_handler.pyx +++ b/src/handlers/request_handler.pyx @@ -267,7 +267,7 @@ cdef public cpp_bool RequestHandler_OnQuotaRequest( returnValue = clientCallback( browser=pyBrowser, origin_url=pyOriginUrl, - new_size=long(newSize), + new_size=newSize, callback=CreatePyRequestCallback(cefRequestCallback)) return bool(returnValue) else: diff --git a/src/handlers/resource_handler.pyx b/src/handlers/resource_handler.pyx index c7e20929a..c4f1d6cd4 100644 --- a/src/handlers/resource_handler.pyx +++ b/src/handlers/resource_handler.pyx @@ -122,7 +122,7 @@ cdef public void ResourceHandler_GetResponseHeaders( if userCallback: returnValue = userCallback(pyResponse, responseLengthOut, redirectUrlOut) - (&cefResponseLength)[0] = long(responseLengthOut[0]) + (&cefResponseLength)[0] = responseLengthOut[0] if redirectUrlOut[0]: PyToCefString(redirectUrlOut[0], cefRedirectUrl) return diff --git a/src/paint_buffer.pyx b/src/paint_buffer.pyx index 3ce59d9e7..0ea480d15 100644 --- a/src/paint_buffer.pyx +++ b/src/paint_buffer.pyx @@ -18,8 +18,8 @@ cdef class PaintBuffer: cdef int height cdef Py_ssize_t length - cpdef long long GetIntPointer(self) except *: - return self.buffer + cpdef uintptr_t GetIntPointer(self) except *: + return self.buffer cpdef object GetString(self, str mode="bgra", str origin="top-left"): cdef void* dest diff --git a/src/process_message_utils.pyx b/src/process_message_utils.pyx index 80e917810..314871d56 100644 --- a/src/process_message_utils.pyx +++ b/src/process_message_utils.pyx @@ -49,8 +49,8 @@ cdef list CefListValueToPyList( cdef cef_types.cef_value_type_t valueType cdef list ret = [] cdef CefRefPtr[CefBinaryValue] binaryValue - cdef cef_types.uint32 uint32_value - cdef cef_types.int64 int64_value + cdef uint32 uint32_value + cdef int64 int64_value cdef object originallyString for index in range(0, size): valueType = cefListValue.get().GetType(index) @@ -111,8 +111,8 @@ cdef dict CefDictionaryValueToPyDict( cdef CefString cefKey cdef py_string pyKey cdef CefRefPtr[CefBinaryValue] binaryValue - cdef cef_types.uint32 uint32_value - cdef cef_types.int64 int64_value + cdef uint32 uint32_value + cdef int64 int64_value cdef object originallyString while iterator != keyList.end(): cefKey = deref(iterator) diff --git a/src/utils.pyx b/src/utils.pyx index 86ced2118..a3ef03aac 100644 --- a/src/utils.pyx +++ b/src/utils.pyx @@ -42,6 +42,7 @@ cpdef py_bool IsThread(int threadID): # This change is required to work with Cython 0.20. cpdef object Debug(py_string msg): + """Print debug message. Will be shown only when settings.debug=True.""" if not g_debug: return # In Python 3 str or bytes may be passed @@ -59,7 +60,8 @@ cpdef object Debug(py_string msg): print("[CEF Python] WARNING: failed writing to debug file: %s" % ( g_debugFile)) -cdef void Error(py_string msg) except *: +cdef void NonCriticalError(py_string msg) except *: + """Notify about error gently. Does not terminate application.""" # In Python 3 str or bytes may be passed if type(msg) != str and type(msg) == bytes: msg = msg.decode("utf-8", "replace") diff --git a/src/web_request.pyx b/src/web_request.pyx index d55588823..cd591ebc7 100644 --- a/src/web_request.pyx +++ b/src/web_request.pyx @@ -122,8 +122,8 @@ cdef class PyWebRequest: cdef public void WebRequestClient_OnUploadProgress( int webRequestId, CefRefPtr[CefURLRequest] cefWebRequest, - cef_types.int64 current, - cef_types.int64 total + int64 current, + int64 total ) except * with gil: cdef PyWebRequest webRequest cdef object userCallback @@ -143,8 +143,8 @@ cdef public void WebRequestClient_OnUploadProgress( cdef public void WebRequestClient_OnDownloadProgress( int webRequestId, CefRefPtr[CefURLRequest] cefWebRequest, - cef_types.int64 current, - cef_types.int64 total + int64 current, + int64 total ) except * with gil: cdef PyWebRequest webRequest cdef object userCallback diff --git a/src/window_utils_linux.pyx b/src/window_utils_linux.pyx index da4030cc2..9427ebb0d 100644 --- a/src/window_utils_linux.pyx +++ b/src/window_utils_linux.pyx @@ -12,19 +12,20 @@ class WindowUtils: # for these methods. @staticmethod - def OnSetFocus(long windowHandle, long msg, long wparam, long lparam): + def OnSetFocus(WindowHandle windowHandle, long msg, long wparam, + long lparam): # Available only on Windows, but have it available on other # platforms so that PyCharm doesn't warn about unresolved reference. pass @staticmethod - def OnSize(long windowHandle, long msg, long wparam, long lparam): + def OnSize(WindowHandle windowHandle, long msg, long wparam, long lparam): # Available only on Windows, but have it available on other # platforms so that PyCharm doesn't warn about unresolved reference. pass @staticmethod - def OnEraseBackground(long windowHandle, long msg, long wparam, + def OnEraseBackground(WindowHandle windowHandle, long msg, long wparam, long lparam): # Available only on Windows, but have it available on other # platforms so that PyCharm doesn't warn about unresolved reference. @@ -41,11 +42,11 @@ class WindowUtils: return True @staticmethod - def gtk_plug_new(long long gdkNativeWindow): - return gtk_plug_new(gdkNativeWindow) + def gtk_plug_new(WindowHandle gdkNativeWindow): + return gtk_plug_new(gdkNativeWindow) @staticmethod - def gtk_widget_show(long long gtkWidgetPtr): + def gtk_widget_show(WindowHandle gtkWidgetPtr): with nogil: gtk_widget_show(gtkWidgetPtr) diff --git a/src/window_utils_mac.pyx b/src/window_utils_mac.pyx index 08eb7b85c..7b8e8569f 100644 --- a/src/window_utils_mac.pyx +++ b/src/window_utils_mac.pyx @@ -9,19 +9,20 @@ class WindowUtils: # for these methods. @staticmethod - def OnSetFocus(long windowHandle, long msg, long wparam, long lparam): + def OnSetFocus(WindowHandle windowHandle, long msg, long wparam, + long lparam): # Available only on Windows, but have it available on other # platforms so that PyCharm doesn't warn about unresolved reference. pass @staticmethod - def OnSize(long windowHandle, long msg, long wparam, long lparam): + def OnSize(WindowHandle windowHandle, long msg, long wparam, long lparam): # Available only on Windows, but have it available on other # platforms so that PyCharm doesn't warn about unresolved reference. pass @staticmethod - def OnEraseBackground(long windowHandle, long msg, long wparam, + def OnEraseBackground(WindowHandle windowHandle, long msg, long wparam, long lparam): # Available only on Windows, but have it available on other # platforms so that PyCharm doesn't warn about unresolved reference. diff --git a/src/window_utils_win.pyx b/src/window_utils_win.pyx index c40bd3831..5f8e80198 100644 --- a/src/window_utils_win.pyx +++ b/src/window_utils_win.pyx @@ -7,7 +7,7 @@ include "cefpython.pyx" class WindowUtils(object): @staticmethod - def OnSetFocus(long windowHandle, long msg, long wparam, long lparam): + def OnSetFocus(WindowHandle windowHandle, long msg, long wparam, long lparam): cdef PyBrowser pyBrowser = GetBrowserByWindowHandle(windowHandle) if not pyBrowser: return 0 @@ -15,7 +15,7 @@ class WindowUtils(object): return 0 @staticmethod - def OnSize(long windowHandle, long msg, long wparam, long lparam): + def OnSize(WindowHandle windowHandle, long msg, long wparam, long lparam): cdef PyBrowser pyBrowser = GetBrowserByWindowHandle(windowHandle) if not pyBrowser: return DefWindowProc(windowHandle, msg, wparam, lparam) @@ -35,7 +35,7 @@ class WindowUtils(object): return DefWindowProc(windowHandle, msg, wparam, lparam) @staticmethod - def OnEraseBackground(long windowHandle, long msg, long wparam, + def OnEraseBackground(WindowHandle windowHandle, long msg, long wparam, long lparam): cdef PyBrowser pyBrowser = GetBrowserByWindowHandle(windowHandle) if not pyBrowser: @@ -58,7 +58,8 @@ class WindowUtils(object): cdef WindowHandle windowHandle if pyBrowser.GetUserData("__outerWindowHandle"): - windowHandle = pyBrowser.GetUserData("__outerWindowHandle") + windowHandle = \ + pyBrowser.GetUserData("__outerWindowHandle") else: windowHandle = pyBrowser.GetWindowHandle() @@ -102,7 +103,7 @@ class WindowUtils(object): iconSmall = SendMessage( windowHandle, WM_GETICON, ICON_SMALL, 0) - cdef long long parentWindowHandle + cdef WindowHandle parentWindowHandle if not iconBig and not iconSmall: parentWindowHandle = pyBrowser.GetOpenerWindowHandle() @@ -134,11 +135,11 @@ class WindowUtils(object): ICON_SMALL, parentIconSmall) @staticmethod - def GetParentHandle(long windowHandle): - return GetParent(windowHandle) + def GetParentHandle(WindowHandle windowHandle): + return GetParent(windowHandle) @staticmethod - def IsWindowHandle(long windowHandle): + def IsWindowHandle(WindowHandle windowHandle): IF UNAME_SYSNAME == "Windows": return bool(IsWindow(windowHandle)) ELSE: diff --git a/tools/build.py b/tools/build.py index 0c2a84a48..7f89faf70 100644 --- a/tools/build.py +++ b/tools/build.py @@ -504,7 +504,9 @@ def except_all_missing(content): patterns.append( r"\bcp?def\s+" "((int|short|long|double|char|unsigned|float|double|cpp_bool" - "|cpp_string|cpp_wstring|uint64_t|uintptr_t|void" + "|cpp_string|cpp_wstring|uintptr_t|void" + "|int32|uint32|int64|uint64" + "|int32_t|uint32_t|int64_t|uint64_t" "|CefString)\s+)+" "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") patterns.append( diff --git a/unittests/_test_runner.py b/unittests/_test_runner.py index 8b970acaf..3968a52ca 100644 --- a/unittests/_test_runner.py +++ b/unittests/_test_runner.py @@ -266,7 +266,7 @@ def _print_summary(self): failed_str += ")" print(failed_str) else: - print("[_test_runner.py] OK") + print("[_test_runner.py] OK all unit tests succeeded") self._exit() def _exit(self): From 101a223464eab744dcca421d2fca188bb6a9c992 Mon Sep 17 00:00:00 2001 From: Czarek Date: Thu, 23 Feb 2017 13:41:21 +0100 Subject: [PATCH 136/557] Up-to-date complete build instructions for all three types of builds. 1. Build using prebuilt binaries and libraries from GH Releases 2. Build using binaries from Spotify Automated Builds 3. Build upstream CEF from sources --- docs/Build-instructions.md | 295 +++++++++++++++++++++++++++---------- 1 file changed, 214 insertions(+), 81 deletions(-) diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index 179a970d0..72ca54e8e 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -7,21 +7,21 @@ the build instructions on the wiki pages. If you would like to quickly build cefpython then see the [Quick build instructions for Windows](#quick-build-instructions-for-windows) and [Quick build instructions for Linux](#quick-build-instructions-for-linux) -sections for complete instructions. +sections. These instructions are complete meaning you don't need +to read anything more from this document. Using these quick +instructions you should be able to build cefpython in less than +10 minutes. -There are several types of builds you can perform: +There are several types of builds described in this document: 1. You can build CEF Python using prebuilt CEF binaries and libraries - that were uploaded to GH releases (tagged eg. v55-upstream) + that were uploaded to GH releases 2. You can build CEF Python using prebuilt CEF binaries from Spotify Automated Builds. -3. You can build both CEF and CEF Python from sources, but note - that Building CEF is a long process that can take hours. +3. You can build upstream CEF from sources, but note that building CEF + is a long process that can take hours. -Detailed instructions for building can be found in module doc comments -in the `automate.py` and `build.py` tools (the tools/ directory). - -Before you can build CEF Python or CEF you must satisfy some +Before you can build CEF Python or CEF you must satisfy [requirements](#requirements) listed on this page. @@ -29,17 +29,23 @@ Table of contents: * [Quick build instructions for Windows](#quick-build-instructions-for-windows) * [Quick build instructions for Linux](#quick-build-instructions-for-linux) * [Requirements](#requirements) -* [Build CEF Python using prebuilt CEF binaries](#build-cef-python-using-prebuilt-cef-binaries) -* [Build both CEF Python and CEF from sources](#build-both-cef-python-and-cef-from-sources) + * [Windows](#windows) + * [Linux](#linux) + * [Mac](#mac) + * [All platforms](#all-platforms) +* [Build using prebuilt CEF binaries and libraries](#build-using-prebuilt-cef-binaries-and-libraries) +* [Build using CEF binaries from Spotify Automated Builds](#build-using-cef-binaries-from-spotify-automated-builds) +* [Build upstream CEF from sources](#build-upstream-cef-from-sources) * [Build CEF manually](#build-cef-manually) -* [CEF automated builds](#cef-automated-builds) -* [How to patch](#how-to-patch) +* [CEF Automated Builds (Spotify and Adobe)](#cef-automated-builds-spotify-and-adobe) +* [Notes](#notes) +* [How to patch mini tutorial](#how-to-patch-mini-tutorial) ## Quick build instructions for Windows Complete steps for building CEF Python v50+ using prebuilt binaries -and libraries from GitHub releases: +and libraries from GitHub Releases: 1) Tested and works fine on Windows 7 64-bit @@ -56,19 +62,30 @@ and libraries from GitHub releases: you have to install "Visual C++ 2008 Redistributable Package (x64)" from [here](https://www.microsoft.com/en-us/download/details.aspx?id=15336) -6) Install python dependencies by running: - `cd cefpython/tools/ && pip install -r requirements.txt` - (Cython version from requirements.txt must match exactly) +6) Clone cefpython and create a build/ directory and enter it: +``` +git clone https://github.com/cztomczak/cefpython.git +cd cefpython/ +mkdir build/ +cd build/ +``` + +7) Install python dependencies: +``` +pip install -r ../tools/requirements.txt +``` -7) Download 32-bit Windows binaries and libraries from +8) Download Windows binaries and libraries from [GH releases](https://github.com/cztomczak/cefpython/tags) - tagged e.g. 'v55-upstream' when building v55. + tagged e.g. 'v55-upstream' when building v55. The version + of the binaries must match exactly the CEF version from + the "cefpython/src/version/cef_version_win.h" file + (the CEF_VERSION constant). -8) Extract the archive it in the "cefpython/build/" directory. +8) Extract the archive in the "build/" directory. -9) Build cefpython and run examples (xx.x is version number eg. 55.4): +9) Build cefpython and run examples (xx.x is version number): ``` -cd cefpython/build/ python ../tools/build.py xx.x ``` @@ -76,29 +93,45 @@ python ../tools/build.py xx.x ## Quick build instructions for Linux Complete steps for building CEF Python v50+ using prebuilt -binaries from GitHub releases: +binaries and libraries from GitHub Releases: -1) Tested and works fine on Ubuntu 14.04 64-bit (cmake 2.8.12 and g++ 4.8.4) +1) Tested and works fine on Ubuntu 14.04 64-bit 2) Download [ninja](https://github.com/ninja-build/ninja) 1.7.1 or later and copy it to /usr/bin and chmod 755. -3) Install packages: `sudo apt-get install python-dev cmake g++ libgtk2.0-dev` +3) Install required packages (tested and works with: cmake 2.8.12 + and g++ 4.8.4): +``` +sudo apt-get install python-dev cmake g++ libgtk2.0-dev +``` -4) Install python dependencies by executing: - `cd cefpython/tools/ && sudo pip install -r requirements.txt` - (Cython version from requirements.txt must match exactly) +4) Clone cefpython and create build/ directory and enter it: +``` +git clone https://github.com/cztomczak/cefpython.git +cd cefpython/ +mkdir build/ +cd build/ +``` + +5) Install python dependencies: +``` +sudo pip install -r ../tools/requirements.txt +``` -5) Download 64-bit Linux binaries and libraries from +6) Download Linux binaries and libraries from [GH releases](https://github.com/cztomczak/cefpython/tags) - tagged e.g. 'v55-upstream' when building v55. + tagged e.g. 'v55-upstream' when building v55. The version + of the binaries must match exactly the CEF version from + the "cefpython/src/version/cef_version_linux.h" file + (the CEF_VERSION constant). -6) Extract it in the cefpython/build/ directory and rename the extracted - directory to "cef_linux64". +7) Extract the archive in the build/ directory and rename + the extracted directory to "cef_linux64/". -7) Build cefpython and run examples (xx.x is version e.g. 50.0): +8) Build cefpython and run examples (xx.x is version number): ``` -cd cefpython/src/linux/ +cd ../src/linux/ python compile.py xx.x ``` @@ -109,7 +142,7 @@ Below are platform specific requirements. Do these first before following instructions in the "All platforms" section that lists requirements common for all platforms. -__Windows__ +### Windows * Install an appropriate MS compiler for a specific Python version: https://wiki.python.org/moin/WindowsCompilers @@ -133,7 +166,7 @@ __Windows__ "%LocalAppData%\Programs\Common\Microsoft\Visual C++ for Python\9.0\VC\include\" -__Linux__ +### Linux * Install packages: `sudo apt-get install python-dev cmake g++ libgtk2.0-dev` * If using prebuilt binaries from Spotify automated builds and want to @@ -159,62 +192,118 @@ __Linux__ [cef/#1804](https://bitbucket.org/chromiumembedded/cef/issues/1804). -__All platforms__ +### Mac + +* MacOS 10.9+, Xcode5+ and Xcode command line tools. Only 64-bit builds + are supported. + + + +### All platforms * Install dependencies for the automate.py tool by executing: `cd tools/ && pip install -r requirements.txt` (on Linux use `sudo`). - This will install some PyPI packages including Cython. On Windows - installing Cython requires a VS compiler - see instructions above - for Windows. + This will install some PyPI packages including Cython. -## Build CEF Python using prebuilt CEF binaries +## Build using prebuilt CEF binaries and libraries -__NOT WORKING YET__ +1) Clone cefpython and create a build/ directory and enter it: +``` +git clone https://github.com/cztomczak/cefpython.git +cd cefpython/ +mkdir build/ +cd build/ +``` -Prebuilt binaries are available on -[GitHub Releases](https://github.com/cztomczak/cefpython/releases) -and tagged eg. 'v51-upstream'. +2) Download binaries and libraries from + [GH releases](https://github.com/cztomczak/cefpython/tags) + tagged eg. 'v55-upstream' when building v55. The version + of the binaries must match exactly the CEF version from + the "cefpython/src/version/" directory (look for CEF_VERSION + constant in .h file). -Run the automate.py tool using the --prebuilt-cef flag that will download -prebuilt binaries from GitHub Releases using version information from -the "src/version/" directory. +3) Extract the downloaded archive eg. "cef55_3.2883.1553.g80bd606_win32.zip" + in the "build/" directory (using "extract here" option) +4) Run the build.py tool (xx.x is version number): ``` -cd tools/ -python automate.py --prebuilt-cef +python ../tools/build.py xx.x ``` -You should be fine by running automate.py with the default options, but if you -need to customize the build then use the --help flag to see more. +## Build using CEF binaries from Spotify Automated Builds -## Build both CEF Python and CEF from sources +1) Clone cefpython and create a build/ directory and enter it: +``` +git clone https://github.com/cztomczak/cefpython.git +cd cefpython/ +mkdir build/ +cd build/ +``` + +2) Download CEF binaries from [Spotify Automated Builds](http://opensource.spotify.com/cefbuilds/index.html). + The version of the binaries must match exactly the CEF version + from the "cefpython/src/version/" directory (look for CEF_VERSION + constant in .h file). -Run the automate.py tool using the --build-cef flag. You can optionally -set how many parallel ninja jobs to run (by default cores/2) with -the --ninja-jobs flag. +3) Extract the downloaded archive eg. + "cef_binary_3.2883.1553.g80bd606_windows32.tar.bz2" + in the build/ directory (using "extract here" option) -The automate script will use version information from the "src/version/" -directory. If you would like to use a custom CEF branch then you can -use the --cef-branch flag - but note that this is only for advanced +4) Run the automate.py tool. After it completes you should see a new + directory eg. "cef55_3.2883.1553.g80bd606_win32/". +``` +python ../tools/automate.py --prebuilt-cef +``` + +5) Run the build.py tool (xx.x is version number): +``` +python ../tools/build.py xx.x +``` + + +## Build upstream CEF from sources + +Building CEF from sources is a very long process that can take several +hours depending on your CPU speed and the platform you're building on. +If you would like to speed up the process you could modify automate.py +tool and remove the `is_official_build=true` flag which slows down +builds significantly (PR to add an option for that is welcome). +You can optionally set how many parallel ninja jobs to run (by default cores/2) with the --ninja-jobs flag passed to automate.py. + +To build CEF from sources run the automate.py tool using the --build-cef +flag. The automate script will use version information from the +"cefpython/src/version/" directory. If you would like to use +a custom CEF branch +then use the --cef-branch flag, but note that this is only for advanced users as this will require updating cefpython's C++/Cython code. -If building on Linux and there are errors, see the MISSING PACKAGES -note futher down. +If building on Linux and there are errors, see the +"MISSING PACKAGES (Linux)" note futher down. -You should be fine by running automate.py with the default options, but if you -need to customize the build then use the --help flag to see more. +You should be fine by running automate.py with the default options, +but if you need to customize the build then use the --help flag to +see more options. +The commands below will build CEF from sources with custom CEF Python +patches applied and then build the CEF Python package (xx.x is version +number): ``` -cd ~/cefpython/ -mkdir build/ && cd build +git clone https://github.com/cztomczak/cefpython.git +cd cefpython/ +mkdir build/ +cd build/ python ../tools/automate.py --build-cef --ninja-jobs 6 -mv cef*_*_linux64/ cef_linux64/ -cd ../../../src/linux/ -python compile.py xx.x +python ../tools/build.py xx.x ``` +The automate.py tool should create eg. "cef55_3.2883.1553.g80bd606_win32/" +directory when it's done. Then the build.py tool will build the cefpython +module, make installer package, install the package and run unit tests +and examples. See the notes for commands for creating package installer +and/or wheel package for distribution. + __MISSING PACKAGES (Linux)__: After the chromium sources are downloaded, it will try to build cef projects and if it fails due to missing packages make sure you've installed all the required packages listed in the @@ -235,8 +324,8 @@ After dependencies are satisifed re-run automate.py. ## Build CEF manually CEF Python official binaries come with custom CEF binaries with -a few patches applied for our use case. These patches are in the -patches/ directory. +a few patches applied for our use case, see the Notes section further +down on this page. On Linux before running any of CEF tools apply the issue73 patch first. @@ -245,16 +334,16 @@ To build CEF follow the instructions on the Branches and Building CEF wiki page: https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding -After it is successfully built - apply patches, rebuild and remake +After it is successfully built, apply patches, rebuild and remake distribs. Note that CEF patches must be applied in the "download_dir/chromium/src/cef/" directory, not in the "download_dir/cef/" directory. -## CEF automated builds +## CEF Automated Builds (Spotify and Adobe) -There are two sites that provide latest builds of CEF: +There are two sites that provide automated CEF builds: * Spotify - http://opensource.spotify.com/cefbuilds/index.html * This is the new build system * Since June 2016 all builds are without tcmalloc, see @@ -264,25 +353,69 @@ There are two sites that provide latest builds of CEF: * This is the old build system. Not tested whether it builds without tcmalloc. + +## Notes + +If you would like to update CEF version in cefpython then +see complete instructions provided in +[Issue #264](https://github.com/cztomczak/cefpython/issues/264). + +When building for multiple Python versions on Linux/Mac use +pyenv to manage multiple Python installations, see +[Issue #249](https://github.com/cztomczak/cefpython/issues/249) +for details. + +Command for making installer package is (xx.x is version number): +``` +cd cefpython/build/ +python ../tools/make_installer.py xx.x +``` + +To create a wheel package from that installer package type: +``` +cd *-setup/ +python setup.py bdist_wheel +cd dist/ +ls *.whl +``` + +Optional flags for the setup.py script above: +* `--python-tag cp27` to generate Python 2.7 only package +* `--universal` to build package for multiple Python versions + (in such case you must first build multiple cefpython modules + for each Python version) + +CEF Python binaries are build using similar configuration as described +on the ["Automated Build Setup"](https://bitbucket.org/chromiumembedded/cef/wiki/AutomatedBuildSetup.md#markdown-header-platform-build-configurations) wiki page in upstream CEF. The automate.py tool incorporates most of +of the flags from these configurations. + To build the "libcef_dll_wrapper" library type these commands: ``` -cd cef_binary/ +cd cef_binary*/ mkdir build cd build/ cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Release .. ninja libcef_dll_wrapper ``` -To build CEF sample applications type `ninja cefclient cefsimple`. +To build CEF sample applications type: +``` +ninja cefclient cefsimple ceftests +``` + +Official CEF Python binaries may come with additional patches applied +to CEF/Chromium depending on platform. These patches can be found +in the "cefpython/patches/" directory. Whether you need these patches +depends on your use case, they may not be required and thus you could +use the Spotify Automated Builds. Spotify builds have the issue73 patch +(no tcmalloc) applied. -Official CEF Python binaries come with additional patches to CEF/Chromium, -see the [patches/](../../../tree/master/patches) directory. Whether you -need these patches depends on your use case, they may not be required -and thus you could use the Spotify binaries. Spotify builds have the -issue73 patch (no tcmalloc) applied. +Currently (February 2017) only Linux releases have the custom +patches applied. Windows and Mac releases use CEF binaries from +Spotify Automated Builds. -## How to patch +## How to patch mini tutorial Create a patch from unstaged changes in current directory: ``` From 6b24eb198159a1e18c6902bb3f219a58276bbd21 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Fri, 24 Feb 2017 22:38:55 +0100 Subject: [PATCH 137/557] Build v55 on Mac Part 1 (#295)... Successfully built the cefpython module. There are still some warnings and issues to resolve, but it looks good. Update makefiles. Update installer setup for Mac. Update Mac requirements in build instructions. Add --fast-build option to automate.py. --- docs/Build-instructions.md | 9 +-- src/client_handler/Makefile | 12 ++- src/client_handler/lifespan_handler.cpp | 2 + src/compile_time_constants.pxi | 2 +- src/extern/cef/cef_mac.pxd | 2 +- src/linux/setup/setup.py | 4 +- src/subprocess/Makefile | 26 +++--- src/subprocess/Makefile-libcefpythonapp | 2 +- src/version/cef_version_mac.h | 102 ++++++++++++++++++++++++ tools/automate.py | 12 ++- tools/build.py | 83 +++++++++---------- tools/build_module.py | 29 +++---- tools/installer/cefpython3.__init__.py | 32 +++++--- 13 files changed, 226 insertions(+), 91 deletions(-) create mode 100644 src/version/cef_version_mac.h diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index 72ca54e8e..d22d02635 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -198,7 +198,6 @@ requirements common for all platforms. are supported. - ### All platforms * Install dependencies for the automate.py tool by executing: @@ -267,10 +266,10 @@ python ../tools/build.py xx.x Building CEF from sources is a very long process that can take several hours depending on your CPU speed and the platform you're building on. -If you would like to speed up the process you could modify automate.py -tool and remove the `is_official_build=true` flag which slows down -builds significantly (PR to add an option for that is welcome). -You can optionally set how many parallel ninja jobs to run (by default cores/2) with the --ninja-jobs flag passed to automate.py. +To speed up the process you can pass the --fast-build flag, however +in such case result binaries won't be optimized. +You can optionally set how many parallel ninja jobs to run (by default +cores/2) with the --ninja-jobs flag passed to automate.py. To build CEF from sources run the automate.py tool using the --build-cef flag. The automate script will use version information from the diff --git a/src/client_handler/Makefile b/src/client_handler/Makefile index 08abf696f..5340da3df 100644 --- a/src/client_handler/Makefile +++ b/src/client_handler/Makefile @@ -10,17 +10,21 @@ UNAME_S = $(shell uname -s) CC = g++ -CCFLAGS = -fPIC -std=gnu++11 -Wall -Werror $(CEF_CCFLAGS) +CCFLAGS = -fPIC -std=c++11 -Wall -Werror $(CEF_CCFLAGS) SRC = client_handler.cpp cookie_visitor.cpp resource_handler.cpp \ web_request_client.cpp string_visitor.cpp request_context_handler.cpp \ - task.cpp x11.cpp context_menu_handler.cpp display_handler.cpp \ + task.cpp context_menu_handler.cpp display_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 OBJ = $(SRC:.cpp=.o) +ifeq ($(UNAME_S), Linux) + OBJ += x11.o +endif + ifeq ($(UNAME_S), Darwin) OBJ += util_mac.o endif @@ -56,6 +60,10 @@ $(OUT): $(OBJ) @echo [CLIENT HANDLER] Creating library $(OUT) from $(OBJ)... ar rcs $(OUT) $(OBJ) +x11.o: x11.cpp + @echo [CLIENT HANDLER] Building $@ from $<... + $(CC) $(CCFLAGS) $(INC) -c $< -o $@ + util_mac.o: util_mac.mm @echo [CLIENT HANDLER] Building $@ from $<... $(CC) $(CCFLAGS) $(INC) -c $< -o $@ diff --git a/src/client_handler/lifespan_handler.cpp b/src/client_handler/lifespan_handler.cpp index 4b9f24a8c..d77a1f0e6 100644 --- a/src/client_handler/lifespan_handler.cpp +++ b/src/client_handler/lifespan_handler.cpp @@ -1,7 +1,9 @@ // Copyright (c) 2016 CEF Python. See the Authors and License files. #include "lifespan_handler.h" +#if defined(OS_WIN) #include "dpi_aware.h" +#endif #include "LOG_DEBUG.h" diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 10ec798af..05306be6d 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 = 2 diff --git a/src/extern/cef/cef_mac.pxd b/src/extern/cef/cef_mac.pxd index 60216fccd..2639eb39c 100644 --- a/src/extern/cef/cef_mac.pxd +++ b/src/extern/cef/cef_mac.pxd @@ -6,7 +6,7 @@ include "compile_time_constants.pxi" from libcpp cimport bool as cpp_bool -cdef extern from "include/internal/cef_linux.h": +cdef extern from "include/internal/cef_mac.h": ctypedef void* CefWindowHandle ctypedef void* CefCursorHandle diff --git a/src/linux/setup/setup.py b/src/linux/setup/setup.py index d06a688fb..c9a4494d0 100644 --- a/src/linux/setup/setup.py +++ b/src/linux/setup/setup.py @@ -16,7 +16,7 @@ # Fast mode disables optimization flags FAST = True print("FAST mode On") - COMPILE_OPTIMIZE_FLAGS = ['-flto', '-std=gnu++11'] + COMPILE_OPTIMIZE_FLAGS = ['-flto', '-std=c++11'] LINK_OPTIMIZE_FLAGS = ['-flto'] else: FAST = False @@ -25,7 +25,7 @@ # prolongs compilation time significantly. # More on the other flags: https://stackoverflow.com/questions/6687630/ COMPILE_OPTIMIZE_FLAGS = ['-flto', '-fdata-sections', '-ffunction-sections', - '-std=gnu++11'] + '-std=c++11'] LINK_OPTIMIZE_FLAGS = ['-flto', '-Wl,--gc-sections'] diff --git a/src/subprocess/Makefile b/src/subprocess/Makefile index fcaad726e..75fdeb36a 100644 --- a/src/subprocess/Makefile +++ b/src/subprocess/Makefile @@ -32,27 +32,33 @@ ifeq ($(UNAME_S), Linux) -L./../../build/cef_linux64/lib \ -L./../../build/cef_linux32/lib else ifeq ($(UNAME_S), Darwin) - LIB_DIRS = -L./../../build/cef_mac64/bin \ - -L./../../build/cef_mac32/bin \ - -L./../../build/cef_mac64/lib \ - -L./../../build/cef_mac32/lib + LIB_DIRS = -F$(CEF_BIN) \ + -L$(CEF_LIB) endif ifeq ($(UNAME_S), Linux) CPP_FILES = print_handler_gtk.cpp - LIBS = -lgobject-2.0 -lglib-2.0 -lgtk-x11-2.0 -else + LIBS = -lcef -lgobject-2.0 -lglib-2.0 -lgtk-x11-2.0 +else ifeq ($(UNAME_S), Darwin) CPP_FILES = - LIBS = + LIBS = -framework Chromium\ Embedded\ Framework endif -CCFLAGS = -g -std=gnu++11 -Wall -Werror -DRENDERER_PROCESS $(CEF_CCFLAGS) + +CCFLAGS = -g -std=c++11 -Wall -Werror -DRENDERER_PROCESS $(CEF_CCFLAGS) + +ifeq ($(UNAME_S), Darwin) + MACFLAGS = -O3 -DNDEBUG -stdlib=libstdc++ \ + -Wl,-search_paths_first -Wl,-ObjC -Wl,-pie -Wl,-dead_strip +else + MACFLAGS = +endif subprocess: # -fPIC is required only for libraries included by Cython. @echo [SUBPROCESS] Building the 'subprocess' executable - g++ $(CCFLAGS) $(INC) $(LIB_DIRS) main.cpp cefpython_app.cpp \ + g++ $(CCFLAGS) $(MACFLAGS) $(INC) $(LIB_DIRS) main.cpp cefpython_app.cpp \ v8function_handler.cpp v8utils.cpp javascript_callback.cpp \ $(CPP_FILES) \ - $(LIBS) -lcef -lcef_dll_wrapper -o subprocess -Wl,-rpath,. + $(LIBS) -lcef_dll_wrapper -o subprocess -Wl,-rpath,. diff --git a/src/subprocess/Makefile-libcefpythonapp b/src/subprocess/Makefile-libcefpythonapp index b52157b7f..5264a9c5e 100644 --- a/src/subprocess/Makefile-libcefpythonapp +++ b/src/subprocess/Makefile-libcefpythonapp @@ -10,7 +10,7 @@ UNAME_S = $(shell uname -s) CC = g++ -CCFLAGS = -fPIC -std=gnu++11 -Wall -Werror -DBROWSER_PROCESS \ +CCFLAGS = -fPIC -std=c++11 -Wall -Werror -DBROWSER_PROCESS \ $(CEF_CCFLAGS) ifeq ($(UNAME_S), Linux) diff --git a/src/version/cef_version_mac.h b/src/version/cef_version_mac.h new file mode 100644 index 000000000..3a20c3f43 --- /dev/null +++ b/src/version/cef_version_mac.h @@ -0,0 +1,102 @@ +// Copyright (c) 2017 Marshall A. Greenblatt. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the name Chromium Embedded +// Framework nor the names of its contributors may be used to endorse +// or promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// --------------------------------------------------------------------------- +// +// This file is generated by the make_version_header.py tool. +// + +#ifndef CEF_INCLUDE_CEF_VERSION_H_ +#define CEF_INCLUDE_CEF_VERSION_H_ + +#define CEF_VERSION "3.2883.1553.g80bd606" +#define CEF_VERSION_MAJOR 3 +#define CEF_COMMIT_NUMBER 1553 +#define CEF_COMMIT_HASH "80bd6062d7ac4c5fd1d7bc7ee78e8e59d4a040aa" +#define COPYRIGHT_YEAR 2017 + +#define CHROME_VERSION_MAJOR 55 +#define CHROME_VERSION_MINOR 0 +#define CHROME_VERSION_BUILD 2883 +#define CHROME_VERSION_PATCH 87 + +#define DO_MAKE_STRING(p) #p +#define MAKE_STRING(p) DO_MAKE_STRING(p) + +#ifndef APSTUDIO_HIDDEN_SYMBOLS + +#include "include/internal/cef_export.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// The API hash is created by analyzing CEF header files for C API type +// definitions. The hash value will change when header files are modified +// in a way that may cause binary incompatibility with other builds. The +// universal hash value will change if any platform is affected whereas the +// platform hash values will change only if that particular platform is +// affected. +#define CEF_API_HASH_UNIVERSAL "87b7eefcb86c87b28f86bfd7919f7d7a6cffc0d8" +#if defined(OS_WIN) +#define CEF_API_HASH_PLATFORM "00823905486d7b7222da5654fe35d2d15f65543a" +#elif defined(OS_MACOSX) +#define CEF_API_HASH_PLATFORM "f0180f006643782254250f34e858b98110a40e6e" +#elif defined(OS_LINUX) +#define CEF_API_HASH_PLATFORM "14b19454a4231fa10a77b8955954dc95f073af6b" +#endif + +// Returns CEF version information for the libcef library. The |entry| +// parameter describes which version component will be returned: +// 0 - CEF_VERSION_MAJOR +// 1 - CEF_COMMIT_NUMBER +// 2 - CHROME_VERSION_MAJOR +// 3 - CHROME_VERSION_MINOR +// 4 - CHROME_VERSION_BUILD +// 5 - CHROME_VERSION_PATCH +/// +CEF_EXPORT int cef_version_info(int entry); + +/// +// Returns CEF API hashes for the libcef library. The returned string is owned +// by the library and should not be freed. The |entry| parameter describes which +// hash value will be returned: +// 0 - CEF_API_HASH_PLATFORM +// 1 - CEF_API_HASH_UNIVERSAL +// 2 - CEF_COMMIT_HASH +/// +CEF_EXPORT const char* cef_api_hash(int entry); + +#ifdef __cplusplus +} +#endif + +#endif // APSTUDIO_HIDDEN_SYMBOLS + +#endif // CEF_INCLUDE_CEF_VERSION_H_ diff --git a/tools/automate.py b/tools/automate.py index 0d9660673..f6dd9fb02 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -20,6 +20,7 @@ Usage: automate.py (--prebuilt-cef | --build-cef) + [--fast-build FAST_BUILD] [--force-chromium-update FORCE_CHROMIUM_UPDATE] [--no-cef-update NO_CEF_UPDATE] [--cef-branch BRANCH] [--cef-commit COMMIT] @@ -34,6 +35,7 @@ binaries for Linux are built on Ubuntu. --build-cef Whether to build CEF from sources with the cefpython patches applied. + --fast-build Fast build with is_official_build=False --force-chromium-update Force Chromium update (gclient sync etc). --no-cef-update Do not update CEF sources (by default both cef/ directories are deleted on every run). @@ -73,6 +75,7 @@ class Options(object): # From command-line prebuilt_cef = False build_cef = False + fast_build = False force_chromium_update = False no_cef_update = False cef_branch = "" @@ -354,8 +357,11 @@ def build_cef_projects(): print("[automate.py] Build cefclient, cefsimple, ceftests") # Cmake command = prepare_build_command() - command.extend(["cmake", "-G", "Ninja", - "-DCMAKE_BUILD_TYPE="+Options.build_type, ".."]) + command.extend(["cmake", "-G", "Ninja"]) + command.append("-DCMAKE_BUILD_TYPE="+Options.build_type) + if MAC: + command.append("-DPROJECT_ARCH=x86_64") + command.append("..") run_command(command, Options.build_cefclient_dir) print("[automate.py] OK") # Ninja @@ -695,7 +701,7 @@ def getenv(): # To perform an official build set GYP_DEFINES=buildtype=Official. # This will disable debugging code and enable additional link-time # optimizations in Release builds. - if Options.release_build: + if Options.release_build and not Options.fast_build: env["GN_DEFINES"] += " is_official_build=true" # Modifications to automate-git.py env["CEFPYTHON_NINJA_JOBS"] = str(Options.ninja_jobs) diff --git a/tools/build.py b/tools/build.py index 7f89faf70..6fcbb5f46 100644 --- a/tools/build.py +++ b/tools/build.py @@ -35,10 +35,10 @@ # 6. More commands: http://docs.cython.org/src/userguide/debugging.html # This will not show "Segmentation fault" error message: -# | subprocess.call(["python", "./wxpython.py"]) -# You need to call it with shell=True for this kind of -# error message to be shown: -# | subprocess.call("python wxpython.py", shell=True) +# > subprocess.call(["python", "./wxpython.py"]) +# You need to call it with command as string and shell=True +# for this kind of error message to be shown: +# > subprocess.call("python wxpython.py", shell=True) from common import * import sys @@ -84,11 +84,17 @@ def main(): check_cython_version() command_line_args() check_directories() - fix_cefpython_h() - if WINDOWS: - compile_cpp_projects_windows() - elif MAC or LINUX: - compile_cpp_projects_unix() + if os.path.exists(CEFPYTHON_H): + fix_cefpython_h() + if WINDOWS: + compile_cpp_projects_windows() + elif MAC or LINUX: + compile_cpp_projects_unix() + else: + print("[build.py] INFO: Looks like first run, as cefpython.h" + " is missing. Skip building C++ projects.") + global FIRST_RUN + FIRST_RUN = True clear_cache() copy_and_fix_pyx_files() create_version_pyx_file() @@ -103,9 +109,6 @@ def setup_environ(): include path. Set Mac compiler options. Etc.""" print("[build.py] Setup environment variables") - if not WINDOWS: - return - # PATH if WINDOWS: path = [ @@ -134,6 +137,11 @@ def setup_environ(): print("[build.py] environ AdditionalLibraryDirectories: {lib}" .format(lib=os.environ["AdditionalLibraryDirectories"])) + # Mac env variables for makefiles + if MAC: + os.environ["CEF_BIN"] = os.path.join(CEF_BINARIES_LIBRARIES, "bin") + os.environ["CEF_LIB"] = os.path.join(CEF_BINARIES_LIBRARIES, "lib") + # Mac compiler options if MAC: os.environ["PATH"] = "/usr/local/bin:"+os.environ["PATH"] @@ -235,14 +243,13 @@ def fix_cefpython_h(): print("[build.py] cefpython.h was not yet generated") return with open("cefpython.h", "r") as fo: - content = fo.read() - pragma = "#pragma warning(disable:4190)" - if pragma in content: - print("[build.py] cefpython.h is already fixed") - return - content = ("%s\n\n" % pragma) + content + contents = fo.read() + # Error/warning depending on compiler: + # > has C-linkage specified, but returns user-defined type + contents = contents.replace("#define __PYX_EXTERN_C extern \"C\"", + "#define __PYX_EXTERN_C extern") with open("cefpython.h", "w") as fo: - fo.write(content) + fo.write(contents) print("[build.py] Save build_cefpython/cefpython.h") @@ -288,13 +295,6 @@ def compile_cpp_projects_windows(): def build_vcproj(vcproj): - if not os.path.exists(CEFPYTHON_H): - print("[build.py] INFO: Looks like first run, as cefpython.h" - " is missing. Skip building C++ project.") - global FIRST_RUN - FIRST_RUN = True - return - if PYVERSION == "27": args = list() args.append(VS2008_VCVARS) @@ -451,7 +451,7 @@ def copy_and_fix_pyx_files(): os.remove(pyxfile) # Copying pyxfiles and reading its contents. - print("[build.py] Copying pyx files to build_cefpython/: %s" % pyxfiles) + print("[build.py] Copying pyx files to build_cefpython/") # Copy cefpython.pyx and fix includes in cefpython.pyx, eg.: # include "handlers/focus_handler.pyx" becomes include "focus_handler.pyx" @@ -467,7 +467,7 @@ def copy_and_fix_pyx_files(): print("[build.py] %s includes fixed in %s" % (subs, mainfile)) # Copy the rest of the files - print("[build.py] Fixing includes in .pyx files:") + print("[build.py] Fix includes in other .pyx files") for pyxfile in pyxfiles: newfile = "./%s" % os.path.basename(pyxfile) shutil.copy(pyxfile, newfile) @@ -489,8 +489,9 @@ def copy_and_fix_pyx_files(): content, flags=re.MULTILINE) if subs: - print("[build.py] %s includes removed in: %s" - % (subs, os.path.basename(pyxfile))) + # print("[build.py] %s includes removed in: %s" + # % (subs, os.path.basename(pyxfile))) + pass with open(pyxfile, "w") as pyxfileopened: pyxfileopened.write(content) @@ -540,24 +541,26 @@ def create_version_pyx_file(): def build_cefpython_module(): - os.chdir(BUILD_CEFPYTHON) # if DEBUG_FLAG: # ret = subprocess.call("python-dbg setup.py build_ext --inplace" # " --cython-gdb", shell=True) print("[build.py] Execute build_module.py script") print("") + + os.chdir(BUILD_CEFPYTHON) + if FAST_FLAG: - ret = subprocess.call([sys.executable, - "{tools_dir}/build_module.py" - .format(tools_dir=TOOLS_DIR), - "build_ext", "--inplace", "--fast"], + ret = subprocess.call("{python} {tools_dir}/build_module.py" + " build_ext --fast" + .format(python=sys.executable, + tools_dir=TOOLS_DIR), shell=True) else: - ret = subprocess.call([sys.executable, - "{tools_dir}/build_module.py" - .format(tools_dir=TOOLS_DIR), - "build_ext", "--inplace"], + ret = subprocess.call("{python} {tools_dir}/build_module.py" + " build_ext" + .format(python=sys.executable, + tools_dir=TOOLS_DIR), shell=True) # if DEBUG_FLAG: @@ -585,7 +588,7 @@ def build_cefpython_module(): args.append(os.path.join(TOOLS_DIR, os.path.basename(__file__))) assert __file__ in sys.argv[0] args.extend(sys.argv[1:]) - ret = subprocess.call(args, shell=True) + ret = subprocess.call(" ".join(args), shell=True) sys.exit(ret) else: print("[build.py] ERROR: failed to build the cefpython module") diff --git a/tools/build_module.py b/tools/build_module.py index 0d1524df6..e5c726681 100644 --- a/tools/build_module.py +++ b/tools/build_module.py @@ -77,36 +77,31 @@ def set_compiler_options(options): # # The above warning LNK4217 is caused by the warning below which occurs # when building the client_handler.lib static library: - # - # cefpython.h(36): warning C4190: 'RequestHandler_GetResourceHandler' - # has C-linkage specified, but returns UDT 'CefRefPtr' which is - # incompatible with C - # - # The C4190 warning is disabled with pragma in cefpython.h, see the - # fix_cefpython_h() in the build.py script. - extra_compile_args.extend(['/EHsc']) - extra_link_args.extend(['/ignore:4217']) + extra_compile_args.extend(["/EHsc"]) + extra_link_args.extend(["/ignore:4217"]) if LINUX: if len(sys.argv) > 1 and "--fast" in sys.argv: sys.argv.remove("--fast") # Fast mode disables optimization flags print("[build_module.py] FAST mode On") - extra_compile_args.extend(['-flto', '-std=gnu++11']) - extra_link_args.extend(['-flto']) + extra_compile_args.extend(["-flto", "-std=c++11"]) + extra_link_args.extend(["-flto"]) else: # Fix "ImportError ... undefined symbol ..." caused by CEF's # include/base/ headers by adding the -flto flag (Issue #230). # Unfortunately -flto prolongs compilation time significantly. # More on the other flags: https://stackoverflow.com/questions/ # 6687630/ . - extra_compile_args.extend(['-flto', '-fdata-sections', - '-ffunction-sections', '-std=gnu++11']) - extra_link_args.extend(['-flto', '-Wl,--gc-sections']) + extra_compile_args.extend(["-flto", "-fdata-sections", + "-ffunction-sections", "-std=c++11"]) + extra_link_args.extend(["-flto", "-Wl,--gc-sections"]) if MAC: - os.environ["CC"] = "gcc" - os.environ["CXX"] = "g++" + extra_compile_args.extend(["-std=c++11"]) + # extra_link_args.extend([]) + # os.environ["CC"] = "gcc" + # os.environ["CXX"] = "g++" options["extra_compile_args"] = extra_compile_args options["extra_link_args"] = extra_link_args @@ -254,7 +249,7 @@ def get_ext_modules(options): "c_string_encoding": "utf-8", }, - language='c++', + language="c++", include_dirs=options["include_dirs"], library_dirs=options["library_dirs"], diff --git a/tools/installer/cefpython3.__init__.py b/tools/installer/cefpython3.__init__.py index 5e794a0aa..67ce48baa 100644 --- a/tools/installer/cefpython3.__init__.py +++ b/tools/installer/cefpython3.__init__.py @@ -10,7 +10,7 @@ import ctypes import platform -__all__ = ["cefpython", "wx"] +__all__ = ["cefpython"] # Disabled: "wx" __version__ = "{{VERSION}}" __author__ = "The CEF Python authors" @@ -26,10 +26,12 @@ package_dir = os.path.dirname(os.path.abspath(__file__)) # This loads the libcef.so library for the subprocess executable. -# On Mac it works without setting library paths, but let's set it -# just to be sure. os.environ["LD_LIBRARY_PATH"] = package_dir -os.environ["DYLD_LIBRARY_PATH"] = package_dir + +# On Mac it works without setting library paths. Better not set it, +# as maybe user's app will set it itself. +# > os.environ["DYLD_LIBRARY_PATH"] = package_dir +# > os.environ["DYLD_FRAMEWORK_PATH"] = package_dir # This env variable will be returned by cefpython.GetModuleDirectory(). os.environ["CEFPYTHON3_PATH"] = package_dir @@ -40,23 +42,35 @@ # it may cause issues to load it here in the browser process. libcef = None if platform.system() == "Darwin": - libcef = os.path.join(package_dir, "libcef.dylib") + cef_framework = "Chromium Embedded Framework.framework" + libcef_name = "Chromium Embedded Framework" + # Search for it in current directory or in ../Frameworks/ dir + # in case this is user's app packaged for distribution. + libcef1 = os.path.join(package_dir, cef_framework, libcef_name) + libcef2 = os.path.join(package_dir, "..", "Frameworks", cef_framework, + libcef_name) + if os.path.exists(libcef1): + libcef = libcef1 + elif os.path.exists(libcef2): + libcef = libcef2 + else: + raise Exception("Can't find: " + cef_framework) elif platform.system() == "Linux": libcef = os.path.join(package_dir, "libcef.so") if libcef: ctypes.CDLL(libcef, ctypes.RTLD_GLOBAL) # Load the cefpython module for proper Python version -if (2, 7) <= sys.version_info < (2, 8): +if sys.version_info[:2] == (2, 8): # noinspection PyUnresolvedReferences from . import cefpython_py27 as cefpython -elif (3, 4) <= sys.version_info < (3, 5): +elif sys.version_info[:2] == (3, 4): # noinspection PyUnresolvedReferences from . import cefpython_py34 as cefpython -elif (3, 5) <= sys.version_info < (3, 6): +elif sys.version_info[:2] == (3, 5): # noinspection PyUnresolvedReferences from . import cefpython_py35 as cefpython -elif (3, 6) <= sys.version_info < (3, 7): +elif sys.version_info[:2] == (3, 6): # noinspection PyUnresolvedReferences from . import cefpython_py36 as cefpython else: From eeef09ab8e3d398e5dc6714efdbcde921d33704d Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 27 Feb 2017 16:00:14 +0100 Subject: [PATCH 138/557] Build v55 on Mac Part 2 (#295)... Update build tools and makefiles. Link to libc++ and libc++abi to avoid undefined symbol error. Fix visibility: PyMODINIT_FUNC. Minimum Mac version: 10.7. Do not use ctypes.CDLL on Mac, load CEF framework statically. Both Mac and Linux: Add -DNDEBUG and -O3 optimization flags. libcef_dll_wrapper needs to be built using this command: cmake -G "Ninja" -DPROJECT_ARCH="x86_64" \ -DCMAKE_CXX_FLAGS="-stdlib=libc++" \ -DCMAKE_BUILD_TYPE=Release .. ninja libcef_dll_wrapper --- docs/Build-instructions.md | 2 + src/__version__.pyx | 2 - src/cefpython.pyx | 12 +- src/client_handler/Makefile | 37 ++--- src/cpp_utils/Makefile | 5 +- src/linux/setup/setup.py | 4 +- src/subprocess/Makefile | 20 +-- src/subprocess/Makefile-libcefpythonapp | 33 ++-- tools/build.py | 109 +++++++++---- tools/build_module.py | 200 +++++++++++++++++++----- tools/common.py | 12 ++ tools/installer/cefpython3.__init__.py | 31 +--- 12 files changed, 312 insertions(+), 155 deletions(-) delete mode 100644 src/__version__.pyx diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index d22d02635..2ee531ae5 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -196,6 +196,8 @@ requirements common for all platforms. * MacOS 10.9+, Xcode5+ and Xcode command line tools. Only 64-bit builds are supported. +* Upgrade setuptools package to latest version otherwise there will be + problems with Cython: `sudo pip install --upgrade setuptools` ### All platforms diff --git a/src/__version__.pyx b/src/__version__.pyx deleted file mode 100644 index 52d26ce1c..000000000 --- a/src/__version__.pyx +++ /dev/null @@ -1,2 +0,0 @@ -# A dummy file. The compile script generates a real __version__.pyx -# in the setup/ directory. diff --git a/src/cefpython.pyx b/src/cefpython.pyx index ffbcde969..9d641ebed 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -246,12 +246,8 @@ END OF: CHANGES in CEF since v31..v47. # Includes being made in other .pyx files are allowed to help # IDE completion, but will be removed during cython compilation. -# Version file is generated by the compile.bat/compile.py script. -include "__version__.pyx" - include "compile_time_constants.pxi" - # ----------------------------------------------------------------------------- # IMPORTS @@ -503,7 +499,11 @@ include "command_line.pyx" include "app.pyx" include "drag_data.pyx" include "helpers.pyx" -include "image.pyx" + +# Currently used only on Linux via DragData. Do not include on other +# platforms otherwise warning about unused function appears. +IF UNAME_SYSNAME == "Linux": + include "image.pyx" # Handlers include "handlers/browser_process_handler.pyx" @@ -645,7 +645,7 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): if "resources_dir_path" not in applicationSettings: applicationSettings["resources_dir_path"] = module_dir if platform.system() == "Darwin": - applicationSettings["resources_dir_path"] = module_dir+"/Resources" + pass # TODO: Check if this needs to be set in v56+ if "browser_subprocess_path" not in applicationSettings: applicationSettings["browser_subprocess_path"] = os.path.join( module_dir, "subprocess") diff --git a/src/client_handler/Makefile b/src/client_handler/Makefile index 5340da3df..f0b9a5a4d 100644 --- a/src/client_handler/Makefile +++ b/src/client_handler/Makefile @@ -4,30 +4,29 @@ # -Wall - show important warnings # -Werror - treat warnings as errors -# Cython compiler options: +# Cython compiler options on Linux: # -fPIC -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions \ # -Wl,-z,relro UNAME_S = $(shell uname -s) -CC = g++ -CCFLAGS = -fPIC -std=c++11 -Wall -Werror $(CEF_CCFLAGS) +CCFLAGS = -fPIC $(CEF_CCFLAGS) + +ifeq ($(UNAME_S), Linux) + SRC_MORE = x11.cpp +else ifeq ($(UNAME_S), Darwin) + SRC_MORE = util_mac.mm +endif SRC = client_handler.cpp cookie_visitor.cpp resource_handler.cpp \ web_request_client.cpp string_visitor.cpp request_context_handler.cpp \ task.cpp context_menu_handler.cpp display_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 - -OBJ = $(SRC:.cpp=.o) - -ifeq ($(UNAME_S), Linux) - OBJ += x11.o -endif + render_handler.cpp request_handler.cpp \ + $(SRC_MORE) -ifeq ($(UNAME_S), Darwin) - OBJ += util_mac.o -endif +OBJ = $(filter %.o, $(SRC:.cpp=.o) $(SRC:.mm=.o)) +.SUFFIXES: .cpp .mm .o OUT = libclient_handler.a @@ -52,21 +51,19 @@ INC = -I./../ -I./../common/ -I/usr/include/python2.7 \ -I/usr/lib/gtk-2.0/gtk-unix-print-2.0 \ -I/usr/lib/glib-2.0/include -.cpp.o: - @echo [CLIENT HANDLER] Building $@ from $<... - $(CC) $(CCFLAGS) $(INC) -c $< -o $@ $(OUT): $(OBJ) @echo [CLIENT HANDLER] Creating library $(OUT) from $(OBJ)... ar rcs $(OUT) $(OBJ) -x11.o: x11.cpp +.cpp.o: @echo [CLIENT HANDLER] Building $@ from $<... - $(CC) $(CCFLAGS) $(INC) -c $< -o $@ + $(CXX) $(CCFLAGS) $(INC) -c $< -o $@ -util_mac.o: util_mac.mm +.mm.o: @echo [CLIENT HANDLER] Building $@ from $<... - $(CC) $(CCFLAGS) $(INC) -c $< -o $@ + $(CXX) $(CCFLAGS) $(INC) -c $< -o $@ + clean: @echo [CLIENT HANDLER] Cleaning... diff --git a/src/cpp_utils/Makefile b/src/cpp_utils/Makefile index 9e589e800..338fd960b 100644 --- a/src/cpp_utils/Makefile +++ b/src/cpp_utils/Makefile @@ -1,5 +1,4 @@ -CC = g++ -CCFLAGS = -g $(CEF_CCFLAGS) +CCFLAGS = -fPIC $(CEF_CCFLAGS) SRC = PaintBuffer.cpp OBJ = $(SRC:.cpp=.o) @@ -15,7 +14,7 @@ INC = -I./../ -I/usr/include/gtk-2.0 \ -I/usr/lib/glib-2.0/include -I/usr/lib/gtk-2.0/include .cpp.o: - $(CC) -fPIC $(INC) $(CCFLAGS) -c $< -o $@ + $(CXX) $(INC) $(CCFLAGS) -c $< -o $@ $(OUT): $(OBJ) ar rcs $(OUT) $(OBJ) diff --git a/src/linux/setup/setup.py b/src/linux/setup/setup.py index c9a4494d0..d06a688fb 100644 --- a/src/linux/setup/setup.py +++ b/src/linux/setup/setup.py @@ -16,7 +16,7 @@ # Fast mode disables optimization flags FAST = True print("FAST mode On") - COMPILE_OPTIMIZE_FLAGS = ['-flto', '-std=c++11'] + COMPILE_OPTIMIZE_FLAGS = ['-flto', '-std=gnu++11'] LINK_OPTIMIZE_FLAGS = ['-flto'] else: FAST = False @@ -25,7 +25,7 @@ # prolongs compilation time significantly. # More on the other flags: https://stackoverflow.com/questions/6687630/ COMPILE_OPTIMIZE_FLAGS = ['-flto', '-fdata-sections', '-ffunction-sections', - '-std=c++11'] + '-std=gnu++11'] LINK_OPTIMIZE_FLAGS = ['-flto', '-Wl,--gc-sections'] diff --git a/src/subprocess/Makefile b/src/subprocess/Makefile index 75fdeb36a..c4d73a5b2 100644 --- a/src/subprocess/Makefile +++ b/src/subprocess/Makefile @@ -41,24 +41,18 @@ ifeq ($(UNAME_S), Linux) LIBS = -lcef -lgobject-2.0 -lglib-2.0 -lgtk-x11-2.0 else ifeq ($(UNAME_S), Darwin) CPP_FILES = - LIBS = -framework Chromium\ Embedded\ Framework -endif - - -CCFLAGS = -g -std=c++11 -Wall -Werror -DRENDERER_PROCESS $(CEF_CCFLAGS) - -ifeq ($(UNAME_S), Darwin) - MACFLAGS = -O3 -DNDEBUG -stdlib=libstdc++ \ - -Wl,-search_paths_first -Wl,-ObjC -Wl,-pie -Wl,-dead_strip -else - MACFLAGS = + # Include framework before libcef_dll_wrapper + LIBS = -framework "Chromium Embedded Framework" endif +CCFLAGS = -DRENDERER_PROCESS $(CEF_CCFLAGS) subprocess: # -fPIC is required only for libraries included by Cython. @echo [SUBPROCESS] Building the 'subprocess' executable - g++ $(CCFLAGS) $(MACFLAGS) $(INC) $(LIB_DIRS) main.cpp cefpython_app.cpp \ + $(CXX) $(CCFLAGS) $(INC) $(LIB_DIRS) main.cpp cefpython_app.cpp \ v8function_handler.cpp v8utils.cpp javascript_callback.cpp \ $(CPP_FILES) \ - $(LIBS) -lcef_dll_wrapper -o subprocess -Wl,-rpath,. + $(CEF_LINK_FLAGS) \ + $(LIBS) -lcef_dll_wrapper \ + -o subprocess -Wl,-rpath,. diff --git a/src/subprocess/Makefile-libcefpythonapp b/src/subprocess/Makefile-libcefpythonapp index 5264a9c5e..bd8186da7 100644 --- a/src/subprocess/Makefile-libcefpythonapp +++ b/src/subprocess/Makefile-libcefpythonapp @@ -9,28 +9,25 @@ # -Wl,-z,relro UNAME_S = $(shell uname -s) -CC = g++ -CCFLAGS = -fPIC -std=c++11 -Wall -Werror -DBROWSER_PROCESS \ - $(CEF_CCFLAGS) +CCFLAGS = -fPIC -DBROWSER_PROCESS $(CEF_CCFLAGS) ifeq ($(UNAME_S), Linux) - CPP_FILES = print_handler_gtk.cpp \ - main_message_loop/main_message_loop_external_pump_linux.cpp + SRC_MORE = print_handler_gtk.cpp \ + main_message_loop/main_message_loop_external_pump_linux.cpp else ifeq ($(UNAME_S), Darwin) - CPP_FILES = \ - main_message_loop/main_message_loop_external_pump_mac.mm -else - CPP_FILES = + SRC_MORE = main_message_loop/main_message_loop_external_pump_mac.mm endif - SRC = cefpython_app.cpp v8function_handler.cpp v8utils.cpp \ javascript_callback.cpp \ main_message_loop/main_message_loop.cpp \ main_message_loop/main_message_loop_std.cpp \ main_message_loop/main_message_loop_external_pump.cpp \ - $(CPP_FILES) -OBJ = $(SRC:.cpp=.o) + $(SRC_MORE) + +OBJ = $(filter %.o, $(SRC:.cpp=.o) $(SRC:.mm=.o)) +.SUFFIXES: .cpp .mm .o + OUT = libcefpythonapp.a INC = -I./../ -I./../common/ -I/usr/include/python2.7 \ @@ -54,10 +51,14 @@ INC = -I./../ -I./../common/ -I/usr/include/python2.7 \ -I/usr/lib/gtk-2.0/gtk-unix-print-2.0 \ -I/usr/lib/glib-2.0/include -.cpp.o: - @echo [CEFPYTHONAPP] Building $@ from $<... - $(CC) $(CCFLAGS) $(INC) -c $< -o $@ - $(OUT): $(OBJ) @echo [CEFPYTHONAPP] Creating library $(OUT) from $(OBJ)... ar rcs $(OUT) $(OBJ) + +.cpp.o: + @echo [CEFPYTHONAPP] Building $@ from $<... + $(CXX) $(CCFLAGS) $(INC) -c $< -o $@ + +.mm.o: + @echo [CEFPYTHONAPP] Building $@ from $<... + $(CXX) $(CCFLAGS) $(INC) -c $< -o $@ diff --git a/tools/build.py b/tools/build.py index 6fcbb5f46..3d070d251 100644 --- a/tools/build.py +++ b/tools/build.py @@ -63,12 +63,6 @@ REBUILD_CPP = False VERSION = "" -# Module extension -if WINDOWS: - MODULE_EXT = "pyd" -else: - MODULE_EXT = "so" - # First run FIRST_RUN = False CEFPYTHON_H = os.path.join(BUILD_CEFPYTHON, "cefpython.h") @@ -97,7 +91,6 @@ def main(): FIRST_RUN = True clear_cache() copy_and_fix_pyx_files() - create_version_pyx_file() build_cefpython_module() fix_cefpython_h() install_and_run() @@ -137,6 +130,20 @@ def setup_environ(): print("[build.py] environ AdditionalLibraryDirectories: {lib}" .format(lib=os.environ["AdditionalLibraryDirectories"])) + if LINUX or MAC: + # Used in makefiles + os.environ["CEF_CCFLAGS"] = "-std=gnu++11 -DNDEBUG -Wall -Werror" + if FAST_FLAG: + os.environ["CEF_CCFLAGS"] += " -O0" + else: + os.environ["CEF_CCFLAGS"] += " -O3" + os.environ["CEF_LINK_FLAGS"] = "" + + if LINUX: + # TODO: Set CEF_CCFLAGS and CEF_LINK_FLAGS according to what is + # in upstream cefclient, see cef/cmake/cef_variables.cmake. + pass + # Mac env variables for makefiles if MAC: os.environ["CEF_BIN"] = os.path.join(CEF_BINARIES_LIBRARIES, "bin") @@ -145,12 +152,42 @@ def setup_environ(): # Mac compiler options if MAC: os.environ["PATH"] = "/usr/local/bin:"+os.environ["PATH"] - os.environ["CC"] = "gcc" - os.environ["CXX"] = "g++" - os.environ["CEF_CCFLAGS"] = "-arch x86_64" - os.environ["ARCHFLAGS"] = "-arch x86_64" + os.environ["CC"] = "c++" + os.environ["CXX"] = "c++" + if ARCH32: raise Exception("Python 32-bit is not supported on Mac") + os.environ["ARCHFLAGS"] = "-arch x86_64" + os.environ["CEF_CCFLAGS"] += " -arch x86_64" + os.environ["CEF_LINK_FLAGS"] += " -mmacosx-version-min=10.7" + + # -Wno-return-type-c-linkage to ignore: + # > warning: 'somefunc' has C-linkage specified, but returns + # > user-defined type 'sometype' which is incompatible with C + os.environ["CEF_CCFLAGS"] += " -Wno-return-type-c-linkage" + + # Compile against libc++ otherwise error "symbol not found" + # with cef::logging::LogMessage symbol. Also include -lc++ + # and -lc++abi libraries. + os.environ["CEF_CCFLAGS"] += " -stdlib=libc++" + + # See compile/link flags in upstream cefclient + os.environ["CEF_CCFLAGS"] += ( + " -fno-strict-aliasing" + " -fno-rtti" + " -fno-threadsafe-statics" + " -fobjc-call-cxx-cdtors" + " -fvisibility=hidden" + " -fvisibility-inlines-hidden" + ) + os.environ["CEF_LINK_FLAGS"] += ( + " -lc++" + " -lc++abi" + " -Wl,-search_paths_first" + " -Wl,-ObjC" + " -Wl,-pie" + " -Wl,-dead_strip" + ) def get_python_path(): @@ -237,6 +274,13 @@ def check_directories(): def fix_cefpython_h(): + # Fix cefpython.h to disable this warning: + # > warning: 'somefunc' has C-linkage specified, but returns + # > user-defined type 'sometype' which is incompatible with C + # On Mac this warning must be disabled using -Wno-return-type-c-linkage + # flag in makefiles. + if MAC: + return os.chdir(BUILD_CEFPYTHON) print("[build.py] Fix cefpython.h to disable warnings") if not os.path.exists("cefpython.h"): @@ -244,10 +288,11 @@ def fix_cefpython_h(): return with open("cefpython.h", "r") as fo: contents = fo.read() - # Error/warning depending on compiler: - # > has C-linkage specified, but returns user-defined type - contents = contents.replace("#define __PYX_EXTERN_C extern \"C\"", - "#define __PYX_EXTERN_C extern") + pragma = "#pragma warning(disable:4190)" + if pragma in contents: + print("[build.py] cefpython.h is already fixed") + return + contents = ("%s\n\n" % pragma) + contents with open("cefpython.h", "w") as fo: fo.write(contents) print("[build.py] Save build_cefpython/cefpython.h") @@ -389,12 +434,14 @@ def clear_cache(): print("[build.py] Clean build cache") # Cache in CEFPYTHON_BINARY directory (eg. cefpython_linux64/) os.chdir(CEFPYTHON_BINARY) - delete_files_by_pattern("./cefpython_py*.{ext}".format(ext=MODULE_EXT)) + delete_files_by_pattern("./"+MODULE_NAME_TEMPLATE + .format(pyversion="*", ext=MODULE_EXT)) # Cache in build_cefpython/ directory os.chdir(BUILD_CEFPYTHON) - delete_files_by_pattern("./cefpython_py*.{ext}".format(ext=MODULE_EXT)) + delete_files_by_pattern("./"+MODULE_NAME_TEMPLATE + .format(pyversion="*", ext=MODULE_EXT)) delete_files_by_pattern("./*.pyx") try: @@ -451,7 +498,7 @@ def copy_and_fix_pyx_files(): os.remove(pyxfile) # Copying pyxfiles and reading its contents. - print("[build.py] Copying pyx files to build_cefpython/") + print("[build.py] Copy pyx files to build_cefpython/") # Copy cefpython.pyx and fix includes in cefpython.pyx, eg.: # include "handlers/focus_handler.pyx" becomes include "focus_handler.pyx" @@ -462,9 +509,12 @@ def copy_and_fix_pyx_files(): "include \"", content, flags=re.MULTILINE) + # Add __version__ variable in cefpython.pyx + print("[build.py] Add __version__ variable to %s" % mainfile) + content = ('__version__ = "{}"\n'.format(VERSION)) + content with open("./%s" % mainfile, "w") as fo: fo.write(content) - print("[build.py] %s includes fixed in %s" % (subs, mainfile)) + print("[build.py] Fix %s includes in %s" % (subs, mainfile)) # Copy the rest of the files print("[build.py] Fix includes in other .pyx files") @@ -533,13 +583,6 @@ def except_all_missing(content): return lineNumber -def create_version_pyx_file(): - os.chdir(BUILD_CEFPYTHON) - print("[build.py] Create __version__.pyx file") - with open("__version__.pyx", "w") as fo: - fo.write('__version__ = "{}"\n'.format(VERSION)) - - def build_cefpython_module(): # if DEBUG_FLAG: # ret = subprocess.call("python-dbg setup.py build_ext --inplace" @@ -595,12 +638,14 @@ def build_cefpython_module(): sys.exit(1) # Move the cefpython module - move_file_by_pattern("./cefpython_py{pyver}*.{ext}" - .format(pyver=PYVERSION, ext=MODULE_EXT), - os.path.join(CEFPYTHON_BINARY, - "cefpython_py{pyver}.{ext}" - .format(pyver=PYVERSION, - ext=MODULE_EXT))) + module_pattern = MODULE_NAME_TEMPLATE.format(pyversion=PYVERSION+"*", + ext=MODULE_EXT) + if MAC: + module_pattern = "./build/lib*/"+module_pattern + else: + module_pattern = "./"+module_pattern + move_file_by_pattern(module_pattern, os.path.join(CEFPYTHON_BINARY, + MODULE_NAME)) print("[build.py] DONE building the cefpython module") diff --git a/tools/build_module.py b/tools/build_module.py index e5c726681..f347bc875 100644 --- a/tools/build_module.py +++ b/tools/build_module.py @@ -18,17 +18,88 @@ # Use "Extension" from Cython.Distutils so that "cython_directives" works from Cython.Distutils import build_ext, Extension from Cython.Compiler import Options +# noinspection PyUnresolvedReferences +from Cython.Compiler.ModuleNode import ModuleNode from common import * import sys import platform import Cython import os +# Must monkey patch Cython's ModuleNode to inject custom C++ code +# in the generated cefpython.cpp. This is a fix for an error on Mac: +# > ImportError: dynamic module does not define init function +# To get rid of CEF's undefined symbol error when importing module +# it was required to pass "-fvisibility=hidden" and "-Wl,-dead_strip" +# flags. However these flags cause the "initcefpython_py27" Python +# Module Initialization function to be hidden as well. To workaround +# this it is required to add default visibility attribute to the +# signature of that init function. +# +# Original definition in Python 2.7: +# | https://github.com/python/cpython/blob/2.7/Include/pyport.h +# > define PyMODINIT_FUNC extern "C" __declspec(dllexport) void +# +# Original definition in Python 3.4 / 3.5 / 3.6: +# > define PyMODINIT_FUNC extern "C" __declspec(dllexport) PyObject* + +if MAC: + g_generate_extern_c_macro_definition_old = ( + ModuleNode.generate_extern_c_macro_definition) + + def generate_extern_c_macro_definition(self, code): + # This code is written to both cefpython.h and cefpython.cpp + g_generate_extern_c_macro_definition_old(self, code) + code.putln("// Added by: cefpython/tools/build_module.py") + code.putln("#undef PyMODINIT_FUNC") + if sys.version_info[:2] == (2, 7): + code.putln("#define PyMODINIT_FUNC extern \"C\"" + " __attribute__((visibility(\"default\"))) void") + else: + code.putln("#define PyMODINIT_FUNC extern \"C\"" + " __attribute__((visibility(\"default\"))) PyObject*") + # Overwrite Cython function + ModuleNode.generate_extern_c_macro_definition = ( + generate_extern_c_macro_definition) + + +# Constants +FAST_FLAG = False + # Cython options. Stop on first error, otherwise hundreds # of errors appear in the console. Options.fast_fail = True +def main(): + global FAST_FLAG + if len(sys.argv) > 1 and "--fast" in sys.argv: + # Fast mode disables optimization flags + print("[build_module.py] FAST mode On") + FAST_FLAG = True + sys.argv.remove("--fast") + + if len(sys.argv) <= 1: + print(__doc__) + sys.exit(1) + + print("[build_module.py] Cython version: %s" % Cython.__version__) + + compile_time_constants() + options = dict() + set_compiler_options(options) + options["include_dirs"] = get_include_dirs() + options["library_dirs"] = get_library_dirs() + options["libraries"] = get_libraries() + + print("[build_module.py] Execute setup()") + setup( + name='cefpython_py%s' % PYVERSION, + cmdclass={'build_ext': build_ext}, + ext_modules=get_ext_modules(options) + ) + + def get_winsdk_lib(): print("[build_module.py] Detect Windows SDK library directory") ret = "" @@ -80,12 +151,25 @@ def set_compiler_options(options): extra_compile_args.extend(["/EHsc"]) extra_link_args.extend(["/ignore:4217"]) + if LINUX or MAC: + # Compiler flags + if FAST_FLAG: + extra_compile_args.append("-O0") + else: + extra_compile_args.append("-O3") + + extra_compile_args.extend([ + "-DNDEBUG", + "-std=gnu++11", + ]) + if LINUX: - if len(sys.argv) > 1 and "--fast" in sys.argv: - sys.argv.remove("--fast") - # Fast mode disables optimization flags - print("[build_module.py] FAST mode On") - extra_compile_args.extend(["-flto", "-std=c++11"]) + os.environ["CC"] = "g++" + os.environ["CXX"] = "g++" + + if FAST_FLAG: + extra_compile_args.extend(["-flto", + "-std=gnu++11"]) extra_link_args.extend(["-flto"]) else: # Fix "ImportError ... undefined symbol ..." caused by CEF's @@ -93,15 +177,72 @@ def set_compiler_options(options): # Unfortunately -flto prolongs compilation time significantly. # More on the other flags: https://stackoverflow.com/questions/ # 6687630/ . - extra_compile_args.extend(["-flto", "-fdata-sections", - "-ffunction-sections", "-std=c++11"]) - extra_link_args.extend(["-flto", "-Wl,--gc-sections"]) + extra_compile_args.extend(["-flto", + "-fdata-sections", + "-ffunction-sections", + "-std=gnu++11"]) + extra_link_args.extend(["-flto", + "-Wl,--gc-sections"]) if MAC: - extra_compile_args.extend(["-std=c++11"]) - # extra_link_args.extend([]) - # os.environ["CC"] = "gcc" - # os.environ["CXX"] = "g++" + # Compiler environment variables + os.environ["CC"] = "c++" + os.environ["CXX"] = "c++" + + # COMPILER ARGS + + # -Wno-return-type-c-linkage to ignore: + # > warning: 'somefunc' has C-linkage specified, but returns + # > user-defined type 'sometype' which is incompatible with C + # + # -Wno-constant-logical-operand to ignore: + # > warning: use of logical '||' with constant operand + + extra_compile_args.extend([ + # Compile against libc++ otherwise error "symbol not found" + # with cef::logging::LogMessage symbol. Also include -lc++ + # and -lc++abi libraries. + "-stdlib=libc++", + "-Wno-return-type-c-linkage", + "-Wno-constant-logical-operand", + ]) + # From upstream CEF cefclient + extra_compile_args.extend([ + "-fno-strict-aliasing", + "-fno-rtti", + "-fno-threadsafe-statics", + "-fobjc-call-cxx-cdtors", + # Visibility of symbols: + "-fvisibility=hidden", + "-fvisibility-inlines-hidden", + ]) + # Visibility of symbols + extra_compile_args.extend([ + # "-flto", + # "-fdata-sections", + # "-ffunction-sections", + ]) + + # Build libcef_dll_wrapper: + # cmake -G "Ninja" -DPROJECT_ARCH="x86_64" + # -DCMAKE_CXX_FLAGS="-stdlib=libc++" + # -DCMAKE_BUILD_TYPE=Release .. + # ninja libcef_dll_wrapper + + # LINKER ARGS + extra_link_args.extend([ + "-mmacosx-version-min=10.7", + "-Wl,-search_paths_first", + "-F"+os.path.join(CEF_BINARIES_LIBRARIES, "bin"), + "-framework", "Chromium Embedded Framework", + "-Wl,-rpath,@loader_path", + ]) + if not FAST_FLAG: + extra_link_args.extend([ + # "-force_flat_namespace", + # "-flto", + "-Wl,-dead_strip", + ]) options["extra_compile_args"] = extra_compile_args options["extra_link_args"] = extra_link_args @@ -189,6 +330,8 @@ def get_library_dirs(): "Release_{os}" .format(os=OS_POSTFIX2)) ]) + if MAC: + library_dirs.append(os.path.join(CEF_BINARIES_LIBRARIES, "bin")) if MAC or LINUX: library_dirs.extend([ os.path.join(SRC_DIR, "client_handler"), @@ -215,10 +358,12 @@ def get_libraries(): ]) elif MAC: libraries.extend([ - 'client_handler', - 'cef_dll_wrapper', - 'cefpythonapp', - 'cpp_utils' + "c++", + "c++abi", + "cef_dll_wrapper", + "cefpythonapp", + "client_handler", + "cpp_utils", ]) elif LINUX: libraries.extend([ @@ -237,8 +382,8 @@ def get_libraries(): def get_ext_modules(options): ext_modules = [Extension( - "cefpython_py%s" % PYVERSION, - ["cefpython.pyx"], + name=MODULE_NAME_NOEXT, + sources=["cefpython.pyx"], # Ignore the warning in the console: # > C:\Python27\lib\distutils\extension.py:133: UserWarning: @@ -282,24 +427,5 @@ def compile_time_constants(): fd.write('DEF PY_MAJOR_VERSION = %s\n' % sys.version_info.major) -def main(): - if len(sys.argv) <= 1: - print(__doc__) - sys.exit(1) - print("[build_module.py] Cython version: %s" % Cython.__version__) - compile_time_constants() - options = dict() - set_compiler_options(options) - options["include_dirs"] = get_include_dirs() - options["library_dirs"] = get_library_dirs() - options["libraries"] = get_libraries() - print("[build_module.py] Execute setup()") - setup( - name='cefpython_py%s' % PYVERSION, - cmdclass={'build_ext': build_ext}, - ext_modules=get_ext_modules(options) - ) - - if __name__ == "__main__": main() diff --git a/tools/common.py b/tools/common.py index 9a5c5b617..bb1615532 100644 --- a/tools/common.py +++ b/tools/common.py @@ -29,6 +29,18 @@ # Python version eg. 27 PYVERSION = str(sys.version_info[0])+str(sys.version_info[1]) +# Module extension +if WINDOWS: + MODULE_EXT = "pyd" +else: + MODULE_EXT = "so" + +# CEF Python module name +MODULE_NAME_TEMPLATE = "cefpython_py{pyversion}.{ext}" +MODULE_NAME_TEMPLATE_NOEXT = "cefpython_py{pyversion}" +MODULE_NAME = MODULE_NAME_TEMPLATE.format(pyversion=PYVERSION, ext=MODULE_EXT) +MODULE_NAME_NOEXT = MODULE_NAME_TEMPLATE_NOEXT.format(pyversion=PYVERSION) + # Root directory assert __file__ ROOT_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) diff --git a/tools/installer/cefpython3.__init__.py b/tools/installer/cefpython3.__init__.py index 67ce48baa..3d821b894 100644 --- a/tools/installer/cefpython3.__init__.py +++ b/tools/installer/cefpython3.__init__.py @@ -26,42 +26,25 @@ package_dir = os.path.dirname(os.path.abspath(__file__)) # This loads the libcef.so library for the subprocess executable. +# On Mac it works without setting library paths. os.environ["LD_LIBRARY_PATH"] = package_dir -# On Mac it works without setting library paths. Better not set it, -# as maybe user's app will set it itself. -# > os.environ["DYLD_LIBRARY_PATH"] = package_dir -# > os.environ["DYLD_FRAMEWORK_PATH"] = package_dir - # This env variable will be returned by cefpython.GetModuleDirectory(). os.environ["CEFPYTHON3_PATH"] = package_dir # This loads the libcef library for the main python executable. -# This is required only on linux and Mac. +# Loading library dynamically using ctypes.CDLL is required on Linux. +# TODO: Check if on Linux libcef.so can be linked like on Mac. +# On Mac the CEF framework dependency information is added to +# the cefpython*.so module by linking to CEF framework. # The libffmpegsumo.so library does not need to be loaded here, # it may cause issues to load it here in the browser process. -libcef = None -if platform.system() == "Darwin": - cef_framework = "Chromium Embedded Framework.framework" - libcef_name = "Chromium Embedded Framework" - # Search for it in current directory or in ../Frameworks/ dir - # in case this is user's app packaged for distribution. - libcef1 = os.path.join(package_dir, cef_framework, libcef_name) - libcef2 = os.path.join(package_dir, "..", "Frameworks", cef_framework, - libcef_name) - if os.path.exists(libcef1): - libcef = libcef1 - elif os.path.exists(libcef2): - libcef = libcef2 - else: - raise Exception("Can't find: " + cef_framework) -elif platform.system() == "Linux": +if platform.system() == "Linux": libcef = os.path.join(package_dir, "libcef.so") -if libcef: ctypes.CDLL(libcef, ctypes.RTLD_GLOBAL) # Load the cefpython module for proper Python version -if sys.version_info[:2] == (2, 8): +if sys.version_info[:2] == (2, 7): # noinspection PyUnresolvedReferences from . import cefpython_py27 as cefpython elif sys.version_info[:2] == (3, 4): From 8ffac63c83ac8a8079f7268fc9e5fdcde7bca773 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 27 Feb 2017 20:47:53 +0100 Subject: [PATCH 139/557] Update to Chromium 56.0.2924.76 (#276)... CEF version 3.2924.1571.gcdcdfa9. Mac: deployment target 10.9+. Fix --fast flag in build.py. Add --clean flag in build.py - clean c++ projects files. --- api/ApplicationSettings.md | 18 ++++++++-- api/BrowserSettings.md | 5 --- src/extern/cef/cef_types.pxd | 2 +- src/include/cef_crash_util.h | 11 +++++- src/include/cef_response_filter.h | 44 ++++++++++++++--------- src/include/internal/cef_types.h | 23 +++++++----- src/include/internal/cef_types_wrappers.h | 1 - src/settings.pyx | 14 ++++---- src/version/cef_version_mac.h | 20 +++++------ tools/build.py | 26 ++++++++++++-- tools/build_module.py | 8 +---- 11 files changed, 110 insertions(+), 62 deletions(-) diff --git a/api/ApplicationSettings.md b/api/ApplicationSettings.md index fba94f943..db00f2f1a 100644 --- a/api/ApplicationSettings.md +++ b/api/ApplicationSettings.md @@ -102,8 +102,12 @@ in a known order. Equivalent to the `SkColor` type. (string) The path to a separate executable that will be launched for sub-processes. -By default the browser process executable is used. See the comments on -CefExecuteProcess() for details. Also configurable using the --browser-subprocess-path switch. +If this value is empty on Windows or Linux then the main process executable +will be used. If this value is empty on macOS then a helper executable must +exist at "Contents/Frameworks/ Helper.app/Contents/MacOS/ Helper" +in the top-level app bundle. See the comments on CefExecuteProcess() for +details. Also configurable using the "browser-subprocess-path" command-line +switch. ### cache_path @@ -177,6 +181,16 @@ Description from upstream CEF: > CefRunMessageLoop() function or multi_threaded_message_loop if possible. +### framework_dir_path + +The path to the CEF framework directory on macOS. If this value is empty +then the framework must exist at "Contents/Frameworks/Chromium Embedded +Framework.framework" in the top-level app bundle. Also configurable using +the "framework-dir-path" command-line switch. + +See also Issue #304. + + ### ignore_certificate_errors (bool) diff --git a/api/BrowserSettings.md b/api/BrowserSettings.md index 780aa1645..a5812fce9 100644 --- a/api/BrowserSettings.md +++ b/api/BrowserSettings.md @@ -85,11 +85,6 @@ of the specified value will be used. The alpha component must greater than 0 to enable use of the background color but will be otherwise ignored. -### caret_browsing_enabled - -(bool) Controls whether the caret position will be drawn. Also configurable using the --enable-caret-browsing switch. - - ### databases_disabled (bool) Controls whether databases can be used. Also configurable using the --disable-databases switch. diff --git a/src/extern/cef/cef_types.pxd b/src/extern/cef/cef_types.pxd index 1b2445210..a15e26f21 100644 --- a/src/extern/cef/cef_types.pxd +++ b/src/extern/cef/cef_types.pxd @@ -56,6 +56,7 @@ cdef extern from "include/internal/cef_types.h": int windowless_rendering_enabled int no_sandbox int external_message_pump + cef_string_t framework_dir_path ctypedef struct CefBrowserSettings: cef_string_t accept_language_list @@ -77,7 +78,6 @@ cdef extern from "include/internal/cef_types.h": cef_state_t javascript_close_windows cef_state_t javascript_access_clipboard cef_state_t javascript_dom_paste - cef_state_t caret_browsing cef_state_t plugins cef_state_t universal_access_from_file_urls cef_state_t file_access_from_file_urls diff --git a/src/include/cef_crash_util.h b/src/include/cef_crash_util.h index d74e792b0..d9ecfe351 100644 --- a/src/include/cef_crash_util.h +++ b/src/include/cef_crash_util.h @@ -54,6 +54,9 @@ // information; default to "CEF"> // ExternalHandler= +// BrowserCrashForwardingEnabled= // ServerURL= // RateLimitEnabled= // MaxUploadsPerDay= Helper.app/Contents/MacOS/ Helper" + // in the top-level app bundle. See the comments on CefExecuteProcess() for + // details. Also configurable using the "browser-subprocess-path" command-line + // switch. /// cef_string_t browser_subprocess_path; + /// + // The path to the CEF framework directory on macOS. If this value is empty + // then the framework must exist at "Contents/Frameworks/Chromium Embedded + // Framework.framework" in the top-level app bundle. Also configurable using + // the "framework-dir-path" command-line switch. + /// + cef_string_t framework_dir_path; + /// // Set to true (1) to have the browser process message loop run in a separate // thread. If false (0) than the CefDoMessageLoopWork() function must be @@ -563,12 +574,6 @@ typedef struct _cef_browser_settings_t { /// cef_state_t javascript_dom_paste; - /// - // Controls whether the caret position will be drawn. Also configurable using - // the "enable-caret-browsing" command-line switch. - /// - cef_state_t caret_browsing; - /// // Controls whether any plugins will be loaded. Also configurable using the // "disable-plugins" command-line switch. diff --git a/src/include/internal/cef_types_wrappers.h b/src/include/internal/cef_types_wrappers.h index e78771ecb..d393035ec 100644 --- a/src/include/internal/cef_types_wrappers.h +++ b/src/include/internal/cef_types_wrappers.h @@ -705,7 +705,6 @@ struct CefBrowserSettingsTraits { target->javascript_close_windows = src->javascript_close_windows; target->javascript_access_clipboard = src->javascript_access_clipboard; target->javascript_dom_paste = src->javascript_dom_paste; - target->caret_browsing = src->caret_browsing; target->plugins = src->plugins; target->universal_access_from_file_urls = src->universal_access_from_file_urls; diff --git a/src/settings.pyx b/src/settings.pyx index 6e35e845a..aefcc9727 100644 --- a/src/settings.pyx +++ b/src/settings.pyx @@ -119,6 +119,10 @@ cdef void SetApplicationSettings( elif key == "external_message_pump": cefAppSettings.external_message_pump = \ int(appSettings[key]) + elif key == "framework_dir_path": + cefString = new CefString(&cefAppSettings.framework_dir_path) + PyToCefStringPointer(appSettings[key], cefString) + del cefString else: raise Exception("Invalid appSettings key: %s" % key) @@ -214,14 +218,10 @@ cdef void SetBrowserSettings( cefBrowserSettings.javascript_dom_paste = ( cef_types.STATE_ENABLED) elif key == "caret_browsing_enabled": - if browserSettings[key]: - cefBrowserSettings.caret_browsing = ( - cef_types.STATE_ENABLED) - else: - cefBrowserSettings.caret_browsing = ( - cef_types.STATE_DISABLED) + # Keep the key for BC + Debug("DEPRECATED: 'caret_browsing_enabled' setting") elif key == "java_disabled": - # Keep for BC, just log info - no error + # Keep the key for BC Debug("DEPRECATED: 'java_disabled' setting") elif key == "plugins_disabled": if browserSettings[key]: diff --git a/src/version/cef_version_mac.h b/src/version/cef_version_mac.h index 3a20c3f43..21f8dd354 100644 --- a/src/version/cef_version_mac.h +++ b/src/version/cef_version_mac.h @@ -35,16 +35,16 @@ #ifndef CEF_INCLUDE_CEF_VERSION_H_ #define CEF_INCLUDE_CEF_VERSION_H_ -#define CEF_VERSION "3.2883.1553.g80bd606" +#define CEF_VERSION "3.2924.1571.gcdcdfa9" #define CEF_VERSION_MAJOR 3 -#define CEF_COMMIT_NUMBER 1553 -#define CEF_COMMIT_HASH "80bd6062d7ac4c5fd1d7bc7ee78e8e59d4a040aa" +#define CEF_COMMIT_NUMBER 1571 +#define CEF_COMMIT_HASH "cdcdfa99913a01f3617a0d25a2e2f2ed145987bd" #define COPYRIGHT_YEAR 2017 -#define CHROME_VERSION_MAJOR 55 +#define CHROME_VERSION_MAJOR 56 #define CHROME_VERSION_MINOR 0 -#define CHROME_VERSION_BUILD 2883 -#define CHROME_VERSION_PATCH 87 +#define CHROME_VERSION_BUILD 2924 +#define CHROME_VERSION_PATCH 76 #define DO_MAKE_STRING(p) #p #define MAKE_STRING(p) DO_MAKE_STRING(p) @@ -63,13 +63,13 @@ extern "C" { // universal hash value will change if any platform is affected whereas the // platform hash values will change only if that particular platform is // affected. -#define CEF_API_HASH_UNIVERSAL "87b7eefcb86c87b28f86bfd7919f7d7a6cffc0d8" +#define CEF_API_HASH_UNIVERSAL "66de193ba22e1d92a99bb29d60f3107709aeefda" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "00823905486d7b7222da5654fe35d2d15f65543a" +#define CEF_API_HASH_PLATFORM "8055740cd08db66cefe838a826dc90806fadfb33" #elif defined(OS_MACOSX) -#define CEF_API_HASH_PLATFORM "f0180f006643782254250f34e858b98110a40e6e" +#define CEF_API_HASH_PLATFORM "12d8ab423df369b68d37c3667123a1812bc0d345" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "14b19454a4231fa10a77b8955954dc95f073af6b" +#define CEF_API_HASH_PLATFORM "86ab23c0d7dafbdff7f66764cf8dac5ec1712af4" #endif // Returns CEF version information for the libcef library. The |entry| diff --git a/tools/build.py b/tools/build.py index 3d070d251..b881f3f2a 100644 --- a/tools/build.py +++ b/tools/build.py @@ -59,6 +59,7 @@ # Command line args variables DEBUG_FLAG = False FAST_FLAG = False +CLEAN_FLAG = False KIVY_FLAG = False REBUILD_CPP = False VERSION = "" @@ -74,10 +75,10 @@ def main(): sys.exit(1) print("[build.py] PYVERSION = %s" % PYVERSION) print("[build.py] OS_POSTFIX2 = %s" % OS_POSTFIX2) - setup_environ() - check_cython_version() command_line_args() + check_cython_version() check_directories() + setup_environ() if os.path.exists(CEFPYTHON_H): fix_cefpython_h() if WINDOWS: @@ -159,7 +160,7 @@ def setup_environ(): raise Exception("Python 32-bit is not supported on Mac") os.environ["ARCHFLAGS"] = "-arch x86_64" os.environ["CEF_CCFLAGS"] += " -arch x86_64" - os.environ["CEF_LINK_FLAGS"] += " -mmacosx-version-min=10.7" + os.environ["CEF_LINK_FLAGS"] += " -mmacosx-version-min=10.9" # -Wno-return-type-c-linkage to ignore: # > warning: 'somefunc' has C-linkage specified, but returns @@ -236,6 +237,10 @@ def command_line_args(): FAST_FLAG = True print("[build.py] FAST mode On") + # --clean flag + if len(sys.argv) > 1 and "--clean" in sys.argv: + CLEAN_FLAG = True + # --kivy flag if len(sys.argv) > 1 and "--kivy" in sys.argv: KIVY_FLAG = True @@ -372,8 +377,23 @@ def compile_ask_to_continue(): sys.exit(1) +def clean_cpp_projects_unix(): + delete_files_by_pattern("{0}/*.o".format(CLIENT_HANDLER_DIR)) + delete_files_by_pattern("{0}/*.a".format(CLIENT_HANDLER_DIR)) + + delete_files_by_pattern("{0}/*.o".format(SUBPROCESS_DIR)) + delete_files_by_pattern("{0}/*.a".format(SUBPROCESS_DIR)) + delete_files_by_pattern("{0}/subprocess".format(SUBPROCESS_DIR)) + + delete_files_by_pattern("{0}/*.o".format(CPP_UTILS_DIR)) + delete_files_by_pattern("{0}/*.a".format(CPP_UTILS_DIR)) + + def compile_cpp_projects_unix(): print("[build.py] Compile C++ projects") + if CLEAN_FLAG: + print("[build.py] Clean C++ projects (--clean flag passed)") + clean_cpp_projects_unix() # Need to allow continuing even when make fails, as it may # fail because the "public" function declaration is not yet diff --git a/tools/build_module.py b/tools/build_module.py index f347bc875..58d206014 100644 --- a/tools/build_module.py +++ b/tools/build_module.py @@ -223,15 +223,9 @@ def set_compiler_options(options): # "-ffunction-sections", ]) - # Build libcef_dll_wrapper: - # cmake -G "Ninja" -DPROJECT_ARCH="x86_64" - # -DCMAKE_CXX_FLAGS="-stdlib=libc++" - # -DCMAKE_BUILD_TYPE=Release .. - # ninja libcef_dll_wrapper - # LINKER ARGS extra_link_args.extend([ - "-mmacosx-version-min=10.7", + "-mmacosx-version-min=10.9", "-Wl,-search_paths_first", "-F"+os.path.join(CEF_BINARIES_LIBRARIES, "bin"), "-framework", "Chromium Embedded Framework", From 2fed32198fefe89ed9b67e442ec0f41364a56fce Mon Sep 17 00:00:00 2001 From: cztomczak Date: Tue, 28 Feb 2017 08:34:20 +0100 Subject: [PATCH 140/557] Rewrite whole README.md, make it brief and less confusing... Information on versions: v50+ vs v31. Add Support development section. Thanks to ClearChat Inc for sponsoring v55/56 releases. Also update TOCs in API docs. --- README.md | 188 +++++++++++++++---------------------- api/ApplicationSettings.md | 1 + api/BrowserSettings.md | 1 - 3 files changed, 77 insertions(+), 113 deletions(-) diff --git a/README.md b/README.md index 25d8956ca..ea188846b 100644 --- a/README.md +++ b/README.md @@ -1,132 +1,96 @@ # CEF Python -[![](https://img.shields.io/badge/python-2.7-yellow.png "Python versions supported")](https://github.com/cztomczak/cefpython#cef-python) -[![](https://img.shields.io/badge/release-v31.2-orange.png "GitHub latest release")](https://github.com/cztomczak/cefpython/releases/latest) -[![](https://img.shields.io/badge/pypi-v31.2-blue.png "PyPI latest release")](https://pypi.python.org/pypi/cefpython3/) -[![](https://img.shields.io/badge/commits%20since-v31.2-lightgray.png "Commits since v31.2 release")](https://github.com/cztomczak/cefpython/compare/05366f2...master) - Table of contents: -* [Important notes](#important-notes) * [Introduction](#introduction) -* [Compatibility](#compatibility) -* [Downloads](#downloads) +* [Information on versions](#information-on-versions) + * [v50+ releases](#v50-releases) + * [v31 release](#v31-release) * [Support](#support) -* [Notifications on new releases](#notifications-on-new-releases) -* [Changes in API during updates](#changes-in-api-during-updates) -* [Donate](#donate) - - -## Important notes - -* Branches cefpython51/52/53+ with latest Chrome are tested and work only - on Linux currently. Instructions for building these are - in docs/[Build-instructions.md](docs/Build-instructions.md). - Beta downloads are available on the [Github Releases](../../releases) page. - Pre-releases are also available on PyPI. -* The last stable release that works on all platforms is in the cefpython31 - branch. Downloads for this branch are available on wiki pages. Up-to-date - API docs for the cefpython31 branch can be viewed in commit - [169a1b2](https://github.com/cztomczak/cefpython/tree/169a1b20d3cd09879070d41aab28cfa195d2a7d5/docs/api). -* Repository rewritten on 2016-02-15 to reduce its size. Please clone it again. +* [Support development](#support-development) + * [Thanks](#thanks) ## Introduction -CEF Python is an open source project founded by -[Czarek Tomczak](http://www.linkedin.com/in/czarektomczak) -in 2012 to provide python bindings for the -[Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef). -See the growing list of -[applications using CEF](http://en.wikipedia.org/wiki/Chromium_Embedded_Framework#Applications_using_CEF) -on wikipedia. Examples of embedding CEF browser are available for many popular -GUI toolkits including: [wxPython](../../wiki/wxPython), -[PyGTK](../../wiki/PyGTK), [PyQt](../../wiki/PyQt), -[PySide](../../wiki/PySide), [Kivy](../../wiki/Kivy), -[Panda3D](../../wiki/Panda3D) -and [PyWin32](src/windows/binaries_32bit/pywin32.py). - -Some use cases for CEF: +CEF Python is an open source project founded by [Czarek Tomczak](http://www.linkedin.com/in/czarektomczak) +in 2012 to provide python bindings for the [Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef). +See the growing list of [applications using CEF](http://en.wikipedia.org/wiki/Chromium_Embedded_Framework#Applications_using_CEF) +on wikipedia. Examples of embedding CEF browser are available for many +popular GUI toolkits including: wxPython, PyGTK, PyQt, PySide, Kivy, +Panda3D, PyWin32 and PyGame/PyOpenGL. -* Embed a web browser control with great HTML5 support (based on Chromium) -* Use it to create a HTML5 based GUI in an application. This can act as a - replacement for GUI toolkits like wxWidgets/Qt/Gtk. For native communication - between javascript and python use - [javascript bindings](api/JavascriptBindings.md). - Another option is to run an internal python web server and use - websockets/XMLHttpRequest for js<>python communication. This way you - can write a desktop app in the same way you write web apps. -* Render web content off-screen in applications that use custom drawing - frameworks. See the [Kivy](../../wiki/Kivy) - and [Panda3D](../../wiki/Panda3D) examples. -* Use it for automated testing of existing web applications. Use it for web - scraping, or as a web crawler or other kind of internet bots. +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 like wxWidgets, Qt or GTK. You can render web +content off-screen in application that use custom drawing frameworks. +You can use it for automated testing of existing applications. You can +use it for web scraping or as a web crawler, or other kind of internet +bots. -## Compatibility +## Information on versions -* Supported Python versions: 2.7 - (for Python 3.4 / 3.5 support see [Issue #121](../../issues/121)). -* Supported platforms: Windows, Linux, Mac.
      - Both 32-bit and 64-bit binaries are available for all platforms. +### v50+ releases +1. Can be installed on all platforms using `pip install` command +2. Downloads are available on [GitHub Releases](../../releases) pages +2. Windows support: 32-bit, Python 2.7 +3. Linux support: 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 +4. Mac support: 64-bit, Python 2.7 +5. Documentation is in the [docs/](docs) directory +6. API reference is in the [api/](api) directory -## Downloads +### v31 release -On Win/Mac you can install from PyPI using this command: -`pip install cefpython3`. - -* For Windows: see the - [Download_CEF3_Windows](../../wiki/Download_CEF3_Windows) wiki page. -* For Linux: see the - [Download_CEF3_Linux](../../wiki/Download_CEF3_Linux) wiki page. -* For Mac: see the - [Download_CEF3_Mac](../../wiki/Download_CEF3_Mac) wiki page. - -To be notified when new downloads are available see the -[Notifications on new releases](#notifications-on-new-releases) section. +1. Downloads are available on [wiki pages](../../wiki#downloads) +2. Supports only Python 2.7 +3. Windows support: 32-bit and 64-bit +4. Linux support: 32-bit and 64-bit +5. Mac support: 32-bit and 64-bit +6. Documentation is on [wiki pages](../../wiki) +7. API reference is available in commit [169a1b2](../../tree/169a1b20d3cd09879070d41aab28cfa195d2a7d5/docs/api) ## Support -* Documentation: - * See [API docs](api/) in the api/ directory - * See [Wiki Pages](../../wiki) - * See issues with the - [Knowledge Base](../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) - label -* Ask questions and report problems on the - [Forum](https://groups.google.com/group/cefpython) -* Please do not ask questions in the Issue Tracker - - -## Notifications on new releases - -To be notified of new releases subscribe to this -[RSS/Atom feed](https://github.com/cztomczak/cefpython/releases.atom). - -Announcements are also made on the -[Forum](https://groups.google.com/d/forum/cefpython). -To be notified of these via email set your Membership and Email settings -and change delivery preference to Daily summaries. - - -## Changes in API during updates - -CEF Python depends on CEF and API breaks are inevitable when updating -to a newer CEF. When updating cefpython to a new version go to the -[GitHub Releases](https://github.com/cztomczak/cefpython/releases) page -and check release notes for all the releases that appeared between -your old version and the new version. Look for lists named -"Changes in API that break backward compatibility". - -Due to unavoidable changes in API it is recommended for your setup scripts -that use for example PIP to install the cefpython3 package, to hardcode -the cefpython version string. If for example using PIP's requirements.txt -file then list the cefpython3 package in the following format: -`cefpython3 == 31.2`. - - -## Donate - -If you would like to support general CEF Python development efforts by -making a donation see the [Donations](../../wiki/Donations) wiki page. +- Ask questions and report problems on the [Forum](https://groups.google.com/group/cefpython) +- Documentation is in the [docs/](docs) directory +- API reference is in the [api/](api) directory +- See issues labelled [Knowledge Base](../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) +- Wiki pages are deprecated and for v31 only + + +## Support development + +If you would like to support general CEF Python development efforts +by making a donation please click the Paypal Donate button: + + + +At this time CEF Python is unable to accept donations that sponsor the +development of specific features. However you can make a donation with +a comment that you would like to see some feature implemented and it will +give it a higher priority. + +If you are interested in sponsorship opportunities please contact Czarek +directly. + +### Thanks + +* Many thanks to [ClearChat Inc.](https://clearchat.com) for sponsoring + the v55/v56 releases for all platforms +* Thanks to JetBrains for providing an Open Source license for + [PyCharm](https://www.jetbrains.com/pycharm/) +* Thanks to those who have made a Paypal donation: [Rentouch GmbH](http://www.rentouch.ch/), + Walter Purvis, Rokas Stupuras, Alex Rattray, Greg Kacy, Paul Korzhyk +* Lots of thanks goes to [Cyan Inc.](http://www.blueplanet.com/) for + sponsoring this project for a long time, making CEF Python 3 mature +* Thanks to those who have donated their time through code contributions, + they are listed in the [Authors](Authors) file +* Thanks to Adam Duston for donating a Macbook to aid the development + of Mac port +* Thanks to [Rentouch GmbH](http://www.rentouch.ch/) for sponsoring the + development of the off-screen rendering support +* Thanks to Thomas Wusatiuk for sponsoring the development of the web + response reading features diff --git a/api/ApplicationSettings.md b/api/ApplicationSettings.md index db00f2f1a..628bac2ba 100644 --- a/api/ApplicationSettings.md +++ b/api/ApplicationSettings.md @@ -16,6 +16,7 @@ Table of contents: * [context_menu](#context_menu) * [downloads_enabled](#downloads_enabled) * [external_message_pump](#external_message_pump) + * [framework_dir_path](#framework_dir_path) * [ignore_certificate_errors](#ignore_certificate_errors) * [javascript_flags](#javascript_flags) * [locale](#locale) diff --git a/api/BrowserSettings.md b/api/BrowserSettings.md index a5812fce9..0cc2816d6 100644 --- a/api/BrowserSettings.md +++ b/api/BrowserSettings.md @@ -11,7 +11,6 @@ Table of contents: * [accept_language_list](#accept_language_list) * [application_cache_disabled](#application_cache_disabled) * [background_color](#background_color) - * [caret_browsing_enabled](#caret_browsing_enabled) * [databases_disabled](#databases_disabled) * [default_encoding](#default_encoding) * [dom_paste_disabled](#dom_paste_disabled) From def5e2ba20e844586ea25272ba38f93b07b51ec9 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Tue, 28 Feb 2017 09:19:38 +0100 Subject: [PATCH 141/557] Create docs/Knowledge-Base.md document --- docs/Knowledge-Base.md | 176 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 docs/Knowledge-Base.md diff --git a/docs/Knowledge-Base.md b/docs/Knowledge-Base.md new file mode 100644 index 000000000..3dd136bea --- /dev/null +++ b/docs/Knowledge-Base.md @@ -0,0 +1,176 @@ +# Knowledge Base + +Table of contents: +* [Notifications on new releases](#notifications-on-new-releases) +* [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) +* [Flash support](#flash-support) +* [Feature X works in Google Chrome, but doesn't work in CEF Python](#feature-x-works-in-google-chrome-but-doesnt-work-in-cef-python) +* [How to capture Audio and Video in HTML5?](#how-to-capture-audio-and-video-in-html5) +* [Touch and multi-touch support](#touch-and-multi-touch-support) +* [Black or white browser screen](#black-or-white-browser-screen) +* [Windows XP support](#windows-xp-support) +* [Mac 32-bit support](#mac-32-bit-support) +* [Security](#security) + + +## Notifications on new releases + +To be notified of new releases subscribe to this [RSS/Atom feed] +(../../../releases.atom). + +Announcements are also made on the [Forum] +(https://groups.google.com/d/forum/cefpython). +To be notified of these via email set your Membership and Email settings +and change delivery preference to Daily summaries. + + +## Changes in API after CEF updates + +CEF Python depends on CEF and API breaks are inevitable when updating +to latest CEF. The [Migration Guide](Migration-guide.md) document which +is still under works, will list most notable breaking changes since +v31 release. Until it's done go to go to the [GitHub Releases] +(../../../releases) page and check release notes for all the releases +that appeared between your old version and the new version. Look for +lists named "Changes in API that break backward compatibility" or +similar. + +Due to unavoidable changes in API it is recommended for your setup +scripts that use for example PIP to install the cefpython3 package, +to hardcode the cefpython version string. If for example using PIP's +requirements.txt file then list the cefpython3 package in the +following format: `cefpython3 == 31.2`. + + +## Differences between Python 2 and Python 3 + +In Python 2 all cefpython strings are byte strings, but in Python 3 +they are all unicode strings. Be aware of this when porting cefpython +based apps to Python 3, as it may cause issues. + + +## Flash support + +See [Issue #235](../../../issues/235) ("Flash support in CEF 51+"). + + +## Feature X works in Google Chrome, but doesn't work in CEF Python + +CEF Python embeds Chromium Embedded Framework (CEF) which is based +on Chromium browser. Functionality may differ a bit from Google Chrome. +The browser from Google is a proprietary software that for example +includes MPEG-4/H.264 codecs that aren't included in the open source +Chromium. CEF currently doesn't support Chrome Extensions, but basic +support for Chrome Extensions is being implemented in upstream CEF +as of now. + +To see if some feature is working or a bug is fixed in newer CEF +release perform the following steps: + +1. Download and install [CMake](https://cmake.org/download/) and + [Ninja](https://github.com/ninja-build/ninja/releases) +2. Go to [Spotify Automated Builds] + (http://opensource.spotify.com/cefbuilds/index.html) + and download latest CEF for your platform. Choose "Standard + Distribution" binaries. +3. Follow the instructions in `CMakeLists.txt` file +4. Run either cefclient or cefsimple to test features + + +## How to capture Audio and Video in HTML5? + +To be able to use the getUserMedia() function you need to set the +"enable-media-stream" switch. +See [api/Command line switches](../api/CommandLineSwitches.md) document. + + +## Touch and multi-touch support + +In CEF v47 or later touch device is auto-detected and everything should +work out of the box. If that's not the case try setting the following +switches: + +* --touch-events=enabled +* --enable-pinch + +See [api/Command line switches](../api/CommandLineSwitches.md) document. + + +## Black or white browser screen + +If you get a black or white screen in the browser view then this may +be caused by incompatible GPU (video card) drivers. There are following +solutions to this: + +1. When CEF Python is updated to a newer CEF/Chromium version then the +problem may be disappear. Check with latest Google Chrome if that is +the case. + +2. Try updating your video card drivers to the latest version available + +3. You can disable GPU hardware acceleration by adding the "disable-gpu" +and "disable-gpu-compositing" command line switches. See the +[api/Command Line Switches](../api/CommandLineSwitches.md). Note that +this will degrade performance if you're using any advanced 3D features. +It will affect 2D accelerated content as well. + +Note that when web page uses WebGL then the black screen may still +appear even after disabling GPU hardware acceleration. This is normal +because GPU was disabled so WebGL cannot work. + + +## Windows XP support + +CEF Python v31.2 was the last version to support Windows XP. This is +due to Chromium/CEF dropping XP support, last CEF version that +supported XP was v49. + +On XP you should disable GPU acceleration by using the --disable-gpu +and --disable-gpu-compositing switches. These switches must be passed +programmatically to cef.Initialize(), see [api/Command Line Switches] +(../api/CommandLineSwitches.md). + + +## Mac 32-bit support + +CEF Python v31.2 was the last version to support Mac 32-bit. +This is due to CEF/Chromium dropping 32-bit support, last CEF version +that supported 32-bit was v38. + + +## Security + +A quote by Marshall Greenblatt: + +> CEF offers significant integration capabilities beyond what +> is offered by a standard Google Chrome browser installation. +> The trade off for these additional capabilities is that +> organizations using CEF must take responsibility for their own +> application security. CEF and the underlying open source projects +> (Chromium, WebKit, etc) involve a significant amount of code and +> offer no warranties. Organizations should document and follow best +> practices to minimize potential security risks. Here are some +> recommended best practices that organizations can consider: +> - Only load known/trusted content. This is by far the best way +> to avoid potential security issues. +> - Disable plugins. This will avoid a large category of security +> issues caused by buggy versions of Flash, Java, etc. +> - Do not explicitly disable or bypass security features in your +> application. For example, do not enable CefBrowserSettings that +> bypass security features or add fake headers to bypass HTTP +> access control. +> - Keep your application up to date with the newest CEF release +> branch. You may want to update the underlying Chromium release +> version and perform your own builds to take immediate advantage +> of any bug fixes. +> - Enforce good programming practices. Every organization should +> have best practices for design, testing and verification. +> - Audit your application for potential security issues. Every +> decision that may have security consequences should be evaluated +> by people who are knowledgeable about security considerations. + +Reference: [Question on browser security] +(http://magpcss.org/ceforum/viewtopic.php?f=10&t=10222) +on the CEF Forum. + From b2861c05c61184a0e464312528e02d402d4ca140 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Tue, 28 Feb 2017 09:24:24 +0100 Subject: [PATCH 142/557] Update Build Instructions, move TOC to top --- docs/Build-instructions.md | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index 2ee531ae5..ded592c32 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -1,5 +1,25 @@ # Build instructions +Table of contents: +* [Preface](#preface) +* [Quick build instructions for Windows](#quick-build-instructions-for-windows) +* [Quick build instructions for Linux](#quick-build-instructions-for-linux) +* [Requirements](#requirements) + * [Windows](#windows) + * [Linux](#linux) + * [Mac](#mac) + * [All platforms](#all-platforms) +* [Build using prebuilt CEF binaries and libraries](#build-using-prebuilt-cef-binaries-and-libraries) +* [Build using CEF binaries from Spotify Automated Builds](#build-using-cef-binaries-from-spotify-automated-builds) +* [Build upstream CEF from sources](#build-upstream-cef-from-sources) +* [Build CEF manually](#build-cef-manually) +* [CEF Automated Builds (Spotify and Adobe)](#cef-automated-builds-spotify-and-adobe) +* [Notes](#notes) +* [How to patch mini tutorial](#how-to-patch-mini-tutorial) + + +## 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. @@ -25,23 +45,6 @@ Before you can build CEF Python or CEF you must satisfy [requirements](#requirements) listed on this page. -Table of contents: -* [Quick build instructions for Windows](#quick-build-instructions-for-windows) -* [Quick build instructions for Linux](#quick-build-instructions-for-linux) -* [Requirements](#requirements) - * [Windows](#windows) - * [Linux](#linux) - * [Mac](#mac) - * [All platforms](#all-platforms) -* [Build using prebuilt CEF binaries and libraries](#build-using-prebuilt-cef-binaries-and-libraries) -* [Build using CEF binaries from Spotify Automated Builds](#build-using-cef-binaries-from-spotify-automated-builds) -* [Build upstream CEF from sources](#build-upstream-cef-from-sources) -* [Build CEF manually](#build-cef-manually) -* [CEF Automated Builds (Spotify and Adobe)](#cef-automated-builds-spotify-and-adobe) -* [Notes](#notes) -* [How to patch mini tutorial](#how-to-patch-mini-tutorial) - - ## Quick build instructions for Windows Complete steps for building CEF Python v50+ using prebuilt binaries From da6bbeda1c26b41af8952e3f4000e4fa91422f73 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Tue, 28 Feb 2017 17:43:55 +0100 Subject: [PATCH 143/557] Fix Mac error: icudtl.dat not found in bundle (#304)... hello_world.py example runs fine on Mac! Add "Location of CEF framework in Mac apps" to Knowledge Base. Set ApplicationSettings.framework_dir_path when not set during a call to cef.Initialize(). Also set resources_dir_path. Fix rpath to "@loader_path/" so that libraries load correctly. Other fixes in build tools and in docs. --- api/API-index.md | 2 +- api/ApplicationSettings.md | 2 +- docs/Knowledge-Base.md | 42 ++++++++++++++ src/cefpython.pyx | 115 ++++++++++++++++++++++--------------- src/subprocess/Makefile | 2 +- tools/build.py | 9 ++- tools/build_module.py | 2 +- 7 files changed, 120 insertions(+), 54 deletions(-) diff --git a/api/API-index.md b/api/API-index.md index 94b887a9c..94fb0c726 100644 --- a/api/API-index.md +++ b/api/API-index.md @@ -12,6 +12,7 @@ * [context_menu](ApplicationSettings.md#context_menu) * [downloads_enabled](ApplicationSettings.md#downloads_enabled) * [external_message_pump](ApplicationSettings.md#external_message_pump) + * [framework_dir_path](ApplicationSettings.md#framework_dir_path) * [ignore_certificate_errors](ApplicationSettings.md#ignore_certificate_errors) * [javascript_flags](ApplicationSettings.md#javascript_flags) * [locale](ApplicationSettings.md#locale) @@ -113,7 +114,6 @@ * [accept_language_list](BrowserSettings.md#accept_language_list) * [application_cache_disabled](BrowserSettings.md#application_cache_disabled) * [background_color](BrowserSettings.md#background_color) - * [caret_browsing_enabled](BrowserSettings.md#caret_browsing_enabled) * [databases_disabled](BrowserSettings.md#databases_disabled) * [default_encoding](BrowserSettings.md#default_encoding) * [dom_paste_disabled](BrowserSettings.md#dom_paste_disabled) diff --git a/api/ApplicationSettings.md b/api/ApplicationSettings.md index 628bac2ba..881de7a15 100644 --- a/api/ApplicationSettings.md +++ b/api/ApplicationSettings.md @@ -189,7 +189,7 @@ then the framework must exist at "Contents/Frameworks/Chromium Embedded Framework.framework" in the top-level app bundle. Also configurable using the "framework-dir-path" command-line switch. -See also Issue #304. +See also [Issue #304](../../../issues/304). ### ignore_certificate_errors diff --git a/docs/Knowledge-Base.md b/docs/Knowledge-Base.md index 3dd136bea..0904afd09 100644 --- a/docs/Knowledge-Base.md +++ b/docs/Knowledge-Base.md @@ -50,6 +50,48 @@ they are all unicode strings. Be aware of this when porting cefpython based apps to Python 3, as it may cause issues. +## Location of CEF framework in Mac apps + +This information here is for when creating apps for distribution +on Mac. + +By default CEF expects that CEF framework is located at +`Contents/Frameworks/Chromium Embedded Framework.framework` +in the top-level app bundle. If that is not the case then you have +to set ApplicationSettings.[framework_dir_path] +(../api/ApplicationSettings.md#framework_dir_path) before calling +cef.Initialize(). + +You may also need to change the structure and embedded paths in +CEF framework and in the cefpython module. Here are the default +settings: +``` +cefpython_package/ + cefpython_py27.so + rpath=@loader_path + load:@rpath/Chromium Embedded Framework.framework/Chromium Embedded Framework + Chromium Embedded Framework.framework/ + Chromium Embedded Framework + id:@rpath/Chromium Embedded Framework.framework/Chromium Embedded Framework +``` + +When creating Mac app for distribution you may want to change +directory structure, so you might have to change these settings +embedded in these libraries. You can do so with these commands: + +``` +install_name_tool -rpath old new +install_name_tool -change old new +install_name_tool -id name +``` + +To check whether it succeeded run these commands: +``` +otool -l file +otool -L file +``` + + ## Flash support See [Issue #235](../../../issues/235) ("Flash support in CEF 51+"). diff --git a/src/cefpython.pyx b/src/cefpython.pyx index 9d641ebed..18509259c 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -577,12 +577,18 @@ cdef public int CommandLineSwitches_GetInt(const char* key) except * with gil: # is called. See Issue #73 in the CEF Python Issue Tracker. def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): + # applicationSettings and commandLineSwitches argument + # names are kept for backward compatibility. + application_settings = applicationSettings + command_line_switches = commandLineSwitches # Alternative names for existing parameters if "settings" in kwargs: - applicationSettings = kwargs["settings"] + assert not applicationSettings, "Bad arguments" + application_settings = kwargs["settings"] if "switches" in kwargs: - commandLineSwitches = kwargs["switches"] + assert not command_line_switches, "Bad arguments" + command_line_switches = kwargs["switches"] IF UNAME_SYSNAME == "Linux": # Fix Issue #231 - Discovery of the "icudtl.dat" file fails on Linux. @@ -595,16 +601,17 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): or Debug("ERROR: CefOverridePath failed") # END IF UNAME_SYSNAME == "Linux": - if not applicationSettings: - applicationSettings = {} + if not application_settings: + application_settings = {} + # 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 applicationSettings: - g_debug = bool(applicationSettings["debug"]) - if "log_file" in applicationSettings: - g_debugFile = applicationSettings["log_file"] + if "debug" in application_settings: + g_debug = bool(application_settings["debug"]) + if "log_file" in application_settings: + g_debugFile = application_settings["log_file"] Debug("Initialize() called") @@ -617,65 +624,79 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): # ------------------------------------------------------------------------- # CEF Python only options - default values - if "debug" not in applicationSettings: - applicationSettings["debug"] = False - if "log_severity" not in applicationSettings: + if "debug" not in application_settings: + application_settings["debug"] = False + if "log_severity" not in application_settings: # By default show only errors. Don't show on Linux X server non-fatal # errors like "WARNING:x11_util.cc(1409)] X error received". - applicationSettings["log_severity"] = LOGSEVERITY_ERROR - if "string_encoding" not in applicationSettings: - applicationSettings["string_encoding"] = "utf-8" - if "unique_request_context_per_browser" not in applicationSettings: - applicationSettings["unique_request_context_per_browser"] = False - if "downloads_enabled" not in applicationSettings: - applicationSettings["downloads_enabled"] = True - if "remote_debugging_port" not in applicationSettings: - applicationSettings["remote_debugging_port"] = 0 - if "auto_zooming" not in applicationSettings: + application_settings["log_severity"] = LOGSEVERITY_ERROR + if "string_encoding" not in application_settings: + application_settings["string_encoding"] = "utf-8" + if "unique_request_context_per_browser" not in application_settings: + application_settings["unique_request_context_per_browser"] = False + if "downloads_enabled" not in application_settings: + application_settings["downloads_enabled"] = True + if "remote_debugging_port" not in application_settings: + application_settings["remote_debugging_port"] = 0 + if "auto_zooming" not in application_settings: IF UNAME_SYSNAME == "Windows": if DpiAware.IsProcessDpiAware(): - applicationSettings["auto_zooming"] = "system_dpi" + application_settings["auto_zooming"] = "system_dpi" # Paths cdef str module_dir = GetModuleDirectory() - if "locales_dir_path" not in applicationSettings: + if platform.system() == "Darwin": + if "framework_dir_path" not in application_settings: + application_settings["framework_dir_path"] = os.path.join( + module_dir, "Chromium Embedded Framework.framework") + # Bug in CEF: CefSettings.framework_dir_path doesn't work. + # Can be worked around by setting command line switch. + if not command_line_switches: + command_line_switches = {} + if "framework-dir-path" not in command_line_switches: + command_line_switches["framework-dir-path"] = \ + application_settings["framework_dir_path"] + if "locales_dir_path" not in application_settings: if platform.system() != "Darwin": - applicationSettings["locales_dir_path"] = os.path.join( + application_settings["locales_dir_path"] = os.path.join( module_dir, "locales") - if "resources_dir_path" not in applicationSettings: - applicationSettings["resources_dir_path"] = module_dir + if "resources_dir_path" not in application_settings: + application_settings["resources_dir_path"] = module_dir if platform.system() == "Darwin": - pass # TODO: Check if this needs to be set in v56+ - if "browser_subprocess_path" not in applicationSettings: - applicationSettings["browser_subprocess_path"] = os.path.join( + # "framework_dir_path" will always be set, see code above. + application_settings["resources_dir_path"] = os.path.join( + application_settings["framework_dir_path"], + "Resources") + if "browser_subprocess_path" not in application_settings: + application_settings["browser_subprocess_path"] = os.path.join( module_dir, "subprocess") # Mouse context menu - if "context_menu" not in applicationSettings: - applicationSettings["context_menu"] = {} + if "context_menu" not in application_settings: + application_settings["context_menu"] = {} menuItems = ["enabled", "navigation", "print", "view_source", "external_browser", "devtools"] for item in menuItems: - if item not in applicationSettings["context_menu"]: - applicationSettings["context_menu"][item] = True + if item not in application_settings["context_menu"]: + application_settings["context_menu"][item] = True # Remote debugging port. If value is 0 we will generate a random # port. To disable remote debugging set value to -1. - if applicationSettings["remote_debugging_port"] == 0: + if application_settings["remote_debugging_port"] == 0: # Generate a random port. - applicationSettings["remote_debugging_port"] =\ + application_settings["remote_debugging_port"] =\ random.randint(49152, 65535) - elif applicationSettings["remote_debugging_port"] == -1: + elif application_settings["remote_debugging_port"] == -1: # Disable remote debugging - applicationSettings["remote_debugging_port"] = 0 + application_settings["remote_debugging_port"] = 0 # ------------------------------------------------------------------------- # CEF options - default values. - if not "multi_threaded_message_loop" in applicationSettings: - applicationSettings["multi_threaded_message_loop"] = False - if not "single_process" in applicationSettings: - applicationSettings["single_process"] = False + if not "multi_threaded_message_loop" in application_settings: + application_settings["multi_threaded_message_loop"] = False + if not "single_process" in application_settings: + application_settings["single_process"] = False cdef CefRefPtr[CefApp] cefApp = new CefPythonApp() @@ -698,21 +719,21 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): # Make a copy as applicationSettings is a reference only # that might get destroyed later. global g_applicationSettings - for key in applicationSettings: - g_applicationSettings[key] = copy.deepcopy(applicationSettings[key]) + for key in application_settings: + g_applicationSettings[key] = copy.deepcopy(application_settings[key]) cdef CefSettings cefApplicationSettings # No sandboxing for the subprocesses cefApplicationSettings.no_sandbox = 1 - SetApplicationSettings(applicationSettings, &cefApplicationSettings) + SetApplicationSettings(application_settings, &cefApplicationSettings) - if commandLineSwitches: + if command_line_switches: # Make a copy as commandLineSwitches is a reference only # that might get destroyed later. global g_commandLineSwitches - for key in commandLineSwitches: + for key in command_line_switches: g_commandLineSwitches[key] = copy.deepcopy( - commandLineSwitches[key]) + command_line_switches[key]) # External message pump if GetAppSetting("external_message_pump")\ diff --git a/src/subprocess/Makefile b/src/subprocess/Makefile index c4d73a5b2..1ed3b15c1 100644 --- a/src/subprocess/Makefile +++ b/src/subprocess/Makefile @@ -55,4 +55,4 @@ subprocess: $(CPP_FILES) \ $(CEF_LINK_FLAGS) \ $(LIBS) -lcef_dll_wrapper \ - -o subprocess -Wl,-rpath,. + -o subprocess -Wl,-rpath,@loader_path/ diff --git a/tools/build.py b/tools/build.py index b881f3f2a..aa10d2d6d 100644 --- a/tools/build.py +++ b/tools/build.py @@ -17,12 +17,13 @@ from sources or use ready binaries from Spotify Automated Builds. Usage: - build.py VERSION [--rebuild-cpp] [--fast] [--kivy] + build.py VERSION [--rebuild-cpp] [--fast] [--clean] [--kivy] Options: VERSION Version in format xx.xx --rebuild-cpp Force rebuild of C++ projects --fast Fast mode + --clean Clean C++ projects build files (.o .a etc) --kivy Run only Kivy example """ @@ -221,7 +222,8 @@ def check_cython_version(): def command_line_args(): - global DEBUG_FLAG, FAST_FLAG, KIVY_FLAG, REBUILD_CPP, VERSION + global DEBUG_FLAG, FAST_FLAG, CLEAN_FLAG, KIVY_FLAG,\ + REBUILD_CPP, VERSION print("[build.py] Parse command line arguments") @@ -393,7 +395,7 @@ def compile_cpp_projects_unix(): print("[build.py] Compile C++ projects") if CLEAN_FLAG: print("[build.py] Clean C++ projects (--clean flag passed)") - clean_cpp_projects_unix() + clean_cpp_projects_unix() # Need to allow continuing even when make fails, as it may # fail because the "public" function declaration is not yet @@ -686,6 +688,7 @@ def delete_files_by_pattern(pattern): files = glob.glob(pattern) for f in files: os.remove(f) + print("[build.py] Removed {0} files".format(len(files))) def delete_directories_by_pattern(pattern): diff --git a/tools/build_module.py b/tools/build_module.py index 58d206014..7beda34f4 100644 --- a/tools/build_module.py +++ b/tools/build_module.py @@ -229,7 +229,7 @@ def set_compiler_options(options): "-Wl,-search_paths_first", "-F"+os.path.join(CEF_BINARIES_LIBRARIES, "bin"), "-framework", "Chromium Embedded Framework", - "-Wl,-rpath,@loader_path", + "-Wl,-rpath,@loader_path/", # ending slash is crucial! ]) if not FAST_FLAG: extra_link_args.extend([ From 7d42d997fc1a199d654a79e1c01107bdb3b5f618 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 1 Mar 2017 08:34:50 +0100 Subject: [PATCH 144/557] Update README, minor fixes --- README.md | 34 +++++++++++++++++++++++----------- docs/Knowledge-Base.md | 1 + 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index ea188846b..1b914f627 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Table of contents: * [Introduction](#introduction) -* [Information on versions](#information-on-versions) +* [Versions](#versions) * [v50+ releases](#v50-releases) * [v31 release](#v31-release) * [Support](#support) @@ -12,9 +12,12 @@ Table of contents: ## Introduction -CEF Python is an open source project founded by [Czarek Tomczak](http://www.linkedin.com/in/czarektomczak) -in 2012 to provide python bindings for the [Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef). -See the growing list of [applications using CEF](http://en.wikipedia.org/wiki/Chromium_Embedded_Framework#Applications_using_CEF) +CEF Python is an open source project founded by [Czarek Tomczak] +(http://www.linkedin.com/in/czarektomczak) +in 2012 to provide python bindings for the [Chromium Embedded Framework] +(https://bitbucket.org/chromiumembedded/cef). +See the growing list of [applications using CEF] +(http://en.wikipedia.org/wiki/Chromium_Embedded_Framework#Applications_using_CEF) on wikipedia. Examples of embedding CEF browser are available for many popular GUI toolkits including: wxPython, PyGTK, PyQt, PySide, Kivy, Panda3D, PyWin32 and PyGame/PyOpenGL. @@ -29,7 +32,7 @@ use it for web scraping or as a web crawler, or other kind of internet bots. -## Information on versions +## Versions ### v50+ releases @@ -40,24 +43,30 @@ bots. 4. Mac support: 64-bit, Python 2.7 5. Documentation is in the [docs/](docs) directory 6. API reference is in the [api/](api) directory +7. Additional documentation is in issues labelled [Knowledge Base] + (../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) ### v31 release 1. Downloads are available on [wiki pages](../../wiki#downloads) + and on GH Releases tagged [v31.2](../../releases/tag/v31.2) 2. Supports only Python 2.7 3. Windows support: 32-bit and 64-bit 4. Linux support: 32-bit and 64-bit 5. Mac support: 32-bit and 64-bit 6. Documentation is on [wiki pages](../../wiki) -7. API reference is available in commit [169a1b2](../../tree/169a1b20d3cd09879070d41aab28cfa195d2a7d5/docs/api) +7. API reference is available in revision [169a1b2] + (../../tree/169a1b20d3cd09879070d41aab28cfa195d2a7d5/docs/api) ## Support -- Ask questions and report problems on the [Forum](https://groups.google.com/group/cefpython) +- Ask questions and report problems on the [Forum] + (https://groups.google.com/group/cefpython) - Documentation is in the [docs/](docs) directory - API reference is in the [api/](api) directory -- See issues labelled [Knowledge Base](../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) +- Additional documentation is in issues labelled [Knowledge Base] + (../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) - Wiki pages are deprecated and for v31 only @@ -66,7 +75,9 @@ bots. If you would like to support general CEF Python development efforts by making a donation please click the Paypal Donate button: - + + + At this time CEF Python is unable to accept donations that sponsor the development of specific features. However you can make a donation with @@ -82,8 +93,9 @@ directly. the v55/v56 releases for all platforms * Thanks to JetBrains for providing an Open Source license for [PyCharm](https://www.jetbrains.com/pycharm/) -* Thanks to those who have made a Paypal donation: [Rentouch GmbH](http://www.rentouch.ch/), - Walter Purvis, Rokas Stupuras, Alex Rattray, Greg Kacy, Paul Korzhyk +* Thanks to those who have made a Paypal donation: [Rentouch GmbH] + (http://www.rentouch.ch/), Walter Purvis, Rokas Stupuras, Alex Rattray, + Greg Kacy, Paul Korzhyk * Lots of thanks goes to [Cyan Inc.](http://www.blueplanet.com/) for sponsoring this project for a long time, making CEF Python 3 mature * Thanks to those who have donated their time through code contributions, diff --git a/docs/Knowledge-Base.md b/docs/Knowledge-Base.md index 0904afd09..591b98376 100644 --- a/docs/Knowledge-Base.md +++ b/docs/Knowledge-Base.md @@ -4,6 +4,7 @@ Table of contents: * [Notifications on new releases](#notifications-on-new-releases) * [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) * [Flash support](#flash-support) * [Feature X works in Google Chrome, but doesn't work in CEF Python](#feature-x-works-in-google-chrome-but-doesnt-work-in-cef-python) * [How to capture Audio and Video in HTML5?](#how-to-capture-audio-and-video-in-html5) From de7664106484827c07ac9f81e14e5d28a9be8bb5 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 1 Mar 2017 10:11:21 +0100 Subject: [PATCH 145/557] Fix wxpython.py example on Mac (#295) --- examples/wxpython.py | 99 +++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 48 deletions(-) diff --git a/examples/wxpython.py b/examples/wxpython.py index 226642c2d..e2eee5572 100644 --- a/examples/wxpython.py +++ b/examples/wxpython.py @@ -4,8 +4,8 @@ # To install wxPython on Linux type "sudo apt-get install python-wxtools". # Tested configurations: +# - wxPython 3.0 on Windows/Mac # - wxPython 2.8 on Linux -# - wxPython 3.0 on Windows # - CEF Python v55.4+ import wx @@ -26,6 +26,9 @@ WIDTH = 800 HEIGHT = 600 +# Globals +g_count_windows = 0 + def main(): check_versions() @@ -34,15 +37,15 @@ def main(): if WINDOWS: # High DPI support settings["auto_zooming"] = "system_dpi" - # Embed DPI awareness xml manifest inside .exe (recommended, - # most reliable) or call the SetProcessDpiAware function. # noinspection PyUnresolvedReferences, PyArgumentList - cef.DpiAware.SetProcessDpiAware() + cef.DpiAware.SetProcessDpiAware() # Alternative is to embed manifest cef.Initialize(settings=settings) app = CefApp(False) app.MainLoop() del app # Must destroy before calling Shutdown - cef.Shutdown() + if not MAC: + # On Mac shutdown is called in OnClose + cef.Shutdown() def check_versions(): @@ -60,6 +63,9 @@ def __init__(self): title='wxPython example', size=(WIDTH, HEIGHT)) self.browser = None + global g_count_windows + g_count_windows += 1 + self.setup_icon() self.create_menu() self.Bind(wx.EVT_CLOSE, self.OnClose) @@ -70,9 +76,14 @@ def __init__(self): self.browser_panel.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) self.browser_panel.Bind(wx.EVT_SIZE, self.OnSize) - # Must show so that handle is available when embedding browser - self.Show() - self.embed_browser() + # On Linux must show before embedding browser, so that handle + # is available. + if LINUX: + self.Show() + self.embed_browser() + else: + self.embed_browser() + self.Show() def setup_icon(self): icon_file = os.path.join(os.path.abspath(os.path.dirname(__file__)), @@ -85,16 +96,15 @@ def create_menu(self): filemenu = wx.Menu() filemenu.Append(1, "Some option") filemenu.Append(2, "Another option") - aboutmenu = wx.Menu() - aboutmenu.Append(1, "Yet another option") menubar = wx.MenuBar() menubar.Append(filemenu, "&File") - menubar.Append(aboutmenu, "&About") self.SetMenuBar(menubar) def embed_browser(self): window_info = cef.WindowInfo() - window_info.SetAsChild(self.browser_panel.GetHandle()) + (width, height) = self.browser_panel.GetClientSizeTuple() + window_info.SetAsChild(self.browser_panel.GetHandle(), + [0, 0, width, height]) self.browser = cef.CreateBrowserSync(window_info, url="https://www.google.com/") self.browser.SetClientHandler(FocusHandler()) @@ -120,49 +130,42 @@ def OnSize(self, _): self.browser.NotifyMoveOrResizeStarted() def OnClose(self, event): - # In cefpython3.wx.chromectrl example calling browser.CloseBrowser() - # and/or self.Destroy() in OnClose is causing crashes when - # embedding multiple browser tabs. The solution is to call only - # browser.ParentWindowWillClose. Behavior of this example - # seems different as it extends wx.Frame, while ChromeWindow - # from chromectrl extends wx.Window. Calling CloseBrowser - # and Destroy does not cause crashes, but is not recommended. - # Call ParentWindowWillClose and event.Skip() instead. See - # also Issue #107: https://github.com/cztomczak/cefpython/issues/107 - self.browser.ParentWindowWillClose() - event.Skip() - - # Clear all browser references for CEF to shutdown cleanly - del self.browser - - -class FocusHandler(object): + print("[wxpython.py] OnClose called") + if not self.browser: + # May already be closing, may be called multiple times on Mac + return - def __init__(self): - pass + if MAC: + # On Mac things work differently, other steps are required + self.browser.CloseBrowser() + self.clear_browser_references() + self.Destroy() + global g_count_windows + g_count_windows -= 1 + if g_count_windows == 0: + cef.Shutdown() + wx.GetApp().Exit() + else: + # Calling browser.CloseBrowser() and/or self.Destroy() + # in OnClose may cause app crash on some paltforms in + # some use cases, details in Issue #107. + self.browser.ParentWindowWillClose() + event.Skip() + self.clear_browser_references() + + def clear_browser_references(self): + # Clear browser references that you keep anywhere in your + # code. All references must be cleared for CEF to shutdown cleanly. + self.browser = None - def OnTakeFocus(self, **kwargs): - # print("[wxpython.py] FocusHandler.OnTakeFocus, next={next}" - # .format(next=kwargs["next_component"]])) - pass - def OnSetFocus(self, **kwargs): - # source_enum = {cef.FOCUS_SOURCE_NAVIGATION: "navigation", - # cef.FOCUS_SOURCE_SYSTEM: "system"} - # print("[wxpython.py] FocusHandler.OnSetFocus, source={source}" - # .format(source=source_enum[kwargs["source"]])) - # return False - pass +class FocusHandler(object): def OnGotFocus(self, browser, **_): # Temporary fix for focus issues on Linux (Issue #284). - # If this is not applied then when switching to another - # window (alt+tab) and then back to this example, keyboard - # focus becomes broken, you can't type anything, even - # though a type cursor blinks in web view. if LINUX: print("[wxpython.py] FocusHandler.OnGotFocus:" - " keyboard focus fix (#284)") + " keyboard focus fix (Issue #284)") browser.SetFocus(True) @@ -185,7 +188,7 @@ 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.timer.Start(10) # 10ms + self.timer.Start(10) # 10ms timer wx.EVT_TIMER(self, self.timer_id, self.on_timer) def on_timer(self, _): From e906a98f62b0d91aef11f2122f765d4615753482 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 1 Mar 2017 13:01:10 +0100 Subject: [PATCH 146/557] Fix Mac wxpython example exiting with error code 255 (#162)... Add comment about tkinter_.py example not working on Mac. Delete deprecated Mac examples. --- examples/tkinter_.py | 9 +- examples/wxpython.py | 6 +- src/mac/deprecated_64bit/prism.css | 130 ---- src/mac/deprecated_64bit/prism.js | 5 - src/mac/deprecated_64bit/wxpython.html | 708 -------------------- src/mac/deprecated_64bit/wxpython.py | 851 ------------------------- 6 files changed, 10 insertions(+), 1699 deletions(-) delete mode 100644 src/mac/deprecated_64bit/prism.css delete mode 100644 src/mac/deprecated_64bit/prism.js delete mode 100644 src/mac/deprecated_64bit/wxpython.html delete mode 100644 src/mac/deprecated_64bit/wxpython.py diff --git a/examples/tkinter_.py b/examples/tkinter_.py index dc5abf246..aed1279ce 100644 --- a/examples/tkinter_.py +++ b/examples/tkinter_.py @@ -1,9 +1,12 @@ # Example of embedding CEF Python browser using Tkinter toolkit. # This example has two widgets: a navigation bar and a browser. # +# NOTE: This example doesn't work on Mac, details in Issue #306. +# # Tested configurations: -# - Tk 8.6 and CEF Python v55.3+ on Linux -# - Tk 8.5 and CEF Python v55.4+ on Windows +# - Tk 8.5 on Windows +# - Tk 8.6 on Linux +# - CEF Python v55.3+ # # Known issue on Linux: When typing url, mouse must be over url # entry widget otherwise keyboard focus is lost (Issue #255 @@ -41,7 +44,7 @@ def main(): logger.addHandler(stream_handler) logger.info("CEF Python {ver}".format(ver=cef.__version__)) logger.info("Python {ver}".format(ver=sys.version[:6])) - logger.info("Tk {ver}".format(ver=tk.TkVersion)) + logger.info("Tk {ver}".format(ver=tk.Tcl().eval('info patchlevel'))) assert cef.__version__ >= "55.3", "CEF Python v55.3+ required to run this" sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error cef.Initialize() diff --git a/examples/wxpython.py b/examples/wxpython.py index e2eee5572..e36da5494 100644 --- a/examples/wxpython.py +++ b/examples/wxpython.py @@ -144,7 +144,10 @@ def OnClose(self, event): g_count_windows -= 1 if g_count_windows == 0: cef.Shutdown() - wx.GetApp().Exit() + wx.GetApp().ExitMainLoop() + # Call _exit otherwise app exits with code 255 (Issue #162). + # noinspection PyProtectedMember + os._exit(0) else: # Calling browser.CloseBrowser() and/or self.Destroy() # in OnClose may cause app crash on some paltforms in @@ -160,7 +163,6 @@ def clear_browser_references(self): class FocusHandler(object): - def OnGotFocus(self, browser, **_): # Temporary fix for focus issues on Linux (Issue #284). if LINUX: diff --git a/src/mac/deprecated_64bit/prism.css b/src/mac/deprecated_64bit/prism.css deleted file mode 100644 index f94cca7c0..000000000 --- a/src/mac/deprecated_64bit/prism.css +++ /dev/null @@ -1,130 +0,0 @@ -/* http://prismjs.com/download.html?themes=prism&languages=clike+javascript+python */ -/** - * prism.js default theme for JavaScript, CSS and HTML - * Based on dabblet (http://dabblet.com) - * @author Lea Verou - */ - -code[class*="language-"], -pre[class*="language-"] { - color: black; - text-shadow: 0 1px white; - font-family: Consolas, Monaco, 'Andale Mono', monospace; - direction: ltr; - text-align: left; - white-space: pre; - word-spacing: normal; - word-break: normal; - - - -moz-tab-size: 4; - -o-tab-size: 4; - tab-size: 4; - - -webkit-hyphens: none; - -moz-hyphens: none; - -ms-hyphens: none; - hyphens: none; -} - -pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, -code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { - text-shadow: none; - background: #b3d4fc; -} - -pre[class*="language-"]::selection, pre[class*="language-"] ::selection, -code[class*="language-"]::selection, code[class*="language-"] ::selection { - text-shadow: none; - background: #b3d4fc; -} - -@media print { - code[class*="language-"], - pre[class*="language-"] { - text-shadow: none; - } -} - -/* Code blocks */ -pre[class*="language-"] { - padding: 1em; - margin: .5em 0; - overflow: auto; -} - -:not(pre) > code[class*="language-"], -pre[class*="language-"] { - background: #f5f2f0; -} - -/* Inline code */ -:not(pre) > code[class*="language-"] { - padding: .1em; - border-radius: .3em; -} - -.token.comment, -.token.prolog, -.token.doctype, -.token.cdata { - color: slategray; -} - -.token.punctuation { - color: #999; -} - -.namespace { - opacity: .7; -} - -.token.property, -.token.tag, -.token.boolean, -.token.number, -.token.constant, -.token.symbol { - color: #905; -} - -.token.selector, -.token.attr-name, -.token.string, -.token.builtin { - color: #690; -} - -.token.operator, -.token.entity, -.token.url, -.language-css .token.string, -.style .token.string, -.token.variable { - color: #a67f59; - background: hsla(0,0%,100%,.5); -} - -.token.atrule, -.token.attr-value, -.token.keyword { - color: #07a; -} - -.token.function { - color: #DD4A68; -} - -.token.regex, -.token.important { - color: #e90; -} - -.token.important { - font-weight: bold; -} - -.token.entity { - cursor: help; -} - diff --git a/src/mac/deprecated_64bit/prism.js b/src/mac/deprecated_64bit/prism.js deleted file mode 100644 index ebaa4b428..000000000 --- a/src/mac/deprecated_64bit/prism.js +++ /dev/null @@ -1,5 +0,0 @@ -/* http://prismjs.com/download.html?themes=prism&languages=clike+javascript+python */ -self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{};var Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content)):"Array"===t.util.type(e)?e.map(t.util.encode):e.replace(/&/g,"&").replace(/e.length)break e;if(!(f instanceof r)){l.lastIndex=0;var h=l.exec(f);if(h){c&&(g=h[1].length);var d=h.index-1+g,h=h[0].slice(g),p=h.length,m=d+p,v=f.slice(0,d+1),y=f.slice(m+1),k=[u,1];v&&k.push(v);var b=new r(o,s?t.tokenize(h,s):h);k.push(b),y&&k.push(y),Array.prototype.splice.apply(a,k)}}}}return a},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[],r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(r&&r.length)for(var a,i=0;a=r[i++];)a(n)}}},n=t.Token=function(e,t){this.type=e,this.content=t};if(n.stringify=function(e,r,a){if("string"==typeof e)return e;if("[object Array]"==Object.prototype.toString.call(e))return e.map(function(t){return n.stringify(t,r,e)}).join("");var i={type:e.type,content:n.stringify(e.content,r,a),tag:"span",classes:["token",e.type],attributes:{},language:r,parent:a};"comment"==i.type&&(i.attributes.spellcheck="true"),t.hooks.run("wrap",i);var o="";for(var l in i.attributes)o+=l+'="'+(i.attributes[l]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+o+">"+i.content+""},!self.document)return self.addEventListener?(self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,a=n.code;self.postMessage(JSON.stringify(t.tokenize(a,t.languages[r]))),self.close()},!1),self.Prism):self.Prism;var r=document.getElementsByTagName("script");return r=r[r.length-1],r&&(t.filename=r.src,document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)),self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism);; -Prism.languages.clike={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,lookbehind:!0},string:/("|')(\\?.)*?\1/g,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/gi,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g,"boolean":/\b(true|false)\b/g,"function":{pattern:/[a-z0-9_]+\(/gi,inside:{punctuation:/\(/}},number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,operator:/[-+]{1,2}|!|<=?|>=?|={1,3}|&{1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};; -Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|function|get|if|implements|import|in|instanceof|interface|let|new|null|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,lookbehind:!0}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/[\w\W]*?<\/script>/gi,inside:{tag:{pattern:/|<\/script>/gi,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}});; -Prism.languages.python={comment:{pattern:/(^|[^\\])#.*?(\r?\n|$)/g,lookbehind:!0},string:/"""[\s\S]+?"""|("|')(\\?.)*?\1/g,keyword:/\b(as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/g,"boolean":/\b(True|False)\b/g,number:/\b-?(0x)?\d*\.?[\da-f]+\b/g,operator:/[-+]{1,2}|=?<|=?>|!|={1,2}|(&){1,2}|(&){1,2}|\|?\||\?|\*|\/|~|\^|%|\b(or|and|not)\b/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};; diff --git a/src/mac/deprecated_64bit/wxpython.html b/src/mac/deprecated_64bit/wxpython.html deleted file mode 100644 index c23b384f0..000000000 --- a/src/mac/deprecated_64bit/wxpython.html +++ /dev/null @@ -1,708 +0,0 @@ - - - - - wxPython CEF 3 example (utf-8: ąś) - - - - - - -Use mouse context menu to go Back/Forward in navigation history.
      - -

      Table of contents

      -
        -
      1. Google search
      2. -
      3. User agent
      4. -
      5. Popups
      6. -
      7. HTML 5 video
      8. -
      9. Developer Tools
      10. -
      11. Downloads
      12. -
      13. HTML controls
      14. -
      15. Browser object
      16. -
      17. Frame object
      18. -
      19. Javascript bindings
      20. -
      21. Javascript callbacks
      22. -
      23. Python callbacks
      24. -
      25. Display handler
      26. -
      27. Keyboard handler
      28. -
      29. Request handler
      30. -
      31. Cookie tests
      32. -
      33. Load handler
      34. -
      35. Javascript Dialog handler
      36. -
      37. Other tests
      38. -
      - - - - - - -

      Google search

      - -http://www.google.com/ - - - - - - - -

      User agent

      - - - - - - - - - -

      Popups

      - -
        -
      1. - window.open('wxpython.html') -
      2. -
      3. - target=_blank href="wxpython.html" -
      4. -
      - -

      CreateAnotherBrowser

      - -This will create a window on its own and embed browser in it. -When using "window.open" the window is created implicitilly -by CEF. You can intercept such popup creation using the -OnBeforePopup callback in LifespanHandler. You can return -True in OnBeforePopup and create popup window on your own -using the CreateAnotherBrowser function. - - - - external.CreateAnotherBrowser() - - - - - - - -

      HTML5 video and accelerated content

      - - -HTML 5 video
      - - -Accelerated canvas
      - - -Accelerated layers
      - - - - - - -

      Developer Tools

      - -You can open devtools popup window in a few different ways: -
        -
      1. Call Browser.ShowDevTools() method: - - external.ShowDevTools()
      2. -
      3. Through mouse context menu
      4. -
      5. Through F12 key (on Mac: Cmd+Opt+I) which is handled in - KeyboardHandler.OnKeyEvent.
      6. -
      - - - - - - -

      Downloads

      - -Download sample Ubuntu wallpapers:
      - - https://cefpython.googlecode.com/files/ubuntu-wallpapers2.zip - -

      -Notes: On Linux it seems that OnLoadError with errorCode = ERR_ABORTED -is called even for successful downloads, you can ignore this behavior. -The proper console messages about successful/aborted download originate -from C++ Browser process code, these are: -

      - -
      Browser: About to download file: ubuntu-wallpapers2.zip
      -Browser: Download completed, saved to: /Downloads/ubuntu-wallpapers2.zip
      -
      - -If download was aborted the messages will be: - -
      Browser: About to download file: ubuntu-wallpapers2.zip
      -Browser: Download was cancelled
      -
      - -

      -Additionally on Linux there are more errors reported by Chromium -about org.gnome.SessionManager.inhibit. These can be safely ignored as well. -

      - -A download handler with callbacks like `OnBeforeDownload` and -`OnDownloadUpdated` may be exposed to CEF Python in the future. - - - - - - -

      HTML controls

      - -

      Textarea

      - -
      - -

      Inputs

      -Text:
      -Password:
      - -

      Select

      - - -

      Buttons

      -Submit:
      -Button:
      - - - - - - -

      Browser object

      - -Tests for the Browser object methods. - -

      GoBack

      - -external.GoBack() - -

      GoForward

      - -external.GoForward() - -

      LoadUrl, GetUrl

      - - - window.open('data:text/html,Test#Browser.LoadUrl') - -

      ReloadIgnoreCache, StopLoad

      -Press F5 to reload page and ignore cache.
      -Press Esc during webpage loading to abort.
      - -Also, when Esc is pressed OnLoadError may get called. See how abort -of page loading or file download is handled: - - - - - - - -

      Frame object

      - -Tests for the Frame object methods. TODO. - - - - - - -

      Javascript bindings

      - -

      PyPrint

      - - - window.PyPrint('printing in python console from js') -
      - -

      Window properties

      - -
      jsBindings.SetProperty("pyProperty", "This was set in Python")
      -jsBindings.SetProperty("pyConfig", ["This was set in Python",
      -        {"name": "Nested dictionary", "isNested": True},
      -        [1,"2", None]])
      -
      - - - window.alert(window.pyProperty)
      - - window.alert(JSON.stringify(window.pyConfig)) -
      - -

      Print

      - - - - external.Print('printing again from js') -
      - -

      TestAllTypes

      - - - - external.TestAllTypes - (undefined, null, true, 1, - ((1<<31)>>>0), 2.14, 'Date not yet supported', 'string', - {key1: 1, key2: 2}, {key1: {'key1.1': 'nested object'}, 'key1.2': [1]}, - [1, 2], [1, [2.1, 'nested array']], [{key1: [{}]}]) -
      - -

      ExecuteFunction

      - - - -
      <script>
      -function JavascriptAlert(message) { window.alert(message); }
      -</script>
      -
      - - - - external.ExecuteFunction('JavascriptAlert', - 'python called from js and then js called from python') -
      - -

      GetSource, GetText

      - - - - - - - external.GetSource() -
      - - external.GetText() - - - - - - -

      Javascript callbacks

      - -

      TestJSCallback

      - - - -
      <script>
      -function JSCallback(arg1) {
      -    window.alert(arg1)
      -}
      -</script>
      -
      - - - - external.TestJSCallback(JSCallback) - -

      TestJSCallbackComplexArguments

      - - - -
      <script>
      -function JSCallback2() {
      -    window.alert(JSON.stringify(arguments))
      -}
      -</script>
      -
      - - - - external.TestJSCallbackComplexArguments({"myCallback": JSCallback2}) - - - - - - - -

      Python callbacks

      - -

      TestPythonCallback

      - - - -
      <script>
      -function JSCallback3(pyCallback) {
      -    pyCallback(1, 2.14, "string", [1, [2, {"key": "value"}]], {"list": [1,2]});
      -}
      -</script>
      -
      - - - - - - external.TestPythonCallback(JSCallback3) - - - - - - -

      Display handler

      - -

      OnAddressChange

      - -See messages in the console during loading of a webpage. - -

      OnTitleChange

      - -See messages in the console during loading of a webpage. - -

      OnTooltip

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

      OnStatusMessage

      - -See messages in the console when hovering over links. - -

      OnConsoleMessage

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

      Keyboard handler

      - -

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

      - - - - - - - - - -

      Request handler

      - -

      OnBeforeResourceLoad

      - -See messages in the console. - -

      OnResourceRedirect

      - -Try this: - - http://tinyurl.com/google404redirect - -

      GetAuthCredentials

      - -Try this: - - http://browserspy.dk/password-ok.php - -

      OnQuotaRequest

      - - - - -
      <script>
      -function DoRequestQuota() {
      -    // Request Quota (only for File System API)
      -    try {
      -        navigator.webkitPersistentStorage.requestQuota(PERSISTENT, 1024*1024,
      -                function(bytes){ window.alert("Granted bytes: "+bytes);},
      -                function(error){ window.alert(error); });
      -    } catch(e) {
      -        navigator.webkitPersistentStorage.requestQuota(1024*1024,
      -                function(bytes){ window.alert("Granted bytes: "+bytes);},
      -                function(error){ window.alert(error); });
      -    }
      -}
      -</script>
      -
      - -Try this: - - https://googledrive.com/host/0B1di2XiBBfacMnhRRkI1YlotUEk/requestquota.html - -

      OnProtocolExecution

      - -Try this: - - magnet:?xt=urn:btih:a4224b45b27f436374391379cc5c7e629e2e5189 - -

      _OnBeforePluginLoad

      - -Try OnBeforePluginLoad() with Flash: - - http://www.adobe.com/software/flash/about/ - -

      _OnCertificateError

      - - -The url below won't be allowed. Click twice "Back" from context menu to return back -here after visiting the url:
      - - https://tv.eurosport.com/do-not-allow -
      - -This url will be allowed:
      - - https://tv.eurosport.com/ - -

      OnRendererProcessTerminated

      - -Try to terminate the "subprocess.exe" renderer process through -task manager. - -

      OnPluginCrashed

      - -No test for that yet. - - - - - - -

      Cookie tests

      - -See messages in the console. - -

      GetCookieManager

      - - - -RequestHandler.GetCookieManager() - an example of having an unique -cookie manager for each browser. -
        -
      1. Visit the url below and set some cookies. Use "Back" from - context menu to get back here (you might have to click "Back" - multiple times).
        - Visit it in the current browser:
        - - http://www.html-kit.com/tools/cookietester/ -
        - Or visit it in a js popup:
        - - javascript:window.open('http://www.html-kit.com/tools/cookietester/') -
      2. -
      3. Open cookietester in a popup:
        - - javascript:external.CreateAnotherBrowser('http://www.html-kit.com/tools/cookietester/') -
      4. -
      - -

      -Popup browsers created javascript's window.open share -the same renderer process and request context. If you want -to have separate cookie managers for popups created using -window.open then you have to implement the -LifespanHandler.`OnBeforePopup` callback. Return True in that -callback to cancel popup creation and instead create the -window on your own and embed browser in it. The CreateAnotherBrowser() -function from the wxpython example does that. -

      - -

      VisitAllCookies

      - -Visit all cookies: -external.VisitAllCookies() -

      - -Note: visit some http:// webpage first, otherwise cookie manager is not -yet created. -
      - -

      VisitUrlCookies

      - -Visit a subset of cookies for the given url: - - external.VisitUrlCookies("http://www.html-kit.com/tools/cookietester/") -
      - -

      SetCookie

      - -Set a cookie: -external.SetCookie() -
      - -

      DeleteCookies

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

      Load Handler

      - -See messages in the console during loading of a webpage. - -

      OnLoadingStateChange

      - - -

      OnLoadStart

      - - -

      OnLoadEnd

      - - -

      OnLoadError

      - -Try this: - - http://www.non-existent.nono/ -

      - -Note: after you see the custom error message you have to hit -twice the Back from the context menu, to get back to this page. - - - - - - -

      Javascript Dialog Handler

      - -See messages in the console. - -

      OnJavascriptDialog

      - - - alert('Test js dialog handler') - - -

      OnBeforeUnloadJavascriptDialog

      - - - -
      <script>
      -function TestOnBeforeUnloadJavascriptDialog() {
      -    window.onbeforeunload = function() {
      -        return 'Testing the OnBeforeUnloadJavascriptDialog() callback';
      -    }
      -    location.href = "wxpython.html";
      -}
      -</script>
      -
      - - - TestOnBeforeUnloadJavascriptDialog() - - -

      OnResetJavascriptDialogState

      - - -

      OnJavascriptDialogClosed

      - - - - - - - -

      Other tests

      - -

      HTTPS caching with SSL certificate errors

      -Set ApplicationSettings["ignore_certificate_errors"] to True. - - - - - - - - - - - - - diff --git a/src/mac/deprecated_64bit/wxpython.py b/src/mac/deprecated_64bit/wxpython.py deleted file mode 100644 index bdcca1ce3..000000000 --- a/src/mac/deprecated_64bit/wxpython.py +++ /dev/null @@ -1,851 +0,0 @@ -# An example of embedding CEF browser in wxPython on Mac. -# Tested with wxPython3.0-osx-3.0.2.0-cocoa-py2.7.dmg which -# was downloaded from the wxpython.org website. - -# IMPORTANT - importing CEF Python -# -------------------------------------------------------------- -# The cefpython library must be the very first library imported. -# This is because CEF was compiled with the tcmalloc memory -# allocator which hooks globally and replaces the default -# malloc allocator. If memory was allocated using malloc and -# then freed using tcmalloc then this would result in random -# segmentation faults in an application. See Issue 155 which -# is to provide CEF builds on Mac with tcmalloc disabled: -# https://github.com/cztomczak/cefpython/issues/155 - -import ctypes, os, sys -libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)),\ - 'libcef.dylib') -if os.path.exists(libcef_so): - # Import a local module - ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import an installed package - from cefpython3 import cefpython - -import wx -import time -import re -import uuid -import platform -import inspect -import struct - -g_applicationSettings = None -g_browserSettings = None -g_switches = None -g_countWindows = 0 - -# Which method to use for message loop processing. -# EVT_IDLE - wx application has priority (default) -# EVT_TIMER - cef browser has priority -# It seems that Flash content behaves better when using a timer. -# IMPORTANT! On Linux EVT_IDLE does not work, the events seems to -# be propagated only when you move your mouse, which is not the -# expected behavior, it is recommended to use EVT_TIMER on Linux, -# so set this value to False. -USE_EVT_IDLE = False - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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" (os._exit()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("[wxpython.py] WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainFrame(wx.Frame): - browser = None - mainPanel = None - clientHandler = None - javascriptExternal = None - - def __init__(self, url=None): - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, - title='wxPython CEF 3 example', size=(800,600)) - - global g_countWindows - g_countWindows += 1 - - if not url: - url = "file://"+GetApplicationPath("wxpython.html") - # Test hash in url. - # url += "#test-hash" - - self.CreateMenu() - - # Cannot attach browser to the main frame as this will cause - # the menu not to work. - # -- - # You also have to set the wx.WANTS_CHARS style for - # all parent panels/controls, if it's deeply embedded. - self.mainPanel = wx.Panel(self, style=wx.WANTS_CHARS) - - # Global client callbacks must be set before browser is created. - self.clientHandler = ClientHandler() - cefpython.SetGlobalClientCallback("OnCertificateError", - self.clientHandler._OnCertificateError) - cefpython.SetGlobalClientCallback("OnBeforePluginLoad", - self.clientHandler._OnBeforePluginLoad) - cefpython.SetGlobalClientCallback("OnAfterCreated", - self.clientHandler._OnAfterCreated) - - windowInfo = cefpython.WindowInfo() - (width, height) = self.mainPanel.GetClientSizeTuple() - windowInfo.SetAsChild(self.mainPanel.GetHandle(), - [0, 0, width, height]) - # Linux requires adding "file://" for local files, - # otherwise /home/some will be replaced as http://home/some - self.browser = cefpython.CreateBrowserSync( - windowInfo, - # If there are problems with Flash you can disable it here, - # by disabling all plugins. - browserSettings=g_browserSettings, - navigateUrl=url) - - self.clientHandler.mainBrowser = self.browser - self.browser.SetClientHandler(self.clientHandler) - - jsBindings = cefpython.JavascriptBindings( - bindToFrames=False, bindToPopups=True) - jsBindings.SetFunction("PyPrint", PyPrint) - jsBindings.SetProperty("pyProperty", "This was set in Python") - jsBindings.SetProperty("pyConfig", ["This was set in Python", - {"name": "Nested dictionary", "isNested": True}, - [1,"2", None]]) - self.javascriptExternal = JavascriptExternal(self.browser) - jsBindings.SetObject("external", self.javascriptExternal) - jsBindings.SetProperty("sources", GetSources()) - self.browser.SetJavascriptBindings(jsBindings) - - self.Bind(wx.EVT_CLOSE, self.OnClose) - if USE_EVT_IDLE: - # Bind EVT_IDLE only for the main application frame. - self.Bind(wx.EVT_IDLE, self.OnIdle) - - def CreateMenu(self): - filemenu = wx.Menu() - filemenu.Append(1, "Open") - exit = filemenu.Append(2, "Exit") - self.Bind(wx.EVT_MENU, self.OnClose, exit) - aboutmenu = wx.Menu() - aboutmenu.Append(1, "CEF Python") - menubar = wx.MenuBar() - menubar.Append(filemenu,"&File") - menubar.Append(aboutmenu, "&About") - self.SetMenuBar(menubar) - - def OnClose(self, event): - # Remove all CEF browser references so that browser is closed - # cleanly. Otherwise there may be issues for example with cookies - # not being flushed to disk when closing app immediately - # (Issue 158). - del self.javascriptExternal.mainBrowser - del self.clientHandler.mainBrowser - del self.browser - - # Destroy wx frame, this will complete the destruction of CEF browser - self.Destroy() - - # In wx.chromectrl calling browser.CloseBrowser and/or self.Destroy - # may cause crashes when embedding multiple browsers in tab - # (Issue 107). In such case instead of calling CloseBrowser/Destroy - # try this code: - # | self.browser.ParentWindowWillClose() - # | event.Skip() - - global g_countWindows - g_countWindows -= 1 - if g_countWindows == 0: - # On Win/Linux the call to cefpython.Shutdown() is after - # app.MainLoop() returns, but on Mac it needs to be here. - cefpython.Shutdown() - print("[wxpython.py] OnClose: Exiting") - wx.GetApp().Exit() - - def OnIdle(self, event): - cefpython.MessageLoopWork() - -def PyPrint(message): - print("[wxpython.py] PyPrint: "+message) - -class JavascriptExternal: - mainBrowser = None - stringVisitor = None - - def __init__(self, mainBrowser): - self.mainBrowser = mainBrowser - - def GoBack(self): - self.mainBrowser.GoBack() - - def GoForward(self): - self.mainBrowser.GoForward() - - def CreateAnotherBrowser(self, url=None): - """ - TODO: There are errors in the console when closing the window: - >> Check failed: window - >> Gdk: _gdk_window_destroy_hierarchy: assertion `GDK_IS_WINDOW\ - >> (window)' failed - >> GLib-GObject: g_object_unref: assertion `G_IS_OBJECT (object)' failed - """ - frame = MainFrame(url=url) - frame.Show() - - def Print(self, message): - print("[wxpython.py] Print: "+message) - - def TestAllTypes(self, *args): - print("[wxpython.py] TestAllTypes: "+str(args)) - - def ExecuteFunction(self, *args): - self.mainBrowser.GetMainFrame().ExecuteFunction(*args) - - def TestJSCallback(self, jsCallback): - print("[wxpython.py] jsCallback.GetFunctionName() = %s"\ - % jsCallback.GetFunctionName()) - print("[wxpython.py] jsCallback.GetFrame().GetIdentifier() = %s" % \ - jsCallback.GetFrame().GetIdentifier()) - jsCallback.Call("This message was sent from python using js callback") - - def TestJSCallbackComplexArguments(self, jsObject): - jsCallback = jsObject["myCallback"]; - jsCallback.Call(1, None, 2.14, "string", ["list", ["nested list", \ - {"nested object":None}]], \ - {"nested list next":[{"deeply nested object":1}]}) - - def TestPythonCallback(self, jsCallback): - jsCallback.Call(self.PyCallback) - - def PyCallback(self, *args): - message = "PyCallback() was executed successfully! "\ - "Arguments: %s" % str(args) - print("[wxpython.py] "+message) - self.mainBrowser.GetMainFrame().ExecuteJavascript( - "window.alert(\"%s\")" % message) - - def GetSource(self): - # Must keep a strong reference to the StringVisitor object - # during the visit. - self.stringVisitor = StringVisitor() - self.mainBrowser.GetMainFrame().GetSource(self.stringVisitor) - - def GetText(self): - # Must keep a strong reference to the StringVisitor object - # during the visit. - self.stringVisitor = StringVisitor() - self.mainBrowser.GetMainFrame().GetText(self.stringVisitor) - - def ShowDevTools(self): - print("[wxpython.py] external.ShowDevTools called") - self.mainBrowser.ShowDevTools() - - # ------------------------------------------------------------------------- - # Cookies - # ------------------------------------------------------------------------- - cookieVisitor = None - - def VisitAllCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.VisitAllCookies(self.cookieVisitor) - - def VisitUrlCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.VisitUrlCookies( - "http://www.html-kit.com/tools/cookietester/", - False, self.cookieVisitor) - # .www.html-kit.com - - def SetCookie(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - "the cookietester website first and create some cookies") - return - cookie = cefpython.Cookie() - cookie.SetName("Created_Via_Python") - cookie.SetValue("yeah really") - cookieManager.SetCookie("http://www.html-kit.com/tools/cookietester/", - cookie) - print("\n[wxpython.py] Cookie created! Visit html-kit cookietester to"\ - " see it") - - def DeleteCookies(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.DeleteCookies( - "http://www.html-kit.com/tools/cookietester/", - "Created_Via_Python") - print("\n[wxpython.py] Cookie deleted! Visit html-kit cookietester "\ - "to see the result") - -class StringVisitor: - def Visit(self, string): - print("\n[wxpython.py] StringVisitor.Visit(): string:") - print("--------------------------------") - print(string) - print("--------------------------------") - -class CookieVisitor: - def Visit(self, cookie, count, total, deleteCookie): - if count == 0: - print("\n[wxpython.py] CookieVisitor.Visit(): total cookies: %s"\ - % total) - print("\n[wxpython.py] CookieVisitor.Visit(): cookie:") - print(" "+str(cookie.Get())) - # True to continue visiting cookies - return True - -class ClientHandler: - mainBrowser = None # May be None for global client callbacks. - - def __init__(self): - pass - - # ------------------------------------------------------------------------- - # DisplayHandler - # ------------------------------------------------------------------------- - - def OnAddressChange(self, browser, frame, url): - print("[wxpython.py] DisplayHandler::OnAddressChange()") - print(" url = %s" % url) - - def OnTitleChange(self, browser, title): - print("[wxpython.py] DisplayHandler::OnTitleChange()") - print(" title = %s" % title) - - def OnTooltip(self, browser, textOut): - # OnTooltip not yet implemented (both Linux and Windows), - # will be fixed in next CEF release, see Issue 783: - # https://code.google.com/p/chromiumembedded/issues/detail?id=783 - print("[wxpython.py] DisplayHandler::OnTooltip()") - print(" text = %s" % textOut[0]) - - statusMessageCount = 0 - def OnStatusMessage(self, browser, value): - if not value: - # Do not notify in the console about empty statuses. - return - self.statusMessageCount += 1 - if self.statusMessageCount > 3: - # Do not spam too much. - return - print("[wxpython.py] DisplayHandler::OnStatusMessage()") - print(" value = %s" % value) - - def OnConsoleMessage(self, browser, message, source, line): - print("[wxpython.py] DisplayHandler::OnConsoleMessage()") - print(" message = %s" % message) - print(" source = %s" % source) - print(" line = %s" % line) - - # ------------------------------------------------------------------------- - # KeyboardHandler - # ------------------------------------------------------------------------- - - def OnPreKeyEvent(self, browser, event, eventHandle, - isKeyboardShortcutOut): - print("[wxpython.py] KeyboardHandler::OnPreKeyEvent()") - - def OnKeyEvent(self, browser, event, eventHandle): - if event["type"] == cefpython.KEYEVENT_KEYUP: - # OnKeyEvent is called twice for F5/Esc keys, with event - # type KEYEVENT_RAWKEYDOWN and KEYEVENT_KEYUP. - # Normal characters a-z should have KEYEVENT_CHAR. - return False - print("[wxpython.py] KeyboardHandler::OnKeyEvent()") - print(" type=%s" % event["type"]) - print(" modifiers=%s" % event["modifiers"]) - print(" windows_key_code=%s" % event["windows_key_code"]) - print(" native_key_code=%s" % event["native_key_code"]) - print(" is_system_key=%s" % event["is_system_key"]) - print(" character=%s" % event["character"]) - print(" unmodified_character=%s" % event["unmodified_character"]) - print(" focus_on_editable_field=%s"\ - % event["focus_on_editable_field"]) - if platform.system() == "Linux": - # F5 - if event["native_key_code"] == 71: - print("[wxpython.py] F5 pressed, calling"\ - " browser.ReloadIgnoreCache()") - browser.ReloadIgnoreCache() - return True - # Escape - if event["native_key_code"] == 9: - print("[wxpython.py] Esc pressed, calling browser.StopLoad()") - browser.StopLoad() - return True - # F12 - if event["native_key_code"] == 96: - print("[wxpython.py] F12 pressed, calling"\ - " browser.ShowDevTools()") - browser.ShowDevTools() - return True - elif platform.system() == "Windows": - # F5 todo - # Escape todo - pass - elif platform.system() == "Darwin": - # Cmd+Opt+I - if event["modifiers"] == 136 and event["character"] == 94: - browser.ShowDevTools() - return True - # F5 - if event["modifiers"] == 0 and event["character"] == 63240: - browser.ReloadIgnoreCache() - return True - # Esc - if event["modifiers"] == 0 and event["character"] == 27: - browser.StopLoad() - return True - return False - - # ------------------------------------------------------------------------- - # RequestHandler - # ------------------------------------------------------------------------- - - def OnBeforeBrowse(self, browser, frame, request, isRedirect): - print("[wxpython.py] RequestHandler::OnBeforeBrowse()") - print(" url = %s" % request.GetUrl()[:100]) - return False - - def OnBeforeResourceLoad(self, browser, frame, request): - print("[wxpython.py] RequestHandler::OnBeforeResourceLoad()") - print(" url = %s" % request.GetUrl()[:100]) - return False - - def OnResourceRedirect(self, browser, frame, oldUrl, newUrlOut, request): - print("[wxpython.py] RequestHandler::OnResourceRedirect()") - print(" old url = %s" % oldUrl[:100]) - print(" new url = %s" % newUrlOut[0][:100]) - - def GetAuthCredentials(self, browser, frame, isProxy, host, port, realm, - scheme, callback): - # This callback is called on the IO thread, thus print messages - # may not be visible. - print("[wxpython.py] RequestHandler::GetAuthCredentials()") - print(" host = %s" % host) - print(" realm = %s" % realm) - callback.Continue(username="test", password="test") - return True - - def OnQuotaRequest(self, browser, originUrl, newSize, callback): - print("[wxpython.py] RequestHandler::OnQuotaRequest()") - print(" origin url = %s" % originUrl) - print(" new size = %s" % newSize) - callback.Continue(True) - return True - - def GetCookieManager(self, browser, mainUrl): - # Create unique cookie manager for each browser. - # You must set the "unique_request_context_per_browser" - # application setting to True for the cookie manager - # to work. - # Return None to have one global cookie manager for - # all CEF browsers. - if not browser: - # The browser param may be empty in some exceptional - # case, see docs. - return None - cookieManager = browser.GetUserData("cookieManager") - if cookieManager: - return cookieManager - else: - print("[wxpython.py] RequestHandler::GetCookieManager():"\ - " created cookie manager") - cookieManager = cefpython.CookieManager.CreateManager("") - if "cache_path" in g_applicationSettings: - path = g_applicationSettings["cache_path"] - # path = os.path.join(path, "cookies_browser_{}".format( - # browser.GetIdentifier())) - cookieManager.SetStoragePath(path) - browser.SetUserData("cookieManager", cookieManager) - return cookieManager - - def OnProtocolExecution(self, browser, url, allowExecutionOut): - # There's no default implementation for OnProtocolExecution on Linux, - # you have to make OS system call on your own. You probably also need - # to use LoadHandler::OnLoadError() when implementing this on Linux. - print("[wxpython.py] RequestHandler::OnProtocolExecution()") - print(" url = %s" % url) - if url.startswith("magnet:"): - print("[wxpython.py] Magnet link allowed!") - allowExecutionOut[0] = True - - def _OnBeforePluginLoad(self, browser, mimeType, pluginUrl, topOriginUrl, - info): - # This is a global callback set using SetGlobalClientCallback(). - # Plugins are loaded on demand, only when website requires it, - # the same plugin may be called multiple times. - # This callback is called on various threads, thus print messages - # may not be visible. - print("[wxpython.py] RequestHandler::_OnBeforePluginLoad()") - print(" mimeType = %s" % mimeType) - print(" pluginUrl = %s" % pluginUrl) - print(" topOriginUrl = %s" % topOriginUrl) - print(" info.GetName() = %s" % info.GetName()) - print(" info.GetPath() = %s" % info.GetPath()) - print(" info.GetVersion() = %s" % info.GetVersion()) - print(" info.GetDescription() = %s" % info.GetDescription()) - # False to allow, True to block plugin. - return False - - def _OnCertificateError(self, certError, requestUrl, callback): - # This is a global callback set using SetGlobalClientCallback(). - print("[wxpython.py] RequestHandler::_OnCertificateError()") - print(" certError = %s" % certError) - print(" requestUrl = %s" % requestUrl) - if requestUrl.startswith( - "https://tv.eurosport.com/do-not-allow"): - print(" Not allowed!") - return False - if requestUrl.startswith( - "https://tv.eurosport.com/"): - print(" Allowed!") - callback.Continue(True) - return True - return False - - def OnRendererProcessTerminated(self, browser, status): - print("[wxpython.py] RequestHandler::OnRendererProcessTerminated()") - statuses = { - cefpython.TS_ABNORMAL_TERMINATION: "TS_ABNORMAL_TERMINATION", - cefpython.TS_PROCESS_WAS_KILLED: "TS_PROCESS_WAS_KILLED", - cefpython.TS_PROCESS_CRASHED: "TS_PROCESS_CRASHED" - } - statusName = "Unknown" - if status in statuses: - statusName = statuses[status] - print(" status = %s" % statusName) - - def OnPluginCrashed(self, browser, pluginPath): - print("[wxpython.py] RequestHandler::OnPluginCrashed()") - print(" plugin path = %s" % pluginPath) - - # ------------------------------------------------------------------------- - # LoadHandler - # ------------------------------------------------------------------------- - - def OnLoadingStateChange(self, browser, isLoading, canGoBack, - canGoForward): - print("[wxpython.py] LoadHandler::OnLoadingStateChange()") - print(" isLoading = %s, canGoBack = %s, canGoForward = %s" \ - % (isLoading, canGoBack, canGoForward)) - - def OnLoadStart(self, browser, frame): - print("[wxpython.py] LoadHandler::OnLoadStart()") - print(" frame url = %s" % frame.GetUrl()[:100]) - - def OnLoadEnd(self, browser, frame, httpStatusCode): - print("[wxpython.py] LoadHandler::OnLoadEnd()") - print(" frame url = %s" % frame.GetUrl()[:100]) - # For file:// urls the status code = 0 - print(" http status code = %s" % httpStatusCode) - # Tests for the Browser object methods - self._Browser_LoadUrl(browser) - - def _Browser_LoadUrl(self, browser): - if browser.GetUrl() == "data:text/html,Test#Browser.LoadUrl": - browser.LoadUrl("file://"+GetApplicationPath("wxpython.html")) - - def OnLoadError(self, browser, frame, errorCode, errorTextList, failedUrl): - print("[wxpython.py] LoadHandler::OnLoadError()") - print(" frame url = %s" % frame.GetUrl()[:100]) - print(" error code = %s" % errorCode) - print(" error text = %s" % errorTextList[0]) - print(" failed url = %s" % failedUrl) - # Handle ERR_ABORTED error code, to handle the following cases: - # 1. Esc key was pressed which calls browser.StopLoad() in OnKeyEvent - # 2. Download of a file was aborted - if errorCode == cefpython.ERR_ABORTED: - print("[wxpython.py] LoadHandler::OnLoadError(): Ignoring load"\ - " error: Esc was pressed or file download was aborted") - return; - customErrorMessage = "My custom error message!" - frame.LoadUrl("data:text/html,%s" % customErrorMessage) - - # ------------------------------------------------------------------------- - # LifespanHandler - # ------------------------------------------------------------------------- - - # ** This callback is executed on the IO thread ** - # Empty place-holders: popupFeatures, client. - def OnBeforePopup(self, browser, frame, targetUrl, targetFrameName, - targetDisposition, userGesture, - popupFeatures, windowInfo, client, browserSettings, - noJavascriptAccess): - print("[wxpython.py] LifespanHandler::OnBeforePopup()") - print(" targetUrl = %s" % targetUrl) - # Custom browser settings for popups: - # > browserSettings[0] = {"plugins_disabled": True} - # Set WindowInfo object: - # > windowInfo[0] = cefpython.WindowInfo() - allowPopups = True - return not allowPopups - - def _OnAfterCreated(self, browser): - # This is a global callback set using SetGlobalClientCallback(). - print("[wxpython.py] LifespanHandler::_OnAfterCreated()") - print(" browserId=%s" % browser.GetIdentifier()) - - def DoClose(self, browser): - print("[wxpython.py] LifespanHandler::DoClose()") - print(" browserId=%s" % browser.GetIdentifier()) - - def OnBeforeClose(self, browser): - print("[wxpython.py] LifespanHandler::OnBeforeClose") - print(" browserId=%s" % browser.GetIdentifier()) - - # ------------------------------------------------------------------------- - # JavascriptDialogHandler - # ------------------------------------------------------------------------- - - def OnJavascriptDialog(self, browser, originUrl, dialogType, - messageText, defaultPromptText, callback, - suppressMessage): - print("[wxpython.py] JavascriptDialogHandler::OnJavascriptDialog()") - print(" originUrl="+originUrl) - print(" dialogType="+str(dialogType)) - print(" messageText="+messageText) - print(" defaultPromptText="+defaultPromptText) - # If you want to suppress the javascript dialog: - # suppressMessage[0] = True - return False - - def OnBeforeUnloadJavascriptDialog(self, browser, messageText, isReload, - callback): - print("[wxpython.py] OnBeforeUnloadJavascriptDialog()") - print(" messageText="+messageText) - print(" isReload="+str(isReload)) - # Return True if the application will use a custom dialog: - # callback.Continue(allow=True, userInput="") - # return True - return False - - def OnResetJavascriptDialogState(self, browser): - print("[wxpython.py] OnResetDialogState()") - - def OnJavascriptDialogClosed(self, browser): - print("[wxpython.py] OnDialogClosed()") - - -class MyApp(wx.App): - timer = None - timerID = 1 - timerCount = 0 - - def OnInit(self): - if not USE_EVT_IDLE: - self.CreateTimer() - frame = MainFrame() - self.SetTopWindow(frame) - frame.Show() - return True - - def CreateTimer(self): - # See "Making a render loop": - # http://wiki.wxwidgets.org/Making_a_render_loop - # Another approach is to use EVT_IDLE in MainFrame, - # see which one fits you better. - self.timer = wx.Timer(self, self.timerID) - self.timer.Start(10) # 10ms - wx.EVT_TIMER(self, self.timerID, self.OnTimer) - - def OnTimer(self, event): - self.timerCount += 1 - # print("[wxpython.py] OnTimer() %d" % self.timerCount) - cefpython.MessageLoopWork() - - def OnExit(self): - # When app.MainLoop() returns, MessageLoopWork() should - # not be called anymore. - if not USE_EVT_IDLE: - self.timer.Stop() - -def GetSources(): - # Get sources of all python functions and methods from this file. - # This is to provide sources preview to wxpython.html. - # The dictionary of functions is binded to "window.sources". - thisModule = sys.modules[__name__] - functions = inspect.getmembers(thisModule, inspect.isfunction) - classes = inspect.getmembers(thisModule, inspect.isclass) - sources = {} - for funcTuple in functions: - sources[funcTuple[0]] = inspect.getsource(funcTuple[1]) - for classTuple in classes: - className = classTuple[0] - classObject = classTuple[1] - methods = inspect.getmembers(classObject) - for methodTuple in methods: - try: - sources[methodTuple[0]] = inspect.getsource(\ - methodTuple[1]) - except: - pass - return sources - -if __name__ == '__main__': - print('[wxpython.py] architecture=%s-bit' % (8 * struct.calcsize("P"))) - print('[wxpython.py] wx.version=%s' % wx.version()) - - # Intercept python exceptions. Exit app immediately when exception - # happens on any of the threads. - sys.excepthook = ExceptHook - - # Application settings - g_applicationSettings = { - # Disk cache - # "cache_path": "webcache/", - - # CEF Python debug messages in console and in log_file - "debug": True, - # Set it to LOGSEVERITY_VERBOSE for more details - "log_severity": cefpython.LOGSEVERITY_INFO, - # Set to "" to disable logging to a file - "log_file": GetApplicationPath("debug.log"), - - # "resources_dir_path" must be set on Mac, "locales_dir_path" not. - # You must also set "locale_pak" using command line switch. - "resources_dir_path": cefpython.GetModuleDirectory()+"/Resources", - # The "subprocess" executable that launches the Renderer - # and GPU processes among others. You may rename that - # executable if you like. - "browser_subprocess_path": "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess"), - - # This option is required for the GetCookieManager callback - # to work. It affects renderer processes, when this option - # is set to True. It will force a separate renderer process - # for each browser created using CreateBrowserSync. - "unique_request_context_per_browser": True, - - # Downloads are handled automatically. A default SaveAs file - # dialog provided by OS will be displayed. - "downloads_enabled": True, - - # Remote debugging port, required for Developer Tools support. - # A value of 0 will generate a random port. To disable devtools - # support set it to -1. - "remote_debugging_port": 0, - - # Mouse context menu - "context_menu": { - "enabled": True, - "navigation": True, # Back, Forward, Reload - "print": True, - "view_source": True, - "external_browser": True, # Open in external browser - "devtools": True, # Developer Tools - }, - - # See also OnCertificateError which allows you to ignore - # certificate errors for specific websites. - "ignore_certificate_errors": False, - } - - # Browser settings. You may have different settings for each - # browser, see the call to CreateBrowserSync. - g_browserSettings = { - # "plugins_disabled": True, - # "file_access_from_file_urls_allowed": True, - # "universal_access_from_file_urls_allowed": True, - } - - # Command line switches set programmatically - g_switches = { - # On Mac it is required to provide path to a specific - # locale.pak file. On Win/Linux you only specify the - # ApplicationSettings.locales_dir_path option. - "locale_pak": cefpython.GetModuleDirectory() - +"/Resources/en.lproj/locale.pak", - - # "proxy-server": "socks5://127.0.0.1:8888", - # "no-proxy-server": "", - # "enable-media-stream": "", - # "remote-debugging-port": "12345", - # "disable-gpu": "", - # "--invalid-switch": "" -> Invalid switch name - } - - cefpython.Initialize(g_applicationSettings, g_switches) - - app = MyApp(False) - app.MainLoop() - - # Let wx.App destructor do the cleanup before calling - # cefpython.Shutdown(). This is to ensure reliable CEF shutdown. - del app - - # On Mac cefpython.Shutdown() is called in MainFrame.OnClose, - # followed by wx.GetApp.Exit(). From 039a4614c7242a0b107fdceaf7f04bd271f6fbe8 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 1 Mar 2017 20:12:30 +0100 Subject: [PATCH 147/557] Fix errors in tkinter_.py example on Mac (#306, #308). Fix tkinter error on Mac "unrecognized selector sent to instance" (Issue #306"). CEF must be initialized after Tk. Fix error with winfo_id() returning a negative value (Issue #308). This was resolved by obtaining NSView pointer using PyObjC package. There is yet another error "Segmentation fault: 11" which crashes app often, however it's hard to debug it (Issue #309). --- docs/Knowledge-Base.md | 5 +- examples/tkinter_.py | 231 +++++++++++++++++++++++------------------ tools/run_examples.py | 5 +- 3 files changed, 135 insertions(+), 106 deletions(-) diff --git a/docs/Knowledge-Base.md b/docs/Knowledge-Base.md index 591b98376..09c3edc78 100644 --- a/docs/Knowledge-Base.md +++ b/docs/Knowledge-Base.md @@ -69,7 +69,7 @@ settings: ``` cefpython_package/ cefpython_py27.so - rpath=@loader_path + rpath=@loader_path/ load:@rpath/Chromium Embedded Framework.framework/Chromium Embedded Framework Chromium Embedded Framework.framework/ Chromium Embedded Framework @@ -117,7 +117,8 @@ release perform the following steps: (http://opensource.spotify.com/cefbuilds/index.html) and download latest CEF for your platform. Choose "Standard Distribution" binaries. -3. Follow the instructions in `CMakeLists.txt` file +3. Follow the instructions in `CMakeLists.txt` file, choose steps + for building using Ninja 4. Run either cefclient or cefsimple to test features diff --git a/examples/tkinter_.py b/examples/tkinter_.py index aed1279ce..dcf6b6d8a 100644 --- a/examples/tkinter_.py +++ b/examples/tkinter_.py @@ -1,10 +1,12 @@ # Example of embedding CEF Python browser using Tkinter toolkit. # This example has two widgets: a navigation bar and a browser. # -# NOTE: This example doesn't work on Mac, details in Issue #306. +# NOTE: This example often crashes on Mac (Tk 8.5) during initial +# app loading with such message: "Segmentation fault: 11". +# Reported as Issue #309. # # Tested configurations: -# - Tk 8.5 on Windows +# - Tk 8.5 on Windows/Mac # - Tk 8.6 on Linux # - CEF Python v55.3+ # @@ -32,8 +34,10 @@ # Globals logger = _logging.getLogger("tkinter_.py") -# Python 2.7 on Windows comes with Tk 8.5 which doesn't support PNG images -IMAGE_EXT = ".gif" if WINDOWS else ".png" + +# Constants +# Tk 8.5 doesn't support png images +IMAGE_EXT = ".png" if tk.TkVersion > 8.5 else ".gif" def main(): @@ -47,25 +51,27 @@ def main(): logger.info("Tk {ver}".format(ver=tk.Tcl().eval('info patchlevel'))) assert cef.__version__ >= "55.3", "CEF Python v55.3+ required to run this" sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error + root = tk.Tk() + app = MainFrame(root) + # Tk must be initialized before CEF otherwise fatal error (Issue #306) cef.Initialize() - app = MainFrame(tk.Tk()) app.mainloop() cef.Shutdown() class MainFrame(tk.Frame): - def __init__(self, master): + def __init__(self, root): self.browser_frame = None self.navigation_bar = None # Root - master.geometry("800x600") - tk.Grid.rowconfigure(master, 0, weight=1) - tk.Grid.columnconfigure(master, 0, weight=1) + root.geometry("800x600") + tk.Grid.rowconfigure(root, 0, weight=1) + tk.Grid.columnconfigure(root, 0, weight=1) # MainFrame - tk.Frame.__init__(self, master) + tk.Frame.__init__(self, root) self.master.title("Tkinter example") self.master.protocol("WM_DELETE_WINDOW", self.on_close) self.master.bind("", self.on_root_configure) @@ -135,6 +141,119 @@ def setup_icon(self): self.master.call("wm", "iconphoto", self.master._w, self.icon) +class BrowserFrame(tk.Frame): + + def __init__(self, master, navigation_bar=None): + self.navigation_bar = navigation_bar + self.closing = False + self.browser = None + tk.Frame.__init__(self, master) + self.bind("", self.on_focus_in) + self.bind("", self.on_focus_out) + self.bind("", self.on_configure) + self.focus_set() + + def embed_browser(self): + window_info = cef.WindowInfo() + rect = [0, 0, self.winfo_width(), self.winfo_height()] + window_info.SetAsChild(self.get_window_handle(), rect) + self.browser = cef.CreateBrowserSync(window_info, + url="https://www.google.com/") + assert self.browser + self.browser.SetClientHandler(LoadHandler(self)) + self.browser.SetClientHandler(FocusHandler(self)) + self.message_loop_work() + + def get_window_handle(self): + if self.winfo_id() > 0: + return self.winfo_id() + elif MAC: + # On Mac window id is an invalid negative value (Issue #308). + # This is kind of a dirty hack to get window handle using + # PyObjC package. If you change structure of windows then you + # need to do modifications here as well. + # noinspection PyUnresolvedReferences + from AppKit import NSApp + # noinspection PyUnresolvedReferences + import objc + # Sometimes there is more than one window, when application + # didn't close cleanly last time Python displays an NSAlert + # window asking whether to Reopen that window. + # noinspection PyUnresolvedReferences + return objc.pyobjc_id(NSApp.windows()[-1].contentView()) + else: + raise Exception("Couldn't obtain window handle") + + def message_loop_work(self): + cef.MessageLoopWork() + self.after(10, self.message_loop_work) + + def on_configure(self, _): + if not self.browser: + self.embed_browser() + + def on_root_configure(self): + # Root event will be called when top window is moved + if self.browser: + self.browser.NotifyMoveOrResizeStarted() + + def on_mainframe_configure(self, width, height): + if self.browser: + if WINDOWS: + WindowUtils.OnSize(self.get_window_handle(), 0, 0, 0) + elif LINUX: + self.browser.SetBounds(0, 0, width, height) + self.browser.NotifyMoveOrResizeStarted() + + def on_focus_in(self, _): + logger.debug("BrowserFrame.on_focus_in") + if self.browser: + self.browser.SetFocus(True) + + def on_focus_out(self, _): + logger.debug("BrowserFrame.on_focus_out") + if self.browser: + self.browser.SetFocus(False) + + def on_root_close(self): + if self.browser: + # Close browser and free reference by setting to None + self.browser.CloseBrowser(True) + self.browser = None + self.destroy() + + +class LoadHandler(object): + + def __init__(self, browser_frame): + self.browser_frame = browser_frame + + def OnLoadStart(self, browser, **_): + if self.browser_frame.master.navigation_bar: + self.browser_frame.master.navigation_bar.set_url(browser.GetUrl()) + + +class FocusHandler(object): + + def __init__(self, browser_frame): + self.browser_frame = browser_frame + + def OnTakeFocus(self, next_component, **_): + logger.debug("FocusHandler.OnTakeFocus, next={next}" + .format(next=next_component)) + + def OnSetFocus(self, source, **_): + logger.debug("FocusHandler.OnSetFocus, source={source}" + .format(source=source)) + return False + + def OnGotFocus(self, **_): + """Fix CEF focus issues (#255). Call browser frame's focus_set + to get rid of type cursor in url entry widget.""" + logger.debug("FocusHandler.OnGotFocus") + self.browser_frame.focus_set() + + class NavigationBar(tk.Frame): def __init__(self, master): @@ -254,97 +373,5 @@ def __init__(self): # TODO: implement tabs -class BrowserFrame(tk.Frame): - - def __init__(self, master, navigation_bar=None): - self.navigation_bar = navigation_bar - self.closing = False - self.browser = None - tk.Frame.__init__(self, master) - self.bind("", self.on_focus_in) - self.bind("", self.on_focus_out) - self.bind("", self.on_configure) - self.focus_set() - - def embed_browser(self): - window_info = cef.WindowInfo() - window_info.SetAsChild(self.winfo_id()) - self.browser = cef.CreateBrowserSync(window_info, - url="https://www.google.com/") - assert self.browser - self.browser.SetClientHandler(LoadHandler(self)) - self.browser.SetClientHandler(FocusHandler(self)) - self.message_loop_work() - - def message_loop_work(self): - cef.MessageLoopWork() - self.after(10, self.message_loop_work) - - def on_configure(self, _): - if not self.browser: - self.embed_browser() - - def on_root_configure(self): - # Root event will be called when top window is moved - if self.browser: - self.browser.NotifyMoveOrResizeStarted() - - def on_mainframe_configure(self, width, height): - if self.browser: - if WINDOWS: - WindowUtils.OnSize(self.winfo_id(), 0, 0, 0) - elif LINUX: - self.browser.SetBounds(0, 0, width, height) - self.browser.NotifyMoveOrResizeStarted() - - def on_focus_in(self, _): - logger.debug("BrowserFrame.on_focus_in") - if self.browser: - self.browser.SetFocus(True) - - def on_focus_out(self, _): - logger.debug("BrowserFrame.on_focus_out") - if self.browser: - self.browser.SetFocus(False) - - def on_root_close(self): - if self.browser: - # Close browser and free reference by setting to None - self.browser.CloseBrowser(True) - self.browser = None - self.destroy() - - -class LoadHandler(object): - - def __init__(self, browser_frame): - self.browser_frame = browser_frame - - def OnLoadStart(self, browser, **_): - if self.browser_frame.master.navigation_bar: - self.browser_frame.master.navigation_bar.set_url(browser.GetUrl()) - - -class FocusHandler(object): - - def __init__(self, browser_frame): - self.browser_frame = browser_frame - - def OnTakeFocus(self, next_component, **_): - logger.debug("FocusHandler.OnTakeFocus, next={next}" - .format(next=next_component)) - - def OnSetFocus(self, source, **_): - logger.debug("FocusHandler.OnSetFocus, source={source}" - .format(source=source)) - return False - - def OnGotFocus(self, **_): - """Fix CEF focus issues (#255). Call browser frame's focus_set - to get rid of type cursor in url entry widget.""" - logger.debug("FocusHandler.OnGotFocus") - self.browser_frame.focus_set() - - if __name__ == '__main__': main() diff --git a/tools/run_examples.py b/tools/run_examples.py index a89084e71..19066b6fe 100644 --- a/tools/run_examples.py +++ b/tools/run_examples.py @@ -65,8 +65,9 @@ def main(): print("[run_examples.py] PASS: qt.py pyside (PySide not installed)") passed.append("qt.py pyside") - # tkinter - if packages["tkinter"] or packages["Tkinter"]: + # tkinter. + # This example often crashes on Mac (Issue #309), so don't run it. + if not MAC and (packages["tkinter"] or packages["Tkinter"]): examples.append("tkinter_.py") else: print(["run_examples.py] PASS: tkinter_.py (tkinter not installed)"]) From 23a6c629257aafde938f910d06e4498d71ec590b Mon Sep 17 00:00:00 2001 From: cztomczak Date: Fri, 3 Mar 2017 17:22:15 +0100 Subject: [PATCH 148/557] Mac v56 release almost ready (#295)... Fixes to examples and build tools on Mac. Update to CEF 3.2924.1575.g97389a9 on Mac. Support automate.py --prebuilt-cef on Mac. Fix qt4.py example on Mac. Rename qt.py to qt4.py. Fix gtk2.py example on Mac. On Mac the gtk2.py example forces CEF message loop by default. You can enable debug information in all examples by passing --debug flag. Added info to KB. Add instructions on how to debug "segmentation fault" crash on Linux and Mac in the Knowledge Base document. Update all examples to add detailed notes about clearing all browser references for CEF to shutdown cleanly. Rename build_module.py tool to cython_setup.py. Enhance sudo detection in build.py. Increase time for message loop to 1 sec, otherwise tests sometimes fail with error: > AssertionError: Check assert: > LoadHandler.FrameSourceVisitor_True Create API.md document which links to root api/ directory. Enhance linking in api/ reference, in top headers and in API index. --- api/API-index.md | 76 +++--- docs/API.md | 3 + docs/Knowledge-Base.md | 54 ++++ examples/gtk2.py | 64 +++-- examples/gtk3.py | 68 +++-- examples/{qt.py => qt4.py} | 294 +++++++++------------ examples/tkinter_.py | 14 +- examples/wxpython.py | 2 +- src/cefpython.pyx | 11 +- src/include/internal/cef_types_wrappers.h | 7 +- src/version/cef_version_mac.h | 6 +- tools/apidocs.py | 6 +- tools/automate.py | 129 +++++++-- tools/build.py | 10 +- tools/common.py | 27 +- tools/{build_module.py => cython_setup.py} | 26 +- tools/run_examples.py | 40 +-- unittests/main_test.py | 4 +- 18 files changed, 514 insertions(+), 327 deletions(-) create mode 100644 docs/API.md rename examples/{qt.py => qt4.py} (74%) rename tools/{build_module.py => cython_setup.py} (94%) diff --git a/api/API-index.md b/api/API-index.md index 94fb0c726..3fe74ca2e 100644 --- a/api/API-index.md +++ b/api/API-index.md @@ -1,8 +1,8 @@ -[API categories](API-categories.md) | [API index](API-index.md) +[API categories](API-categories.md#api-categories) | [API index](API-index.md#api-index) # API index -* [Application settings](ApplicationSettings.md) +* [Application settings](ApplicationSettings.md#application-settings) * [accept_language_list](ApplicationSettings.md#accept_language_list) * [auto_zooming](ApplicationSettings.md#auto_zooming) * [background_color](ApplicationSettings.md#background_color) @@ -35,7 +35,7 @@ * [user_agent](ApplicationSettings.md#user_agent) * [user_data_path](ApplicationSettings.md#user_data_path) * [windowless_rendering_enabled](ApplicationSettings.md#windowless_rendering_enabled) -* [Browser (object)](Browser.md) +* [Browser (object)](Browser.md#browser-object) * [AddWordToDictionary](Browser.md#addwordtodictionary) * [CanGoBack](Browser.md#cangoback) * [CanGoForward](Browser.md#cangoforward) @@ -109,7 +109,7 @@ * [TryCloseBrowser](Browser.md#tryclosebrowser) * [WasResized](Browser.md#wasresized) * [WasHidden](Browser.md#washidden) -* [Browser settings](BrowserSettings.md) +* [Browser settings](BrowserSettings.md#browser-settings) * [Font settings](BrowserSettings.md#font-settings) * [accept_language_list](BrowserSettings.md#accept_language_list) * [application_cache_disabled](BrowserSettings.md#application_cache_disabled) @@ -134,10 +134,10 @@ * [web_security_disabled](BrowserSettings.md#web_security_disabled) * [webgl_disabled](BrowserSettings.md#webgl_disabled) * [windowless_frame_rate](BrowserSettings.md#windowless_frame_rate) -* [Callback (object)](Callback.md) +* [Callback (object)](Callback.md#callback-object) * [Continue](Callback.md#continue) * [Cancel](Callback.md#cancel) -* [cefpython](cefpython.md) +* [cefpython](cefpython.md#cefpython) * [CreateBrowser](cefpython.md#createbrowser) * [CreateBrowserSync](cefpython.md#createbrowsersync) * [ExceptHook](cefpython.md#excepthook) @@ -156,12 +156,12 @@ * [SetGlobalClientCallback](cefpython.md#setglobalclientcallback) * [SetOsModalLoop](cefpython.md#setosmodalloop) * [Shutdown](cefpython.md#shutdown) -* [Command line switches](CommandLineSwitches.md) +* [Command line switches](CommandLineSwitches.md#command-line-switches) * [enable-media-stream](CommandLineSwitches.md#enable-media-stream) * [proxy-server](CommandLineSwitches.md#proxy-server) * [no-proxy-server](CommandLineSwitches.md#no-proxy-server) * [disable-gpu](CommandLineSwitches.md#disable-gpu) -* [Cookie (class)](Cookie.md) +* [Cookie (class)](Cookie.md#cookie-class) * [Set](Cookie.md#set) * [Get](Cookie.md#get) * [SetName](Cookie.md#setname) @@ -184,7 +184,7 @@ * [GetHasExpires](Cookie.md#gethasexpires) * [SetExpires](Cookie.md#setexpires) * [GetExpires](Cookie.md#getexpires) -* [CookieManager (class)](CookieManager.md) +* [CookieManager (class)](CookieManager.md#cookiemanager-class) * [GetGlobalManager](CookieManager.md#getglobalmanager) * [CreateManager](CookieManager.md#createmanager) * [SetSupportedSchemes](CookieManager.md#setsupportedschemes) @@ -194,21 +194,21 @@ * [DeleteCookies](CookieManager.md#deletecookies) * [SetStoragePath](CookieManager.md#setstoragepath) * [FlushStore](CookieManager.md#flushstore) -* [CookieVisitor (interface)](CookieVisitor.md) +* [CookieVisitor (interface)](CookieVisitor.md#cookievisitor-interface) * [Visit](CookieVisitor.md#visit) -* [DisplayHandler (interface)](DisplayHandler.md) +* [DisplayHandler (interface)](DisplayHandler.md#displayhandler-interface) * [OnAddressChange](DisplayHandler.md#onaddresschange) * [OnTitleChange](DisplayHandler.md#ontitlechange) * [OnTooltip](DisplayHandler.md#ontooltip) * [OnStatusMessage](DisplayHandler.md#onstatusmessage) * [OnConsoleMessage](DisplayHandler.md#onconsolemessage) -* [DownloadHandler](DownloadHandler.md) -* [DpiAware (class)](DpiAware.md) +* [DownloadHandler](DownloadHandler.md#downloadhandler) +* [DpiAware (class)](DpiAware.md#dpiaware-class) * [CalculateWindowSize](DpiAware.md#calculatewindowsize) * [GetSystemDpi](DpiAware.md#getsystemdpi) * [IsProcessDpiAware](DpiAware.md#isprocessdpiaware) * [SetProcessDpiAware](DpiAware.md#setprocessdpiaware) -* [DragData (object)](DragData.md) +* [DragData (object)](DragData.md#dragdata-object) * [IsLink](DragData.md#islink) * [IsFragment](DragData.md#isfragment) * [GetLinkUrl](DragData.md#getlinkurl) @@ -217,11 +217,11 @@ * [GetFragmentHtml](DragData.md#getfragmenthtml) * [GetImage](DragData.md#getimage) * [HasImage](DragData.md#hasimage) -* [FocusHandler (interface)](FocusHandler.md) +* [FocusHandler (interface)](FocusHandler.md#focushandler-interface) * [OnTakeFocus](FocusHandler.md#ontakefocus) * [OnSetFocus](FocusHandler.md#onsetfocus) * [OnGotFocus](FocusHandler.md#ongotfocus) -* [Frame (object)](Frame.md) +* [Frame (object)](Frame.md#frame-object) * [Copy](Frame.md#copy) * [Cut](Frame.md#cut) * [Delete](Frame.md#delete) @@ -248,42 +248,42 @@ * [SetProperty](Frame.md#setproperty) * [Undo](Frame.md#undo) * [ViewSource](Frame.md#viewsource) -* [Image (object)](Image.md) +* [Image (object)](Image.md#image-object) * [GetAsBitmap](Image.md#getasbitmap) * [GetAsPng](Image.md#getaspng) * [GetHeight](Image.md#getheight) * [GetWidth](Image.md#getwidth) -* [JavascriptBindings (class)](JavascriptBindings.md) +* [JavascriptBindings (class)](JavascriptBindings.md#javascriptbindings-class) * [\_\_init\_\_](JavascriptBindings.md#__init__) * [IsValueAllowed](JavascriptBindings.md#isvalueallowed) * [Rebind](JavascriptBindings.md#rebind) * [SetFunction](JavascriptBindings.md#setfunction) * [SetObject](JavascriptBindings.md#setobject) * [SetProperty](JavascriptBindings.md#setproperty) -* [JavascriptCallback (object)](JavascriptCallback.md) +* [JavascriptCallback (object)](JavascriptCallback.md#javascriptcallback-object) * [Call](JavascriptCallback.md#call) * [GetName](JavascriptCallback.md#getname) -* [JavascriptDialogHandler (interface)](JavascriptDialogHandler.md) +* [JavascriptDialogHandler (interface)](JavascriptDialogHandler.md#javascriptdialoghandler-interface) * [Continue](JavascriptDialogHandler.md#continue) * [OnJavascriptDialog](JavascriptDialogHandler.md#onjavascriptdialog) * [OnBeforeUnloadJavascriptDialog](JavascriptDialogHandler.md#onbeforeunloadjavascriptdialog) * [OnResetJavascriptDialogState](JavascriptDialogHandler.md#onresetjavascriptdialogstate) * [OnJavascriptDialogClosed](JavascriptDialogHandler.md#onjavascriptdialogclosed) -* [KeyboardHandler (interface)](KeyboardHandler.md) +* [KeyboardHandler (interface)](KeyboardHandler.md#keyboardhandler-interface) * [OnPreKeyEvent](KeyboardHandler.md#onprekeyevent) * [OnKeyEvent](KeyboardHandler.md#onkeyevent) -* [LifespanHandler (interface)](LifespanHandler.md) +* [LifespanHandler (interface)](LifespanHandler.md#lifespanhandler-interface) * [OnBeforePopup](LifespanHandler.md#onbeforepopup) * [_OnAfterCreated](LifespanHandler.md#_onaftercreated) * [DoClose](LifespanHandler.md#doclose) * [OnBeforeClose](LifespanHandler.md#onbeforeclose) -* [LoadHandler (interface)](LoadHandler.md) +* [LoadHandler (interface)](LoadHandler.md#loadhandler-interface) * [OnLoadingStateChange](LoadHandler.md#onloadingstatechange) * [OnLoadStart](LoadHandler.md#onloadstart) * [OnDomReady](LoadHandler.md#ondomready) * [OnLoadEnd](LoadHandler.md#onloadend) * [OnLoadError](LoadHandler.md#onloaderror) -* [Network error](NetworkError.md) +* [Network error](NetworkError.md#network-error) * [ERR_NONE](NetworkError.md#err_none) * [ERR_ABORTED](NetworkError.md#err_aborted) * [ERR_ACCESS_DENIED](NetworkError.md#err_access_denied) @@ -333,10 +333,10 @@ * [ERR_UNKNOWN_URL_SCHEME](NetworkError.md#err_unknown_url_scheme) * [ERR_UNSAFE_PORT](NetworkError.md#err_unsafe_port) * [ERR_UNSAFE_REDIRECT](NetworkError.md#err_unsafe_redirect) -* [PaintBuffer (object)](PaintBuffer.md) +* [PaintBuffer (object)](PaintBuffer.md#paintbuffer-object) * [GetIntPointer](PaintBuffer.md#getintpointer) * [GetString](PaintBuffer.md#getstring) -* [RenderHandler (interface)](RenderHandler.md) +* [RenderHandler (interface)](RenderHandler.md#renderhandler-interface) * [GetRootScreenRect](RenderHandler.md#getrootscreenrect) * [GetViewRect](RenderHandler.md#getviewrect) * [GetScreenRect](RenderHandler.md#getscreenrect) @@ -348,7 +348,7 @@ * [OnScrollOffsetChanged](RenderHandler.md#onscrolloffsetchanged) * [StartDragging](RenderHandler.md#startdragging) * [UpdateDragCursor](RenderHandler.md#updatedragcursor) -* [Request (class)](Request.md) +* [Request (class)](Request.md#request-class) * [CreateRequest](Request.md#createrequest) * [IsReadOnly](Request.md#isreadonly) * [GetUrl](Request.md#geturl) @@ -367,7 +367,7 @@ * [SetFirstPartyForCookies](Request.md#setfirstpartyforcookies) * [GetResourceType](Request.md#getresourcetype) * [GetTransitionType](Request.md#gettransitiontype) -* [RequestHandler (interface)](RequestHandler.md) +* [RequestHandler (interface)](RequestHandler.md#requesthandler-interface) * [OnBeforeBrowse](RequestHandler.md#onbeforebrowse) * [OnBeforeResourceLoad](RequestHandler.md#onbeforeresourceload) * [GetResourceHandler](RequestHandler.md#getresourcehandler) @@ -381,14 +381,14 @@ * [_OnCertificateError](RequestHandler.md#_oncertificateerror) * [OnRendererProcessTerminated](RequestHandler.md#onrendererprocessterminated) * [OnPluginCrashed](RequestHandler.md#onplugincrashed) -* [ResourceHandler (interface)](ResourceHandler.md) +* [ResourceHandler (interface)](ResourceHandler.md#resourcehandler-interface) * [ProcessRequest](ResourceHandler.md#processrequest) * [GetResponseHeaders](ResourceHandler.md#getresponseheaders) * [ReadResponse](ResourceHandler.md#readresponse) * [CanGetCookie](ResourceHandler.md#cangetcookie) * [CanSetCookie](ResourceHandler.md#cansetcookie) * [Cancel](ResourceHandler.md#cancel) -* [Response (object)](Response.md) +* [Response (object)](Response.md#response-object) * [IsReadOnly](Response.md#isreadonly) * [GetStatus](Response.md#getstatus) * [SetStatus](Response.md#setstatus) @@ -401,35 +401,35 @@ * [GetHeaderMultimap](Response.md#getheadermultimap) * [SetHeaderMap](Response.md#setheadermap) * [SetHeaderMultimap](Response.md#setheadermultimap) -* [StringVisitor (interface)](StringVisitor.md) +* [StringVisitor (interface)](StringVisitor.md#stringvisitor-interface) * [Visit](StringVisitor.md#visit) -* [V8ContextHandler (interface)](V8ContextHandler.md) +* [V8ContextHandler (interface)](V8ContextHandler.md#v8contexthandler-interface) * [OnContextCreated](V8ContextHandler.md#oncontextcreated) * [OnContextReleased](V8ContextHandler.md#oncontextreleased) -* [Virtual Key codes](VirtualKey.md) -* [WebPluginInfo (object)](WebPluginInfo.md) +* [Virtual Key codes](VirtualKey.md#virtual-key-codes) +* [WebPluginInfo (object)](WebPluginInfo.md#webplugininfo-object) * [GetName](WebPluginInfo.md#getname) * [GetPath](WebPluginInfo.md#getpath) * [GetVersion](WebPluginInfo.md#getversion) * [GetDescription](WebPluginInfo.md#getdescription) -* [WebRequest (class)](WebRequest.md) +* [WebRequest (class)](WebRequest.md#webrequest-class) * [Create](WebRequest.md#create) * [GetRequest](WebRequest.md#getrequest) * [GetRequestStatus](WebRequest.md#getrequeststatus) * [GetRequestError](WebRequest.md#getrequesterror) * [GetResponse](WebRequest.md#getresponse) * [Cancel](WebRequest.md#cancel) -* [WebRequestClient (interface)](WebRequestClient.md) +* [WebRequestClient (interface)](WebRequestClient.md#webrequestclient-interface) * [OnUploadProgress](WebRequestClient.md#onuploadprogress) * [OnDownloadProgress](WebRequestClient.md#ondownloadprogress) * [OnDownloadData](WebRequestClient.md#ondownloaddata) * [OnRequestComplete](WebRequestClient.md#onrequestcomplete) -* [WindowInfo (class)](WindowInfo.md) +* [WindowInfo (class)](WindowInfo.md#windowinfo-class) * [SetAsChild](WindowInfo.md#setaschild) * [SetAsPopup](WindowInfo.md#setaspopup) * [SetAsOffscreen](WindowInfo.md#setasoffscreen) * [SetTransparentPainting](WindowInfo.md#settransparentpainting) -* [WindowUtils (class)](WindowUtils.md) +* [WindowUtils (class)](WindowUtils.md#windowutils-class) * [OnSetFocus ](WindowUtils.md#onsetfocus-win) * [OnSize ](WindowUtils.md#onsize-win) * [OnEraseBackground ](WindowUtils.md#onerasebackground-win) diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 000000000..85df057cc --- /dev/null +++ b/docs/API.md @@ -0,0 +1,3 @@ +# API + +API reference is available in the root [api/](../api) directory. diff --git a/docs/Knowledge-Base.md b/docs/Knowledge-Base.md index 09c3edc78..73aa95b6b 100644 --- a/docs/Knowledge-Base.md +++ b/docs/Knowledge-Base.md @@ -10,6 +10,7 @@ Table of contents: * [How to capture Audio and Video in HTML5?](#how-to-capture-audio-and-video-in-html5) * [Touch and multi-touch support](#touch-and-multi-touch-support) * [Black or white browser screen](#black-or-white-browser-screen) +* [Python crashes with "Segmentation fault" - how to debug?](#python-crashes-with-segmentation-fault-how-to-debug) * [Windows XP support](#windows-xp-support) * [Mac 32-bit support](#mac-32-bit-support) * [Security](#security) @@ -164,6 +165,59 @@ appear even after disabling GPU hardware acceleration. This is normal because GPU was disabled so WebGL cannot work. +## How to enable debug information in examples? + +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} +cef.Initialize(settings=settings) +``` + +Now you should see debug information displayed in console like this: +``` +[CEF Python] Initialize() called +[CEF Python] CefExecuteProcess(): exitCode = -1 +[CEF Python] CefInitialize() +[CEF Python] App_OnBeforeCommandLineProcessing_BrowserProcess() +[CEF Python] Command line string for the browser process: ... +``` + + +## Python crashes with "Segmentation fault" - how to debug? + +Install gdb: +- On Linux type: `sudo apt-get install gdb` +- On Mac type: `brew install gdb` and then [sign gdb] + (https://sourceware.org/gdb/wiki/BuildingOnDarwin#Giving_gdb_permission_to_control_other_processes) +- Additionally on Mac to get a meaningful stack trace with gdb do these steps: + - Install [macports](https://www.macports.org/install.php) + and restart terminal + - Type `sudo port install gdb-apple` + - Type `sudo codesign -s "gdb-cert" /opt/local/bin/gdb-apple` + - Type `/opt/local/bin/gdb-apple python` + +Run python script using gdb: +``` +gdb python +run tkinter_.py +``` + +On segmentation fault to display stack trace type: +``` +bt +``` + +On Mac to use lldb: +``` +lldb python +run tkinter_.py +bt +``` + + ## Windows XP support CEF Python v31.2 was the last version to support Windows XP. This is diff --git a/examples/gtk2.py b/examples/gtk2.py index c7b4c84b6..fafe46d88 100644 --- a/examples/gtk2.py +++ b/examples/gtk2.py @@ -1,6 +1,8 @@ -# Example of embedding CEF Python browser using PyGTK library (GTK 2). -# Tested with GTK 2.24 and CEF Python v55.3+, on Windows/Linux. -# Known issue on Linux: Keyboard focus problem (Issue #284). +# Example of embedding CEF browser using PyGTK library (GTK 2). + +# Tested configurations: +# - GTK 2.24 on Windows/Linux/Mac +# - CEF Python v55.3+ from cefpython3 import cefpython as cef import pygtk @@ -10,7 +12,7 @@ import os import platform -# Fix for PyCharm hints warnings +# Fix for PyCharm hints warnings when using static methods WindowUtils = cef.WindowUtils() # Platforms @@ -18,13 +20,15 @@ LINUX = (platform.system() == "Linux") MAC = (platform.system() == "Darwin") -# In CEF you can run message loop in two ways (see API docs for more details): +# In CEF you can run message loop in two ways (see API ref for more details): # 1. By calling cef.MessageLoopWork() in a timer - each call performs # a single iteration of CEF message loop processing. # 2. By calling cef.MessageLoop() instead of an application-provided # message loop to get the best balance between performance and CPU # usage. This function will block until a quit message is received by # the system. This seem to work only on Linux in GTK example. +# NOTE: On Mac message loop timer doesn't work, so using CEF message +# loop by default. MESSAGE_LOOP_TIMER = 1 MESSAGE_LOOP_CEF = 2 # Pass --message-loop-cef flag to script on Linux g_message_loop = None @@ -55,6 +59,9 @@ def check_versions(): def configure_message_loop(): global g_message_loop + if MAC and "--message-loop-cef" not in sys.argv: + print("[gtk2.py] Force --message-loop-cef flag on Mac") + sys.argv.append("--message-loop-cef") if "--message-loop-cef" in sys.argv: print("[gkt2.py] Message loop mode: CEF (best performance)") g_message_loop = MESSAGE_LOOP_CEF @@ -62,14 +69,11 @@ def configure_message_loop(): else: print("[gkt2.py] Message loop mode: TIMER") g_message_loop = MESSAGE_LOOP_TIMER - if len(sys.argv) > 1: - print("[gkt2.py] ERROR: unknown argument passed") - sys.exit(1) class Gtk2Example: - def __init__(self): + self.browser = None self.menubar_height = 0 self.exiting = False @@ -91,11 +95,7 @@ def __init__(self): self.vbox.pack_start(self.menubar, False, False, 0) self.main_window.add(self.vbox) - windowInfo = cef.WindowInfo() - windowInfo.SetAsChild(self.get_handle()) - self.browser = cef.CreateBrowserSync(windowInfo, settings={}, - url="https://www.google.com/") - self.browser.SetClientHandler(LoadHandler()) + self.embed_browser() self.vbox.show() self.main_window.show() @@ -104,11 +104,22 @@ def __init__(self): if g_message_loop == MESSAGE_LOOP_TIMER: gobject.timeout_add(10, self.on_timer) - def get_handle(self): - if LINUX: - return self.main_window.window.xid - else: + def embed_browser(self): + windowInfo = cef.WindowInfo() + size = self.main_window.get_size() + rect = [0, 0, size[0], size[1]] + windowInfo.SetAsChild(self.get_window_handle(), rect) + self.browser = cef.CreateBrowserSync(windowInfo, settings={}, + url="https://www.google.com/") + self.browser.SetClientHandler(LoadHandler()) + + def get_window_handle(self): + if WINDOWS: return self.main_window.window.handle + elif LINUX: + return self.main_window.window.xid + elif MAC: + return self.main_window.window.nsview def create_menu(self): item1 = gtk.MenuItem('MenuBar') @@ -147,7 +158,7 @@ def on_vbox_size_allocate(self, _, data): width = data.width height = data.height - self.menubar_height if WINDOWS: - WindowUtils.OnSize(self.get_handle(), 0, 0, 0) + WindowUtils.OnSize(self.get_window_handle(), 0, 0, 0) elif LINUX: self.browser.SetBounds(x, y, width, height) @@ -160,28 +171,29 @@ def on_exit(self, *_): return self.exiting = True self.browser.CloseBrowser(True) - self.browser = None + self.clear_browser_references() if g_message_loop == MESSAGE_LOOP_CEF: cef.QuitMessageLoop() else: gtk.main_quit() + def clear_browser_references(self): + # Clear browser references that you keep anywhere in your + # code. All references must be cleared for CEF to shutdown cleanly. + self.browser = None + class LoadHandler(object): - def __init__(self): self.initial_app_loading = True def OnLoadStart(self, browser, **_): if self.initial_app_loading: # Temporary fix for focus issue during initial loading - # on Linux (Issue #284). If this is not applied then - # sometimes during initial loading, keyboard focus may - # break and it is not possible to type anything, even - # though a type cursor blinks in web view. + # on Linux (Issue #284). if LINUX: print("[gtk2.py] LoadHandler.OnLoadStart:" - " keyboard focus fix (#284)") + " keyboard focus fix (Issue #284)") browser.SetFocus(True) self.initial_app_loading = False diff --git a/examples/gtk3.py b/examples/gtk3.py index 2223362b0..1e2caf04c 100644 --- a/examples/gtk3.py +++ b/examples/gtk3.py @@ -1,8 +1,12 @@ # Example of embedding CEF Python browser using PyGObject/PyGI (GTK 3). - +# +# Mac note: This example crashes on Mac with error message: +# > _createMenuRef called with existing principal MenuRef.. +# Reported as Issue #310. +# # Linux note: This example is currently broken in v54+ on Linux (Issue #261). # It works fine with cefpython v53. - +# # Tested configurations: # - GTK 3.18 on Windows # - GTK 3.10 on Linux @@ -10,13 +14,16 @@ from cefpython3 import cefpython as cef import ctypes -# noinspection PyUnresolvedReferences -from gi.repository import Gtk, GObject, Gdk, GdkPixbuf -import sys +import gi import os import platform +import sys + +gi.require_version("Gtk", "3.0") +# noinspection PyUnresolvedReferences +from gi.repository import Gtk, GObject, Gdk, GdkPixbuf # noqa -# Fix for PyCharm hints warnings +# Fix for PyCharm hints warnings when using static methods WindowUtils = cef.WindowUtils() # Platforms @@ -37,7 +44,11 @@ def main(): major=Gtk.get_major_version(), minor=Gtk.get_minor_version())) assert cef.__version__ >= "53.1", "CEF Python v53.1+ required to run this" - sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error + if not MAC: + # On Mac exception hook doesn't work and is causing a strange error: + # > Python[57738:d07] _createMenuRef called with existing principal + # > MenuRef already associated with menu + sys.excepthook = cef.ExceptHook # To shutdown CEF processes on error cef.Initialize() app = Gtk3Example() SystemExit(app.run(sys.argv)) @@ -54,31 +65,36 @@ def __init__(self): def run(self, argv): GObject.threads_init() GObject.timeout_add(10, self.on_timer) + self.connect("startup", self.on_startup) self.connect("activate", self.on_activate) self.connect("shutdown", self.on_shutdown) return super(Gtk3Example, self).run(argv) def get_handle(self): - if LINUX: - return self.window.get_property("window").get_xid() - elif WINDOWS: + if WINDOWS: Gdk.threads_enter() ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p ctypes.pythonapi.PyCapsule_GetPointer.argtypes = \ [ctypes.py_object] gpointer = ctypes.pythonapi.PyCapsule_GetPointer( self.window.get_property("window").__gpointer__, None) - gdk_dll = ctypes.CDLL("libgdk-3-0.dll") - self.win32_handle = gdk_dll.gdk_win32_window_get_handle( - gpointer) + libgdk = ctypes.CDLL("libgdk-3-0.dll") + self.win32_handle = libgdk.gdk_win32_window_get_handle(gpointer) Gdk.threads_leave() return self.win32_handle + elif LINUX: + return self.window.get_property("window").get_xid() + elif MAC: + # TODO: Must call libgdk.gdk_quartz_window_get_nsview(gpointer) + # similarly as on Windows. + print("[gtk3.py] WARNING: get_handle not implemented on Mac") + return 0 def on_timer(self): cef.MessageLoopWork() return True - def on_activate(self, *_): + def on_startup(self, *_): self.window = Gtk.ApplicationWindow.new(self) self.window.set_title("GTK 3 example (PyGObject)") self.window.set_default_size(800, 600) @@ -86,17 +102,24 @@ def on_activate(self, *_): self.window.connect("size-allocate", self.on_size_allocate) self.window.connect("focus-in-event", self.on_focus_in) self.window.connect("delete-event", self.on_window_close) + self.add_window(self.window) self.setup_icon() + + def on_activate(self, *_): self.window.realize() - window_info = cef.WindowInfo() - window_info.SetAsChild(self.get_handle()) - self.browser = cef.CreateBrowserSync(window_info, - url="https://www.google.com/") + self.embed_browser() self.window.show_all() # Must set size of the window again after it was shown, # otherwise browser occupies only part of the window area. self.window.resize(*self.window.get_default_size()) + def embed_browser(self): + window_info = cef.WindowInfo() + # TODO: on Mac pass rect[x, y, width, height] to SetAsChild + window_info.SetAsChild(self.get_handle()) + self.browser = cef.CreateBrowserSync(window_info, + url="https://www.google.com/") + def on_configure(self, *_): if self.browser: self.browser.NotifyMoveOrResizeStarted() @@ -117,8 +140,13 @@ def on_focus_in(self, *_): return False def on_window_close(self, *_): - # Close browser and free reference by setting to None - self.browser.CloseBrowser(True) + if self.browser: + self.browser.CloseBrowser(True) + self.clear_browser_references() + + def clear_browser_references(self): + # Clear browser references that you keep anywhere in your + # code. All references must be cleared for CEF to shutdown cleanly. self.browser = None def on_shutdown(self, *_): diff --git a/examples/qt.py b/examples/qt4.py similarity index 74% rename from examples/qt.py rename to examples/qt4.py index 995f637fa..b5925ca37 100644 --- a/examples/qt.py +++ b/examples/qt4.py @@ -1,12 +1,14 @@ -# Example of embedding CEF Python browser using PyQt/PySide libraries. +# Example of embedding CEF browser using PyQt/PySide libraries. # This example has two widgets: a navigation bar and a browser. # # Tested configurations: -# - PyQt 4.11.4 (4.8.7) on Windows -# - PySide 1.2.4 (4.8.7) on Windows -# - PyQt 4.10.4 (4.8.6) on Linux -# - PySide 1.2.1 (4.8.6) 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): +# - Keyboard focus issues when switching between controls (Issue #284) +# - Mouse cursor never changes when hovering over links (Issue #311) from cefpython3 import cefpython as cef import ctypes @@ -32,11 +34,11 @@ from PySide.QtCore import * else: print("USAGE:") - print(" qt.py pyqt") - print(" qt.py pyside") + print(" qt4.py pyqt") + print(" qt4.py pyside") sys.exit(1) -# Fix for PyCharm hints warnings +# Fix for PyCharm hints warnings when using static methods WindowUtils = cef.WindowUtils() # Platforms @@ -62,31 +64,32 @@ def main(): app = CefApplication(sys.argv) main_window = MainWindow() main_window.show() + main_window.activateWindow() + main_window.raise_() app.exec_() app.stopTimer() - del main_window # Just to be safe, see below - del app # Must destroy before calling Shutdown + del main_window # Just to be safe, similarly to "del app" + del app # Must destroy app object before calling Shutdown cef.Shutdown() def check_versions(): - print("[qt.py] CEF Python {ver}".format(ver=cef.__version__)) - print("[qt.py] Python {ver}".format(ver=sys.version[:6])) + print("[qt4.py] CEF Python {ver}".format(ver=cef.__version__)) + print("[qt4.py] Python {ver}".format(ver=sys.version[:6])) # PyQt version if "pyqt" in sys.argv: # noinspection PyUnresolvedReferences - print("[qt.py] PyQt {v1} ({v2})".format( + print("[qt4.py] PyQt {v1} (qt {v2})".format( v1=PYQT_VERSION_STR, v2=qVersion())) # PySide version elif "pyside" in sys.argv: - print("[qt.py] PySide {v1} ({v2})".format( + print("[qt4.py] PySide {v1} (qt {v2})".format( v1=PySide.__version__, v2=QtCore.__version__)) # CEF Python version requirement - assert cef.__version__ >= "55.3", "CEF Python v55.3+ required to run this" + assert cef.__version__ >= "55.4", "CEF Python v55.+ required to run this" class MainWindow(QMainWindow): - def __init__(self): super(MainWindow, self).__init__(None) self.cef_widget = None @@ -115,126 +118,48 @@ def setupLayout(self): # Browser can be embedded only after layout was set up self.cef_widget.embedBrowser() - def focusInEvent(self, event): - # This event seems to never get called on Linux, as CEF is - # stealing all focus due to Issue #284. - # print("[qt.py] focusInEvent") - if self.cef_widget.browser: - if WINDOWS: - WindowUtils.OnSetFocus(self.cef_widget.getHandle(), - 0, 0, 0) - self.cef_widget.browser.SetFocus(True) - - def focusOutEvent(self, event): - # This event seems to never get called on Linux, as CEF is - # stealing all focus due to Issue #284. - # print("[qt.py] focusOutEvent") - pass - def closeEvent(self, event): # Close browser (force=True) and free CEF reference if self.cef_widget.browser: self.cef_widget.browser.CloseBrowser(True) - self.cef_widget.browser = None # free ref - - -class NavigationBar(QFrame): - - def __init__(self, cef_widget): - super(NavigationBar, self).__init__() - self.cef_widget = cef_widget - - # Init layout - layout = QGridLayout() - layout.setContentsMargins(0, 0, 0, 0) - layout.setSpacing(0) - - # 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) + self.clear_browser_references() - # Layout - self.setLayout(layout) - self.updateState() - - def onBack(self): - if self.cef_widget.browser: - self.cef_widget.browser.GoBack() - - def onForward(self): - if self.cef_widget.browser: - self.cef_widget.browser.GoForward() - - def onReload(self): - if self.cef_widget.browser: - self.cef_widget.browser.Reload() - - def onGoUrl(self): - if self.cef_widget.browser: - self.cef_widget.browser.LoadUrl(self.url.text()) - - def updateState(self): - browser = self.cef_widget.browser - if not browser: - self.back.setEnabled(False) - self.forward.setEnabled(False) - self.reload.setEnabled(False) - self.url.setEnabled(False) - return - self.back.setEnabled(browser.CanGoBack()) - self.forward.setEnabled(browser.CanGoForward()) - self.reload.setEnabled(True) - self.url.setEnabled(True) - self.url.setText(browser.GetUrl()) - - def createButton(self, name): - resources = os.path.join(os.path.abspath(os.path.dirname(__file__)), - "resources") - pixmap = QPixmap(os.path.join(resources, "{0}.png".format(name))) - icon = QIcon(pixmap) - button = QPushButton() - button.setIcon(icon) - button.setIconSize(pixmap.rect().size()) - return button + def clear_browser_references(self): + # Clear browser references that you keep anywhere in your + # code. All references must be cleared for CEF to shutdown cleanly. + self.cef_widget.browser = None class CefWidget(CefWidgetParent): - def __init__(self, parent=None): super(CefWidget, self).__init__(parent) self.parent = parent self.browser = None self.show() + def focusInEvent(self, event): + # This event seems to never get called on Linux, as CEF is + # stealing all focus due to Issue #284. + if self.browser: + if WINDOWS: + WindowUtils.OnSetFocus(self.cef_widget.getHandle(), + 0, 0, 0) + self.browser.SetFocus(True) + + def focusOutEvent(self, event): + # This event seems to never get called on Linux, as CEF is + # stealing all focus due to Issue #284. + if self.browser: + self.browser.SetFocus(False) + def embedBrowser(self): - self.width = 0 - self.height = 0 window_info = cef.WindowInfo() - window_info.SetAsChild(self.getHandle()) + rect = [0, 0, self.width(), self.height()] + window_info.SetAsChild(self.getHandle(), rect) self.browser = cef.CreateBrowserSync(window_info, url="https://www.google.com/") self.browser.SetClientHandler(LoadHandler(self.parent.navigation_bar)) - self.browser.SetClientHandler(FocusHandler()) + self.browser.SetClientHandler(FocusHandler(self)) def getHandle(self): # PySide bug: QWidget.winId() returns @@ -259,9 +184,6 @@ def getHandle(self): self.winId(), None) def moveEvent(self, _): - # pos = event.pos() - # self.x = pos.x() - # self.y = pos.y() self.x = 0 self.y = 0 if self.browser: @@ -269,24 +191,21 @@ def moveEvent(self, _): WindowUtils.OnSize(self.getHandle(), 0, 0, 0) elif LINUX: self.browser.SetBounds(self.x, self.y, - self.width, self.height) + self.width(), self.height()) self.browser.NotifyMoveOrResizeStarted() def resizeEvent(self, event): size = event.size() - self.width = size.width() - self.height = size.height() if self.browser: if WINDOWS: WindowUtils.OnSize(self.getHandle(), 0, 0, 0) elif LINUX: self.browser.SetBounds(self.x, self.y, - self.width, self.height) + size.width(), size.height()) self.browser.NotifyMoveOrResizeStarted() class CefApplication(QApplication): - def __init__(self, args): super(CefApplication, self).__init__(args) self.timer = self.createTimer() @@ -300,14 +219,6 @@ def createTimer(self): return timer def onTimer(self): - # For best performance, a proper way of doing message loop should - # probably be: - # 1. In createTimer() call self.timer.start(0) - # 2. In onTimer() call MessageLoopWork() only when - # QtGui.QApplication.instance()->hasPendingEvents() returns False. - # But... there is a bug in Qt, hasPendingEvents() always returns true. - # TODO: The bug above was noticed in Qt 4.8 on Windows. Other versions - # and/or other OSes may not be affected, so check it. cef.MessageLoopWork() def stopTimer(self): @@ -322,7 +233,6 @@ def setupIcon(self): class LoadHandler(object): - def __init__(self, navigation_bar): self.initial_app_loading = True self.navigation_bar = navigation_bar @@ -333,47 +243,107 @@ def OnLoadingStateChange(self, **_): def OnLoadStart(self, browser, **_): self.navigation_bar.url.setText(browser.GetUrl()) if self.initial_app_loading: - # Temporary fix no. 2 for focus issue during initial loading - # on Linux (Issue #284). If this is not applied then - # sometimes during initial loading, keyboard focus may - # break and it is not possible to type anything, even - # though a type cursor blinks in web view. + self.navigation_bar.cef_widget.setFocus() + # Temporary fix no. 2 for focus issue on Linux (Issue #284) if LINUX: - print("[qt.py] LoadHandler.OnLoadStart:" - " keyboard focus fix no. 2 (#284)") + print("[qt4.py] LoadHandler.OnLoadStart:" + " keyboard focus fix no. 2 (Issue #284)") browser.SetFocus(True) self.initial_app_loading = False class FocusHandler(object): + def __init__(self, cef_widget): + self.cef_widget = cef_widget - def __init__(self): - pass - - def OnTakeFocus(self, **kwargs): - # print("[qt.py] FocusHandler.OnTakeFocus, next={next}" - # .format(next=kwargs["next_component"]])) - pass - - def OnSetFocus(self, **kwargs): - # source_enum = {cef.FOCUS_SOURCE_NAVIGATION: "navigation", - # cef.FOCUS_SOURCE_SYSTEM: "system"} - # print("[qt.py] FocusHandler.OnSetFocus, source={source}" - # .format(source=source_enum[kwargs["source"]])) - # return False + def OnSetFocus(self, **_): pass def OnGotFocus(self, browser, **_): - # Temporary fix no. 1 for focus issues on Linux (Issue #284). - # If this is not applied then when switching to another - # window (alt+tab) and then back to this example, keyboard - # focus becomes broken, you can't type anything, even - # though a type cursor blinks in web view. + # Temporary fix no. 1 for focus issues on Linux (Issue #284) if LINUX: - print("[qt.py] FocusHandler.OnGotFocus:" - " keyboard focus fix no. 1 (#284)") + print("[qt4.py] FocusHandler.OnGotFocus:" + " keyboard focus fix no. 1 (Issue #284)") browser.SetFocus(True) +class NavigationBar(QFrame): + def __init__(self, cef_widget): + super(NavigationBar, self).__init__() + self.cef_widget = cef_widget + + # Init layout + layout = QGridLayout() + layout.setContentsMargins(0, 0, 0, 0) + layout.setSpacing(0) + + # 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) + + # Layout + self.setLayout(layout) + self.updateState() + + def onBack(self): + if self.cef_widget.browser: + self.cef_widget.browser.GoBack() + + def onForward(self): + if self.cef_widget.browser: + self.cef_widget.browser.GoForward() + + def onReload(self): + if self.cef_widget.browser: + self.cef_widget.browser.Reload() + + def onGoUrl(self): + if self.cef_widget.browser: + self.cef_widget.browser.LoadUrl(self.url.text()) + + def updateState(self): + browser = self.cef_widget.browser + if not browser: + self.back.setEnabled(False) + self.forward.setEnabled(False) + self.reload.setEnabled(False) + self.url.setEnabled(False) + return + self.back.setEnabled(browser.CanGoBack()) + self.forward.setEnabled(browser.CanGoForward()) + self.reload.setEnabled(True) + self.url.setEnabled(True) + self.url.setText(browser.GetUrl()) + + def createButton(self, name): + resources = os.path.join(os.path.abspath(os.path.dirname(__file__)), + "resources") + pixmap = QPixmap(os.path.join(resources, "{0}.png".format(name))) + icon = QIcon(pixmap) + button = QPushButton() + button.setIcon(icon) + button.setIconSize(pixmap.rect().size()) + return button + if __name__ == '__main__': main() diff --git a/examples/tkinter_.py b/examples/tkinter_.py index dcf6b6d8a..ad9cc06de 100644 --- a/examples/tkinter_.py +++ b/examples/tkinter_.py @@ -1,9 +1,9 @@ # Example of embedding CEF Python browser using Tkinter toolkit. # This example has two widgets: a navigation bar and a browser. # -# NOTE: This example often crashes on Mac (Tk 8.5) during initial -# app loading with such message: "Segmentation fault: 11". -# Reported as Issue #309. +# NOTE: This example often crashes on Mac (Python 2.7, Tk 8.5/8.6) +# during initial app loading with such message: +# "Segmentation fault: 11". Reported as Issue #309. # # Tested configurations: # - Tk 8.5 on Windows/Mac @@ -217,11 +217,15 @@ def on_focus_out(self, _): def on_root_close(self): if self.browser: - # Close browser and free reference by setting to None self.browser.CloseBrowser(True) - self.browser = None + self.clear_browser_references() self.destroy() + def clear_browser_references(self): + # Clear browser references that you keep anywhere in your + # code. All references must be cleared for CEF to shutdown cleanly. + self.browser = None + class LoadHandler(object): diff --git a/examples/wxpython.py b/examples/wxpython.py index e36da5494..c9176a0b6 100644 --- a/examples/wxpython.py +++ b/examples/wxpython.py @@ -14,7 +14,7 @@ import sys import os -# Fix for PyCharm hints warnings +# Fix for PyCharm hints warnings when using static methods WindowUtils = cef.WindowUtils() # Platforms diff --git a/src/cefpython.pyx b/src/cefpython.pyx index 18509259c..fe4b4e426 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -608,6 +608,10 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): # 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_severity"] = LOGSEVERITY_WARNING + sys.argv.remove("--debug") if "debug" in application_settings: g_debug = bool(application_settings["debug"]) if "log_file" in application_settings: @@ -649,13 +653,6 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): if "framework_dir_path" not in application_settings: application_settings["framework_dir_path"] = os.path.join( module_dir, "Chromium Embedded Framework.framework") - # Bug in CEF: CefSettings.framework_dir_path doesn't work. - # Can be worked around by setting command line switch. - if not command_line_switches: - command_line_switches = {} - if "framework-dir-path" not in command_line_switches: - command_line_switches["framework-dir-path"] = \ - application_settings["framework_dir_path"] if "locales_dir_path" not in application_settings: if platform.system() != "Darwin": application_settings["locales_dir_path"] = os.path.join( diff --git a/src/include/internal/cef_types_wrappers.h b/src/include/internal/cef_types_wrappers.h index d393035ec..0c125c965 100644 --- a/src/include/internal/cef_types_wrappers.h +++ b/src/include/internal/cef_types_wrappers.h @@ -555,6 +555,7 @@ struct CefSettingsTraits { static inline void clear(struct_type* s) { cef_string_clear(&s->browser_subprocess_path); + cef_string_clear(&s->framework_dir_path); cef_string_clear(&s->cache_path); cef_string_clear(&s->user_data_path); cef_string_clear(&s->user_agent); @@ -574,6 +575,9 @@ struct CefSettingsTraits { cef_string_set(src->browser_subprocess_path.str, src->browser_subprocess_path.length, &target->browser_subprocess_path, copy); + cef_string_set(src->framework_dir_path.str, + src->framework_dir_path.length, + &target->framework_dir_path, copy); target->multi_threaded_message_loop = src->multi_threaded_message_loop; target->external_message_pump = src->external_message_pump; target->windowless_rendering_enabled = src->windowless_rendering_enabled; @@ -982,7 +986,8 @@ struct CefCompositionUnderlineTraits { typedef cef_composition_underline_t struct_type; static inline void init(struct_type* s) { - s->range.from = 0; s->range.to = 0; + s->range.from = 0; + s->range.to = 0; s->color = 0; s->background_color = 0; s->thick = 0; diff --git a/src/version/cef_version_mac.h b/src/version/cef_version_mac.h index 21f8dd354..5e718118b 100644 --- a/src/version/cef_version_mac.h +++ b/src/version/cef_version_mac.h @@ -35,10 +35,10 @@ #ifndef CEF_INCLUDE_CEF_VERSION_H_ #define CEF_INCLUDE_CEF_VERSION_H_ -#define CEF_VERSION "3.2924.1571.gcdcdfa9" +#define CEF_VERSION "3.2924.1575.g97389a9" #define CEF_VERSION_MAJOR 3 -#define CEF_COMMIT_NUMBER 1571 -#define CEF_COMMIT_HASH "cdcdfa99913a01f3617a0d25a2e2f2ed145987bd" +#define CEF_COMMIT_NUMBER 1575 +#define CEF_COMMIT_HASH "97389a92ee2309ded830338d6afd61ba109d31d8" #define COPYRIGHT_YEAR 2017 #define CHROME_VERSION_MAJOR 56 diff --git a/tools/apidocs.py b/tools/apidocs.py index abae18b39..75e97cc6a 100644 --- a/tools/apidocs.py +++ b/tools/apidocs.py @@ -26,8 +26,8 @@ def main(): def api_index(): """Generate API-index.md file with all modules/classes/funcs/methods.""" files = glob.glob(os.path.join(API_DIR, "*.md")) - contents = ("[API categories](API-categories.md) | " + - "[API index](API-index.md)\n\n" + + contents = ("[API categories](API-categories.md#api-categories) | " + + "[API index](API-index.md#api-index)\n\n" + "# API index\n\n") files = sorted(files, key=lambda s: s.lower()) for file_ in files: @@ -45,7 +45,7 @@ def api_index(): title = title.strip() if hlevel == "#": indent = "" - link = os.path.basename(file_) + link = os.path.basename(file_) + "#" + headinghash(title) elif hlevel == "###": indent = " " link = os.path.basename(file_) + "#" + headinghash(title) diff --git a/tools/automate.py b/tools/automate.py index f6dd9fb02..096abc9c7 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -96,6 +96,7 @@ class Options(object): build_type = "" # Will be set according to "release_build" value cef_binary = "" build_cefclient_dir = "" + build_wrapper_dir = "" build_wrapper_mt_dir = "" build_wrapper_md_dir = "" @@ -311,7 +312,8 @@ def build_cef_projects(): fix_cef_include_files() - # Find cef_binary directory + # Find cef_binary directory. + # Might already be set if --prebuilt-cef flag was passed. if not Options.cef_binary: if platform.system() == "Windows": files = glob.glob(os.path.join(Options.binary_distrib, @@ -366,14 +368,62 @@ def build_cef_projects(): print("[automate.py] OK") # Ninja command = prepare_build_command() - command.extend(["ninja", "cefclient", "cefsimple", "ceftests"]) + # On Mac cefclient fails with XCode 5: + # > cefclient_mac.mm:22:29: error: property 'mainMenu' not found + if MAC: + # Build only cefsimple + command.extend(["ninja", "cefsimple"]) + else: + command.extend(["ninja", "cefclient", "cefsimple", "ceftests"]) run_command(command, Options.build_cefclient_dir) print("[automate.py] OK") assert build_cefclient_succeeded() # Build libcef_dll_wrapper libs - if platform.system() == "Windows": + if WINDOWS: build_wrapper_windows() + elif MAC: + build_wrapper_mac() + + +def build_wrapper_mac(): + # On Mac it is required to link libcef_dll_wrapper against + # libc++ library, so must build this library separately + # from cefclient. + cmake_wrapper = prepare_build_command(build_lib=True) + cmake_wrapper.extend(["cmake", "-G", "Ninja", + "-DPROJECT_ARCH=x86_64" + "-DCMAKE_CXX_FLAGS=-stdlib=libc++", + "-DCMAKE_BUILD_TYPE=" + Options.build_type, + ".."]) + Options.build_wrapper_dir = os.path.join(Options.cef_binary, + "build_wrapper") + # Check whether already built + already_built = False + if build_wrapper_mac_succeeded(): + already_built = True + elif os.path.exists(Options.build_wrapper_dir): + # Last build failed, clean directory + assert Options.build_wrapper_dir + shutil.rmtree(Options.build_wrapper_dir) + os.makedirs(Options.build_wrapper_dir) + else: + os.makedirs(Options.build_wrapper_dir) + + # Build libcef_dll_wrapper library + if already_built: + print("[automate.py] Already built: libcef_dll_wrapper") + else: + print("[automate.py] Build libcef_dll_wrapper") + # Cmake + run_command(cmake_wrapper, Options.build_wrapper_dir) + print("[automate.py] cmake OK") + # Ninja + ninja_wrapper = prepare_build_command(build_lib=True) + ninja_wrapper.extend(["ninja", "libcef_dll_wrapper"]) + run_command(ninja_wrapper, Options.build_wrapper_dir) + print("[automate.py] ninja OK") + assert build_wrapper_mac_succeeded() def build_wrapper_windows(): @@ -515,7 +565,7 @@ def fix_cmake_variables_for_md_library(undo=False, try_undo=False): def build_cefclient_succeeded(): """Whether building cefclient/cefsimple/ceftests succeeded.""" assert Options.build_cefclient_dir - cefclient_exe = "cefclient.exe" if WINDOWS else "cefclient" + cefclient_exe = "cefclient" + EXECUTABLE_EXT return os.path.exists(os.path.join(Options.build_cefclient_dir, "tests", "cefclient", @@ -523,6 +573,14 @@ def build_cefclient_succeeded(): cefclient_exe)) +def build_wrapper_mac_succeeded(): + """Whether building libcef_dll_wrapper succeeded.""" + return os.path.exists(os.path.join( + Options.build_wrapper_dir, + "libcef_dll_wrapper", + "libcef_dll_wrapper.a")) + + def build_wrapper_mt_succeeded(): """Whether building /MT library succeeded (Windows-only).""" assert Options.build_wrapper_mt_dir @@ -557,6 +615,8 @@ def prepare_build_command(build_lib=False): def fix_cef_include_files(): """Fixes to CEF include header files for eg. VS2008 on Windows.""" + # TODO: This was fixed in upstream CEF, remove this code during + # next CEF update on Windows. if platform.system() == "Windows" and get_msvs_for_python() == "2008": print("[automate.py] Fixing CEF include/ files") # cef_types_wrappers.h @@ -571,8 +631,10 @@ def fix_cef_include_files(): fp.write(contents) -def create_prebuilt_binaries(): - """After building copy binaries/libs to build/cef_xxxx/. """ +def create_prebuilt_binaries(copy_apps=True): + """After building copy binaries/libs to build/cef_xxxx/. + Not all projects may have been built on all platforms.""" + # Directories src = Options.cef_binary version_header = os.path.join(src, "include", "cef_version.h") @@ -587,7 +649,20 @@ def create_prebuilt_binaries(): # Copy Release/Debug and Resources cpdir(os.path.join(src, Options.build_type), bindir) - cpdir(os.path.join(src, "Resources"), bindir) + if not MAC: + cpdir(os.path.join(src, "Resources"), bindir) + + # Fix id in CEF framework on Mac (currently it expects Frameworks/ dir) + if MAC: + new_id = ("@rpath/Chromium Embedded Framework.framework" + "/Chromium Embedded Framework") + cef_framework_dir = os.path.join( + bindir, "Chromium Embedded Framework.framework") + cef_library = os.path.join( + cef_framework_dir, "Chromium Embedded Framework") + assert os.path.isdir(cef_framework_dir) + run_command(["install_name_tool", "-id", new_id, cef_library], + working_dir=cef_framework_dir) # Copy cefclient, cefsimple, ceftests @@ -596,8 +671,8 @@ def create_prebuilt_binaries(): src, "build_cefclient", "tests", "cefclient", Options.build_type, - "cefclient") - if platform.system() != "Windows": + "cefclient" + EXECUTABLE_EXT) + if LINUX and os.path.exists(cefclient): # On Windows resources/*.html files are embedded inside exe cefclient_files = os.path.join( src, @@ -611,15 +686,15 @@ def create_prebuilt_binaries(): src, "build_cefclient", "tests", "cefsimple", Options.build_type, - "cefsimple") + "cefsimple" + EXECUTABLE_EXT) # ceftests ceftests = os.path.join( src, "build_cefclient", "tests", "ceftests", Options.build_type, - "ceftests") - if platform.system() != "Windows": + "ceftests" + EXECUTABLE_EXT) + if LINUX and os.path.exists(ceftests): # On Windows resources/*.html files are embedded inside exe ceftests_files = os.path.join( src, @@ -628,14 +703,21 @@ def create_prebuilt_binaries(): "ceftests_files") cpdir(ceftests_files, os.path.join(bindir, "ceftests_files")) - if platform.system() == "Windows": - cefclient += ".exe" - cefsimple += ".exe" - ceftests += ".exe" + def copy_app(app): + if os.path.exists(app): + if os.path.isdir(app): + # On Mac app is a directory + shutil.copytree(app, + os.path.join(bindir, + os.path.basename(app))) + else: + shutil.copy(app, bindir) - shutil.copy(cefclient, bindir) - shutil.copy(cefsimple, bindir) - shutil.copy(ceftests, bindir) + if not MAC: + # Currently do not copy apps on Mac + copy_app(cefclient) + copy_app(cefsimple) + copy_app(ceftests) # END: Copy cefclient, cefsimple, ceftests @@ -653,11 +735,12 @@ def create_prebuilt_binaries(): "libcef_dll_wrapper.lib") libdst = os.path.join(libdir, "libcef_dll_wrapper_md.lib") shutil.copy(libsrc, libdst) - elif platform.system() == "Linux": - cpdir(os.path.join(src, "build_cefclient", "libcef_dll_wrapper"), - libdir) + else: + shutil.copy(os.path.join(src, "build_cefclient", "libcef_dll_wrapper", + "libcef_dll_wrapper.a"), + libdir) - # Remove .lib files from bin/ only after libraries were copied + # Remove .lib files from bin/ only after libraries were copied (Windows) libs = glob.glob(os.path.join(bindir, "*.lib")) for lib in libs: os.remove(lib) diff --git a/tools/build.py b/tools/build.py index aa10d2d6d..a7297c9ab 100644 --- a/tools/build.py +++ b/tools/build.py @@ -74,6 +74,8 @@ def main(): if len(sys.argv) <= 1: print(__doc__) sys.exit(1) + print("[build.py] Python version: %s" % platform.python_version()) + print("[build.py] Python executable: %s" % sys.executable) print("[build.py] PYVERSION = %s" % PYVERSION) print("[build.py] OS_POSTFIX2 = %s" % OS_POSTFIX2) command_line_args() @@ -610,19 +612,19 @@ def build_cefpython_module(): # ret = subprocess.call("python-dbg setup.py build_ext --inplace" # " --cython-gdb", shell=True) - print("[build.py] Execute build_module.py script") + print("[build.py] Execute cython_setup.py script") print("") os.chdir(BUILD_CEFPYTHON) if FAST_FLAG: - ret = subprocess.call("{python} {tools_dir}/build_module.py" + ret = subprocess.call("{python} {tools_dir}/cython_setup.py" " build_ext --fast" .format(python=sys.executable, tools_dir=TOOLS_DIR), shell=True) else: - ret = subprocess.call("{python} {tools_dir}/build_module.py" + ret = subprocess.call("{python} {tools_dir}/cython_setup.py" " build_ext" .format(python=sys.executable, tools_dir=TOOLS_DIR), @@ -766,7 +768,7 @@ def install_and_run(): def get_sudo(): # System Python requires sudo when installing package - if sys.executable in ["/usr/bin/python", "/usr/bin/python3"]: + if sys.executable.startswith("/usr/"): sudo = "sudo" else: sudo = "" diff --git a/tools/common.py b/tools/common.py index bb1615532..40f796922 100644 --- a/tools/common.py +++ b/tools/common.py @@ -1,4 +1,4 @@ -# Common stuff for tools: automate.py, build.py, build_module.py +# Common stuff for tools such as automate.py, build.py, etc. import struct import platform @@ -41,6 +41,20 @@ MODULE_NAME = MODULE_NAME_TEMPLATE.format(pyversion=PYVERSION, ext=MODULE_EXT) MODULE_NAME_NOEXT = MODULE_NAME_TEMPLATE_NOEXT.format(pyversion=PYVERSION) +# Executable extension +if WINDOWS: + EXECUTABLE_EXT = ".exe" +elif MAC: + EXECUTABLE_EXT = ".app" +else: + EXECUTABLE_EXT = "" + +# Library extension +if WINDOWS: + STATIC_LIBRARY_EXT = ".lib" +else: + STATIC_LIBRARY_EXT = ".a" + # Root directory assert __file__ ROOT_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) @@ -70,12 +84,19 @@ # Visual Studio constants VS_PLATFORM_ARG = "x86" if ARCH32 else "amd64" + VS2015_VCVARS = ("C:\\Program Files (x86)\\Microsoft Visual Studio 14.0" "\\VC\\vcvarsall.bat") -VS2015_BUILD = "" # TODO +VS2015_BUILD = "" # TODO: add VS2015 Python 3.5/3.6 support + +# For CEF build VS2013_VCVARS = ("C:\\Program Files (x86)\\Microsoft Visual Studio 12.0" "\\VC\\vcvarsall.bat") -VS2013_BUILD = "" # TODO + +VS2010_VCVARS = ("C:\\Program Files (x86)\\Microsoft Visual Studio 10.0" + "\\VC\\vcvarsall.bat") +VS2010_BUILD = "" # TODO: add VS2010 Python 3.4 support + VS2008_VCVARS = ("%LocalAppData%\\Programs\\Common\\Microsoft" "\\Visual C++ for Python\\9.0\\vcvarsall.bat") VS2008_BUILD = ("%LocalAppData%\\Programs\\Common\\" diff --git a/tools/build_module.py b/tools/cython_setup.py similarity index 94% rename from tools/build_module.py rename to tools/cython_setup.py index 7beda34f4..f96c3b8d7 100644 --- a/tools/build_module.py +++ b/tools/cython_setup.py @@ -2,7 +2,7 @@ # Licensed under the BSD 3-clause license. """ -build_module.py is for internal use only - called by build.py. +cython_setup.py is for internal use only - called by build.py. This is Cython's setup for building the cefpython module """ @@ -50,7 +50,7 @@ def generate_extern_c_macro_definition(self, code): # This code is written to both cefpython.h and cefpython.cpp g_generate_extern_c_macro_definition_old(self, code) - code.putln("// Added by: cefpython/tools/build_module.py") + code.putln("// Added by: cefpython/tools/cython_setup.py") code.putln("#undef PyMODINIT_FUNC") if sys.version_info[:2] == (2, 7): code.putln("#define PyMODINIT_FUNC extern \"C\"" @@ -72,10 +72,14 @@ def generate_extern_c_macro_definition(self, code): def main(): + print("[cython_setup.py] Python version: %s" % platform.python_version()) + print("[cython_setup.py] Python executable: %s" % sys.executable) + print("[cython_setup.py] Cython version: %s" % Cython.__version__) + global FAST_FLAG if len(sys.argv) > 1 and "--fast" in sys.argv: # Fast mode disables optimization flags - print("[build_module.py] FAST mode On") + print("[cython_setup.py] FAST mode enabled") FAST_FLAG = True sys.argv.remove("--fast") @@ -83,8 +87,6 @@ def main(): print(__doc__) sys.exit(1) - print("[build_module.py] Cython version: %s" % Cython.__version__) - compile_time_constants() options = dict() set_compiler_options(options) @@ -92,7 +94,7 @@ def main(): options["library_dirs"] = get_library_dirs() options["libraries"] = get_libraries() - print("[build_module.py] Execute setup()") + print("[cython_setup.py] Execute setup()") setup( name='cefpython_py%s' % PYVERSION, cmdclass={'build_ext': build_ext}, @@ -101,7 +103,7 @@ def main(): def get_winsdk_lib(): - print("[build_module.py] Detect Windows SDK library directory") + print("[cython_setup.py] Detect Windows SDK library directory") ret = "" if WINDOWS: if ARCH32: @@ -130,7 +132,7 @@ def get_winsdk_lib(): def set_compiler_options(options): """Extends options and also sets environment variables.""" - print("[build_module.py] Set compiler options") + print("[cython_setup.py] Set compiler options") extra_compile_args = list() extra_link_args = list() @@ -243,7 +245,7 @@ def set_compiler_options(options): def get_include_dirs(): - print("[build_module.py] Prepare include directories") + print("[cython_setup.py] Prepare include directories") include_dirs = list() common_include_dirs = [ SRC_DIR, @@ -304,7 +306,7 @@ def get_include_dirs(): def get_library_dirs(): - print("[build_module.py] Prepare library directories") + print("[cython_setup.py] Prepare library directories") library_dirs = [ os.path.join(CEF_BINARIES_LIBRARIES, "lib"), ] @@ -336,7 +338,7 @@ def get_library_dirs(): def get_libraries(): - print("[build_module.py] Prepare libraries") + print("[cython_setup.py] Prepare libraries") libraries = list() if WINDOWS: libraries.extend([ @@ -413,7 +415,7 @@ def get_ext_modules(options): def compile_time_constants(): - print("[build_module.py] Generate compile_time_constants.pxi") + print("[cython_setup.py] Generate compile_time_constants.pxi") with open(os.path.join(SRC_DIR, "compile_time_constants.pxi"), "w") as fd: fd.write('# This file was generated by setup.py\n') # A way around Python 3.2 bug: UNAME_SYSNAME is not set diff --git a/tools/run_examples.py b/tools/run_examples.py index 19066b6fe..7d191e27f 100644 --- a/tools/run_examples.py +++ b/tools/run_examples.py @@ -40,34 +40,40 @@ def main(): passed.append("gtk2.py") # gtk3 - if packages["gi"]: - if not LINUX: - examples.append("gtk3.py") - else: - # Gtk 3 example is currently broken on Linux (Issue #261) - print("[run_examples.py] PASS: gtk3.py (Issue #261)") - passed.append("gtk3.py") + if LINUX: + # Broken on Linux (Issue #261) + print("[run_examples.py] PASS: gtk3.py (Issue #261)") + passed.append("gtk3.py (Issue #261)") + elif MAC: + # Crashes on Mac (Issue #310) + print("[run_examples.py] PASS: gtk3.py (Issue #310)") + passed.append("gtk3.py (Issue #310)") + elif packages["gi"]: + examples.append("gtk3.py") else: print("[run_examples.py] PASS: gtk3.py (Gtk 3 not installed)") passed.append("gtk3.py") # pyqt if packages["PyQt4"]: - examples.append("qt.py pyqt") + examples.append("qt4.py pyqt") else: - print("[run_examples.py] PASS: qt.py pyqt (PyQt4 not installed)") - passed.append("qt.py pyqt") + print("[run_examples.py] PASS: qt4.py pyqt (PyQt4 not installed)") + passed.append("qt4.py pyqt") # pyside if packages["PySide"]: - examples.append("qt.py pyside") + examples.append("qt4.py pyside") else: - print("[run_examples.py] PASS: qt.py pyside (PySide not installed)") - passed.append("qt.py pyside") - - # tkinter. - # This example often crashes on Mac (Issue #309), so don't run it. - if not MAC and (packages["tkinter"] or packages["Tkinter"]): + print("[run_examples.py] PASS: qt4.py pyside (PySide not installed)") + passed.append("qt4.py pyside") + + # tkinter + if MAC: + # This example often crashes on Mac (Issue #309) + print(["run_examples.py] PASS: tkinter_.py (Issue #309)"]) + passed.append("tkinter_.py (Issue #309)") + elif packages["tkinter"] or packages["Tkinter"]: examples.append("tkinter_.py") else: print(["run_examples.py] PASS: tkinter_.py (tkinter not installed)"]) diff --git a/unittests/main_test.py b/unittests/main_test.py index 05f341589..5ace78c64 100644 --- a/unittests/main_test.py +++ b/unittests/main_test.py @@ -10,7 +10,7 @@ import sys # To show the window for an extended period of time increase this number. -MESSAGE_LOOP_RANGE = 25 # each iteration is 0.01 sec +MESSAGE_LOOP_RANGE = 100 # each iteration is 0.01 sec g_datauri_data = """ @@ -140,7 +140,7 @@ def test_main(self): browser.SetJavascriptBindings(bindings) subtest_message("browser.SetJavascriptBindings() ok") - # Run message loop for 0.5 sec. + # Run message loop for some time. # noinspection PyTypeChecker for i in range(MESSAGE_LOOP_RANGE): cef.MessageLoopWork() From c23bc2d2a5509e727bcdda3ccf90783a10241c50 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Fri, 3 Mar 2017 17:46:21 +0100 Subject: [PATCH 149/557] Handle copy/paste commands by default on Mac (#161) --- src/handlers/keyboard_handler.pyx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/handlers/keyboard_handler.pyx b/src/handlers/keyboard_handler.pyx index 6391d74b7..b0b03f536 100644 --- a/src/handlers/keyboard_handler.pyx +++ b/src/handlers/keyboard_handler.pyx @@ -90,7 +90,20 @@ cdef public cpp_bool KeyboardHandler_OnKeyEvent( browser=pyBrowser, event=pyEvent, event_handle=PyLong_FromVoidPtr(cefEventHandle)) - return bool(returnValue) + # If returnValue is False then handle copy/paste on Mac + if returnValue: + return bool(returnValue) + if platform.system() == "Darwin": + # Handle copy: command + c + if pyEvent["modifiers"] == 128 \ + and pyEvent["native_key_code"] == 8: + pyBrowser.GetFocusedFrame().Copy() + return True + # Handle paste: command + v + elif pyEvent["modifiers"] == 128 \ + and pyEvent["native_key_code"] == 9: + pyBrowser.GetFocusedFrame().Paste() + return True return False except: (exc_type, exc_value, exc_trace) = sys.exc_info() From 510d60302d1d49cad69a3ec1b991c85043d60e0d Mon Sep 17 00:00:00 2001 From: cztomczak Date: Fri, 3 Mar 2017 22:07:00 +0100 Subject: [PATCH 150/557] Python 3 support on Mac (#121, #295) --- docs/Knowledge-Base.md | 13 +++++-------- examples/qt4.py | 1 + tools/build.py | 4 ++-- tools/make_installer.py | 6 +++--- tools/run_examples.py | 2 +- 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/docs/Knowledge-Base.md b/docs/Knowledge-Base.md index 73aa95b6b..31d26909c 100644 --- a/docs/Knowledge-Base.md +++ b/docs/Knowledge-Base.md @@ -112,15 +112,12 @@ as of now. To see if some feature is working or a bug is fixed in newer CEF release perform the following steps: -1. Download and install [CMake](https://cmake.org/download/) and - [Ninja](https://github.com/ninja-build/ninja/releases) -2. Go to [Spotify Automated Builds] +1. Go to [Spotify Automated Builds] (http://opensource.spotify.com/cefbuilds/index.html) - and download latest CEF for your platform. Choose "Standard - Distribution" binaries. -3. Follow the instructions in `CMakeLists.txt` file, choose steps - for building using Ninja -4. Run either cefclient or cefsimple to test features + to download latest CEF for your platform. Choose "Sample + Application" binaries. +2. Extract the archive and run sample application from the + Release/ directory. ## How to capture Audio and Video in HTML5? diff --git a/examples/qt4.py b/examples/qt4.py index b5925ca37..dad875ca8 100644 --- a/examples/qt4.py +++ b/examples/qt4.py @@ -9,6 +9,7 @@ # Issues on Mac (tested with PySide): # - 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 from cefpython3 import cefpython as cef import ctypes diff --git a/tools/build.py b/tools/build.py index a7297c9ab..54b9c56e6 100644 --- a/tools/build.py +++ b/tools/build.py @@ -459,13 +459,13 @@ def clear_cache(): # Cache in CEFPYTHON_BINARY directory (eg. cefpython_linux64/) os.chdir(CEFPYTHON_BINARY) delete_files_by_pattern("./"+MODULE_NAME_TEMPLATE - .format(pyversion="*", ext=MODULE_EXT)) + .format(pyversion=PYVERSION, ext=MODULE_EXT)) # Cache in build_cefpython/ directory os.chdir(BUILD_CEFPYTHON) delete_files_by_pattern("./"+MODULE_NAME_TEMPLATE - .format(pyversion="*", ext=MODULE_EXT)) + .format(pyversion=PYVERSION, ext=MODULE_EXT)) delete_files_by_pattern("./*.pyx") try: diff --git a/tools/make_installer.py b/tools/make_installer.py index 5d4f7501a..901dfd7ca 100644 --- a/tools/make_installer.py +++ b/tools/make_installer.py @@ -126,10 +126,10 @@ def copy_template_file(src, dst, variables): print("[make_installer.py] Copy_t: {src} ==> {dst}" .format(src=short_src_path(src), dst=short_dst_path(dst))) with open(src, "rb") as fo: - contents = fo.read() + contents = fo.read().decode("utf-8") contents = replace_template_vars(contents, variables) with open(dst, "wb") as fo: - fo.write(contents) + fo.write(contents.encode("utf-8")) return contents @@ -280,7 +280,7 @@ def create_empty_log_file(log_file): print("[make_installer.py] Create: {file}" .format(file=short_dst_path(log_file))) with open(log_file, "wb") as fo: - fo.write("") + fo.write("".encode("utf-8")) # On Linux and Mac chmod so that for cases when package is # installed using sudo. When wheel package is created it # will remember file permissions set. diff --git a/tools/run_examples.py b/tools/run_examples.py index 7d191e27f..db77572d8 100644 --- a/tools/run_examples.py +++ b/tools/run_examples.py @@ -71,7 +71,7 @@ def main(): # tkinter if MAC: # This example often crashes on Mac (Issue #309) - print(["run_examples.py] PASS: tkinter_.py (Issue #309)"]) + print("[run_examples.py] PASS: tkinter_.py (Issue #309)") passed.append("tkinter_.py (Issue #309)") elif packages["tkinter"] or packages["Tkinter"]: examples.append("tkinter_.py") From c6b99221a5334abf15bb1c9204502121aef57c39 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Fri, 3 Mar 2017 22:51:33 +0100 Subject: [PATCH 151/557] Update README, Mac supports Python 3 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1b914f627..509983c4e 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ bots. 2. Downloads are available on [GitHub Releases](../../releases) pages 2. Windows support: 32-bit, Python 2.7 3. Linux support: 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 -4. Mac support: 64-bit, Python 2.7 +4. Mac support: 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 5. Documentation is in the [docs/](docs) directory 6. API reference is in the [api/](api) directory 7. Additional documentation is in issues labelled [Knowledge Base] From 17b3ba274ef2e768da634f388a51066206d1ccfa Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 4 Mar 2017 10:27:15 +0100 Subject: [PATCH 152/557] Fix TOC generation --- docs/Knowledge-Base.md | 3 ++- tools/toc.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/Knowledge-Base.md b/docs/Knowledge-Base.md index 31d26909c..c43b417c4 100644 --- a/docs/Knowledge-Base.md +++ b/docs/Knowledge-Base.md @@ -10,7 +10,8 @@ Table of contents: * [How to capture Audio and Video in HTML5?](#how-to-capture-audio-and-video-in-html5) * [Touch and multi-touch support](#touch-and-multi-touch-support) * [Black or white browser screen](#black-or-white-browser-screen) -* [Python crashes with "Segmentation fault" - how to debug?](#python-crashes-with-segmentation-fault-how-to-debug) +* [How to enable debug information in examples?](#how-to-enable-debug-information-in-examples) +* [Python crashes with "Segmentation fault" - how to debug?](#python-crashes-with-segmentation-fault---how-to-debug) * [Windows XP support](#windows-xp-support) * [Mac 32-bit support](#mac-32-bit-support) * [Security](#security) diff --git a/tools/toc.py b/tools/toc.py index 3e4d698c6..21967e120 100644 --- a/tools/toc.py +++ b/tools/toc.py @@ -160,10 +160,12 @@ def parse_headings(raw_contents, file_): def headinghash(title): """Get a link hash for a heading H1,H2,H3.""" hash_ = title.lower() + hash_ = hash_.replace(" - ", "specialcase1") 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", "---") return hash_ From cfd4912eea0fe4e722a1a0294e7dc31e7e7cb297 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 4 Mar 2017 18:25:31 +0100 Subject: [PATCH 153/557] Support wheel package creation with "make-installer.py --wheel" (#219)... Add long description in wheel package, fix "DESCRIPTION.rst UNKNOWN" (#166). --- tools/installer/cefpython3.setup.py | 60 +++++++++++++++++------------ tools/make_installer.py | 39 +++++++++++++++++-- 2 files changed, 71 insertions(+), 28 deletions(-) diff --git a/tools/installer/cefpython3.setup.py b/tools/installer/cefpython3.setup.py index bfdc570d7..7ab1ba179 100644 --- a/tools/installer/cefpython3.setup.py +++ b/tools/installer/cefpython3.setup.py @@ -66,35 +66,13 @@ def run(self): post_install_hook() -class BinaryDistribution(Distribution): - def is_pure(self): - return False - - # Provide a custom install command print("[setup.py] Overload install command to enable execution of" " post install hook") cmdclass = {"install": custom_install} -# Set custom platform tags on Mac when generating wheel package. See: -# http://lepture.com/en/2014/python-on-a-hard-wheel -if platform.system() == "Darwin" and "bdist_wheel" in sys.argv: - print("[setup.py] Overload bdist_wheel command to add custom" - " platform tags") - from wheel.bdist_wheel import bdist_wheel - - class custom_bdist_wheel(bdist_wheel): - def get_tag(self): - tag = bdist_wheel.get_tag(self) - platform_tag = ("macosx_10_6_intel" - ".macosx_10_9_intel.macosx_10_9_x86_64" - ".macosx_10_10_intel.macosx_10_10_x86_64") - tag = (tag[0], tag[1], platform_tag) - return tag - - cmdclass["bdist_wheel"] = custom_bdist_wheel -elif platform.system() in ["Windows", "Linux"] and "bdist_wheel" in sys.argv: - # On Windows and Linux platform tag is always "any". +# Fix platform tag in wheel package +if "bdist_wheel" in sys.argv: print("[setup.py] Overload bdist_wheel command to fix platform tag") from wheel.bdist_wheel import bdist_wheel @@ -102,20 +80,52 @@ class custom_bdist_wheel(bdist_wheel): def get_tag(self): tag = bdist_wheel.get_tag(self) platform_tag = sysconfig.get_platform() + if platform.system() == "Linux": + assert "linux" in platform_tag + # "linux-x86_64" replace with "manylinux1_x86_64" + platform_tag = platform_tag.replace("linux", "manylinux1") + platform_tag = platform_tag.replace("-", "_") + elif platform.system() == "Darwin": + # For explanation of Mac platform tags, see: + # http://lepture.com/en/2014/python-on-a-hard-wheel + platform_tag = ("macosx_10_6_intel" + ".macosx_10_9_intel.macosx_10_9_x86_64" + ".macosx_10_10_intel.macosx_10_10_x86_64") tag = (tag[0], tag[1], platform_tag) return tag + # Overwrite bdist_wheel command cmdclass["bdist_wheel"] = custom_bdist_wheel def main(): setup( - distclass=BinaryDistribution, + distclass=Distribution, cmdclass=cmdclass, name="cefpython3", # No spaces here, so that it works with deb pkg version="{{VERSION}}", description="GUI toolkit for embedding a Chromium widget" " in desktop applications", + long_description="CEF Python is an open source project founded" + " by Czarek Tomczak in 2012 to provide python" + " bindings for the Chromium Embedded Framework." + " Examples of embedding CEF browser are available" + " for many popular GUI toolkits including:" + " wxPython, PyQt, PySide, Kivy, Panda3D, PyGTK," + " PyGObject, PyGame/PyOpenGL and PyWin32.\n\n" + "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" + " like wxWidgets, Qt or GTK. You can render web" + " content off-screen in application that use custom" + " drawing frameworks. You can use it for automated" + " testing of existing applications. You can use it" + " for web scraping or as a web crawler, or other" + " kind of internet bots.\n\n" + "Project website:\n" + "https://github.com/cztomczak/cefpython", license="BSD 3-clause", author="Czarek Tomczak", author_email="czarek.tomczak@@gmail.com", diff --git a/tools/make_installer.py b/tools/make_installer.py index 901dfd7ca..f2858be6e 100644 --- a/tools/make_installer.py +++ b/tools/make_installer.py @@ -5,10 +5,14 @@ Create setup.py package installer. Usage: - make_installer.py VERSION + make_installer.py VERSION [--wheel] [--python-tag xx] [--universal] Options: VERSION Version number eg. 50.0 + --wheel Generate wheel package. + Additional args for the wheel package: + --python-tag xx (eg. cp27 - cpython 2.7) + --universal (any python 2 or 3) """ from common import * @@ -23,6 +27,8 @@ # Command line args VERSION = "" +WHEEL = False +WHEEL_ARGS = list() # Globals SETUP_DIR = "" @@ -89,16 +95,43 @@ def main(): print("[make_installer.py] DONE. Installer package created: {setup_dir}" .format(setup_dir=SETUP_DIR)) + # Optional generation of wheel package + if WHEEL: + print("[make_installer.py] Create Wheel package") + if not len(WHEEL_ARGS): + print("[make_installer.py] ERROR: you must specify flags" + " eg. --python-tag cp27 or --universal") + sys.exit(1) + command = ("{python} setup.py bdist_wheel {wheel_args}" + .format(python=sys.executable, + wheel_args=" ".join(WHEEL_ARGS))) + print("[make_installer.py] Run command: '{0}' in setup directory" + .format(command)) + subprocess.check_call(command, cwd=SETUP_DIR, shell=True) + dist_dir = os.path.join(SETUP_DIR, "dist") + files = glob.glob(os.path.join(dist_dir, "*.whl")) + assert len(files) == 1 + print("[make_installer.py] DONE. Wheel package created: {0}" + .format(files[0])) + def command_line_args(): + global VERSION, WHEEL, WHEEL_ARGS args = " ".join(sys.argv) match = re.search(r"\d+\.\d+", args) if match: - global VERSION VERSION = match.group(0) else: print(__doc__) sys.exit(1) + for arg in sys.argv: + if arg == VERSION: + continue + if arg == "--wheel": + WHEEL = True + continue + if WHEEL: + WHEEL_ARGS.append(arg) def copy_tools_installer_files(setup_dir, pkg_dir): @@ -288,7 +321,7 @@ def create_empty_log_file(log_file): command = "chmod 666 {file}".format(file=log_file) print("[make_installer.py] {command}" .format(command=command.replace(SETUP_DIR, ""))) - subprocess.call(command, shell=True) + subprocess.check_call(command, shell=True) def short_src_path(path): From 1837d34fc20dc587b755a54f1a3a61e0470d638b Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 6 Mar 2017 12:58:56 +0100 Subject: [PATCH 154/557] Update to v56 on Windows (#276)... Minor fixes to tools, examples and build instructions. --- docs/Build-instructions.md | 13 ++++++------- examples/qt4.py | 3 +-- src/compile_time_constants.pxi | 2 +- src/version/cef_version_win.h | 20 ++++++++++---------- tools/automate.py | 10 ++++++---- tools/build.py | 5 +---- tools/common.py | 7 +++++++ 7 files changed, 32 insertions(+), 28 deletions(-) diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index ded592c32..5e2a414ab 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -75,7 +75,7 @@ cd build/ 7) Install python dependencies: ``` -pip install -r ../tools/requirements.txt +pip install --upgrade -r ../tools/requirements.txt ``` 8) Download Windows binaries and libraries from @@ -119,7 +119,7 @@ cd build/ 5) Install python dependencies: ``` -sudo pip install -r ../tools/requirements.txt +sudo pip install --upgrade -r ../tools/requirements.txt ``` 6) Download Linux binaries and libraries from @@ -199,15 +199,14 @@ requirements common for all platforms. * MacOS 10.9+, Xcode5+ and Xcode command line tools. Only 64-bit builds are supported. -* Upgrade setuptools package to latest version otherwise there will be - problems with Cython: `sudo pip install --upgrade setuptools` ### All platforms -* Install dependencies for the automate.py tool by executing: - `cd tools/ && pip install -r requirements.txt` (on Linux use `sudo`). - This will install some PyPI packages including Cython. +* Install/update dependencies for the tools by executing: + `cd cefpython/tools/ && pip install --upgrade -r requirements.txt`. + On Linux use `sudo`. You should run it each time you update to newer + cefpython version to avoid issues. ## Build using prebuilt CEF binaries and libraries diff --git a/examples/qt4.py b/examples/qt4.py index dad875ca8..d48ff45bd 100644 --- a/examples/qt4.py +++ b/examples/qt4.py @@ -143,8 +143,7 @@ def focusInEvent(self, event): # stealing all focus due to Issue #284. if self.browser: if WINDOWS: - WindowUtils.OnSetFocus(self.cef_widget.getHandle(), - 0, 0, 0) + WindowUtils.OnSetFocus(self.getHandle(), 0, 0, 0) self.browser.SetFocus(True) def focusOutEvent(self, event): diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 05306be6d..10ec798af 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 = "Darwin" +DEF UNAME_SYSNAME = "Windows" DEF PY_MAJOR_VERSION = 2 diff --git a/src/version/cef_version_win.h b/src/version/cef_version_win.h index 3a20c3f43..5e718118b 100644 --- a/src/version/cef_version_win.h +++ b/src/version/cef_version_win.h @@ -35,16 +35,16 @@ #ifndef CEF_INCLUDE_CEF_VERSION_H_ #define CEF_INCLUDE_CEF_VERSION_H_ -#define CEF_VERSION "3.2883.1553.g80bd606" +#define CEF_VERSION "3.2924.1575.g97389a9" #define CEF_VERSION_MAJOR 3 -#define CEF_COMMIT_NUMBER 1553 -#define CEF_COMMIT_HASH "80bd6062d7ac4c5fd1d7bc7ee78e8e59d4a040aa" +#define CEF_COMMIT_NUMBER 1575 +#define CEF_COMMIT_HASH "97389a92ee2309ded830338d6afd61ba109d31d8" #define COPYRIGHT_YEAR 2017 -#define CHROME_VERSION_MAJOR 55 +#define CHROME_VERSION_MAJOR 56 #define CHROME_VERSION_MINOR 0 -#define CHROME_VERSION_BUILD 2883 -#define CHROME_VERSION_PATCH 87 +#define CHROME_VERSION_BUILD 2924 +#define CHROME_VERSION_PATCH 76 #define DO_MAKE_STRING(p) #p #define MAKE_STRING(p) DO_MAKE_STRING(p) @@ -63,13 +63,13 @@ extern "C" { // universal hash value will change if any platform is affected whereas the // platform hash values will change only if that particular platform is // affected. -#define CEF_API_HASH_UNIVERSAL "87b7eefcb86c87b28f86bfd7919f7d7a6cffc0d8" +#define CEF_API_HASH_UNIVERSAL "66de193ba22e1d92a99bb29d60f3107709aeefda" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "00823905486d7b7222da5654fe35d2d15f65543a" +#define CEF_API_HASH_PLATFORM "8055740cd08db66cefe838a826dc90806fadfb33" #elif defined(OS_MACOSX) -#define CEF_API_HASH_PLATFORM "f0180f006643782254250f34e858b98110a40e6e" +#define CEF_API_HASH_PLATFORM "12d8ab423df369b68d37c3667123a1812bc0d345" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "14b19454a4231fa10a77b8955954dc95f073af6b" +#define CEF_API_HASH_PLATFORM "86ab23c0d7dafbdff7f66764cf8dac5ec1712af4" #endif // Returns CEF version information for the libcef library. The |entry| diff --git a/tools/automate.py b/tools/automate.py index 096abc9c7..e3863f6e3 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -221,20 +221,22 @@ def prebuilt_cef(): # Find cef_binary directory in the build directory if Options.cef_version: cef_binary = os.path.join(Options.build_dir, - "cef_binary_{cef_version}_*{sep}" + "cef_binary_{cef_version}_{os}{sep}" .format(cef_version=Options.cef_version, + os=CEF_POSTFIX2, sep=os.sep)) else: cef_binary = os.path.join(Options.build_dir, - "cef_binary_3.{cef_branch}.*{sep}" + "cef_binary_3.{cef_branch}.*_{os}{sep}" .format(cef_branch=Options.cef_branch, + os=CEF_POSTFIX2, sep=os.sep)) dirs = glob.glob(cef_binary) if len(dirs) == 1: Options.cef_binary = dirs[0] else: - print("ERROR: Could not find prebuilt binaries in the build dir.") - print(" Eg. cef_binary_3.2883.1553.g80bd606_windows32/") + print("ERROR: Could not find prebuilt binaries in the build dir:") + print(" {cef_binary}".format(cef_binary=cef_binary)) sys.exit(1) build_cef_projects() diff --git a/tools/build.py b/tools/build.py index 54b9c56e6..05a0de6c4 100644 --- a/tools/build.py +++ b/tools/build.py @@ -664,10 +664,7 @@ def build_cefpython_module(): # Move the cefpython module module_pattern = MODULE_NAME_TEMPLATE.format(pyversion=PYVERSION+"*", ext=MODULE_EXT) - if MAC: - module_pattern = "./build/lib*/"+module_pattern - else: - module_pattern = "./"+module_pattern + module_pattern = "./build/lib*/" + module_pattern move_file_by_pattern(module_pattern, os.path.join(CEFPYTHON_BINARY, MODULE_NAME)) diff --git a/tools/common.py b/tools/common.py index 40f796922..b71e0b26d 100644 --- a/tools/common.py +++ b/tools/common.py @@ -10,16 +10,23 @@ # Architecture and OS postfixes ARCH32 = (8 * struct.calcsize('P') == 32) ARCH64 = (8 * struct.calcsize('P') == 64) +# OS_POSTFIX is for directories/files names in cefpython sources +# OS_POSTFIX2 is for platform name in cefpython binaries +# CEF_POSTFIX2 is for platform name in upstream CEF binaries OS_POSTFIX = ("win" if platform.system() == "Windows" else "linux" if platform.system() == "Linux" else "mac" if platform.system() == "Darwin" else "unknown") OS_POSTFIX2 = "unknown" +CEF_POSTFIX2 = "unknown" # Upstream CEF binaries postfix if OS_POSTFIX == "win": OS_POSTFIX2 = "win32" if ARCH32 else "win64" + CEF_POSTFIX2 = "windows32" if ARCH32 else "windows64" elif OS_POSTFIX == "mac": OS_POSTFIX2 = "mac32" if ARCH32 else "mac64" + CEF_POSTFIX2 = "macosx32" if ARCH32 else "macosx64" elif OS_POSTFIX == "linux": OS_POSTFIX2 = "linux32" if ARCH32 else "linux64" + CEF_POSTFIX2 = "linux32" if ARCH32 else "linux64" # Platforms WINDOWS = (platform.system() == "Windows") From 5f24f50b5f829e9f1567968c236370260ebeaec9 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Tue, 7 Mar 2017 19:50:33 +0100 Subject: [PATCH 155/557] Add build_cpp_projects.py tool to build with Python 3 on Windows (#121)... Currently tested with Python 3.4. There are still required changes to automate.py tool to generate libcef_dll_wrapper libraries for all Python 2 and 3 compilers (VS2008, VS2010, VS2015). Update build instructions for Windows. Generate and use cefpython_fixed.h so that recompilation of C++ projects doesn't happen each time when rebuilding the cefpython module. Update README. Add requirements for all platforms. Fix incomplete pip install command. --- README.md | 11 +- api/WindowUtils.md | 3 + docs/Build-instructions.md | 23 +- src/client_handler/client_handler.h | 2 +- src/client_handler/cookie_visitor.h | 2 +- src/client_handler/request_context_handler.h | 2 +- src/client_handler/resource_handler.h | 2 +- src/client_handler/string_visitor.h | 2 +- src/client_handler/web_request_client.h | 2 +- src/common/cefpython_public_api.h | 10 +- src/compile_time_constants.pxi | 2 +- src/cpp_utils/PaintBuffer.h | 4 +- src/cpp_utils/stdint_win.h | 247 ---------------- src/windows/{ => py27}/stdint.h | 0 tools/automate.py | 2 +- tools/build.py | 54 +++- tools/build_cpp_projects.py | 292 +++++++++++++++++++ tools/common.py | 77 +++-- 18 files changed, 432 insertions(+), 305 deletions(-) delete mode 100644 src/cpp_utils/stdint_win.h rename src/windows/{ => py27}/stdint.h (100%) create mode 100644 tools/build_cpp_projects.py diff --git a/README.md b/README.md index 509983c4e..27067efc1 100644 --- a/README.md +++ b/README.md @@ -36,11 +36,14 @@ bots. ### v50+ releases -1. Can be installed on all platforms using `pip install` command +1. Can be installed on all platforms using `pip install cefpython3` command 2. Downloads are available on [GitHub Releases](../../releases) pages 2. Windows support: 32-bit, Python 2.7 + (requirements: Windows 7+) 3. Linux support: 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 + (requirements: Debian 7+ / Ubuntu 12.04+) 4. Mac support: 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 + (requirements: MacOS 10.9+) 5. Documentation is in the [docs/](docs) directory 6. API reference is in the [api/](api) directory 7. Additional documentation is in issues labelled [Knowledge Base] @@ -51,9 +54,9 @@ bots. 1. Downloads are available on [wiki pages](../../wiki#downloads) and on GH Releases tagged [v31.2](../../releases/tag/v31.2) 2. Supports only Python 2.7 -3. Windows support: 32-bit and 64-bit -4. Linux support: 32-bit and 64-bit -5. Mac support: 32-bit and 64-bit +3. Windows support: 32-bit and 64-bit (requirements: Windows XP+) +4. Linux support: 32-bit and 64-bit (requirements: Debian 7+ / Ubuntu 12.04+) +5. Mac support: 32-bit and 64-bit (requirements: MacOS 10.7+) 6. Documentation is on [wiki pages](../../wiki) 7. API reference is available in revision [169a1b2] (../../tree/169a1b20d3cd09879070d41aab28cfa195d2a7d5/docs/api) diff --git a/api/WindowUtils.md b/api/WindowUtils.md index 90b8ade6f..4d292132e 100644 --- a/api/WindowUtils.md +++ b/api/WindowUtils.md @@ -137,3 +137,6 @@ Linux-only. This method is utilized in the PyQt example. Linux-only. Install xlib error handlers so that the application won't be terminated on non-fatal errors. Must be done after initializing GTK. + +CEF Python calls this function automatically during a call to +Initialize, so there is no need to call it manually anymore. diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index 5e2a414ab..e185c6798 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -149,11 +149,22 @@ requirements common for all platforms. * Install an appropriate MS compiler for a specific Python version: https://wiki.python.org/moin/WindowsCompilers -* For Python 2.7 install "Microsoft Visual C++ Compiler for Python 2.7" - from [here](https://www.microsoft.com/en-us/download/details.aspx?id=44266) -* When using "Visual C++ compiler for Python 2.7" you have to install - "Microsoft Visual C++ 2008 Redistributable Package (x64)" from - [here](https://www.microsoft.com/en-us/download/details.aspx?id=15336) + * For Python 2.7 install "Microsoft Visual C++ Compiler for Python 2.7" + from [here](https://www.microsoft.com/en-us/download/details.aspx?id=44266) + * When using "Visual C++ compiler for Python 2.7" you have to install + "Microsoft Visual C++ 2008 Redistributable Package (x64)" from + [here](https://www.microsoft.com/en-us/download/details.aspx?id=15336) + * For Python 2.7 copy "cefpython/src/windows/py27/stdint.h" to + "%LocalAppData%\Programs\Common\Microsoft\Visual C++ for Python\9.0\VC\include\" + if does not exist + * For Python 3.4 follow the instructions for installing Windows SDK 7.1. + If you encounter issue with .NET Framework 4 then make registry edits + as suggested here: [Windows SDK setup failure] + (http://stackoverflow.com/a/33260090/623622). + * For Python 3.4, if getting error: + `Cannot open include file 'ammintrin.h': No such file or directory` + then Copy that `ammitrin.h` file from for example VS 2015 installation + directory or find this file on the web. This is a Microsoft issue. * To build CEF from sources: * Use Win7 x64 or later. 32-bit OS'es are not supported. For more details see [here](https://www.chromium.org/developers/how-tos/build-instructions-windows). @@ -165,8 +176,6 @@ requirements common for all platforms. to PATH * You need about 16 GB of RAM during linking. If there is an error just add additional virtual memory. - * For Python 2.7 copy "cefpython/src/windows/stdint.h" to - "%LocalAppData%\Programs\Common\Microsoft\Visual C++ for Python\9.0\VC\include\" ### Linux diff --git a/src/client_handler/client_handler.h b/src/client_handler/client_handler.h index 149f9305f..e4e5432dc 100644 --- a/src/client_handler/client_handler.h +++ b/src/client_handler/client_handler.h @@ -7,7 +7,7 @@ #pragma once #if defined(_WIN32) -#include "../windows/stdint.h" +#include #endif #include "common/cefpython_public_api.h" diff --git a/src/client_handler/cookie_visitor.h b/src/client_handler/cookie_visitor.h index b7db461f3..187d6633d 100644 --- a/src/client_handler/cookie_visitor.h +++ b/src/client_handler/cookie_visitor.h @@ -5,7 +5,7 @@ #pragma once #if defined(_WIN32) -#include "../windows/stdint.h" +#include #endif #include "common/cefpython_public_api.h" diff --git a/src/client_handler/request_context_handler.h b/src/client_handler/request_context_handler.h index 0b4837ec8..c6a7184b8 100644 --- a/src/client_handler/request_context_handler.h +++ b/src/client_handler/request_context_handler.h @@ -5,7 +5,7 @@ #pragma once #if defined(_WIN32) -#include "../windows/stdint.h" +#include #endif #include "common/cefpython_public_api.h" diff --git a/src/client_handler/resource_handler.h b/src/client_handler/resource_handler.h index 0cb2f3291..e386a1665 100644 --- a/src/client_handler/resource_handler.h +++ b/src/client_handler/resource_handler.h @@ -5,7 +5,7 @@ #pragma once #if defined(_WIN32) -#include "../windows/stdint.h" +#include #endif #include "common/cefpython_public_api.h" diff --git a/src/client_handler/string_visitor.h b/src/client_handler/string_visitor.h index eec7baa95..439b35ad0 100644 --- a/src/client_handler/string_visitor.h +++ b/src/client_handler/string_visitor.h @@ -5,7 +5,7 @@ #pragma once #if defined(_WIN32) -#include "../windows/stdint.h" +#include #endif #include "common/cefpython_public_api.h" diff --git a/src/client_handler/web_request_client.h b/src/client_handler/web_request_client.h index 9d36dfee1..191049c5e 100644 --- a/src/client_handler/web_request_client.h +++ b/src/client_handler/web_request_client.h @@ -5,7 +5,7 @@ #pragma once #if defined(_WIN32) -#include "../windows/stdint.h" +#include #endif #include "common/cefpython_public_api.h" diff --git a/src/common/cefpython_public_api.h b/src/common/cefpython_public_api.h index e2b6b1504..ff4400aaf 100644 --- a/src/common/cefpython_public_api.h +++ b/src/common/cefpython_public_api.h @@ -1,4 +1,4 @@ -/* This is a wrapper around including cefpython.h that is generated +/* This is a wrapper around including cefpython_fixed.h that is generated by Cython. Functions marked with the 'public' keyword are exposed to C through that header file. */ @@ -6,12 +6,12 @@ #define CEFPYTHON_PUBLIC_API_H #if defined(OS_WIN) -#pragma warning(disable:4190) // cefpython.h extern C-linkage warnings +#pragma warning(disable:4190) // cefpython_fixed.h extern C-linkage warnings #endif #include "Python.h" -// cefpython.h declares public functions using DL_IMPORT and these +// cefpython_fixed.h declares public functions using DL_IMPORT and these // macros are not available in Python 3. #ifndef DL_IMPORT #define DL_IMPORT(RTYPE) RTYPE @@ -20,12 +20,12 @@ #define DL_EXPORT(RTYPE) RTYPE #endif -// Includes required by "cefpython.h". +// Includes required by "cefpython_fixed.h". #include "include/cef_client.h" #include "include/cef_urlrequest.h" #include "include/cef_command_line.h" #include "util.h" -#include "../../build/build_cefpython/cefpython.h" +#include "../../build/build_cefpython/cefpython_fixed.h" #endif // CEFPYTHON_PUBLIC_API_H diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 10ec798af..632aab59c 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 = 2 +DEF PY_MAJOR_VERSION = 3 diff --git a/src/cpp_utils/PaintBuffer.h b/src/cpp_utils/PaintBuffer.h index 7a9d06423..d085473af 100644 --- a/src/cpp_utils/PaintBuffer.h +++ b/src/cpp_utils/PaintBuffer.h @@ -8,13 +8,13 @@ // _WIN32 is defined on both 32bit and 64bit. #if defined(_WIN32) #include "windows.h" -#include "stdint_win.h" #include #else -#include #include #endif +#include + void FlipBufferUpsideDown(void* _dest, const void* _src, int width, int height \ ) { // In CEF the buffer passed to Browser.GetImage() & RenderHandler.OnPaint() diff --git a/src/cpp_utils/stdint_win.h b/src/cpp_utils/stdint_win.h deleted file mode 100644 index d02608a59..000000000 --- a/src/cpp_utils/stdint_win.h +++ /dev/null @@ -1,247 +0,0 @@ -// ISO C9x compliant stdint.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006-2008 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. The name of the author may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_STDINT_H_ // [ -#define _MSC_STDINT_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include - -// For Visual Studio 6 in C++ mode and for many Visual Studio versions when -// compiling for ARM we should wrap include with 'extern "C++" {}' -// or compiler give many errors like this: -// error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#ifdef __cplusplus -extern "C" { -#endif -# include -#ifdef __cplusplus -} -#endif - -// Define _W64 macros to mark types changing their size, like intptr_t. -#ifndef _W64 -# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 -# define _W64 __w64 -# else -# define _W64 -# endif -#endif - - -// 7.18.1 Integer types - -// 7.18.1.1 Exact-width integer types - -// Visual Studio 6 and Embedded Visual C++ 4 doesn't -// realize that, e.g. char has the same size as __int8 -// so we give up on __intX for them. -#if (_MSC_VER < 1300) - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; -#else - typedef signed __int8 int8_t; - typedef signed __int16 int16_t; - typedef signed __int32 int32_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; -#endif -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; - - -// 7.18.1.2 Minimum-width integer types -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -// 7.18.1.3 Fastest minimum-width integer types -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; - -// 7.18.1.4 Integer types capable of holding object pointers -#ifdef _WIN64 // [ - typedef signed __int64 intptr_t; - typedef unsigned __int64 uintptr_t; -#else // _WIN64 ][ - typedef _W64 signed int intptr_t; - typedef _W64 unsigned int uintptr_t; -#endif // _WIN64 ] - -// 7.18.1.5 Greatest-width integer types -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - - -// 7.18.2 Limits of specified-width integer types - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 - -// 7.18.2.1 Limits of exact-width integer types -#define INT8_MIN ((int8_t)_I8_MIN) -#define INT8_MAX _I8_MAX -#define INT16_MIN ((int16_t)_I16_MIN) -#define INT16_MAX _I16_MAX -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX _I64_MAX -#define UINT8_MAX _UI8_MAX -#define UINT16_MAX _UI16_MAX -#define UINT32_MAX _UI32_MAX -#define UINT64_MAX _UI64_MAX - -// 7.18.2.2 Limits of minimum-width integer types -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -// 7.18.2.3 Limits of fastest minimum-width integer types -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -// 7.18.2.4 Limits of integer types capable of holding object pointers -#ifdef _WIN64 // [ -# define INTPTR_MIN INT64_MIN -# define INTPTR_MAX INT64_MAX -# define UINTPTR_MAX UINT64_MAX -#else // _WIN64 ][ -# define INTPTR_MIN INT32_MIN -# define INTPTR_MAX INT32_MAX -# define UINTPTR_MAX UINT32_MAX -#endif // _WIN64 ] - -// 7.18.2.5 Limits of greatest-width integer types -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -// 7.18.3 Limits of other integer types - -#ifdef _WIN64 // [ -# define PTRDIFF_MIN _I64_MIN -# define PTRDIFF_MAX _I64_MAX -#else // _WIN64 ][ -# define PTRDIFF_MIN _I32_MIN -# define PTRDIFF_MAX _I32_MAX -#endif // _WIN64 ] - -#define SIG_ATOMIC_MIN INT_MIN -#define SIG_ATOMIC_MAX INT_MAX - -#ifndef SIZE_MAX // [ -# ifdef _WIN64 // [ -# define SIZE_MAX _UI64_MAX -# else // _WIN64 ][ -# define SIZE_MAX _UI32_MAX -# endif // _WIN64 ] -#endif // SIZE_MAX ] - -// WCHAR_MIN and WCHAR_MAX are also defined in -#ifndef WCHAR_MIN // [ -# define WCHAR_MIN 0 -#endif // WCHAR_MIN ] -#ifndef WCHAR_MAX // [ -# define WCHAR_MAX _UI16_MAX -#endif // WCHAR_MAX ] - -#define WINT_MIN 0 -#define WINT_MAX _UI16_MAX - -#endif // __STDC_LIMIT_MACROS ] - - -// 7.18.4 Limits of other integer types - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 - -// 7.18.4.1 Macros for minimum-width integer constants - -#define INT8_C(val) val##i8 -#define INT16_C(val) val##i16 -#define INT32_C(val) val##i32 -#define INT64_C(val) val##i64 - -#define UINT8_C(val) val##ui8 -#define UINT16_C(val) val##ui16 -#define UINT32_C(val) val##ui32 -#define UINT64_C(val) val##ui64 - -// 7.18.4.2 Macros for greatest-width integer constants -#define INTMAX_C INT64_C -#define UINTMAX_C UINT64_C - -#endif // __STDC_CONSTANT_MACROS ] - - -#endif // _MSC_STDINT_H_ ] diff --git a/src/windows/stdint.h b/src/windows/py27/stdint.h similarity index 100% rename from src/windows/stdint.h rename to src/windows/py27/stdint.h diff --git a/tools/automate.py b/tools/automate.py index e3863f6e3..c89b419e1 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -633,7 +633,7 @@ def fix_cef_include_files(): fp.write(contents) -def create_prebuilt_binaries(copy_apps=True): +def create_prebuilt_binaries(): """After building copy binaries/libs to build/cef_xxxx/. Not all projects may have been built on all platforms.""" diff --git a/tools/build.py b/tools/build.py index 05a0de6c4..d791b8849 100644 --- a/tools/build.py +++ b/tools/build.py @@ -67,7 +67,6 @@ # First run FIRST_RUN = False -CEFPYTHON_H = os.path.join(BUILD_CEFPYTHON, "cefpython.h") def main(): @@ -283,31 +282,62 @@ def check_directories(): def fix_cefpython_h(): + """This function does two things: 1) Disable warnings in cefpython.h + and 2) Make a copy named cefpython_fixed.h - this copy will be used + by C++ projects and its modification time won't change every time + you run build.py script, thus C++ won't rebuild each time.""" + # Fix cefpython.h to disable this warning: # > warning: 'somefunc' has C-linkage specified, but returns # > user-defined type 'sometype' which is incompatible with C # On Mac this warning must be disabled using -Wno-return-type-c-linkage # flag in makefiles. - if MAC: - return - os.chdir(BUILD_CEFPYTHON) - print("[build.py] Fix cefpython.h to disable warnings") - if not os.path.exists("cefpython.h"): + + print("[build.py] Fix cefpython.h in the build_cefpython/ directory") + if not os.path.exists(CEFPYTHON_H): + assert not os.path.exists(CEFPYTHON_H_FIXED) print("[build.py] cefpython.h was not yet generated") return - with open("cefpython.h", "r") as fo: + + with open(CEFPYTHON_H, "r") as fo: contents = fo.read() + + already_fixed = False pragma = "#pragma warning(disable:4190)" if pragma in contents: + already_fixed = True print("[build.py] cefpython.h is already fixed") - return - contents = ("%s\n\n" % pragma) + contents - with open("cefpython.h", "w") as fo: - fo.write(contents) - print("[build.py] Save build_cefpython/cefpython.h") + else: + if not MAC: + contents = ("%s\n\n" % pragma) + contents + + if not already_fixed: + with open(CEFPYTHON_H, "w") as fo: + fo.write(contents) + print("[build.py] Save cefpython.h") + + if os.path.exists(CEFPYTHON_H_FIXED): + with open(CEFPYTHON_H_FIXED, "r") as fo: + contents_fixed = fo.read() + else: + contents_fixed = "" + if contents != contents_fixed: + print("[build.py] Save cefpython_fixed.h") + with open(CEFPYTHON_H_FIXED, "w") as fo: + fo.write(contents) + + +def compile_cpp_projects_windows_v2(): + """Use setuptools to build static libraries / executable.""" + compile_cpp_projects = os.path.join(TOOLS_DIR, "build_cpp_projects.py") + retcode = subprocess.call([sys.executable, compile_cpp_projects]) + if retcode != 0: + print("[build.py] ERROR: Failed to compile C++ projects") + sys.exit(1) def compile_cpp_projects_windows(): + """Build C++ projects using .vcproj files.""" print("[build.py] Compile C++ projects") print("[build.py] ~~ Build CLIENT_HANDLER vcproj") diff --git a/tools/build_cpp_projects.py b/tools/build_cpp_projects.py new file mode 100644 index 000000000..4e4881c62 --- /dev/null +++ b/tools/build_cpp_projects.py @@ -0,0 +1,292 @@ +"""Build C++ projects. This tool is executed by build.py on Windows +only currently. Output directories are in build/build_cefpython/. + +Usage: + build_cpp_projects.py [--force] + +TODO: Linux/Mac support, see makefiles, add include dirs using + compiler.add_include_dir, compiler/linker flags, + refactor macros. +""" + +# import setuptools so that distutils msvc compiler is patched +# noinspection PyUnresolvedReferences +import setuptools +from distutils.ccompiler import new_compiler +from common import * +import shutil + +# Macros +MACROS = [ + "WIN32", "_WIN32", "_WINDOWS", + ("WINVER", "0x0601"), ("_WIN32_WINNT", "0x0601"), # Windows 7+ + "NDEBUG", "_NDEBUG", + "_CRT_SECURE_NO_WARNINGS", +] +cefpython_app_MACROS = MACROS + [ + "BROWSER_PROCESS", +] +subprocess_MACROS = MACROS + [ + "RENDERER_PROCESS", + "UNICODE", "_UNICODE", + "NOMINMAX", + "WIN32_LEAN_AND_MEAN", + ("_HAS_EXCEPTIONS", "0"), +] + +# Compiler args +COMPILER_ARGS = [ + "/EHsc", +] +subprocess_COMPILER_ARGS = [ + "/MT", +] + +# Linker args +subprocess_LINKER_ARGS = [ + "/MANIFEST:NO", + "/LARGEADDRESSAWARE", +] + +# Command line args +FORCE_FLAG = False + + +def main(): + command_line_args() + clean_build_directories_if_forced() + build_cefpython_app_library() + build_library(lib_name="client_handler", + macros=MACROS, + sources_dir=CLIENT_HANDLER_DIR, + output_dir=BUILD_CLIENT_HANDLER) + build_library(lib_name="cpp_utils", + macros=MACROS, + sources_dir=CPP_UTILS_DIR, + output_dir=BUILD_CPP_UTILS) + build_subprocess_executable() + print("[build_cpp_projects.py] Done building C++ projects") + + +def command_line_args(): + global FORCE_FLAG + if "--force" in sys.argv: + FORCE_FLAG = True + + +def clean_build_directories_if_forced(): + build_dirs = [BUILD_CEFPYTHON_APP, BUILD_CLIENT_HANDLER, BUILD_CPP_UTILS, + BUILD_SUBPROCESS] + if FORCE_FLAG: + print("[build_cpp_projects.py] Clean C++ projects build directories") + for bdir in build_dirs: + if os.path.isdir(bdir): + shutil.rmtree(bdir) + + +def get_compiler(static=False): + # NOTES: + # - VS2008 and VS2010 are both using distutils/msvc9compiler.py + compiler = new_compiler() + # Must initialize so that "compile_options" and others are available + compiler.initialize() + if static: + compiler.compile_options.remove("/MD") + # Overwrite function that adds /MANIFESTFILE, as for subprocess + # manifest is disabled. Otherwise warning LNK4075 is generated. + if hasattr(compiler, "manifest_setup_ldargs"): + compiler.manifest_setup_ldargs = lambda *_: None + return compiler + + +def build_library(lib_name, macros, output_dir, + sources=None, sources_dir=None): + assert bool(sources_dir) ^ bool(sources) # xor + print("[build_cpp_projects.py] Build library: {lib_name}" + .format(lib_name=lib_name)) + compiler = get_compiler() + if not os.path.exists(output_dir): + os.makedirs(output_dir) + if sources_dir: + assert not sources + sources = get_sources(sources_dir) + (changed, objects) = smart_compile(compiler, + macros=macros, + extra_args=COMPILER_ARGS, + sources=sources, + output_dir=output_dir) + lib_path = os.path.join(output_dir, lib_name + LIB_EXT) + if changed or not os.path.exists(lib_path): + compiler.create_static_lib(objects, lib_name, + output_dir=output_dir) + print("[build_cpp_projects.py] Created library: {lib_name}" + .format(lib_name=lib_name)) + else: + print("[build_cpp_projects.py] Library is up-to-date: {lib_name}" + .format(lib_name=lib_name)) + + +def build_cefpython_app_library(): + sources = get_sources(SUBPROCESS_DIR, exclude_names=["main.cpp"]) + main_message_loop_dir = os.path.join(SUBPROCESS_DIR, "main_message_loop") + sources.extend(get_sources(main_message_loop_dir)) + build_library(lib_name="cefpython_app", + macros=cefpython_app_MACROS, + sources=sources, + output_dir=BUILD_CEFPYTHON_APP) + + +def build_subprocess_executable(): + print("[buil_cpp_projects.py] Build executable: subprocess") + compiler = get_compiler(static=True) + sources = get_sources(SUBPROCESS_DIR, + exclude_names=["print_handler_gtk.cpp"]) + (changed, objects) = smart_compile(compiler, + macros=subprocess_MACROS, + extra_args=subprocess_COMPILER_ARGS, + sources=sources, + output_dir=BUILD_SUBPROCESS) + executable_path = os.path.join(BUILD_SUBPROCESS, + "subprocess" + EXECUTABLE_EXT) + if changed or not os.path.exists(executable_path): + lib_dir = os.path.join(CEF_BINARIES_LIBRARIES, "lib") + compiler.link_executable(objects, + output_progname="subprocess", + output_dir=BUILD_SUBPROCESS, + libraries=["libcef", + "libcef_dll_wrapper_mt"], + library_dirs=[lib_dir], + # TODO linker flags for Linux/Mac + extra_preargs=None, + extra_postargs=subprocess_LINKER_ARGS) + else: + print("[build_cpp_projects.py] Executable is up-to-date: subprocess") + + +def get_sources(sources_dir, exclude_names=None): + if not exclude_names: + exclude_names = list() + sources = glob.glob(os.path.join(sources_dir, "*.cpp")) + if MAC: + sources.extend(glob.glob(os.path.join(sources_dir, "*.mm"))) + ret = list() + for source_file in sources: + filename = os.path.basename(source_file) + if "_win.cpp" in filename and not WINDOWS: + continue + if "_linux.cpp" in filename and not LINUX: + continue + if "x11" in filename and not LINUX: + continue + if "gtk" in filename and not LINUX: + continue + if "_mac.cpp" in filename and not MAC: + continue + exclude = False + for name in exclude_names: + if name in filename: + exclude = True + break + if not exclude: + ret.append(source_file) + return ret + + +def smart_compile(compiler, macros, extra_args, sources, output_dir): + """Smart compile will only recompile files that need recompiling.""" + if not os.path.exists(output_dir): + os.makedirs(output_dir) + any_changed = False + objects = list() + for source_file in sources: + header_file = source_file.replace(".cpp", ".h") + header_file = header_file.replace(".mm", ".h") + assert header_file.endswith(".h") + if not os.path.isfile(header_file): + header_file = None + obj_file = os.path.join(output_dir, os.path.basename(source_file)) + obj_file = obj_file.replace(".cpp", OBJ_EXT) + obj_file = obj_file.replace(".mm", OBJ_EXT) + assert obj_file.endswith(OBJ_EXT) + if os.path.exists(obj_file): + # Recompile source file if its time is newer than obj file, + # Also check its header file time. Also check times of any + # possible includes: cefpython_fixed.h, src/common/ files. + obj_time = os.path.getmtime(obj_file) + source_time = os.path.getmtime(source_file) + header_time = os.path.getmtime(header_file) if header_file else 0 + cefpython_h_fixed_time = os.path.getmtime(CEFPYTHON_H_FIXED) + common_files_time = get_directory_mtime(os.path.join(SRC_DIR, + "common")) + changed = ((source_time > obj_time) + or (header_time > obj_time) + or (cefpython_h_fixed_time > obj_time) + or (common_files_time > obj_time)) + else: + changed = True + if changed: + any_changed = True + else: + objects.append(obj_file) + if any_changed: + # If any has changed must recompile all given sources (for a library + # or executable). This is because we don't know which sources include + # which header files so must recompile everything. + objects = list() + # Compile each source file separately so that when compiling + # source files from different directories, object files are + # all put in the same output_directory. Otherwise distutils + # will create lots of subdirs in output_directory. + macros = macros_as_tuples(macros) + python_include = os.path.join(os.path.dirname(sys.executable), + "include") + common_dir = os.path.join(SRC_DIR, "common") + original_dir = os.getcwd() + for source_file in sources: + source_dir = os.path.dirname(source_file) + os.chdir(source_dir) + source_basename = os.path.basename(source_file) + oneobj = compiler.compile([source_basename], + output_dir=output_dir, + macros=macros, + # TODO include dirs for Linux/Mac + include_dirs=[SRC_DIR, + common_dir, + python_include], + # TODO compiler flags for Linux/Mac + extra_preargs=None, + extra_postargs=extra_args) + assert len(oneobj) == 1 + objects.append(os.path.join(source_dir, oneobj[0])) + os.chdir(original_dir) + assert len(objects) + return any_changed, objects + + +def macros_as_tuples(macros): + """Return all macros as tuples. Required by distutils.ccompiler.""" + ret_macros = list() + for macro in macros: + if isinstance(macro, str): + ret_macros.append((macro, "")) + else: + assert isinstance(macro, tuple) + ret_macros.append(macro) + return ret_macros + + +def get_directory_mtime(directory): + # For example check src/common/ directory for newest modification time + assert os.path.isdir(directory) + files = glob.glob(os.path.join(directory, "*")) + ret_mtime = 0 + for header_file in files: + mtime = os.path.getmtime(header_file) + if mtime > ret_mtime: + ret_mtime = mtime + assert ret_mtime + return ret_mtime + + +if __name__ == "__main__": + main() diff --git a/tools/common.py b/tools/common.py index b71e0b26d..779a76e10 100644 --- a/tools/common.py +++ b/tools/common.py @@ -58,36 +58,73 @@ # Library extension if WINDOWS: - STATIC_LIBRARY_EXT = ".lib" + LIB_EXT = ".lib" else: - STATIC_LIBRARY_EXT = ".a" + LIB_EXT = ".a" -# Root directory +# Compiled object extension +if WINDOWS: + OBJ_EXT = ".obj" +else: + OBJ_EXT = ".o" + +# ---------------------------------------------------------------------------- +# Directories +# ---------------------------------------------------------------------------- assert __file__ ROOT_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) -# Other directories +# Build directories BUILD_DIR = os.path.join(ROOT_DIR, "build") -if BUILD_DIR: - BUILD_CEFPYTHON = os.path.join(BUILD_DIR, "build_cefpython") - # -- Auto-detected directories. - # May be auto-overwritten through detect_cef_binaries_libraries_dir() - CEF_BINARIES_LIBRARIES = os.path.join(BUILD_DIR, "cef_"+OS_POSTFIX2) - # Will be overwritten through detect_cefpython_binary_dir() - CEFPYTHON_BINARY = "CEFPYTHON_BINARY" +BUILD_CEFPYTHON = os.path.join(BUILD_DIR, "build_cefpython") + +# May be auto-overwritten through detect_cef_binaries_libraries_dir() +CEF_BINARIES_LIBRARIES = os.path.join(BUILD_DIR, "cef_"+OS_POSTFIX2) + +# Will be overwritten through detect_cefpython_binary_dir() +CEFPYTHON_BINARY = "CEFPYTHON_BINARY" + +# Build C++ projects directories +BUILD_CEFPYTHON_APP = os.path.join(BUILD_CEFPYTHON, + "cefpython_app_" + OS_POSTFIX2) +BUILD_CLIENT_HANDLER = os.path.join(BUILD_CEFPYTHON, + "client_handler_" + OS_POSTFIX2) +BUILD_CPP_UTILS = os.path.join(BUILD_CEFPYTHON, + "cpp_utils_" + OS_POSTFIX2) +BUILD_SUBPROCESS = os.path.join(BUILD_CEFPYTHON, + "subprocess_" + OS_POSTFIX2) +# -- end build directories + EXAMPLES_DIR = os.path.join(ROOT_DIR, "examples") SRC_DIR = os.path.join(ROOT_DIR, "src") -if SRC_DIR: - CLIENT_HANDLER_DIR = os.path.join(SRC_DIR, "client_handler") - CPP_UTILS_DIR = os.path.join(SRC_DIR, "cpp_utils") - LINUX_DIR = os.path.join(SRC_DIR, "linux") - MAC_DIR = os.path.join(SRC_DIR, "mac") - SUBPROCESS_DIR = os.path.join(SRC_DIR, "subprocess") - WINDOWS_DIR = os.path.abspath(os.path.join(SRC_DIR, "windows")) + +# Subdirectories in src/ +CLIENT_HANDLER_DIR = os.path.join(SRC_DIR, "client_handler") +CPP_UTILS_DIR = os.path.join(SRC_DIR, "cpp_utils") +LINUX_DIR = os.path.join(SRC_DIR, "linux") +MAC_DIR = os.path.join(SRC_DIR, "mac") +SUBPROCESS_DIR = os.path.join(SRC_DIR, "subprocess") +WINDOWS_DIR = os.path.abspath(os.path.join(SRC_DIR, "windows")) +# -- end subdirectories in src/ + TOOLS_DIR = os.path.join(ROOT_DIR, "tools") -if TOOLS_DIR: - INSTALLER_DIR = os.path.join(TOOLS_DIR, "installer") +INSTALLER_DIR = os.path.join(TOOLS_DIR, "installer") UNITTESTS_DIR = os.path.abspath(os.path.join(ROOT_DIR, "unittests")) +# ---------------------------------------------------------------------------- + +# cefpython.h and fixed version +CEFPYTHON_H = os.path.join(BUILD_CEFPYTHON, "cefpython.h") +CEFPYTHON_H_FIXED = os.path.join(BUILD_CEFPYTHON, "cefpython_fixed.h") + +# Result libraries paths +CEFPYTHON_APP_LIB = os.path.join(BUILD_CEFPYTHON_APP, + "cefpython_app" + LIB_EXT) +CLIENT_HANDLER_LIB = os.path.join(BUILD_CLIENT_HANDLER, + "client_handler" + LIB_EXT) +CPP_UTILS_LIB = os.path.join(BUILD_CPP_UTILS, + "cpp_utils" + LIB_EXT) +SUBPROCESS_EXE = os.path.join(BUILD_SUBPROCESS, + "subprocess" + EXECUTABLE_EXT) # Visual Studio constants VS_PLATFORM_ARG = "x86" if ARCH32 else "amd64" From ae2727fd95fc16bd5f90e781f1a535e6fc3bbf06 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 8 Mar 2017 08:53:16 +0100 Subject: [PATCH 156/557] Fix copyright notices in source files. Update info on ApplicationSettings.external_message_pump. --- api/ApplicationSettings.md | 10 +++++++--- src/app.pyx | 6 +++--- src/browser.pyx | 6 +++--- src/callback.pyx | 6 +++--- src/cefpython.pyx | 6 +++--- src/client_handler/client_handler.cpp | 6 +++--- src/client_handler/client_handler.h | 6 +++--- src/client_handler/context_menu_handler.cpp | 4 +++- src/client_handler/context_menu_handler.h | 4 +++- src/client_handler/cookie_visitor.cpp | 6 +++--- src/client_handler/cookie_visitor.h | 6 +++--- src/client_handler/display_handler.cpp | 4 +++- src/client_handler/display_handler.h | 4 +++- src/client_handler/download_handler.cpp | 4 +++- src/client_handler/download_handler.h | 4 +++- src/client_handler/dpi_aware.cpp | 6 +++--- src/client_handler/dpi_aware.h | 6 +++--- src/client_handler/focus_handler.cpp | 4 +++- src/client_handler/focus_handler.h | 4 +++- src/client_handler/js_dialog_handler.cpp | 4 +++- src/client_handler/js_dialog_handler.h | 4 +++- src/client_handler/keyboard_handler.cpp | 4 +++- src/client_handler/keyboard_handler.h | 4 +++- src/client_handler/lifespan_handler.cpp | 4 +++- src/client_handler/lifespan_handler.h | 4 +++- src/client_handler/load_handler.cpp | 4 +++- src/client_handler/load_handler.h | 4 +++- src/client_handler/render_handler.cpp | 4 +++- src/client_handler/render_handler.h | 4 +++- src/client_handler/request_context_handler.cpp | 6 +++--- src/client_handler/request_context_handler.h | 6 +++--- src/client_handler/request_handler.cpp | 4 +++- src/client_handler/request_handler.h | 4 +++- src/client_handler/resource_handler.cpp | 6 +++--- src/client_handler/resource_handler.h | 6 +++--- src/client_handler/string_visitor.cpp | 6 +++--- src/client_handler/string_visitor.h | 6 +++--- src/client_handler/task.cpp | 4 +++- src/client_handler/task.h | 4 +++- src/client_handler/web_request_client.cpp | 6 +++--- src/client_handler/web_request_client.h | 6 +++--- src/client_handler/x11.cpp | 4 +++- src/client_handler/x11.h | 4 +++- src/command_line.pyx | 6 +++--- src/common/DebugLog.h | 6 +++--- src/common/LOG_DEBUG.h | 2 +- src/common/cefpython_public_api.h | 4 ++++ src/cookie.pyx | 6 +++--- src/cpp_utils/PaintBuffer.cpp | 4 ++++ src/cpp_utils/PaintBuffer.h | 6 +++--- src/dpi_aware_win.pyx | 6 +++--- src/drag_data.pyx | 4 +++- src/extern/cef/cef_app.pxd | 6 +++--- src/extern/cef/cef_base.pxd | 6 +++--- src/extern/cef/cef_browser.pxd | 6 +++--- src/extern/cef/cef_browser_static.pxd | 6 +++--- src/extern/cef/cef_callback.pxd | 6 +++--- src/extern/cef/cef_client.pxd | 6 +++--- src/extern/cef/cef_command_line.pxd | 6 +++--- src/extern/cef/cef_cookie.pxd | 6 +++--- src/extern/cef/cef_cookie_manager_namespace.pxd | 4 ++++ src/extern/cef/cef_drag_data.pxd | 4 +++- src/extern/cef/cef_frame.pxd | 6 +++--- src/extern/cef/cef_image.pxd | 4 +++- src/extern/cef/cef_jsdialog_handler.pxd | 6 +++--- src/extern/cef/cef_linux.pxd | 6 +++--- src/extern/cef/cef_mac.pxd | 6 +++--- src/extern/cef/cef_path_util.pxd | 4 +++- src/extern/cef/cef_platform.pxd | 6 +++--- src/extern/cef/cef_process_message.pxd | 6 +++--- src/extern/cef/cef_ptr.pxd | 6 +++--- src/extern/cef/cef_request.pxd | 6 +++--- src/extern/cef/cef_request_context.pxd | 6 +++--- src/extern/cef/cef_request_context_handler.pxd | 6 +++--- src/extern/cef/cef_request_handler.pxd | 6 +++--- src/extern/cef/cef_resource_handler.pxd | 6 +++--- src/extern/cef/cef_response.pxd | 6 +++--- src/extern/cef/cef_scoped_ptr.pxd | 4 +++- src/extern/cef/cef_string.pxd | 6 +++--- src/extern/cef/cef_string_visitor.pxd | 6 +++--- src/extern/cef/cef_task.pxd | 6 +++--- src/extern/cef/cef_time.pxd | 6 +++--- src/extern/cef/cef_types.pxd | 6 +++--- src/extern/cef/cef_urlrequest.pxd | 6 +++--- src/extern/cef/cef_values.pxd | 6 +++--- src/extern/cef/cef_web_plugin.pxd | 6 +++--- src/extern/cef/cef_win.pxd | 6 +++--- src/extern/cefpython_app.pxd | 6 +++--- src/extern/client_handler.pxd | 6 +++--- src/extern/cookie_visitor.pxd | 6 +++--- src/extern/cpp_utils.pxd | 6 +++--- src/extern/ctime.pxd | 6 +++--- src/extern/dpi_aware_win.pxd | 6 +++--- src/extern/linux.pxd | 6 +++--- src/extern/mac.pxd | 6 +++--- src/extern/main_message_loop.pxd | 4 +++- src/extern/multimap.pxd | 6 +++--- src/extern/request_context_handler.pxd | 6 +++--- src/extern/resource_handler.pxd | 6 +++--- src/extern/string_visitor.pxd | 6 +++--- src/extern/task.pxd | 6 +++--- src/extern/web_request_client.pxd | 6 +++--- src/extern/windows.pxd | 6 +++--- src/extern/wstring.pxd | 2 ++ src/extern/x11.pxd | 4 +++- src/frame.pyx | 6 +++--- src/handlers/browser_process_handler.pyx | 6 +++--- src/handlers/display_handler.pyx | 6 +++--- src/handlers/focus_handler.pyx | 4 +++- src/handlers/javascript_dialog_handler.pyx | 6 +++--- src/handlers/keyboard_handler.pyx | 6 +++--- src/handlers/lifespan_handler.pyx | 6 +++--- src/handlers/load_handler.pyx | 6 +++--- src/handlers/render_handler.pyx | 6 +++--- src/handlers/request_handler.pyx | 6 +++--- src/handlers/resource_handler.pyx | 6 +++--- src/handlers/v8context_handler.pyx | 6 +++--- src/handlers/v8function_handler.pyx | 6 +++--- src/helpers.pyx | 4 +++- src/image.pyx | 4 +++- src/javascript_bindings.pyx | 6 +++--- src/javascript_callback.pyx | 6 +++--- src/network_error.pyx | 6 +++--- src/paint_buffer.pyx | 6 +++--- src/process_message_utils.pyx | 6 +++--- src/python_callback.pyx | 6 +++--- src/request.pyx | 6 +++--- src/response.pyx | 6 +++--- src/settings.pyx | 6 +++--- src/string_utils.pyx | 6 +++--- src/string_utils_win.pyx | 6 +++--- src/string_visitor.pyx | 6 +++--- src/subprocess/cefpython_app.cpp | 6 +++--- src/subprocess/cefpython_app.h | 6 +++--- src/subprocess/javascript_callback.cpp | 6 +++--- src/subprocess/javascript_callback.h | 6 +++--- src/subprocess/main.cpp | 6 +++--- src/subprocess/v8function_handler.cpp | 6 +++--- src/subprocess/v8function_handler.h | 6 +++--- src/subprocess/v8utils.cpp | 6 +++--- src/subprocess/v8utils.h | 6 +++--- src/task.pyx | 6 +++--- src/time_utils.pyx | 6 +++--- src/utils.pyx | 6 +++--- src/virtual_keys.pyx | 6 +++--- src/web_plugin_info.pyx | 6 +++--- src/web_request.pyx | 6 +++--- src/window_info.pyx | 6 +++--- src/window_utils_linux.pyx | 6 +++--- src/window_utils_mac.pyx | 6 +++--- src/window_utils_win.pyx | 6 +++--- tools/apidocs.py | 4 +++- tools/automate.py | 4 +++- tools/build.py | 5 +++-- tools/build_cpp_projects.py | 4 ++++ tools/common.py | 4 ++++ tools/cython_setup.py | 5 +++-- tools/installer/cefpython3.__init__.py | 5 +++-- tools/installer/cefpython3.setup.py | 5 +++-- tools/make_installer.py | 5 +++-- tools/run_examples.py | 4 ++++ tools/toc.py | 4 +++- unittests/_test_runner.py | 4 +++- unittests/isolated_test.py | 4 ++++ unittests/main_test.py | 4 ++++ unittests/unittest_test.py | 4 ++++ 166 files changed, 508 insertions(+), 385 deletions(-) diff --git a/api/ApplicationSettings.md b/api/ApplicationSettings.md index 881de7a15..f651941b8 100644 --- a/api/ApplicationSettings.md +++ b/api/ApplicationSettings.md @@ -163,13 +163,17 @@ Downloads are handled automatically. A default `SaveAs` file dialog provided by (bool) Default: False -EXPERIMENTAL: currently this option makes browser slower, so don't use it. - Reported issue in upstream, see Issue #246 for details. +EXPERIMENTAL: So far this was tested only on Linux and actually made app + significantly slower. Windows and Mac platforms were not + tested yet. Reported issue in upstream, see [Issue #246] + (https://github.com/cztomczak/cefpython/issues/246) for details. It is recommended to use this option as a replacement for calls to cefpython.MessageLoopWork(). CEF Python will do these calls automatically using CEF's OnScheduleMessagePumpWork. This results in improved performance -and resolves some bugs. See Issue #246 for more details. +on Windows and Mac and resolves some bugs with missing keyboard events +on these platforms. See [Issue #246] +(https://github.com/cztomczak/cefpython/issues/246) for more details. Description from upstream CEF: > Set to true (1) to control browser process main (UI) thread message pump diff --git a/src/app.pyx b/src/app.pyx index cfd6e254d..a00d58bf6 100644 --- a/src/app.pyx +++ b/src/app.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2014 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/browser.pyx b/src/browser.pyx index 4a38f0d8e..c5aadd53c 100644 --- a/src/browser.pyx +++ b/src/browser.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "cefpython.pyx" diff --git a/src/callback.pyx b/src/callback.pyx index a98ced6ec..902b9b526 100644 --- a/src/callback.pyx +++ b/src/callback.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/cefpython.pyx b/src/cefpython.pyx index fe4b4e426..261da9758 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 """ CHANGES in CEF since v31..v51. diff --git a/src/client_handler/client_handler.cpp b/src/client_handler/client_handler.cpp index 498631274..d8f6189e6 100644 --- a/src/client_handler/client_handler.cpp +++ b/src/client_handler/client_handler.cpp @@ -1,6 +1,6 @@ -// Copyright (c) 2012 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// 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 // NOTE: clienthandler code is running only in the BROWSER PROCESS. // cefpythonapp code is running in both BROWSER PROCESS and subprocess diff --git a/src/client_handler/client_handler.h b/src/client_handler/client_handler.h index e4e5432dc..33c125072 100644 --- a/src/client_handler/client_handler.h +++ b/src/client_handler/client_handler.h @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// 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 // ClientHandler code is running only in the Browser process. diff --git a/src/client_handler/context_menu_handler.cpp b/src/client_handler/context_menu_handler.cpp index 4d5a24c8f..1304e8035 100644 --- a/src/client_handler/context_menu_handler.cpp +++ b/src/client_handler/context_menu_handler.cpp @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// Copyright (c) 2016 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "context_menu_handler.h" #include "common/DebugLog.h" diff --git a/src/client_handler/context_menu_handler.h b/src/client_handler/context_menu_handler.h index f44bc68b0..e22f7541b 100644 --- a/src/client_handler/context_menu_handler.h +++ b/src/client_handler/context_menu_handler.h @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// Copyright (c) 2016 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #pragma once diff --git a/src/client_handler/cookie_visitor.cpp b/src/client_handler/cookie_visitor.cpp index e70c83b58..eea845f35 100644 --- a/src/client_handler/cookie_visitor.cpp +++ b/src/client_handler/cookie_visitor.cpp @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2014 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "cookie_visitor.h" #include diff --git a/src/client_handler/cookie_visitor.h b/src/client_handler/cookie_visitor.h index 187d6633d..54c2b53fd 100644 --- a/src/client_handler/cookie_visitor.h +++ b/src/client_handler/cookie_visitor.h @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2014 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #pragma once diff --git a/src/client_handler/display_handler.cpp b/src/client_handler/display_handler.cpp index 1d45a3d4b..a30109d06 100644 --- a/src/client_handler/display_handler.cpp +++ b/src/client_handler/display_handler.cpp @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// 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 #include "display_handler.h" diff --git a/src/client_handler/display_handler.h b/src/client_handler/display_handler.h index 4df798744..6b6810cac 100644 --- a/src/client_handler/display_handler.h +++ b/src/client_handler/display_handler.h @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// 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 diff --git a/src/client_handler/download_handler.cpp b/src/client_handler/download_handler.cpp index 39efa5d3b..fae9b3138 100644 --- a/src/client_handler/download_handler.cpp +++ b/src/client_handler/download_handler.cpp @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// Copyright (c) 2014 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "download_handler.h" #include "common/DebugLog.h" diff --git a/src/client_handler/download_handler.h b/src/client_handler/download_handler.h index 8c6d809b4..e4fc5faf1 100644 --- a/src/client_handler/download_handler.h +++ b/src/client_handler/download_handler.h @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// Copyright (c) 2014 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "common/cefpython_public_api.h" #include "include/cef_download_handler.h" diff --git a/src/client_handler/dpi_aware.cpp b/src/client_handler/dpi_aware.cpp index 92d35685c..6c8a9213b 100644 --- a/src/client_handler/dpi_aware.cpp +++ b/src/client_handler/dpi_aware.cpp @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2014 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython // Windows only diff --git a/src/client_handler/dpi_aware.h b/src/client_handler/dpi_aware.h index 7bd5caea2..d3a973c4e 100644 --- a/src/client_handler/dpi_aware.h +++ b/src/client_handler/dpi_aware.h @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2014 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython // Windows only diff --git a/src/client_handler/focus_handler.cpp b/src/client_handler/focus_handler.cpp index 4fba67dd5..b0e17a777 100644 --- a/src/client_handler/focus_handler.cpp +++ b/src/client_handler/focus_handler.cpp @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// Copyright (c) 2016 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "focus_handler.h" diff --git a/src/client_handler/focus_handler.h b/src/client_handler/focus_handler.h index 52e972fb1..956ffdee1 100644 --- a/src/client_handler/focus_handler.h +++ b/src/client_handler/focus_handler.h @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// Copyright (c) 2016 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "common/cefpython_public_api.h" #include "include/cef_focus_handler.h" diff --git a/src/client_handler/js_dialog_handler.cpp b/src/client_handler/js_dialog_handler.cpp index c34db1ec9..a1f641a0c 100644 --- a/src/client_handler/js_dialog_handler.cpp +++ b/src/client_handler/js_dialog_handler.cpp @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// Copyright (c) 2016 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "js_dialog_handler.h" diff --git a/src/client_handler/js_dialog_handler.h b/src/client_handler/js_dialog_handler.h index dfaa9b7ac..6d3ce3e48 100644 --- a/src/client_handler/js_dialog_handler.h +++ b/src/client_handler/js_dialog_handler.h @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// Copyright (c) 2016 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "common/cefpython_public_api.h" #include "include/cef_jsdialog_handler.h" diff --git a/src/client_handler/keyboard_handler.cpp b/src/client_handler/keyboard_handler.cpp index 77b007807..badaf01ae 100644 --- a/src/client_handler/keyboard_handler.cpp +++ b/src/client_handler/keyboard_handler.cpp @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// 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 #include "keyboard_handler.h" diff --git a/src/client_handler/keyboard_handler.h b/src/client_handler/keyboard_handler.h index 3ecb48d90..7aa5f1e39 100644 --- a/src/client_handler/keyboard_handler.h +++ b/src/client_handler/keyboard_handler.h @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// 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 #include "common/cefpython_public_api.h" #include "include/cef_keyboard_handler.h" diff --git a/src/client_handler/lifespan_handler.cpp b/src/client_handler/lifespan_handler.cpp index d77a1f0e6..0cfd2d1b1 100644 --- a/src/client_handler/lifespan_handler.cpp +++ b/src/client_handler/lifespan_handler.cpp @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// 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 #include "lifespan_handler.h" #if defined(OS_WIN) diff --git a/src/client_handler/lifespan_handler.h b/src/client_handler/lifespan_handler.h index b4b97022b..91244eff9 100644 --- a/src/client_handler/lifespan_handler.h +++ b/src/client_handler/lifespan_handler.h @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// 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 #include "common/cefpython_public_api.h" #include "include/cef_life_span_handler.h" diff --git a/src/client_handler/load_handler.cpp b/src/client_handler/load_handler.cpp index f0a975272..20a6d341d 100644 --- a/src/client_handler/load_handler.cpp +++ b/src/client_handler/load_handler.cpp @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// 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 #include "load_handler.h" diff --git a/src/client_handler/load_handler.h b/src/client_handler/load_handler.h index 04ba44e36..fd203d7d1 100644 --- a/src/client_handler/load_handler.h +++ b/src/client_handler/load_handler.h @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// 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 #include "common/cefpython_public_api.h" #include "include/cef_load_handler.h" diff --git a/src/client_handler/render_handler.cpp b/src/client_handler/render_handler.cpp index fcbbbfeb9..f6b4d5bec 100644 --- a/src/client_handler/render_handler.cpp +++ b/src/client_handler/render_handler.cpp @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "render_handler.h" diff --git a/src/client_handler/render_handler.h b/src/client_handler/render_handler.h index bcf2c5626..5baae3202 100644 --- a/src/client_handler/render_handler.h +++ b/src/client_handler/render_handler.h @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "common/cefpython_public_api.h" #include "include/cef_render_handler.h" diff --git a/src/client_handler/request_context_handler.cpp b/src/client_handler/request_context_handler.cpp index 116d1faba..ef7cc8b9b 100644 --- a/src/client_handler/request_context_handler.cpp +++ b/src/client_handler/request_context_handler.cpp @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "request_context_handler.h" #include "common/cefpython_public_api.h" diff --git a/src/client_handler/request_context_handler.h b/src/client_handler/request_context_handler.h index c6a7184b8..b8bf25f3a 100644 --- a/src/client_handler/request_context_handler.h +++ b/src/client_handler/request_context_handler.h @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #pragma once diff --git a/src/client_handler/request_handler.cpp b/src/client_handler/request_handler.cpp index c2134f7ae..699043776 100644 --- a/src/client_handler/request_handler.cpp +++ b/src/client_handler/request_handler.cpp @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// 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 #include "request_handler.h" #include "common/DebugLog.h" diff --git a/src/client_handler/request_handler.h b/src/client_handler/request_handler.h index 66ee9aa64..afaf3f832 100644 --- a/src/client_handler/request_handler.h +++ b/src/client_handler/request_handler.h @@ -1,4 +1,6 @@ -// Copyright (c) 2016 CEF Python. See the Authors and License files. +// 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 #include "common/cefpython_public_api.h" #include "include/cef_request_handler.h" diff --git a/src/client_handler/resource_handler.cpp b/src/client_handler/resource_handler.cpp index 7c2cfebbf..963575928 100644 --- a/src/client_handler/resource_handler.cpp +++ b/src/client_handler/resource_handler.cpp @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "resource_handler.h" diff --git a/src/client_handler/resource_handler.h b/src/client_handler/resource_handler.h index e386a1665..3bf5e41f6 100644 --- a/src/client_handler/resource_handler.h +++ b/src/client_handler/resource_handler.h @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #pragma once diff --git a/src/client_handler/string_visitor.cpp b/src/client_handler/string_visitor.cpp index d8f368f00..f6b199247 100644 --- a/src/client_handler/string_visitor.cpp +++ b/src/client_handler/string_visitor.cpp @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "string_visitor.h" #include diff --git a/src/client_handler/string_visitor.h b/src/client_handler/string_visitor.h index 439b35ad0..3765442c5 100644 --- a/src/client_handler/string_visitor.h +++ b/src/client_handler/string_visitor.h @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #pragma once diff --git a/src/client_handler/task.cpp b/src/client_handler/task.cpp index ba096579d..8767e5156 100644 --- a/src/client_handler/task.cpp +++ b/src/client_handler/task.cpp @@ -1,4 +1,6 @@ -// Copyright (c) 2012-2016 CEF Python. All rights reserved. +// Copyright (c) 2014 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "task.h" #include "include/wrapper/cef_closure_task.h" diff --git a/src/client_handler/task.h b/src/client_handler/task.h index 62271599d..ee9821694 100644 --- a/src/client_handler/task.h +++ b/src/client_handler/task.h @@ -1,4 +1,6 @@ -// Copyright (c) 2012-2016 CEF Python. All rights reserved. +// Copyright (c) 2014 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #pragma once diff --git a/src/client_handler/web_request_client.cpp b/src/client_handler/web_request_client.cpp index 1634c8f17..965de919b 100644 --- a/src/client_handler/web_request_client.cpp +++ b/src/client_handler/web_request_client.cpp @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "web_request_client.h" diff --git a/src/client_handler/web_request_client.h b/src/client_handler/web_request_client.h index 191049c5e..8b815a968 100644 --- a/src/client_handler/web_request_client.h +++ b/src/client_handler/web_request_client.h @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #pragma once diff --git a/src/client_handler/x11.cpp b/src/client_handler/x11.cpp index 2ed495de9..9199f4c95 100644 --- a/src/client_handler/x11.cpp +++ b/src/client_handler/x11.cpp @@ -1,4 +1,6 @@ -// Copyright (c) 2016 The CEF Python authors. All rights reserved. +// Copyright (c) 2016 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include #include "LOG_DEBUG.h" diff --git a/src/client_handler/x11.h b/src/client_handler/x11.h index a8a19eb31..863296fed 100644 --- a/src/client_handler/x11.h +++ b/src/client_handler/x11.h @@ -1,4 +1,6 @@ -// Copyright (c) 2016 The CEF Python authors. All rights reserved. +// Copyright (c) 2016 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython void InstallX11ErrorHandlers(); void SetX11WindowBounds(CefRefPtr browser, diff --git a/src/command_line.pyx b/src/command_line.pyx index 21f42df46..dd26b61d3 100644 --- a/src/command_line.pyx +++ b/src/command_line.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2014 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/common/DebugLog.h b/src/common/DebugLog.h index 83ffaadd6..4c5419a6b 100644 --- a/src/common/DebugLog.h +++ b/src/common/DebugLog.h @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// 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 diff --git a/src/common/LOG_DEBUG.h b/src/common/LOG_DEBUG.h index 1c735d2cb..672ad25e1 100644 --- a/src/common/LOG_DEBUG.h +++ b/src/common/LOG_DEBUG.h @@ -1,6 +1,6 @@ // Taken from here: http://www.drdobbs.com/cpp/logging-in-c/201804215 // Original author: Petru Marginean -// Modified by: Czarek Tomczak +// Modified by: Czarek Tomczak // Usage: // LOG_DEBUG << "Browser: someVar = " << someVar; diff --git a/src/common/cefpython_public_api.h b/src/common/cefpython_public_api.h index ff4400aaf..fe0dc5a0d 100644 --- a/src/common/cefpython_public_api.h +++ b/src/common/cefpython_public_api.h @@ -1,3 +1,7 @@ +// Copyright (c) 2012 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython + /* This is a wrapper around including cefpython_fixed.h that is generated by Cython. Functions marked with the 'public' keyword are exposed to C through that header file. */ diff --git a/src/cookie.pyx b/src/cookie.pyx index a38d8a821..45b692ccb 100644 --- a/src/cookie.pyx +++ b/src/cookie.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/cpp_utils/PaintBuffer.cpp b/src/cpp_utils/PaintBuffer.cpp index ebaa03568..91c52f46b 100644 --- a/src/cpp_utils/PaintBuffer.cpp +++ b/src/cpp_utils/PaintBuffer.cpp @@ -1 +1,5 @@ +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython + #include "PaintBuffer.h" diff --git a/src/cpp_utils/PaintBuffer.h b/src/cpp_utils/PaintBuffer.h index d085473af..8621fda06 100644 --- a/src/cpp_utils/PaintBuffer.h +++ b/src/cpp_utils/PaintBuffer.h @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #pragma once diff --git a/src/dpi_aware_win.pyx b/src/dpi_aware_win.pyx index 29001e0d4..13d07d034 100644 --- a/src/dpi_aware_win.pyx +++ b/src/dpi_aware_win.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2014 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/drag_data.pyx b/src/drag_data.pyx index 0f2b42377..29e0cbd8f 100644 --- a/src/drag_data.pyx +++ b/src/drag_data.pyx @@ -1,4 +1,6 @@ -# Copyright (c) 2016 The CEF Python authors. All rights reserved. +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/extern/cef/cef_app.pxd b/src/extern/cef/cef_app.pxd index d763e81da..1715c0cfd 100644 --- a/src/extern/cef/cef_app.pxd +++ b/src/extern/cef/cef_app.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 # Circular imports are allowed in form "cimport ...", # but won't work if you do "from ... cimport *". diff --git a/src/extern/cef/cef_base.pxd b/src/extern/cef/cef_base.pxd index 00646bf77..3134bd8bf 100644 --- a/src/extern/cef/cef_base.pxd +++ b/src/extern/cef/cef_base.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 cdef extern from "include/cef_base.h": diff --git a/src/extern/cef/cef_browser.pxd b/src/extern/cef/cef_browser.pxd index 663fcb2b7..50a70393a 100644 --- a/src/extern/cef/cef_browser.pxd +++ b/src/extern/cef/cef_browser.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "compile_time_constants.pxi" diff --git a/src/extern/cef/cef_browser_static.pxd b/src/extern/cef/cef_browser_static.pxd index 34370a69b..17b1a283d 100644 --- a/src/extern/cef/cef_browser_static.pxd +++ b/src/extern/cef/cef_browser_static.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "compile_time_constants.pxi" diff --git a/src/extern/cef/cef_callback.pxd b/src/extern/cef/cef_callback.pxd index 01d7602db..5189d07c4 100644 --- a/src/extern/cef/cef_callback.pxd +++ b/src/extern/cef/cef_callback.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython cdef extern from "include/cef_callback.h": diff --git a/src/extern/cef/cef_client.pxd b/src/extern/cef/cef_client.pxd index 89568bb74..a3a4b01a0 100644 --- a/src/extern/cef/cef_client.pxd +++ b/src/extern/cef/cef_client.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 cdef extern from "include/cef_client.h": diff --git a/src/extern/cef/cef_command_line.pxd b/src/extern/cef/cef_command_line.pxd index 371010806..7fd9b3c23 100644 --- a/src/extern/cef/cef_command_line.pxd +++ b/src/extern/cef/cef_command_line.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2014 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython # Circular imports are allowed in form "cimport ...", # but won't work if you do "from ... cimport *". diff --git a/src/extern/cef/cef_cookie.pxd b/src/extern/cef/cef_cookie.pxd index f6c94b231..94263a6b4 100644 --- a/src/extern/cef/cef_cookie.pxd +++ b/src/extern/cef/cef_cookie.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from cef_string cimport cef_string_t from libcpp cimport bool as cpp_bool diff --git a/src/extern/cef/cef_cookie_manager_namespace.pxd b/src/extern/cef/cef_cookie_manager_namespace.pxd index fe0c14dac..bcc8a1b33 100644 --- a/src/extern/cef/cef_cookie_manager_namespace.pxd +++ b/src/extern/cef/cef_cookie_manager_namespace.pxd @@ -1,3 +1,7 @@ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython + include "compile_time_constants.pxi" from libcpp cimport bool as cpp_bool diff --git a/src/extern/cef/cef_drag_data.pxd b/src/extern/cef/cef_drag_data.pxd index 9b9a8469b..a011df10a 100644 --- a/src/extern/cef/cef_drag_data.pxd +++ b/src/extern/cef/cef_drag_data.pxd @@ -1,4 +1,6 @@ -# Copyright (c) 2016 The CEF Python authors. All rights reserved. +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from libcpp cimport bool as cpp_bool from cef_string cimport CefString diff --git a/src/extern/cef/cef_frame.pxd b/src/extern/cef/cef_frame.pxd index 499546a21..28cdceee2 100644 --- a/src/extern/cef/cef_frame.pxd +++ b/src/extern/cef/cef_frame.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "compile_time_constants.pxi" diff --git a/src/extern/cef/cef_image.pxd b/src/extern/cef/cef_image.pxd index 2e59cd93a..aafb75b85 100644 --- a/src/extern/cef/cef_image.pxd +++ b/src/extern/cef/cef_image.pxd @@ -1,4 +1,6 @@ -# Copyright (c) 2016 The CEF Python authors. All rights reserved. +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from cef_ptr cimport CefRefPtr from libcpp cimport bool as cpp_bool diff --git a/src/extern/cef/cef_jsdialog_handler.pxd b/src/extern/cef/cef_jsdialog_handler.pxd index b55f7a376..00178a01d 100644 --- a/src/extern/cef/cef_jsdialog_handler.pxd +++ b/src/extern/cef/cef_jsdialog_handler.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from cef_string cimport CefString from libcpp cimport bool as cpp_bool diff --git a/src/extern/cef/cef_linux.pxd b/src/extern/cef/cef_linux.pxd index c094bcc01..e42b9dd5d 100644 --- a/src/extern/cef/cef_linux.pxd +++ b/src/extern/cef/cef_linux.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "compile_time_constants.pxi" diff --git a/src/extern/cef/cef_mac.pxd b/src/extern/cef/cef_mac.pxd index 2639eb39c..ec6a0898c 100644 --- a/src/extern/cef/cef_mac.pxd +++ b/src/extern/cef/cef_mac.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2015 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "compile_time_constants.pxi" diff --git a/src/extern/cef/cef_path_util.pxd b/src/extern/cef/cef_path_util.pxd index 4a75f16b6..d90c08496 100644 --- a/src/extern/cef/cef_path_util.pxd +++ b/src/extern/cef/cef_path_util.pxd @@ -1,4 +1,6 @@ -# Copyright (c) 2016 The CEF Python Authors. All rights reserved. +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from cef_types cimport PathKey from cef_string cimport CefString diff --git a/src/extern/cef/cef_platform.pxd b/src/extern/cef/cef_platform.pxd index 3ee19a1e1..bf428e5f5 100644 --- a/src/extern/cef/cef_platform.pxd +++ b/src/extern/cef/cef_platform.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "compile_time_constants.pxi" diff --git a/src/extern/cef/cef_process_message.pxd b/src/extern/cef/cef_process_message.pxd index 14807ed9b..bb3584038 100644 --- a/src/extern/cef/cef_process_message.pxd +++ b/src/extern/cef/cef_process_message.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython # noinspection PyUnresolvedReferences from cef_types cimport cef_process_id_t diff --git a/src/extern/cef/cef_ptr.pxd b/src/extern/cef/cef_ptr.pxd index dae079b87..ed4cdcae9 100644 --- a/src/extern/cef/cef_ptr.pxd +++ b/src/extern/cef/cef_ptr.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 cdef extern from "include/internal/cef_ptr.h": cdef cppclass CefRefPtr[T]: diff --git a/src/extern/cef/cef_request.pxd b/src/extern/cef/cef_request.pxd index 1e73fb897..e7bd336d0 100644 --- a/src/extern/cef/cef_request.pxd +++ b/src/extern/cef/cef_request.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from cef_ptr cimport CefRefPtr from cef_string cimport CefString diff --git a/src/extern/cef/cef_request_context.pxd b/src/extern/cef/cef_request_context.pxd index 08a796124..811cf72f5 100644 --- a/src/extern/cef/cef_request_context.pxd +++ b/src/extern/cef/cef_request_context.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from cef_ptr cimport CefRefPtr # noinspection PyUnresolvedReferences diff --git a/src/extern/cef/cef_request_context_handler.pxd b/src/extern/cef/cef_request_context_handler.pxd index b48437268..e11a88e92 100644 --- a/src/extern/cef/cef_request_context_handler.pxd +++ b/src/extern/cef/cef_request_context_handler.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython cdef extern from "include/cef_request_context_handler.h": cdef cppclass CefRequestContextHandler: diff --git a/src/extern/cef/cef_request_handler.pxd b/src/extern/cef/cef_request_handler.pxd index 17d1496c9..96a7d88c6 100644 --- a/src/extern/cef/cef_request_handler.pxd +++ b/src/extern/cef/cef_request_handler.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2012 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from cef_string cimport CefString from libcpp cimport bool as cpp_bool diff --git a/src/extern/cef/cef_resource_handler.pxd b/src/extern/cef/cef_resource_handler.pxd index 42be21819..3e34e85b7 100644 --- a/src/extern/cef/cef_resource_handler.pxd +++ b/src/extern/cef/cef_resource_handler.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython cdef extern from "include/cef_resource_handler.h": cdef cppclass CefResourceHandler: diff --git a/src/extern/cef/cef_response.pxd b/src/extern/cef/cef_response.pxd index 041aa5941..ef6729f12 100644 --- a/src/extern/cef/cef_response.pxd +++ b/src/extern/cef/cef_response.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from cef_string cimport CefString # noinspection PyUnresolvedReferences diff --git a/src/extern/cef/cef_scoped_ptr.pxd b/src/extern/cef/cef_scoped_ptr.pxd index 92c0e9854..f23cd156b 100644 --- a/src/extern/cef/cef_scoped_ptr.pxd +++ b/src/extern/cef/cef_scoped_ptr.pxd @@ -1,4 +1,6 @@ -# Copyright (c) 2016 CEF Python. See the Authors and License files. +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython cdef extern from "include/base/cef_scoped_ptr.h": cdef cppclass scoped_ptr[T]: diff --git a/src/extern/cef/cef_string.pxd b/src/extern/cef/cef_string.pxd index 07970b24a..74f2e342b 100644 --- a/src/extern/cef/cef_string.pxd +++ b/src/extern/cef/cef_string.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2012 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from libcpp cimport bool as cpp_bool from libc.stddef cimport wchar_t diff --git a/src/extern/cef/cef_string_visitor.pxd b/src/extern/cef/cef_string_visitor.pxd index 653c43c7f..bb253b7d7 100644 --- a/src/extern/cef/cef_string_visitor.pxd +++ b/src/extern/cef/cef_string_visitor.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython cdef extern from "include/cef_string_visitor.h": cdef cppclass CefStringVisitor: diff --git a/src/extern/cef/cef_task.pxd b/src/extern/cef/cef_task.pxd index d40be65fb..9ca2aaece 100644 --- a/src/extern/cef/cef_task.pxd +++ b/src/extern/cef/cef_task.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2014 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from libcpp cimport bool as cpp_bool # noinspection PyUnresolvedReferences diff --git a/src/extern/cef/cef_time.pxd b/src/extern/cef/cef_time.pxd index 87a7901c2..cdbdc639f 100644 --- a/src/extern/cef/cef_time.pxd +++ b/src/extern/cef/cef_time.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from ctime cimport time_t diff --git a/src/extern/cef/cef_types.pxd b/src/extern/cef/cef_types.pxd index a15e26f21..78484f6e0 100644 --- a/src/extern/cef/cef_types.pxd +++ b/src/extern/cef/cef_types.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "compile_time_constants.pxi" diff --git a/src/extern/cef/cef_urlrequest.pxd b/src/extern/cef/cef_urlrequest.pxd index c65efd285..a0f5b1b7b 100644 --- a/src/extern/cef/cef_urlrequest.pxd +++ b/src/extern/cef/cef_urlrequest.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from cef_ptr cimport CefRefPtr cimport cef_types diff --git a/src/extern/cef/cef_values.pxd b/src/extern/cef/cef_values.pxd index a9da24216..201bb82be 100644 --- a/src/extern/cef/cef_values.pxd +++ b/src/extern/cef/cef_values.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from cef_ptr cimport CefRefPtr from libcpp cimport bool as cpp_bool diff --git a/src/extern/cef/cef_web_plugin.pxd b/src/extern/cef/cef_web_plugin.pxd index 99e31d060..25d33fa9d 100644 --- a/src/extern/cef/cef_web_plugin.pxd +++ b/src/extern/cef/cef_web_plugin.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from cef_string cimport CefString diff --git a/src/extern/cef/cef_win.pxd b/src/extern/cef/cef_win.pxd index ed5243d20..ce742d79a 100644 --- a/src/extern/cef/cef_win.pxd +++ b/src/extern/cef/cef_win.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "compile_time_constants.pxi" diff --git a/src/extern/cefpython_app.pxd b/src/extern/cefpython_app.pxd index ad854ce3e..c6175d8c7 100644 --- a/src/extern/cefpython_app.pxd +++ b/src/extern/cefpython_app.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 cdef extern from "subprocess/cefpython_app.h": cdef cppclass CefPythonApp: diff --git a/src/extern/client_handler.pxd b/src/extern/client_handler.pxd index 5de3ff9d2..2150bc939 100644 --- a/src/extern/client_handler.pxd +++ b/src/extern/client_handler.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 cdef extern from "client_handler/client_handler.h": diff --git a/src/extern/cookie_visitor.pxd b/src/extern/cookie_visitor.pxd index 1e034fa95..e5ce8be4e 100644 --- a/src/extern/cookie_visitor.pxd +++ b/src/extern/cookie_visitor.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2014 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/cookie_visitor.h": diff --git a/src/extern/cpp_utils.pxd b/src/extern/cpp_utils.pxd index 40cb802d3..212ba22fb 100644 --- a/src/extern/cpp_utils.pxd +++ b/src/extern/cpp_utils.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython cdef extern from "cpp_utils/PaintBuffer.h": diff --git a/src/extern/ctime.pxd b/src/extern/ctime.pxd index 64fc9ed85..2e5d1f3dd 100644 --- a/src/extern/ctime.pxd +++ b/src/extern/ctime.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython cdef extern from "time.h": ctypedef struct time_t: diff --git a/src/extern/dpi_aware_win.pxd b/src/extern/dpi_aware_win.pxd index 390bbf659..3842062a2 100644 --- a/src/extern/dpi_aware_win.pxd +++ b/src/extern/dpi_aware_win.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2014 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from libcpp cimport bool as cpp_bool diff --git a/src/extern/linux.pxd b/src/extern/linux.pxd index 4292c8d0b..fb565243b 100644 --- a/src/extern/linux.pxd +++ b/src/extern/linux.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython cdef extern from "gtk/gtk.h" nogil: ctypedef void* GdkNativeWindow diff --git a/src/extern/mac.pxd b/src/extern/mac.pxd index b9ad4cc26..6d6b73a85 100644 --- a/src/extern/mac.pxd +++ b/src/extern/mac.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2015 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2015 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/util_mac.h": cdef void MacInitialize() diff --git a/src/extern/main_message_loop.pxd b/src/extern/main_message_loop.pxd index c5c48ab2b..486f309af 100644 --- a/src/extern/main_message_loop.pxd +++ b/src/extern/main_message_loop.pxd @@ -1,4 +1,6 @@ -# Copyright (c) 2016 CEF Python. See the Authors and License files. +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from cef_scoped_ptr cimport scoped_ptr diff --git a/src/extern/multimap.pxd b/src/extern/multimap.pxd index ee68b7952..a059744a5 100644 --- a/src/extern/multimap.pxd +++ b/src/extern/multimap.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2012 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from libcpp.utility cimport pair diff --git a/src/extern/request_context_handler.pxd b/src/extern/request_context_handler.pxd index 16c6ee649..b57739c30 100644 --- a/src/extern/request_context_handler.pxd +++ b/src/extern/request_context_handler.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from cef_ptr cimport CefRefPtr from cef_browser cimport CefBrowser diff --git a/src/extern/resource_handler.pxd b/src/extern/resource_handler.pxd index 8f8f7865d..3467157aa 100644 --- a/src/extern/resource_handler.pxd +++ b/src/extern/resource_handler.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython cdef extern from "client_handler/resource_handler.h": diff --git a/src/extern/string_visitor.pxd b/src/extern/string_visitor.pxd index e648f6067..ec9e83de2 100644 --- a/src/extern/string_visitor.pxd +++ b/src/extern/string_visitor.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython cdef extern from "client_handler/string_visitor.h": diff --git a/src/extern/task.pxd b/src/extern/task.pxd index 2cb8c9d12..b4e75e146 100644 --- a/src/extern/task.pxd +++ b/src/extern/task.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2014 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from cef_ptr cimport CefRefPtr # noinspection PyUnresolvedReferences diff --git a/src/extern/web_request_client.pxd b/src/extern/web_request_client.pxd index 688afbd3e..0aaa124c4 100644 --- a/src/extern/web_request_client.pxd +++ b/src/extern/web_request_client.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython cdef extern from "client_handler/web_request_client.h": diff --git a/src/extern/windows.pxd b/src/extern/windows.pxd index 4de753191..82355a60e 100644 --- a/src/extern/windows.pxd +++ b/src/extern/windows.pxd @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2012 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from libc.stddef cimport wchar_t diff --git a/src/extern/wstring.pxd b/src/extern/wstring.pxd index 58c24b910..fdfbe9b9e 100644 --- a/src/extern/wstring.pxd +++ b/src/extern/wstring.pxd @@ -1,3 +1,5 @@ +# Copyright (c) Cython + from libc.stddef cimport wchar_t from libcpp.string cimport string diff --git a/src/extern/x11.pxd b/src/extern/x11.pxd index 3d9003010..5963a1317 100644 --- a/src/extern/x11.pxd +++ b/src/extern/x11.pxd @@ -1,4 +1,6 @@ -# Copyright (c) 2016 The CEF Python authors. All rights reserved. +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython from cef_ptr cimport CefRefPtr # noinspection PyUnresolvedReferences diff --git a/src/frame.pyx b/src/frame.pyx index ab22ba4fb..9a3faca94 100644 --- a/src/frame.pyx +++ b/src/frame.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "cefpython.pyx" diff --git a/src/handlers/browser_process_handler.pyx b/src/handlers/browser_process_handler.pyx index f5800d44b..5847d6700 100644 --- a/src/handlers/browser_process_handler.pyx +++ b/src/handlers/browser_process_handler.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "../cefpython.pyx" diff --git a/src/handlers/display_handler.pyx b/src/handlers/display_handler.pyx index 3d6f7bf4b..3db61a7c6 100644 --- a/src/handlers/display_handler.pyx +++ b/src/handlers/display_handler.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "../cefpython.pyx" diff --git a/src/handlers/focus_handler.pyx b/src/handlers/focus_handler.pyx index e9598f4fc..f966c6132 100644 --- a/src/handlers/focus_handler.pyx +++ b/src/handlers/focus_handler.pyx @@ -1,4 +1,6 @@ -# Copyright (c) 2016 CEF Python. See the Authors and License files. +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "../cefpython.pyx" cimport cef_types diff --git a/src/handlers/javascript_dialog_handler.pyx b/src/handlers/javascript_dialog_handler.pyx index d6b16325e..0c7fa071b 100644 --- a/src/handlers/javascript_dialog_handler.pyx +++ b/src/handlers/javascript_dialog_handler.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "../cefpython.pyx" diff --git a/src/handlers/keyboard_handler.pyx b/src/handlers/keyboard_handler.pyx index b0b03f536..408487c5f 100644 --- a/src/handlers/keyboard_handler.pyx +++ b/src/handlers/keyboard_handler.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "../cefpython.pyx" diff --git a/src/handlers/lifespan_handler.pyx b/src/handlers/lifespan_handler.pyx index c682ba3c7..dbc379434 100644 --- a/src/handlers/lifespan_handler.pyx +++ b/src/handlers/lifespan_handler.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "../cefpython.pyx" include "../browser.pyx" diff --git a/src/handlers/load_handler.pyx b/src/handlers/load_handler.pyx index caeefae15..47e1d28df 100644 --- a/src/handlers/load_handler.pyx +++ b/src/handlers/load_handler.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "../cefpython.pyx" diff --git a/src/handlers/render_handler.pyx b/src/handlers/render_handler.pyx index 3204ca3b7..acbb5c285 100644 --- a/src/handlers/render_handler.pyx +++ b/src/handlers/render_handler.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "../cefpython.pyx" diff --git a/src/handlers/request_handler.pyx b/src/handlers/request_handler.pyx index a4709d98c..259e23a1c 100644 --- a/src/handlers/request_handler.pyx +++ b/src/handlers/request_handler.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "../cefpython.pyx" diff --git a/src/handlers/resource_handler.pyx b/src/handlers/resource_handler.pyx index c4f1d6cd4..1c379f192 100644 --- a/src/handlers/resource_handler.pyx +++ b/src/handlers/resource_handler.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "../cefpython.pyx" diff --git a/src/handlers/v8context_handler.pyx b/src/handlers/v8context_handler.pyx index 8f8f9de37..741daab8c 100644 --- a/src/handlers/v8context_handler.pyx +++ b/src/handlers/v8context_handler.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 # In CEF 3 there is no V8ContextHandler, the methods OnContextCreated(), # OnContextReleased(), OnUncaughtException() are in CefRenderProcessHandler diff --git a/src/handlers/v8function_handler.pyx b/src/handlers/v8function_handler.pyx index 64df44ca4..c4cfd89d9 100644 --- a/src/handlers/v8function_handler.pyx +++ b/src/handlers/v8function_handler.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "../cefpython.pyx" diff --git a/src/helpers.pyx b/src/helpers.pyx index b3508ee8e..595d2cd09 100644 --- a/src/helpers.pyx +++ b/src/helpers.pyx @@ -1,4 +1,6 @@ -# Copyright (c) 2016 The CEF Python authors. All rights reserved. +# 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 include "cefpython.pyx" diff --git a/src/image.pyx b/src/image.pyx index 7164bbd69..14b29e748 100644 --- a/src/image.pyx +++ b/src/image.pyx @@ -1,4 +1,6 @@ -# Copyright (c) 2016 The CEF Python authors. All rights reserved. +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/javascript_bindings.pyx b/src/javascript_bindings.pyx index d81609d30..9043639e3 100644 --- a/src/javascript_bindings.pyx +++ b/src/javascript_bindings.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "cefpython.pyx" diff --git a/src/javascript_callback.pyx b/src/javascript_callback.pyx index eccab67ec..81a06eb86 100644 --- a/src/javascript_callback.pyx +++ b/src/javascript_callback.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/network_error.pyx b/src/network_error.pyx index 77ebdef4e..58fdcd450 100644 --- a/src/network_error.pyx +++ b/src/network_error.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython # noinspection PyUnresolvedReferences cimport cef_types diff --git a/src/paint_buffer.pyx b/src/paint_buffer.pyx index 0ea480d15..4d1d23984 100644 --- a/src/paint_buffer.pyx +++ b/src/paint_buffer.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/process_message_utils.pyx b/src/process_message_utils.pyx index 314871d56..a9c10f225 100644 --- a/src/process_message_utils.pyx +++ b/src/process_message_utils.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython # CefListValue->SetXxxx() functions need first param to be be cast # to (int) because GetSize() returns size_t and generates a warning diff --git a/src/python_callback.pyx b/src/python_callback.pyx index c604a6df0..705e0f54c 100644 --- a/src/python_callback.pyx +++ b/src/python_callback.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/request.pyx b/src/request.pyx index 3ae0e6670..3e0e66d86 100644 --- a/src/request.pyx +++ b/src/request.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/response.pyx b/src/response.pyx index 31e4076d5..88e35c8a9 100644 --- a/src/response.pyx +++ b/src/response.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/settings.pyx b/src/settings.pyx index aefcc9727..79efe6799 100644 --- a/src/settings.pyx +++ b/src/settings.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 # More options/flags can be specified for Chromium through # CefApp::OnBeforeCommandLineProcessing(), see comment 10 by Marshall: diff --git a/src/string_utils.pyx b/src/string_utils.pyx index 9ec6364b7..3129b1a38 100644 --- a/src/string_utils.pyx +++ b/src/string_utils.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 # In Python 2 all cefpython strings are byte strings, but in Python 3 # all cefpython strings are unicode. Unicode issues were discussed diff --git a/src/string_utils_win.pyx b/src/string_utils_win.pyx index e6f7ca841..cb4b75ca7 100644 --- a/src/string_utils_win.pyx +++ b/src/string_utils_win.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "cefpython.pyx" diff --git a/src/string_visitor.pyx b/src/string_visitor.pyx index ae952b306..13f7a10bd 100644 --- a/src/string_visitor.pyx +++ b/src/string_visitor.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/subprocess/cefpython_app.cpp b/src/subprocess/cefpython_app.cpp index 936d2fb3d..9dd456a0d 100644 --- a/src/subprocess/cefpython_app.cpp +++ b/src/subprocess/cefpython_app.cpp @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// 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 // BROWSER_PROCESS macro is defined when compiling the libcefpythonapp library. // RENDERER_PROCESS macro is define when compiling the subprocess executable. diff --git a/src/subprocess/cefpython_app.h b/src/subprocess/cefpython_app.h index 57f18f905..63e30225c 100644 --- a/src/subprocess/cefpython_app.h +++ b/src/subprocess/cefpython_app.h @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// 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 "include/cef_app.h" diff --git a/src/subprocess/javascript_callback.cpp b/src/subprocess/javascript_callback.cpp index ac673c0e3..fd9f55e5d 100644 --- a/src/subprocess/javascript_callback.cpp +++ b/src/subprocess/javascript_callback.cpp @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "javascript_callback.h" #include diff --git a/src/subprocess/javascript_callback.h b/src/subprocess/javascript_callback.h index 6cc0b63fb..2e91e79ad 100644 --- a/src/subprocess/javascript_callback.h +++ b/src/subprocess/javascript_callback.h @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #pragma once #include "include/cef_v8.h" diff --git a/src/subprocess/main.cpp b/src/subprocess/main.cpp index 1192f4a84..1000dc0a6 100644 --- a/src/subprocess/main.cpp +++ b/src/subprocess/main.cpp @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #include "cefpython_app.h" diff --git a/src/subprocess/v8function_handler.cpp b/src/subprocess/v8function_handler.cpp index ce49752aa..508a78bbf 100644 --- a/src/subprocess/v8function_handler.cpp +++ b/src/subprocess/v8function_handler.cpp @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// 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 #include "cefpython_app.h" #include "v8utils.h" diff --git a/src/subprocess/v8function_handler.h b/src/subprocess/v8function_handler.h index d268a9672..71a04b60b 100644 --- a/src/subprocess/v8function_handler.h +++ b/src/subprocess/v8function_handler.h @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// 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 "include/cef_v8.h" diff --git a/src/subprocess/v8utils.cpp b/src/subprocess/v8utils.cpp index 126657e64..e53d46a41 100644 --- a/src/subprocess/v8utils.cpp +++ b/src/subprocess/v8utils.cpp @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython // CefListValue->SetXxxx() functions need first param to be be cast // to (int) because GetSize() returns size_t and generates a warning diff --git a/src/subprocess/v8utils.h b/src/subprocess/v8utils.h index a6d0ed03f..289dddf4f 100644 --- a/src/subprocess/v8utils.h +++ b/src/subprocess/v8utils.h @@ -1,6 +1,6 @@ -// Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -// License: New BSD License. -// Website: http://code.google.com/p/cefpython/ +// Copyright (c) 2013 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython #pragma once #include "include/cef_v8.h" diff --git a/src/task.pyx b/src/task.pyx index 5737541ba..43f994253 100644 --- a/src/task.pyx +++ b/src/task.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2014 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/time_utils.pyx b/src/time_utils.pyx index efdeee845..9070ae5e3 100644 --- a/src/time_utils.pyx +++ b/src/time_utils.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/utils.pyx b/src/utils.pyx index a3ef03aac..3f51b25ae 100644 --- a/src/utils.pyx +++ b/src/utils.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "cefpython.pyx" diff --git a/src/virtual_keys.pyx b/src/virtual_keys.pyx index 99a6d4b0a..685aa1571 100644 --- a/src/virtual_keys.pyx +++ b/src/virtual_keys.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 # Regular expression to transform these constants to a form # that can be later pasted to wiki page: diff --git a/src/web_plugin_info.pyx b/src/web_plugin_info.pyx index 4245b14ea..79e5a77aa 100644 --- a/src/web_plugin_info.pyx +++ b/src/web_plugin_info.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/web_request.pyx b/src/web_request.pyx index cd591ebc7..9891dade8 100644 --- a/src/web_request.pyx +++ b/src/web_request.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" import weakref diff --git a/src/window_info.pyx b/src/window_info.pyx index 27c6cf165..9cfe17fbd 100644 --- a/src/window_info.pyx +++ b/src/window_info.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/window_utils_linux.pyx b/src/window_utils_linux.pyx index 9427ebb0d..ccd628e1c 100644 --- a/src/window_utils_linux.pyx +++ b/src/window_utils_linux.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/window_utils_mac.pyx b/src/window_utils_mac.pyx index 7b8e8569f..07c70b64d 100644 --- a/src/window_utils_mac.pyx +++ b/src/window_utils_mac.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# Copyright (c) 2015 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" diff --git a/src/window_utils_win.pyx b/src/window_utils_win.pyx index 5f8e80198..6a7862cdf 100644 --- a/src/window_utils_win.pyx +++ b/src/window_utils_win.pyx @@ -1,6 +1,6 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ +# 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 include "cefpython.pyx" diff --git a/tools/apidocs.py b/tools/apidocs.py index 75e97cc6a..c7bde27c9 100644 --- a/tools/apidocs.py +++ b/tools/apidocs.py @@ -1,4 +1,6 @@ -# Copyright (c) 2016 CEF Python, see the Authors file. All rights reserved. +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython """Generate API docs from sources. diff --git a/tools/automate.py b/tools/automate.py index c89b419e1..6ac65f7a2 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -1,4 +1,6 @@ -# Copyright (c) 2016 CEF Python, see the Authors file. All rights reserved. +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython """ Prepares CEF binaries and libraries for work with the build.py tool. diff --git a/tools/build.py b/tools/build.py index d791b8849..5b9c59f2b 100644 --- a/tools/build.py +++ b/tools/build.py @@ -1,5 +1,6 @@ -# Copyright (c) 2017 The CEF Python authors. All rights reserved. -# Licensed under the BSD 3-clause license. +# 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 """ Build the cefpython module, install package and run example. diff --git a/tools/build_cpp_projects.py b/tools/build_cpp_projects.py index 4e4881c62..cc8c571ec 100644 --- a/tools/build_cpp_projects.py +++ b/tools/build_cpp_projects.py @@ -1,3 +1,7 @@ +# 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 + """Build C++ projects. This tool is executed by build.py on Windows only currently. Output directories are in build/build_cefpython/. diff --git a/tools/common.py b/tools/common.py index 779a76e10..801e64fd9 100644 --- a/tools/common.py +++ b/tools/common.py @@ -1,3 +1,7 @@ +# 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 + # Common stuff for tools such as automate.py, build.py, etc. import struct diff --git a/tools/cython_setup.py b/tools/cython_setup.py index f96c3b8d7..efab8e993 100644 --- a/tools/cython_setup.py +++ b/tools/cython_setup.py @@ -1,5 +1,6 @@ -# Copyright (c) 2017 The CEF Python authors. All rights reserved. -# Licensed under the BSD 3-clause license. +# 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 """ cython_setup.py is for internal use only - called by build.py. diff --git a/tools/installer/cefpython3.__init__.py b/tools/installer/cefpython3.__init__.py index 3d821b894..d7463248a 100644 --- a/tools/installer/cefpython3.__init__.py +++ b/tools/installer/cefpython3.__init__.py @@ -1,5 +1,6 @@ -# Copyright (c) 2017 The CEF Python authors. All rights reserved. -# Licensed under BSD 3-clause license. +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython # NOTE: Template variables like {{VERSION}} are replaced with actual # values when make_installer.py tool generates this package diff --git a/tools/installer/cefpython3.setup.py b/tools/installer/cefpython3.setup.py index 7ab1ba179..7cc55356e 100644 --- a/tools/installer/cefpython3.setup.py +++ b/tools/installer/cefpython3.setup.py @@ -1,5 +1,6 @@ -# Copyright (c) 2017 The CEF Python authors. All rights reserved. -# Licensed under BSD 3-clause license. +# 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 """ cefpython3 package setup.py file. diff --git a/tools/make_installer.py b/tools/make_installer.py index f2858be6e..84f3aba2b 100644 --- a/tools/make_installer.py +++ b/tools/make_installer.py @@ -1,5 +1,6 @@ -# Copyright (c) 2017 The CEF Python authors. All rights reserved. -# Licensed under BSD 3-clause license. +# 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 """ Create setup.py package installer. diff --git a/tools/run_examples.py b/tools/run_examples.py index db77572d8..b2ae112d8 100644 --- a/tools/run_examples.py +++ b/tools/run_examples.py @@ -1,3 +1,7 @@ +# 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 + """ Run all examples that can be run on current configuration. diff --git a/tools/toc.py b/tools/toc.py index 21967e120..b7f64c1be 100644 --- a/tools/toc.py +++ b/tools/toc.py @@ -1,4 +1,6 @@ -# Copyright (c) 2016 CEF Python, see the Authors file. All rights reserved. +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython """Create Table of contents (TOC) for a single .md file or for a directory. diff --git a/unittests/_test_runner.py b/unittests/_test_runner.py index 3968a52ca..3b2147bd3 100644 --- a/unittests/_test_runner.py +++ b/unittests/_test_runner.py @@ -1,4 +1,6 @@ -# Copyright (c) 2016 The CEF Python authors. All rights reserved. +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython """Run unit tests. With no arguments all tests are run. Read notes below. diff --git a/unittests/isolated_test.py b/unittests/isolated_test.py index 1700145bb..e4264c708 100644 --- a/unittests/isolated_test.py +++ b/unittests/isolated_test.py @@ -1,3 +1,7 @@ +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython + """ Test isolated test. Isolated tests are run each using a new instance of Python interpreter. They also implement some unique features for diff --git a/unittests/main_test.py b/unittests/main_test.py index 5ace78c64..a75b4a9e6 100644 --- a/unittests/main_test.py +++ b/unittests/main_test.py @@ -1,3 +1,7 @@ +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython + """General testing of CEF Python.""" import unittest diff --git a/unittests/unittest_test.py b/unittests/unittest_test.py index f504c1dcc..f659350dc 100644 --- a/unittests/unittest_test.py +++ b/unittests/unittest_test.py @@ -1,3 +1,7 @@ +# Copyright (c) 2016 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython + """Test the unittest itself.""" import unittest From 7e4d587f7268fd7372aa44bb5d602281a1eaf0dd Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 8 Mar 2017 22:25:06 +0100 Subject: [PATCH 157/557] Add Python 3 support on Windows (#121)... Tested using Python 3.4 / 3.5 / 3.6. Only 32-bit. Everything works good. Update tools for Python 3. On Windows build.py tool will call build_cpp_projects.py to build C++ projects. On Linux and Mac C++ projects are built using Makefiles. There are still deprecated .vcproj files across directories, however they are all deprecated and not used anymore. automate.py --prebuilt-cef works on Python 3. However --build-cef depends on upstream automate-git.py which supports only Python 2. Minor fixes to build instructions. --- docs/Build-instructions.md | 9 +- src/compile_time_constants.pxi | 2 +- tools/apidocs.py | 4 +- tools/automate.py | 407 ++++++++++++++++++--------------- tools/build.py | 59 ++--- tools/build_cpp_projects.py | 6 +- tools/common.py | 37 ++- tools/cython_setup.py | 37 ++- 8 files changed, 312 insertions(+), 249 deletions(-) diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index e185c6798..db67f0908 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -55,7 +55,7 @@ and libraries from GitHub Releases: 2) Download [ninja](https://github.com/ninja-build/ninja) 1.7.2 or later and add it to PATH. -3) Download [cmake](https://cmake.org/download/) 3.7.2 or later and add +3) Download [cmake](https://cmake.org/download/) and add it to PATH. 4) For Python 2.7 Install "Visual C++ Compiler for Python 2.7" @@ -147,6 +147,9 @@ requirements common for all platforms. ### Windows +* Download [ninja](https://github.com/ninja-build/ninja) 1.7.2 or later + and add it to PATH. +* Download [cmake](https://cmake.org/download/) and add it to PATH. * Install an appropriate MS compiler for a specific Python version: https://wiki.python.org/moin/WindowsCompilers * For Python 2.7 install "Microsoft Visual C++ Compiler for Python 2.7" @@ -208,6 +211,10 @@ requirements common for all platforms. * MacOS 10.9+, Xcode5+ and Xcode command line tools. Only 64-bit builds are supported. +* Download [ninja](https://github.com/ninja-build/ninja) 1.7.2 or later + and add it to PATH. +* Download [cmake](https://cmake.org/download/) and add it to PATH. + ### All platforms diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 632aab59c..10ec798af 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 PY_MAJOR_VERSION = 2 diff --git a/tools/apidocs.py b/tools/apidocs.py index c7bde27c9..69e6ed9dd 100644 --- a/tools/apidocs.py +++ b/tools/apidocs.py @@ -36,7 +36,7 @@ def api_index(): if "API-" in file_: continue with open(file_, "rb") as fo: - raw_mdcontents = fo.read() + raw_mdcontents = fo.read().decode("utf-8") parsable_mdcontents = re.sub(r"```[\s\S]+?```", "", raw_mdcontents) allmatches = re.findall(r"^(#|###)\s+(.*)", parsable_mdcontents, @@ -58,7 +58,7 @@ def api_index(): contents += (indent + "* " + "[%s](%s)\n" % (title, link)) indexfile = os.path.join(API_DIR, "API-index.md") with open(indexfile, "wb") as fo: - fo.write(contents) + fo.write(contents.encode("utf-8")) print("Created %s in %s" % (os.path.basename(indexfile), API_DIR)) print("Done") diff --git a/tools/automate.py b/tools/automate.py index 6ac65f7a2..9c6295560 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -67,8 +67,13 @@ import glob import shutil import multiprocessing +from collections import OrderedDict +from setuptools.msvc import msvc9_query_vcvarsall +# Constants CEF_GIT_URL = "https://bitbucket.org/chromiumembedded/cef.git" +RUNTIME_MT = "MT" +RUNTIME_MD = "MD" class Options(object): @@ -97,20 +102,11 @@ class Options(object): release_build = True build_type = "" # Will be set according to "release_build" value cef_binary = "" - build_cefclient_dir = "" - build_wrapper_dir = "" - build_wrapper_mt_dir = "" - build_wrapper_md_dir = "" def main(): """Main entry point.""" - if not ((2, 7) <= sys.version_info < (2, 8)): - print("ERROR: to run this tool you need Python 2.7, as upstream") - print(" automate-git.py works only with that version.") - sys.exit(1) - if len(sys.argv) <= 1: print(__doc__) sys.exit(1) @@ -118,6 +114,11 @@ def main(): setup_options(docopt.docopt(__doc__)) if Options.build_cef: + if not sys.version_info[:2] == (2, 7): + print("ERROR: To build CEF from sources you need Python 2.7," + " as upstream automate-git.py only works with that" + " version of python.") + sys.exit(1) build_cef() # Build cefclient, cefsimple, ceftests, libcef_dll_wrapper build_cef_projects() @@ -181,6 +182,7 @@ def setup_options(docopt_args): # --depot-tools-dir Options.depot_tools_dir = os.path.join(Options.cef_build_dir, "depot_tools") + # binary_distrib Options.binary_distrib = os.path.join(Options.cef_build_dir, "chromium", "src", "cef", "binary_distrib") @@ -297,22 +299,25 @@ def update_cef_patches(): cef_patch_cfg = os.path.join(cef_patch_dir, "patch.cfg") print("[automate.py] Overwriting %s" % cef_patch_cfg) with open(cef_patch_cfg, "rb") as fp: - cef_patch_cfg_contents = fp.read() + cef_patch_cfg_contents = fp.read().decode("utf-8") cef_patch_cfg_contents += "\n" cefpython_patch_cfg = os.path.join(cefpython_patches_dir, "patch.py") with open(cefpython_patch_cfg, "rb") as fp: - cefpython_patch_cfg_contents = fp.read() + cefpython_patch_cfg_contents = fp.read().decode("utf-8") with open(cef_patch_cfg, "wb") as fp: cef_patch_cfg_contents = cef_patch_cfg_contents.replace("\r\n", "\n") cefpython_patch_cfg_contents = cefpython_patch_cfg_contents.replace( "\r\n", "\n") new_contents = cef_patch_cfg_contents + cefpython_patch_cfg_contents - fp.write(new_contents) + fp.write(new_contents.encode("utf-8")) def build_cef_projects(): """Build cefclient, cefsimple, ceftests, libcef_dll_wrapper.""" - print("[automate.py] Building cef projects...") + print("[automate.py] Build cef projects...") + + if WINDOWS: + fix_cmake_variables_permanently_windows() fix_cef_include_files() @@ -339,22 +344,25 @@ def build_cef_projects(): Options.cef_binary = cef_binary # Set build directory - Options.build_cefclient_dir = os.path.join(Options.cef_binary, - "build_cefclient") - - print("[automate.py] Creating build_cefclient dir in cef_binary dir") + build_cefclient_dir = os.path.join(Options.cef_binary, + "build_cefclient") + cefclient_exe = os.path.join(build_cefclient_dir, "tests", "cefclient", + Options.build_type, + "cefclient" + EXECUTABLE_EXT) # Check whether already built already_built = False - if build_cefclient_succeeded(): + if os.path.exists(cefclient_exe): already_built = True - elif os.path.exists(Options.build_cefclient_dir): + elif os.path.exists(build_cefclient_dir): # Last build failed, clean directory - assert Options.build_cefclient_dir - shutil.rmtree(Options.build_cefclient_dir) - os.makedirs(Options.build_cefclient_dir) + assert build_cefclient_dir + shutil.rmtree(build_cefclient_dir) + print("[automate.py] Create build_cefclient/ dir in cef_binary*/ dir") + os.makedirs(build_cefclient_dir) else: - os.makedirs(Options.build_cefclient_dir) + print("[automate.py] Create build_cefclient/ dir in cef_binary*/ dir") + os.makedirs(build_cefclient_dir) # Build cefclient, cefsimple, ceftests if already_built: @@ -368,7 +376,7 @@ def build_cef_projects(): if MAC: command.append("-DPROJECT_ARCH=x86_64") command.append("..") - run_command(command, Options.build_cefclient_dir) + run_command(command, build_cefclient_dir) print("[automate.py] OK") # Ninja command = prepare_build_command() @@ -379,143 +387,129 @@ def build_cef_projects(): command.extend(["ninja", "cefsimple"]) else: command.extend(["ninja", "cefclient", "cefsimple", "ceftests"]) - run_command(command, Options.build_cefclient_dir) + run_command(command, build_cefclient_dir) print("[automate.py] OK") - assert build_cefclient_succeeded() + assert os.path.exists(cefclient_exe) # Build libcef_dll_wrapper libs if WINDOWS: - build_wrapper_windows() + build_all_wrapper_libraries_windows() elif MAC: - build_wrapper_mac() + build_wrapper_library_mac() -def build_wrapper_mac(): - # On Mac it is required to link libcef_dll_wrapper against - # libc++ library, so must build this library separately - # from cefclient. - cmake_wrapper = prepare_build_command(build_lib=True) - cmake_wrapper.extend(["cmake", "-G", "Ninja", - "-DPROJECT_ARCH=x86_64" - "-DCMAKE_CXX_FLAGS=-stdlib=libc++", - "-DCMAKE_BUILD_TYPE=" + Options.build_type, - ".."]) - Options.build_wrapper_dir = os.path.join(Options.cef_binary, - "build_wrapper") - # Check whether already built - already_built = False - if build_wrapper_mac_succeeded(): - already_built = True - elif os.path.exists(Options.build_wrapper_dir): - # Last build failed, clean directory - assert Options.build_wrapper_dir - shutil.rmtree(Options.build_wrapper_dir) - os.makedirs(Options.build_wrapper_dir) - else: - os.makedirs(Options.build_wrapper_dir) - - # Build libcef_dll_wrapper library - if already_built: - print("[automate.py] Already built: libcef_dll_wrapper") - else: - print("[automate.py] Build libcef_dll_wrapper") - # Cmake - run_command(cmake_wrapper, Options.build_wrapper_dir) - print("[automate.py] cmake OK") - # Ninja - ninja_wrapper = prepare_build_command(build_lib=True) - ninja_wrapper.extend(["ninja", "libcef_dll_wrapper"]) - run_command(ninja_wrapper, Options.build_wrapper_dir) - print("[automate.py] ninja OK") - assert build_wrapper_mac_succeeded() +def build_all_wrapper_libraries_windows(): + python_compilers = get_available_python_compilers() + if not len(python_compilers): + print("[automate.py] ERROR: Visual Studio compiler not found") + sys.exit(1) + for msvs in python_compilers: + vcvars = python_compilers[msvs] + print("[automate.py] Build libcef_dll_wrapper libraries for" + " VS{msvs}".format(msvs=msvs)) + build_wrapper_library_windows(runtime_library=RUNTIME_MT, + msvs=msvs, vcvars=vcvars) + build_wrapper_library_windows(runtime_library=RUNTIME_MD, + msvs=msvs, vcvars=vcvars) -def build_wrapper_windows(): +def build_wrapper_library_windows(runtime_library, msvs, vcvars): # When building library cmake variables file is being modified # for the /MD build. If the build fails and variables aren't # restored then the next /MT build would be broken. Make sure # that original contents of cmake variables files is always # restored. - fix_cmake_variables_for_md_library(try_undo=True) + fix_cmake_variables_for_MD_library(try_undo=True) # Command to build libcef_dll_wrapper - cmake_wrapper = prepare_build_command(build_lib=True) + cmake_wrapper = prepare_build_command(build_lib=True, vcvars=vcvars) cmake_wrapper.extend(["cmake", "-G", "Ninja", "-DCMAKE_BUILD_TYPE="+Options.build_type, ".."]) - # Set build directory for /MT lib. - Options.build_wrapper_mt_dir = os.path.join(Options.cef_binary, - "build_wrapper_mt") + # Build directory and library path + build_wrapper_dir = os.path.join( + Options.cef_binary, + "build_wrapper_{runtime_library}_VS{msvs}" + .format(runtime_library=runtime_library, msvs=msvs)) + wrapper_lib = os.path.join(build_wrapper_dir, "libcef_dll_wrapper", + "libcef_dll_wrapper{ext}".format(ext=LIB_EXT)) - # Check whether already built + # Check whether library is already built mt_already_built = False - if build_wrapper_mt_succeeded(): + if os.path.exists(wrapper_lib): mt_already_built = True - elif os.path.exists(Options.build_wrapper_mt_dir): + elif os.path.exists(build_wrapper_dir): # Last build failed, clean directory - assert Options.build_wrapper_mt_dir - shutil.rmtree(Options.build_wrapper_mt_dir) - os.makedirs(Options.build_wrapper_mt_dir) + assert build_wrapper_dir + shutil.rmtree(build_wrapper_dir) + os.makedirs(build_wrapper_dir) else: - os.makedirs(Options.build_wrapper_mt_dir) + os.makedirs(build_wrapper_dir) - # Build /MT lib. + # Build library if mt_already_built: - print("[automate.py] Already built: libcef_dll_wrapper /MT") + print("[automate.py] Already built: libcef_dll_wrapper" + " /{runtime_library} for VS{msvs}" + .format(runtime_library=runtime_library, msvs=msvs)) else: - print("[automate.py] Build libcef_dll_wrapper /MT") + print("[automate.py] Build libcef_dll_wrapper" + " /{runtime_library} for VS{msvs}" + .format(runtime_library=runtime_library, msvs=msvs)) + + # Run cmake old_gyp_msvs_version = Options.gyp_msvs_version - Options.gyp_msvs_version = get_msvs_for_python() - # Cmake - run_command(cmake_wrapper, Options.build_wrapper_mt_dir) + Options.gyp_msvs_version = msvs + if runtime_library == RUNTIME_MD: + fix_cmake_variables_for_MD_library() + env = getenv() + if msvs == "2010": + # 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)) + run_command(cmake_wrapper, working_dir=build_wrapper_dir, env=env) Options.gyp_msvs_version = old_gyp_msvs_version + if runtime_library == RUNTIME_MD: + fix_cmake_variables_for_MD_library(undo=True) print("[automate.py] cmake OK") - # Ninja - ninja_wrapper = prepare_build_command(build_lib=True) + + # Run ninja + ninja_wrapper = prepare_build_command(build_lib=True, vcvars=vcvars) ninja_wrapper.extend(["ninja", "libcef_dll_wrapper"]) - run_command(ninja_wrapper, Options.build_wrapper_mt_dir) + run_command(ninja_wrapper, working_dir=build_wrapper_dir) print("[automate.py] ninja OK") - assert build_wrapper_mt_succeeded() + assert os.path.exists(wrapper_lib) - # Set build directory for /MD lib. - Options.build_wrapper_md_dir = os.path.join(Options.cef_binary, - "build_wrapper_md") - - # Check whether already built - md_already_built = False - if build_wrapper_md_succeeded(): - md_already_built = True - elif os.path.exists(Options.build_wrapper_md_dir): - # Last build failed, clean directory - assert Options.build_wrapper_md_dir - shutil.rmtree(Options.build_wrapper_md_dir) - os.makedirs(Options.build_wrapper_md_dir) - else: - os.makedirs(Options.build_wrapper_md_dir) - # Build /MD lib. - if md_already_built: - print("[automate.py] Already built: libcef_dll_wrapper /MD") +def fix_cmake_variables_permanently_windows(): + """Changes to cef_variables.cmake are made permanently, there is no undo. + """ + # To get rid of these warnings: + # > cl : Command line warning D9025 : overriding '/GR' with '/GR-' + # > cl : Command line warning D9025 : overriding '/W3' with '/W4' + # > cl : Command line warning D9025 : overriding '/MD' with '/MT' + cmake_variables = os.path.join(Options.cef_binary, "cmake", + "cef_variables.cmake") + with open(cmake_variables, "rb") as fp: + contents = fp.read().decode("utf-8") + set1 = 'set(CMAKE_CXX_FLAGS_RELEASE "")' + set2 = 'set(CMAKE_CXX_FLAGS "")' + if "if(OS_WINDOWS)" not in contents: + print("[automate.py] WARNING: failed to fix cmake variables" + " permanently on Windows") + return + if set1 not in contents or set2 not in contents: + contents = contents.replace("if(OS_WINDOWS)", + "if(OS_WINDOWS)\n {set1}\n {set2}" + .format(set1=set1, set2=set2)) else: - print("[automate.py] Build libcef_dll_wrapper /MD") - old_gyp_msvs_version = Options.gyp_msvs_version - Options.gyp_msvs_version = get_msvs_for_python() - # Fix cmake variables - # Cmake - fix_cmake_variables_for_md_library() - run_command(cmake_wrapper, Options.build_wrapper_md_dir) - Options.gyp_msvs_version = old_gyp_msvs_version - fix_cmake_variables_for_md_library(undo=True) - print("[automate.py] cmake OK") - # Ninja - ninja_wrapper = prepare_build_command(build_lib=True) - ninja_wrapper.extend(["ninja", "libcef_dll_wrapper"]) - run_command(ninja_wrapper, Options.build_wrapper_md_dir) - print("[automate.py] ninja OK") - assert build_wrapper_md_succeeded() + return + with open(cmake_variables, "wb") as fp: + print("[automate.py] Fix permanently: {filename}" + .format(filename=os.path.basename(cmake_variables))) + fp.write(contents.encode("utf-8")) -def fix_cmake_variables_for_md_library(undo=False, try_undo=False): +def fix_cmake_variables_for_MD_library(undo=False, try_undo=False): """Fix cmake variables or undo it. The try_undo param is for a case when want to be sure that the file wasn't modified, for example in case the last build failed.""" @@ -537,7 +531,7 @@ def fix_cmake_variables_for_md_library(undo=False, try_undo=False): cmake_variables = os.path.join(Options.cef_binary, "cmake", "cef_variables.cmake") with open(cmake_variables, "rb") as fp: - contents = fp.read() + contents = fp.read().decode("utf-8") if try_undo: matches1 = re.findall(re.escape(mt_replace), contents) @@ -563,51 +557,66 @@ def fix_cmake_variables_for_md_library(undo=False, try_undo=False): assert count == 1 with open(cmake_variables, "wb") as fp: - fp.write(contents) - - -def build_cefclient_succeeded(): - """Whether building cefclient/cefsimple/ceftests succeeded.""" - assert Options.build_cefclient_dir - cefclient_exe = "cefclient" + EXECUTABLE_EXT - return os.path.exists(os.path.join(Options.build_cefclient_dir, - "tests", - "cefclient", - Options.build_type, - cefclient_exe)) + fp.write(contents.encode("utf-8")) -def build_wrapper_mac_succeeded(): - """Whether building libcef_dll_wrapper succeeded.""" - return os.path.exists(os.path.join( - Options.build_wrapper_dir, - "libcef_dll_wrapper", - "libcef_dll_wrapper.a")) - - -def build_wrapper_mt_succeeded(): - """Whether building /MT library succeeded (Windows-only).""" - assert Options.build_wrapper_mt_dir - return os.path.exists(os.path.join(Options.build_wrapper_mt_dir, - "libcef_dll_wrapper", - "libcef_dll_wrapper.lib")) +def build_wrapper_library_mac(): + # On Mac it is required to link libcef_dll_wrapper against + # libc++ library, so must build this library separately + # from cefclient. + cmake_wrapper = prepare_build_command(build_lib=True) + cmake_wrapper.extend(["cmake", "-G", "Ninja", + "-DPROJECT_ARCH=x86_64" + "-DCMAKE_CXX_FLAGS=-stdlib=libc++", + "-DCMAKE_BUILD_TYPE=" + Options.build_type, + ".."]) + build_wrapper_dir = os.path.join(Options.cef_binary, + "build_wrapper") + wrapper_lib = os.path.join(build_wrapper_dir, "libcef_dll_wrapper", + "libcef_dll_wrapper.a") + # Check whether already built + already_built = False + if os.path.exists(wrapper_lib): + already_built = True + elif os.path.exists(build_wrapper_dir): + # Last build failed, clean directory + assert build_wrapper_dir + shutil.rmtree(build_wrapper_dir) + os.makedirs(build_wrapper_dir) + else: + os.makedirs(build_wrapper_dir) -def build_wrapper_md_succeeded(): - """Whether building /MD library succeeded (Windows-only).""" - assert Options.build_wrapper_md_dir - return os.path.exists(os.path.join(Options.build_wrapper_md_dir, - "libcef_dll_wrapper", - "libcef_dll_wrapper.lib")) + # Build libcef_dll_wrapper library + if already_built: + print("[automate.py] Already built: libcef_dll_wrapper") + else: + print("[automate.py] Build libcef_dll_wrapper") + # Cmake + run_command(cmake_wrapper, build_wrapper_dir) + print("[automate.py] cmake OK") + # Ninja + ninja_wrapper = prepare_build_command(build_lib=True) + ninja_wrapper.extend(["ninja", "libcef_dll_wrapper"]) + run_command(ninja_wrapper, build_wrapper_dir) + print("[automate.py] ninja OK") + assert os.path.exists(wrapper_lib) -def prepare_build_command(build_lib=False): +def prepare_build_command(build_lib=False, vcvars=None): """On Windows VS env variables must be set up by calling vcvarsall.bat""" command = list() if platform.system() == "Windows": if build_lib: - msvs = get_msvs_for_python() - command.append(globals()["VS"+msvs+"_VCVARS"]) + if vcvars == VS2010_VCVARS: + # When using WinSDK 7.1 vcvarsall.bat is broken. Instead + # env variables are queried using setuptools.msvc. + return command + if vcvars: + command.append(vcvars) + else: + command.append(get_vcvars_for_python()) + command.append(VS_PLATFORM_ARG) else: if int(Options.cef_branch) >= 2704: command.append(VS2015_VCVARS) @@ -627,12 +636,12 @@ def fix_cef_include_files(): cef_types_wrappers = os.path.join(Options.cef_binary, "include", "internal", "cef_types_wrappers.h") with open(cef_types_wrappers, "rb") as fp: - contents = fp.read() + contents = fp.read().decode("utf-8") # error C2059: syntax error : '{' contents = contents.replace("s->range = {0, 0};", "s->range.from = 0; s->range.to = 0;") with open(cef_types_wrappers, "wb") as fp: - fp.write(contents) + fp.write(contents.encode("utf-8")) def create_prebuilt_binaries(): @@ -729,17 +738,30 @@ def copy_app(app): if platform.system() == "Windows": # libcef.lib and cef_sandbox.lib mvfiles(bindir, libdir, ".lib") - # MT lib - libsrc = os.path.join(src, "build_wrapper_mt", "libcef_dll_wrapper", - "libcef_dll_wrapper.lib") - libdst = os.path.join(libdir, "libcef_dll_wrapper_mt.lib") - shutil.copy(libsrc, libdst) - # MD lib - libsrc = os.path.join(src, "build_wrapper_md", "libcef_dll_wrapper", - "libcef_dll_wrapper.lib") - libdst = os.path.join(libdir, "libcef_dll_wrapper_md.lib") - shutil.copy(libsrc, libdst) + python_compilers = get_available_python_compilers() + for msvs in python_compilers: + vs_subdir = os.path.join(libdir, "VS{msvs}".format(msvs=msvs)) + os.makedirs(vs_subdir) + # MT library + libsrc = os.path.join( + src, "build_wrapper_MT_VS{msvs}".format(msvs=msvs), + "libcef_dll_wrapper", "libcef_dll_wrapper.lib") + libdst = os.path.join(vs_subdir, "libcef_dll_wrapper_MT.lib") + shutil.copy(libsrc, libdst) + # MD library + libsrc = os.path.join( + src, "build_wrapper_MD_VS{msvs}".format(msvs=msvs), + "libcef_dll_wrapper", "libcef_dll_wrapper.lib") + libdst = os.path.join(vs_subdir, "libcef_dll_wrapper_MD.lib") + shutil.copy(libsrc, libdst) + elif platform.system() == "Darwin": + shutil.copy(os.path.join(src, "build_wrapper", "libcef_dll_wrapper", + "libcef_dll_wrapper.a"), + libdir) else: + # cefclient builds libcef_dll_wrapper by default and this version + # is good for cefpython on Linux. On Windows and Mac + # libcef_dll_wrapper is built seprately. shutil.copy(os.path.join(src, "build_cefclient", "libcef_dll_wrapper", "libcef_dll_wrapper.a"), libdir) @@ -761,23 +783,34 @@ def copy_app(app): print("[automate.py] OK prebuilt binaries created in '%s/'" % dst) -def get_msvs_for_python(): - """Get MSVS version (eg 2008) for current python running.""" - if sys.version_info[:2] == (2, 7): - return "2008" - elif sys.version_info[:2] == (3, 4): - return "2010" - elif sys.version_info[:2] == (3, 5): - return "2015" - else: - print("ERROR: This python version is not yet supported") - sys.exit(1) +def get_available_python_compilers(): + all_python_compilers = OrderedDict([ + ("2008", VS2008_VCVARS), + ("2010", VS2010_VCVARS), + ("2015", VS2015_VCVARS), + ]) + ret_compilers = OrderedDict() + for msvs in all_python_compilers: + vcvars = all_python_compilers[msvs] + if os.path.exists(vcvars): + ret_compilers[msvs] = vcvars + else: + print("[automate.py] INFO: Visual Studio compiler not found:" + " {vcvars}".format(vcvars=vcvars)) + return ret_compilers + + +def get_vcvars_for_python(): + msvs = get_msvs_for_python() + return globals()["VS"+msvs+"_VCVARS"] def getenv(): """Env variables passed to shell when running commands.""" env = os.environ - env["PATH"] = Options.depot_tools_dir + os.pathsep + env["PATH"] + if Options.build_cef: + if os.path.exists(Options.depot_tools_dir): + env["PATH"] = Options.depot_tools_dir + os.pathsep + env["PATH"] env["GYP_GENERATORS"] = Options.gyp_generators if platform.system() == "Windows": env["GYP_MSVS_VERSION"] = Options.gyp_msvs_version @@ -795,7 +828,7 @@ def getenv(): return env -def run_command(command, working_dir): +def run_command(command, working_dir, env=None): """Run command in a given directory with env variables set. On Linux multiple commands on one line with the use of && are not allowed. """ @@ -805,7 +838,9 @@ def run_command(command, working_dir): args = shlex.split(command.replace("\\", "\\\\")) else: args = command - return subprocess.check_call(args, cwd=working_dir, env=getenv(), + if not env: + env = getenv() + return subprocess.check_call(args, cwd=working_dir, env=env, shell=(platform.system() == "Windows")) diff --git a/tools/build.py b/tools/build.py index 5b9c59f2b..2ff5a37ea 100644 --- a/tools/build.py +++ b/tools/build.py @@ -85,7 +85,7 @@ def main(): if os.path.exists(CEFPYTHON_H): fix_cefpython_h() if WINDOWS: - compile_cpp_projects_windows() + compile_cpp_projects_with_setuptools() elif MAC or LINUX: compile_cpp_projects_unix() else: @@ -201,8 +201,8 @@ def get_python_path(): def check_cython_version(): print("[build.py] Check Cython version") - with open(os.path.join(TOOLS_DIR, "requirements.txt"), "r") as fileobj: - contents = fileobj.read() + with open(os.path.join(TOOLS_DIR, "requirements.txt"), "rb") as fileobj: + contents = fileobj.read().decode("utf-8") match = re.search(r"cython\s*==\s*([\d.]+)", contents, flags=re.IGNORECASE) assert match, "cython package not found in requirements.txt" @@ -300,8 +300,8 @@ def fix_cefpython_h(): print("[build.py] cefpython.h was not yet generated") return - with open(CEFPYTHON_H, "r") as fo: - contents = fo.read() + with open(CEFPYTHON_H, "rb") as fo: + contents = fo.read().decode("utf-8") already_fixed = False pragma = "#pragma warning(disable:4190)" @@ -313,51 +313,55 @@ def fix_cefpython_h(): contents = ("%s\n\n" % pragma) + contents if not already_fixed: - with open(CEFPYTHON_H, "w") as fo: - fo.write(contents) + with open(CEFPYTHON_H, "wb") as fo: + fo.write(contents.encode("utf-8")) print("[build.py] Save cefpython.h") if os.path.exists(CEFPYTHON_H_FIXED): - with open(CEFPYTHON_H_FIXED, "r") as fo: - contents_fixed = fo.read() + with open(CEFPYTHON_H_FIXED, "rb") as fo: + contents_fixed = fo.read().decode("utf-8") else: contents_fixed = "" if contents != contents_fixed: print("[build.py] Save cefpython_fixed.h") - with open(CEFPYTHON_H_FIXED, "w") as fo: - fo.write(contents) + with open(CEFPYTHON_H_FIXED, "wb") as fo: + fo.write(contents.encode("utf-8")) -def compile_cpp_projects_windows_v2(): +def compile_cpp_projects_with_setuptools(): """Use setuptools to build static libraries / executable.""" compile_cpp_projects = os.path.join(TOOLS_DIR, "build_cpp_projects.py") retcode = subprocess.call([sys.executable, compile_cpp_projects]) if retcode != 0: print("[build.py] ERROR: Failed to compile C++ projects") sys.exit(1) + # Copy subprocess executable + print("[build.py] Copy subprocess executable") + shutil.copy(SUBPROCESS_EXE, CEFPYTHON_BINARY) -def compile_cpp_projects_windows(): - """Build C++ projects using .vcproj files.""" +def compile_cpp_projects_windows_deprecated(): + """DEPRECATED. Not used currently. + Build C++ projects using .vcproj files.""" print("[build.py] Compile C++ projects") print("[build.py] ~~ Build CLIENT_HANDLER vcproj") vcproj = ("client_handler_py{pyver}_{os}.vcproj" .format(pyver=PYVERSION, os=OS_POSTFIX2)) vcproj = os.path.join(SRC_DIR, "client_handler", vcproj) - build_vcproj(vcproj) + build_vcproj_deprecated(vcproj) print("[build.py] ~~ Build LIBCEFPYTHONAPP vcproj") vcproj = ("libcefpythonapp_py{pyver}_{os}.vcproj" .format(pyver=PYVERSION, os=OS_POSTFIX2)) vcproj = os.path.join(SRC_DIR, "subprocess", vcproj) - build_vcproj(vcproj) + build_vcproj_deprecated(vcproj) print("[build.py] ~~ Build SUBPROCESS vcproj") vcproj = ("subprocess_{os}.vcproj" .format(os=OS_POSTFIX2)) vcproj = os.path.join(SRC_DIR, "subprocess", vcproj) - ret = build_vcproj(vcproj) + ret = build_vcproj_deprecated(vcproj) # Copy subprocess executable subprocess_from = os.path.join( @@ -376,10 +380,11 @@ def compile_cpp_projects_windows(): vcproj = ("cpp_utils_{os}.vcproj" .format(os=OS_POSTFIX2)) vcproj = os.path.join(SRC_DIR, "cpp_utils", vcproj) - build_vcproj(vcproj) + build_vcproj_deprecated(vcproj) -def build_vcproj(vcproj): +def build_vcproj_deprecated(vcproj): + """DEPRECATED. Not used currently.""" if PYVERSION == "27": args = list() args.append(VS2008_VCVARS) @@ -558,8 +563,8 @@ def copy_and_fix_pyx_files(): # Copy cefpython.pyx and fix includes in cefpython.pyx, eg.: # include "handlers/focus_handler.pyx" becomes include "focus_handler.pyx" shutil.copy("../../src/%s" % mainfile, "./%s" % mainfile) - with open("./%s" % mainfile, "r") as fo: - content = fo.read() + with open("./%s" % mainfile, "rb") as fo: + content = fo.read().decode("utf-8") (content, subs) = re.subn(r"^include \"handlers/", "include \"", content, @@ -567,8 +572,8 @@ def copy_and_fix_pyx_files(): # Add __version__ variable in cefpython.pyx print("[build.py] Add __version__ variable to %s" % mainfile) content = ('__version__ = "{}"\n'.format(VERSION)) + content - with open("./%s" % mainfile, "w") as fo: - fo.write(content) + with open("./%s" % mainfile, "wb") as fo: + fo.write(content.encode("utf-8")) print("[build.py] Fix %s includes in %s" % (subs, mainfile)) # Copy the rest of the files @@ -577,8 +582,8 @@ def copy_and_fix_pyx_files(): newfile = "./%s" % os.path.basename(pyxfile) shutil.copy(pyxfile, newfile) pyxfile = newfile - with open(pyxfile, "r") as pyxfileopened: - content = pyxfileopened.read() + with open(pyxfile, "rb") as pyxfileopened: + content = pyxfileopened.read().decode("utf-8") lineNumber = except_all_missing(content) if lineNumber: print("[build.py] WARNING: 'except *' missing" @@ -597,8 +602,8 @@ def copy_and_fix_pyx_files(): # print("[build.py] %s includes removed in: %s" # % (subs, os.path.basename(pyxfile))) pass - with open(pyxfile, "w") as pyxfileopened: - pyxfileopened.write(content) + with open(pyxfile, "wb") as pyxfileopened: + pyxfileopened.write(content.encode("utf-8")) print("\n") diff --git a/tools/build_cpp_projects.py b/tools/build_cpp_projects.py index cc8c571ec..d3ae08211 100644 --- a/tools/build_cpp_projects.py +++ b/tools/build_cpp_projects.py @@ -154,12 +154,14 @@ def build_subprocess_executable(): "subprocess" + EXECUTABLE_EXT) if changed or not os.path.exists(executable_path): lib_dir = os.path.join(CEF_BINARIES_LIBRARIES, "lib") + lib_dir_vs = os.path.join(lib_dir, + get_msvs_for_python(vs_prefix=True)) compiler.link_executable(objects, output_progname="subprocess", output_dir=BUILD_SUBPROCESS, libraries=["libcef", - "libcef_dll_wrapper_mt"], - library_dirs=[lib_dir], + "libcef_dll_wrapper_MT"], + library_dirs=[lib_dir, lib_dir_vs], # TODO linker flags for Linux/Mac extra_preargs=None, extra_postargs=subprocess_LINKER_ARGS) diff --git a/tools/common.py b/tools/common.py index 801e64fd9..8d490160a 100644 --- a/tools/common.py +++ b/tools/common.py @@ -90,13 +90,17 @@ # Build C++ projects directories BUILD_CEFPYTHON_APP = os.path.join(BUILD_CEFPYTHON, - "cefpython_app_" + OS_POSTFIX2) + "cefpython_app_py{pyver}_{os}" + .format(pyver=PYVERSION, os=OS_POSTFIX2)) BUILD_CLIENT_HANDLER = os.path.join(BUILD_CEFPYTHON, - "client_handler_" + OS_POSTFIX2) + "client_handler_py{pyver}_{os}" + .format(pyver=PYVERSION, os=OS_POSTFIX2)) BUILD_CPP_UTILS = os.path.join(BUILD_CEFPYTHON, - "cpp_utils_" + OS_POSTFIX2) + "cpp_utils_py{pyver}_{os}" + .format(pyver=PYVERSION, os=OS_POSTFIX2)) BUILD_SUBPROCESS = os.path.join(BUILD_CEFPYTHON, - "subprocess_" + OS_POSTFIX2) + "subprocess_py{pyver}_{os}" + .format(pyver=PYVERSION, os=OS_POSTFIX2)) # -- end build directories EXAMPLES_DIR = os.path.join(ROOT_DIR, "examples") @@ -135,21 +139,25 @@ VS2015_VCVARS = ("C:\\Program Files (x86)\\Microsoft Visual Studio 14.0" "\\VC\\vcvarsall.bat") -VS2015_BUILD = "" # TODO: add VS2015 Python 3.5/3.6 support # For CEF build VS2013_VCVARS = ("C:\\Program Files (x86)\\Microsoft Visual Studio 12.0" "\\VC\\vcvarsall.bat") +# VS2010 vcvarsall not used, using detection with setuptools instead VS2010_VCVARS = ("C:\\Program Files (x86)\\Microsoft Visual Studio 10.0" "\\VC\\vcvarsall.bat") -VS2010_BUILD = "" # TODO: add VS2010 Python 3.4 support VS2008_VCVARS = ("%LocalAppData%\\Programs\\Common\\Microsoft" "\\Visual C++ for Python\\9.0\\vcvarsall.bat") VS2008_BUILD = ("%LocalAppData%\\Programs\\Common\\" "Microsoft\\Visual C++ for Python\\9.0\\" "VC\\bin\\amd64\\vcbuild.exe") +if "LOCALAPPDATA" in os.environ: + VS2008_VCVARS = VS2008_VCVARS.replace("%LocalAppData%", + os.environ["LOCALAPPDATA"]) + VS2008_BUILD = VS2008_BUILD.replace("%LocalAppData%", + os.environ["LOCALAPPDATA"]) def detect_cef_binaries_libraries_dir(): @@ -192,7 +200,7 @@ def get_cefpython_version(): def get_version_from_file(header_file): with open(header_file, "rU") as fp: - contents = fp.read() + contents = fp.read() # no need to decode() as "rU" specified ret = dict() matches = re.findall(r'^#define (\w+) "?([^\s"]+)"?', contents, re.MULTILINE) @@ -201,5 +209,20 @@ def get_version_from_file(header_file): return ret +def get_msvs_for_python(vs_prefix=False): + """Get MSVS version (eg 2008) for current python running.""" + if sys.version_info[:2] == (2, 7): + return "VS2008" if vs_prefix else "2008" + elif sys.version_info[:2] == (3, 4): + return "VS2010" if vs_prefix else "2010" + elif sys.version_info[:2] == (3, 5): + return "VS2015" if vs_prefix else "2015" + elif sys.version_info[:2] == (3, 6): + return "VS2015" if vs_prefix else "2015" + else: + print("ERROR: This version of Python is not supported") + sys.exit(1) + + detect_cef_binaries_libraries_dir() detect_cefpython_binary_dir() diff --git a/tools/cython_setup.py b/tools/cython_setup.py index efab8e993..30e04171b 100644 --- a/tools/cython_setup.py +++ b/tools/cython_setup.py @@ -310,22 +310,15 @@ def get_library_dirs(): print("[cython_setup.py] Prepare library directories") library_dirs = [ os.path.join(CEF_BINARIES_LIBRARIES, "lib"), + os.path.join(CEF_BINARIES_LIBRARIES, "lib", + get_msvs_for_python(vs_prefix=True)), ] if WINDOWS: library_dirs.extend([ get_winsdk_lib(), - os.path.join(SRC_DIR, "client_handler", - "Release_py{pyver}_{os}" - .format(pyver=PYVERSION, os=OS_POSTFIX2)), - os.path.join(SRC_DIR, "subprocess", - "Release_{os}" - .format(os=OS_POSTFIX2)), - os.path.join(SRC_DIR, "subprocess", - "Release_py{pyver}_{os}" - .format(pyver=PYVERSION, os=OS_POSTFIX2)), - os.path.join(SRC_DIR, "cpp_utils", - "Release_{os}" - .format(os=OS_POSTFIX2)) + BUILD_CEFPYTHON_APP, + BUILD_CLIENT_HANDLER, + BUILD_CPP_UTILS, ]) if MAC: library_dirs.append(os.path.join(CEF_BINARIES_LIBRARIES, "bin")) @@ -344,14 +337,11 @@ def get_libraries(): if WINDOWS: libraries.extend([ "libcef", - "libcef_dll_wrapper_md", + "libcef_dll_wrapper_MD", "User32", - "client_handler_py{pyver}_{os}".format( - pyver=PYVERSION, os=OS_POSTFIX2), - "libcefpythonapp_py{pyver}_{os}".format( - pyver=PYVERSION, os=OS_POSTFIX2), - "cpp_utils_{os}".format( - os=OS_POSTFIX2), + "cefpython_app", + "cpp_utils", + "client_handler", ]) elif MAC: libraries.extend([ @@ -417,11 +407,12 @@ def get_ext_modules(options): def compile_time_constants(): print("[cython_setup.py] Generate compile_time_constants.pxi") - with open(os.path.join(SRC_DIR, "compile_time_constants.pxi"), "w") as fd: - fd.write('# This file was generated by setup.py\n') + with open(os.path.join(SRC_DIR, "compile_time_constants.pxi"), "wb") as fo: + contents = "# This file was generated by setup.py\n" # A way around Python 3.2 bug: UNAME_SYSNAME is not set - fd.write('DEF UNAME_SYSNAME = "%s"\n' % platform.uname()[0]) - fd.write('DEF PY_MAJOR_VERSION = %s\n' % sys.version_info.major) + contents += 'DEF UNAME_SYSNAME = "%s"\n' % platform.uname()[0] + contents += 'DEF PY_MAJOR_VERSION = %s\n' % sys.version_info.major + fo.write(contents.encode("utf-8")) if __name__ == "__main__": From ed758d864fa0bb702ea64a2f323be7bab2b96eff Mon Sep 17 00:00:00 2001 From: cztomczak Date: Thu, 9 Mar 2017 08:41:45 +0100 Subject: [PATCH 158/557] Change cefpython API header file name depending on Python version (#315) --- src/common/cefpython_public_api.h | 16 +++++- tools/build.py | 82 +++++++++++++++++-------------- tools/build_cpp_projects.py | 2 +- tools/common.py | 10 ++-- tools/cython_setup.py | 9 ++-- 5 files changed, 72 insertions(+), 47 deletions(-) diff --git a/src/common/cefpython_public_api.h b/src/common/cefpython_public_api.h index fe0dc5a0d..7de519527 100644 --- a/src/common/cefpython_public_api.h +++ b/src/common/cefpython_public_api.h @@ -10,7 +10,7 @@ #define CEFPYTHON_PUBLIC_API_H #if defined(OS_WIN) -#pragma warning(disable:4190) // cefpython_fixed.h extern C-linkage warnings +#pragma warning(disable:4190) // cefpython API extern C-linkage warnings #endif #include "Python.h" @@ -30,6 +30,18 @@ #include "include/cef_command_line.h" #include "util.h" -#include "../../build/build_cefpython/cefpython_fixed.h" +#if PY_MAJOR_VERSION == 2 +#if PY_MINOR_VERSION == 7 +#include "../../build/build_cefpython/cefpython_py27_fixed.h" +#endif // PY_MINOR_VERSION +#elif PY_MAJOR_VERSION == 3 +#if PY_MINOR_VERSION == 4 +#include "../../build/build_cefpython/cefpython_py34_fixed.h" +#elif PY_MINOR_VERSION == 5 +#include "../../build/build_cefpython/cefpython_py35_fixed.h" +#elif PY_MINOR_VERSION == 6 +#include "../../build/build_cefpython/cefpython_py36_fixed.h" +#endif // PY_MINOR_VERSION +#endif // PY_MAJOR_VERSION #endif // CEFPYTHON_PUBLIC_API_H diff --git a/tools/build.py b/tools/build.py index 2ff5a37ea..ffa2d44ec 100644 --- a/tools/build.py +++ b/tools/build.py @@ -82,21 +82,23 @@ def main(): check_cython_version() check_directories() setup_environ() - if os.path.exists(CEFPYTHON_H): - fix_cefpython_h() + if os.path.exists(CEFPYTHON_API_HFILE): + fix_cefpython_api_header_file() if WINDOWS: compile_cpp_projects_with_setuptools() elif MAC or LINUX: compile_cpp_projects_unix() else: - print("[build.py] INFO: Looks like first run, as cefpython.h" - " is missing. Skip building C++ projects.") + print("[build.py] INFO: Looks like first run, as" + " cefpython_py{pyver}.h is missing. Skip building" + " C++ projects." + .format(pyver=PYVERSION)) global FIRST_RUN FIRST_RUN = True clear_cache() copy_and_fix_pyx_files() build_cefpython_module() - fix_cefpython_h() + fix_cefpython_api_header_file() install_and_run() @@ -282,49 +284,52 @@ def check_directories(): assert os.path.exists(CEFPYTHON_BINARY) -def fix_cefpython_h(): - """This function does two things: 1) Disable warnings in cefpython.h - and 2) Make a copy named cefpython_fixed.h - this copy will be used - by C++ projects and its modification time won't change every time - you run build.py script, thus C++ won't rebuild each time.""" +def fix_cefpython_api_header_file(): + """This function does two things: 1) Disable warnings in cefpython + API header file and 2) Make a copy named cefpython_pyXX_fixed.h, + this copy will be used by C++ projects and its modification time + won't change every time you run build.py script, thus C++ won't + rebuild each time.""" - # Fix cefpython.h to disable this warning: + # Fix cefpython_pyXX.h to disable this warning: # > warning: 'somefunc' has C-linkage specified, but returns # > user-defined type 'sometype' which is incompatible with C # On Mac this warning must be disabled using -Wno-return-type-c-linkage # flag in makefiles. - print("[build.py] Fix cefpython.h in the build_cefpython/ directory") - if not os.path.exists(CEFPYTHON_H): - assert not os.path.exists(CEFPYTHON_H_FIXED) - print("[build.py] cefpython.h was not yet generated") + print("[build.py] Fix cefpython API header file in the build_cefpython/" + " directory") + if not os.path.exists(CEFPYTHON_API_HFILE): + assert not os.path.exists(CEFPYTHON_API_HFILE_FIXED) + print("[build.py] cefpython API header file was not yet generated") return - with open(CEFPYTHON_H, "rb") as fo: + with open(CEFPYTHON_API_HFILE, "rb") as fo: contents = fo.read().decode("utf-8") already_fixed = False pragma = "#pragma warning(disable:4190)" if pragma in contents: already_fixed = True - print("[build.py] cefpython.h is already fixed") + print("[build.py] cefpython API header file is already fixed") else: if not MAC: contents = ("%s\n\n" % pragma) + contents if not already_fixed: - with open(CEFPYTHON_H, "wb") as fo: + with open(CEFPYTHON_API_HFILE, "wb") as fo: fo.write(contents.encode("utf-8")) - print("[build.py] Save cefpython.h") + print("[build.py] Save {filename}" + .format(filename=CEFPYTHON_API_HFILE)) - if os.path.exists(CEFPYTHON_H_FIXED): - with open(CEFPYTHON_H_FIXED, "rb") as fo: + if os.path.exists(CEFPYTHON_API_HFILE_FIXED): + with open(CEFPYTHON_API_HFILE_FIXED, "rb") as fo: contents_fixed = fo.read().decode("utf-8") else: contents_fixed = "" if contents != contents_fixed: print("[build.py] Save cefpython_fixed.h") - with open(CEFPYTHON_H_FIXED, "wb") as fo: + with open(CEFPYTHON_API_HFILE_FIXED, "wb") as fo: fo.write(contents.encode("utf-8")) @@ -437,9 +442,9 @@ def compile_cpp_projects_unix(): # Need to allow continuing even when make fails, as it may # fail because the "public" function declaration is not yet - # in "cefpython.h", but for it to be generated we need to run - # cython compiling, so in this case you continue even when make - # fails and then run the compile.py script again and this time + # in cefpython API header file, but for it to be generated we need + # to run cython compiling, so in this case you continue even when + # make fails and then run the compile.py script again and this time # make should succeed. # -- CLIENT_HANDLER @@ -533,15 +538,16 @@ def copy_and_fix_pyx_files(): os.chdir(BUILD_CEFPYTHON) print("\n") - mainfile = "cefpython.pyx" + mainfile_original = "cefpython.pyx" + mainfile_newname = "cefpython_py{pyver}.pyx".format(pyver=PYVERSION) pyxfiles = glob.glob("../../src/*.pyx") if not len(pyxfiles): print("[build.py] ERROR: no .pyx files found in root") sys.exit(1) - pyxfiles = [f for f in pyxfiles if f.find(mainfile) == -1] - # Now, pyxfiles contains all pyx files except the mainfile (cefpython.pyx), - # we do not fix includes in mainfile. + pyxfiles = [f for f in pyxfiles if f.find(mainfile_original) == -1] + # Now, pyxfiles contains all pyx files except mainfile_original + # (cefpython.pyx), we do not fix includes in mainfile. pyxfiles2 = glob.glob("../../src/handlers/*.pyx") if not len(pyxfiles2): @@ -562,19 +568,19 @@ def copy_and_fix_pyx_files(): # Copy cefpython.pyx and fix includes in cefpython.pyx, eg.: # include "handlers/focus_handler.pyx" becomes include "focus_handler.pyx" - shutil.copy("../../src/%s" % mainfile, "./%s" % mainfile) - with open("./%s" % mainfile, "rb") as fo: + shutil.copy("../../src/%s" % mainfile_original, "./%s" % mainfile_newname) + with open("./%s" % mainfile_newname, "rb") as fo: content = fo.read().decode("utf-8") (content, subs) = re.subn(r"^include \"handlers/", "include \"", content, flags=re.MULTILINE) # Add __version__ variable in cefpython.pyx - print("[build.py] Add __version__ variable to %s" % mainfile) + print("[build.py] Add __version__ variable to %s" % mainfile_newname) content = ('__version__ = "{}"\n'.format(VERSION)) + content - with open("./%s" % mainfile, "wb") as fo: + with open("./%s" % mainfile_newname, "wb") as fo: fo.write(content.encode("utf-8")) - print("[build.py] Fix %s includes in %s" % (subs, mainfile)) + print("[build.py] Fix %s includes in %s" % (subs, mainfile_newname)) # Copy the rest of the files print("[build.py] Fix includes in other .pyx files") @@ -682,10 +688,12 @@ def build_cefpython_module(): # Check if built succeeded after pyx files were removed if ret != 0: - if FIRST_RUN and os.path.exists(CEFPYTHON_H): + if FIRST_RUN and os.path.exists(CEFPYTHON_API_HFILE): print("[build.py] INFO: looks like this was first run and" - " linking is expected to fail in such case. Will re-run" - " the build.py script programmatically now.") + " building the cefpython module is expected to fail" + " in such case due to cefpython API header file not" + " being generated yet. Will re-run the build.py script" + " programmatically now.") args = list() args.append(sys.executable) args.append(os.path.join(TOOLS_DIR, os.path.basename(__file__))) diff --git a/tools/build_cpp_projects.py b/tools/build_cpp_projects.py index d3ae08211..aa39e59b5 100644 --- a/tools/build_cpp_projects.py +++ b/tools/build_cpp_projects.py @@ -221,7 +221,7 @@ def smart_compile(compiler, macros, extra_args, sources, output_dir): obj_time = os.path.getmtime(obj_file) source_time = os.path.getmtime(source_file) header_time = os.path.getmtime(header_file) if header_file else 0 - cefpython_h_fixed_time = os.path.getmtime(CEFPYTHON_H_FIXED) + cefpython_h_fixed_time = os.path.getmtime(CEFPYTHON_API_HFILE_FIXED) common_files_time = get_directory_mtime(os.path.join(SRC_DIR, "common")) changed = ((source_time > obj_time) diff --git a/tools/common.py b/tools/common.py index 8d490160a..c22723efe 100644 --- a/tools/common.py +++ b/tools/common.py @@ -120,9 +120,13 @@ UNITTESTS_DIR = os.path.abspath(os.path.join(ROOT_DIR, "unittests")) # ---------------------------------------------------------------------------- -# cefpython.h and fixed version -CEFPYTHON_H = os.path.join(BUILD_CEFPYTHON, "cefpython.h") -CEFPYTHON_H_FIXED = os.path.join(BUILD_CEFPYTHON, "cefpython_fixed.h") +# cefpython API header file and a fixed copy of it +CEFPYTHON_API_HFILE = os.path.join(BUILD_CEFPYTHON, + "cefpython_py{pyver}.h" + .format(pyver=PYVERSION)) +CEFPYTHON_API_HFILE_FIXED = os.path.join(BUILD_CEFPYTHON, + "cefpython_py{pyver}_fixed.h" + .format(pyver=PYVERSION)) # Result libraries paths CEFPYTHON_APP_LIB = os.path.join(BUILD_CEFPYTHON_APP, diff --git a/tools/cython_setup.py b/tools/cython_setup.py index 30e04171b..c3c2356ee 100644 --- a/tools/cython_setup.py +++ b/tools/cython_setup.py @@ -49,7 +49,8 @@ ModuleNode.generate_extern_c_macro_definition) def generate_extern_c_macro_definition(self, code): - # This code is written to both cefpython.h and cefpython.cpp + # This code is written by Cython to both cefpython API header file + # and cefpython module cpp file. g_generate_extern_c_macro_definition_old(self, code) code.putln("// Added by: cefpython/tools/cython_setup.py") code.putln("#undef PyMODINIT_FUNC") @@ -97,8 +98,8 @@ def main(): print("[cython_setup.py] Execute setup()") setup( - name='cefpython_py%s' % PYVERSION, - cmdclass={'build_ext': build_ext}, + name="cefpython_py{pyver}".format(pyver=PYVERSION), + cmdclass={"build_ext": build_ext}, ext_modules=get_ext_modules(options) ) @@ -370,7 +371,7 @@ def get_libraries(): def get_ext_modules(options): ext_modules = [Extension( name=MODULE_NAME_NOEXT, - sources=["cefpython.pyx"], + sources=["cefpython_py{pyver}.pyx".format(pyver=PYVERSION)], # Ignore the warning in the console: # > C:\Python27\lib\distutils\extension.py:133: UserWarning: From e0ef669e6f33b120c6d089abb182fe6baa5af42d Mon Sep 17 00:00:00 2001 From: cztomczak Date: Thu, 9 Mar 2017 14:20:46 +0100 Subject: [PATCH 159/557] Windows 64-bit support (#316)... Minor fixes to tools. Add cef.GetVersion() function with keys like cef_version, chrome_version etc. Print architecture along with python version in examples/tools. --- api/cefpython.md | 17 +++ docs/API.md | 2 +- examples/gtk2.py | 5 +- examples/gtk3.py | 3 +- examples/hello_world.py | 4 +- examples/qt4.py | 3 +- examples/tkinter_.py | 3 +- examples/wxpython.py | 3 +- src/cefpython.pyx | 13 ++ src/compile_time_constants.pxi | 2 +- src/window_utils_win.pyx | 3 +- tools/automate.py | 7 + tools/build.py | 235 +++++++++++++++++++-------------- tools/common.py | 34 ++++- tools/cython_setup.py | 3 +- tools/make_installer.py | 7 +- unittests/_test_runner.py | 5 +- 17 files changed, 226 insertions(+), 123 deletions(-) diff --git a/api/cefpython.md b/api/cefpython.md index 1757ab76b..d994c9443 100644 --- a/api/cefpython.md +++ b/api/cefpython.md @@ -17,6 +17,7 @@ Table of contents: * [GetCommandLineSwitch](#getcommandlineswitch) * [GetGlobalClientCallback](#getglobalclientcallback) * [GetModuleDirectory](#getmoduledirectory) + * [GetVersion](#getversion) * [Initialize](#initialize) * [IsThread](#isthread) * [MessageLoop](#messageloop) @@ -144,6 +145,22 @@ Returns a global client callback that was set using SetGlobalClientCallback(). R Get the cefpython module directory. This method is useful to get full path to CEF binaries. This is required when setting [ApplicationSettings](ApplicationSettings.md) options like: 'browser_subprocess_path', 'resources_dir_pat' and 'locales_dir_path'. +### GetVersion + +| | | +| --- | --- | +| __Return__ | dict | + +Return CEF Python and CEF versions dictionary with keys: +* version +* chrome_version +* cef_version +* cef_api_hash_platform +* cef_api_hash_universal +* cef_commit_hash +* cef_commit_number + + ### Initialize | Parameter | Type | diff --git a/docs/API.md b/docs/API.md index 85df057cc..720df3f57 100644 --- a/docs/API.md +++ b/docs/API.md @@ -1,3 +1,3 @@ # API -API reference is available in the root [api/](../api) directory. +API reference is available in the [api/](../api) root directory. diff --git a/examples/gtk2.py b/examples/gtk2.py index fafe46d88..2f8821819 100644 --- a/examples/gtk2.py +++ b/examples/gtk2.py @@ -8,9 +8,9 @@ import pygtk import gtk import gobject -import sys import os import platform +import sys # Fix for PyCharm hints warnings when using static methods WindowUtils = cef.WindowUtils() @@ -50,7 +50,8 @@ def main(): def check_versions(): print("[gkt2.py] CEF Python {ver}".format(ver=cef.__version__)) - print("[gkt2.py] Python {ver}".format(ver=sys.version[:6])) + print("[gkt2.py] Python {ver} {arch}".format( + ver=platform.python_version(), arch=platform.architecture()[0])) print("[gkt2.py] GTK {ver}".format(ver='.'.join( map(str, list(gtk.gtk_version))))) assert cef.__version__ >= "55.3", "CEF Python v55.3+ required to run this" diff --git a/examples/gtk3.py b/examples/gtk3.py index 1e2caf04c..6e0032600 100644 --- a/examples/gtk3.py +++ b/examples/gtk3.py @@ -39,7 +39,8 @@ def main(): print("[gkt3.py] CEF Python {ver}".format(ver=cef.__version__)) - print("[gkt3.py] Python {ver}".format(ver=sys.version[:6])) + print("[gkt3.py] Python {ver} {arch}".format( + ver=platform.python_version(), arch=platform.architecture()[0])) print("[gkt3.py] GTK {major}.{minor}".format( major=Gtk.get_major_version(), minor=Gtk.get_minor_version())) diff --git a/examples/hello_world.py b/examples/hello_world.py index 0c64ab843..c29a2669f 100644 --- a/examples/hello_world.py +++ b/examples/hello_world.py @@ -2,6 +2,7 @@ # Tested with CEF Python v55.3+. from cefpython3 import cefpython as cef +import platform import sys @@ -16,7 +17,8 @@ def main(): def check_versions(): print("[hello_world.py] CEF Python {ver}".format(ver=cef.__version__)) - print("[hello_world.py] Python {ver}".format(ver=sys.version[:6])) + print("[hello_world.py] Python {ver} {arch}".format( + ver=platform.python_version(), arch=platform.architecture()[0])) assert cef.__version__ >= "55.3", "CEF Python v55.3+ required to run this" diff --git a/examples/qt4.py b/examples/qt4.py index d48ff45bd..7b3516a2c 100644 --- a/examples/qt4.py +++ b/examples/qt4.py @@ -76,7 +76,8 @@ def main(): def check_versions(): print("[qt4.py] CEF Python {ver}".format(ver=cef.__version__)) - print("[qt4.py] Python {ver}".format(ver=sys.version[:6])) + print("[qt4.py] Python {ver} {arch}".format( + ver=platform.python_version(), arch=platform.architecture()[0])) # PyQt version if "pyqt" in sys.argv: # noinspection PyUnresolvedReferences diff --git a/examples/tkinter_.py b/examples/tkinter_.py index ad9cc06de..024e0feb2 100644 --- a/examples/tkinter_.py +++ b/examples/tkinter_.py @@ -47,7 +47,8 @@ def main(): stream_handler.setFormatter(formatter) logger.addHandler(stream_handler) logger.info("CEF Python {ver}".format(ver=cef.__version__)) - logger.info("Python {ver}".format(ver=sys.version[:6])) + logger.info("Python {ver} {arch}".format( + ver=platform.python_version(), arch=platform.architecture()[0])) logger.info("Tk {ver}".format(ver=tk.Tcl().eval('info patchlevel'))) assert cef.__version__ >= "55.3", "CEF Python v55.3+ required to run this" sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error diff --git a/examples/wxpython.py b/examples/wxpython.py index c9176a0b6..144bab7ed 100644 --- a/examples/wxpython.py +++ b/examples/wxpython.py @@ -50,7 +50,8 @@ def main(): def check_versions(): print("[wxpython.py] CEF Python {ver}".format(ver=cef.__version__)) - print("[wxpython.py] Python {ver}".format(ver=sys.version[:6])) + print("[wxpython.py] Python {ver} {arch}".format( + ver=platform.python_version(), arch=platform.architecture()[0])) print("[wxpython.py] wxPython {ver}".format(ver=wx.version())) # CEF Python version requirement assert cef.__version__ >= "55.3", "CEF Python v55.3+ required to run this" diff --git a/src/cefpython.pyx b/src/cefpython.pyx index 261da9758..941fff00b 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -998,3 +998,16 @@ cpdef object GetAppSetting(py_string key): if key in g_applicationSettings: return g_applicationSettings[key] return None + +cpdef dict GetVersion(): + # These variable are set when building the module. + # noinspection PyUnresolvedReferences + return dict( + version=__version__, + chrome_version=__chrome_version__, + cef_version=__cef_version__, + cef_api_hash_platform=__cef_api_hash_platform__, + cef_api_hash_universal=__cef_api_hash_universal__, + cef_commit_hash=__cef_commit_hash__, + cef_commit_number=__cef_commit_number__, + ) diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 10ec798af..632aab59c 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 = 2 +DEF PY_MAJOR_VERSION = 3 diff --git a/src/window_utils_win.pyx b/src/window_utils_win.pyx index 6a7862cdf..a1b613878 100644 --- a/src/window_utils_win.pyx +++ b/src/window_utils_win.pyx @@ -117,7 +117,8 @@ class WindowUtils(object): # of the parent window, try again. if not parentIconBig and not parentIconSmall: - parentWindowHandle = GetParent(parentWindowHandle) + parentWindowHandle = GetParent( + parentWindowHandle) Debug("WindowUtils.SetIcon(): popup inherits icon from " "parent window: %s" % parentWindowHandle) diff --git a/tools/automate.py b/tools/automate.py index 9c6295560..e7559af33 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -466,6 +466,12 @@ 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. + for env_key in env: + env_value = env[env_key] + if type(env_value) != str: + env[env_key] = env_value.encode("utf-8") run_command(cmake_wrapper, working_dir=build_wrapper_dir, env=env) Options.gyp_msvs_version = old_gyp_msvs_version if runtime_library == RUNTIME_MD: @@ -622,6 +628,7 @@ def prepare_build_command(build_lib=False, vcvars=None): command.append(VS2015_VCVARS) else: command.append(VS2013_VCVARS) + command.append(VS_PLATFORM_ARG) command.append("&&") return command diff --git a/tools/build.py b/tools/build.py index ffa2d44ec..15fc1da5f 100644 --- a/tools/build.py +++ b/tools/build.py @@ -21,7 +21,7 @@ build.py VERSION [--rebuild-cpp] [--fast] [--clean] [--kivy] Options: - VERSION Version in format xx.xx + VERSION Version number eg. 50.0 --rebuild-cpp Force rebuild of C++ projects --fast Fast mode --clean Clean C++ projects build files (.o .a etc) @@ -71,14 +71,12 @@ def main(): - if len(sys.argv) <= 1: - print(__doc__) - sys.exit(1) - print("[build.py] Python version: %s" % platform.python_version()) + command_line_args() + print("[build.py] Python version: {ver} {arch}" + .format(ver=platform.python_version(), arch=ARCH_STR)) print("[build.py] Python executable: %s" % sys.executable) print("[build.py] PYVERSION = %s" % PYVERSION) print("[build.py] OS_POSTFIX2 = %s" % OS_POSTFIX2) - command_line_args() check_cython_version() check_directories() setup_environ() @@ -102,6 +100,86 @@ def main(): install_and_run() +def command_line_args(): + global DEBUG_FLAG, FAST_FLAG, CLEAN_FLAG, KIVY_FLAG,\ + REBUILD_CPP, VERSION + + VERSION = get_version_from_command_line_args() + if not VERSION: + print(__doc__) + sys.exit(1) + + print("[build.py] Parse command line arguments") + + # -- debug flag + if len(sys.argv) > 1 and "--debug" in sys.argv: + DEBUG_FLAG = True + print("[build.py] DEBUG mode On") + + # --fast flag + if len(sys.argv) > 1 and "--fast" in sys.argv: + # Fast mode doesn't delete C++ .o .a files. + # Fast mode also disables optimization flags in setup/setup.py . + FAST_FLAG = True + print("[build.py] FAST mode On") + + # --clean flag + if len(sys.argv) > 1 and "--clean" in sys.argv: + CLEAN_FLAG = True + + # --kivy flag + if len(sys.argv) > 1 and "--kivy" in sys.argv: + KIVY_FLAG = True + print("[build.py] KIVY mode enabled") + + # --rebuild-cpp flag + # Rebuild c++ projects + if len(sys.argv) > 1 and "--rebuild-cpp" in sys.argv: + REBUILD_CPP = True + print("[build.py] REBUILD_CPP mode enabled") + + print("[build.py] VERSION=%s" % VERSION) + + +def check_cython_version(): + print("[build.py] Check Cython version") + with open(os.path.join(TOOLS_DIR, "requirements.txt"), "rb") as fileobj: + contents = fileobj.read().decode("utf-8") + match = re.search(r"cython\s*==\s*([\d.]+)", contents, + flags=re.IGNORECASE) + assert match, "cython package not found in requirements.txt" + require_version = match.group(1) + try: + import Cython + version = Cython.__version__ + except ImportError: + # noinspection PyUnusedLocal + Cython = None + print("[build.py] ERROR: Cython is not installed ({0} required)" + .format(require_version)) + sys.exit(1) + if version != require_version: + print("[build.py] ERROR: Wrong Cython version: {0}. Required: {1}" + .format(version, require_version)) + sys.exit(1) + print("[build.py] Cython version: {0}".format(version)) + + +def check_directories(): + print("[build.py] Check directories") + # Create directories if necessary + if not os.path.exists(CEFPYTHON_BINARY): + os.makedirs(CEFPYTHON_BINARY) + if not os.path.exists(BUILD_CEFPYTHON): + os.makedirs(BUILD_CEFPYTHON) + + # Check directories exist + assert os.path.exists(BUILD_DIR) + assert os.path.exists(BUILD_CEFPYTHON) + assert os.path.exists(CEF_BINARIES_LIBRARIES) + assert os.path.exists(CEFPYTHON_BINARY) + + def setup_environ(): """Set environment variables. Set PATH so that it contains only minimum set of directories,to avoid any possible issues. Set Python @@ -201,89 +279,6 @@ def get_python_path(): return os.path.dirname(sys.executable) -def check_cython_version(): - print("[build.py] Check Cython version") - with open(os.path.join(TOOLS_DIR, "requirements.txt"), "rb") as fileobj: - contents = fileobj.read().decode("utf-8") - match = re.search(r"cython\s*==\s*([\d.]+)", contents, - flags=re.IGNORECASE) - assert match, "cython package not found in requirements.txt" - require_version = match.group(1) - try: - import Cython - version = Cython.__version__ - except ImportError: - # noinspection PyUnusedLocal - Cython = None - print("[build.py] ERROR: Cython is not installed ({0} required)" - .format(require_version)) - sys.exit(1) - if version != require_version: - print("[build.py] ERROR: Wrong Cython version: {0}. Required: {1}" - .format(version, require_version)) - sys.exit(1) - print("[build.py] Cython version: {0}".format(version)) - - -def command_line_args(): - global DEBUG_FLAG, FAST_FLAG, CLEAN_FLAG, KIVY_FLAG,\ - REBUILD_CPP, VERSION - - print("[build.py] Parse command line arguments") - - # -- debug flag - if len(sys.argv) > 1 and "--debug" in sys.argv: - DEBUG_FLAG = True - print("[build.py] DEBUG mode On") - - # --fast flag - if len(sys.argv) > 1 and "--fast" in sys.argv: - # Fast mode doesn't delete C++ .o .a files. - # Fast mode also disables optimization flags in setup/setup.py . - FAST_FLAG = True - print("[build.py] FAST mode On") - - # --clean flag - if len(sys.argv) > 1 and "--clean" in sys.argv: - CLEAN_FLAG = True - - # --kivy flag - if len(sys.argv) > 1 and "--kivy" in sys.argv: - KIVY_FLAG = True - print("[build.py] KIVY mode enabled") - - # --rebuild-cpp flag - # Rebuild c++ projects - if len(sys.argv) > 1 and "--rebuild-cpp" in sys.argv: - REBUILD_CPP = True - print("[build.py] REBUILD_CPP mode enabled") - - # version arg - if len(sys.argv) > 1 and re.search(r"^\d+\.\d+$", sys.argv[1]): - VERSION = sys.argv[1] - else: - print("[build.py] ERROR: expected first arg to be a version number") - print(" Allowed version format: \\d+\.\\d+") - sys.exit(1) - - print("[build.py] VERSION=%s" % VERSION) - - -def check_directories(): - print("[build.py] Check directories") - # Create directories if necessary - if not os.path.exists(CEFPYTHON_BINARY): - os.makedirs(CEFPYTHON_BINARY) - if not os.path.exists(BUILD_CEFPYTHON): - os.makedirs(BUILD_CEFPYTHON) - - # Check directories exist - assert os.path.exists(BUILD_DIR) - assert os.path.exists(BUILD_CEFPYTHON) - assert os.path.exists(CEF_BINARIES_LIBRARIES) - assert os.path.exists(CEFPYTHON_BINARY) - - def fix_cefpython_api_header_file(): """This function does two things: 1) Disable warnings in cefpython API header file and 2) Make a copy named cefpython_pyXX_fixed.h, @@ -345,28 +340,31 @@ def compile_cpp_projects_with_setuptools(): shutil.copy(SUBPROCESS_EXE, CEFPYTHON_BINARY) -def compile_cpp_projects_windows_deprecated(): +def compile_cpp_projects_windows_DEPRECATED(): """DEPRECATED. Not used currently. Build C++ projects using .vcproj files.""" + + # TODO: Remove code after setuptools compilation was tested for some time + print("[build.py] Compile C++ projects") print("[build.py] ~~ Build CLIENT_HANDLER vcproj") vcproj = ("client_handler_py{pyver}_{os}.vcproj" .format(pyver=PYVERSION, os=OS_POSTFIX2)) vcproj = os.path.join(SRC_DIR, "client_handler", vcproj) - build_vcproj_deprecated(vcproj) + build_vcproj_DEPRECATED(vcproj) print("[build.py] ~~ Build LIBCEFPYTHONAPP vcproj") vcproj = ("libcefpythonapp_py{pyver}_{os}.vcproj" .format(pyver=PYVERSION, os=OS_POSTFIX2)) vcproj = os.path.join(SRC_DIR, "subprocess", vcproj) - build_vcproj_deprecated(vcproj) + build_vcproj_DEPRECATED(vcproj) print("[build.py] ~~ Build SUBPROCESS vcproj") vcproj = ("subprocess_{os}.vcproj" .format(os=OS_POSTFIX2)) vcproj = os.path.join(SRC_DIR, "subprocess", vcproj) - ret = build_vcproj_deprecated(vcproj) + ret = build_vcproj_DEPRECATED(vcproj) # Copy subprocess executable subprocess_from = os.path.join( @@ -385,11 +383,28 @@ def compile_cpp_projects_windows_deprecated(): vcproj = ("cpp_utils_{os}.vcproj" .format(os=OS_POSTFIX2)) vcproj = os.path.join(SRC_DIR, "cpp_utils", vcproj) - build_vcproj_deprecated(vcproj) + build_vcproj_DEPRECATED(vcproj) -def build_vcproj_deprecated(vcproj): +def build_vcproj_DEPRECATED(vcproj): """DEPRECATED. Not used currently.""" + + # TODO: Remove code after setuptools compilation was tested for some time + + # In VS2010 vcbuild.exe was replaced by msbuild.exe. + # Ufortunately WinSDK 7.1 does not come with msbuild.exe, + # so it would be required to install Visual Studio 2010, + # and to support both 32-bit ad 64-bit compilations it + # a non-express version would have to be installed, which + # is not free. So to make it free open-source it was + # required migrate to a new compilation system that uses + # distutils/setuptools packages. + + # msbuild.exe flags: + # /clp:disableconsolecolor + # msbuild /p:BuildProjectReferences=false project.proj + # MSBuild.exe MyProject.proj /t:build + if PYVERSION == "27": args = list() args.append(VS2008_VCVARS) @@ -409,11 +424,6 @@ def build_vcproj_deprecated(vcproj): else: raise Exception("Only Python 2.7 32-bit is currently supported") - # In VS2010 vcbuild was replaced by msbuild.exe. - # /clp:disableconsolecolor - # msbuild /p:BuildProjectReferences=false project.proj - # MSBuild.exe MyProject.proj /t:build - def compile_ask_to_continue(): # noinspection PyUnboundLocalVariable @@ -577,7 +587,7 @@ def copy_and_fix_pyx_files(): flags=re.MULTILINE) # Add __version__ variable in cefpython.pyx print("[build.py] Add __version__ variable to %s" % mainfile_newname) - content = ('__version__ = "{}"\n'.format(VERSION)) + content + content = generate_cefpython_module_variables() + content with open("./%s" % mainfile_newname, "wb") as fo: fo.write(content.encode("utf-8")) print("[build.py] Fix %s includes in %s" % (subs, mainfile_newname)) @@ -614,6 +624,26 @@ def copy_and_fix_pyx_files(): print("\n") +def generate_cefpython_module_variables(): + """Global variables that will be appended to cefpython.pyx sources.""" + ret = ('__version__ = "{0}"\n'.format(VERSION)) + version = get_cefpython_version() + chrome_version = "{0}.{1}.{2}.{3}".format( + version["CHROME_VERSION_MAJOR"], version["CHROME_VERSION_MINOR"], + version["CHROME_VERSION_BUILD"], version["CHROME_VERSION_PATCH"]) + ret += ('__chrome_version__ = "{0}"\n'.format(chrome_version)) + ret += ('__cef_version__ = "{0}"\n'.format(version["CEF_VERSION"])) + ret += ('__cef_api_hash_platform__ = "{0}"\n' + .format(version["CEF_API_HASH_PLATFORM"])) + ret += ('__cef_api_hash_universal__ = "{0}"\n' + .format(version["CEF_API_HASH_UNIVERSAL"])) + ret += ('__cef_commit_hash__ = "{0}"\n' + .format(version["CEF_COMMIT_HASH"])) + ret += ('__cef_commit_number__ = "{0}"\n' + .format(version["CEF_COMMIT_NUMBER"])) + return ret + + def except_all_missing(content): # This is not perfect, won't detect C++ custom types, but will find # the built-in types, templates and pointers. @@ -782,6 +812,9 @@ def install_and_run(): sys.exit(ret) os.chdir(BUILD_DIR) + # Delete setup installer directory after the package was installed + delete_directory_reliably(setup_installer_dir) + # Run unittests print("[build.py] Run unittests") test_runner = os.path.join(UNITTESTS_DIR, "_test_runner.py") diff --git a/tools/common.py b/tools/common.py index c22723efe..8f63bdd3f 100644 --- a/tools/common.py +++ b/tools/common.py @@ -14,6 +14,7 @@ # Architecture and OS postfixes ARCH32 = (8 * struct.calcsize('P') == 32) ARCH64 = (8 * struct.calcsize('P') == 64) +ARCH_STR = "32-bit" if (8 * struct.calcsize('P') == 32) else "64-bit" # OS_POSTFIX is for directories/files names in cefpython sources # OS_POSTFIX2 is for platform name in cefpython binaries # CEF_POSTFIX2 is for platform name in upstream CEF binaries @@ -86,7 +87,7 @@ CEF_BINARIES_LIBRARIES = os.path.join(BUILD_DIR, "cef_"+OS_POSTFIX2) # Will be overwritten through detect_cefpython_binary_dir() -CEFPYTHON_BINARY = "CEFPYTHON_BINARY" +CEFPYTHON_BINARY = "CEFPYTHON_BINARY_NOTSET" # Build C++ projects directories BUILD_CEFPYTHON_APP = os.path.join(BUILD_CEFPYTHON, @@ -185,16 +186,39 @@ def detect_cef_binaries_libraries_dir(): def detect_cefpython_binary_dir(): """Detect cefpython binary directory where cefpython modules - will be put. Eg. buil/cefpython55_win32/.""" - version = get_cefpython_version() - binary_dir = "cefpython{major}_{os}".format( - major=version["CHROME_VERSION_MAJOR"], + will be put. Eg. build/cefpython_56.0_win32/.""" + # Check cef version from header file and check cefpython version + # that was passed as command line argument to either build.py + # or make-installer.py. The CEFPYTHON_BINARY constant should + # only be used in those two scripts, so version number in sys.argv + # is expected. If not found then keep the default + # "CEFPYTHON_BINARY_NOTSET" value intact. + cef_version = get_cefpython_version() + cmdline_version = get_version_from_command_line_args() + if not cmdline_version: + return + # If cef_version is 56 then expect version from command line to + # start with "56.". + cef_major = cef_version["CHROME_VERSION_MAJOR"] + if not cmdline_version.startswith("{major}.".format(major=cef_major)): + return + binary_dir = "cefpython_binary_{version}_{os}".format( + version=cmdline_version, os=OS_POSTFIX2) binary_dir = os.path.join(BUILD_DIR, binary_dir) global CEFPYTHON_BINARY CEFPYTHON_BINARY = binary_dir +def get_version_from_command_line_args(): + args = " ".join(sys.argv) + match = re.search(r"\b\d+\.\d+\b", args) + if match: + version = match.group(0) + return version + return "" + + def get_cefpython_version(): """Get CEF version from the 'src/version/' directory.""" header_file = os.path.join(SRC_DIR, "version", diff --git a/tools/cython_setup.py b/tools/cython_setup.py index c3c2356ee..368d5ccc3 100644 --- a/tools/cython_setup.py +++ b/tools/cython_setup.py @@ -74,7 +74,8 @@ def generate_extern_c_macro_definition(self, code): def main(): - print("[cython_setup.py] Python version: %s" % platform.python_version()) + print("[cython_setup.py] Python version: {ver} {arch}" + .format(ver=platform.python_version(), arch=ARCH_STR)) print("[cython_setup.py] Python executable: %s" % sys.executable) print("[cython_setup.py] Cython version: %s" % Cython.__version__) diff --git a/tools/make_installer.py b/tools/make_installer.py index 84f3aba2b..6dd1eb717 100644 --- a/tools/make_installer.py +++ b/tools/make_installer.py @@ -118,11 +118,8 @@ def main(): def command_line_args(): global VERSION, WHEEL, WHEEL_ARGS - args = " ".join(sys.argv) - match = re.search(r"\d+\.\d+", args) - if match: - VERSION = match.group(0) - else: + VERSION = get_version_from_command_line_args() + if not VERSION: print(__doc__) sys.exit(1) for arg in sys.argv: diff --git a/unittests/_test_runner.py b/unittests/_test_runner.py index 3b2147bd3..1c67b2da0 100644 --- a/unittests/_test_runner.py +++ b/unittests/_test_runner.py @@ -25,6 +25,7 @@ import unittest import os +import platform import sys from os.path import dirname, realpath import re @@ -254,7 +255,9 @@ def _print_summary(self): print("-"*70) print("[_test_runner.py] CEF Python {ver}" .format(ver=self.cefpython_version)) - print("[_test_runner.py] Python {ver}".format(ver=sys.version[:6])) + print("[_test_runner.py] Python {ver} {arch}" + .format(ver=platform.python_version(), + arch=platform.architecture()[0])) print("[_test_runner.py] Ran {ran} tests in total" .format(ran=self.ran)) if self.errors or self.failures: From 36c0560230b2896138e94726c143c242d1f6e251 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Fri, 10 Mar 2017 14:42:09 +0100 Subject: [PATCH 160/557] Support Python executables with spaces in path (PR #318)... Python 3.5/3.6 installs to C:\Program Files (x86)\ when "install into PATH for all users" is checked. --- tools/automate.py | 15 +++++++-------- tools/build.py | 14 +++++++------- tools/make_installer.py | 2 +- tools/run_examples.py | 2 +- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/tools/automate.py b/tools/automate.py index e7559af33..584d09a68 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -851,19 +851,13 @@ def run_command(command, working_dir, env=None): shell=(platform.system() == "Windows")) -def run_python(command_line, working_dir): - """Run python script using depot_tools.""" - python = "python" - return run_command("%s %s" % (python, command_line), working_dir) - - def run_git(command_line, working_dir): """Run git command using depot_tools.""" return run_command("git %s" % command_line, working_dir) def run_automate_git(): - """Run CEF automate-git.py.""" + """Run CEF automate-git.py using Python 2.7.""" script = os.path.join(Options.cefpython_dir, "tools", "automate-git.py") """ Example automate-git.py command: @@ -898,8 +892,13 @@ def run_automate_git(): # later in cef_binary/ with cmake/ninja do works fine. args.append("--build-target=cefsimple") + # On Windows automate-git.py must be run using Python 2.7 + # from depot_tools. depot_tools should already be added to PATH. + python = "python" # *do not* replace with sys.executable! args = " ".join(args) - return run_python(script+" "+args, Options.cef_build_dir) + command = script + " " + args + working_dir = Options.cef_build_dir + return run_command("%s %s" % (python, command), working_dir) def rmdir(path): diff --git a/tools/build.py b/tools/build.py index 15fc1da5f..5afa215fd 100644 --- a/tools/build.py +++ b/tools/build.py @@ -690,13 +690,13 @@ def build_cefpython_module(): os.chdir(BUILD_CEFPYTHON) if FAST_FLAG: - ret = subprocess.call("{python} {tools_dir}/cython_setup.py" + ret = subprocess.call("\"{python}\" {tools_dir}/cython_setup.py" " build_ext --fast" .format(python=sys.executable, tools_dir=TOOLS_DIR), shell=True) else: - ret = subprocess.call("{python} {tools_dir}/cython_setup.py" + ret = subprocess.call("\"{python}\" {tools_dir}/cython_setup.py" " build_ext" .format(python=sys.executable, tools_dir=TOOLS_DIR), @@ -725,7 +725,7 @@ def build_cefpython_module(): " being generated yet. Will re-run the build.py script" " programmatically now.") args = list() - args.append(sys.executable) + args.append("\"{python}\"".format(python=sys.executable)) args.append(os.path.join(TOOLS_DIR, os.path.basename(__file__))) assert __file__ in sys.argv[0] args.extend(sys.argv[1:]) @@ -794,7 +794,7 @@ def install_and_run(): # Make setup installer print("[build.py] Make setup installer") make_tool = os.path.join(TOOLS_DIR, "make_installer.py") - ret = os.system("{python} {make_tool} --version {version}" + ret = os.system("\"{python}\" {make_tool} --version {version}" .format(python=sys.executable, make_tool=make_tool, version=VERSION)) @@ -805,7 +805,7 @@ def install_and_run(): # Install print("[build.py] Install the cefpython package") os.chdir(setup_installer_dir) - ret = os.system("{sudo} {python} setup.py install" + ret = os.system("{sudo} \"{python}\" setup.py install" .format(sudo=get_sudo(), python=sys.executable)) if ret != 0: print("[build.py] ERROR while installing package") @@ -818,7 +818,7 @@ def install_and_run(): # Run unittests print("[build.py] Run unittests") test_runner = os.path.join(UNITTESTS_DIR, "_test_runner.py") - ret = os.system("{python} {test_runner}" + ret = os.system("\"{python}\" {test_runner}" .format(python=sys.executable, test_runner=test_runner)) if ret != 0: print("[build.py] ERROR while running unit tests") @@ -829,7 +829,7 @@ def install_and_run(): os.chdir(EXAMPLES_DIR) kivy_flag = "--kivy" if KIVY_FLAG else "" run_examples = os.path.join(TOOLS_DIR, "run_examples.py") - ret = os.system("{python} {run_examples} {kivy_flag}" + ret = os.system("\"{python}\" {run_examples} {kivy_flag}" .format(python=sys.executable, run_examples=run_examples, kivy_flag=kivy_flag)) diff --git a/tools/make_installer.py b/tools/make_installer.py index 6dd1eb717..d13b7155d 100644 --- a/tools/make_installer.py +++ b/tools/make_installer.py @@ -103,7 +103,7 @@ def main(): print("[make_installer.py] ERROR: you must specify flags" " eg. --python-tag cp27 or --universal") sys.exit(1) - command = ("{python} setup.py bdist_wheel {wheel_args}" + command = ("\"{python}\" setup.py bdist_wheel {wheel_args}" .format(python=sys.executable, wheel_args=" ".join(WHEEL_ARGS))) print("[make_installer.py] Run command: '{0}' in setup directory" diff --git a/tools/run_examples.py b/tools/run_examples.py index b2ae112d8..9f2583c65 100644 --- a/tools/run_examples.py +++ b/tools/run_examples.py @@ -96,7 +96,7 @@ def main(): for example in examples: print("[run_examples.py] Running '{example}'..." .format(example=example)) - ret = os.system("{python} {example}" + ret = os.system("\"{python}\" {example}" .format(python=sys.executable, example=example)) if ret == 0: succeeded.append(example) From e9db0e8e88f1572bf141e6330bd7c38cb4e3d2b4 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 11 Mar 2017 16:56:24 +0100 Subject: [PATCH 161/557] Create build_distrib.py tool (#317)... Add --no-run-examples flag to build.py. --- docs/Build-instructions.md | 4 +- tools/build.py | 66 +++--- tools/build_cpp_projects.py | 3 +- tools/build_distrib.py | 436 ++++++++++++++++++++++++++++++++++++ tools/common.py | 119 +++++++--- tools/make_installer.py | 9 +- 6 files changed, 571 insertions(+), 66 deletions(-) create mode 100644 tools/build_distrib.py diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index db67f0908..821adab6e 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -47,8 +47,8 @@ Before you can build CEF Python or CEF you must satisfy ## Quick build instructions for Windows -Complete steps for building CEF Python v50+ using prebuilt binaries -and libraries from GitHub Releases: +Complete steps for building CEF Python v50+ with Python 2.7 using +prebuilt binaries and libraries from GitHub Releases: 1) Tested and works fine on Windows 7 64-bit diff --git a/tools/build.py b/tools/build.py index 5afa215fd..0319a2ea5 100644 --- a/tools/build.py +++ b/tools/build.py @@ -21,11 +21,12 @@ build.py VERSION [--rebuild-cpp] [--fast] [--clean] [--kivy] Options: - VERSION Version number eg. 50.0 - --rebuild-cpp Force rebuild of C++ projects - --fast Fast mode - --clean Clean C++ projects build files (.o .a etc) - --kivy Run only Kivy example + VERSION Version number eg. 50.0 + --no-run-examples Do not run examples after build, only unit tests + --rebuild-cpp Force rebuild of .vcproj C++ projects (DISABLED) + --fast Fast mode + --clean Clean C++ projects build files on Linux/Mac + --kivy Run only Kivy example """ # How to debug on Linux: @@ -59,12 +60,13 @@ pass # Command line args variables +VERSION = "" +NO_RUN_EXAMPLES = False DEBUG_FLAG = False FAST_FLAG = False CLEAN_FLAG = False KIVY_FLAG = False REBUILD_CPP = False -VERSION = "" # First run FIRST_RUN = False @@ -102,39 +104,44 @@ def main(): def command_line_args(): global DEBUG_FLAG, FAST_FLAG, CLEAN_FLAG, KIVY_FLAG,\ - REBUILD_CPP, VERSION + REBUILD_CPP, VERSION, NO_RUN_EXAMPLES - VERSION = get_version_from_command_line_args() + VERSION = get_version_from_command_line_args(__file__) if not VERSION: print(__doc__) sys.exit(1) print("[build.py] Parse command line arguments") - # -- debug flag - if len(sys.argv) > 1 and "--debug" in sys.argv: + # --no-run-examples + if "--no-run-examples" in sys.argv: + NO_RUN_EXAMPLES = True + print("[build.py] Running examples disabled (--no-run-examples)") + + # -- debug + if "--debug" in sys.argv: DEBUG_FLAG = True print("[build.py] DEBUG mode On") - # --fast flag - if len(sys.argv) > 1 and "--fast" in sys.argv: + # --fast + if "--fast" in sys.argv: # Fast mode doesn't delete C++ .o .a files. # Fast mode also disables optimization flags in setup/setup.py . FAST_FLAG = True print("[build.py] FAST mode On") - # --clean flag - if len(sys.argv) > 1 and "--clean" in sys.argv: + # --clean + if "--clean" in sys.argv: CLEAN_FLAG = True - # --kivy flag - if len(sys.argv) > 1 and "--kivy" in sys.argv: + # --kivy + if "--kivy" in sys.argv: KIVY_FLAG = True print("[build.py] KIVY mode enabled") - # --rebuild-cpp flag + # --rebuild-cpp # Rebuild c++ projects - if len(sys.argv) > 1 and "--rebuild-cpp" in sys.argv: + if "--rebuild-cpp" in sys.argv: REBUILD_CPP = True print("[build.py] REBUILD_CPP mode enabled") @@ -825,17 +832,18 @@ def install_and_run(): sys.exit(ret) # Run examples - print("[build.py] Run examples") - os.chdir(EXAMPLES_DIR) - kivy_flag = "--kivy" if KIVY_FLAG else "" - run_examples = os.path.join(TOOLS_DIR, "run_examples.py") - ret = os.system("\"{python}\" {run_examples} {kivy_flag}" - .format(python=sys.executable, - run_examples=run_examples, - kivy_flag=kivy_flag)) - if ret != 0: - print("[build.py] ERROR while running examples") - sys.exit(1) + if not NO_RUN_EXAMPLES: + print("[build.py] Run examples") + os.chdir(EXAMPLES_DIR) + kivy_flag = "--kivy" if KIVY_FLAG else "" + run_examples = os.path.join(TOOLS_DIR, "run_examples.py") + ret = os.system("\"{python}\" {run_examples} {kivy_flag}" + .format(python=sys.executable, + run_examples=run_examples, + kivy_flag=kivy_flag)) + if ret != 0: + print("[build.py] ERROR while running examples") + sys.exit(1) print("[build.py] Everything OK") diff --git a/tools/build_cpp_projects.py b/tools/build_cpp_projects.py index aa39e59b5..f7eae2a84 100644 --- a/tools/build_cpp_projects.py +++ b/tools/build_cpp_projects.py @@ -221,7 +221,8 @@ def smart_compile(compiler, macros, extra_args, sources, output_dir): obj_time = os.path.getmtime(obj_file) source_time = os.path.getmtime(source_file) header_time = os.path.getmtime(header_file) if header_file else 0 - cefpython_h_fixed_time = os.path.getmtime(CEFPYTHON_API_HFILE_FIXED) + cefpython_h_fixed_time = os.path.getmtime( + CEFPYTHON_API_HFILE_FIXED) common_files_time = get_directory_mtime(os.path.join(SRC_DIR, "common")) changed = ((source_time > obj_time) diff --git a/tools/build_distrib.py b/tools/build_distrib.py new file mode 100644 index 000000000..84c661d89 --- /dev/null +++ b/tools/build_distrib.py @@ -0,0 +1,436 @@ +# 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 + +""" +Build distribution packages for all architectures and all supported +python versions. + +TODO: Linux/Mac support. Currently runs only on Windows. + +Usage: + build_distrib.py VERSION [--no-run-examples] + +Options: + VERSION Version number eg. 50.0 + --no-run-examples Do not run examples while building cefpython modules. + Only unit tests will be run in such case. + +This script does the following: +1. Expects that all supported python versions are installed + a) On Windows search for Pythons in the multiple default install + locations + b) On Mac use system Python 2.7 and Python 3 from ~/.pyenv/versions/ + directory + c) On Linux use only Pythons from ~/.pyenv/versions/ directory +2. Expects that all python compilers for supported python versions + are installed. See docs/Build-instructions.md > Requirements. +3. Expects cef_binary*/ directories from Spotify Automated Builds + to be in the build/ directory +4. Install and/or upgrade tools/requirements.txt and uninstall + cefpython3 packages for all python versions +5. Run automate.py --prebuilt-cef using both Python 32-bit and Python 64-bit +6. Pack the prebuilt biaries using zip on Win/Mac and .tar.gz on Linux + and move to build/distrib/ +7. Build cefpython modules for all supported Python versions on both + 32-bit and 64-bit +8. Make setup installers and pack them to zip (Win/Mac) or .tar.gz (Linux) +9. Make wheel packages +10. Move setup and wheel packages to the build/distrib/ directory +""" + +from common import * +import glob +import os +import pprint +import re +import shutil +import subprocess +import zipfile + +# Command line args +VERSION = "" +NO_RUN_EXAMPLES = False + +# Pythons +SUPPORTED_PYTHON_VERSIONS = [(2, 7), (3, 4), (3, 5), (3, 6)] +PYTHON_SEARCH_PATHS_WINDOWS = [ + "C:\\Python*\\", + "%LocalAppData%\\Programs\\Python\\Python*\\", + "C:\\Program Files\\Python*\\", + "C:\\Program Files (x86)\\Python*\\", +] + + +def main(): + command_line_args() + print("[build_distrib.py] Supported python versions:") + pp = pprint.PrettyPrinter(indent=4) + pp.pprint(SUPPORTED_PYTHON_VERSIONS) + clean_build_directories() + pythons_32bit = list() + pythons_64bit = list() + if WINDOWS: + pythons_32bit = search_for_pythons("32bit") + pythons_64bit = search_for_pythons("64bit") + check_pythons(pythons_32bit, pythons_64bit) + install_upgrade_requirements(pythons_32bit + pythons_64bit) + uninstall_cefpython3_packages(pythons_32bit + pythons_64bit) + if not os.path.exists(DISTRIB_DIR): + os.makedirs(DISTRIB_DIR) + if pythons_32bit: + run_automate_prebuilt_cef(pythons_32bit[0]) + pack_prebuilt_cef(pythons_32bit[0]["arch"]) + if pythons_64bit is not None: + run_automate_prebuilt_cef(pythons_64bit[0]) + pack_prebuilt_cef(pythons_64bit[0]["arch"]) + build_cefpython_modules(pythons_32bit + pythons_64bit) + if pythons_32bit: + make_packages(pythons_32bit[0], "32bit") + if pythons_64bit: + make_packages(pythons_64bit[0], "64bit") + show_summary(pythons_32bit, pythons_64bit) + + +def command_line_args(): + global VERSION, NO_RUN_EXAMPLES + version = get_version_from_command_line_args(__file__) + if not version: + print(__doc__) + sys.exit(1) + VERSION = version + if "--no-run-examples" in sys.argv: + NO_RUN_EXAMPLES = True + + +def clean_build_directories(): + print("[build_distrib.py] Clean build directories") + + # Distrib dir + if os.path.exists(DISTRIB_DIR): + print("[build_distrib.py] Delete directory: {distrib_dir}/" + .format(distrib_dir=os.path.basename(DISTRIB_DIR))) + shutil.rmtree(DISTRIB_DIR) + + # build_cefpython/ dir + if os.path.exists(BUILD_CEFPYTHON): + print("[build_distirb.py] Delete directory: {dir}/" + .format(dir=os.path.basename(BUILD_CEFPYTHON))) + shutil.rmtree(BUILD_CEFPYTHON) + + # cefpython_binary_*/ dirs + delete_cefpython_binary_dir("32bit") + delete_cefpython_binary_dir("64bit") + + # cef binaries and libraries dirs + delete_cef_binaries_libraries_dir("32bit") + delete_cef_binaries_libraries_dir("64bit") + + +def delete_cefpython_binary_dir(arch): + cefpython_binary = get_cefpython_binary_basename( + postfix2=get_postfix2_for_arch(arch)) + assert cefpython_binary, cefpython_binary + cefpython_binary = os.path.join(BUILD_DIR, cefpython_binary) + if os.path.exists(cefpython_binary): + print("[build_distrib.py] Delete directory: {dir}/" + .format(dir=os.path.basename(cefpython_binary))) + shutil.rmtree(cefpython_binary) + + +def delete_cef_binaries_libraries_dir(arch): + cef_binlib = get_cef_binaries_libraries_basename( + postfix2=get_postfix2_for_arch(arch)) + assert cef_binlib, cef_binlib + cef_binlib = os.path.join(BUILD_DIR, cef_binlib) + if os.path.exists(cef_binlib): + print("[build_distrib.py] Delete directory: {dir}/" + .format(dir=os.path.basename(cef_binlib))) + shutil.rmtree(cef_binlib) + + +def check_pythons(pythons_32bit, pythons_64bit): + pp = pprint.PrettyPrinter(indent=4) + if pythons_32bit: + print("[build_distrib.py] Pythons 32-bit found:") + pp.pprint(pythons_32bit) + if WINDOWS and len(pythons_32bit) != len(SUPPORTED_PYTHON_VERSIONS): + print("[build_distrib.py] ERROR: Couldn't find all supported" + " python 32-bit installations. Found: {found}." + .format(found=len(pythons_32bit))) + sys.exit(1) + if pythons_64bit: + print("[build_distrib.py] Pythons 64-bit found:") + pp.pprint(pythons_64bit) + if len(pythons_64bit) != len(SUPPORTED_PYTHON_VERSIONS): + print("[build_distrib.py] ERROR: Couldn't find all supported" + " python 64-bit installations. Found: {found}." + .format(found=len(pythons_64bit))) + sys.exit(1) + + +def search_for_pythons(search_arch): + print("[build_distrib.py] Search for Pythons...") + if WINDOWS: + return search_for_pythons_windows(search_arch) + raise Exception("Only Windows platform supported currently") + + +def search_for_pythons_windows(search_arch): + """Returns pythons ordered by version from lowest to highest.""" + pythons_found = list() + for pattern in PYTHON_SEARCH_PATHS_WINDOWS: + pattern = pattern.replace("%LocalAppData%", + os.environ["LOCALAPPDATA"]) + results = glob.glob(pattern) + for path in results: + if os.path.isdir(path): + python = os.path.join(path, "python.exe") + version_code = ("import sys;" + "print(str(sys.version_info[:3]));") + version_str = subprocess.check_output([python, "-c", + version_code]) + version_str = version_str.strip() + match = re.search("^\((\d+), (\d+), (\d+)\)$", version_str) + assert match, version_str + major = match.group(1) + minor = match.group(2) + micro = match.group(3) + version_tuple2 = (int(major), int(minor)) + version_tuple3 = (int(major), int(minor), int(micro)) + arch_code = ("import platform;" + "print(str(platform.architecture()[0]));") + arch = subprocess.check_output([python, "-c", arch_code]) + arch = arch.strip() + if version_tuple2 in SUPPORTED_PYTHON_VERSIONS \ + and arch == search_arch: + name = ("Python {major}.{minor}.{micro} {arch}" + .format(major=major, minor=minor, micro=micro, + arch=arch)) + pythons_found.append(dict( + version2=version_tuple2, + version3=version_tuple3, + arch=arch, + executable=python, + name=name)) + ret_pythons = list() + for version_tuple in SUPPORTED_PYTHON_VERSIONS: + supported_python = None + for python in pythons_found: + if python["version2"] == version_tuple: + # Always go through the whole loop and save the last + # python executable for the given version (eg. 2.7), + # so that the latest version is used (eg. 2.7.12). + # This is assuming that glob.glob sorted directories. + supported_python = python + if supported_python: + ret_pythons.append(supported_python) + return ret_pythons + + +def install_upgrade_requirements(pythons): + for python in pythons: + print("[build_distrib.py] pip install/upgrade requirements.txt" + " for: {name}".format(name=python["name"])) + + # Upgrade pip + command = "\"{python}\" -m pip install --upgrade pip" + command = command.format(python=python["executable"]) + if python["executable"].startswith("/usr/"): + command = "sudo {command}".format(command=command) + pcode = subprocess.call(command, shell=True) + if pcode != 0: + print("[build_distrib.py] ERROR while upgrading pip") + sys.exit(1) + + # Install/upgrade requirements.txt + requirements = os.path.join(TOOLS_DIR, "requirements.txt") + command = "\"{python}\" -m pip install --upgrade -r {requirements}" + command = command.format(python=python["executable"], + requirements=requirements) + if python["executable"].startswith("/usr/"): + command = "sudo {command}".format(command=command) + pcode = subprocess.call(command, shell=True) + if pcode != 0: + print("[build_distrib.py] ERROR while running pip install/upgrade") + sys.exit(1) + + +def uninstall_cefpython3_packages(pythons): + for python in pythons: + print("[build_distrib.py] pip uninstall cefpython3 package" + " for: {name}".format(name=python["name"])) + + # Check if package is installed + command = ("\"{python}\" -m pip show cefpython3" + .format(python=python["executable"])) + try: + output = subprocess.check_output(command) + except subprocess.CalledProcessError, exc: + # pip show returns error code when package is not installed + output = exc.output + if not len(output.strip()): + # Package is not installed - info is an empty string + print("[build_distrib.py] Not installed") + continue + + # Uninstall package. Only uninstall if package is installed, + # otherwise error code is returned. + command = ("\"{python}\" -m pip uninstall -y cefpython3" + .format(python=python["executable"])) + if python["executable"].startswith("/usr/"): + command = "sudo {command}".format(command=command) + pcode = subprocess.call(command, shell=True) + if pcode != 0: + print("[build_distrib.py] ERROR while uninstall cefpython3" + " package using pip") + sys.exit(1) + + +def run_automate_prebuilt_cef(python): + print("[build_distrib.py] Run automate.py --prebuilt-cef for {arch}" + .format(arch=python["arch"])) + automate = os.path.join(TOOLS_DIR, "automate.py") + command = ("\"{python}\" {automate} --prebuilt-cef" + .format(python=python["executable"], automate=automate)) + code = subprocess.call(command) + if code != 0: + print("[build_distrib.py] ERROR while running automate.py") + sys.exit(1) + + +def pack_prebuilt_cef(arch): + prebuilt_basename = get_cef_binaries_libraries_basename( + get_postfix2_for_arch(arch)) + print("[build_distrib.py] Pack directory: {dir}/ ..." + .format(dir=prebuilt_basename)) + prebuilt_dir = os.path.join(BUILD_DIR, prebuilt_basename) + assert os.path.exists(prebuilt_dir), prebuilt_dir + archive = pack_directory(prebuilt_dir, base_path=BUILD_DIR) + shutil.move(archive, DISTRIB_DIR) + print("[build_distrib.py] Created archive in distrib dir: {archive}" + .format(archive=os.path.basename(archive))) + + +def pack_directory(path, base_path): + if path.endswith(os.path.sep): + path = path[:-1] + ext = ".zip" if WINDOWS or MAC else ".tar.gz" + archive = path + ext + if os.path.exists(archive): + os.remove(archive) + if WINDOWS or MAC: + zip_directory(path, base_path=base_path, archive=archive) + else: + # LINUX + raise Exception("pack_directory(): Linux not yet supported") # TODO + assert os.path.isfile(archive), archive + return archive + + +def zip_directory(path, base_path, archive): + original_dir = os.getcwd() + os.chdir(base_path) + path = path.replace(base_path, "") + if path[0] == os.path.sep: + path = path[1:] + zipf = zipfile.ZipFile(archive, "w", zipfile.ZIP_DEFLATED) + for root, dirs, files in os.walk(path): + for file_ in files: + zipf.write(os.path.join(root, file_)) + zipf.close() + os.chdir(original_dir) + + +def build_cefpython_modules(pythons): + for python in pythons: + print("[build_distrib.py] Build cefpython module for {python_name}" + .format(python_name=python["name"])) + flags = "" + if NO_RUN_EXAMPLES: + flags += " --no-run-examples" + command = ("\"{python}\" {build_py} {version} {flags}" + .format(python=python["executable"], + build_py=os.path.join(TOOLS_DIR, "build.py"), + version=VERSION, + flags=flags)) + # build.py may require sudo if system python, so shell=True + pcode = subprocess.call(command, shell=True) + if pcode != 0: + print("[build_distrib.py] ERROR: failed to build cefpython" + " module for {python_name}" + .format(python_name=python["name"])) + 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") + + +def make_packages(python, arch): + # Make setup package + print("[build_distrib.py] Make setup package for {arch}..." + .format(arch=arch)) + make_installer_py = os.path.join(TOOLS_DIR, "make_installer.py") + installer_command = ("\"{python}\" {make_installer_py} {version}" + .format(python=python["executable"], + make_installer_py=make_installer_py, + version=VERSION)) + pcode = subprocess.call(installer_command, cwd=BUILD_DIR) + if pcode != 0: + print("[build_distrib.py] ERROR: failed to make setup package for" + " {arch}".format(arch=arch)) + sys.exit(1) + + # Pack setup package and move to distrib dir + print("[build_distrib.py] Pack setup package for {arch}..." + .format(arch=arch)) + setup_basename = get_setup_installer_basename( + VERSION, get_postfix2_for_arch(arch)) + setup_dir = os.path.join(BUILD_DIR, setup_basename) + archive = pack_directory(setup_dir, BUILD_DIR) + shutil.move(archive, DISTRIB_DIR) + + # Make wheel package + print("[build_distrib.py] Make wheel package for {arch}..." + .format(arch=arch)) + wheel_args = "bdist_wheel --universal" + wheel_command = ("\"{python}\" setup.py {wheel_args}" + .format(python=python["executable"], + wheel_args=wheel_args)) + pcode = subprocess.call(wheel_command, cwd=setup_dir) + if pcode != 0: + print("[build_distrib.py] ERROR: failed to make wheel package for" + " {arch}".format(arch=arch)) + sys.exit(1) + + # Move wheel package + files = glob.glob(os.path.join(setup_dir, "dist", "*.whl")) + assert len(files) == 1, ".whl file not found" + shutil.move(files[0], DISTRIB_DIR) + + # Delete setup directory + print("[build_distrib.py] Delete setup directory: {setup_dir}/" + .format(setup_dir=os.path.basename(setup_dir))) + shutil.rmtree(setup_dir) + + +def show_summary(pythons_32bit, pythons_64bit): + print("[build_distrib.py] SUMMARY:") + print(" Pythons 32bit ({count})".format(count=len(pythons_32bit))) + for python in pythons_32bit: + print(" {python_name}".format(python_name=python["name"])) + print(" Pythons 64bit ({count})".format(count=len(pythons_64bit))) + for python in pythons_64bit: + print(" {python_name}".format(python_name=python["name"])) + files = glob.glob(os.path.join(DISTRIB_DIR, "*")) + print(" Files in the build/{distrib_basename}/ directory ({count})" + .format(distrib_basename=os.path.basename(DISTRIB_DIR), + count=len(files))) + for file_ in files: + print(" {filename}".format(filename=os.path.basename(file_))) + print("[build_distrib.py] Done. Distribution packages created.") + + +if __name__ == "__main__": + main() diff --git a/tools/common.py b/tools/common.py index 8f63bdd3f..576626f36 100644 --- a/tools/common.py +++ b/tools/common.py @@ -14,7 +14,13 @@ # Architecture and OS postfixes ARCH32 = (8 * struct.calcsize('P') == 32) ARCH64 = (8 * struct.calcsize('P') == 64) -ARCH_STR = "32-bit" if (8 * struct.calcsize('P') == 32) else "64-bit" +# Make sure platform.architecture()[0] shows correctly 32bit when +# running Python 32bit on Windows 64bit. +if ARCH32: + assert platform.architecture()[0] == "32bit" +if ARCH64: + assert platform.architecture()[0] == "64bit" +ARCH_STR = platform.architecture()[0] # OS_POSTFIX is for directories/files names in cefpython sources # OS_POSTFIX2 is for platform name in cefpython binaries # CEF_POSTFIX2 is for platform name in upstream CEF binaries @@ -34,9 +40,16 @@ CEF_POSTFIX2 = "linux32" if ARCH32 else "linux64" # Platforms -WINDOWS = (platform.system() == "Windows") -LINUX = (platform.system() == "Linux") -MAC = (platform.system() == "Darwin") +SYSTEM = platform.system() +WINDOWS = SYSTEM if SYSTEM == "Windows" else False +LINUX = SYSTEM if SYSTEM == "Linux" else False +MAC = SYSTEM if SYSTEM == "Darwin" else False + +OS_POSTFIX2_ARCH = dict( + Windows={"32bit": "win32", "64bit": "win64"}, + Linux={"32bit": "linux32", "64bit": "linux64"}, + Darwin={"32bit": "mac32", "64bit": "mac64"}, +) # Python version eg. 27 PYVERSION = str(sys.version_info[0])+str(sys.version_info[1]) @@ -89,6 +102,9 @@ # Will be overwritten through detect_cefpython_binary_dir() CEFPYTHON_BINARY = "CEFPYTHON_BINARY_NOTSET" +# Distrib directory +DISTRIB_DIR = os.path.join(BUILD_DIR, "DISTRIB_NOTSET") + # Build C++ projects directories BUILD_CEFPYTHON_APP = os.path.join(BUILD_CEFPYTHON, "cefpython_app_py{pyver}_{os}" @@ -165,58 +181,102 @@ os.environ["LOCALAPPDATA"]) -def detect_cef_binaries_libraries_dir(): +def get_postfix2_for_arch(arch): + return OS_POSTFIX2_ARCH[SYSTEM][arch] + + +def _detect_cef_binaries_libraries_dir(): """Detect cef binary directory created by automate.py eg. build/cef55_3.2883.1553.g80bd606_win32/ and set CEF_BINARIES_LIBRARIES to it, otherwise it will point to eg. build/cef_win32/ .""" global CEF_BINARIES_LIBRARIES if not os.path.exists(CEF_BINARIES_LIBRARIES): - version = get_cefpython_version() dirs = glob.glob(os.path.join( BUILD_DIR, - "cef{major}_{cef_version}_{os}{sep}" - .format(major=version["CHROME_VERSION_MAJOR"], - cef_version=version["CEF_VERSION"], - os=OS_POSTFIX2, - sep=os.sep))) + get_cef_binaries_libraries_basename(OS_POSTFIX2))) if len(dirs) == 1: CEF_BINARIES_LIBRARIES = os.path.normpath(dirs[0]) -def detect_cefpython_binary_dir(): - """Detect cefpython binary directory where cefpython modules - will be put. Eg. build/cefpython_56.0_win32/.""" - # Check cef version from header file and check cefpython version - # that was passed as command line argument to either build.py - # or make-installer.py. The CEFPYTHON_BINARY constant should - # only be used in those two scripts, so version number in sys.argv - # is expected. If not found then keep the default - # "CEFPYTHON_BINARY_NOTSET" value intact. +def get_cef_binaries_libraries_basename(postfix2): + version = get_cefpython_version() + return ("cef{major}_{cef_version}_{os}" + .format(major=version["CHROME_VERSION_MAJOR"], + cef_version=version["CEF_VERSION"], + os=postfix2)) + + +def get_cefpython_binary_basename(postfix2, ignore_error=False): cef_version = get_cefpython_version() - cmdline_version = get_version_from_command_line_args() + cmdline_version = get_version_from_command_line_args( + __file__, ignore_error=ignore_error) if not cmdline_version: + if not ignore_error: + raise Exception("Version arg not found in command line args") return # If cef_version is 56 then expect version from command line to # start with "56.". cef_major = cef_version["CHROME_VERSION_MAJOR"] if not cmdline_version.startswith("{major}.".format(major=cef_major)): + if not ignore_error: + raise Exception("cmd line arg major version != Chrome version") return - binary_dir = "cefpython_binary_{version}_{os}".format( + dirname = "cefpython_binary_{version}_{os}".format( version=cmdline_version, - os=OS_POSTFIX2) - binary_dir = os.path.join(BUILD_DIR, binary_dir) + os=postfix2) + return dirname + + +def get_setup_installer_basename(version, postfix2): + setup_basename = ("cefpython3-{version}-{os}-setup" + .format(version=version, os=postfix2)) + return setup_basename + + +def _detect_cefpython_binary_dir(): + """Detect cefpython binary directory where cefpython modules + will be put. Eg. build/cefpython_56.0_win32/.""" + # Check cef version from header file and check cefpython version + # that was passed as command line argument to either build.py + # or make-installer.py. The CEFPYTHON_BINARY constant should + # only be used in those two scripts, so version number in sys.argv + # is expected. If not found then keep the default + # "CEFPYTHON_BINARY_NOTSET" value intact. + dirname = get_cefpython_binary_basename(OS_POSTFIX2, ignore_error=True) + if not dirname: + return + binary_dir = os.path.join(BUILD_DIR, dirname) global CEFPYTHON_BINARY CEFPYTHON_BINARY = binary_dir -def get_version_from_command_line_args(): +def _detect_distrib_dir(): + global DISTRIB_DIR + version = get_version_from_command_line_args(__file__, ignore_error=True) + if version: + # Will only be set when called from scripts that had version + # number arg passed on command line: build.py, build_distrib.py, + # make_installer.py, etc. + dirname = "distrib_{version}".format(version=version) + DISTRIB_DIR = os.path.join(BUILD_DIR, dirname) + + +def get_version_from_command_line_args(caller_script, ignore_error=False): args = " ".join(sys.argv) - match = re.search(r"\b\d+\.\d+\b", args) + match = re.search(r"\b(\d+)\.\d+\b", args) if match: version = match.group(0) + major = match.group(1) + cef_version = get_cefpython_version() + if major != cef_version["CHROME_VERSION_MAJOR"]: + if ignore_error: + return "" + print("[{script}] ERROR: cmd arg major version != Chrome version" + .format(script=os.path.basename(caller_script))) + sys.exit(1) return version - return "" + return def get_cefpython_version(): @@ -252,5 +312,6 @@ def get_msvs_for_python(vs_prefix=False): sys.exit(1) -detect_cef_binaries_libraries_dir() -detect_cefpython_binary_dir() +_detect_cef_binaries_libraries_dir() +_detect_cefpython_binary_dir() +_detect_distrib_dir() diff --git a/tools/make_installer.py b/tools/make_installer.py index d13b7155d..518b62cc2 100644 --- a/tools/make_installer.py +++ b/tools/make_installer.py @@ -45,8 +45,7 @@ def main(): # Setup and package directories global SETUP_DIR, PKG_DIR - setup_dir_name = ("cefpython3-{version}-{os}-setup" - .format(version=VERSION, os=OS_POSTFIX2)) + setup_dir_name = get_setup_installer_basename(VERSION, OS_POSTFIX2) SETUP_DIR = os.path.join(BUILD_DIR, setup_dir_name) PKG_DIR = os.path.join(SETUP_DIR, "cefpython3") @@ -93,7 +92,7 @@ def main(): create_empty_log_file(os.path.join(PKG_DIR, "debug.log")) create_empty_log_file(os.path.join(PKG_DIR, "examples/debug.log")) - print("[make_installer.py] DONE. Installer package created: {setup_dir}" + print("[make_installer.py] Done. Installer package created: {setup_dir}" .format(setup_dir=SETUP_DIR)) # Optional generation of wheel package @@ -112,13 +111,13 @@ def main(): dist_dir = os.path.join(SETUP_DIR, "dist") files = glob.glob(os.path.join(dist_dir, "*.whl")) assert len(files) == 1 - print("[make_installer.py] DONE. Wheel package created: {0}" + print("[make_installer.py] Done. Wheel package created: {0}" .format(files[0])) def command_line_args(): global VERSION, WHEEL, WHEEL_ARGS - VERSION = get_version_from_command_line_args() + VERSION = get_version_from_command_line_args(__file__) if not VERSION: print(__doc__) sys.exit(1) From 4a9c639ee33f3e073d6ebd1f85fabf1f2bfe4f21 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 11 Mar 2017 17:41:34 +0100 Subject: [PATCH 162/557] Update README - Windows now supports Python 3 and 64-bit. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 27067efc1..ad3afd0fe 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ bots. 1. Can be installed on all platforms using `pip install cefpython3` command 2. Downloads are available on [GitHub Releases](../../releases) pages -2. Windows support: 32-bit, Python 2.7 +2. Windows support: 32-bit and 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 (requirements: Windows 7+) 3. Linux support: 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 (requirements: Debian 7+ / Ubuntu 12.04+) From 8664386f67366e79be8c32aecf2bc2d02fb59ee3 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 11 Mar 2017 18:32:57 +0100 Subject: [PATCH 163/557] Fix platform tag in wheel package on Windows 64-bit --- tools/build_distrib.py | 7 +++++++ tools/common.py | 5 +++++ tools/installer/cefpython3.setup.py | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/tools/build_distrib.py b/tools/build_distrib.py index 84c661d89..8368b63cd 100644 --- a/tools/build_distrib.py +++ b/tools/build_distrib.py @@ -6,6 +6,7 @@ Build distribution packages for all architectures and all supported python versions. +TODO: test_wheel_package_installation() TODO: Linux/Mac support. Currently runs only on Windows. Usage: @@ -89,6 +90,7 @@ def main(): make_packages(pythons_32bit[0], "32bit") if pythons_64bit: make_packages(pythons_64bit[0], "64bit") + test_wheel_package_installation() show_summary(pythons_32bit, pythons_64bit) @@ -415,6 +417,11 @@ def make_packages(python, arch): shutil.rmtree(setup_dir) +def test_wheel_package_installation(): + # PYPI_POSTFIX2_ARCH + pass # TODO + + def show_summary(pythons_32bit, pythons_64bit): print("[build_distrib.py] SUMMARY:") print(" Pythons 32bit ({count})".format(count=len(pythons_32bit))) diff --git a/tools/common.py b/tools/common.py index 576626f36..2b3d595fa 100644 --- a/tools/common.py +++ b/tools/common.py @@ -50,6 +50,11 @@ Linux={"32bit": "linux32", "64bit": "linux64"}, Darwin={"32bit": "mac32", "64bit": "mac64"}, ) +PYPI_POSTFIX2_ARCH = dict( + Windows={"32bit": "win32", "64bit": "win-amd64"}, + Linux={"32bit": "i686", "64bit": "x86_64"}, + Darwin={"64bit": "x86_64"}, +) # Python version eg. 27 PYVERSION = str(sys.version_info[0])+str(sys.version_info[1]) diff --git a/tools/installer/cefpython3.setup.py b/tools/installer/cefpython3.setup.py index 7cc55356e..3458e09a1 100644 --- a/tools/installer/cefpython3.setup.py +++ b/tools/installer/cefpython3.setup.py @@ -81,11 +81,11 @@ class custom_bdist_wheel(bdist_wheel): def get_tag(self): tag = bdist_wheel.get_tag(self) platform_tag = sysconfig.get_platform() + platform_tag = platform_tag.replace("-", "_") if platform.system() == "Linux": assert "linux" in platform_tag # "linux-x86_64" replace with "manylinux1_x86_64" platform_tag = platform_tag.replace("linux", "manylinux1") - platform_tag = platform_tag.replace("-", "_") elif platform.system() == "Darwin": # For explanation of Mac platform tags, see: # http://lepture.com/en/2014/python-on-a-hard-wheel From 26d64ba3d15b79e1a81937c7af493cb1dbabfeb1 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 11 Mar 2017 23:19:46 +0100 Subject: [PATCH 164/557] Update README, minor changes in description --- README.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ad3afd0fe..9b1fe314d 100644 --- a/README.md +++ b/README.md @@ -12,20 +12,23 @@ Table of contents: ## Introduction -CEF Python is an open source project founded by [Czarek Tomczak] -(http://www.linkedin.com/in/czarektomczak) -in 2012 to provide python bindings for the [Chromium Embedded Framework] -(https://bitbucket.org/chromiumembedded/cef). -See the growing list of [applications using CEF] +CEF Python is a BSD-licensed open source project founded by [Czarek Tomczak] +(http://www.linkedin.com/in/czarektomczak) in 2012 and is based on +Google Chromium and the [CEF Framework] +(https://bitbucket.org/chromiumembedded/cef) projects. The Chromium +project focuses mainly on Google Chrome application development, while +CEF focuses on facilitating embedded browser use cases in third-party +applications. Lots of applications use CEF control, there are more than +[100 million CEF instances] (http://en.wikipedia.org/wiki/Chromium_Embedded_Framework#Applications_using_CEF) -on wikipedia. Examples of embedding CEF browser are available for many -popular GUI toolkits including: wxPython, PyGTK, PyQt, PySide, Kivy, -Panda3D, PyWin32 and PyGame/PyOpenGL. +installed around the world. Examples of embedding Chrome browser are +available for many popular GUI toolkits including: wxPython, PyGTK, +PyQt, PySide, Kivy, Panda3D and PyGame/PyOpenGL. 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 like wxWidgets, Qt or GTK. You can render web +standard GUI toolkits such as wxWidgets, Qt or GTK. You can render web content off-screen in application that use custom drawing frameworks. You can use it for automated testing of existing applications. You can use it for web scraping or as a web crawler, or other kind of internet From 4d2b05ef74defd8efc18ae4b68aaa308964039f8 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sun, 12 Mar 2017 09:50:56 +0100 Subject: [PATCH 165/557] Create Examples-README.md --- README.md | 6 ++--- docs/Examples.md | 4 ++++ examples/Examples-README.md | 48 +++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 docs/Examples.md create mode 100644 examples/Examples-README.md diff --git a/README.md b/README.md index 9b1fe314d..7ebe356fb 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,9 @@ CEF focuses on facilitating embedded browser use cases in third-party applications. Lots of applications use CEF control, there are more than [100 million CEF instances] (http://en.wikipedia.org/wiki/Chromium_Embedded_Framework#Applications_using_CEF) -installed around the world. Examples of embedding Chrome browser are -available for many popular GUI toolkits including: wxPython, PyGTK, -PyQt, PySide, Kivy, Panda3D and PyGame/PyOpenGL. +installed around the world. [Examples of embedding](examples/Examples-README.md) +Chrome browser are available for many popular GUI toolkits including: +wxPython, PyGTK, PyQt, PySide, Kivy, Panda3D and PyGame/PyOpenGL. 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 diff --git a/docs/Examples.md b/docs/Examples.md new file mode 100644 index 000000000..aa2af612e --- /dev/null +++ b/docs/Examples.md @@ -0,0 +1,4 @@ +# Examples + +Examples are available in the examples/ root directory. See +[Examples-README.md](../examples/Examples-README.md). diff --git a/examples/Examples-README.md b/examples/Examples-README.md new file mode 100644 index 000000000..1257bd7cd --- /dev/null +++ b/examples/Examples-README.md @@ -0,0 +1,48 @@ +# Examples + +Table of contents: +* [Supported examples](#supported-examples) +* [More examples](#more-examples) + + +## Supported examples + +Examples provided in the examples/ root directory are actively +maintained: + +- [gtk2.py](gtk2.py): example for [PyGTK](http://www.pygtk.org/) + library (GTK 2) +- [gtk3.py](gtk3.py): example for [PyGObject/PyGI] + (https://wiki.gnome.org/Projects/PyGObject) library (GTK 3). + Currently broken on Linux/Mac, see top comments in sources. +- [hello_world.py](hello_world.py): doesn't require any third party + GUI framework +- [qt4.py](qt4.py): example for [PyQt4](https://wiki.python.org/moin/PyQt4) + and [PySide](https://wiki.qt.io/PySide) libraries (Qt 4) +- [tkinter_.py](tkinter_.py): example for [Tkinter] + (https://wiki.python.org/moin/TkInter). Currently broken on Mac. +- [wxpython.py](wxpython.py): example for wxPython + +If there are any issues in examples read top comments in sources +to see whether this is a known issue with available workarounds. + + +## More examples + +There are even more examples available, some of them are externally +maintained. + +- Kivy framework: + see [Kivy](https://github.com/cztomczak/cefpython/wiki/Kivy) wiki page. +- Panda3D game engine: + see [Panda3D](https://github.com/cztomczak/cefpython/wiki/Panda3D) wiki page. +- PyGame/PyOpenGL: + see [gist by AnishN](https://gist.github.com/AnishN/aa3bb27fc9d69319955ed9a8973cd40f) +- Screenshot example: + see [gist by stefanbacon](https://gist.github.com/stefanbacon/7b1571d57aee54aa9f8e9021b4848d06) +- Old PyWin32 example: + see [pywin32.py](https://github.com/cztomczak/cefpython/blob/cefpython31/cefpython/cef3/windows/binaries_32bit/pywin32.py) + in the cefpython31 branch + +There are ongoing efforts to add these examples to the official examples/ +directory, see issues in the tracker. From 8d53d65fbc721b9140af1030c3ce458b3e9e64df Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sun, 12 Mar 2017 10:32:36 +0100 Subject: [PATCH 166/557] Update docs --- README.md | 6 ++++-- docs/API.md | 2 +- examples/Examples-README.md | 2 +- tools/build_cpp_projects.py | 6 ++++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7ebe356fb..af22e2053 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,10 @@ wxPython, PyGTK, PyQt, PySide, Kivy, Panda3D and PyGame/PyOpenGL. 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. You can render web -content off-screen in application that use custom drawing frameworks. +standard GUI toolkits such as wxWidgets, Qt or GTK. In such case to +communicate between Python<>Javascript use javascript bindings or +embed an internal web server and talk using http requests. You can render +web content off-screen in application that use custom drawing frameworks. You can use it for automated testing of existing applications. You can use it for web scraping or as a web crawler, or other kind of internet bots. diff --git a/docs/API.md b/docs/API.md index 720df3f57..35ea01ea0 100644 --- a/docs/API.md +++ b/docs/API.md @@ -1,3 +1,3 @@ # API -API reference is available in the [api/](../api) root directory. +API reference is available in the [api/ root directory](../api). diff --git a/examples/Examples-README.md b/examples/Examples-README.md index 1257bd7cd..b1b4109bd 100644 --- a/examples/Examples-README.md +++ b/examples/Examples-README.md @@ -1,4 +1,4 @@ -# Examples +# Examples README Table of contents: * [Supported examples](#supported-examples) diff --git a/tools/build_cpp_projects.py b/tools/build_cpp_projects.py index f7eae2a84..8bb6bf335 100644 --- a/tools/build_cpp_projects.py +++ b/tools/build_cpp_projects.py @@ -2,8 +2,10 @@ # All rights reserved. Licensed under BSD 3-clause license. # Project website: https://github.com/cztomczak/cefpython -"""Build C++ projects. This tool is executed by build.py on Windows -only currently. Output directories are in build/build_cefpython/. +"""Called by build.py internally. Builds C++ projects using +distutils/setuptools compilers. This tool is executed by build.py +on Windows only currently. Output directories are in +build/build_cefpython/. Usage: build_cpp_projects.py [--force] From cc227fdbfad8b04914a0cdba61d41188a556868a Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sun, 12 Mar 2017 14:01:34 +0100 Subject: [PATCH 167/557] Update README with quick links to docs (#326)... Update apidocs.py tool to add API reference links also to README. --- .github/CONTRIBUTING.md | 11 +- .github/ISSUE_TEMPLATE.md | 12 +- README.md | 531 +++++++++++++++++++++++++++++++++++--- api/API-index.md | 1 + tools/apidocs.py | 90 +++++-- tools/common.py | 3 + 6 files changed, 574 insertions(+), 74 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index f4f8ab2a5..dcb75da2e 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,4 +1,7 @@ -Please read this: -1. Do not create Issues to report problems and/or ask questions. Use the Forum for that. -2. Before creating an Issue it must first be discussed and confirmed on the Forum. -3. Always use the Forum: https://goo.gl/xz4cEF +Please do not create Issues. Issues must first be discussed +and confirmed on the Forum. Report issues on the Forum here: + +https://goo.gl/xz4cEF + +Please do not ask questions in existing issues. Ask questions +on the Forum, link above. diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index f4f8ab2a5..2bf4f13a8 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,4 +1,8 @@ -Please read this: -1. Do not create Issues to report problems and/or ask questions. Use the Forum for that. -2. Before creating an Issue it must first be discussed and confirmed on the Forum. -3. Always use the Forum: https://goo.gl/xz4cEF +Please do not create Issues using this form. Issues must +first be discussed and confirmed on the Forum. Report issues +on the Forum here: + +https://goo.gl/xz4cEF + +Please do not ask questions in existing issues. Ask questions +on the Forum, link above. diff --git a/README.md b/README.md index af22e2053..44d7979ea 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,15 @@ Table of contents: * [Introduction](#introduction) -* [Versions](#versions) +* [Support](#support) +* [Releases](#releases) * [v50+ releases](#v50-releases) * [v31 release](#v31-release) -* [Support](#support) * [Support development](#support-development) * [Thanks](#thanks) +* [Quick links](#quick-links) + * [Docs](#docs) + * [API reference](#api-reference) ## Introduction @@ -29,53 +32,53 @@ 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 or -embed an internal web server and talk using http requests. You can render -web content off-screen in application that use custom drawing frameworks. -You can use it for automated testing of existing applications. You can -use it for web scraping or as a web crawler, or other kind of internet -bots. +communicate between Python<>Javascript use [javascript bindings] +(api/JavascriptBindings.md) 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 applications. You can use it for web +scraping or as a web crawler, or other kind of internet bots. -## Versions - -### v50+ releases - -1. Can be installed on all platforms using `pip install cefpython3` command -2. Downloads are available on [GitHub Releases](../../releases) pages -2. Windows support: 32-bit and 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 - (requirements: Windows 7+) -3. Linux support: 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 - (requirements: Debian 7+ / Ubuntu 12.04+) -4. Mac support: 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 - (requirements: MacOS 10.9+) -5. Documentation is in the [docs/](docs) directory -6. API reference is in the [api/](api) directory -7. Additional documentation is in issues labelled [Knowledge Base] - (../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) +## Support -### v31 release +- Ask questions, report problems and issues on the [Forum] + (https://groups.google.com/group/cefpython) +- Documentation is in the [docs/](docs) directory +- API reference is in the [api/](api) directory +- Additional documentation is in issues labelled [Knowledge Base] + (../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) +- Wiki pages are deprecated and for v31 only -1. Downloads are available on [wiki pages](../../wiki#downloads) - and on GH Releases tagged [v31.2](../../releases/tag/v31.2) -2. Supports only Python 2.7 -3. Windows support: 32-bit and 64-bit (requirements: Windows XP+) -4. Linux support: 32-bit and 64-bit (requirements: Debian 7+ / Ubuntu 12.04+) -5. Mac support: 32-bit and 64-bit (requirements: MacOS 10.7+) -6. Documentation is on [wiki pages](../../wiki) -7. API reference is available in revision [169a1b2] - (../../tree/169a1b20d3cd09879070d41aab28cfa195d2a7d5/docs/api) +## Releases -## Support +### v50+ releases -- Ask questions and report problems on the [Forum] - (https://groups.google.com/group/cefpython) +- Can be installed on all platforms using `pip install cefpython3` command +- Downloads are available on [GitHub Releases](../../releases) pages +- Windows support: 32-bit and 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 + (requirements: Windows 7+) +- Linux support: 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 + (requirements: Debian 7+ / Ubuntu 12.04+) +- Mac support: 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 + (requirements: MacOS 10.9+) - Documentation is in the [docs/](docs) directory - API reference is in the [api/](api) directory - Additional documentation is in issues labelled [Knowledge Base] (../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) -- Wiki pages are deprecated and for v31 only + +### v31 release + +- Downloads are available on [wiki pages](../../wiki#downloads) + and on GH Releases tagged [v31.2](../../releases/tag/v31.2) +- Supports only Python 2.7 +- Windows support: 32-bit and 64-bit (requirements: Windows XP+) +- Linux support: 32-bit and 64-bit (requirements: Debian 7+ / Ubuntu 12.04+) +- Mac support: 32-bit and 64-bit (requirements: MacOS 10.7+) +- Documentation is on [wiki pages](../../wiki) +- API reference is available in revision [169a1b2] + (../../tree/169a1b20d3cd09879070d41aab28cfa195d2a7d5/docs/api) ## Support development @@ -114,3 +117,455 @@ directly. development of the off-screen rendering support * Thanks to Thomas Wusatiuk for sponsoring the development of the web response reading features + + +## Quick links + +### Docs + +- [Build instructions](docs/Build-instructions.md) +- [Knowledge Base](docs/Knowledge-Base.md) +- [Migration guide](docs/Migration-guide.md) +- [Tutorial](docs/Tutorial.md) + +### API reference + +* [Application settings](api/ApplicationSettings.md#application-settings) + * [accept_language_list](api/ApplicationSettings.md#accept_language_list) + * [auto_zooming](api/ApplicationSettings.md#auto_zooming) + * [background_color](api/ApplicationSettings.md#background_color) + * [browser_subprocess_path](api/ApplicationSettings.md#browser_subprocess_path) + * [cache_path](api/ApplicationSettings.md#cache_path) + * [command_line_args_disabled](api/ApplicationSettings.md#command_line_args_disabled) + * [context_menu](api/ApplicationSettings.md#context_menu) + * [downloads_enabled](api/ApplicationSettings.md#downloads_enabled) + * [external_message_pump](api/ApplicationSettings.md#external_message_pump) + * [framework_dir_path](api/ApplicationSettings.md#framework_dir_path) + * [ignore_certificate_errors](api/ApplicationSettings.md#ignore_certificate_errors) + * [javascript_flags](api/ApplicationSettings.md#javascript_flags) + * [locale](api/ApplicationSettings.md#locale) + * [locales_dir_path](api/ApplicationSettings.md#locales_dir_path) + * [debug](api/ApplicationSettings.md#debug) + * [log_file](api/ApplicationSettings.md#log_file) + * [log_severity](api/ApplicationSettings.md#log_severity) + * [multi_threaded_message_loop](api/ApplicationSettings.md#multi_threaded_message_loop) + * [net_security_expiration_enabled](api/ApplicationSettings.md#net_security_expiration_enabled) + * [pack_loading_disabled](api/ApplicationSettings.md#pack_loading_disabled) + * [persist_session_cookies](api/ApplicationSettings.md#persist_session_cookies) + * [persist_user_preferences](api/ApplicationSettings.md#persist_user_preferences) + * [product_version](api/ApplicationSettings.md#product_version) + * [remote_debugging_port](api/ApplicationSettings.md#remote_debugging_port) + * [resources_dir_path](api/ApplicationSettings.md#resources_dir_path) + * [single_process](api/ApplicationSettings.md#single_process) + * [string_encoding](api/ApplicationSettings.md#string_encoding) + * [uncaught_exception_stack_size](api/ApplicationSettings.md#uncaught_exception_stack_size) + * [unique_request_context_per_browser](api/ApplicationSettings.md#unique_request_context_per_browser) + * [user_agent](api/ApplicationSettings.md#user_agent) + * [user_data_path](api/ApplicationSettings.md#user_data_path) + * [windowless_rendering_enabled](api/ApplicationSettings.md#windowless_rendering_enabled) +* [Browser (object)](api/Browser.md#browser-object) + * [AddWordToDictionary](api/Browser.md#addwordtodictionary) + * [CanGoBack](api/Browser.md#cangoback) + * [CanGoForward](api/Browser.md#cangoforward) + * [CloseBrowser](api/Browser.md#closebrowser) + * [CloseDevTools](api/Browser.md#closedevtools) + * [DragTargetDragEnter](api/Browser.md#dragtargetdragenter) + * [DragTargetDragOver](api/Browser.md#dragtargetdragover) + * [DragTargetDragLeave](api/Browser.md#dragtargetdragleave) + * [DragTargetDrop](api/Browser.md#dragtargetdrop) + * [DragSourceEndedAt](api/Browser.md#dragsourceendedat) + * [DragSourceSystemDragEnded](api/Browser.md#dragsourcesystemdragended) + * [ExecuteFunction](api/Browser.md#executefunction) + * [ExecuteJavascript](api/Browser.md#executejavascript) + * [Find](api/Browser.md#find) + * [GetClientCallback](api/Browser.md#getclientcallback) + * [GetClientCallbacksDict](api/Browser.md#getclientcallbacksdict) + * [GetFocusedFrame](api/Browser.md#getfocusedframe) + * [GetFrame](api/Browser.md#getframe) + * [GetFrameByIdentifier](api/Browser.md#getframebyidentifier) + * [GetFrames](api/Browser.md#getframes) + * [GetFrameCount](api/Browser.md#getframecount) + * [GetFrameIdentifiers](api/Browser.md#getframeidentifiers) + * [GetFrameNames](api/Browser.md#getframenames) + * [GetJavascriptBindings](api/Browser.md#getjavascriptbindings) + * [GetMainFrame](api/Browser.md#getmainframe) + * [GetNSTextInputContext](api/Browser.md#getnstextinputcontext) + * [GetOpenerWindowHandle](api/Browser.md#getopenerwindowhandle) + * [GetOuterWindowHandle](api/Browser.md#getouterwindowhandle) + * [GetUrl](api/Browser.md#geturl) + * [GetUserData](api/Browser.md#getuserdata) + * [GetWindowHandle](api/Browser.md#getwindowhandle) + * [GetIdentifier](api/Browser.md#getidentifier) + * [GetZoomLevel](api/Browser.md#getzoomlevel) + * [GoBack](api/Browser.md#goback) + * [GoForward](api/Browser.md#goforward) + * [HandleKeyEventAfterTextInputClient](api/Browser.md#handlekeyeventaftertextinputclient) + * [HandleKeyEventBeforeTextInputClient](api/Browser.md#handlekeyeventbeforetextinputclient) + * [HasDocument](api/Browser.md#hasdocument) + * [IsFullscreen](api/Browser.md#isfullscreen) + * [IsLoading](api/Browser.md#isloading) + * [IsMouseCursorChangeDisabled](api/Browser.md#ismousecursorchangedisabled) + * [IsPopup](api/Browser.md#ispopup) + * [IsWindowRenderingDisabled](api/Browser.md#iswindowrenderingdisabled) + * [LoadUrl](api/Browser.md#loadurl) + * [Navigate](api/Browser.md#navigate) + * [NotifyMoveOrResizeStarted](api/Browser.md#notifymoveorresizestarted) + * [NotifyScreenInfoChanged](api/Browser.md#notifyscreeninfochanged) + * [ParentWindowWillClose](api/Browser.md#parentwindowwillclose) + * [Reload](api/Browser.md#reload) + * [ReloadIgnoreCache](api/Browser.md#reloadignorecache) + * [ReplaceMisspelling](api/Browser.md#replacemisspelling) + * [SetBounds](api/Browser.md#setbounds) + * [SendKeyEvent](api/Browser.md#sendkeyevent) + * [SendMouseClickEvent](api/Browser.md#sendmouseclickevent) + * [SendMouseMoveEvent](api/Browser.md#sendmousemoveevent) + * [SendMouseWheelEvent](api/Browser.md#sendmousewheelevent) + * [SendFocusEvent](api/Browser.md#sendfocusevent) + * [SendCaptureLostEvent](api/Browser.md#sendcapturelostevent) + * [SetClientCallback](api/Browser.md#setclientcallback) + * [SetClientHandler](api/Browser.md#setclienthandler) + * [SetFocus](api/Browser.md#setfocus) + * [SetMouseCursorChangeDisabled](api/Browser.md#setmousecursorchangedisabled) + * [SetJavascriptBindings](api/Browser.md#setjavascriptbindings) + * [SetUserData](api/Browser.md#setuserdata) + * [SetZoomLevel](api/Browser.md#setzoomlevel) + * [ShowDevTools](api/Browser.md#showdevtools) + * [StartDownload](api/Browser.md#startdownload) + * [StopLoad](api/Browser.md#stopload) + * [StopFinding](api/Browser.md#stopfinding) + * [ToggleFullscreen](api/Browser.md#togglefullscreen) + * [TryCloseBrowser](api/Browser.md#tryclosebrowser) + * [WasResized](api/Browser.md#wasresized) + * [WasHidden](api/Browser.md#washidden) +* [Browser settings](api/BrowserSettings.md#browser-settings) + * [Font settings](api/BrowserSettings.md#font-settings) + * [accept_language_list](api/BrowserSettings.md#accept_language_list) + * [application_cache_disabled](api/BrowserSettings.md#application_cache_disabled) + * [background_color](api/BrowserSettings.md#background_color) + * [databases_disabled](api/BrowserSettings.md#databases_disabled) + * [default_encoding](api/BrowserSettings.md#default_encoding) + * [dom_paste_disabled](api/BrowserSettings.md#dom_paste_disabled) + * [file_access_from_file_urls_allowed](api/BrowserSettings.md#file_access_from_file_urls_allowed) + * [image_load_disabled](api/BrowserSettings.md#image_load_disabled) + * [javascript_disabled](api/BrowserSettings.md#javascript_disabled) + * [javascript_open_windows_disallowed](api/BrowserSettings.md#javascript_open_windows_disallowed) + * [javascript_close_windows_disallowed](api/BrowserSettings.md#javascript_close_windows_disallowed) + * [javascript_access_clipboard_disallowed](api/BrowserSettings.md#javascript_access_clipboard_disallowed) + * [local_storage_disabled](api/BrowserSettings.md#local_storage_disabled) + * [plugins_disabled](api/BrowserSettings.md#plugins_disabled) + * [remote_fonts](api/BrowserSettings.md#remote_fonts) + * [shrink_standalone_images_to_fit](api/BrowserSettings.md#shrink_standalone_images_to_fit) + * [tab_to_links_disabled](api/BrowserSettings.md#tab_to_links_disabled) + * [text_area_resize_disabled](api/BrowserSettings.md#text_area_resize_disabled) + * [universal_access_from_file_urls_allowed](api/BrowserSettings.md#universal_access_from_file_urls_allowed) + * [user_style_sheet_location](api/BrowserSettings.md#user_style_sheet_location) + * [web_security_disabled](api/BrowserSettings.md#web_security_disabled) + * [webgl_disabled](api/BrowserSettings.md#webgl_disabled) + * [windowless_frame_rate](api/BrowserSettings.md#windowless_frame_rate) +* [Callback (object)](api/Callback.md#callback-object) + * [Continue](api/Callback.md#continue) + * [Cancel](api/Callback.md#cancel) +* [cefpython](api/cefpython.md#cefpython) + * [CreateBrowser](api/cefpython.md#createbrowser) + * [CreateBrowserSync](api/cefpython.md#createbrowsersync) + * [ExceptHook](api/cefpython.md#excepthook) + * [GetAppSetting](api/cefpython.md#getappsetting) + * [GetAppPath](api/cefpython.md#getapppath) + * [GetBrowserByWindowHandle](api/cefpython.md#getbrowserbywindowhandle) + * [GetCommandLineSwitch](api/cefpython.md#getcommandlineswitch) + * [GetGlobalClientCallback](api/cefpython.md#getglobalclientcallback) + * [GetModuleDirectory](api/cefpython.md#getmoduledirectory) + * [GetVersion](api/cefpython.md#getversion) + * [Initialize](api/cefpython.md#initialize) + * [IsThread](api/cefpython.md#isthread) + * [MessageLoop](api/cefpython.md#messageloop) + * [MessageLoopWork](api/cefpython.md#messageloopwork) + * [PostTask](api/cefpython.md#posttask) + * [QuitMessageLoop](api/cefpython.md#quitmessageloop) + * [SetGlobalClientCallback](api/cefpython.md#setglobalclientcallback) + * [SetOsModalLoop](api/cefpython.md#setosmodalloop) + * [Shutdown](api/cefpython.md#shutdown) +* [Command line switches](api/CommandLineSwitches.md#command-line-switches) + * [enable-media-stream](api/CommandLineSwitches.md#enable-media-stream) + * [proxy-server](api/CommandLineSwitches.md#proxy-server) + * [no-proxy-server](api/CommandLineSwitches.md#no-proxy-server) + * [disable-gpu](api/CommandLineSwitches.md#disable-gpu) +* [Cookie (class)](api/Cookie.md#cookie-class) + * [Set](api/Cookie.md#set) + * [Get](api/Cookie.md#get) + * [SetName](api/Cookie.md#setname) + * [GetName](api/Cookie.md#getname) + * [SetValue](api/Cookie.md#setvalue) + * [GetValue](api/Cookie.md#getvalue) + * [SetDomain](api/Cookie.md#setdomain) + * [GetDomain](api/Cookie.md#getdomain) + * [SetPath](api/Cookie.md#setpath) + * [GetPath](api/Cookie.md#getpath) + * [SetSecure](api/Cookie.md#setsecure) + * [GetSecure](api/Cookie.md#getsecure) + * [SetHttpOnly](api/Cookie.md#sethttponly) + * [GetHttpOnly](api/Cookie.md#gethttponly) + * [SetCreation](api/Cookie.md#setcreation) + * [GetCreation](api/Cookie.md#getcreation) + * [SetLastAccess](api/Cookie.md#setlastaccess) + * [GetLastAccess](api/Cookie.md#getlastaccess) + * [SetHasExpires](api/Cookie.md#sethasexpires) + * [GetHasExpires](api/Cookie.md#gethasexpires) + * [SetExpires](api/Cookie.md#setexpires) + * [GetExpires](api/Cookie.md#getexpires) +* [CookieManager (class)](api/CookieManager.md#cookiemanager-class) + * [GetGlobalManager](api/CookieManager.md#getglobalmanager) + * [CreateManager](api/CookieManager.md#createmanager) + * [SetSupportedSchemes](api/CookieManager.md#setsupportedschemes) + * [VisitAllCookies](api/CookieManager.md#visitallcookies) + * [VisitUrlCookies](api/CookieManager.md#visiturlcookies) + * [SetCookie](api/CookieManager.md#setcookie) + * [DeleteCookies](api/CookieManager.md#deletecookies) + * [SetStoragePath](api/CookieManager.md#setstoragepath) + * [FlushStore](api/CookieManager.md#flushstore) +* [CookieVisitor (interface)](api/CookieVisitor.md#cookievisitor-interface) + * [Visit](api/CookieVisitor.md#visit) +* [DisplayHandler (interface)](api/DisplayHandler.md#displayhandler-interface) + * [OnAddressChange](api/DisplayHandler.md#onaddresschange) + * [OnTitleChange](api/DisplayHandler.md#ontitlechange) + * [OnTooltip](api/DisplayHandler.md#ontooltip) + * [OnStatusMessage](api/DisplayHandler.md#onstatusmessage) + * [OnConsoleMessage](api/DisplayHandler.md#onconsolemessage) +* [DownloadHandler](api/DownloadHandler.md#downloadhandler) +* [DpiAware (class)](api/DpiAware.md#dpiaware-class) + * [CalculateWindowSize](api/DpiAware.md#calculatewindowsize) + * [GetSystemDpi](api/DpiAware.md#getsystemdpi) + * [IsProcessDpiAware](api/DpiAware.md#isprocessdpiaware) + * [SetProcessDpiAware](api/DpiAware.md#setprocessdpiaware) +* [DragData (object)](api/DragData.md#dragdata-object) + * [IsLink](api/DragData.md#islink) + * [IsFragment](api/DragData.md#isfragment) + * [GetLinkUrl](api/DragData.md#getlinkurl) + * [GetLinkTitle](api/DragData.md#getlinktitle) + * [GetFragmentText](api/DragData.md#getfragmenttext) + * [GetFragmentHtml](api/DragData.md#getfragmenthtml) + * [GetImage](api/DragData.md#getimage) + * [HasImage](api/DragData.md#hasimage) +* [FocusHandler (interface)](api/FocusHandler.md#focushandler-interface) + * [OnTakeFocus](api/FocusHandler.md#ontakefocus) + * [OnSetFocus](api/FocusHandler.md#onsetfocus) + * [OnGotFocus](api/FocusHandler.md#ongotfocus) +* [Frame (object)](api/Frame.md#frame-object) + * [Copy](api/Frame.md#copy) + * [Cut](api/Frame.md#cut) + * [Delete](api/Frame.md#delete) + * [ExecuteFunction](api/Frame.md#executefunction) + * [ExecuteJavascript](api/Frame.md#executejavascript) + * [GetBrowser](api/Frame.md#getbrowser) + * [GetParent](api/Frame.md#getparent) + * [GetIdentifier](api/Frame.md#getidentifier) + * [GetBrowserIdentifier](api/Frame.md#getbrowseridentifier) + * [GetName](api/Frame.md#getname) + * [GetParent](api/Frame.md#getparent) + * [GetProperty](api/Frame.md#getproperty) + * [GetSource](api/Frame.md#getsource) + * [GetText](api/Frame.md#gettext) + * [GetUrl](api/Frame.md#geturl) + * [IsFocused](api/Frame.md#isfocused) + * [IsMain](api/Frame.md#ismain) + * [IsValid](api/Frame.md#isvalid) + * [LoadString](api/Frame.md#loadstring) + * [LoadUrl](api/Frame.md#loadurl) + * [Paste](api/Frame.md#paste) + * [Redo](api/Frame.md#redo) + * [SelectAll](api/Frame.md#selectall) + * [SetProperty](api/Frame.md#setproperty) + * [Undo](api/Frame.md#undo) + * [ViewSource](api/Frame.md#viewsource) +* [Image (object)](api/Image.md#image-object) + * [GetAsBitmap](api/Image.md#getasbitmap) + * [GetAsPng](api/Image.md#getaspng) + * [GetHeight](api/Image.md#getheight) + * [GetWidth](api/Image.md#getwidth) +* [JavascriptBindings (class)](api/JavascriptBindings.md#javascriptbindings-class) + * [\_\_init\_\_](api/JavascriptBindings.md#__init__) + * [IsValueAllowed](api/JavascriptBindings.md#isvalueallowed) + * [Rebind](api/JavascriptBindings.md#rebind) + * [SetFunction](api/JavascriptBindings.md#setfunction) + * [SetObject](api/JavascriptBindings.md#setobject) + * [SetProperty](api/JavascriptBindings.md#setproperty) +* [JavascriptCallback (object)](api/JavascriptCallback.md#javascriptcallback-object) + * [Call](api/JavascriptCallback.md#call) + * [GetName](api/JavascriptCallback.md#getname) +* [JavascriptDialogHandler (interface)](api/JavascriptDialogHandler.md#javascriptdialoghandler-interface) + * [Continue](api/JavascriptDialogHandler.md#continue) + * [OnJavascriptDialog](api/JavascriptDialogHandler.md#onjavascriptdialog) + * [OnBeforeUnloadJavascriptDialog](api/JavascriptDialogHandler.md#onbeforeunloadjavascriptdialog) + * [OnResetJavascriptDialogState](api/JavascriptDialogHandler.md#onresetjavascriptdialogstate) + * [OnJavascriptDialogClosed](api/JavascriptDialogHandler.md#onjavascriptdialogclosed) +* [KeyboardHandler (interface)](api/KeyboardHandler.md#keyboardhandler-interface) + * [OnPreKeyEvent](api/KeyboardHandler.md#onprekeyevent) + * [OnKeyEvent](api/KeyboardHandler.md#onkeyevent) +* [LifespanHandler (interface)](api/LifespanHandler.md#lifespanhandler-interface) + * [OnBeforePopup](api/LifespanHandler.md#onbeforepopup) + * [_OnAfterCreated](api/LifespanHandler.md#_onaftercreated) + * [DoClose](api/LifespanHandler.md#doclose) + * [OnBeforeClose](api/LifespanHandler.md#onbeforeclose) +* [LoadHandler (interface)](api/LoadHandler.md#loadhandler-interface) + * [OnLoadingStateChange](api/LoadHandler.md#onloadingstatechange) + * [OnLoadStart](api/LoadHandler.md#onloadstart) + * [OnDomReady](api/LoadHandler.md#ondomready) + * [OnLoadEnd](api/LoadHandler.md#onloadend) + * [OnLoadError](api/LoadHandler.md#onloaderror) +* [Network error](api/NetworkError.md#network-error) + * [ERR_NONE](api/NetworkError.md#err_none) + * [ERR_ABORTED](api/NetworkError.md#err_aborted) + * [ERR_ACCESS_DENIED](api/NetworkError.md#err_access_denied) + * [ERR_ADDRESS_INVALID](api/NetworkError.md#err_address_invalid) + * [ERR_ADDRESS_UNREACHABLE](api/NetworkError.md#err_address_unreachable) + * [ERR_CACHE_MISS](api/NetworkError.md#err_cache_miss) + * [ERR_CERT_AUTHORITY_INVALID](api/NetworkError.md#err_cert_authority_invalid) + * [ERR_CERT_COMMON_NAME_INVALID](api/NetworkError.md#err_cert_common_name_invalid) + * [ERR_CERT_CONTAINS_ERRORS](api/NetworkError.md#err_cert_contains_errors) + * [ERR_CERT_DATE_INVALID](api/NetworkError.md#err_cert_date_invalid) + * [ERR_CERT_END](api/NetworkError.md#err_cert_end) + * [ERR_CERT_INVALID](api/NetworkError.md#err_cert_invalid) + * [ERR_CERT_NO_REVOCATION_MECHANISM](api/NetworkError.md#err_cert_no_revocation_mechanism) + * [ERR_CERT_REVOKED](api/NetworkError.md#err_cert_revoked) + * [ERR_CERT_UNABLE_TO_CHECK_REVOCATION](api/NetworkError.md#err_cert_unable_to_check_revocation) + * [ERR_CONNECTION_ABORTED](api/NetworkError.md#err_connection_aborted) + * [ERR_CONNECTION_CLOSED](api/NetworkError.md#err_connection_closed) + * [ERR_CONNECTION_FAILED](api/NetworkError.md#err_connection_failed) + * [ERR_CONNECTION_REFUSED](api/NetworkError.md#err_connection_refused) + * [ERR_CONNECTION_RESET](api/NetworkError.md#err_connection_reset) + * [ERR_DISALLOWED_URL_SCHEME](api/NetworkError.md#err_disallowed_url_scheme) + * [ERR_EMPTY_RESPONSE](api/NetworkError.md#err_empty_response) + * [ERR_FAILED](api/NetworkError.md#err_failed) + * [ERR_FILE_NOT_FOUND](api/NetworkError.md#err_file_not_found) + * [ERR_FILE_TOO_BIG](api/NetworkError.md#err_file_too_big) + * [ERR_INSECURE_RESPONSE](api/NetworkError.md#err_insecure_response) + * [ERR_INTERNET_DISCONNECTED](api/NetworkError.md#err_internet_disconnected) + * [ERR_INVALID_ARGUMENT](api/NetworkError.md#err_invalid_argument) + * [ERR_INVALID_CHUNKED_ENCODING](api/NetworkError.md#err_invalid_chunked_encoding) + * [ERR_INVALID_HANDLE](api/NetworkError.md#err_invalid_handle) + * [ERR_INVALID_RESPONSE](api/NetworkError.md#err_invalid_response) + * [ERR_INVALID_URL](api/NetworkError.md#err_invalid_url) + * [ERR_METHOD_NOT_SUPPORTED](api/NetworkError.md#err_method_not_supported) + * [ERR_NAME_NOT_RESOLVED](api/NetworkError.md#err_name_not_resolved) + * [ERR_NO_SSL_VERSIONS_ENABLED](api/NetworkError.md#err_no_ssl_versions_enabled) + * [ERR_NOT_IMPLEMENTED](api/NetworkError.md#err_not_implemented) + * [ERR_RESPONSE_HEADERS_TOO_BIG](api/NetworkError.md#err_response_headers_too_big) + * [ERR_SSL_CLIENT_AUTH_CERT_NEEDED](api/NetworkError.md#err_ssl_client_auth_cert_needed) + * [ERR_SSL_PROTOCOL_ERROR](api/NetworkError.md#err_ssl_protocol_error) + * [ERR_SSL_RENEGOTIATION_REQUESTED](api/NetworkError.md#err_ssl_renegotiation_requested) + * [ERR_SSL_VERSION_OR_CIPHER_MISMATCH](api/NetworkError.md#err_ssl_version_or_cipher_mismatch) + * [ERR_TIMED_OUT](api/NetworkError.md#err_timed_out) + * [ERR_TOO_MANY_REDIRECTS](api/NetworkError.md#err_too_many_redirects) + * [ERR_TUNNEL_CONNECTION_FAILED](api/NetworkError.md#err_tunnel_connection_failed) + * [ERR_UNEXPECTED](api/NetworkError.md#err_unexpected) + * [ERR_UNEXPECTED_PROXY_AUTH](api/NetworkError.md#err_unexpected_proxy_auth) + * [ERR_UNKNOWN_URL_SCHEME](api/NetworkError.md#err_unknown_url_scheme) + * [ERR_UNSAFE_PORT](api/NetworkError.md#err_unsafe_port) + * [ERR_UNSAFE_REDIRECT](api/NetworkError.md#err_unsafe_redirect) +* [PaintBuffer (object)](api/PaintBuffer.md#paintbuffer-object) + * [GetIntPointer](api/PaintBuffer.md#getintpointer) + * [GetString](api/PaintBuffer.md#getstring) +* [RenderHandler (interface)](api/RenderHandler.md#renderhandler-interface) + * [GetRootScreenRect](api/RenderHandler.md#getrootscreenrect) + * [GetViewRect](api/RenderHandler.md#getviewrect) + * [GetScreenRect](api/RenderHandler.md#getscreenrect) + * [GetScreenPoint](api/RenderHandler.md#getscreenpoint) + * [OnPopupShow](api/RenderHandler.md#onpopupshow) + * [OnPopupSize](api/RenderHandler.md#onpopupsize) + * [OnPaint](api/RenderHandler.md#onpaint) + * [OnCursorChange](api/RenderHandler.md#oncursorchange) + * [OnScrollOffsetChanged](api/RenderHandler.md#onscrolloffsetchanged) + * [StartDragging](api/RenderHandler.md#startdragging) + * [UpdateDragCursor](api/RenderHandler.md#updatedragcursor) +* [Request (class)](api/Request.md#request-class) + * [CreateRequest](api/Request.md#createrequest) + * [IsReadOnly](api/Request.md#isreadonly) + * [GetUrl](api/Request.md#geturl) + * [SetUrl](api/Request.md#seturl) + * [GetMethod](api/Request.md#getmethod) + * [SetMethod](api/Request.md#setmethod) + * [GetPostData](api/Request.md#getpostdata) + * [SetPostData](api/Request.md#setpostdata) + * [GetHeaderMap](api/Request.md#getheadermap) + * [GetHeaderMultimap](api/Request.md#getheadermultimap) + * [SetHeaderMap](api/Request.md#setheadermap) + * [SetHeaderMultimap](api/Request.md#setheadermultimap) + * [GetFlags](api/Request.md#getflags) + * [SetFlags](api/Request.md#setflags) + * [GetFirstPartyForCookies](api/Request.md#getfirstpartyforcookies) + * [SetFirstPartyForCookies](api/Request.md#setfirstpartyforcookies) + * [GetResourceType](api/Request.md#getresourcetype) + * [GetTransitionType](api/Request.md#gettransitiontype) +* [RequestHandler (interface)](api/RequestHandler.md#requesthandler-interface) + * [OnBeforeBrowse](api/RequestHandler.md#onbeforebrowse) + * [OnBeforeResourceLoad](api/RequestHandler.md#onbeforeresourceload) + * [GetResourceHandler](api/RequestHandler.md#getresourcehandler) + * [OnResourceRedirect](api/RequestHandler.md#onresourceredirect) + * [OnResourceResponse](api/RequestHandler.md#onresourceresponse) + * [GetAuthCredentials](api/RequestHandler.md#getauthcredentials) + * [OnQuotaRequest](api/RequestHandler.md#onquotarequest) + * [GetCookieManager](api/RequestHandler.md#getcookiemanager) + * [OnProtocolExecution](api/RequestHandler.md#onprotocolexecution) + * [_OnBeforePluginLoad](api/RequestHandler.md#_onbeforepluginload) + * [_OnCertificateError](api/RequestHandler.md#_oncertificateerror) + * [OnRendererProcessTerminated](api/RequestHandler.md#onrendererprocessterminated) + * [OnPluginCrashed](api/RequestHandler.md#onplugincrashed) +* [ResourceHandler (interface)](api/ResourceHandler.md#resourcehandler-interface) + * [ProcessRequest](api/ResourceHandler.md#processrequest) + * [GetResponseHeaders](api/ResourceHandler.md#getresponseheaders) + * [ReadResponse](api/ResourceHandler.md#readresponse) + * [CanGetCookie](api/ResourceHandler.md#cangetcookie) + * [CanSetCookie](api/ResourceHandler.md#cansetcookie) + * [Cancel](api/ResourceHandler.md#cancel) +* [Response (object)](api/Response.md#response-object) + * [IsReadOnly](api/Response.md#isreadonly) + * [GetStatus](api/Response.md#getstatus) + * [SetStatus](api/Response.md#setstatus) + * [GetStatusText](api/Response.md#getstatustext) + * [SetStatusText](api/Response.md#setstatustext) + * [GetMimeType](api/Response.md#getmimetype) + * [SetMimeType](api/Response.md#setmimetype) + * [GetHeader](api/Response.md#getheader) + * [GetHeaderMap](api/Response.md#getheadermap) + * [GetHeaderMultimap](api/Response.md#getheadermultimap) + * [SetHeaderMap](api/Response.md#setheadermap) + * [SetHeaderMultimap](api/Response.md#setheadermultimap) +* [StringVisitor (interface)](api/StringVisitor.md#stringvisitor-interface) + * [Visit](api/StringVisitor.md#visit) +* [V8ContextHandler (interface)](api/V8ContextHandler.md#v8contexthandler-interface) + * [OnContextCreated](api/V8ContextHandler.md#oncontextcreated) + * [OnContextReleased](api/V8ContextHandler.md#oncontextreleased) +* [Virtual Key codes](api/VirtualKey.md#virtual-key-codes) +* [WebPluginInfo (object)](api/WebPluginInfo.md#webplugininfo-object) + * [GetName](api/WebPluginInfo.md#getname) + * [GetPath](api/WebPluginInfo.md#getpath) + * [GetVersion](api/WebPluginInfo.md#getversion) + * [GetDescription](api/WebPluginInfo.md#getdescription) +* [WebRequest (class)](api/WebRequest.md#webrequest-class) + * [Create](api/WebRequest.md#create) + * [GetRequest](api/WebRequest.md#getrequest) + * [GetRequestStatus](api/WebRequest.md#getrequeststatus) + * [GetRequestError](api/WebRequest.md#getrequesterror) + * [GetResponse](api/WebRequest.md#getresponse) + * [Cancel](api/WebRequest.md#cancel) +* [WebRequestClient (interface)](api/WebRequestClient.md#webrequestclient-interface) + * [OnUploadProgress](api/WebRequestClient.md#onuploadprogress) + * [OnDownloadProgress](api/WebRequestClient.md#ondownloadprogress) + * [OnDownloadData](api/WebRequestClient.md#ondownloaddata) + * [OnRequestComplete](api/WebRequestClient.md#onrequestcomplete) +* [WindowInfo (class)](api/WindowInfo.md#windowinfo-class) + * [SetAsChild](api/WindowInfo.md#setaschild) + * [SetAsPopup](api/WindowInfo.md#setaspopup) + * [SetAsOffscreen](api/WindowInfo.md#setasoffscreen) + * [SetTransparentPainting](api/WindowInfo.md#settransparentpainting) +* [WindowUtils (class)](api/WindowUtils.md#windowutils-class) + * [OnSetFocus ](api/WindowUtils.md#onsetfocus-win) + * [OnSize ](api/WindowUtils.md#onsize-win) + * [OnEraseBackground ](api/WindowUtils.md#onerasebackground-win) + * [SetTitle ](api/WindowUtils.md#settitle-win) + * [SetIcon ](api/WindowUtils.md#seticon-win) + * [GetParentHandle](api/WindowUtils.md#getparenthandle) + * [IsWindowHandle](api/WindowUtils.md#iswindowhandle) + * [gtk_plug_new ](api/WindowUtils.md#gtk_plug_new-linux) + * [gtk_widget_show ](api/WindowUtils.md#gtk_widget_show-linux) + * [InstallX11ErrorHandlers ](api/WindowUtils.md#installx11errorhandlers-linux) diff --git a/api/API-index.md b/api/API-index.md index 3fe74ca2e..df2dc4bd2 100644 --- a/api/API-index.md +++ b/api/API-index.md @@ -147,6 +147,7 @@ * [GetCommandLineSwitch](cefpython.md#getcommandlineswitch) * [GetGlobalClientCallback](cefpython.md#getglobalclientcallback) * [GetModuleDirectory](cefpython.md#getmoduledirectory) + * [GetVersion](cefpython.md#getversion) * [Initialize](cefpython.md#initialize) * [IsThread](cefpython.md#isthread) * [MessageLoop](cefpython.md#messageloop) diff --git a/tools/apidocs.py b/tools/apidocs.py index 69e6ed9dd..0ba3aa5e1 100644 --- a/tools/apidocs.py +++ b/tools/apidocs.py @@ -2,7 +2,7 @@ # All rights reserved. Licensed under BSD 3-clause license. # Project website: https://github.com/cztomczak/cefpython -"""Generate API docs from sources. +"""Generate API reference index in api/ directory and in root/README.md. TODO: - generate api/ docs from Cython sources @@ -12,59 +12,93 @@ (eg. TerminationStatus, KeyEvent, KeyEventFlags) """ -import os +from common import * + import glob +import os import re -# Constants -API_DIR = os.path.join(os.path.dirname(__file__), "..", "api") - def main(): """Main entry point.""" - api_index() + api_links = generate_api_links() + update_api_index_file(api_links) + update_readme_file(api_links) -def api_index(): - """Generate API-index.md file with all modules/classes/funcs/methods.""" - files = glob.glob(os.path.join(API_DIR, "*.md")) +def update_api_index_file(api_links): + """Create or update API-index.md file.""" contents = ("[API categories](API-categories.md#api-categories) | " + "[API index](API-index.md#api-index)\n\n" + "# API index\n\n") + contents += api_links + index_file = os.path.join(API_DIR, "API-index.md") + with open(index_file, "rb") as fo: + current_contents = fo.read().decode("utf-8") + if contents == current_contents: + print("No changes: %s/%s" % (os.path.basename(API_DIR), + os.path.basename(index_file))) + return + with open(index_file, "wb") as fo: + fo.write(contents.encode("utf-8")) + print("Updated: %s/%s" % (os.path.basename(API_DIR), + os.path.basename(index_file))) + + +def update_readme_file(api_links): + """Update root/README.md with API reference links.""" + api_links = api_links.replace("](", "](api/") + readme_file = os.path.join(ROOT_DIR, "README.md") + with open(readme_file, "rb") as fo: + current_contents = fo.read().decode("utf-8") + contents = current_contents + contents = re.sub((r"### API reference\s+" + r"(\s*\*[ ]\[[^\r\n\[\]]+\]\([^\r\n()]+\)\s+)*"), + ("### API reference\r\n\r\n{api_links}" + .format(api_links=api_links)), + contents) + if contents == current_contents: + print("No changes: /%s" % (os.path.basename(readme_file))) + return + with open(readme_file, "wb") as fo: + fo.write(contents.encode("utf-8")) + print("Updated: /%s" % (os.path.basename(readme_file))) + + +def generate_api_links(): + """Generate API index with all modules / classes / functions.""" + contents = "" + files = glob.glob(os.path.join(API_DIR, "*.md")) files = sorted(files, key=lambda s: s.lower()) for file_ in files: + # Ignore API-index.md and API-categories.md files if "API-" in file_: continue with open(file_, "rb") as fo: - raw_mdcontents = fo.read().decode("utf-8") - - parsable_mdcontents = re.sub(r"```[\s\S]+?```", "", raw_mdcontents) - allmatches = re.findall(r"^(#|###)\s+(.*)", parsable_mdcontents, - re.MULTILINE) - for allmatch in allmatches: - hlevel = allmatch[0].strip() - title = allmatch[1].strip() + md_contents = fo.read().decode("utf-8") + md_contents = re.sub(r"```[\s\S]+?```", "", md_contents) + matches = re.findall(r"^(#|###)\s+(.*)", md_contents, + re.MULTILINE) + for match in matches: + heading_level = match[0].strip() + title = match[1].strip() title = title.strip() - if hlevel == "#": + if heading_level == "#": indent = "" - link = os.path.basename(file_) + "#" + headinghash(title) - elif hlevel == "###": + link = os.path.basename(file_) + "#" + get_heading_hash(title) + elif heading_level == "###": indent = " " - link = os.path.basename(file_) + "#" + headinghash(title) + link = os.path.basename(file_) + "#" + get_heading_hash(title) # hash generation needs complete title. Now we can strip some. title = re.sub(r"\(.*", r"", title) else: assert False, "Heading level unsupported" contents += (indent + "* " + "[%s](%s)\n" % (title, link)) - indexfile = os.path.join(API_DIR, "API-index.md") - with open(indexfile, "wb") as fo: - fo.write(contents.encode("utf-8")) - print("Created %s in %s" % (os.path.basename(indexfile), API_DIR)) - print("Done") + return contents -def headinghash(title): - """Get a link hash for a heading H1,H2,H3.""" +def get_heading_hash(title): + """Get a link hash for headings H1, H2, H3.""" hash_ = title.lower() hash_ = re.sub(r"[^a-z0-9_\- ]+", r"", hash_) hash_ = hash_.replace(" ", "-") diff --git a/tools/common.py b/tools/common.py index 2b3d595fa..360494172 100644 --- a/tools/common.py +++ b/tools/common.py @@ -97,6 +97,9 @@ assert __file__ ROOT_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) +# API reference +API_DIR = os.path.join(ROOT_DIR, "api") + # Build directories BUILD_DIR = os.path.join(ROOT_DIR, "build") BUILD_CEFPYTHON = os.path.join(BUILD_DIR, "build_cefpython") From 2ae6f08c73a661c335c527524312f0174c15842e Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sun, 12 Mar 2017 14:44:34 +0100 Subject: [PATCH 168/557] Add API categories to README (#326)... Update apidocs.py. --- README.md | 63 ++++++++++++++++++++++++++++++++++++-- api/API-categories.md | 70 +++++++++++++++++++++---------------------- tools/apidocs.py | 40 ++++++++++++++++++++----- 3 files changed, 129 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 44d7979ea..3b391bf7c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,8 @@ Table of contents: * [Thanks](#thanks) * [Quick links](#quick-links) * [Docs](#docs) - * [API reference](#api-reference) + * [API categories](#api-categories) + * [API index](#api-index) ## Introduction @@ -128,7 +129,65 @@ directly. - [Migration guide](docs/Migration-guide.md) - [Tutorial](docs/Tutorial.md) -### API reference + +### API categories + +#### Modules + + * [cefpython](cefpython.md#cefpython) module + + +#### Settings + + * [ApplicationSettings](ApplicationSettings.md#application-settings) dictionary + * [BrowserSettings](BrowserSettings.md#browser-settings) dictionary + * [CommandLineSwitches](CommandLineSwitches.md#command-line-switches) dictionary + + +#### Classes and objects + + * [Browser](Browser.md#browser-object) object + * [Callback](Callback.md#callback-object) object + * [Cookie](Cookie.md#cookie-class) class + * [CookieManager](CookieManager.md#cookiemanager-class) class + * [DpiAware](DpiAware.md#dpiaware-class) class (Win) + * [DragData](DragData.md#dragdata-object) object + * [Frame](Frame.md#frame-object) object + * [Image](Image.md#image-object) object + * [JavascriptBindings](JavascriptBindings.md#javascriptbindings-class) class + * [JavascriptCallback](JavascriptCallback.md#javascriptcallback-object) object + * [PaintBuffer](PaintBuffer.md#paintbuffer-object) object + * [Request](Request.md#request-class) class + * [Response](Response.md#response-object) object + * [WebPluginInfo](WebPluginInfo.md#webplugininfo-object) object + * [WebRequest](WebRequest.md#webrequest-class) class + * [WindowInfo](WindowInfo.md#windowinfo-class) class + * [WindowUtils](WindowUtils.md#windowutils-class) class + + +#### Handlers (interfaces) + + * [DisplayHandler](DisplayHandler.md#displayhandler-interface) + * [DownloadHandler](DownloadHandler.md#downloadhandler) + * [FocusHandler](FocusHandler.md#focushandler-interface) + * [JavascriptDialogHandler](JavascriptDialogHandler.md#javascriptdialoghandler-interface) + * [KeyboardHandler](KeyboardHandler.md#keyboardhandler-interface) + * [LifespanHandler](LifespanHandler.md#lifespanhandler-interface) + * [LoadHandler](LoadHandler.md#loadhandler-interface) + * [RenderHandler](RenderHandler.md#renderhandler-interface) + * [RequestHandler](RequestHandler.md#requesthandler-interface) + * [ResourceHandler](ResourceHandler.md#resourcehandler-interface) + * [V8ContextHandler](V8ContextHandler.md#v8contexthandler-interface) + + +#### Other interfaces + + * [CookieVisitor](CookieVisitor.md#cookievisitor-interface) interface + * [StringVisitor](StringVisitor.md#stringvisitor-interface) interface + * [WebRequestClient](WebRequestClient.md#webrequestclient-interface) interface + + +### API index * [Application settings](api/ApplicationSettings.md#application-settings) * [accept_language_list](api/ApplicationSettings.md#accept_language_list) diff --git a/api/API-categories.md b/api/API-categories.md index a338fc34c..cceb66fe7 100644 --- a/api/API-categories.md +++ b/api/API-categories.md @@ -5,55 +5,55 @@ ### Modules - * [cefpython](cefpython.md) module + * [cefpython](cefpython.md#cefpython) module ### Settings - * [ApplicationSettings](ApplicationSettings.md) dictionary - * [BrowserSettings](BrowserSettings.md) dictionary - * [CommandLineSwitches](CommandLineSwitches.md) dictionary + * [ApplicationSettings](ApplicationSettings.md#application-settings) dictionary + * [BrowserSettings](BrowserSettings.md#browser-settings) dictionary + * [CommandLineSwitches](CommandLineSwitches.md#command-line-switches) dictionary ### Classes and objects - * [Browser](Browser.md) object - * [Callback](Callback.md) object - * [Cookie](Cookie.md) class - * [CookieManager](CookieManager.md) class - * [DpiAware](DpiAware.md) class (Win) - * [DragData](DragData.md) object - * [Frame](Frame.md) object - * [Image](Image.md) object - * [JavascriptBindings](JavascriptBindings.md) class - * [JavascriptCallback](JavascriptCallback.md) object - * [PaintBuffer](PaintBuffer.md) object - * [Request](Request.md) class - * [Response](Response.md) object - * [WebPluginInfo](WebPluginInfo.md) object - * [WebRequest](WebRequest.md) class - * [WindowInfo](WindowInfo.md) class - * [WindowUtils](WindowUtils.md) class + * [Browser](Browser.md#browser-object) object + * [Callback](Callback.md#callback-object) object + * [Cookie](Cookie.md#cookie-class) class + * [CookieManager](CookieManager.md#cookiemanager-class) class + * [DpiAware](DpiAware.md#dpiaware-class) class (Win) + * [DragData](DragData.md#dragdata-object) object + * [Frame](Frame.md#frame-object) object + * [Image](Image.md#image-object) object + * [JavascriptBindings](JavascriptBindings.md#javascriptbindings-class) class + * [JavascriptCallback](JavascriptCallback.md#javascriptcallback-object) object + * [PaintBuffer](PaintBuffer.md#paintbuffer-object) object + * [Request](Request.md#request-class) class + * [Response](Response.md#response-object) object + * [WebPluginInfo](WebPluginInfo.md#webplugininfo-object) object + * [WebRequest](WebRequest.md#webrequest-class) class + * [WindowInfo](WindowInfo.md#windowinfo-class) class + * [WindowUtils](WindowUtils.md#windowutils-class) class ### Handlers (interfaces) - * [DisplayHandler](DisplayHandler.md) - * [DownloadHandler](DownloadHandler.md) - * [FocusHandler](FocusHandler.md) - * [JavascriptDialogHandler](JavascriptDialogHandler.md) - * [KeyboardHandler](KeyboardHandler.md) - * [LifespanHandler](LifespanHandler.md) - * [LoadHandler](LoadHandler.md) - * [RenderHandler](RenderHandler.md) - * [RequestHandler](RequestHandler.md) - * [ResourceHandler](ResourceHandler.md) - * [V8ContextHandler](V8ContextHandler.md) + * [DisplayHandler](DisplayHandler.md#displayhandler-interface) + * [DownloadHandler](DownloadHandler.md#downloadhandler) + * [FocusHandler](FocusHandler.md#focushandler-interface) + * [JavascriptDialogHandler](JavascriptDialogHandler.md#javascriptdialoghandler-interface) + * [KeyboardHandler](KeyboardHandler.md#keyboardhandler-interface) + * [LifespanHandler](LifespanHandler.md#lifespanhandler-interface) + * [LoadHandler](LoadHandler.md#loadhandler-interface) + * [RenderHandler](RenderHandler.md#renderhandler-interface) + * [RequestHandler](RequestHandler.md#requesthandler-interface) + * [ResourceHandler](ResourceHandler.md#resourcehandler-interface) + * [V8ContextHandler](V8ContextHandler.md#v8contexthandler-interface) ### Other interfaces - * [CookieVisitor](CookieVisitor.md) interface - * [StringVisitor](StringVisitor.md) interface - * [WebRequestClient](WebRequestClient.md) interface + * [CookieVisitor](CookieVisitor.md#cookievisitor-interface) interface + * [StringVisitor](StringVisitor.md#stringvisitor-interface) interface + * [WebRequestClient](WebRequestClient.md#webrequestclient-interface) interface diff --git a/tools/apidocs.py b/tools/apidocs.py index 0ba3aa5e1..badb067ec 100644 --- a/tools/apidocs.py +++ b/tools/apidocs.py @@ -46,18 +46,44 @@ def update_api_index_file(api_links): def update_readme_file(api_links): - """Update root/README.md with API reference links.""" + """Update root/README.md with API categories and index links. + API categories are copied from API-categories.md which is + generated manually. """ api_links = api_links.replace("](", "](api/") readme_file = os.path.join(ROOT_DIR, "README.md") with open(readme_file, "rb") as fo: - current_contents = fo.read().decode("utf-8") - contents = current_contents - contents = re.sub((r"### API reference\s+" - r"(\s*\*[ ]\[[^\r\n\[\]]+\]\([^\r\n()]+\)\s+)*"), - ("### API reference\r\n\r\n{api_links}" + readme_contents = fo.read().decode("utf-8") + contents = readme_contents + + # Update API categories + categories_file = os.path.join(API_DIR, "API-categories.md") + with open(categories_file, "rb") as fo: + categories_contents = fo.read().decode("utf-8") + match = re.search(r"# API categories\s+(###[\s\S]+)", + categories_contents) + assert match and match.group(1), "Failed to parse API categories" + categories_contents = match.group(1) + categories_contents = categories_contents.replace("###", "####") + re_find = r"### API categories[\s\S]+### API index" + assert re.search(re_find, readme_contents), ("API categories not found" + " in README") + contents = re.sub(re_find, + ("### API categories\r\n\r\n{categories_contents}" + "\r\n### API index" + .format(categories_contents=categories_contents)), + contents) + + # Update API index + re_find = (r"### API index\s+" + r"(\s*\*[ ]\[[^\r\n\[\]]+\]\([^\r\n()]+\)\s+)*") + assert re.search(re_find, readme_contents), ("API index not found" + " in README") + contents = re.sub(re_find, + ("### API index\r\n\r\n{api_links}" .format(api_links=api_links)), contents) - if contents == current_contents: + + if contents == readme_contents: print("No changes: /%s" % (os.path.basename(readme_file))) return with open(readme_file, "wb") as fo: From 94f2c05eb99b0dcefe68cdad2b2d428e8a61232d Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sun, 12 Mar 2017 14:46:56 +0100 Subject: [PATCH 169/557] Fix API links in README (#326) --- README.md | 70 ++++++++++++++++++++++++------------------------ tools/apidocs.py | 1 + 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 3b391bf7c..feb5768c5 100644 --- a/README.md +++ b/README.md @@ -134,57 +134,57 @@ directly. #### Modules - * [cefpython](cefpython.md#cefpython) module + * [cefpython](api/cefpython.md#cefpython) module #### Settings - * [ApplicationSettings](ApplicationSettings.md#application-settings) dictionary - * [BrowserSettings](BrowserSettings.md#browser-settings) dictionary - * [CommandLineSwitches](CommandLineSwitches.md#command-line-switches) dictionary + * [ApplicationSettings](api/ApplicationSettings.md#application-settings) dictionary + * [BrowserSettings](api/BrowserSettings.md#browser-settings) dictionary + * [CommandLineSwitches](api/CommandLineSwitches.md#command-line-switches) dictionary #### Classes and objects - * [Browser](Browser.md#browser-object) object - * [Callback](Callback.md#callback-object) object - * [Cookie](Cookie.md#cookie-class) class - * [CookieManager](CookieManager.md#cookiemanager-class) class - * [DpiAware](DpiAware.md#dpiaware-class) class (Win) - * [DragData](DragData.md#dragdata-object) object - * [Frame](Frame.md#frame-object) object - * [Image](Image.md#image-object) object - * [JavascriptBindings](JavascriptBindings.md#javascriptbindings-class) class - * [JavascriptCallback](JavascriptCallback.md#javascriptcallback-object) object - * [PaintBuffer](PaintBuffer.md#paintbuffer-object) object - * [Request](Request.md#request-class) class - * [Response](Response.md#response-object) object - * [WebPluginInfo](WebPluginInfo.md#webplugininfo-object) object - * [WebRequest](WebRequest.md#webrequest-class) class - * [WindowInfo](WindowInfo.md#windowinfo-class) class - * [WindowUtils](WindowUtils.md#windowutils-class) class + * [Browser](api/Browser.md#browser-object) object + * [Callback](api/Callback.md#callback-object) object + * [Cookie](api/Cookie.md#cookie-class) class + * [CookieManager](api/CookieManager.md#cookiemanager-class) class + * [DpiAware](api/DpiAware.md#dpiaware-class) class (Win) + * [DragData](api/DragData.md#dragdata-object) object + * [Frame](api/Frame.md#frame-object) object + * [Image](api/Image.md#image-object) object + * [JavascriptBindings](api/JavascriptBindings.md#javascriptbindings-class) class + * [JavascriptCallback](api/JavascriptCallback.md#javascriptcallback-object) object + * [PaintBuffer](api/PaintBuffer.md#paintbuffer-object) object + * [Request](api/Request.md#request-class) class + * [Response](api/Response.md#response-object) object + * [WebPluginInfo](api/WebPluginInfo.md#webplugininfo-object) object + * [WebRequest](api/WebRequest.md#webrequest-class) class + * [WindowInfo](api/WindowInfo.md#windowinfo-class) class + * [WindowUtils](api/WindowUtils.md#windowutils-class) class #### Handlers (interfaces) - * [DisplayHandler](DisplayHandler.md#displayhandler-interface) - * [DownloadHandler](DownloadHandler.md#downloadhandler) - * [FocusHandler](FocusHandler.md#focushandler-interface) - * [JavascriptDialogHandler](JavascriptDialogHandler.md#javascriptdialoghandler-interface) - * [KeyboardHandler](KeyboardHandler.md#keyboardhandler-interface) - * [LifespanHandler](LifespanHandler.md#lifespanhandler-interface) - * [LoadHandler](LoadHandler.md#loadhandler-interface) - * [RenderHandler](RenderHandler.md#renderhandler-interface) - * [RequestHandler](RequestHandler.md#requesthandler-interface) - * [ResourceHandler](ResourceHandler.md#resourcehandler-interface) - * [V8ContextHandler](V8ContextHandler.md#v8contexthandler-interface) + * [DisplayHandler](api/DisplayHandler.md#displayhandler-interface) + * [DownloadHandler](api/DownloadHandler.md#downloadhandler) + * [FocusHandler](api/FocusHandler.md#focushandler-interface) + * [JavascriptDialogHandler](api/JavascriptDialogHandler.md#javascriptdialoghandler-interface) + * [KeyboardHandler](api/KeyboardHandler.md#keyboardhandler-interface) + * [LifespanHandler](api/LifespanHandler.md#lifespanhandler-interface) + * [LoadHandler](api/LoadHandler.md#loadhandler-interface) + * [RenderHandler](api/RenderHandler.md#renderhandler-interface) + * [RequestHandler](api/RequestHandler.md#requesthandler-interface) + * [ResourceHandler](api/ResourceHandler.md#resourcehandler-interface) + * [V8ContextHandler](api/V8ContextHandler.md#v8contexthandler-interface) #### Other interfaces - * [CookieVisitor](CookieVisitor.md#cookievisitor-interface) interface - * [StringVisitor](StringVisitor.md#stringvisitor-interface) interface - * [WebRequestClient](WebRequestClient.md#webrequestclient-interface) interface + * [CookieVisitor](api/CookieVisitor.md#cookievisitor-interface) interface + * [StringVisitor](api/StringVisitor.md#stringvisitor-interface) interface + * [WebRequestClient](api/WebRequestClient.md#webrequestclient-interface) interface ### API index diff --git a/tools/apidocs.py b/tools/apidocs.py index badb067ec..8bd8da318 100644 --- a/tools/apidocs.py +++ b/tools/apidocs.py @@ -64,6 +64,7 @@ def update_readme_file(api_links): assert match and match.group(1), "Failed to parse API categories" categories_contents = match.group(1) categories_contents = categories_contents.replace("###", "####") + categories_contents = categories_contents.replace("](", "](api/") re_find = r"### API categories[\s\S]+### API index" assert re.search(re_find, readme_contents), ("API categories not found" " in README") From 3681c59aebcda67f5460c000be12dcf4d3bf4db2 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 13 Mar 2017 10:41:49 +0100 Subject: [PATCH 170/557] Update to Chromium v56 on Linux (#276)... Update build instructions for Linux. Requirements changed, install-build-deps command changed, there is one error during build and a solution for that problem was added. Update patches. Minor fixes to automate.py. --- docs/Build-instructions.md | 33 ++++++++++++++++++++++++++------- patches/issue125.patch | 4 ++-- patches/issue231.patch | 8 ++++---- patches/issue251.patch | 36 ++++++++++++++++++------------------ tools/automate.py | 37 +++++++++++++++++++++++++++++++------ 5 files changed, 81 insertions(+), 37 deletions(-) diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index 821adab6e..832e0f968 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -12,6 +12,7 @@ Table of contents: * [Build using prebuilt CEF binaries and libraries](#build-using-prebuilt-cef-binaries-and-libraries) * [Build using CEF binaries from Spotify Automated Builds](#build-using-cef-binaries-from-spotify-automated-builds) * [Build upstream CEF from sources](#build-upstream-cef-from-sources) + * [Possible errors](#possible-errors) * [Build CEF manually](#build-cef-manually) * [CEF Automated Builds (Spotify and Adobe)](#cef-automated-builds-spotify-and-adobe) * [Notes](#notes) @@ -191,8 +192,9 @@ requirements common for all platforms. * Official binaries are built on Ubuntu 14.04 (cmake 2.8.12, g++ 4.8.4) * Download [ninja](http://martine.github.io/ninja/) 1.7.1 or later and copy it to /usr/bin and chmod 755. - * Install required packages using one of the three methods below: - 1. Type command: `sudo apt-get install bison build-essential cdbs curl devscripts dpkg-dev elfutils fakeroot flex g++ git-core git-svn gperf libapache2-mod-php5 libasound2-dev libav-tools libbrlapi-dev libbz2-dev libcairo2-dev libcap-dev libcups2-dev libcurl4-gnutls-dev libdrm-dev libelf-dev libexif-dev libffi-dev libgconf2-dev libgl1-mesa-dev libglib2.0-dev libglu1-mesa-dev libgnome-keyring-dev libgtk2.0-dev libkrb5-dev libnspr4-dev libnss3-dev libpam0g-dev libpci-dev libpulse-dev libsctp-dev libspeechd-dev libsqlite3-dev libssl-dev libudev-dev libwww-perl libxslt1-dev libxss-dev libxt-dev libxtst-dev mesa-common-dev openbox patch perl php5-cgi pkg-config python python-cherrypy3 python-crypto python-dev python-psutil python-numpy python-opencv python-openssl python-yaml rpm ruby subversion ttf-dejavu-core ttf-indic-fonts ttf-kochi-gothic ttf-kochi-mincho fonts-thai-tlwg wdiff zip` + * Install/upgrade required packages using one of the three methods below + (these packages should be upgraded each time you update to newer CEF): + 1. Type command: `sudo apt-get install bison build-essential cdbs curl devscripts dpkg-dev elfutils fakeroot flex g++ git-core git-svn gperf libapache2-mod-php5 libasound2-dev libav-tools libbrlapi-dev libbz2-dev libcairo2-dev libcap-dev libcups2-dev libcurl4-gnutls-dev libdrm-dev libelf-dev libexif-dev libffi-dev libgconf2-dev libgl1-mesa-dev libglib2.0-dev libglu1-mesa-dev libgnome-keyring-dev libgtk2.0-dev libkrb5-dev libnspr4-dev libnss3-dev libpam0g-dev libpci-dev libpulse-dev libsctp-dev libspeechd-dev libsqlite3-dev libssl-dev libudev-dev libwww-perl libxslt1-dev libxss-dev libxt-dev libxtst-dev mesa-common-dev openbox patch perl php5-cgi pkg-config python python-cherrypy3 python-crypto python-dev python-psutil python-numpy python-opencv python-openssl python-yaml rpm ruby subversion ttf-dejavu-core ttf-indic-fonts ttf-kochi-gothic ttf-kochi-mincho fonts-thai-tlwg wdiff wget zip` 2. See the list of packages on the [cef/AutomatedBuildSetup.md](https://bitbucket.org/chromiumembedded/cef/wiki/AutomatedBuildSetup.md#markdown-header-linux-configuration) wiki page. @@ -298,13 +300,16 @@ a custom CEF branch then use the --cef-branch flag, but note that this is only for advanced users as this will require updating cefpython's C++/Cython code. -If building on Linux and there are errors, see the -"MISSING PACKAGES (Linux)" note futher down. - You should be fine by running automate.py with the default options, but if you need to customize the build then use the --help flag to see more options. +Remember to always upgrade packages listed in Requirements section each +time you update to newer CEF. + +On Linux if there are errors about missing packages or others, +then see solutions in the [Possible errors](#possible-errors) section. + The commands below will build CEF from sources with custom CEF Python patches applied and then build the CEF Python package (xx.x is version number): @@ -323,6 +328,15 @@ module, make installer package, install the package and run unit tests and examples. See the notes for commands for creating package installer and/or wheel package for distribution. +### Possible errors + +__Debug_GN_arm/ configuration error (Linux)__: Even though building +on Linux for Linux, Chromium still runs ARM configuration files. If +there is an error showing that pkg-config fails with GTK 3 library +then see solution in the third post in this topic on CEF Forum: +[Debug_GN_arm error when building on Linux, *not* arm] +(https://magpcss.org/ceforum/viewtopic.php?f=6&t=14976). + __MISSING PACKAGES (Linux)__: After the chromium sources are downloaded, it will try to build cef projects and if it fails due to missing packages make sure you've installed all the required packages listed in the @@ -334,7 +348,7 @@ graphical installer pops up don't install it - deny EULA. ``` cd build/chromium/src/build/ chmod 755 install-build-deps.sh -sudo ./install-build-deps.sh --no-lib32 --no-arm --no-chromeos-fonts --no-nacl +sudo ./install-build-deps.sh --no-chromeos-fonts --no-nacl ``` After dependencies are satisifed re-run automate.py. @@ -442,7 +456,12 @@ cd chromium/src/cef/ git diff --no-prefix --relative > issue251.patch ``` -Apply a patch in current directory: +Apply a patch in current directory and ignore git index: +``` +patch -p0 < issue251.patch +``` + +Apply a patch in current directory and do not ignore git index: ``` cd chromium/src/cef/ git apply -v -p0 issue251.patch diff --git a/patches/issue125.patch b/patches/issue125.patch index 0f3323672..1cde324ae 100644 --- a/patches/issue125.patch +++ b/patches/issue125.patch @@ -1,8 +1,8 @@ diff --git http_cache_transaction.cc http_cache_transaction.cc -index 45f3db6aed3c..373b1e3c5b45 100644 +index 717522eb6951..e92ba22a9ca9 100644 --- http_cache_transaction.cc +++ http_cache_transaction.cc -@@ -2552,7 +2552,8 @@ int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { +@@ -2554,7 +2554,8 @@ int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { // blocking page is shown. An alternative would be to reverse-map the cert // status to a net error and replay the net error. if ((response_.headers->HasHeaderValue("cache-control", "no-store")) || diff --git a/patches/issue231.patch b/patches/issue231.patch index 80175a2fb..c265759bc 100644 --- a/patches/issue231.patch +++ b/patches/issue231.patch @@ -83,10 +83,10 @@ index 6a759309..ad620d7f 100644 + return PathService::Override(pref_key, file_path); +} diff --git libcef_dll/libcef_dll.cc libcef_dll/libcef_dll.cc -index cc1aafe5..bde00c09 100644 +index 1f037f92..b0274ad8 100644 --- libcef_dll/libcef_dll.cc +++ libcef_dll/libcef_dll.cc -@@ -930,6 +930,23 @@ CEF_EXPORT int cef_get_path(cef_path_key_t key, cef_string_t* path) { +@@ -927,6 +927,23 @@ CEF_EXPORT int cef_get_path(cef_path_key_t key, cef_string_t* path) { return _retval; } @@ -111,10 +111,10 @@ index cc1aafe5..bde00c09 100644 // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING diff --git libcef_dll/wrapper/libcef_dll_wrapper.cc libcef_dll/wrapper/libcef_dll_wrapper.cc -index 08ddbd83..42e7dca1 100644 +index c4a1b559..a0b7765b 100644 --- libcef_dll/wrapper/libcef_dll_wrapper.cc +++ libcef_dll/wrapper/libcef_dll_wrapper.cc -@@ -851,6 +851,23 @@ CEF_GLOBAL bool CefGetPath(PathKey key, CefString& path) { +@@ -848,6 +848,23 @@ CEF_GLOBAL bool CefGetPath(PathKey key, CefString& path) { return _retval?true:false; } diff --git a/patches/issue251.patch b/patches/issue251.patch index 0c2ddc7dc..e1e9bc4ea 100644 --- a/patches/issue251.patch +++ b/patches/issue251.patch @@ -1,5 +1,5 @@ diff --git include/capi/cef_drag_data_capi.h include/capi/cef_drag_data_capi.h -index 5f86225..1684de2 100644 +index 2e84df8f..5b17e212 100644 --- include/capi/cef_drag_data_capi.h +++ include/capi/cef_drag_data_capi.h @@ -39,6 +39,7 @@ @@ -34,7 +34,7 @@ index 5f86225..1684de2 100644 diff --git include/cef_drag_data.h include/cef_drag_data.h -index 8f8094b..8b4602b 100644 +index 8f8094b4..8b4602b1 100644 --- include/cef_drag_data.h +++ include/cef_drag_data.h @@ -39,6 +39,7 @@ @@ -70,21 +70,21 @@ index 8f8094b..8b4602b 100644 }; #endif // CEF_INCLUDE_CEF_DRAG_DATA_H_ -diff --git libcef/browser/osr/web_contents_view_osr.cc libcef/browser/osr/web_contents_view_osr.cc -index c39a29c..8b3c30a 100644 ---- libcef/browser/osr/web_contents_view_osr.cc -+++ libcef/browser/osr/web_contents_view_osr.cc -@@ -6,6 +6,7 @@ - #include "libcef/browser/osr/web_contents_view_osr.h" +diff --git libcef/browser/osr/browser_platform_delegate_osr.cc libcef/browser/osr/browser_platform_delegate_osr.cc +index 2cf44f6d..2e6b8c32 100644 +--- libcef/browser/osr/browser_platform_delegate_osr.cc ++++ libcef/browser/osr/browser_platform_delegate_osr.cc +@@ -7,6 +7,7 @@ + #include #include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/image_impl.h" #include "libcef/browser/osr/render_widget_host_view_osr.h" + #include "libcef/browser/osr/web_contents_view_osr.h" #include "libcef/common/drag_data_impl.h" - -@@ -230,7 +231,9 @@ void CefWebContentsViewOSR::StartDragging( - if (browser.get()) - handler = browser->GetClient()->GetRenderHandler(); +@@ -393,7 +394,9 @@ void CefBrowserPlatformDelegateOsr::StartDragging( + CefRefPtr handler = + browser_->GetClient()->GetRenderHandler(); if (handler.get()) { - CefRefPtr drag_data(new CefDragDataImpl(drop_data)); + CefRefPtr cef_image(new CefImageImpl(image)); @@ -94,7 +94,7 @@ index c39a29c..8b3c30a 100644 base::MessageLoop::ScopedNestableTaskAllower allow( base::MessageLoop::current()); diff --git libcef/common/drag_data_impl.cc libcef/common/drag_data_impl.cc -index 6b632ab..2f12b92 100644 +index 6b632ab2..2f12b928 100644 --- libcef/common/drag_data_impl.cc +++ libcef/common/drag_data_impl.cc @@ -20,6 +20,13 @@ CefDragDataImpl::CefDragDataImpl(const content::DropData& data) @@ -142,7 +142,7 @@ index 6b632ab..2f12b92 100644 + else return false; +} diff --git libcef/common/drag_data_impl.h libcef/common/drag_data_impl.h -index 64f29ed..9870726 100644 +index 64f29ed3..98707262 100644 --- libcef/common/drag_data_impl.h +++ libcef/common/drag_data_impl.h @@ -7,6 +7,7 @@ @@ -181,7 +181,7 @@ index 64f29ed..9870726 100644 // True if this object is read-only. bool read_only_; diff --git libcef_dll/cpptoc/drag_data_cpptoc.cc libcef_dll/cpptoc/drag_data_cpptoc.cc -index c36069e..ddb5729 100644 +index ffad1755..70a6c5c2 100644 --- libcef_dll/cpptoc/drag_data_cpptoc.cc +++ libcef_dll/cpptoc/drag_data_cpptoc.cc @@ -11,6 +11,7 @@ @@ -256,7 +256,7 @@ index c36069e..ddb5729 100644 template<> CefRefPtr CefCppToC Date: Mon, 13 Mar 2017 20:51:47 +0100 Subject: [PATCH 171/557] Update to Chromium v56 on Linux Part 2 (#276)... Everything builds and runs fine now. tools/build.py works fine on Linux (#299). --- docs/Build-instructions.md | 2 +- src/compile_time_constants.pxi | 4 ++-- src/subprocess/Makefile | 8 +++----- src/version/cef_version_linux.h | 20 +++++++++---------- tools/build.py | 35 +++++++++++++++++++-------------- 5 files changed, 36 insertions(+), 33 deletions(-) diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index 832e0f968..1b0cc0e2e 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -348,7 +348,7 @@ graphical installer pops up don't install it - deny EULA. ``` cd build/chromium/src/build/ chmod 755 install-build-deps.sh -sudo ./install-build-deps.sh --no-chromeos-fonts --no-nacl +sudo ./install-build-deps.sh --no-chromeos-fonts --no-nacl --no-arm ``` After dependencies are satisifed re-run automate.py. diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 632aab59c..35f850027 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/subprocess/Makefile b/src/subprocess/Makefile index 1ed3b15c1..580cb784f 100644 --- a/src/subprocess/Makefile +++ b/src/subprocess/Makefile @@ -27,13 +27,11 @@ INC = -I./../ -I./../common/ -I/usr/include/python2.7 \ -I/usr/lib/glib-2.0/include ifeq ($(UNAME_S), Linux) - LIB_DIRS = -L./../../build/cef_linux64/bin \ - -L./../../build/cef_linux32/bin \ - -L./../../build/cef_linux64/lib \ - -L./../../build/cef_linux32/lib + LIB_DIRS = -L$(CEF_BIN) \ + -L$(CEF_LIB) else ifeq ($(UNAME_S), Darwin) LIB_DIRS = -F$(CEF_BIN) \ - -L$(CEF_LIB) + -L$(CEF_LIB) endif ifeq ($(UNAME_S), Linux) diff --git a/src/version/cef_version_linux.h b/src/version/cef_version_linux.h index 39126c00a..5e718118b 100644 --- a/src/version/cef_version_linux.h +++ b/src/version/cef_version_linux.h @@ -35,16 +35,16 @@ #ifndef CEF_INCLUDE_CEF_VERSION_H_ #define CEF_INCLUDE_CEF_VERSION_H_ -#define CEF_VERSION "3.2883.1554.gf984155" +#define CEF_VERSION "3.2924.1575.g97389a9" #define CEF_VERSION_MAJOR 3 -#define CEF_COMMIT_NUMBER 1554 -#define CEF_COMMIT_HASH "f984155b3f0ad80833742d17cdab2065f3ec75ce" +#define CEF_COMMIT_NUMBER 1575 +#define CEF_COMMIT_HASH "97389a92ee2309ded830338d6afd61ba109d31d8" #define COPYRIGHT_YEAR 2017 -#define CHROME_VERSION_MAJOR 55 +#define CHROME_VERSION_MAJOR 56 #define CHROME_VERSION_MINOR 0 -#define CHROME_VERSION_BUILD 2883 -#define CHROME_VERSION_PATCH 87 +#define CHROME_VERSION_BUILD 2924 +#define CHROME_VERSION_PATCH 76 #define DO_MAKE_STRING(p) #p #define MAKE_STRING(p) DO_MAKE_STRING(p) @@ -63,13 +63,13 @@ extern "C" { // universal hash value will change if any platform is affected whereas the // platform hash values will change only if that particular platform is // affected. -#define CEF_API_HASH_UNIVERSAL "87b7eefcb86c87b28f86bfd7919f7d7a6cffc0d8" +#define CEF_API_HASH_UNIVERSAL "66de193ba22e1d92a99bb29d60f3107709aeefda" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "00823905486d7b7222da5654fe35d2d15f65543a" +#define CEF_API_HASH_PLATFORM "8055740cd08db66cefe838a826dc90806fadfb33" #elif defined(OS_MACOSX) -#define CEF_API_HASH_PLATFORM "f0180f006643782254250f34e858b98110a40e6e" +#define CEF_API_HASH_PLATFORM "12d8ab423df369b68d37c3667123a1812bc0d345" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "14b19454a4231fa10a77b8955954dc95f073af6b" +#define CEF_API_HASH_PLATFORM "86ab23c0d7dafbdff7f66764cf8dac5ec1712af4" #endif // Returns CEF version information for the libcef library. The |entry| diff --git a/tools/build.py b/tools/build.py index 0319a2ea5..df0355b43 100644 --- a/tools/build.py +++ b/tools/build.py @@ -23,12 +23,13 @@ Options: VERSION Version number eg. 50.0 --no-run-examples Do not run examples after build, only unit tests - --rebuild-cpp Force rebuild of .vcproj C++ projects (DISABLED) --fast Fast mode --clean Clean C++ projects build files on Linux/Mac --kivy Run only Kivy example """ +# --rebuild-cpp Force rebuild of .vcproj C++ projects (DISABLED) + # How to debug on Linux: # 1. Install "python-dbg" package # 2. Install "python-wxgtk2.8-dbg" package @@ -236,7 +237,7 @@ def setup_environ(): pass # Mac env variables for makefiles - if MAC: + if MAC or LINUX: os.environ["CEF_BIN"] = os.path.join(CEF_BINARIES_LIBRARIES, "bin") os.environ["CEF_LIB"] = os.path.join(CEF_BINARIES_LIBRARIES, "lib") @@ -306,29 +307,33 @@ def fix_cefpython_api_header_file(): print("[build.py] cefpython API header file was not yet generated") return + # Original contents with open(CEFPYTHON_API_HFILE, "rb") as fo: contents = fo.read().decode("utf-8") - already_fixed = False - pragma = "#pragma warning(disable:4190)" - if pragma in contents: - already_fixed = True - print("[build.py] cefpython API header file is already fixed") - else: - if not MAC: + # Pragma fix on Windows + if WINDOWS: + already_fixed = False + pragma = "#pragma warning(disable:4190)" + if pragma in contents: + already_fixed = True + print("[build.py] cefpython API header file is already fixed") + else: contents = ("%s\n\n" % pragma) + contents + with open(CEFPYTHON_API_HFILE, "wb") as fo: + fo.write(contents.encode("utf-8")) + print("[build.py] Save {filename}" + .format(filename=CEFPYTHON_API_HFILE)) - if not already_fixed: - with open(CEFPYTHON_API_HFILE, "wb") as fo: - fo.write(contents.encode("utf-8")) - print("[build.py] Save {filename}" - .format(filename=CEFPYTHON_API_HFILE)) - + # Make a copy with a "_fixed" postfix if os.path.exists(CEFPYTHON_API_HFILE_FIXED): with open(CEFPYTHON_API_HFILE_FIXED, "rb") as fo: contents_fixed = fo.read().decode("utf-8") else: contents_fixed = "" + + # Resave fixed copy only if contents changed. Other scripts + # depend on "modified time" of the "_fixed" file. if contents != contents_fixed: print("[build.py] Save cefpython_fixed.h") with open(CEFPYTHON_API_HFILE_FIXED, "wb") as fo: From 0c8a3b02b95b6bac4420752e07e256049736634d Mon Sep 17 00:00:00 2001 From: cztomczak Date: Tue, 14 Mar 2017 10:22:06 +0100 Subject: [PATCH 172/557] Reduce packages size with build_distrib.py tool (#321, #262)... Test wheel package installation in build_distrib.py. Add --no-rebuild flag to build_distrib.py. --- src/compile_time_constants.pxi | 4 +- tools/automate.py | 8 +- tools/build_distrib.py | 145 ++++++++++++++++++++++++++------- tools/common.py | 13 ++- 4 files changed, 132 insertions(+), 38 deletions(-) diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 35f850027..632aab59c 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/automate.py b/tools/automate.py index 97d7968c4..7fed6b255 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -348,7 +348,7 @@ def build_cef_projects(): "build_cefclient") cefclient_exe = os.path.join(build_cefclient_dir, "tests", "cefclient", Options.build_type, - "cefclient" + EXECUTABLE_EXT) + "cefclient" + APP_EXT) # Check whether already built already_built = False @@ -691,7 +691,7 @@ def create_prebuilt_binaries(): src, "build_cefclient", "tests", "cefclient", Options.build_type, - "cefclient" + EXECUTABLE_EXT) + "cefclient" + APP_EXT) if LINUX and os.path.exists(cefclient): # On Windows resources/*.html files are embedded inside exe cefclient_files = os.path.join( @@ -706,14 +706,14 @@ def create_prebuilt_binaries(): src, "build_cefclient", "tests", "cefsimple", Options.build_type, - "cefsimple" + EXECUTABLE_EXT) + "cefsimple" + APP_EXT) # ceftests ceftests = os.path.join( src, "build_cefclient", "tests", "ceftests", Options.build_type, - "ceftests" + EXECUTABLE_EXT) + "ceftests" + APP_EXT) if LINUX and os.path.exists(ceftests): # On Windows resources/*.html files are embedded inside exe ceftests_files = os.path.join( diff --git a/tools/build_distrib.py b/tools/build_distrib.py index 8368b63cd..c40035c73 100644 --- a/tools/build_distrib.py +++ b/tools/build_distrib.py @@ -6,16 +6,18 @@ Build distribution packages for all architectures and all supported python versions. -TODO: test_wheel_package_installation() TODO: Linux/Mac support. Currently runs only on Windows. Usage: - build_distrib.py VERSION [--no-run-examples] + build_distrib.py VERSION [--no-run-examples] [--no-rebuild] Options: VERSION Version number eg. 50.0 --no-run-examples Do not run examples while building cefpython modules. Only unit tests will be run in such case. + --no-rebuild Do not rebuild cefpython modules. For internal use + so that changes to packaging can be quickly tested. + This script does the following: 1. Expects that all supported python versions are installed @@ -27,17 +29,24 @@ 2. Expects that all python compilers for supported python versions are installed. See docs/Build-instructions.md > Requirements. 3. Expects cef_binary*/ directories from Spotify Automated Builds - to be in the build/ directory + to be in the build/ directory. It does not rebuild cefclient + nor libcef_dll_wrapper libraries in these directories. If you + would like to rebuild everything from scratch then delete subdirs + manually (build_cefclient/, build_wrapper*/). 4. Install and/or upgrade tools/requirements.txt and uninstall cefpython3 packages for all python versions 5. Run automate.py --prebuilt-cef using both Python 32-bit and Python 64-bit 6. Pack the prebuilt biaries using zip on Win/Mac and .tar.gz on Linux and move to build/distrib/ -7. Build cefpython modules for all supported Python versions on both +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 -8. Make setup installers and pack them to zip (Win/Mac) or .tar.gz (Linux) -9. Make wheel packages -10. Move setup and wheel packages to the build/distrib/ directory +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 +12. Test installation of wheel packages +13. Show summary """ from common import * @@ -52,6 +61,7 @@ # Command line args VERSION = "" NO_RUN_EXAMPLES = False +NO_REBUILD = False # Pythons SUPPORTED_PYTHON_VERSIONS = [(2, 7), (3, 4), (3, 5), (3, 6)] @@ -81,50 +91,67 @@ def main(): os.makedirs(DISTRIB_DIR) if pythons_32bit: run_automate_prebuilt_cef(pythons_32bit[0]) - pack_prebuilt_cef(pythons_32bit[0]["arch"]) + pack_prebuilt_cef("32bit") + if LINUX: + reduce_package_size_issue_262("32bit") + reduce_package_size_issue_321("32bit") if pythons_64bit is not None: run_automate_prebuilt_cef(pythons_64bit[0]) - pack_prebuilt_cef(pythons_64bit[0]["arch"]) - build_cefpython_modules(pythons_32bit + pythons_64bit) + pack_prebuilt_cef("64bit") + if LINUX: + reduce_package_size_issue_262("64bit") + reduce_package_size_issue_321("64bit") + if not NO_REBUILD: + build_cefpython_modules(pythons_32bit + pythons_64bit) if pythons_32bit: make_packages(pythons_32bit[0], "32bit") if pythons_64bit: make_packages(pythons_64bit[0], "64bit") - test_wheel_package_installation() + test_wheel_package_installation(pythons_32bit + pythons_64bit) show_summary(pythons_32bit, pythons_64bit) def command_line_args(): - global VERSION, NO_RUN_EXAMPLES + global VERSION, NO_RUN_EXAMPLES, NO_REBUILD version = get_version_from_command_line_args(__file__) - if not version: + if not version or "--help" in sys.argv: print(__doc__) sys.exit(1) VERSION = version if "--no-run-examples" in sys.argv: NO_RUN_EXAMPLES = True + sys.argv.remove("--no-run-examples") + if "--no-rebuild" in sys.argv: + NO_REBUILD = True + sys.argv.remove("--no-rebuild") + args = sys.argv[1:] + for arg in args: + if arg == version: + continue + print("[build_distrib.py] Invalid argument: {arg}".format(arg=arg)) + sys.exit(1) def clean_build_directories(): print("[build_distrib.py] Clean build directories") - # Distrib dir + # Delete distrib dir if os.path.exists(DISTRIB_DIR): print("[build_distrib.py] Delete directory: {distrib_dir}/" .format(distrib_dir=os.path.basename(DISTRIB_DIR))) shutil.rmtree(DISTRIB_DIR) - # build_cefpython/ dir - if os.path.exists(BUILD_CEFPYTHON): - print("[build_distirb.py] Delete directory: {dir}/" - .format(dir=os.path.basename(BUILD_CEFPYTHON))) - shutil.rmtree(BUILD_CEFPYTHON) - - # cefpython_binary_*/ dirs - delete_cefpython_binary_dir("32bit") - delete_cefpython_binary_dir("64bit") - - # cef binaries and libraries dirs + if not NO_REBUILD: + # Delete build_cefpython/ dir + if os.path.exists(BUILD_CEFPYTHON): + print("[build_distirb.py] Delete directory: {dir}/" + .format(dir=os.path.basename(BUILD_CEFPYTHON))) + shutil.rmtree(BUILD_CEFPYTHON) + # Delete cefpython_binary_*/ dirs + delete_cefpython_binary_dir("32bit") + delete_cefpython_binary_dir("64bit") + + # Delete cef binaries and libraries dirs delete_cef_binaries_libraries_dir("32bit") delete_cef_binaries_libraries_dir("64bit") @@ -344,6 +371,47 @@ def zip_directory(path, base_path, archive): os.chdir(original_dir) +def reduce_package_size_issue_262(arch): + """Linux only: libcef.so is huge (500 MB) in Chrome v54+. Issue #262.""" + print("[build_distrib.py] Reduce package size for {arch} (Issue #262)" + .format(arch=arch)) + prebuilt_basename = get_cef_binaries_libraries_basename( + get_postfix2_for_arch(arch)) + bin_dir = os.path.join(prebuilt_basename, "bin") + + # Run `strip` command on `libcef.so` + libcef_so = os.path.join(bin_dir, "libcef.so") + print("[build_distrib.py] Strip {libcef_so}" + .format(libcef_so=os.path.basename(libcef_so))) + command = "strip {libcef_so}".format(libcef_so=libcef_so) + pcode = subprocess.call(command) + if pcode != 0: + print("[build_distrib.py] ") + sys.exit(1) + + +def reduce_package_size_issue_321(arch): + """PyPI has file size limit and must reduce package size. Issue #321.""" + print("[build_distrib.py] Reduce package size for {arch} (Issue #321)" + .format(arch=arch)) + prebuilt_basename = get_cef_binaries_libraries_basename( + get_postfix2_for_arch(arch)) + bin_dir = os.path.join(prebuilt_basename, "bin") + + # Delete sample applications to reduce package size + sample_apps = ["cefclient", "cefsimple", "ceftests"] + for sample_app in sample_apps: + sample_app = os.path.join(bin_dir, sample_app + APP_EXT) + # Not on all platforms sample apps may be available + if os.path.exists(sample_app): + print("[build_distrib.py] Delete {sample_app}" + .format(sample_app=os.path.basename(sample_app))) + if os.path.isdir(sample_app): + shutil.rmtree(sample_app) + else: + os.remove(sample_app) + + def build_cefpython_modules(pythons): for python in pythons: print("[build_distrib.py] Build cefpython module for {python_name}" @@ -417,9 +485,28 @@ def make_packages(python, arch): shutil.rmtree(setup_dir) -def test_wheel_package_installation(): - # PYPI_POSTFIX2_ARCH - pass # TODO +def test_wheel_package_installation(pythons): + uninstall_cefpython3_packages(pythons) + for python in pythons: + print("[build_distrib.py] Test wheel package installation for" + " {python_name}".format(python_name=python["name"])) + platform_tag = get_pypi_postfix2_for_arch(python["arch"]) + whl_pattern = (r"*-{platform_tag}.whl" + .format(platform_tag=platform_tag)) + wheels = glob.glob(os.path.join(DISTRIB_DIR, whl_pattern)) + assert len(wheels) == 1, ("No wheels found in distrib dir for %s" + % python["arch"]) + # Install wheel + command = ("\"{python}\" -m pip install {wheel}" + .format(python=python["executable"], + wheel=os.path.basename(wheels[0]))) + if python["executable"].startswith("/usr/"): + command = "sudo {command}".format(command=command) + pcode = subprocess.call(command, cwd=DISTRIB_DIR) + if pcode != 0: + print("[build_distrib.py] Wheel package installation failed for" + " {python_name}".format(python_name=python["name"])) + sys.exit(1) def show_summary(pythons_32bit, pythons_64bit): @@ -436,7 +523,7 @@ def show_summary(pythons_32bit, pythons_64bit): count=len(files))) for file_ in files: print(" {filename}".format(filename=os.path.basename(file_))) - print("[build_distrib.py] Done. Distribution packages created.") + print("[build_distrib.py] Everything OK. Distribution packages created.") if __name__ == "__main__": diff --git a/tools/common.py b/tools/common.py index 360494172..3c868c2af 100644 --- a/tools/common.py +++ b/tools/common.py @@ -51,7 +51,7 @@ Darwin={"32bit": "mac32", "64bit": "mac64"}, ) PYPI_POSTFIX2_ARCH = dict( - Windows={"32bit": "win32", "64bit": "win-amd64"}, + Windows={"32bit": "win32", "64bit": "win_amd64"}, Linux={"32bit": "i686", "64bit": "x86_64"}, Darwin={"64bit": "x86_64"}, ) @@ -71,12 +71,15 @@ MODULE_NAME = MODULE_NAME_TEMPLATE.format(pyversion=PYVERSION, ext=MODULE_EXT) MODULE_NAME_NOEXT = MODULE_NAME_TEMPLATE_NOEXT.format(pyversion=PYVERSION) -# Executable extension +# App and Executable extensions if WINDOWS: + APP_EXT = ".exe" EXECUTABLE_EXT = ".exe" elif MAC: - EXECUTABLE_EXT = ".app" + APP_EXT = ".app" # cefclient, cefsimple, ceftests + EXECUTABLE_EXT = "" # subprocess else: + APP_EXT = "" EXECUTABLE_EXT = "" # Library extension @@ -193,6 +196,10 @@ def get_postfix2_for_arch(arch): return OS_POSTFIX2_ARCH[SYSTEM][arch] +def get_pypi_postfix2_for_arch(arch): + return PYPI_POSTFIX2_ARCH[SYSTEM][arch] + + def _detect_cef_binaries_libraries_dir(): """Detect cef binary directory created by automate.py eg. build/cef55_3.2883.1553.g80bd606_win32/ From d0844b1c5a44a5356f8477467511175095e3d675 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Tue, 14 Mar 2017 20:56:25 +0100 Subject: [PATCH 173/557] Fix and enhance tools for Linux (#327)... Add 32-bit support to automate.py. Fix build.py and build_distrib.py on Linux. Run unit tests in build_distrib.py after wheel package was installed. --- docs/Build-instructions.md | 9 +- src/compile_time_constants.pxi | 2 +- tools/automate.py | 34 +++-- tools/build.py | 64 ++++------ tools/build_distrib.py | 222 ++++++++++++++++++++------------- tools/common.py | 53 ++++++-- tools/run_examples.py | 5 +- 7 files changed, 237 insertions(+), 152 deletions(-) diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index 1b0cc0e2e..f52645a84 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -204,6 +204,8 @@ requirements common for all platforms. [cef/BuildingOnDebian7.md](https://bitbucket.org/chromiumembedded/cef/wiki/BuildingOnDebian7.md) and [cef/#1575](https://bitbucket.org/chromiumembedded/cef/issues/1575), and [cef/#1697](https://bitbucket.org/chromiumembedded/cef/issues/1697) +* If building CEF from sources, 32-bit on 64-bit machine: + * Follow the configuration [here](https://bitbucket.org/chromiumembedded/cef/wiki/AutomatedBuildSetup.md#markdown-header-linux-configuration) * To perform a 32-bit Linux build on a 64-bit Linux system see Linux configuration in upstream cef/AutomatedBuildSetup.md. See also [cef/#1804](https://bitbucket.org/chromiumembedded/cef/issues/1804). @@ -311,14 +313,15 @@ On Linux if there are errors about missing packages or others, then see solutions in the [Possible errors](#possible-errors) section. The commands below will build CEF from sources with custom CEF Python -patches applied and then build the CEF Python package (xx.x is version -number): +patches applied and then build the CEF Python package. "xx.x" is version +number and "ninja-jobs 4" means to run 4 parallel jobs for compiling, +increase it if you have more CPU cores and want things to build faster: ``` git clone https://github.com/cztomczak/cefpython.git cd cefpython/ mkdir build/ cd build/ -python ../tools/automate.py --build-cef --ninja-jobs 6 +python ../tools/automate.py --build-cef --ninja-jobs 4 python ../tools/build.py xx.x ``` diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 632aab59c..47dedaecd 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 = "Linux" DEF PY_MAJOR_VERSION = 3 diff --git a/tools/automate.py b/tools/automate.py index 7fed6b255..716f9c579 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -6,7 +6,10 @@ Prepares CEF binaries and libraries for work with the build.py tool. Option 1 is to build CEF from sources with the CEF Python patches applied -using the --build-cef flag. +using the --build-cef flag. Building CEF from sources is supported only +on 64-bit systems. 32-bit is also built on 64-bit using cross-compiling. +Note that building CEF from sources was last tested with v56 on Linux +and with v50 on Windows, so if there are issues report them on the Forum. Option 2 is to use CEF binaries from Spotify Automated Builds using the --prebuilt-cef flag. In such case check the cefpython/src/version/ @@ -22,6 +25,7 @@ Usage: automate.py (--prebuilt-cef | --build-cef) + [--x86 X86] [--fast-build FAST_BUILD] [--force-chromium-update FORCE_CHROMIUM_UPDATE] [--no-cef-update NO_CEF_UPDATE] @@ -37,6 +41,7 @@ binaries for Linux are built on Ubuntu. --build-cef Whether to build CEF from sources with the cefpython patches applied. + --x86 Build 32-bit CEF on 64-bit system --fast-build Fast build with is_official_build=False --force-chromium-update Force Chromium update (gclient sync etc). --no-cef-update Do not update CEF sources (by default both cef/ @@ -82,6 +87,7 @@ class Options(object): # From command-line prebuilt_cef = False build_cef = False + x86 = False fast_build = False force_chromium_update = False no_cef_update = False @@ -223,17 +229,20 @@ def prebuilt_cef(): # eg. tag 'upstream-cef47'. # Find cef_binary directory in the build directory + postfix2 = CEF_POSTFIX2 + if Options.x86: + postfix2 = get_cef_postfix2_for_arch("32bit") if Options.cef_version: cef_binary = os.path.join(Options.build_dir, "cef_binary_{cef_version}_{os}{sep}" .format(cef_version=Options.cef_version, - os=CEF_POSTFIX2, + os=postfix2, sep=os.sep)) else: cef_binary = os.path.join(Options.build_dir, "cef_binary_3.{cef_branch}.*_{os}{sep}" .format(cef_branch=Options.cef_branch, - os=CEF_POSTFIX2, + os=postfix2, sep=os.sep)) dirs = glob.glob(cef_binary) if len(dirs) == 1: @@ -336,8 +345,11 @@ def build_cef_projects(): cef_binary = symbols.replace("_debug_symbols", "") assert "symbols" not in os.path.basename(cef_binary) else: + postfix2 = CEF_POSTFIX2 + if Options.x86: + postfix2 = get_cef_postfix2_for_arch("32bit") files = glob.glob(os.path.join(Options.binary_distrib, - "cef_binary_*_"+OS_POSTFIX2)) + "cef_binary_*_"+postfix2)) assert len(files) == 1, "Error finding binary distrib" cef_binary = files[0] assert os.path.exists(cef_binary) @@ -832,7 +844,6 @@ def getenv(): # GN configuration env["CEF_USE_GN"] = "1" # Issue #73 patch applied here with "use_allocator=none" - # TODO: 32-bit GN defines: host_arch=x86_64 target_arch=ia32 env["GN_DEFINES"] = "use_sysroot=true use_allocator=none symbol_level=1" # env["GN_DEFINES"] += " use_gtk3=false" # To perform an official build set GYP_DEFINES=buildtype=Official. @@ -845,7 +856,8 @@ def getenv(): # upstream Linux configuration on AutomatedBuildSetup wiki page, # so setting it here as well. env["GYP_DEFINES"] = "disable_nacl=1 use_sysroot=1 use_allocator=none" - # Note: 32-bit GYP defines: host_arch=x86_64 target_arch=ia32 + if Options.x86: + env["GYP_DEFINES"] += " host_arch=x86_64 target_arch=ia32" if Options.release_build and not Options.fast_build: env["GYP_DEFINES"] += " buildtype=Official" @@ -872,8 +884,7 @@ def run_command(command, working_dir, env=None): args = command if not env: env = getenv() - return subprocess.check_call(args, cwd=working_dir, env=env, - shell=(platform.system() == "Windows")) + return subprocess.check_call(args, cwd=working_dir, env=env, shell=True) def run_git(command_line, working_dir): @@ -893,7 +904,7 @@ def run_automate_git(): ninja -v -j2 -Cout\Release cefclient """ args = [] - if ARCH64: + if ARCH64 and not Options.x86: args.append("--x64-build") args.append("--download-dir=" + Options.cef_build_dir) args.append("--branch=" + Options.cef_branch) @@ -972,10 +983,13 @@ def get_prebuilt_name(header_file=""): version = get_version_from_file(header_file) else: version = get_cefpython_version() + postfix2 = OS_POSTFIX2 + if Options.x86: + postfix2 = get_os_postfix2_for_arch("32bit") name = "cef%s_%s_%s" % ( version["CHROME_VERSION_MAJOR"], version["CEF_VERSION"], - OS_POSTFIX2, + postfix2 ) return name diff --git a/tools/build.py b/tools/build.py index df0355b43..375d64973 100644 --- a/tools/build.py +++ b/tools/build.py @@ -313,10 +313,8 @@ def fix_cefpython_api_header_file(): # Pragma fix on Windows if WINDOWS: - already_fixed = False pragma = "#pragma warning(disable:4190)" if pragma in contents: - already_fixed = True print("[build.py] cefpython API header file is already fixed") else: contents = ("%s\n\n" % pragma) + contents @@ -701,18 +699,11 @@ def build_cefpython_module(): os.chdir(BUILD_CEFPYTHON) + command = ("\"{python}\" {tools_dir}/cython_setup.py build_ext" + .format(python=sys.executable, tools_dir=TOOLS_DIR)) if FAST_FLAG: - ret = subprocess.call("\"{python}\" {tools_dir}/cython_setup.py" - " build_ext --fast" - .format(python=sys.executable, - tools_dir=TOOLS_DIR), - shell=True) - else: - ret = subprocess.call("\"{python}\" {tools_dir}/cython_setup.py" - " build_ext" - .format(python=sys.executable, - tools_dir=TOOLS_DIR), - shell=True) + command += " --fast" + ret = subprocess.call(command, shell=True) # if DEBUG_FLAG: # shutil.rmtree("./../binaries_%s/cython_debug/" % BITS, @@ -741,7 +732,8 @@ def build_cefpython_module(): args.append(os.path.join(TOOLS_DIR, os.path.basename(__file__))) assert __file__ in sys.argv[0] args.extend(sys.argv[1:]) - ret = subprocess.call(" ".join(args), shell=True) + command = " ".join(args) + ret = subprocess.call(command, shell=True) sys.exit(ret) else: print("[build.py] ERROR: failed to build the cefpython module") @@ -806,10 +798,11 @@ def install_and_run(): # Make setup installer print("[build.py] Make setup installer") make_tool = os.path.join(TOOLS_DIR, "make_installer.py") - ret = os.system("\"{python}\" {make_tool} --version {version}" - .format(python=sys.executable, - make_tool=make_tool, - version=VERSION)) + command = ("\"{python}\" {make_tool} --version {version}" + .format(python=sys.executable, + make_tool=make_tool, + version=VERSION)) + ret = os.system(command) if ret != 0: print("[build.py] ERROR while making installer package") sys.exit(ret) @@ -817,8 +810,10 @@ def install_and_run(): # Install print("[build.py] Install the cefpython package") os.chdir(setup_installer_dir) - ret = os.system("{sudo} \"{python}\" setup.py install" - .format(sudo=get_sudo(), python=sys.executable)) + command = ("\"{python}\" setup.py install" + .format(python=sys.executable)) + command = sudo_command(command, python=sys.executable) + ret = os.system(command) if ret != 0: print("[build.py] ERROR while installing package") sys.exit(ret) @@ -830,8 +825,10 @@ def install_and_run(): # Run unittests print("[build.py] Run unittests") test_runner = os.path.join(UNITTESTS_DIR, "_test_runner.py") - ret = os.system("\"{python}\" {test_runner}" - .format(python=sys.executable, test_runner=test_runner)) + command = ("\"{python}\" {test_runner}" + .format(python=sys.executable, + test_runner=test_runner)) + ret = os.system(command) if ret != 0: print("[build.py] ERROR while running unit tests") sys.exit(ret) @@ -842,10 +839,11 @@ def install_and_run(): os.chdir(EXAMPLES_DIR) kivy_flag = "--kivy" if KIVY_FLAG else "" run_examples = os.path.join(TOOLS_DIR, "run_examples.py") - ret = os.system("\"{python}\" {run_examples} {kivy_flag}" - .format(python=sys.executable, - run_examples=run_examples, - kivy_flag=kivy_flag)) + command = ("\"{python}\" {run_examples} {kivy_flag}" + .format(python=sys.executable, + run_examples=run_examples, + kivy_flag=kivy_flag)) + ret = os.system(command) if ret != 0: print("[build.py] ERROR while running examples") sys.exit(1) @@ -853,15 +851,6 @@ def install_and_run(): print("[build.py] Everything OK") -def get_sudo(): - # System Python requires sudo when installing package - if sys.executable.startswith("/usr/"): - sudo = "sudo" - else: - sudo = "" - return sudo - - def delete_directory_reliably(adir): assert len(adir) > 2 assert os.path.isdir(adir) @@ -873,8 +862,9 @@ def delete_directory_reliably(adir): # On Linux sudo might be required to delete directory, as this # might be a setup installer directory with package installed # using sudo and in such case files were created with sudo. - os.system("{sudo} rm -rf {dir}" - .format(sudo=get_sudo(), dir=adir)) + command = "rm -rf {dir}".format(dir=adir) + command = sudo_command(command, python=sys.executable) + os.system(command) if __name__ == "__main__": diff --git a/tools/build_distrib.py b/tools/build_distrib.py index c40035c73..93f3cf340 100644 --- a/tools/build_distrib.py +++ b/tools/build_distrib.py @@ -6,7 +6,7 @@ Build distribution packages for all architectures and all supported python versions. -TODO: Linux/Mac support. Currently runs only on Windows. +TODO: Mac support. Currently runs only on Windows/Linux. Usage: build_distrib.py VERSION [--no-run-examples] [--no-rebuild] @@ -14,7 +14,8 @@ Options: VERSION Version number eg. 50.0 --no-run-examples Do not run examples while building cefpython modules. - Only unit tests will be run in such case. + Examples require interaction, closing window before + proceeding. Only unit tests will be run in such case. --no-rebuild Do not rebuild cefpython modules. For internal use so that changes to packaging can be quickly tested. @@ -33,6 +34,8 @@ nor libcef_dll_wrapper libraries in these directories. If you would like to rebuild everything from scratch then delete subdirs manually (build_cefclient/, build_wrapper*/). + When building CEF from sources copy build/chromium/src/cef/binary_distrib + /cef_binary_*/ to the build/ directory. 4. Install and/or upgrade tools/requirements.txt and uninstall cefpython3 packages for all python versions 5. Run automate.py --prebuilt-cef using both Python 32-bit and Python 64-bit @@ -45,7 +48,8 @@ 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 -12. Test installation of wheel packages +12. Test wheel packages installation and run unit tests using the + installed wheel package. 13. Show summary """ @@ -56,6 +60,7 @@ import re import shutil import subprocess +import tarfile import zipfile # Command line args @@ -63,27 +68,45 @@ NO_RUN_EXAMPLES = False NO_REBUILD = False -# Pythons +# Python versions SUPPORTED_PYTHON_VERSIONS = [(2, 7), (3, 4), (3, 5), (3, 6)] -PYTHON_SEARCH_PATHS_WINDOWS = [ - "C:\\Python*\\", - "%LocalAppData%\\Programs\\Python\\Python*\\", - "C:\\Program Files\\Python*\\", - "C:\\Program Files (x86)\\Python*\\", -] + +# Python search paths. It will use first Python found for specific version. +# Supports replacement of one environment variable in path eg.: %ENV_KEY%. +PYTHON_SEARCH_PATHS = dict( + WINDOWS=[ + "C:\\Python*\\", + "%LOCALAPPDATA%\\Programs\\Python\\Python*\\", + "C:\\Program Files\\Python*\\", + "C:\\Program Files (x86)\\Python*\\", + ], + LINUX=[ + "%PYENV_ROOT%/versions/*/bin", + ], +) def main(): command_line_args() - print("[build_distrib.py] Supported python versions:") - pp = pprint.PrettyPrinter(indent=4) - pp.pprint(SUPPORTED_PYTHON_VERSIONS) + supported = list() + for version in SUPPORTED_PYTHON_VERSIONS: + supported.append("{major}.{minor}".format(major=version[0], + minor=version[1])) + print("[build_distrib.py] Supported python versions: {supported}" + .format(supported=" / ".join(supported))) clean_build_directories() - pythons_32bit = list() - pythons_64bit = list() if WINDOWS: pythons_32bit = search_for_pythons("32bit") pythons_64bit = search_for_pythons("64bit") + elif LINUX: + pythons_32bit = search_for_pythons("32bit") if ARCH32 else list() + pythons_64bit = search_for_pythons("64bit") if ARCH64 else list() + elif MAC: + pythons_32bit = list() + pythons_64bit = search_for_pythons("64bit") + else: + print("ERROR: Unsupported OS") + sys.exit(1) check_pythons(pythons_32bit, pythons_64bit) install_upgrade_requirements(pythons_32bit + pythons_64bit) uninstall_cefpython3_packages(pythons_32bit + pythons_64bit) @@ -107,7 +130,7 @@ def main(): make_packages(pythons_32bit[0], "32bit") if pythons_64bit: make_packages(pythons_64bit[0], "64bit") - test_wheel_package_installation(pythons_32bit + pythons_64bit) + test_wheel_packages(pythons_32bit + pythons_64bit) show_summary(pythons_32bit, pythons_64bit) @@ -158,7 +181,7 @@ def clean_build_directories(): def delete_cefpython_binary_dir(arch): cefpython_binary = get_cefpython_binary_basename( - postfix2=get_postfix2_for_arch(arch)) + postfix2=get_os_postfix2_for_arch(arch)) assert cefpython_binary, cefpython_binary cefpython_binary = os.path.join(BUILD_DIR, cefpython_binary) if os.path.exists(cefpython_binary): @@ -169,7 +192,7 @@ def delete_cefpython_binary_dir(arch): def delete_cef_binaries_libraries_dir(arch): cef_binlib = get_cef_binaries_libraries_basename( - postfix2=get_postfix2_for_arch(arch)) + postfix2=get_os_postfix2_for_arch(arch)) assert cef_binlib, cef_binlib cef_binlib = os.path.join(BUILD_DIR, cef_binlib) if os.path.exists(cef_binlib): @@ -178,45 +201,31 @@ def delete_cef_binaries_libraries_dir(arch): shutil.rmtree(cef_binlib) -def check_pythons(pythons_32bit, pythons_64bit): - pp = pprint.PrettyPrinter(indent=4) - if pythons_32bit: - print("[build_distrib.py] Pythons 32-bit found:") - pp.pprint(pythons_32bit) - if WINDOWS and len(pythons_32bit) != len(SUPPORTED_PYTHON_VERSIONS): - print("[build_distrib.py] ERROR: Couldn't find all supported" - " python 32-bit installations. Found: {found}." - .format(found=len(pythons_32bit))) - sys.exit(1) - if pythons_64bit: - print("[build_distrib.py] Pythons 64-bit found:") - pp.pprint(pythons_64bit) - if len(pythons_64bit) != len(SUPPORTED_PYTHON_VERSIONS): - print("[build_distrib.py] ERROR: Couldn't find all supported" - " python 64-bit installations. Found: {found}." - .format(found=len(pythons_64bit))) - sys.exit(1) - - def search_for_pythons(search_arch): - print("[build_distrib.py] Search for Pythons...") - if WINDOWS: - return search_for_pythons_windows(search_arch) - raise Exception("Only Windows platform supported currently") - - -def search_for_pythons_windows(search_arch): """Returns pythons ordered by version from lowest to highest.""" pythons_found = list() - for pattern in PYTHON_SEARCH_PATHS_WINDOWS: - pattern = pattern.replace("%LocalAppData%", - os.environ["LOCALAPPDATA"]) + for pattern in PYTHON_SEARCH_PATHS[SYSTEM]: + # Replace env variable in path + match = re.search(r"%(\w+)%", pattern) + if match: + env_key = match.group(1) + if env_key in os.environ: + pattern = pattern.replace(match.group(0), os.environ[env_key]) + else: + print("ERROR: Env variable not found: {env_key}" + .format(env_key=env_key)) + sys.exit(1) results = glob.glob(pattern) for path in results: if os.path.isdir(path): - python = os.path.join(path, "python.exe") + python = os.path.join(path, + "python{ext}".format(ext=EXECUTABLE_EXT)) version_code = ("import sys;" "print(str(sys.version_info[:3]));") + if not os.path.isfile(python): + print("ERROR: Python executable not found: {executable}" + .format(executable=python)) + sys.exit(1) version_str = subprocess.check_output([python, "-c", version_code]) version_str = version_str.strip() @@ -247,26 +256,42 @@ def search_for_pythons_windows(search_arch): supported_python = None for python in pythons_found: if python["version2"] == version_tuple: - # Always go through the whole loop and save the last - # python executable for the given version (eg. 2.7), - # so that the latest version is used (eg. 2.7.12). - # This is assuming that glob.glob sorted directories. supported_python = python + break if supported_python: ret_pythons.append(supported_python) return ret_pythons +def check_pythons(pythons_32bit, pythons_64bit): + pp = pprint.PrettyPrinter(indent=4) + if pythons_32bit: + print("[build_distrib.py] Pythons 32-bit found:") + pp.pprint(pythons_32bit) + if WINDOWS and len(pythons_32bit) != len(SUPPORTED_PYTHON_VERSIONS): + print("[build_distrib.py] ERROR: Couldn't find all supported" + " python 32-bit installations. Found: {found}." + .format(found=len(pythons_32bit))) + sys.exit(1) + if pythons_64bit: + print("[build_distrib.py] Pythons 64-bit found:") + pp.pprint(pythons_64bit) + if len(pythons_64bit) != len(SUPPORTED_PYTHON_VERSIONS): + print("[build_distrib.py] ERROR: Couldn't find all supported" + " python 64-bit installations. Found: {found}." + .format(found=len(pythons_64bit))) + sys.exit(1) + + def install_upgrade_requirements(pythons): for python in pythons: print("[build_distrib.py] pip install/upgrade requirements.txt" " for: {name}".format(name=python["name"])) # Upgrade pip - command = "\"{python}\" -m pip install --upgrade pip" - command = command.format(python=python["executable"]) - if python["executable"].startswith("/usr/"): - command = "sudo {command}".format(command=command) + command = ("\"{python}\" -m pip install --upgrade pip" + .format(python=python["executable"])) + command = sudo_command(command, python=python["executable"]) pcode = subprocess.call(command, shell=True) if pcode != 0: print("[build_distrib.py] ERROR while upgrading pip") @@ -274,11 +299,10 @@ def install_upgrade_requirements(pythons): # Install/upgrade requirements.txt requirements = os.path.join(TOOLS_DIR, "requirements.txt") - command = "\"{python}\" -m pip install --upgrade -r {requirements}" - command = command.format(python=python["executable"], - requirements=requirements) - if python["executable"].startswith("/usr/"): - command = "sudo {command}".format(command=command) + command = ("\"{python}\" -m pip install --upgrade -r {requirements}" + .format(python=python["executable"], + requirements=requirements)) + command = sudo_command(command, python=python["executable"]) pcode = subprocess.call(command, shell=True) if pcode != 0: print("[build_distrib.py] ERROR while running pip install/upgrade") @@ -287,14 +311,14 @@ def install_upgrade_requirements(pythons): def uninstall_cefpython3_packages(pythons): for python in pythons: - print("[build_distrib.py] pip uninstall cefpython3 package" + print("[build_distrib.py] Uninstall cefpython3 package" " for: {name}".format(name=python["name"])) # Check if package is installed command = ("\"{python}\" -m pip show cefpython3" .format(python=python["executable"])) try: - output = subprocess.check_output(command) + output = subprocess.check_output(command, shell=True) except subprocess.CalledProcessError, exc: # pip show returns error code when package is not installed output = exc.output @@ -307,8 +331,7 @@ def uninstall_cefpython3_packages(pythons): # otherwise error code is returned. command = ("\"{python}\" -m pip uninstall -y cefpython3" .format(python=python["executable"])) - if python["executable"].startswith("/usr/"): - command = "sudo {command}".format(command=command) + command = sudo_command(command, python=python["executable"]) pcode = subprocess.call(command, shell=True) if pcode != 0: print("[build_distrib.py] ERROR while uninstall cefpython3" @@ -322,7 +345,7 @@ def run_automate_prebuilt_cef(python): automate = os.path.join(TOOLS_DIR, "automate.py") command = ("\"{python}\" {automate} --prebuilt-cef" .format(python=python["executable"], automate=automate)) - code = subprocess.call(command) + code = subprocess.call(command, shell=True) if code != 0: print("[build_distrib.py] ERROR while running automate.py") sys.exit(1) @@ -330,7 +353,7 @@ def run_automate_prebuilt_cef(python): def pack_prebuilt_cef(arch): prebuilt_basename = get_cef_binaries_libraries_basename( - get_postfix2_for_arch(arch)) + get_os_postfix2_for_arch(arch)) print("[build_distrib.py] Pack directory: {dir}/ ..." .format(dir=prebuilt_basename)) prebuilt_dir = os.path.join(BUILD_DIR, prebuilt_basename) @@ -351,8 +374,8 @@ def pack_directory(path, base_path): if WINDOWS or MAC: zip_directory(path, base_path=base_path, archive=archive) else: - # LINUX - raise Exception("pack_directory(): Linux not yet supported") # TODO + with tarfile.open(archive, "w:gz") as tar: + tar.add(path, arcname=os.path.basename(path)) assert os.path.isfile(archive), archive return archive @@ -376,7 +399,7 @@ def reduce_package_size_issue_262(arch): print("[build_distrib.py] Reduce package size for {arch} (Issue #262)" .format(arch=arch)) prebuilt_basename = get_cef_binaries_libraries_basename( - get_postfix2_for_arch(arch)) + get_os_postfix2_for_arch(arch)) bin_dir = os.path.join(prebuilt_basename, "bin") # Run `strip` command on `libcef.so` @@ -384,10 +407,8 @@ def reduce_package_size_issue_262(arch): print("[build_distrib.py] Strip {libcef_so}" .format(libcef_so=os.path.basename(libcef_so))) command = "strip {libcef_so}".format(libcef_so=libcef_so) - pcode = subprocess.call(command) - if pcode != 0: - print("[build_distrib.py] ") - sys.exit(1) + pcode = subprocess.call(command, shell=True) + assert pcode, "strip command failed" def reduce_package_size_issue_321(arch): @@ -395,13 +416,13 @@ def reduce_package_size_issue_321(arch): print("[build_distrib.py] Reduce package size for {arch} (Issue #321)" .format(arch=arch)) prebuilt_basename = get_cef_binaries_libraries_basename( - get_postfix2_for_arch(arch)) + get_os_postfix2_for_arch(arch)) bin_dir = os.path.join(prebuilt_basename, "bin") # Delete sample applications to reduce package size sample_apps = ["cefclient", "cefsimple", "ceftests"] - for sample_app in sample_apps: - sample_app = os.path.join(bin_dir, sample_app + APP_EXT) + for sample_app_name in sample_apps: + sample_app = os.path.join(bin_dir, sample_app_name + APP_EXT) # Not on all platforms sample apps may be available if os.path.exists(sample_app): print("[build_distrib.py] Delete {sample_app}" @@ -410,6 +431,20 @@ def reduce_package_size_issue_321(arch): shutil.rmtree(sample_app) else: os.remove(sample_app) + # Also delete subdirs eg. cefclient_files/, ceftests_files/ + files_subdir = os.path.join(bin_dir, sample_app_name + "_files") + if os.path.isdir(files_subdir): + print("[build_distrib.py] Delete directory: {dir}/" + .format(dir=os.path.basename(files_subdir))) + shutil.rmtree(files_subdir) + + # Strip symbols from cefpython .so modules to reduce size + modules = glob.glob(os.path.join(CEFPYTHON_BINARY, "*.so")) + for module in modules: + print("[build_distrib.py] strip {module}" + .format(module=os.path.basename(module))) + command = "strip {module}".format(module=module) + assert os.system(command) == 0, "strip command failed" def build_cefpython_modules(pythons): @@ -419,7 +454,8 @@ def build_cefpython_modules(pythons): flags = "" if NO_RUN_EXAMPLES: flags += " --no-run-examples" - command = ("\"{python}\" {build_py} {version} {flags}" + # On Linux/Mac Makefiles are used and must pass --clean flag + command = ("\"{python}\" {build_py} {version} --clean {flags}" .format(python=python["executable"], build_py=os.path.join(TOOLS_DIR, "build.py"), version=VERSION, @@ -446,7 +482,7 @@ def make_packages(python, arch): .format(python=python["executable"], make_installer_py=make_installer_py, version=VERSION)) - pcode = subprocess.call(installer_command, cwd=BUILD_DIR) + pcode = subprocess.call(installer_command, cwd=BUILD_DIR, shell=True) if pcode != 0: print("[build_distrib.py] ERROR: failed to make setup package for" " {arch}".format(arch=arch)) @@ -456,7 +492,7 @@ def make_packages(python, arch): print("[build_distrib.py] Pack setup package for {arch}..." .format(arch=arch)) setup_basename = get_setup_installer_basename( - VERSION, get_postfix2_for_arch(arch)) + VERSION, get_os_postfix2_for_arch(arch)) setup_dir = os.path.join(BUILD_DIR, setup_basename) archive = pack_directory(setup_dir, BUILD_DIR) shutil.move(archive, DISTRIB_DIR) @@ -468,7 +504,7 @@ def make_packages(python, arch): wheel_command = ("\"{python}\" setup.py {wheel_args}" .format(python=python["executable"], wheel_args=wheel_args)) - pcode = subprocess.call(wheel_command, cwd=setup_dir) + pcode = subprocess.call(wheel_command, cwd=setup_dir, shell=True) if pcode != 0: print("[build_distrib.py] ERROR: failed to make wheel package for" " {arch}".format(arch=arch)) @@ -485,10 +521,11 @@ def make_packages(python, arch): shutil.rmtree(setup_dir) -def test_wheel_package_installation(pythons): +def test_wheel_packages(pythons): + """Test wheel packages installation and run unit tests.""" uninstall_cefpython3_packages(pythons) for python in pythons: - print("[build_distrib.py] Test wheel package installation for" + print("[build_distrib.py] Test wheel package (install, unittests) for" " {python_name}".format(python_name=python["name"])) platform_tag = get_pypi_postfix2_for_arch(python["arch"]) whl_pattern = (r"*-{platform_tag}.whl" @@ -496,18 +533,29 @@ def test_wheel_package_installation(pythons): wheels = glob.glob(os.path.join(DISTRIB_DIR, whl_pattern)) assert len(wheels) == 1, ("No wheels found in distrib dir for %s" % python["arch"]) + # Install wheel command = ("\"{python}\" -m pip install {wheel}" .format(python=python["executable"], wheel=os.path.basename(wheels[0]))) - if python["executable"].startswith("/usr/"): - command = "sudo {command}".format(command=command) - pcode = subprocess.call(command, cwd=DISTRIB_DIR) + command = sudo_command(command, python=python["executable"]) + pcode = subprocess.call(command, cwd=DISTRIB_DIR, shell=True) if pcode != 0: print("[build_distrib.py] Wheel package installation failed for" " {python_name}".format(python_name=python["name"])) sys.exit(1) + # Run unittests using the installed wheel package + command = ("\"{python}\" {unittests}" + .format(python=python["executable"], + unittests=os.path.join(UNITTESTS_DIR, + "main_test.py"))) + pcode = subprocess.call(command, cwd=DISTRIB_DIR, shell=True) + if pcode != 0: + print("[build_distrib.py] ERROR: Unit tests failed for" + " {python_name}".format(python_name=python["name"])) + sys.exit(1) + def show_summary(pythons_32bit, pythons_64bit): print("[build_distrib.py] SUMMARY:") diff --git a/tools/common.py b/tools/common.py index 3c868c2af..b84476d81 100644 --- a/tools/common.py +++ b/tools/common.py @@ -21,6 +21,7 @@ if ARCH64: assert platform.architecture()[0] == "64bit" ARCH_STR = platform.architecture()[0] + # OS_POSTFIX is for directories/files names in cefpython sources # OS_POSTFIX2 is for platform name in cefpython binaries # CEF_POSTFIX2 is for platform name in upstream CEF binaries @@ -29,6 +30,7 @@ "mac" if platform.system() == "Darwin" else "unknown") OS_POSTFIX2 = "unknown" CEF_POSTFIX2 = "unknown" # Upstream CEF binaries postfix + if OS_POSTFIX == "win": OS_POSTFIX2 = "win32" if ARCH32 else "win64" CEF_POSTFIX2 = "windows32" if ARCH32 else "windows64" @@ -40,20 +42,25 @@ CEF_POSTFIX2 = "linux32" if ARCH32 else "linux64" # Platforms -SYSTEM = platform.system() -WINDOWS = SYSTEM if SYSTEM == "Windows" else False -LINUX = SYSTEM if SYSTEM == "Linux" else False -MAC = SYSTEM if SYSTEM == "Darwin" else False +SYSTEM = platform.system().upper() +WINDOWS = SYSTEM if SYSTEM == "WINDOWS" else False +LINUX = SYSTEM if SYSTEM == "LINUX" else False +MAC = SYSTEM if SYSTEM == "DARWIN" else False OS_POSTFIX2_ARCH = dict( - Windows={"32bit": "win32", "64bit": "win64"}, - Linux={"32bit": "linux32", "64bit": "linux64"}, - Darwin={"32bit": "mac32", "64bit": "mac64"}, + WINDOWS={"32bit": "win32", "64bit": "win64"}, + LINUX={"32bit": "linux32", "64bit": "linux64"}, + DARWIN={"32bit": "mac32", "64bit": "mac64"}, +) +CEF_POSTFIX2_ARCH = dict( + WINDOWS={"32bit": "windows32", "64bit": "windows64"}, + LINUX={"32bit": "linux32", "64bit": "linux64"}, + DARWIN={"64bit": "macosx64"}, ) PYPI_POSTFIX2_ARCH = dict( - Windows={"32bit": "win32", "64bit": "win_amd64"}, - Linux={"32bit": "i686", "64bit": "x86_64"}, - Darwin={"64bit": "x86_64"}, + WINDOWS={"32bit": "win32", "64bit": "win_amd64"}, + LINUX={"32bit": "manylinux1_i686", "64bit": "manylinux1_x86_64"}, + DARWIN={"64bit": "x86_64"}, ) # Python version eg. 27 @@ -192,14 +199,26 @@ os.environ["LOCALAPPDATA"]) -def get_postfix2_for_arch(arch): +def get_os_postfix2_for_arch(arch): return OS_POSTFIX2_ARCH[SYSTEM][arch] +def get_cef_postfix2_for_arch(arch): + return CEF_POSTFIX2_ARCH[SYSTEM][arch] + + def get_pypi_postfix2_for_arch(arch): return PYPI_POSTFIX2_ARCH[SYSTEM][arch] +def sudo_command(command, python): + """Prepends command with sudo when installing python packages + requires sudo.""" + if python.startswith("/usr/"): + command = "sudo " + command + return command + + def _detect_cef_binaries_libraries_dir(): """Detect cef binary directory created by automate.py eg. build/cef55_3.2883.1553.g80bd606_win32/ @@ -273,7 +292,17 @@ def _detect_distrib_dir(): # Will only be set when called from scripts that had version # number arg passed on command line: build.py, build_distrib.py, # make_installer.py, etc. - dirname = "distrib_{version}".format(version=version) + if LINUX: + # On Linux buildig 32bit and 64bit separately, so don't + # delete eg. 64bit distrib when building 32bit distrib. + # Keep them in different directories. + dirname = ("distrib_{version}_{postfix2}" + .format(version=version, postfix2=OS_POSTFIX2)) + else: + # On Windows both 32bit and 64bit distribs are built at + # the same time. + # On Mac only 64bit is supported. + dirname = "distrib_{version}".format(version=version) DISTRIB_DIR = os.path.join(BUILD_DIR, dirname) diff --git a/tools/run_examples.py b/tools/run_examples.py index 9f2583c65..6562af669 100644 --- a/tools/run_examples.py +++ b/tools/run_examples.py @@ -96,8 +96,9 @@ def main(): for example in examples: print("[run_examples.py] Running '{example}'..." .format(example=example)) - ret = os.system("\"{python}\" {example}" - .format(python=sys.executable, example=example)) + command = "\"{python}\" {example}".format(python=sys.executable, + example=example) + ret = os.system(command) if ret == 0: succeeded.append(example) else: From c472898bc06aa6134d1b4cf385dc6a904ec29fde Mon Sep 17 00:00:00 2001 From: cztomczak Date: Thu, 16 Mar 2017 22:54:17 +0100 Subject: [PATCH 174/557] Fix tools on Linux. Add 32-bit support on Linux (#327). --- README.md | 2 +- docs/Build-instructions.md | 7 ++- examples/Examples-README.md | 2 +- src/client_handler/Makefile | 2 +- src/subprocess/Makefile | 2 +- src/subprocess/Makefile-libcefpythonapp | 2 +- tools/automate.py | 25 ++++++++-- tools/build.py | 40 +++++++-------- tools/build_cpp_projects.py | 4 +- tools/build_distrib.py | 66 ++++++++++--------------- tools/common.py | 65 ++++++++++++++++++++++-- tools/installer/cefpython3.setup.py | 4 +- tools/make_installer.py | 9 +++- 13 files changed, 147 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index feb5768c5..ebf04ddad 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ scraping or as a web crawler, or other kind of internet bots. - Downloads are available on [GitHub Releases](../../releases) pages - Windows support: 32-bit and 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 (requirements: Windows 7+) -- Linux support: 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 +- Linux support: 32-bit and 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 (requirements: Debian 7+ / Ubuntu 12.04+) - Mac support: 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 (requirements: MacOS 10.9+) diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index f52645a84..910e9d5f1 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -184,10 +184,7 @@ requirements common for all platforms. ### Linux -* Install packages: `sudo apt-get install python-dev cmake g++ libgtk2.0-dev` -* If using prebuilt binaries from Spotify automated builds and want to - build cefclient/cefsimple you need to install these packages: - `sudo apt-get install libgtkglext1-dev` +* Install packages: `sudo apt-get install python-dev cmake g++ libgtk2.0-dev libgtkglext1-dev` * If building CEF from sources: * Official binaries are built on Ubuntu 14.04 (cmake 2.8.12, g++ 4.8.4) * Download [ninja](http://martine.github.io/ninja/) 1.7.1 or later @@ -209,6 +206,8 @@ requirements common for all platforms. * To perform a 32-bit Linux build on a 64-bit Linux system see Linux configuration in upstream cef/AutomatedBuildSetup.md. See also [cef/#1804](https://bitbucket.org/chromiumembedded/cef/issues/1804). +* Sometimes it is also required to install these packages (eg. chroot): + `sudo apt-get install libnss3 libnspr4 libxss1 libgconf-2-4` ### Mac diff --git a/examples/Examples-README.md b/examples/Examples-README.md index b1b4109bd..337004d79 100644 --- a/examples/Examples-README.md +++ b/examples/Examples-README.md @@ -21,7 +21,7 @@ maintained: and [PySide](https://wiki.qt.io/PySide) libraries (Qt 4) - [tkinter_.py](tkinter_.py): example for [Tkinter] (https://wiki.python.org/moin/TkInter). Currently broken on Mac. -- [wxpython.py](wxpython.py): example for wxPython +- [wxpython.py](wxpython.py): example for [wxPython](https://wxpython.org/) If there are any issues in examples read top comments in sources to see whether this is a known issue with available workarounds. diff --git a/src/client_handler/Makefile b/src/client_handler/Makefile index f0b9a5a4d..4465d28b5 100644 --- a/src/client_handler/Makefile +++ b/src/client_handler/Makefile @@ -30,7 +30,7 @@ OBJ = $(filter %.o, $(SRC:.cpp=.o) $(SRC:.mm=.o)) OUT = libclient_handler.a -INC = -I./../ -I./../common/ -I/usr/include/python2.7 \ +INC = -I./../ -I./../common/ -I$(PYTHON_INCLUDE) \ -I/usr/include/gtk-2.0 \ -I/usr/include/gtk-unix-print-2.0 \ -I/usr/include/glib-2.0 \ diff --git a/src/subprocess/Makefile b/src/subprocess/Makefile index 580cb784f..b6f003be4 100644 --- a/src/subprocess/Makefile +++ b/src/subprocess/Makefile @@ -5,7 +5,7 @@ # -Werror - treat warnings as errors UNAME_S = $(shell uname -s) -INC = -I./../ -I./../common/ -I/usr/include/python2.7 \ +INC = -I./../ -I./../common/ -I$(PYTHON_INCLUDE) \ -I/usr/include/gtk-2.0 \ -I/usr/include/gtk-unix-print-2.0 \ -I/usr/include/glib-2.0 \ diff --git a/src/subprocess/Makefile-libcefpythonapp b/src/subprocess/Makefile-libcefpythonapp index bd8186da7..e811a32fa 100644 --- a/src/subprocess/Makefile-libcefpythonapp +++ b/src/subprocess/Makefile-libcefpythonapp @@ -30,7 +30,7 @@ OBJ = $(filter %.o, $(SRC:.cpp=.o) $(SRC:.mm=.o)) OUT = libcefpythonapp.a -INC = -I./../ -I./../common/ -I/usr/include/python2.7 \ +INC = -I./../ -I./../common/ -I$(PYTHON_INCLUDE) \ -I/usr/include/gtk-2.0 \ -I/usr/include/gtk-unix-print-2.0 \ -I/usr/include/glib-2.0 \ diff --git a/tools/automate.py b/tools/automate.py index 716f9c579..1a12398e5 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -126,9 +126,6 @@ def main(): " version of python.") sys.exit(1) build_cef() - # Build cefclient, cefsimple, ceftests, libcef_dll_wrapper - build_cef_projects() - create_prebuilt_binaries() elif Options.prebuilt_cef: prebuilt_cef() @@ -209,6 +206,11 @@ def setup_options(docopt_args): def build_cef(): """Build CEF from sources.""" + if ARCH32: + print("[automate.py] INFO: building CEF 32-bit from sources is" + " supported only with cross-compiling on 64-bit OS.") + sys.exit(1) + # cef/ repo create_cef_directories() @@ -221,6 +223,18 @@ def build_cef(): print("[automate.py] Binary distrib created in %s" % Options.binary_distrib) + if Options.x86: + print("[automate.py] INFO: to build CEF projects and create prebuilt" + " binaries you have to use 32-bit chroot. Copy the binary" + " distrib's cef_binary_*/ directory (path displayed above) to" + " cefpython's build/ directory. Then run automate.py" + " --prebuilt-cef using 32-bit chroot.") + sys.exit(0) + else: + # Build cefclient, cefsimple, ceftests, libcef_dll_wrapper + build_cef_projects() + create_prebuilt_binaries() + def prebuilt_cef(): """Use prebuilt binaries.""" @@ -884,7 +898,10 @@ def run_command(command, working_dir, env=None): args = command if not env: env = getenv() - return subprocess.check_call(args, cwd=working_dir, env=env, shell=True) + # When passing list of args shell cannot be True on eg. Linux, read + # notes in build.py + shell=(platform.system() == "Windows") + return subprocess.check_call(args, cwd=working_dir, env=env, shell=shell) def run_git(command_line, working_dir): diff --git a/tools/build.py b/tools/build.py index 375d64973..fce02f349 100644 --- a/tools/build.py +++ b/tools/build.py @@ -30,7 +30,16 @@ # --rebuild-cpp Force rebuild of .vcproj C++ projects (DISABLED) -# How to debug on Linux: +# NOTE: When passing string command to subprocess functions you must +# always use shell=True, otherwise on Linux error is thrown: +# "No such file or directory". Always pass string commands to +# subprocess functions with shell=True. If you pass a list of +# arguments instead, then on Linux a "Segmentation fault" error +# message is not shown. When passing a list of args to subprocess +# function then you can't pass shell=True on Linux. If you pass +# then it will execute args[0] and ignore others args. + +# How to debug on Linux (OLD unsupported). # 1. Install "python-dbg" package # 2. Install "python-wxgtk2.8-dbg" package # 3. Run "python compile.py debug" @@ -38,12 +47,6 @@ # 5. To display debug backtrace type "cy bt" # 6. More commands: http://docs.cython.org/src/userguide/debugging.html -# This will not show "Segmentation fault" error message: -# > subprocess.call(["python", "./wxpython.py"]) -# You need to call it with command as string and shell=True -# for this kind of error message to be shown: -# > subprocess.call("python wxpython.py", shell=True) - from common import * import sys import os @@ -210,8 +213,7 @@ def setup_environ(): if WINDOWS: if "INCLUDE" not in os.environ: os.environ["INCLUDE"] = "" - os.environ["INCLUDE"] += os.pathsep + os.path.join(get_python_path(), - "include") + os.environ["INCLUDE"] += os.pathsep + get_python_include_path() print("[build.py] environ INCLUDE: {include}" .format(include=os.environ["INCLUDE"])) @@ -223,7 +225,11 @@ def setup_environ(): .format(lib=os.environ["AdditionalLibraryDirectories"])) if LINUX or MAC: - # Used in makefiles + # Env variables for makefiles + os.environ["PYTHON_INCLUDE"] = get_python_include_path() + print("[build.py] PYTHON_INCLUDE: {python_include}" + .format(python_include=os.environ["PYTHON_INCLUDE"])) + os.environ["CEF_CCFLAGS"] = "-std=gnu++11 -DNDEBUG -Wall -Werror" if FAST_FLAG: os.environ["CEF_CCFLAGS"] += " -O0" @@ -231,16 +237,14 @@ def setup_environ(): os.environ["CEF_CCFLAGS"] += " -O3" os.environ["CEF_LINK_FLAGS"] = "" + os.environ["CEF_BIN"] = os.path.join(CEF_BINARIES_LIBRARIES, "bin") + os.environ["CEF_LIB"] = os.path.join(CEF_BINARIES_LIBRARIES, "lib") + if LINUX: # TODO: Set CEF_CCFLAGS and CEF_LINK_FLAGS according to what is # in upstream cefclient, see cef/cmake/cef_variables.cmake. pass - # Mac env variables for makefiles - if MAC or LINUX: - os.environ["CEF_BIN"] = os.path.join(CEF_BINARIES_LIBRARIES, "bin") - os.environ["CEF_LIB"] = os.path.join(CEF_BINARIES_LIBRARIES, "lib") - # Mac compiler options if MAC: os.environ["PATH"] = "/usr/local/bin:"+os.environ["PATH"] @@ -282,11 +286,6 @@ def setup_environ(): ) -def get_python_path(): - """Get Python path.""" - return os.path.dirname(sys.executable) - - def fix_cefpython_api_header_file(): """This function does two things: 1) Disable warnings in cefpython API header file and 2) Make a copy named cefpython_pyXX_fixed.h, @@ -449,6 +448,7 @@ def clean_cpp_projects_unix(): delete_files_by_pattern("{0}/*.o".format(SUBPROCESS_DIR)) delete_files_by_pattern("{0}/*.a".format(SUBPROCESS_DIR)) delete_files_by_pattern("{0}/subprocess".format(SUBPROCESS_DIR)) + delete_files_by_pattern("{0}/main_message_loop/*.o".format(SUBPROCESS_DIR)) delete_files_by_pattern("{0}/*.o".format(CPP_UTILS_DIR)) delete_files_by_pattern("{0}/*.a".format(CPP_UTILS_DIR)) diff --git a/tools/build_cpp_projects.py b/tools/build_cpp_projects.py index 8bb6bf335..f62f85c37 100644 --- a/tools/build_cpp_projects.py +++ b/tools/build_cpp_projects.py @@ -247,8 +247,6 @@ def smart_compile(compiler, macros, extra_args, sources, output_dir): # all put in the same output_directory. Otherwise distutils # will create lots of subdirs in output_directory. macros = macros_as_tuples(macros) - python_include = os.path.join(os.path.dirname(sys.executable), - "include") common_dir = os.path.join(SRC_DIR, "common") original_dir = os.getcwd() for source_file in sources: @@ -261,7 +259,7 @@ def smart_compile(compiler, macros, extra_args, sources, output_dir): # TODO include dirs for Linux/Mac include_dirs=[SRC_DIR, common_dir, - python_include], + get_python_include_path()], # TODO compiler flags for Linux/Mac extra_preargs=None, extra_postargs=extra_args) diff --git a/tools/build_distrib.py b/tools/build_distrib.py index 93f3cf340..a88f059cc 100644 --- a/tools/build_distrib.py +++ b/tools/build_distrib.py @@ -60,7 +60,7 @@ import re import shutil import subprocess -import tarfile +# import tarfile # Currently using zip on all platforms import zipfile # Command line args @@ -117,13 +117,13 @@ def main(): pack_prebuilt_cef("32bit") if LINUX: reduce_package_size_issue_262("32bit") - reduce_package_size_issue_321("32bit") - if pythons_64bit is not None: + remove_unnecessary_package_files("32bit") + if pythons_64bit: run_automate_prebuilt_cef(pythons_64bit[0]) pack_prebuilt_cef("64bit") if LINUX: reduce_package_size_issue_262("64bit") - reduce_package_size_issue_321("64bit") + remove_unnecessary_package_files("64bit") if not NO_REBUILD: build_cefpython_modules(pythons_32bit + pythons_64bit) if pythons_32bit: @@ -264,11 +264,21 @@ def search_for_pythons(search_arch): def check_pythons(pythons_32bit, pythons_64bit): + check_32bit = True + check_64bit = True + if MAC: + check_32bit = False + elif LINUX: + if pythons_64bit: + check_32bit = False + elif pythons_32bit: + check_64bit = False + pp = pprint.PrettyPrinter(indent=4) if pythons_32bit: print("[build_distrib.py] Pythons 32-bit found:") pp.pprint(pythons_32bit) - if WINDOWS and len(pythons_32bit) != len(SUPPORTED_PYTHON_VERSIONS): + if check_32bit and len(pythons_32bit) != len(SUPPORTED_PYTHON_VERSIONS): print("[build_distrib.py] ERROR: Couldn't find all supported" " python 32-bit installations. Found: {found}." .format(found=len(pythons_32bit))) @@ -276,7 +286,7 @@ def check_pythons(pythons_32bit, pythons_64bit): if pythons_64bit: print("[build_distrib.py] Pythons 64-bit found:") pp.pprint(pythons_64bit) - if len(pythons_64bit) != len(SUPPORTED_PYTHON_VERSIONS): + if check_64bit and len(pythons_64bit) != len(SUPPORTED_PYTHON_VERSIONS): print("[build_distrib.py] ERROR: Couldn't find all supported" " python 64-bit installations. Found: {found}." .format(found=len(pythons_64bit))) @@ -367,15 +377,17 @@ def pack_prebuilt_cef(arch): def pack_directory(path, base_path): if path.endswith(os.path.sep): path = path[:-1] - ext = ".zip" if WINDOWS or MAC else ".tar.gz" + # ext = ".zip" if WINDOWS or MAC else ".tar.gz" + ext = ".zip" archive = path + ext if os.path.exists(archive): os.remove(archive) if WINDOWS or MAC: zip_directory(path, base_path=base_path, archive=archive) else: - with tarfile.open(archive, "w:gz") as tar: - tar.add(path, arcname=os.path.basename(path)) + zip_directory(path, base_path=base_path, archive=archive) + # with tarfile.open(archive, "w:gz") as tar: + # tar.add(path, arcname=os.path.basename(path)) assert os.path.isfile(archive), archive return archive @@ -408,43 +420,19 @@ def reduce_package_size_issue_262(arch): .format(libcef_so=os.path.basename(libcef_so))) command = "strip {libcef_so}".format(libcef_so=libcef_so) pcode = subprocess.call(command, shell=True) - assert pcode, "strip command failed" + assert pcode == 0, "strip command failed" -def reduce_package_size_issue_321(arch): - """PyPI has file size limit and must reduce package size. Issue #321.""" +def remove_unnecessary_package_files(arch): + """Do not ship sample applications (cefclient etc) with the package. + They increase size and also are an additional unnecessary factor + when dealing with false-positives in Anti-Virus software.""" print("[build_distrib.py] Reduce package size for {arch} (Issue #321)" .format(arch=arch)) prebuilt_basename = get_cef_binaries_libraries_basename( get_os_postfix2_for_arch(arch)) bin_dir = os.path.join(prebuilt_basename, "bin") - - # Delete sample applications to reduce package size - sample_apps = ["cefclient", "cefsimple", "ceftests"] - for sample_app_name in sample_apps: - sample_app = os.path.join(bin_dir, sample_app_name + APP_EXT) - # Not on all platforms sample apps may be available - if os.path.exists(sample_app): - print("[build_distrib.py] Delete {sample_app}" - .format(sample_app=os.path.basename(sample_app))) - if os.path.isdir(sample_app): - shutil.rmtree(sample_app) - else: - os.remove(sample_app) - # Also delete subdirs eg. cefclient_files/, ceftests_files/ - files_subdir = os.path.join(bin_dir, sample_app_name + "_files") - if os.path.isdir(files_subdir): - print("[build_distrib.py] Delete directory: {dir}/" - .format(dir=os.path.basename(files_subdir))) - shutil.rmtree(files_subdir) - - # Strip symbols from cefpython .so modules to reduce size - modules = glob.glob(os.path.join(CEFPYTHON_BINARY, "*.so")) - for module in modules: - print("[build_distrib.py] strip {module}" - .format(module=os.path.basename(module))) - command = "strip {module}".format(module=module) - assert os.system(command) == 0, "strip command failed" + delete_cef_sample_apps(caller_script=__file__, bin_dir=bin_dir) def build_cefpython_modules(pythons): diff --git a/tools/common.py b/tools/common.py index b84476d81..3df0404b9 100644 --- a/tools/common.py +++ b/tools/common.py @@ -4,12 +4,16 @@ # Common stuff for tools such as automate.py, build.py, etc. -import struct -import platform -import sys -import os import glob +import os +import platform import re +import shutil +import struct +import sys + +# These sample apps will be deleted when creating setup/wheel packages +CEF_SAMPLE_APPS = ["cefclient", "cefsimple", "ceftests", "chrome-sandbox"] # Architecture and OS postfixes ARCH32 = (8 * struct.calcsize('P') == 32) @@ -198,6 +202,8 @@ VS2008_BUILD = VS2008_BUILD.replace("%LocalAppData%", os.environ["LOCALAPPDATA"]) +# ----------------------------------------------------------------------------- + def get_os_postfix2_for_arch(arch): return OS_POSTFIX2_ARCH[SYSTEM][arch] @@ -219,6 +225,57 @@ def sudo_command(command, python): return command +def get_python_path(): + """Get Python path.""" + return os.path.dirname(sys.executable) + + +def get_python_include_path(): + # 1) C:\Python27\include + # 2) ~/.pyenv/versions/2.7.13/bin/python + # ~/.pyenv/versions/2.7.13/include/python2.7 + # 3) ~/.pyenv/versions/3.4.6/include/python2.7m + # 4) /usr/include/python2.7 + base_dir = os.path.dirname(sys.executable) + try_dirs = ["{base_dir}/include", + "{base_dir}/../include/python{ver}", + "{base_dir}/../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]) + for pattern in try_dirs: + pattern = pattern.format(base_dir=base_dir, ver=ver) + if WINDOWS: + pattern = pattern.replace("/", "\\") + results = glob.glob(pattern) + if len(results) == 1: + python_h = os.path.join(results[0], "Python.h") + if os.path.isfile(python_h): + return results[0] + return ".\\" if WINDOWS else "./" + + +def delete_cef_sample_apps(caller_script, bin_dir): + """Delete CEF sample apps to reduce package size.""" + for sample_app_name in CEF_SAMPLE_APPS: + sample_app = os.path.join(bin_dir, sample_app_name + APP_EXT) + # Not on all platforms sample apps may be available + if os.path.exists(sample_app): + print("[{script}] Delete {sample_app}" + .format(script=os.path.basename(caller_script), + sample_app=os.path.basename(sample_app))) + if os.path.isdir(sample_app): + shutil.rmtree(sample_app) + else: + os.remove(sample_app) + # Also delete subdirs eg. cefclient_files/, ceftests_files/ + files_subdir = os.path.join(bin_dir, sample_app_name + "_files") + if os.path.isdir(files_subdir): + print("[build_distrib.py] Delete directory: {dir}/" + .format(dir=os.path.basename(files_subdir))) + shutil.rmtree(files_subdir) + + def _detect_cef_binaries_libraries_dir(): """Detect cef binary directory created by automate.py eg. build/cef55_3.2883.1553.g80bd606_win32/ diff --git a/tools/installer/cefpython3.setup.py b/tools/installer/cefpython3.setup.py index 3458e09a1..08065ebd5 100644 --- a/tools/installer/cefpython3.setup.py +++ b/tools/installer/cefpython3.setup.py @@ -152,8 +152,6 @@ def main(): "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: Browsers", "Topic :: Multimedia", - ("Topic :: Software Development :: Libraries" - ":: Application Frameworks"), "Topic :: Software Development :: User Interfaces", ], ) @@ -236,6 +234,8 @@ def post_install_hook(): print("[setup.py] Set execute permissions on executables") for executable in get_executables(): executable = os.path.join(installed_package_dir, executable) + if not os.path.exists(executable): + continue command = "chmod +x {executable}".format(executable=executable) print("[setup.py] {command}".format(command=command)) subprocess.call(command, shell=True) diff --git a/tools/make_installer.py b/tools/make_installer.py index 518b62cc2..058c3869a 100644 --- a/tools/make_installer.py +++ b/tools/make_installer.py @@ -76,14 +76,16 @@ def main(): (EXAMPLES_DIR, "*"), (SETUP_DIR, "examples/"), ] perform_copy_operations(copy_operations) + delete_cef_sample_apps(caller_script=__file__, bin_dir=PKG_DIR) # Linux only operations if LINUX: + os.makedirs(os.path.join(SETUP_DIR, "examples", "kivy-select-boxes")) copy_operations_linux = [ (LINUX_DIR, "binaries_64bit/kivy_.py"), - (PKG_DIR, "examples/"), + (SETUP_DIR, "examples/"), (LINUX_DIR, "binaries_64bit/kivy-select-boxes/*"), - (PKG_DIR, "examples/") + (SETUP_DIR, "examples/kivy-select-boxes/") ] perform_copy_operations(copy_operations_linux) @@ -129,6 +131,9 @@ def command_line_args(): continue if WHEEL: WHEEL_ARGS.append(arg) + if WHEEL and not len(WHEEL_ARGS): + print("ERROR: wheel requires additional args eg. --universal") + sys.exit(1) def copy_tools_installer_files(setup_dir, pkg_dir): From 6640ed2cb841a68381312d16cbe32dfb0eb3abae Mon Sep 17 00:00:00 2001 From: cztomczak Date: Thu, 16 Mar 2017 23:00:27 +0100 Subject: [PATCH 175/557] Fix links in README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ebf04ddad..e144c7659 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ scraping or as a web crawler, or other kind of internet bots. - Documentation is in the [docs/](docs) directory - API reference is in the [api/](api) directory - Additional documentation is in issues labelled [Knowledge Base] - (../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) +(../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) - Wiki pages are deprecated and for v31 only @@ -67,7 +67,7 @@ scraping or as a web crawler, or other kind of internet bots. - Documentation is in the [docs/](docs) directory - API reference is in the [api/](api) directory - Additional documentation is in issues labelled [Knowledge Base] - (../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) +(../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) ### v31 release @@ -79,7 +79,7 @@ scraping or as a web crawler, or other kind of internet bots. - Mac support: 32-bit and 64-bit (requirements: MacOS 10.7+) - Documentation is on [wiki pages](../../wiki) - API reference is available in revision [169a1b2] - (../../tree/169a1b20d3cd09879070d41aab28cfa195d2a7d5/docs/api) +(../../tree/169a1b20d3cd09879070d41aab28cfa195d2a7d5/docs/api) ## Support development From 41fa14fe05736066b7f4523697f677e8aa68185c Mon Sep 17 00:00:00 2001 From: cztomczak Date: Thu, 16 Mar 2017 23:06:38 +0100 Subject: [PATCH 176/557] Fix links in docs/ and in README again --- README.md | 44 ++++++++++++++++---------------------- docs/Build-instructions.md | 6 ++---- docs/Knowledge-Base.md | 27 +++++++++-------------- 3 files changed, 30 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index e144c7659..a656c62da 100644 --- a/README.md +++ b/README.md @@ -16,15 +16,12 @@ Table of contents: ## Introduction -CEF Python is a BSD-licensed open source project founded by [Czarek Tomczak] -(http://www.linkedin.com/in/czarektomczak) in 2012 and is based on -Google Chromium and the [CEF Framework] -(https://bitbucket.org/chromiumembedded/cef) projects. The Chromium -project focuses mainly on Google Chrome application development, while -CEF focuses on facilitating embedded browser use cases in third-party -applications. Lots of applications use CEF control, there are more than -[100 million CEF instances] -(http://en.wikipedia.org/wiki/Chromium_Embedded_Framework#Applications_using_CEF) +CEF Python is a BSD-licensed open source project founded by [Czarek Tomczak](http://www.linkedin.com/in/czarektomczak) +in 2012 and is based on Google Chromium and the [CEF Framework](https://bitbucket.org/chromiumembedded/cef) +projects. The Chromium project focuses mainly on Google Chrome application +development, while CEF focuses on facilitating embedded browser use cases +in third-party applications. Lots of applications use CEF control, there are +more than [100 million CEF instances](http://en.wikipedia.org/wiki/Chromium_Embedded_Framework#Applications_using_CEF) installed around the world. [Examples of embedding](examples/Examples-README.md) Chrome browser are available for many popular GUI toolkits including: wxPython, PyGTK, PyQt, PySide, Kivy, Panda3D and PyGame/PyOpenGL. @@ -33,22 +30,20 @@ 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) 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 applications. You can use it for web -scraping or as a web crawler, or other kind of internet bots. +communicate between Python<>Javascript use [javascript bindings](api/JavascriptBindings.md) +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 +applications. You can use it for web scraping or as a web crawler, +or other kind of internet bots. ## Support -- Ask questions, report problems and issues on the [Forum] - (https://groups.google.com/group/cefpython) +- Ask questions, report problems and issues on the [Forum](https://groups.google.com/group/cefpython) - Documentation is in the [docs/](docs) directory - API reference is in the [api/](api) directory -- Additional documentation is in issues labelled [Knowledge Base] -(../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) +- Additional documentation is in issues labelled [Knowledge Base](../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) - Wiki pages are deprecated and for v31 only @@ -66,8 +61,7 @@ scraping or as a web crawler, or other kind of internet bots. (requirements: MacOS 10.9+) - Documentation is in the [docs/](docs) directory - API reference is in the [api/](api) directory -- Additional documentation is in issues labelled [Knowledge Base] -(../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) +- Additional documentation is in issues labelled [Knowledge Base](../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) ### v31 release @@ -78,8 +72,7 @@ scraping or as a web crawler, or other kind of internet bots. - Linux support: 32-bit and 64-bit (requirements: Debian 7+ / Ubuntu 12.04+) - Mac support: 32-bit and 64-bit (requirements: MacOS 10.7+) - Documentation is on [wiki pages](../../wiki) -- API reference is available in revision [169a1b2] -(../../tree/169a1b20d3cd09879070d41aab28cfa195d2a7d5/docs/api) +- API reference is available in revision [169a1b2](../../tree/169a1b20d3cd09879070d41aab28cfa195d2a7d5/docs/api) ## Support development @@ -105,9 +98,8 @@ directly. the v55/v56 releases for all platforms * Thanks to JetBrains for providing an Open Source license for [PyCharm](https://www.jetbrains.com/pycharm/) -* Thanks to those who have made a Paypal donation: [Rentouch GmbH] - (http://www.rentouch.ch/), Walter Purvis, Rokas Stupuras, Alex Rattray, - Greg Kacy, Paul Korzhyk +* Thanks to those who have made a Paypal donation: [Rentouch GmbH](http://www.rentouch.ch/), + Walter Purvis, Rokas Stupuras, Alex Rattray, Greg Kacy, Paul Korzhyk * Lots of thanks goes to [Cyan Inc.](http://www.blueplanet.com/) for sponsoring this project for a long time, making CEF Python 3 mature * Thanks to those who have donated their time through code contributions, diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index 910e9d5f1..f9009799e 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -163,8 +163,7 @@ requirements common for all platforms. if does not exist * For Python 3.4 follow the instructions for installing Windows SDK 7.1. If you encounter issue with .NET Framework 4 then make registry edits - as suggested here: [Windows SDK setup failure] - (http://stackoverflow.com/a/33260090/623622). + as suggested here: [Windows SDK setup failure](http://stackoverflow.com/a/33260090/623622). * For Python 3.4, if getting error: `Cannot open include file 'ammintrin.h': No such file or directory` then Copy that `ammitrin.h` file from for example VS 2015 installation @@ -336,8 +335,7 @@ __Debug_GN_arm/ configuration error (Linux)__: Even though building on Linux for Linux, Chromium still runs ARM configuration files. If there is an error showing that pkg-config fails with GTK 3 library then see solution in the third post in this topic on CEF Forum: -[Debug_GN_arm error when building on Linux, *not* arm] -(https://magpcss.org/ceforum/viewtopic.php?f=6&t=14976). +[Debug_GN_arm error when building on Linux, *not* arm](https://magpcss.org/ceforum/viewtopic.php?f=6&t=14976). __MISSING PACKAGES (Linux)__: After the chromium sources are downloaded, it will try to build cef projects and if it fails due to missing packages diff --git a/docs/Knowledge-Base.md b/docs/Knowledge-Base.md index c43b417c4..fb9ea8658 100644 --- a/docs/Knowledge-Base.md +++ b/docs/Knowledge-Base.md @@ -19,11 +19,9 @@ Table of contents: ## Notifications on new releases -To be notified of new releases subscribe to this [RSS/Atom feed] -(../../../releases.atom). +To be notified of new releases subscribe to this [RSS/Atom feed](../../../releases.atom). -Announcements are also made on the [Forum] -(https://groups.google.com/d/forum/cefpython). +Announcements are also made on the [Forum](https://groups.google.com/d/forum/cefpython). To be notified of these via email set your Membership and Email settings and change delivery preference to Daily summaries. @@ -33,8 +31,8 @@ and change delivery preference to Daily summaries. CEF Python depends on CEF and API breaks are inevitable when updating to latest CEF. The [Migration Guide](Migration-guide.md) document which is still under works, will list most notable breaking changes since -v31 release. Until it's done go to go to the [GitHub Releases] -(../../../releases) page and check release notes for all the releases +v31 release. Until it's done go to go to the [GitHub Releases](../../../releases) +page and check release notes for all the releases that appeared between your old version and the new version. Look for lists named "Changes in API that break backward compatibility" or similar. @@ -61,9 +59,8 @@ on Mac. By default CEF expects that CEF framework is located at `Contents/Frameworks/Chromium Embedded Framework.framework` in the top-level app bundle. If that is not the case then you have -to set ApplicationSettings.[framework_dir_path] -(../api/ApplicationSettings.md#framework_dir_path) before calling -cef.Initialize(). +to set ApplicationSettings.[framework_dir_path](../api/ApplicationSettings.md#framework_dir_path) +before calling cef.Initialize(). You may also need to change the structure and embedded paths in CEF framework and in the cefpython module. Here are the default @@ -113,8 +110,7 @@ as of now. To see if some feature is working or a bug is fixed in newer CEF release perform the following steps: -1. Go to [Spotify Automated Builds] - (http://opensource.spotify.com/cefbuilds/index.html) +1. Go to [Spotify Automated Builds](http://opensource.spotify.com/cefbuilds/index.html) to download latest CEF for your platform. Choose "Sample Application" binaries. 2. Extract the archive and run sample application from the @@ -188,8 +184,7 @@ Now you should see debug information displayed in console like this: Install gdb: - On Linux type: `sudo apt-get install gdb` -- On Mac type: `brew install gdb` and then [sign gdb] - (https://sourceware.org/gdb/wiki/BuildingOnDarwin#Giving_gdb_permission_to_control_other_processes) +- On Mac type: `brew install gdb` and then [sign gdb](https://sourceware.org/gdb/wiki/BuildingOnDarwin#Giving_gdb_permission_to_control_other_processes) - Additionally on Mac to get a meaningful stack trace with gdb do these steps: - Install [macports](https://www.macports.org/install.php) and restart terminal @@ -224,8 +219,7 @@ supported XP was v49. On XP you should disable GPU acceleration by using the --disable-gpu and --disable-gpu-compositing switches. These switches must be passed -programmatically to cef.Initialize(), see [api/Command Line Switches] -(../api/CommandLineSwitches.md). +programmatically to cef.Initialize(), see [api/Command Line Switches](../api/CommandLineSwitches.md). ## Mac 32-bit support @@ -266,7 +260,6 @@ A quote by Marshall Greenblatt: > decision that may have security consequences should be evaluated > by people who are knowledgeable about security considerations. -Reference: [Question on browser security] -(http://magpcss.org/ceforum/viewtopic.php?f=10&t=10222) +Reference: [Question on browser security](http://magpcss.org/ceforum/viewtopic.php?f=10&t=10222) on the CEF Forum. From 36faf91f3a508b9e62c6c098947c71d184469981 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 18 Mar 2017 13:20:44 +0100 Subject: [PATCH 177/557] Fix PyBrowser references living forever (#330). --- api/Browser.md | 14 ++- api/Frame.md | 13 +++ api/JavascriptCallback.md | 27 ++++- src/browser.pyx | 113 ++++++++++++++------- src/cefpython.pyx | 7 +- src/frame.pyx | 41 ++++++-- src/handlers/display_handler.pyx | 11 +- src/handlers/focus_handler.pyx | 8 +- src/handlers/javascript_dialog_handler.pyx | 12 ++- src/handlers/keyboard_handler.pyx | 4 +- src/handlers/lifespan_handler.pyx | 11 +- src/handlers/load_handler.pyx | 9 +- src/handlers/render_handler.pyx | 24 ++--- src/handlers/request_handler.pyx | 23 +++-- src/handlers/v8context_handler.pyx | 11 +- src/handlers/v8function_handler.pyx | 3 +- src/javascript_callback.pyx | 22 ++-- tools/build.py | 11 ++ 18 files changed, 257 insertions(+), 107 deletions(-) diff --git a/api/Browser.md b/api/Browser.md index 46135cc0f..58e566980 100644 --- a/api/Browser.md +++ b/api/Browser.md @@ -5,8 +5,18 @@ Remember to free all browser references 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. To free a reference -just assign a None value to a "browser" variable. +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. + +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. Table of contents: diff --git a/api/Frame.md b/api/Frame.md index f214bdcdb..aef391b4e 100644 --- a/api/Frame.md +++ b/api/Frame.md @@ -3,6 +3,19 @@ # Frame (object) +Remember to free all frame references 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. + +To compare frame objects always use [GetIdentifier()](#getidentifier) +method. Do not compare two Frame objects variables directly. There +are some edge cases when after the OnBeforeClose event frame objects +are no more globally referenced thus a new instance is created that +wraps upstream CefFrame object. Frame objects that were globally +unreferenced do not have properties of the original Frame object. + Table of contents: * [Methods](#methods) diff --git a/api/JavascriptCallback.md b/api/JavascriptCallback.md index 6f4ba790b..97b3bc063 100644 --- a/api/JavascriptCallback.md +++ b/api/JavascriptCallback.md @@ -15,7 +15,9 @@ See also [Issue #11](../issues/11) (Throw JS / Python exceptions according to ex Table of contents: * [Methods](#methods) * [Call](#call) - * [GetName](#getname) + * [GetFrame](#getframe) + * [GetId](#getid) + * [GetFunctionName](#getfunctionname) ## Methods @@ -30,10 +32,29 @@ Table of contents: Call the javascript callback function. -For a list of allowed types for `mixed` see [JavascriptBindings](JavascriptBindings.md).IsValueAllowed(). +For a list of allowed types for `mixed` see JavascriptBindings.[IsValueAllowed()](JavascriptBindings.md#isvalueallowed). -### GetName +### GetFrame + +| | | +| --- | --- | +| __Return__ | [Frame](Frame.md) | + +Get Frame object associated with this callback. If Browser was destroyed +then Frame may be None. + + +### GetId + +| | | +| --- | --- | +| __Return__ | int | + +Get this callback's identifier. + + +### GetFunctionName | | | | --- | --- | diff --git a/src/browser.pyx b/src/browser.pyx index c5aadd53c..d27a75e77 100644 --- a/src/browser.pyx +++ b/src/browser.pyx @@ -17,75 +17,109 @@ MOUSEBUTTON_RIGHT = cef_types.MBT_RIGHT # get segmentation faults, as they will be garbage collected. cdef dict g_pyBrowsers = {} + +# Unreferenced browsers are added to this list in OnBeforeClose(). +# Must keep a list of unreferenced browsers so that a new reference +# is not created in GetPyBrowser() when browser was closed. +cdef list g_unreferenced_browsers = [] # [int identifier, ..] + +# Browsers that are about to be closed are added to this list in +# CloseBrowser(). cdef list g_closed_browsers = [] # [int identifier, ..] cdef PyBrowser GetPyBrowserById(int browserId): + """May return None value so always check returned value.""" if browserId in g_pyBrowsers: return g_pyBrowsers[browserId] return None -cdef PyBrowser GetPyBrowser(CefRefPtr[CefBrowser] cefBrowser): +cdef PyBrowser GetPyBrowser(CefRefPtr[CefBrowser] cefBrowser, + callerIdStr="GetPyBrowser"): + """The second argument 'callerIdStr' is so that a debug + message can be displayed informing which CEF handler callback + is being called to which an incomplete PyBrowser instance is + provided.""" + global g_pyBrowsers + + # This probably ain't needed, but just to be sure. if cefBrowser == NULL or not cefBrowser.get(): - # noinspection PyUnresolvedReferences - Debug("GetPyBrowser(): returning None") - return None + raise Exception("{caller}: CefBrowser reference is NULL" + .format(caller=callerIdStr)) cdef PyBrowser pyBrowser cdef int browserId - cdef int identifier - browserId = cefBrowser.get().GetIdentifier() + if browserId in g_pyBrowsers: return g_pyBrowsers[browserId] + # This code probably ain't needed. + # ---- + cdef list toRemove = [] + cdef int identifier for identifier, pyBrowser in g_pyBrowsers.items(): if not pyBrowser.cefBrowser.get(): - # noinspection PyUnresolvedReferences - Debug("GetPyBrowser(): removing an empty CefBrowser reference, " - "browserId=%s" % identifier) - del g_pyBrowsers[identifier] + toRemove.append(identifier) + for identifier in toRemove: + Debug("GetPyBrowser(): removing an empty CefBrowser reference," + " browserId=%s" % identifier) + RemovePyBrowser(identifier) + # ---- - # noinspection PyUnresolvedReferences - Debug("GetPyBrowser(): creating new PyBrowser, browserId=%s" % browserId) pyBrowser = PyBrowser() pyBrowser.cefBrowser = cefBrowser - g_pyBrowsers[browserId] = pyBrowser - - # Inherit client callbacks and javascript bindings - # from parent browser. - - # Checking __outerWindowHandle as we should not inherit - # client callbacks and javascript bindings if the browser - # was created explicitily by calling CreateBrowserSync(). - - # Popups inherit client callbacks by default. - - # Popups inherit javascript bindings only when "bindToPopups" - # constructor param was set to True. cdef WindowHandle openerHandle cdef dict clientCallbacks cdef JavascriptBindings javascriptBindings cdef PyBrowser tempPyBrowser - if pyBrowser.IsPopup() and \ - not pyBrowser.GetUserData("__outerWindowHandle"): - openerHandle = pyBrowser.GetOpenerWindowHandle() - for identifier, tempPyBrowser in g_pyBrowsers.items(): - if tempPyBrowser.GetWindowHandle() == openerHandle: - clientCallbacks = tempPyBrowser.GetClientCallbacksDict() - if clientCallbacks: - pyBrowser.SetClientCallbacksDict(clientCallbacks) - javascriptBindings = tempPyBrowser.GetJavascriptBindings() - if javascriptBindings: - if javascriptBindings.GetBindToPopups(): - pyBrowser.SetJavascriptBindings(javascriptBindings) + if browserId in g_unreferenced_browsers: + # This browser was already unreferenced due to OnBeforeClose + # was already called. An incomplete new instance of Browser + # object is created. This instance doesn't have the client + # callbacks, javascript bindings or user data that was already + # available in the original Browser object. + Debug("{caller}: Browser was already globally unreferenced" + ", a new incomplete instance is created, browser id={id}" + .format(caller=callerIdStr, id=str(browserId))) + else: + # This is first creation of browser. Store a reference globally + # and inherit client callbacks and javascript bindings from + # parent browsers. + Debug("GetPyBrowser(): create new PyBrowser, browserId=%s" + % browserId) + + g_pyBrowsers[browserId] = pyBrowser + + # Inherit client callbacks and javascript bindings + # from parent browser. + # - Checking __outerWindowHandle as we should not inherit + # client callbacks and javascript bindings if the browser + # was created explicitily by calling CreateBrowserSync(). + # - Popups inherit client callbacks by default. + # - Popups inherit javascript bindings only when "bindToPopups" + # constructor param was set to True. + + if pyBrowser.IsPopup() and \ + not pyBrowser.GetUserData("__outerWindowHandle"): + openerHandle = pyBrowser.GetOpenerWindowHandle() + for identifier, tempPyBrowser in g_pyBrowsers.items(): + if tempPyBrowser.GetWindowHandle() == openerHandle: + clientCallbacks = tempPyBrowser.GetClientCallbacksDict() + if clientCallbacks: + pyBrowser.SetClientCallbacksDict(clientCallbacks) + javascriptBindings = tempPyBrowser.GetJavascriptBindings() + if javascriptBindings: + if javascriptBindings.GetBindToPopups(): + pyBrowser.SetJavascriptBindings(javascriptBindings) + return pyBrowser cdef void RemovePyBrowser(int browserId) except *: # Called from LifespanHandler_OnBeforeClose(). - global g_pyBrowsers + global g_pyBrowsers, g_unreferenced_browsers if browserId in g_pyBrowsers: if len(g_pyBrowsers) == 1: # This is the last browser remaining. @@ -97,6 +131,7 @@ cdef void RemovePyBrowser(int browserId) except *: # noinspection PyUnresolvedReferences Debug("del g_pyBrowsers[%s]" % browserId) del g_pyBrowsers[browserId] + g_unreferenced_browsers.append(browserId) else: # noinspection PyUnresolvedReferences Debug("RemovePyBrowser() FAILED: browser not found, id = %s" \ @@ -116,7 +151,7 @@ cdef public void PyBrowser_ShowDevTools(CefRefPtr[CefBrowser] cefBrowser # Called from ClientHandler::OnContextMenuCommand cdef PyBrowser pyBrowser try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "ShowDevTools") pyBrowser.ShowDevTools() except: (exc_type, exc_value, exc_trace) = sys.exc_info() diff --git a/src/cefpython.pyx b/src/cefpython.pyx index 941fff00b..6fb922e1b 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -838,7 +838,8 @@ def CreateBrowserSync(windowInfo=None, requestContextHandler.get().SetBrowser(cefBrowser) cdef PyBrowser pyBrowser = GetPyBrowser(cefBrowser) - pyBrowser.SetUserData("__outerWindowHandle", int(windowInfo.parentWindowHandle)) + pyBrowser.SetUserData("__outerWindowHandle", + int(windowInfo.parentWindowHandle)) return pyBrowser @@ -889,6 +890,10 @@ def Shutdown(): # Run some message loop work, force closing browsers and then run # some message loop work again for the browsers to close cleanly. # + # UPDATE: This code needs to be rechecked. There were enhancements + # to unrferencing globally stored Browser objects in + # g_pyBrowsers. See Issue #330 and its commits. + # # CASE 1: # There might be a case when python error occured after creating # browser, but before any message loop was run. In such case diff --git a/src/frame.pyx b/src/frame.pyx index 9a3faca94..9342719c6 100644 --- a/src/frame.pyx +++ b/src/frame.pyx @@ -3,6 +3,7 @@ # Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" +include "browser.pyx" cdef dict g_pyFrames = {} @@ -17,25 +18,51 @@ cdef PyFrame GetPyFrameById(int browserId, object frameId): cdef PyFrame GetPyFrame(CefRefPtr[CefFrame] cefFrame): global g_pyFrames + + # This code probably ain't needed, but just to be sure. if cefFrame == NULL or not cefFrame.get(): - Debug("GetPyFrame(): returning None") - return + raise Exception("GetPyFrame(): CefFrame reference is NULL") + cdef PyFrame pyFrame cdef object frameId = cefFrame.get().GetIdentifier() # int64 cdef int browserId = cefFrame.get().GetBrowser().get().GetIdentifier() assert (frameId and browserId), "frameId or browserId empty" cdef object uniqueFrameId = GetUniqueFrameId(browserId, frameId) + if uniqueFrameId in g_pyFrames: return g_pyFrames[uniqueFrameId] + + # This code probably ain't needed. + # ---- + cdef list toRemove = [] for uFid, pyFrame in g_pyFrames.items(): if not pyFrame.cefFrame.get(): - Debug("GetPyFrame(): removing an empty CefFrame reference, " \ - "uniqueFrameId = %s" % uniqueFrameId) - del g_pyFrames[uFid] - # Debug("GetPyFrame(): creating new PyFrame, frameId=%s" % frameId) + toRemove.append(uFid) + for uFid in toRemove: + Debug("GetPyFrame(): removing an empty CefFrame reference, " + "uniqueFrameId = %s" % uniqueFrameId) + del g_pyFrames[uFid] + # ---- + pyFrame = PyFrame(browserId, frameId) pyFrame.cefFrame = cefFrame - g_pyFrames[uniqueFrameId] = pyFrame + + if browserId in g_unreferenced_browsers: + # Browser was already globally unreferenced in OnBeforeClose, + # thus all frames are globally unreferenced too. Create a new + # incomplete instance of PyFrame object. Read comments in + # browser.pyx > GetPyBrowser and in Browser.md for what + # "incomplete" means. + pass + else: + # Keep a global reference to this frame only if the browser + # wasn't destroyed in OnBeforeClose. Otherwise we would leave + # dead frames references living forever. + # SIDE EFFECT: two calls to GetPyFrame for the same frame object + # may return two different PyFrame objects. Compare + # frame objects always using GetIdentifier(). + # Debug("GetPyFrame(): create new PyFrame, frameId=%s" % frameId) + g_pyFrames[uniqueFrameId] = pyFrame return pyFrame cdef void RemovePyFrame(int browserId, object frameId) except *: diff --git a/src/handlers/display_handler.pyx b/src/handlers/display_handler.pyx index 3db61a7c6..d67cb4d17 100644 --- a/src/handlers/display_handler.pyx +++ b/src/handlers/display_handler.pyx @@ -3,6 +3,7 @@ # Project website: https://github.com/cztomczak/cefpython include "../cefpython.pyx" +include "../browser.pyx" cdef public void DisplayHandler_OnAddressChange( CefRefPtr[CefBrowser] cefBrowser, @@ -14,7 +15,7 @@ cdef public void DisplayHandler_OnAddressChange( cdef py_string pyUrl cdef object callback try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnAddressChange") pyFrame = GetPyFrame(cefFrame) pyUrl = CefToPyString(cefUrl) callback = pyBrowser.GetClientCallback("OnAddressChange") @@ -32,7 +33,7 @@ cdef public void DisplayHandler_OnTitleChange( cdef py_string pyTitle cdef object callback try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnTitleChange") pyTitle = CefToPyString(cefTitle) callback = pyBrowser.GetClientCallback("OnTitleChange") if callback: @@ -51,7 +52,7 @@ cdef public cpp_bool DisplayHandler_OnTooltip( cdef object callback cdef py_bool returnValue try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnTooltip") pyText = CefToPyString(cefText) pyTextOut = [pyText] callback = pyBrowser.GetClientCallback("OnTooltip") @@ -73,7 +74,7 @@ cdef public void DisplayHandler_OnStatusMessage( cdef py_string pyValue cdef object callback try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnStatusMessage") pyValue = CefToPyString(cefValue) callback = pyBrowser.GetClientCallback("OnStatusMessage") if callback: @@ -94,7 +95,7 @@ cdef public cpp_bool DisplayHandler_OnConsoleMessage( cdef py_bool returnValue cdef object callback try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnConsoleMessage") pyMessage = CefToPyString(cefMessage) pySource = CefToPyString(cefSource) callback = pyBrowser.GetClientCallback("OnConsoleMessage") diff --git a/src/handlers/focus_handler.pyx b/src/handlers/focus_handler.pyx index f966c6132..71c04523a 100644 --- a/src/handlers/focus_handler.pyx +++ b/src/handlers/focus_handler.pyx @@ -3,6 +3,8 @@ # Project website: https://github.com/cztomczak/cefpython include "../cefpython.pyx" +include "../browser.pyx" + cimport cef_types from cef_types cimport TID_UI @@ -17,7 +19,7 @@ cdef public void FocusHandler_OnTakeFocus( cdef PyBrowser browser try: assert IsThread(TID_UI), "Must be called on the UI thread" - browser = GetPyBrowser(cef_browser) + browser = GetPyBrowser(cef_browser, "OnTakeFocus") callback = browser.GetClientCallback("OnTakeFocus") if callback: callback(browser=browser, next=next_) @@ -34,7 +36,7 @@ cdef public cpp_bool FocusHandler_OnSetFocus( cdef py_bool ret try: assert IsThread(TID_UI), "Must be called on the UI thread" - browser = GetPyBrowser(cef_browser) + browser = GetPyBrowser(cef_browser, "OnSetFocus") callback = browser.GetClientCallback("OnSetFocus") if callback: ret = callback(browser=browser, source=source) @@ -52,7 +54,7 @@ cdef public void FocusHandler_OnGotFocus( cdef PyBrowser browser try: assert IsThread(TID_UI), "Must be called on the UI thread" - browser = GetPyBrowser(cef_browser) + browser = GetPyBrowser(cef_browser, "OnGotFocus") callback = browser.GetClientCallback("OnGotFocus") if callback: callback(browser=browser) diff --git a/src/handlers/javascript_dialog_handler.pyx b/src/handlers/javascript_dialog_handler.pyx index 0c7fa071b..283aad54c 100644 --- a/src/handlers/javascript_dialog_handler.pyx +++ b/src/handlers/javascript_dialog_handler.pyx @@ -3,6 +3,7 @@ # Project website: https://github.com/cztomczak/cefpython include "../cefpython.pyx" +include "../browser.pyx" # enum cef_jsdialog_type_t cimport cef_types @@ -48,7 +49,7 @@ cdef public cpp_bool JavascriptDialogHandler_OnJavascriptDialog( cdef object clientCallback cdef py_bool returnValue try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnJavascriptDialog") pyOriginUrl = CefToPyString(origin_url) pyMessageText = CefToPyString(message_text) pyDefaultPromptText = CefToPyString(default_prompt_text) @@ -86,7 +87,8 @@ cdef public cpp_bool JavascriptDialogHandler_OnBeforeUnloadJavascriptDialog( cdef object clientCallback cdef py_bool returnValue try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, + "OnBeforeUnloadJavascriptDialog") pyMessageText = CefToPyString(message_text) pyIsReload = bool(is_reload) pyCallback = CreatePyJavascriptDialogCallback(callback) @@ -110,7 +112,8 @@ cdef public void JavascriptDialogHandler_OnResetJavascriptDialogState( ) except * with gil: cdef PyBrowser pyBrowser try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, + "OnResetJavascriptDialogState") callback = pyBrowser.GetClientCallback( "OnResetJavascriptDialogState") if callback: @@ -124,7 +127,8 @@ cdef public void JavascriptDialogHandler_OnJavascriptDialogClosed( ) except * with gil: cdef PyBrowser pyBrowser try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, + "OnJavascriptDialogClosed") callback = pyBrowser.GetClientCallback("OnJavascriptDialogClosed") if callback: callback(browser=pyBrowser) diff --git a/src/handlers/keyboard_handler.pyx b/src/handlers/keyboard_handler.pyx index 408487c5f..c895b9b5e 100644 --- a/src/handlers/keyboard_handler.pyx +++ b/src/handlers/keyboard_handler.pyx @@ -54,7 +54,7 @@ cdef public cpp_bool KeyboardHandler_OnPreKeyEvent( cdef py_bool returnValue cdef object callback try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnPreKeyEvent") pyEvent = CefToPyKeyEvent(cefEvent) pyIsKeyboardShortcutOut = [cefIsKeyboardShortcut[0]] callback = pyBrowser.GetClientCallback("OnPreKeyEvent") @@ -82,7 +82,7 @@ cdef public cpp_bool KeyboardHandler_OnKeyEvent( cdef py_bool returnValue cdef object callback try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnKeyEvent") pyEvent = CefToPyKeyEvent(cefEvent) callback = pyBrowser.GetClientCallback("OnKeyEvent") if callback: diff --git a/src/handlers/lifespan_handler.pyx b/src/handlers/lifespan_handler.pyx index dbc379434..ad6730b1b 100644 --- a/src/handlers/lifespan_handler.pyx +++ b/src/handlers/lifespan_handler.pyx @@ -47,7 +47,7 @@ cdef public cpp_bool LifespanHandler_OnBeforePopup( cdef object callback cdef py_bool returnValue try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnBeforePopup") pyFrame = GetPyFrame(cefFrame) pyTargetUrl = CefToPyString(targetUrl) pyTargetFrameName = CefToPyString(targetFrameName) @@ -84,7 +84,7 @@ cdef public void LifespanHandler_OnAfterCreated( ) except * with gil: cdef PyBrowser pyBrowser try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnAfterCreated") callback = GetGlobalClientCallback("OnAfterCreated") if callback: callback(browser=pyBrowser) @@ -97,7 +97,7 @@ cdef public cpp_bool LifespanHandler_DoClose( ) except * with gil: cdef PyBrowser pyBrowser try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "DoClose") callback = pyBrowser.GetClientCallback("DoClose") if callback: return bool(callback(browser=pyBrowser)) @@ -112,7 +112,8 @@ cdef public void LifespanHandler_OnBeforeClose( cdef PyBrowser pyBrowser cdef object callback try: - pyBrowser = GetPyBrowser(cefBrowser) + Debug("LifespanHandler_OnBeforeClose") + pyBrowser = GetPyBrowser(cefBrowser, "OnBeforeClose") callback = pyBrowser.GetClientCallback("OnBeforeClose") if callback: callback(browser=pyBrowser) @@ -120,6 +121,8 @@ cdef public void LifespanHandler_OnBeforeClose( RemovePyFramesForBrowser(pyBrowser.GetIdentifier()) RemovePyBrowser(pyBrowser.GetIdentifier()) if g_MessageLoop_called and not len(g_pyBrowsers): + # Automatically quit message loop when last browser was closed. + # This is required for hello_world.py example to work. QuitMessageLoop() except: diff --git a/src/handlers/load_handler.pyx b/src/handlers/load_handler.pyx index 47e1d28df..c7627f5cf 100644 --- a/src/handlers/load_handler.pyx +++ b/src/handlers/load_handler.pyx @@ -3,6 +3,7 @@ # Project website: https://github.com/cztomczak/cefpython include "../cefpython.pyx" +include "../browser.pyx" cdef public void LoadHandler_OnLoadingStateChange( CefRefPtr[CefBrowser] cefBrowser, @@ -13,7 +14,7 @@ cdef public void LoadHandler_OnLoadingStateChange( cdef PyBrowser pyBrowser cdef object callback try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnLoadingStateChange") callback = pyBrowser.GetClientCallback("OnLoadingStateChange") if callback: callback(browser=pyBrowser, @@ -32,7 +33,7 @@ cdef public void LoadHandler_OnLoadStart( cdef PyFrame pyFrame cdef object clientCallback try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnLoadStart") pyFrame = GetPyFrame(cefFrame) clientCallback = pyBrowser.GetClientCallback("OnLoadStart") if clientCallback: @@ -50,7 +51,7 @@ cdef public void LoadHandler_OnLoadEnd( cdef PyFrame pyFrame cdef object clientCallback try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnLoadEnd") pyFrame = GetPyFrame(cefFrame) clientCallback = pyBrowser.GetClientCallback("OnLoadEnd") if clientCallback: @@ -77,7 +78,7 @@ cdef public void LoadHandler_OnLoadError( # the error code will be ERR_ABORTED. In such cases calls # to OnLoadError should be ignored and not handled by user # scripts. The wxpython example implements such behavior. - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnLoadError") pyFrame = GetPyFrame(cefFrame) errorTextOut = [CefToPyString(cefErrorText)] clientCallback = pyBrowser.GetClientCallback("OnLoadError") diff --git a/src/handlers/render_handler.pyx b/src/handlers/render_handler.pyx index acbb5c285..1594d6bd6 100644 --- a/src/handlers/render_handler.pyx +++ b/src/handlers/render_handler.pyx @@ -3,6 +3,7 @@ # Project website: https://github.com/cztomczak/cefpython include "../cefpython.pyx" +include "../browser.pyx" cimport cef_types @@ -29,7 +30,7 @@ cdef public cpp_bool RenderHandler_GetRootScreenRect( cdef list pyRect = [] cdef py_bool ret try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "GetRootScreenRect") callback = pyBrowser.GetClientCallback("GetRootScreenRect") if callback: ret = callback(browser=pyBrowser, rect_out=pyRect) @@ -56,7 +57,7 @@ cdef public cpp_bool RenderHandler_GetViewRect( cdef list pyRect = [] cdef py_bool ret try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "GetViewRect") callback = pyBrowser.GetClientCallback("GetViewRect") if callback: ret = callback(browser=pyBrowser, rect_out=pyRect) @@ -83,7 +84,7 @@ cdef public cpp_bool RenderHandler_GetScreenRect( cdef list pyRect = [] cdef py_bool ret try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "GetScreenRect") callback = pyBrowser.GetClientCallback("GetScreenRect") if callback: ret = callback(browser=pyBrowser, rect_out=pyRect) @@ -112,7 +113,7 @@ cdef public cpp_bool RenderHandler_GetScreenPoint( cdef list screenCoordinates = [] cdef py_bool ret try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "GetScreenPoint") callback = pyBrowser.GetClientCallback("GetScreenPoint") if callback: ret = callback(browser=pyBrowser, @@ -146,7 +147,7 @@ cdef public void RenderHandler_OnPopupShow( ) except * with gil: cdef PyBrowser pyBrowser try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnPopupShow") callback = pyBrowser.GetClientCallback("OnPopupShow") if callback: callback(browser=pyBrowser, show=show) @@ -161,7 +162,7 @@ cdef public void RenderHandler_OnPopupSize( cdef PyBrowser pyBrowser cdef list pyRect try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnPopupSize") callback = pyBrowser.GetClientCallback("OnPopupSize") if callback: pyRect = [cefRect.x, cefRect.y, cefRect.width, cefRect.height] @@ -187,8 +188,7 @@ cdef public void RenderHandler_OnPaint( cdef CefRect cefRect cdef PaintBuffer paintBuffer try: - pyBrowser = GetPyBrowser(cefBrowser) - + pyBrowser = GetPyBrowser(cefBrowser, "OnPaint") iterator = cefDirtyRects.begin() while iterator != cefDirtyRects.end(): cefRect = deref(iterator) @@ -223,7 +223,7 @@ cdef public void RenderHandler_OnCursorChange( ) except * with gil: cdef PyBrowser pyBrowser try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnCursorChange") callback = pyBrowser.GetClientCallback("OnCursorChange") if callback: callback(browser=pyBrowser, cursor=cursor) @@ -236,7 +236,7 @@ cdef public void RenderHandler_OnScrollOffsetChanged( ) except * with gil: cdef PyBrowser pyBrowser try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnScrollOffsetChanged") callback = pyBrowser.GetClientCallback("OnScrollOffsetChanged") if callback: callback(browser=pyBrowser) @@ -254,7 +254,7 @@ cdef public cpp_bool RenderHandler_StartDragging( cdef DragData drag_data cdef py_bool ret try: - browser = GetPyBrowser(cef_browser) + browser = GetPyBrowser(cef_browser, "StartDragging") drag_data = DragData_Init(cef_drag_data) callback = browser.GetClientCallback("StartDragging") if callback: @@ -280,7 +280,7 @@ cdef public void RenderHandler_UpdateDragCursor( ) except * with gil: cdef PyBrowser browser try: - browser = GetPyBrowser(cef_browser) + browser = GetPyBrowser(cef_browser, "UpdateDragCursor") callback = browser.GetClientCallback("UpdateDragCursor") if callback: callback(browser=browser, operation=operation) diff --git a/src/handlers/request_handler.pyx b/src/handlers/request_handler.pyx index 259e23a1c..b2cadbe7d 100644 --- a/src/handlers/request_handler.pyx +++ b/src/handlers/request_handler.pyx @@ -3,6 +3,7 @@ # Project website: https://github.com/cztomczak/cefpython include "../cefpython.pyx" +include "../browser.pyx" # cef_termination_status_t cimport cef_types @@ -67,7 +68,7 @@ cdef public cpp_bool RequestHandler_OnBeforeBrowse( cdef object clientCallback cdef py_bool returnValue try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnBeforeBrowse") pyFrame = GetPyFrame(cefFrame) pyRequest = CreatePyRequest(cefRequest) pyIsRedirect = bool(cefIsRedirect) @@ -97,7 +98,7 @@ cdef public cpp_bool RequestHandler_OnBeforeResourceLoad( cdef object clientCallback cdef py_bool returnValue try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnBeforeResourceLoad") pyFrame = GetPyFrame(cefFrame) pyRequest = CreatePyRequest(cefRequest) clientCallback = pyBrowser.GetClientCallback("OnBeforeResourceLoad") @@ -125,7 +126,7 @@ cdef public CefRefPtr[CefResourceHandler] RequestHandler_GetResourceHandler( cdef object clientCallback cdef object returnValue try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "GetResourceHandler") pyFrame = GetPyFrame(cefFrame) pyRequest = CreatePyRequest(cefRequest) clientCallback = pyBrowser.GetClientCallback("GetResourceHandler") @@ -161,7 +162,7 @@ cdef public void RequestHandler_OnResourceRedirect( cdef PyResponse pyResponse cdef object clientCallback try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnResourceRedirect") pyFrame = GetPyFrame(cefFrame) pyOldUrl = CefToPyString(cefOldUrl) pyNewUrlOut = [CefToPyString(cefNewUrl)] @@ -206,7 +207,7 @@ cdef public cpp_bool RequestHandler_GetAuthCredentials( cdef list pyPasswordOut cdef object clientCallback try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "GetAuthCredentials") pyFrame = GetPyFrame(cefFrame) pyIsProxy = bool(cefIsProxy) pyHost = CefToPyString(cefHost) @@ -260,7 +261,7 @@ cdef public cpp_bool RequestHandler_OnQuotaRequest( cdef py_bool returnValue cdef object clientCallback try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnQuotaRequest") pyOriginUrl = CefToPyString(cefOriginUrl) clientCallback = pyBrowser.GetClientCallback("OnQuotaRequest") if clientCallback: @@ -290,7 +291,7 @@ cdef public CefRefPtr[CefCookieManager] RequestHandler_GetCookieManager( cdef object clientCallback cdef PyCookieManager returnValue try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "GetCookieManager") pyMainUrl = CefToPyString(cefMainUrl) if pyBrowser: # Browser may be empty. @@ -322,7 +323,7 @@ cdef public void RequestHandler_OnProtocolExecution( cdef list pyAllowOSExecutionOut cdef object clientCallback try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnProtocolExecution") pyUrl = CefToPyString(cefUrl) pyAllowOSExecutionOut = [bool(cefAllowOSExecution)] clientCallback = pyBrowser.GetClientCallback("OnProtocolExecution") @@ -357,7 +358,7 @@ cdef public cpp_bool RequestHandler_OnBeforePluginLoad( cdef py_bool returnValue cdef object clientCallback try: - py_browser = GetPyBrowser(browser) + py_browser = GetPyBrowser(browser, "OnBeforePluginLoad") py_plugin_info = CreatePyWebPluginInfo(plugin_info) clientCallback = GetGlobalClientCallback("OnBeforePluginLoad") if clientCallback: @@ -412,7 +413,7 @@ cdef public void RequestHandler_OnRendererProcessTerminated( cdef PyBrowser pyBrowser cdef object clientCallback try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnRendererProcessTerminated") clientCallback = pyBrowser.GetClientCallback( "OnRendererProcessTerminated") if clientCallback: @@ -434,7 +435,7 @@ cdef public void RequestHandler_OnPluginCrashed( cdef PyBrowser pyBrowser cdef object clientCallback try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnPluginCrashed") clientCallback = pyBrowser.GetClientCallback("OnPluginCrashed") if clientCallback: clientCallback( diff --git a/src/handlers/v8context_handler.pyx b/src/handlers/v8context_handler.pyx index 741daab8c..704f6ad92 100644 --- a/src/handlers/v8context_handler.pyx +++ b/src/handlers/v8context_handler.pyx @@ -9,6 +9,7 @@ # a bit delayed due to asynchronous way this is being done. include "../cefpython.pyx" +include "../browser.pyx" cdef public void V8ContextHandler_OnContextCreated( CefRefPtr[CefBrowser] cefBrowser, @@ -19,7 +20,7 @@ cdef public void V8ContextHandler_OnContextCreated( cdef object clientCallback try: Debug("V8ContextHandler_OnContextCreated()") - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "OnContextCreated") pyBrowser.SetUserData("__v8ContextCreated", True) pyFrame = GetPyFrame(cefFrame) # User defined callback. @@ -48,6 +49,10 @@ cdef public void V8ContextHandler_OnContextReleased( # were released. Debug("V8ContextHandler_OnContextReleased()") pyBrowser = GetPyBrowserById(browserId) + if not pyBrowser: + Debug("OnContextReleased: Browser doesn't exist anymore, id={id}" + .format(id=str(browserId))) + return pyFrame = GetPyFrameById(browserId, frameId) if pyBrowser and pyFrame: clientCallback = pyBrowser.GetClientCallback("OnContextReleased") @@ -56,10 +61,10 @@ cdef public void V8ContextHandler_OnContextReleased( else: if not pyBrowser: Debug("V8ContextHandler_OnContextReleased() WARNING: " - "pyBrowser not found") + "PyBrowser not found") if not pyFrame: Debug("V8ContextHandler_OnContextReleased() WARNING: " - "pyFrame not found") + "PyFrame not found") RemovePyFrame(browserId, frameId) except: (exc_type, exc_value, exc_trace) = sys.exc_info() diff --git a/src/handlers/v8function_handler.pyx b/src/handlers/v8function_handler.pyx index c4cfd89d9..2c9b3f1cf 100644 --- a/src/handlers/v8function_handler.pyx +++ b/src/handlers/v8function_handler.pyx @@ -3,6 +3,7 @@ # Project website: https://github.com/cztomczak/cefpython include "../cefpython.pyx" +include "../browser.pyx" cdef public void V8FunctionHandler_Execute( CefRefPtr[CefBrowser] cefBrowser, @@ -18,7 +19,7 @@ cdef public void V8FunctionHandler_Execute( cdef object returnValue cdef py_string jsErrorMessage try: - pyBrowser = GetPyBrowser(cefBrowser) + pyBrowser = GetPyBrowser(cefBrowser, "V8FunctionHandler_Execute") pyFrame = GetPyFrame(cefFrame) functionName = CefToPyString(cefFunctionName) Debug("V8FunctionHandler_Execute(): functionName=%s" % functionName) diff --git a/src/javascript_callback.pyx b/src/javascript_callback.pyx index 81a06eb86..be474be77 100644 --- a/src/javascript_callback.pyx +++ b/src/javascript_callback.pyx @@ -3,9 +3,11 @@ # Project website: https://github.com/cztomczak/cefpython include "cefpython.pyx" +include "browser.pyx" cdef JavascriptCallback CreateJavascriptCallback(int callbackId, - CefRefPtr[CefBrowser] cefBrowser, object frameId, py_string functionName): + CefRefPtr[CefBrowser] cefBrowser, object frameId, + py_string functionName): # frameId is int64 cdef JavascriptCallback jsCallback = JavascriptCallback() jsCallback.callbackId = callbackId @@ -17,6 +19,8 @@ cdef JavascriptCallback CreateJavascriptCallback(int callbackId, return jsCallback cdef class JavascriptCallback: + """A javascript callback object may still live while browser/frame + are destroyed. Always check frame/browser for None value.""" cdef int callbackId cdef PyFrame frame cdef py_string functionName @@ -32,18 +36,24 @@ cdef class JavascriptCallback: "ExecuteJavascriptCallback", [self.callbackId] + list(args)) else: - Debug("JavascriptCallback.Call() FAILED: browser not found, " \ - "callbackId = %s" % self.callbackId) + # This code probably ain't needed + raise Exception("JavascriptCallback.Call() FAILED: browser" + " not found, callbackId = %s" + % self.callbackId) else: - Debug("JavascriptCallback.Call() FAILED: frame not found, " \ - "callbackId = %s" % self.callbackId) + # This code probably ain't needed + raise Exception("JavascriptCallback.Call() FAILED: frame not found" + ", callbackId = %s" % self.callbackId) def GetFunctionName(self): return self.functionName def GetName(self): - # DEPRECATED name. + """@deprecated.""" return self.GetFunctionName() + def GetId(self): + return self.callbackId + def GetFrame(self): return self.frame diff --git a/tools/build.py b/tools/build.py index fce02f349..9b6db3518 100644 --- a/tools/build.py +++ b/tools/build.py @@ -184,6 +184,17 @@ def check_directories(): if not os.path.exists(BUILD_CEFPYTHON): os.makedirs(BUILD_CEFPYTHON) + # Info if directory missing + if not os.path.exists(CEF_BINARIES_LIBRARIES): + prebuilt_name = get_cef_binaries_libraries_basename(OS_POSTFIX2) + print("[build.py] ERROR: Couldn't find CEF prebuilt binaries and" + " libraries: 'build/{prebuilt_dir}/'. Download it" + " from GitHub released tagged eg. 'v50-upstream` or download" + " CEF binaries from Spotify Automated Builds and then run" + "`automate.py --prebuilt-cef`." + .format(prebuilt_dir=prebuilt_name)) + sys.exit(1) + # Check directories exist assert os.path.exists(BUILD_DIR) assert os.path.exists(BUILD_CEFPYTHON) From 7f1e84b910f4992e9cdc9740b6031b3584c65563 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sun, 19 Mar 2017 12:47:03 +0100 Subject: [PATCH 178/557] Fix segmentation fault during release of shared request context (#333) --- src/browser.pyx | 14 -------- src/cefpython.pyx | 59 ++++++++++++++++--------------- src/extern/cef/cef_ptr.pxd | 4 +-- src/extern/cef/cef_scoped_ptr.pxd | 4 +-- 4 files changed, 34 insertions(+), 47 deletions(-) diff --git a/src/browser.pyx b/src/browser.pyx index d27a75e77..59c1aaf1e 100644 --- a/src/browser.pyx +++ b/src/browser.pyx @@ -121,13 +121,6 @@ cdef void RemovePyBrowser(int browserId) except *: # Called from LifespanHandler_OnBeforeClose(). global g_pyBrowsers, g_unreferenced_browsers if browserId in g_pyBrowsers: - if len(g_pyBrowsers) == 1: - # This is the last browser remaining. - if g_sharedRequestContext.get(): - # A similar release is done in Shutdown and CloseBrowser. - # noinspection PyUnresolvedReferences - Debug("RemovePyBrowser: releasing shared request context") - g_sharedRequestContext.Assign(NULL) # noinspection PyUnresolvedReferences Debug("del g_pyBrowsers[%s]" % browserId) del g_pyBrowsers[browserId] @@ -302,13 +295,6 @@ cdef class PyBrowser: pass cpdef py_void CloseBrowser(self, py_bool forceClose=False): - if len(g_pyBrowsers) == 1: - # This is the last browser remaining. - if g_sharedRequestContext.get(): - # A similar release is done in Shutdown - # and RemovePyBrowser. - Debug("CloseBrowser: releasing shared request context") - g_sharedRequestContext.Assign(NULL) Debug("CefBrowser::CloseBrowser(%s)" % forceClose) cdef int browserId = self.GetCefBrowser().get().GetIdentifier() self.GetCefBrowserHost().get().CloseBrowser(bool(forceClose)) diff --git a/src/cefpython.pyx b/src/cefpython.pyx index 6fb922e1b..64b1fe7c9 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -198,8 +198,8 @@ END OF: CHANGES in CEF since v31..v47. # | cdef cppclass _Object "Object": # # - Supporting operators that are not yet supported: -# | CefRefPtr[T]& Assign "operator="(T* p) -# | cefBrowser.Assign(CefBrowser*) +# | RetValue& Assign "operator="(T* p) +# | object.Assign(T*) # In the same way you can import function with a different name, this one # imports a static method Create() while adding a prefix "CefSome_": # | cdef extern from "..": @@ -390,9 +390,14 @@ from cef_types cimport ( int32, uint32, int64, uint64, ) +# noinspection PyUnresolvedReferences +from cef_ptr cimport CefRefPtr + +# noinspection PyUnresolvedReferences +from cef_scoped_ptr cimport scoped_ptr + from cef_task cimport * from cef_platform cimport * -from cef_ptr cimport * from cef_app cimport * from cef_browser cimport * # noinspection PyUnresolvedReferences @@ -428,9 +433,6 @@ from cef_path_util cimport * from cef_drag_data cimport * from cef_image cimport * from main_message_loop cimport * -# noinspection PyUnresolvedReferences -from cef_scoped_ptr cimport scoped_ptr - # ----------------------------------------------------------------------------- # GLOBAL VARIABLES @@ -445,6 +447,12 @@ g_debugFile = "debug.log" g_applicationSettings = {"string_encoding": "utf-8"} g_commandLineSwitches = {} +# If ApplicationSettings.unique_request_context_per_browser is False +# then a shared request context is used for all browsers. Otherwise +# a unique one is created for each call to CreateBrowserSync. +# noinspection PyUnresolvedReferences +cdef CefRefPtr[CefRequestContext] g_shared_request_context + cdef scoped_ptr[MainMessageLoopExternalPump] g_external_message_pump cdef py_bool g_MessageLoop_called = False @@ -452,12 +460,6 @@ cdef py_bool g_MessageLoopWork_called = False cdef dict g_globalClientCallbacks = {} -# If ApplicationSettings.unique_request_context_per_browser is False -# then a shared request context is used for all browsers. Otherwise -# a unique one is created for each call to CreateBrowserSync. -# noinspection PyUnresolvedReferences -cdef CefRefPtr[CefRequestContext] g_sharedRequestContext - # ----------------------------------------------------------------------------- include "utils.pyx" @@ -735,7 +737,8 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): # External message pump if GetAppSetting("external_message_pump")\ and not g_external_message_pump.get(): - g_external_message_pump.Assign(MainMessageLoopExternalPump.Create()) + g_external_message_pump.reset( + MainMessageLoopExternalPump.Create().get()) Debug("CefInitialize()") cdef cpp_bool ret @@ -786,7 +789,6 @@ def CreateBrowserSync(windowInfo=None, cdef CefWindowInfo cefWindowInfo SetCefWindowInfo(cefWindowInfo, windowInfo) - navigateUrl = GetNavigateUrl(navigateUrl) Debug("navigateUrl: %s" % navigateUrl) cdef CefString cefNavigateUrl @@ -798,7 +800,7 @@ def CreateBrowserSync(windowInfo=None, cdef CefRefPtr[CefBrowser] cefBrowser # Request context - part 1/2. - createSharedRequestContext = bool(not g_sharedRequestContext.get()) + createSharedRequestContext = bool(not g_shared_request_context.get()) cdef CefRefPtr[CefRequestContext] cefRequestContext cdef CefRefPtr[RequestContextHandler] requestContextHandler =\ new RequestContextHandler( @@ -807,15 +809,13 @@ def CreateBrowserSync(windowInfo=None, cefRequestContext = CefRequestContext.CreateContext( CefRequestContext.GetGlobalContext(), requestContextHandler) + elif createSharedRequestContext: + cefRequestContext = CefRequestContext.CreateContext( + CefRequestContext.GetGlobalContext(), + requestContextHandler) + g_shared_request_context.Assign(cefRequestContext.get()) else: - if createSharedRequestContext: - cefRequestContext = CefRequestContext.CreateContext( - CefRequestContext.GetGlobalContext(), - \ - requestContextHandler) - g_sharedRequestContext.Assign(cefRequestContext.get()) - else: - cefRequestContext.Assign(g_sharedRequestContext.get()) + cefRequestContext.Assign(g_shared_request_context.get()) # CEF browser creation. with nogil: @@ -881,11 +881,12 @@ def QuitMessageLoop(): CefQuitMessageLoop() def Shutdown(): - if g_sharedRequestContext.get(): - # A similar release is done in RemovePyBrowser and CloseBrowser. - # This one is probably redundant. Additional testing should be done. - Debug("Shutdown: releasing shared request context") - g_sharedRequestContext.Assign(NULL) + Debug("Shutdown()") + + # Release shared request context. This is sometimes causing + # segmentation fault, so disabling it for now. See Issue #333: + # https://github.com/cztomczak/cefpython/issues/333 + # OFF: g_shared_request_context.Assign(NULL) # Run some message loop work, force closing browsers and then run # some message loop work again for the browsers to close cleanly. @@ -968,7 +969,7 @@ def Shutdown(): NonCriticalError("Shutdown called, but there are still browser" " references alive") - Debug("Shutdown()") + Debug("CefShutdown()") with nogil: CefShutdown() diff --git a/src/extern/cef/cef_ptr.pxd b/src/extern/cef/cef_ptr.pxd index ed4cdcae9..c5d9877cf 100644 --- a/src/extern/cef/cef_ptr.pxd +++ b/src/extern/cef/cef_ptr.pxd @@ -10,8 +10,8 @@ cdef extern from "include/internal/cef_ptr.h": # noinspection PyUnresolvedReferences CefRefPtr(const CefRefPtr[T]& r) # noinspection PyUnresolvedReferences - CefRefPtr[T]& Assign "operator="(T* p) # cefBrowser.Assign(CefBrowser*) - # noinspection PyUnresolvedReferences T* get() # noinspection PyUnresolvedReferences void swap(CefRefPtr[T]& r) + # noinspection PyUnresolvedReferences + CefRefPtr[T]& Assign "operator="(T* p) diff --git a/src/extern/cef/cef_scoped_ptr.pxd b/src/extern/cef/cef_scoped_ptr.pxd index f23cd156b..4498360cd 100644 --- a/src/extern/cef/cef_scoped_ptr.pxd +++ b/src/extern/cef/cef_scoped_ptr.pxd @@ -10,6 +10,6 @@ cdef extern from "include/base/cef_scoped_ptr.h": # noinspection PyUnresolvedReferences void reset() # noinspection PyUnresolvedReferences - T* get() + void reset(T* p) # noinspection PyUnresolvedReferences - scoped_ptr[T]& Assign "operator="(scoped_ptr[T]& p) + T* get() From c0a218ba1f44e6cef175a236545bebd7a8ab570e Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sun, 19 Mar 2017 19:59:48 +0100 Subject: [PATCH 179/557] Updated examples' README file - add wxpython-response.py example --- examples/Examples-README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/Examples-README.md b/examples/Examples-README.md index 337004d79..d7bb153cb 100644 --- a/examples/Examples-README.md +++ b/examples/Examples-README.md @@ -40,6 +40,11 @@ maintained. see [gist by AnishN](https://gist.github.com/AnishN/aa3bb27fc9d69319955ed9a8973cd40f) - Screenshot example: see [gist by stefanbacon](https://gist.github.com/stefanbacon/7b1571d57aee54aa9f8e9021b4848d06) +- Example of implementing [ResourceHandler](../api/ResourceHandler.md) + with the use of [WebRequest](../api/WebRequest.md) object and + [WebRequestClient](../api/WebRequestClient.md) interface to allow + for reading/modifying web requests: see the [wxpython-response.py](https://github.com/cztomczak/cefpython/blob/cefpython31/cefpython/cef3/linux/binaries_64bit/wxpython-response.py) + example in the cefpython31 branch. - Old PyWin32 example: see [pywin32.py](https://github.com/cztomczak/cefpython/blob/cefpython31/cefpython/cef3/windows/binaries_32bit/pywin32.py) in the cefpython31 branch From c5951b67bd59014f249f75912db153c8a3b3aadf Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 20 Mar 2017 09:23:22 +0100 Subject: [PATCH 180/557] Provide default implementation for js and file dialogs on Linux (#241)... In wxpython.py and gtk2.py examples the js alert dialog when run from a popup gives focus to the main window. The popup window is created internally by CEF and this probably needs to be changed so that popups are created by wx in OnBeforePopup and this will resolve issue with alert focus. In qt4.py and tkinter.py and hello_world.py examples focus works fine in the popup window. Add --hello-world flag to build.py and run_examples.py tools. --- src/client_handler/Makefile | 4 +- src/client_handler/client_handler.cpp | 1 + src/client_handler/client_handler.h | 8 + src/client_handler/dialog_handler.cpp | 37 ++ src/client_handler/dialog_handler.h | 38 ++ src/client_handler/dialog_handler_gtk.cpp | 464 ++++++++++++++++++++++ src/client_handler/dialog_handler_gtk.h | 59 +++ src/client_handler/js_dialog_handler.cpp | 32 +- src/client_handler/js_dialog_handler.h | 12 +- src/compile_time_constants.pxi | 2 +- src/handlers/lifespan_handler.pyx | 9 + src/window_utils_mac.pyx | 4 + src/window_utils_win.pyx | 4 + tools/build.py | 22 +- tools/run_examples.py | 24 +- 15 files changed, 704 insertions(+), 16 deletions(-) create mode 100644 src/client_handler/dialog_handler.cpp create mode 100644 src/client_handler/dialog_handler.h create mode 100644 src/client_handler/dialog_handler_gtk.cpp create mode 100644 src/client_handler/dialog_handler_gtk.h diff --git a/src/client_handler/Makefile b/src/client_handler/Makefile index 4465d28b5..13586c8ed 100644 --- a/src/client_handler/Makefile +++ b/src/client_handler/Makefile @@ -12,7 +12,7 @@ UNAME_S = $(shell uname -s) CCFLAGS = -fPIC $(CEF_CCFLAGS) ifeq ($(UNAME_S), Linux) - SRC_MORE = x11.cpp + SRC_MORE = x11.cpp dialog_handler_gtk.cpp else ifeq ($(UNAME_S), Darwin) SRC_MORE = util_mac.mm endif @@ -22,7 +22,7 @@ SRC = client_handler.cpp cookie_visitor.cpp resource_handler.cpp \ task.cpp context_menu_handler.cpp display_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 \ + render_handler.cpp request_handler.cpp dialog_handler.cpp \ $(SRC_MORE) OBJ = $(filter %.o, $(SRC:.cpp=.o) $(SRC:.mm=.o)) diff --git a/src/client_handler/client_handler.cpp b/src/client_handler/client_handler.cpp index d8f6189e6..f14fbaf85 100644 --- a/src/client_handler/client_handler.cpp +++ b/src/client_handler/client_handler.cpp @@ -24,6 +24,7 @@ // CefClient // ---------------------------------------------------------------------------- + bool ClientHandler::OnProcessMessageReceived( CefRefPtr browser, CefProcessId source_process, diff --git a/src/client_handler/client_handler.h b/src/client_handler/client_handler.h index 33c125072..4a5c29b7c 100644 --- a/src/client_handler/client_handler.h +++ b/src/client_handler/client_handler.h @@ -13,6 +13,7 @@ #include "common/cefpython_public_api.h" #include "context_menu_handler.h" +#include "dialog_handler.h" #include "display_handler.h" #include "download_handler.h" #include "focus_handler.h" @@ -26,6 +27,7 @@ class ClientHandler : public CefClient, public ContextMenuHandler, + public DialogHandler, public DisplayHandler, public DownloadHandler, public FocusHandler, @@ -44,6 +46,12 @@ class ClientHandler : public CefClient, return this; } +#if defined(OS_LINUX) + CefRefPtr GetDialogHandler() override { + return this; + } +#endif + CefRefPtr GetDisplayHandler() override { return this; } diff --git a/src/client_handler/dialog_handler.cpp b/src/client_handler/dialog_handler.cpp new file mode 100644 index 000000000..ab90de9b6 --- /dev/null +++ b/src/client_handler/dialog_handler.cpp @@ -0,0 +1,37 @@ +// 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 "dialog_handler.h" + + +DialogHandler::DialogHandler() +{ +#if defined(OS_LINUX) + // Provide the GTK-based default dialog implementation on Linux. + dialog_handler_ = new ClientDialogHandlerGtk(); +#endif +} + + +bool DialogHandler::OnFileDialog(CefRefPtr browser, + FileDialogMode mode, + const CefString& title, + const CefString& default_file_path, + const std::vector& accept_filters, + int selected_accept_filter, + CefRefPtr callback) +{ +#if defined(OS_LINUX) + return dialog_handler_->OnFileDialog(browser, + mode, + title, + default_file_path, + accept_filters, + selected_accept_filter, + callback); +#else + return false; +#endif + +} diff --git a/src/client_handler/dialog_handler.h b/src/client_handler/dialog_handler.h new file mode 100644 index 000000000..21d79a60d --- /dev/null +++ b/src/client_handler/dialog_handler.h @@ -0,0 +1,38 @@ +// 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 + +#include "common/cefpython_public_api.h" +#include "include/cef_dialog_handler.h" + +#if defined(OS_LINUX) +#include "dialog_handler_gtk.h" +#endif + + +class DialogHandler : public CefDialogHandler +{ +public: + DialogHandler(); + virtual ~DialogHandler(){} + + bool OnFileDialog(CefRefPtr browser, + FileDialogMode mode, + const CefString& title, + const CefString& default_file_path, + const std::vector& accept_filters, + int selected_accept_filter, + CefRefPtr callback) + override; + +public: +#if defined(OS_LINUX) + // Default dialog handler impl for GTK. + CefRefPtr dialog_handler_; +#endif + +private: + IMPLEMENT_REFCOUNTING(DialogHandler); +}; diff --git a/src/client_handler/dialog_handler_gtk.cpp b/src/client_handler/dialog_handler_gtk.cpp new file mode 100644 index 000000000..1db132907 --- /dev/null +++ b/src/client_handler/dialog_handler_gtk.cpp @@ -0,0 +1,464 @@ +// Default dialog handler implementation on Linux. +// Copied from upstream cefclient with changes: +// - Rewrote GetWindow() func +// - Removed "client" namespace +// - Changed titles of JS alerts, removed URL and "Javascript" word + +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include +#include +#include +#include + +#include "include/cef_browser.h" +#include "include/cef_parser.h" +#include "include/wrapper/cef_helpers.h" + +#include "dialog_handler_gtk.h" +#include "x11.h" + +namespace { + +const char kPromptTextId[] = "cef_prompt_text"; + +// If there's a text entry in the dialog, get the text from the first one and +// return it. +std::string GetPromptText(GtkDialog* dialog) { + GtkWidget* widget = static_cast( + g_object_get_data(G_OBJECT(dialog), kPromptTextId)); + if (widget) + return gtk_entry_get_text(GTK_ENTRY(widget)); + return std::string(); +} + +std::string GetDescriptionFromMimeType(const std::string& mime_type) { + // Check for wild card mime types and return an appropriate description. + static const struct { + const char* mime_type; + const char* label; + } kWildCardMimeTypes[] = { + { "audio", "Audio Files" }, + { "image", "Image Files" }, + { "text", "Text Files" }, + { "video", "Video Files" }, + }; + + for (size_t i = 0; + i < sizeof(kWildCardMimeTypes) / sizeof(kWildCardMimeTypes[0]); ++i) { + if (mime_type == std::string(kWildCardMimeTypes[i].mime_type) + "/*") + return std::string(kWildCardMimeTypes[i].label); + } + + return std::string(); +} + +void AddFilters(GtkFileChooser* chooser, + const std::vector& accept_filters, + bool include_all_files, + std::vector* filters) { + bool has_filter = false; + + for (size_t i = 0; i < accept_filters.size(); ++i) { + const std::string& filter = accept_filters[i]; + if (filter.empty()) + continue; + + std::vector extensions; + std::string description; + + size_t sep_index = filter.find('|'); + if (sep_index != std::string::npos) { + // Treat as a filter of the form "Filter Name|.ext1;.ext2;.ext3". + description = filter.substr(0, sep_index); + + const std::string& exts = filter.substr(sep_index + 1); + size_t last = 0; + size_t size = exts.size(); + for (size_t i = 0; i <= size; ++i) { + if (i == size || exts[i] == ';') { + std::string ext(exts, last, i - last); + if (!ext.empty() && ext[0] == '.') + extensions.push_back(ext); + last = i + 1; + } + } + } else if (filter[0] == '.') { + // Treat as an extension beginning with the '.' character. + extensions.push_back(filter); + } else { + // Otherwise convert mime type to one or more extensions. + description = GetDescriptionFromMimeType(filter); + + std::vector ext; + CefGetExtensionsForMimeType(filter, ext); + for (size_t x = 0; x < ext.size(); ++x) + extensions.push_back("." + ext[x].ToString()); + } + + if (extensions.empty()) + continue; + + GtkFileFilter* gtk_filter = gtk_file_filter_new(); + + std::string ext_str; + for (size_t x = 0; x < extensions.size(); ++x) { + const std::string& pattern = "*" + extensions[x]; + if (x != 0) + ext_str += ";"; + ext_str += pattern; + gtk_file_filter_add_pattern(gtk_filter, pattern.c_str()); + } + + if (description.empty()) + description = ext_str; + else + description += " (" + ext_str + ")"; + + gtk_file_filter_set_name(gtk_filter, description.c_str()); + gtk_file_chooser_add_filter(chooser, gtk_filter); + if (!has_filter) + has_filter = true; + + filters->push_back(gtk_filter); + } + + // Add the *.* filter, but only if we have added other filters (otherwise it + // is implied). + if (include_all_files && has_filter) { + GtkFileFilter* filter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(filter, "*"); + gtk_file_filter_set_name(filter, "All Files (*)"); + gtk_file_chooser_add_filter(chooser, filter); + } +} + +GtkWindow* GetWindow(CefRefPtr browser) { + // -- REWRITTEN FOR CEF PYTHON USE CASE -- + // X11 window handle + ::Window xwindow = browser->GetHost()->GetWindowHandle(); + // X11 display + ::Display* xdisplay = cef_get_xdisplay(); + // GDK display + GdkDisplay* gdk_display = NULL; + if (xdisplay) { + // See if we can find GDK display using X11 display + gdk_display = gdk_x11_lookup_xdisplay(xdisplay); + } + if (!gdk_display) { + // If not then get the default display + gdk_display = gdk_display_get_default(); + } + if (!gdk_display) { + // The tkinter_.py and hello_world.py examples do not use GTK + // 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. + gtk_init(0, NULL); + InstallX11ErrorHandlers(); + // Now the display is available + gdk_display = gdk_display_get_default(); + } + // In kivy_.py example getting error message: + // > Can't create GtkPlug as child of non-GtkSocket + // However dialog handler works just fine. + GtkWidget* widget = gtk_plug_new_for_display(gdk_display, xwindow); + // Getting top level widget doesn't seem to be required. + // OFF: GtkWidget* toplevel = gtk_widget_get_toplevel(widget); + GtkWindow* window = GTK_WINDOW(widget); + if (!window) { + LOG(ERROR) << "No GtkWindow for browser"; + } + return window; +} + +} // namespace + + +ClientDialogHandlerGtk::ClientDialogHandlerGtk() + : gtk_dialog_(NULL) { +} + +bool ClientDialogHandlerGtk::OnFileDialog( + CefRefPtr browser, + FileDialogMode mode, + const CefString& title, + const CefString& default_file_path, + const std::vector& accept_filters, + int selected_accept_filter, + CefRefPtr callback) { + std::vector files; + + GtkFileChooserAction action; + const gchar* accept_button; + + // Remove any modifier flags. + FileDialogMode mode_type = + static_cast(mode & FILE_DIALOG_TYPE_MASK); + + if (mode_type == FILE_DIALOG_OPEN || mode_type == FILE_DIALOG_OPEN_MULTIPLE) { + action = GTK_FILE_CHOOSER_ACTION_OPEN; + accept_button = GTK_STOCK_OPEN; + } else if (mode_type == FILE_DIALOG_OPEN_FOLDER) { + action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; + accept_button = GTK_STOCK_OPEN; + } else if (mode_type == FILE_DIALOG_SAVE) { + action = GTK_FILE_CHOOSER_ACTION_SAVE; + accept_button = GTK_STOCK_SAVE; + } else { + NOTREACHED(); + return false; + } + + std::string title_str; + if (!title.empty()) { + title_str = title; + } else { + switch (mode_type) { + case FILE_DIALOG_OPEN: + title_str = "Open File"; + break; + case FILE_DIALOG_OPEN_MULTIPLE: + title_str = "Open Files"; + break; + case FILE_DIALOG_OPEN_FOLDER: + title_str = "Open Folder"; + break; + case FILE_DIALOG_SAVE: + title_str = "Save File"; + break; + default: + break; + } + } + + GtkWindow* window = GetWindow(browser); + if (!window) + return false; + + GtkWidget* dialog = gtk_file_chooser_dialog_new( + title_str.c_str(), + GTK_WINDOW(window), + action, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + accept_button, GTK_RESPONSE_ACCEPT, + NULL); + + if (mode_type == FILE_DIALOG_OPEN_MULTIPLE) + gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); + + if (mode_type == FILE_DIALOG_SAVE) { + gtk_file_chooser_set_do_overwrite_confirmation( + GTK_FILE_CHOOSER(dialog), + !!(mode & FILE_DIALOG_OVERWRITEPROMPT_FLAG)); + } + + gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dialog), + !(mode & FILE_DIALOG_HIDEREADONLY_FLAG)); + + if (!default_file_path.empty() && mode_type == FILE_DIALOG_SAVE) { + const std::string& file_path = default_file_path; + bool exists = false; + + struct stat sb; + if (stat(file_path.c_str(), &sb) == 0 && S_ISREG(sb.st_mode)) { + // Use the directory and name of the existing file. + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), + file_path.data()); + exists = true; + } + + if (!exists) { + // Set the current file name but let the user choose the directory. + std::string file_name_str = file_path; + const char* file_name = basename(const_cast(file_name_str.data())); + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), file_name); + } + } + + std::vector filters; + AddFilters(GTK_FILE_CHOOSER(dialog), accept_filters, true, &filters); + if (selected_accept_filter < static_cast(filters.size())) { + gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), + filters[selected_accept_filter]); + } + + bool success = false; + + if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { + if (mode_type == FILE_DIALOG_OPEN || mode_type == FILE_DIALOG_OPEN_FOLDER || + mode_type == FILE_DIALOG_SAVE) { + char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + files.push_back(std::string(filename)); + success = true; + } else if (mode_type == FILE_DIALOG_OPEN_MULTIPLE) { + GSList* filenames = + gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)); + if (filenames) { + for (GSList* iter = filenames; iter != NULL; + iter = g_slist_next(iter)) { + std::string path(static_cast(iter->data)); + g_free(iter->data); + files.push_back(path); + } + g_slist_free(filenames); + success = true; + } + } + } + + int filter_index = selected_accept_filter; + if (success) { + GtkFileFilter* selected_filter = + gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog)); + if (selected_filter != NULL) { + for (size_t x = 0; x < filters.size(); ++x) { + if (filters[x] == selected_filter) { + filter_index = x; + break; + } + } + } + } + + gtk_widget_destroy(dialog); + + if (success) + callback->Continue(filter_index, files); + else + callback->Cancel(); + + return true; +} + +bool ClientDialogHandlerGtk::OnJSDialog( + CefRefPtr browser, + const CefString& origin_url, + JSDialogType dialog_type, + const CefString& message_text, + const CefString& default_prompt_text, + CefRefPtr callback, + bool& suppress_message) { + CEF_REQUIRE_UI_THREAD(); + + GtkButtonsType buttons = GTK_BUTTONS_NONE; + GtkMessageType gtk_message_type = GTK_MESSAGE_OTHER; + std::string title; + + switch (dialog_type) { + case JSDIALOGTYPE_ALERT: + buttons = GTK_BUTTONS_NONE; + gtk_message_type = GTK_MESSAGE_WARNING; + title = "Alert"; + break; + + case JSDIALOGTYPE_CONFIRM: + buttons = GTK_BUTTONS_CANCEL; + gtk_message_type = GTK_MESSAGE_QUESTION; + title = "Confirm"; + break; + + case JSDIALOGTYPE_PROMPT: + buttons = GTK_BUTTONS_CANCEL; + gtk_message_type = GTK_MESSAGE_QUESTION; + title = "Prompt"; + break; + } + + js_dialog_callback_ = callback; + + if (!origin_url.empty()) { + // title += " - "; + // title += CefFormatUrlForSecurityDisplay(origin_url).ToString(); + } + + GtkWindow* window = GetWindow(browser); + if (!window) + return false; + + gtk_dialog_ = gtk_message_dialog_new(GTK_WINDOW(window), + GTK_DIALOG_MODAL, + gtk_message_type, + buttons, + "%s", + message_text.ToString().c_str()); + g_signal_connect(gtk_dialog_, + "delete-event", + G_CALLBACK(gtk_widget_hide_on_delete), + NULL); + + gtk_window_set_title(GTK_WINDOW(gtk_dialog_), title.c_str()); + + GtkWidget* ok_button = gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_), + GTK_STOCK_OK, + GTK_RESPONSE_OK); + + if (dialog_type != JSDIALOGTYPE_PROMPT) + gtk_widget_grab_focus(ok_button); + + if (dialog_type == JSDIALOGTYPE_PROMPT) { + GtkWidget* content_area = + gtk_dialog_get_content_area(GTK_DIALOG(gtk_dialog_)); + GtkWidget* text_box = gtk_entry_new(); + gtk_entry_set_text(GTK_ENTRY(text_box), + default_prompt_text.ToString().c_str()); + gtk_box_pack_start(GTK_BOX(content_area), text_box, TRUE, TRUE, 0); + g_object_set_data(G_OBJECT(gtk_dialog_), kPromptTextId, text_box); + gtk_entry_set_activates_default(GTK_ENTRY(text_box), TRUE); + } + + gtk_dialog_set_default_response(GTK_DIALOG(gtk_dialog_), GTK_RESPONSE_OK); + g_signal_connect(gtk_dialog_, "response", G_CALLBACK(OnDialogResponse), this); + gtk_widget_show_all(GTK_WIDGET(gtk_dialog_)); + + return true; +} + +bool ClientDialogHandlerGtk::OnBeforeUnloadDialog( + CefRefPtr browser, + const CefString& message_text, + bool is_reload, + CefRefPtr callback) { + CEF_REQUIRE_UI_THREAD(); + + const std::string& new_message_text = + message_text.ToString() + "\n\nIs it OK to leave/reload this page?"; + bool suppress_message = false; + + return OnJSDialog(browser, CefString(), JSDIALOGTYPE_CONFIRM, + new_message_text, CefString(), callback, suppress_message); +} + +void ClientDialogHandlerGtk::OnResetDialogState(CefRefPtr browser) { + CEF_REQUIRE_UI_THREAD(); + + if (!gtk_dialog_) + return; + gtk_widget_destroy(gtk_dialog_); + gtk_dialog_ = NULL; + js_dialog_callback_ = NULL; +} + +// static +void ClientDialogHandlerGtk::OnDialogResponse(GtkDialog* dialog, + gint response_id, + ClientDialogHandlerGtk* handler) { + CEF_REQUIRE_UI_THREAD(); + + DCHECK_EQ(dialog, GTK_DIALOG(handler->gtk_dialog_)); + switch (response_id) { + case GTK_RESPONSE_OK: + handler->js_dialog_callback_->Continue(true, GetPromptText(dialog)); + break; + case GTK_RESPONSE_CANCEL: + case GTK_RESPONSE_DELETE_EVENT: + handler->js_dialog_callback_->Continue(false, CefString()); + break; + default: + NOTREACHED(); + } + + handler->OnResetDialogState(NULL); +} diff --git a/src/client_handler/dialog_handler_gtk.h b/src/client_handler/dialog_handler_gtk.h new file mode 100644 index 000000000..aba4857ae --- /dev/null +++ b/src/client_handler/dialog_handler_gtk.h @@ -0,0 +1,59 @@ +// Default dialog handler implementation on Linux. +// Copied from upstream cefclient with changes: +// - Removed "client" namespace + +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#ifndef CEF_TESTS_CEFCLIENT_BROWSER_DIALOG_HANDLER_GTK_H_ +#define CEF_TESTS_CEFCLIENT_BROWSER_DIALOG_HANDLER_GTK_H_ +#pragma once + +#include + +#include "include/cef_dialog_handler.h" +#include "include/cef_jsdialog_handler.h" + +class ClientDialogHandlerGtk : public CefDialogHandler, + public CefJSDialogHandler { + public: + ClientDialogHandlerGtk(); + + // CefDialogHandler methods. + bool OnFileDialog(CefRefPtr browser, + FileDialogMode mode, + const CefString& title, + const CefString& default_file_path, + const std::vector& accept_filters, + int selected_accept_filter, + CefRefPtr callback) OVERRIDE; + + // CefJSDialogHandler methods. + bool OnJSDialog(CefRefPtr browser, + const CefString& origin_url, + JSDialogType dialog_type, + const CefString& message_text, + const CefString& default_prompt_text, + CefRefPtr callback, + bool& suppress_message) OVERRIDE; + bool OnBeforeUnloadDialog( + CefRefPtr browser, + const CefString& message_text, + bool is_reload, + CefRefPtr callback) OVERRIDE; + void OnResetDialogState(CefRefPtr browser) OVERRIDE; + + private: + static void OnDialogResponse(GtkDialog *dialog, + gint response_id, + ClientDialogHandlerGtk* handler); + + GtkWidget* gtk_dialog_; + CefRefPtr js_dialog_callback_; + + IMPLEMENT_REFCOUNTING(ClientDialogHandlerGtk); + DISALLOW_COPY_AND_ASSIGN(ClientDialogHandlerGtk); +}; + +#endif // CEF_TESTS_CEFCLIENT_BROWSER_DIALOG_HANDLER_GTK_H_ diff --git a/src/client_handler/js_dialog_handler.cpp b/src/client_handler/js_dialog_handler.cpp index a1f641a0c..3d3ecd09f 100644 --- a/src/client_handler/js_dialog_handler.cpp +++ b/src/client_handler/js_dialog_handler.cpp @@ -4,6 +4,14 @@ #include "js_dialog_handler.h" +JSDialogHandler::JSDialogHandler() +{ +#if defined(OS_LINUX) + // Provide the GTK-based default dialog implementation on Linux. + dialog_handler_ = new ClientDialogHandlerGtk(); +#endif +} + bool JSDialogHandler::OnJSDialog(CefRefPtr browser, const CefString& origin_url, @@ -14,11 +22,18 @@ bool JSDialogHandler::OnJSDialog(CefRefPtr browser, bool& suppress_message) { REQUIRE_UI_THREAD(); - return JavascriptDialogHandler_OnJavascriptDialog( + bool ret = JavascriptDialogHandler_OnJavascriptDialog( browser, origin_url, dialog_type, message_text, default_prompt_text, callback, suppress_message); + if (!ret) { + // Default implementation + return dialog_handler_->OnJSDialog(browser, origin_url, dialog_type, + message_text, default_prompt_text, + callback, suppress_message); + } + return ret; } @@ -29,21 +44,30 @@ bool JSDialogHandler::OnBeforeUnloadDialog( CefRefPtr callback) { REQUIRE_UI_THREAD(); - return JavascriptDialogHandler_OnBeforeUnloadJavascriptDialog( + bool ret = JavascriptDialogHandler_OnBeforeUnloadJavascriptDialog( browser, message_text, is_reload, callback); + if (!ret) { + // Default implementation + return dialog_handler_->OnBeforeUnloadDialog(browser, message_text, + is_reload, callback); + } + return ret; } void JSDialogHandler::OnResetDialogState(CefRefPtr browser) { REQUIRE_UI_THREAD(); - return JavascriptDialogHandler_OnResetJavascriptDialogState(browser); + // Default implementation + dialog_handler_->OnResetDialogState(browser); + // User implementation + JavascriptDialogHandler_OnResetJavascriptDialogState(browser); } void JSDialogHandler::OnDialogClosed(CefRefPtr browser) { REQUIRE_UI_THREAD(); - return JavascriptDialogHandler_OnJavascriptDialogClosed(browser); + JavascriptDialogHandler_OnJavascriptDialogClosed(browser); } diff --git a/src/client_handler/js_dialog_handler.h b/src/client_handler/js_dialog_handler.h index 6d3ce3e48..43fdf2514 100644 --- a/src/client_handler/js_dialog_handler.h +++ b/src/client_handler/js_dialog_handler.h @@ -5,11 +5,15 @@ #include "common/cefpython_public_api.h" #include "include/cef_jsdialog_handler.h" +#if defined(OS_LINUX) +#include "dialog_handler_gtk.h" +#endif + class JSDialogHandler : public CefJSDialogHandler { public: - JSDialogHandler(){} + JSDialogHandler(); virtual ~JSDialogHandler(){} typedef cef_jsdialog_type_t JSDialogType; @@ -31,6 +35,12 @@ class JSDialogHandler : public CefJSDialogHandler void OnResetDialogState(CefRefPtr browser) override; void OnDialogClosed(CefRefPtr browser) override; +public: +#if defined(OS_LINUX) + // Default dialog handler impl for GTK. + CefRefPtr dialog_handler_; +#endif + private: IMPLEMENT_REFCOUNTING(JSDialogHandler); }; diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 47dedaecd..35f850027 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 = 3 +DEF PY_MAJOR_VERSION = 2 diff --git a/src/handlers/lifespan_handler.pyx b/src/handlers/lifespan_handler.pyx index ad6730b1b..32a3f0c46 100644 --- a/src/handlers/lifespan_handler.pyx +++ b/src/handlers/lifespan_handler.pyx @@ -113,6 +113,15 @@ cdef public void LifespanHandler_OnBeforeClose( cdef object callback try: Debug("LifespanHandler_OnBeforeClose") + # NOTE: browser_id may not necessarily be in g_pyBrowsers currently. + # I haven't yet debugged it but the logic in Shutdown that + # tries to force close browsers and removes references might + # have something to do with it. Such scenario is reproducible + # with the following steps: + # 1. Run wxpython.py example + # 2. Google "js alert" and open w3schools + # 3. Open demo popup + # 4. Close main window (not popup) pyBrowser = GetPyBrowser(cefBrowser, "OnBeforeClose") callback = pyBrowser.GetClientCallback("OnBeforeClose") if callback: diff --git a/src/window_utils_mac.pyx b/src/window_utils_mac.pyx index 07c70b64d..d683daf81 100644 --- a/src/window_utils_mac.pyx +++ b/src/window_utils_mac.pyx @@ -37,3 +37,7 @@ class WindowUtils: def IsWindowHandle(WindowHandle windowHandle): Debug("WindowUtils::IsWindowHandle() not implemented (always True)") return True + + @staticmethod + def InstallX11ErrorHandlers(): + pass diff --git a/src/window_utils_win.pyx b/src/window_utils_win.pyx index a1b613878..0dd9ee70b 100644 --- a/src/window_utils_win.pyx +++ b/src/window_utils_win.pyx @@ -145,3 +145,7 @@ class WindowUtils(object): return bool(IsWindow(windowHandle)) ELSE: return False + + @staticmethod + def InstallX11ErrorHandlers(): + pass diff --git a/tools/build.py b/tools/build.py index 9b6db3518..7debfffcb 100644 --- a/tools/build.py +++ b/tools/build.py @@ -19,6 +19,7 @@ Usage: build.py VERSION [--rebuild-cpp] [--fast] [--clean] [--kivy] + [--hello-world] Options: VERSION Version number eg. 50.0 @@ -26,6 +27,7 @@ --fast Fast mode --clean Clean C++ projects build files on Linux/Mac --kivy Run only Kivy example + --hello-world Run only Hello World example """ # --rebuild-cpp Force rebuild of .vcproj C++ projects (DISABLED) @@ -70,6 +72,7 @@ FAST_FLAG = False CLEAN_FLAG = False KIVY_FLAG = False +HELLO_WORLD_FLAG = False REBUILD_CPP = False # First run @@ -107,7 +110,7 @@ def main(): def command_line_args(): - global DEBUG_FLAG, FAST_FLAG, CLEAN_FLAG, KIVY_FLAG,\ + global DEBUG_FLAG, FAST_FLAG, CLEAN_FLAG, KIVY_FLAG, HELLO_WORLD_FLAG, \ REBUILD_CPP, VERSION, NO_RUN_EXAMPLES VERSION = get_version_from_command_line_args(__file__) @@ -141,7 +144,12 @@ def command_line_args(): # --kivy if "--kivy" in sys.argv: KIVY_FLAG = True - print("[build.py] KIVY mode enabled") + print("[build.py] KIVY example") + + # --kivy + if "--hello-world" in sys.argv: + HELLO_WORLD_FLAG = True + print("[build.py] HELLO WORLD example") # --rebuild-cpp # Rebuild c++ projects @@ -848,12 +856,16 @@ def install_and_run(): if not NO_RUN_EXAMPLES: print("[build.py] Run examples") os.chdir(EXAMPLES_DIR) - kivy_flag = "--kivy" if KIVY_FLAG else "" + flags = "" + if KIVY_FLAG: + flags += " --kivy" + if HELLO_WORLD_FLAG: + flags += " --hello-world" run_examples = os.path.join(TOOLS_DIR, "run_examples.py") - command = ("\"{python}\" {run_examples} {kivy_flag}" + command = ("\"{python}\" {run_examples} {flags}" .format(python=sys.executable, run_examples=run_examples, - kivy_flag=kivy_flag)) + flags=flags)) ret = os.system(command) if ret != 0: print("[build.py] ERROR while running examples") diff --git a/tools/run_examples.py b/tools/run_examples.py index 6562af669..a4a1f0bbb 100644 --- a/tools/run_examples.py +++ b/tools/run_examples.py @@ -20,6 +20,19 @@ def main(): os.chdir(EXAMPLES_DIR) + # When importing Kivy package there can't be any flags unknown to Kivy, + # use sys.argv.remove to remove them. + + kivy_flag = False + if "--kivy" in sys.argv: + sys.argv.remove("--kivy") + kivy_flag = True + + hello_world_flag = False + if "--hello-world" in sys.argv: + sys.argv.remove("--hello-world") + hello_world_flag = True + packages = check_installed_packages() examples = list() examples.append("hello_world.py") @@ -83,15 +96,20 @@ def main(): print(["run_examples.py] PASS: tkinter_.py (tkinter not installed)"]) passed.append("tkinter_.py") - # kivy if LINUX and packages["kivy"] and packages["gtk"]: - if "--kivy" in sys.argv: - # When --kivy flag passed run only Kivy example + # When --kivy flag passed run only Kivy example + if kivy_flag: examples = list() passed = list() examples.append("{linux_dir}/binaries_64bit/kivy_.py" .format(linux_dir=LINUX_DIR)) + # When --hello-world flag is passed run only hello_world.py example + if hello_world_flag: + examples = list() + passed = list() + examples.append("hello_world.py") + # Run all for example in examples: print("[run_examples.py] Running '{example}'..." From b93cebfbcfa750f4047d6c243e90517e53a4708c Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 20 Mar 2017 09:30:28 +0100 Subject: [PATCH 181/557] Fix 'BadWindow' x11 errors in wxpython.py example (#334) --- examples/wxpython.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/wxpython.py b/examples/wxpython.py index 144bab7ed..bc5ccf495 100644 --- a/examples/wxpython.py +++ b/examples/wxpython.py @@ -64,6 +64,12 @@ def __init__(self): title='wxPython example', size=(WIDTH, HEIGHT)) self.browser = None + # Must ignore X11 errors like 'BadWindow' and others by + # installing X11 error handlers. This must be done after + # wx was intialized. + if LINUX: + WindowUtils.InstallX11ErrorHandlers() + global g_count_windows g_count_windows += 1 From eb732d977c7addcfb692f5b099d72c0d4c71810b Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 20 Mar 2017 10:49:58 +0100 Subject: [PATCH 182/557] Rename setup installer's filename and other cleanup... Delete old tools on Linux. New tools are in tools/ root dir. Delete deprecated examples on Linux and Windows. --- docs/Build-instructions.md | 12 +- src/.gitignore | 42 - .../binaries_64bit/deprecated/example.html | 58 -- src/linux/binaries_64bit/deprecated/prism.css | 130 --- src/linux/binaries_64bit/deprecated/prism.js | 5 - src/linux/binaries_64bit/deprecated/pygtk_.py | 220 ----- src/linux/binaries_64bit/deprecated/pyqt.py | 238 ----- .../deprecated/wxpython-response.py | 452 --------- .../binaries_64bit/deprecated/wxpython.html | 707 -------------- .../binaries_64bit/deprecated/wxpython.py | 769 --------------- src/linux/compile.py | 325 ------- .../.gitignore | 0 .../debian.postinst | 0 .../deps.txt | 0 .../find-deps.py | 0 .../make-deb.py | 0 .../stdeb.cfg.template | 0 src/linux/installer/README.txt | 20 - src/linux/installer/__init__.py.template | 40 - src/linux/installer/make-setup.py | 222 ----- src/linux/installer/setup.cfg.template | 2 - src/linux/installer/setup.py.template | 104 -- src/linux/setup/.gitignore | 7 - src/linux/setup/cefpython.h | 103 -- src/linux/setup/fix_pyx_files.py | 131 --- src/linux/setup/setup.py | 156 --- src/windows/deprecated_32bit/LICENSE.txt | 39 - src/windows/deprecated_32bit/README.txt | 119 --- src/windows/deprecated_32bit/cefwindow.py | 205 ---- src/windows/deprecated_32bit/example.html | 58 -- src/windows/deprecated_32bit/icon.ico | Bin 198275 -> 0 bytes src/windows/deprecated_32bit/prism.css | 130 --- src/windows/deprecated_32bit/prism.js | 5 - src/windows/deprecated_32bit/pygtk_.py | 196 ---- src/windows/deprecated_32bit/pyqt.py | 190 ---- src/windows/deprecated_32bit/pyside.py | 188 ---- src/windows/deprecated_32bit/pywin32.py | 151 --- src/windows/deprecated_32bit/smoke.css | 110 --- src/windows/deprecated_32bit/smoke.min.js | 1 - src/windows/deprecated_32bit/wxpython.html | 743 -------------- src/windows/deprecated_32bit/wxpython.py | 906 ------------------ tools/common.py | 2 +- 42 files changed, 7 insertions(+), 6779 deletions(-) delete mode 100644 src/linux/binaries_64bit/deprecated/example.html delete mode 100644 src/linux/binaries_64bit/deprecated/prism.css delete mode 100644 src/linux/binaries_64bit/deprecated/prism.js delete mode 100644 src/linux/binaries_64bit/deprecated/pygtk_.py delete mode 100644 src/linux/binaries_64bit/deprecated/pyqt.py delete mode 100644 src/linux/binaries_64bit/deprecated/wxpython-response.py delete mode 100644 src/linux/binaries_64bit/deprecated/wxpython.html delete mode 100644 src/linux/binaries_64bit/deprecated/wxpython.py delete mode 100644 src/linux/compile.py rename src/linux/{installer => deb_pkg_deprecated}/.gitignore (100%) rename src/linux/{installer => deb_pkg_deprecated}/debian.postinst (100%) rename src/linux/{installer => deb_pkg_deprecated}/deps.txt (100%) rename src/linux/{installer => deb_pkg_deprecated}/find-deps.py (100%) rename src/linux/{installer => deb_pkg_deprecated}/make-deb.py (100%) rename src/linux/{installer => deb_pkg_deprecated}/stdeb.cfg.template (100%) delete mode 100644 src/linux/installer/README.txt delete mode 100644 src/linux/installer/__init__.py.template delete mode 100644 src/linux/installer/make-setup.py delete mode 100644 src/linux/installer/setup.cfg.template delete mode 100644 src/linux/installer/setup.py.template delete mode 100644 src/linux/setup/.gitignore delete mode 100644 src/linux/setup/cefpython.h delete mode 100644 src/linux/setup/fix_pyx_files.py delete mode 100644 src/linux/setup/setup.py delete mode 100644 src/windows/deprecated_32bit/LICENSE.txt delete mode 100644 src/windows/deprecated_32bit/README.txt delete mode 100644 src/windows/deprecated_32bit/cefwindow.py delete mode 100644 src/windows/deprecated_32bit/example.html delete mode 100644 src/windows/deprecated_32bit/icon.ico delete mode 100644 src/windows/deprecated_32bit/prism.css delete mode 100644 src/windows/deprecated_32bit/prism.js delete mode 100644 src/windows/deprecated_32bit/pygtk_.py delete mode 100644 src/windows/deprecated_32bit/pyqt.py delete mode 100644 src/windows/deprecated_32bit/pyside.py delete mode 100644 src/windows/deprecated_32bit/pywin32.py delete mode 100644 src/windows/deprecated_32bit/smoke.css delete mode 100644 src/windows/deprecated_32bit/smoke.min.js delete mode 100644 src/windows/deprecated_32bit/wxpython.html delete mode 100644 src/windows/deprecated_32bit/wxpython.py diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index f9009799e..3281810eb 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -404,15 +404,15 @@ cd cefpython/build/ python ../tools/make_installer.py xx.x ``` -To create a wheel package from that installer package type: +To create a wheel package type: ``` -cd *-setup/ -python setup.py bdist_wheel -cd dist/ -ls *.whl +cd cefpython/build/ +python ../tools/make_installer.py xx.xx --wheel --universal +cd cefpython3_*/dist/ +ls ``` -Optional flags for the setup.py script above: +Additional flags when using --wheel flag: * `--python-tag cp27` to generate Python 2.7 only package * `--universal` to build package for multiple Python versions (in such case you must first build multiple cefpython modules diff --git a/src/.gitignore b/src/.gitignore index 7bc2904b7..c794c5a00 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,46 +1,4 @@ -/cef1/windows/setup/build/ -*.pyc - # If you want to ignore an already commited directory run: # git rm --cached -r .idea -/.idea/ -debug.log -error.log -console.log - -# WingIDE project files -/wingide.wpr -/wingide.wpu - -*.ncb -*.suo -*.user -*.aps -*.sdf -*.sln -Debug*/ -Release*/ -*.pdb - -ctags - -/windows/installer/Output/ - -# Inno setup files generated from a template -*.generated - -cython_debug/ - -cefpython_py27.pyd -cefpython_py32.pyd -cefpython_py27.so -cefpython_py32.so - compile_time_constants.pxi - -debug_32bit/ -debug_64bit/ - -libcef_debug/ -libcef_release/ diff --git a/src/linux/binaries_64bit/deprecated/example.html b/src/linux/binaries_64bit/deprecated/example.html deleted file mode 100644 index 891bc5e8c..000000000 --- a/src/linux/binaries_64bit/deprecated/example.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - - CEF Python 3 example (utf-8: ąś) - - - - - - -

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

      - - - -

      Google Search

      -https://www.google.com/ - - - -

      User agent

      - - - - -

      Popup

      - - window.open('example.html') - - - -

      HTML5 video and accelerated content

      - -HTML 5 video
      - -Accelerated canvas
      - -Accelerated layers
      - - - -

      Advanced example

      - -See the wxpython.py script for an advanced usage of CEF Python 3 -features - including javascript bindings, js and python callbacks, -client handlers and others. - - -



      -



      -



      -



      - - - diff --git a/src/linux/binaries_64bit/deprecated/prism.css b/src/linux/binaries_64bit/deprecated/prism.css deleted file mode 100644 index f94cca7c0..000000000 --- a/src/linux/binaries_64bit/deprecated/prism.css +++ /dev/null @@ -1,130 +0,0 @@ -/* http://prismjs.com/download.html?themes=prism&languages=clike+javascript+python */ -/** - * prism.js default theme for JavaScript, CSS and HTML - * Based on dabblet (http://dabblet.com) - * @author Lea Verou - */ - -code[class*="language-"], -pre[class*="language-"] { - color: black; - text-shadow: 0 1px white; - font-family: Consolas, Monaco, 'Andale Mono', monospace; - direction: ltr; - text-align: left; - white-space: pre; - word-spacing: normal; - word-break: normal; - - - -moz-tab-size: 4; - -o-tab-size: 4; - tab-size: 4; - - -webkit-hyphens: none; - -moz-hyphens: none; - -ms-hyphens: none; - hyphens: none; -} - -pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, -code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { - text-shadow: none; - background: #b3d4fc; -} - -pre[class*="language-"]::selection, pre[class*="language-"] ::selection, -code[class*="language-"]::selection, code[class*="language-"] ::selection { - text-shadow: none; - background: #b3d4fc; -} - -@media print { - code[class*="language-"], - pre[class*="language-"] { - text-shadow: none; - } -} - -/* Code blocks */ -pre[class*="language-"] { - padding: 1em; - margin: .5em 0; - overflow: auto; -} - -:not(pre) > code[class*="language-"], -pre[class*="language-"] { - background: #f5f2f0; -} - -/* Inline code */ -:not(pre) > code[class*="language-"] { - padding: .1em; - border-radius: .3em; -} - -.token.comment, -.token.prolog, -.token.doctype, -.token.cdata { - color: slategray; -} - -.token.punctuation { - color: #999; -} - -.namespace { - opacity: .7; -} - -.token.property, -.token.tag, -.token.boolean, -.token.number, -.token.constant, -.token.symbol { - color: #905; -} - -.token.selector, -.token.attr-name, -.token.string, -.token.builtin { - color: #690; -} - -.token.operator, -.token.entity, -.token.url, -.language-css .token.string, -.style .token.string, -.token.variable { - color: #a67f59; - background: hsla(0,0%,100%,.5); -} - -.token.atrule, -.token.attr-value, -.token.keyword { - color: #07a; -} - -.token.function { - color: #DD4A68; -} - -.token.regex, -.token.important { - color: #e90; -} - -.token.important { - font-weight: bold; -} - -.token.entity { - cursor: help; -} - diff --git a/src/linux/binaries_64bit/deprecated/prism.js b/src/linux/binaries_64bit/deprecated/prism.js deleted file mode 100644 index ebaa4b428..000000000 --- a/src/linux/binaries_64bit/deprecated/prism.js +++ /dev/null @@ -1,5 +0,0 @@ -/* http://prismjs.com/download.html?themes=prism&languages=clike+javascript+python */ -self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{};var Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content)):"Array"===t.util.type(e)?e.map(t.util.encode):e.replace(/&/g,"&").replace(/e.length)break e;if(!(f instanceof r)){l.lastIndex=0;var h=l.exec(f);if(h){c&&(g=h[1].length);var d=h.index-1+g,h=h[0].slice(g),p=h.length,m=d+p,v=f.slice(0,d+1),y=f.slice(m+1),k=[u,1];v&&k.push(v);var b=new r(o,s?t.tokenize(h,s):h);k.push(b),y&&k.push(y),Array.prototype.splice.apply(a,k)}}}}return a},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[],r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(r&&r.length)for(var a,i=0;a=r[i++];)a(n)}}},n=t.Token=function(e,t){this.type=e,this.content=t};if(n.stringify=function(e,r,a){if("string"==typeof e)return e;if("[object Array]"==Object.prototype.toString.call(e))return e.map(function(t){return n.stringify(t,r,e)}).join("");var i={type:e.type,content:n.stringify(e.content,r,a),tag:"span",classes:["token",e.type],attributes:{},language:r,parent:a};"comment"==i.type&&(i.attributes.spellcheck="true"),t.hooks.run("wrap",i);var o="";for(var l in i.attributes)o+=l+'="'+(i.attributes[l]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+o+">"+i.content+""},!self.document)return self.addEventListener?(self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,a=n.code;self.postMessage(JSON.stringify(t.tokenize(a,t.languages[r]))),self.close()},!1),self.Prism):self.Prism;var r=document.getElementsByTagName("script");return r=r[r.length-1],r&&(t.filename=r.src,document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)),self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism);; -Prism.languages.clike={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,lookbehind:!0},string:/("|')(\\?.)*?\1/g,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/gi,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g,"boolean":/\b(true|false)\b/g,"function":{pattern:/[a-z0-9_]+\(/gi,inside:{punctuation:/\(/}},number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,operator:/[-+]{1,2}|!|<=?|>=?|={1,3}|&{1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};; -Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|function|get|if|implements|import|in|instanceof|interface|let|new|null|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,lookbehind:!0}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/[\w\W]*?<\/script>/gi,inside:{tag:{pattern:/|<\/script>/gi,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}});; -Prism.languages.python={comment:{pattern:/(^|[^\\])#.*?(\r?\n|$)/g,lookbehind:!0},string:/"""[\s\S]+?"""|("|')(\\?.)*?\1/g,keyword:/\b(as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/g,"boolean":/\b(True|False)\b/g,number:/\b-?(0x)?\d*\.?[\da-f]+\b/g,operator:/[-+]{1,2}|=?<|=?>|!|={1,2}|(&){1,2}|(&){1,2}|\|?\||\?|\*|\/|~|\^|%|\b(or|and|not)\b/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};; diff --git a/src/linux/binaries_64bit/deprecated/pygtk_.py b/src/linux/binaries_64bit/deprecated/pygtk_.py deleted file mode 100644 index 14ec01e08..000000000 --- a/src/linux/binaries_64bit/deprecated/pygtk_.py +++ /dev/null @@ -1,220 +0,0 @@ -# An example of embedding the CEF browser in PyGTK on Linux. -# Tested with GTK "2.24.10". - -# The official CEF Python binaries come with tcmalloc hook -# disabled. But if you've built custom binaries and kept tcmalloc -# hook enabled, then be aware that in such case it is required -# for the cefpython module to be the very first import in -# python scripts. See Issue 73 in the CEF Python Issue Tracker -# for more details. - -import ctypes, os, sys -libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.so') -if os.path.exists(libcef_so): - # Import local module - ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import from package - from cefpython3 import cefpython - -import pygtk -pygtk.require('2.0') -import gtk -import gobject -import re - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("[pygtk_.py]: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class PyGTKExample: - mainWindow = None - container = None - browser = None - exiting = None - searchEntry = None - vbox = None - menubar = None - menubar_height = None - - def __init__(self): - self.mainWindow = gtk.Window(gtk.WINDOW_TOPLEVEL) - self.mainWindow.connect('focus-in-event', self.OnFocusIn) - self.mainWindow.connect('configure-event', self.OnConfigure) - self.mainWindow.connect('destroy', self.OnExit) - self.mainWindow.set_size_request(width=800, height=600) - self.mainWindow.set_title('PyGTK CEF example') - self.mainWindow.realize() - - self.vbox = gtk.VBox(False, 0) - self.vbox.connect('size-allocate', self.OnVBoxSize) - self.menubar = self.CreateMenu() - self.menubar.connect('size-allocate', self.OnMenubarSize) - self.vbox.pack_start(self.menubar, False, False, 0) - self.mainWindow.add(self.vbox) - - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(self.mainWindow.window.xid, [0,0,0,0]) - # Linux requires adding "file://" for local files, - # otherwise /home/some will be replaced as http://home/some - self.browser = cefpython.CreateBrowserSync( - windowInfo, - browserSettings={}, - navigateUrl="file://"+GetApplicationPath("example.html")) - - self.vbox.show() - self.mainWindow.show() - self.vbox.get_window().focus() - self.mainWindow.get_window().focus() - gobject.timeout_add(10, self.OnTimer) - - def CreateMenu(self): - file = gtk.MenuItem('File') - file.show() - filemenu = gtk.Menu() - item = gtk.MenuItem('Open') - filemenu.append(item) - item.show() - item = gtk.MenuItem('Exit') - filemenu.append(item) - item.show() - file.set_submenu(filemenu) - - about = gtk.MenuItem('About') - about.show() - aboutmenu = gtk.Menu() - item = gtk.MenuItem('CEF Python') - aboutmenu.append(item) - item.show() - about.set_submenu(aboutmenu) - - menubar = gtk.MenuBar() - menubar.append(file) - menubar.append(about) - menubar.show() - - return menubar - - # count = 0 - def OnTimer(self): - if self.exiting: - return False - # self.count += 1 - # print(self.count) - cefpython.MessageLoopWork() - return True - - def OnFocusIn(self, widget, data): - if self.browser: - self.browser.SetFocus(True) - return True - return False - - def OnConfigure(self, widget, data): - if self.browser: - self.browser.NotifyMoveOrResizeStarted() - return False - - def OnVBoxSize(self, widget, data): - if self.browser: - x = data.x - y = data.y + self.menubar_height - width = data.width - height = data.height - self.menubar_height - self.browser.SetBounds(x, y, width, height) - - def OnMenubarSize(self, widget, data): - self.menubar_height = data.height - - def OnExit(self, widget, data=None): - self.exiting = True - gtk.main_quit() - -if __name__ == '__main__': - version = '.'.join(map(str, list(gtk.gtk_version))) - print('[pygtk_.py] GTK version: %s' % version) - - # Intercept python exceptions. Exit app immediately when exception - # happens on any of the threads. - sys.excepthook = ExceptHook - - # Application settings - settings = { - "debug": True, # cefpython debug messages in console and in log_file - "log_severity": cefpython.LOGSEVERITY_INFO, # LOGSEVERITY_VERBOSE - "log_file": GetApplicationPath("debug.log"), # Set to "" to disable - # This directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory(), - "browser_subprocess_path": "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess"), - } - - cefpython.Initialize(settings) - cefpython.WindowUtils.InstallX11ErrorHandlers() - - gobject.threads_init() # Timer for the message loop - PyGTKExample() - gtk.main() - - cefpython.Shutdown() diff --git a/src/linux/binaries_64bit/deprecated/pyqt.py b/src/linux/binaries_64bit/deprecated/pyqt.py deleted file mode 100644 index c43805754..000000000 --- a/src/linux/binaries_64bit/deprecated/pyqt.py +++ /dev/null @@ -1,238 +0,0 @@ -# An example of embedding CEF browser in a PyQt4 application. -# Tested with PyQt "4.9.1". -# Command for installing PyQt4: "sudo apt-get install python-qt4". - -# The official CEF Python binaries come with tcmalloc hook -# disabled. But if you've built custom binaries and kept tcmalloc -# hook enabled, then be aware that in such case it is required -# for the cefpython module to be the very first import in -# python scripts. See Issue 73 in the CEF Python Issue Tracker -# for more details. - -import ctypes, os, sys -libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)),\ - 'libcef.so') -if os.path.exists(libcef_so): - # Import local module - ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import from package - from cefpython3 import cefpython - -from PyQt4 import QtGui -from PyQt4 import QtCore - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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" (os._exit()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("[pyqt.py] WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainWindow(QtGui.QMainWindow): - mainFrame = None - - def __init__(self): - super(MainWindow, self).__init__(None) - self.createMenu() - self.mainFrame = MainFrame(self) - self.setCentralWidget(self.mainFrame) - self.resize(1024, 768) - self.setWindowTitle('PyQT CEF 3 example') - self.setFocusPolicy(QtCore.Qt.StrongFocus) - - def createMenu(self): - menubar = self.menuBar() - filemenu = menubar.addMenu("&File") - filemenu.addAction(QtGui.QAction("Open", self)) - filemenu.addAction(QtGui.QAction("Exit", self)) - aboutmenu = menubar.addMenu("&About") - - def focusInEvent(self, event): - # cefpython.WindowUtils.OnSetFocus( - # int(self.centralWidget().winId()), 0, 0, 0) - pass - - def closeEvent(self, event): - self.mainFrame.browser.CloseBrowser() - -class MainFrame(QtGui.QX11EmbedContainer): - browser = None - plug = None - - def __init__(self, parent=None): - super(MainFrame, self).__init__(parent) - - # QX11EmbedContainer provides an X11 window. The CEF - # browser can be embedded only by providing a GtkWidget - # pointer. So we're embedding a GtkPlug inside the X11 - # window. In latest CEF trunk it is possible to embed - # the CEF browser by providing X11 window id. So it will - # be possible to remove the GTK dependency from CEF - # Python in the future. - gtkPlugPtr = cefpython.WindowUtils.gtk_plug_new(\ - int(self.winId())) - print("[pyqt.py] MainFrame: GDK Native Window id: "+str(self.winId())) - print("[pyqt.py] MainFrame: GTK Plug ptr: "+str(gtkPlugPtr)) - - """ - Embedding GtkPlug is also possible with the pygtk module. - --------------------------------------------------------- - self.plug = gtk.Plug(self.winId()) - import re - m = re.search("GtkPlug at 0x(\w+)", str(self.plug)) - hexId = m.group(1) - gtkPlugPtr = int(hexId, 16) - ... - plug.show() - self.show() - --------------------------------------------------------- - """ - - windowInfo = cefpython.WindowInfo() - # Need to pass to CEF the GtkWidget* pointer - windowInfo.SetAsChild(gtkPlugPtr) - # Linux requires adding "file://" for local files, - # otherwise /home/some will be replaced as http://home/some - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings={}, - navigateUrl="file://"+GetApplicationPath("example.html")) - - cefpython.WindowUtils.gtk_widget_show(gtkPlugPtr) - self.show() - - def moveEvent(self, event): - # cefpython.WindowUtils.OnSize(int(self.winId()), 0, 0, 0) - pass - - def resizeEvent(self, event): - # cefpython.WindowUtils.OnSize(int(self.winId()), 0, 0, 0) - pass - -class CefApplication(QtGui.QApplication): - timer = None - - def __init__(self, args): - super(CefApplication, self).__init__(args) - self.createTimer() - - def createTimer(self): - self.timer = QtCore.QTimer() - self.timer.timeout.connect(self.onTimer) - self.timer.start(10) - - def onTimer(self): - # The proper way of doing message loop should be: - # 1. In createTimer() call self.timer.start(0) - # 2. In onTimer() call MessageLoopWork() only when - # QtGui.QApplication.instance()->hasPendingEvents() - # returns False. - # But there is a bug in Qt, hasPendingEvents() returns - # always true. - # (The behavior described above was tested on Windows - # with pyqt 4.8, maybe this is not true anymore, - # test it TODO) - cefpython.MessageLoopWork() - - def stopTimer(self): - # Stop the timer after Qt message loop ended, calls to - # MessageLoopWork() should not happen anymore. - self.timer.stop() - -if __name__ == '__main__': - print("[pyqt.py] PyQt version: %s" % QtCore.PYQT_VERSION_STR) - print("[pyqt.py] QtCore version: %s" % QtCore.qVersion()) - - # Intercept python exceptions. Exit app immediately when exception - # happens on any of the threads. - sys.excepthook = ExceptHook - - # Application settings - settings = { - "debug": True, # cefpython debug messages in console and in log_file - "log_severity": cefpython.LOGSEVERITY_INFO, # LOGSEVERITY_VERBOSE - "log_file": GetApplicationPath("debug.log"), # Set to "" to disable. - # This directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory(), - "browser_subprocess_path": "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess"), - } - - # Command line switches set programmatically - switches = { - # "proxy-server": "socks5://127.0.0.1:8888", - # "enable-media-stream": "", - # "--invalid-switch": "" -> Invalid switch name - } - - cefpython.Initialize(settings, switches) - - app = CefApplication(sys.argv) - mainWindow = MainWindow() - mainWindow.show() - app.exec_() - app.stopTimer() - - # Need to destroy QApplication(), otherwise Shutdown() fails. - # Unset main window also just to be safe. - del mainWindow - del app - - cefpython.Shutdown() diff --git a/src/linux/binaries_64bit/deprecated/wxpython-response.py b/src/linux/binaries_64bit/deprecated/wxpython-response.py deleted file mode 100644 index 8992e14a2..000000000 --- a/src/linux/binaries_64bit/deprecated/wxpython-response.py +++ /dev/null @@ -1,452 +0,0 @@ -# An example of embedding CEF browser in wxPython on Linux. -# Tested with wxPython 2.8.12.1 (gtk2-unicode). -# To install wxPython type "sudo apt-get install python-wxtools". - -# This example implements a custom "_OnResourceResponse" callback -# that emulates reading response by utilizing Resourcehandler -# and WebRequest. - -FIX_ENCODING_BUG = True -BROWSER_DEFAULT_ENCODING = "utf-8" - -# The official CEF Python binaries come with tcmalloc hook -# disabled. But if you've built custom binaries and kept tcmalloc -# hook enabled, then be aware that in such case it is required -# for the cefpython module to be the very first import in -# python scripts. See Issue 73 in the CEF Python Issue Tracker -# for more details. - -import ctypes, os, sys -libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'libcef.so') -if os.path.exists(libcef_so): - # Import local module - ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import from package - from cefpython3 import cefpython - -import wx -import time -import re -import uuid -import platform -import shutil - -class ClientHandler: - - # RequestHandler.GetResourceHandler() - def GetResourceHandler(self, browser, frame, request): - # Called on the IO thread before a resource is loaded. - # To allow the resource to load normally return None. - print("GetResourceHandler(): url = %s" % request.GetUrl()) - resHandler = ResourceHandler() - resHandler._clientHandler = self - resHandler._browser = browser - resHandler._frame = frame - resHandler._request = request - self._AddStrongReference(resHandler) - return resHandler - - def _OnResourceResponse(self, browser, frame, request, requestStatus, - requestError, response, data): - # This callback is emulated through ResourceHandler - # and WebRequest. Real "OnResourceResponse" is not yet - # available in CEF 3 (as of CEF revision 1450). See - # issue 515 in the CEF Issue Tracker: - # https://code.google.com/p/chromiumembedded/issues/detail?id=515 - # ---- - # requestStatus => cefpython.WebRequest.Status - # {"Unknown", "Success", "Pending", "Canceled", "Failed"} - # For "file://" requests the status will be "Unknown". - # requestError => see the NetworkError wiki page - # response.GetStatus() => http status code - print("_OnResourceResponse()") - print("data length = %s" % len(data)) - # Return the new data - you can modify it. - if request.GetUrl().startswith("file://") \ - and request.GetUrl().endswith("example.html"): - data = "This text was inserted through " \ - + "_OnResourceResponse()
      " + data - # Non-english characters are not displaying correctly. - # This is a bug in CEF. A quick fix is to get the charset - # from response headers and insert into - # the html page. - # Bug reported on the CEF C++ Forum: - # http://www.magpcss.org/ceforum/viewtopic.php?p=18401#p18401 - if FIX_ENCODING_BUG: - contentType = response.GetHeader("Content-Type") - if contentType: - contentType = contentType.lower() - isHtml = False - headerCharset = "" - if contentType and "text/html" in contentType: - isHtml = True - if contentType and "charset" in contentType: - match = re.search(r"charset\s*=\s*([^\s]+)", contentType) - if match and match.group(1): - headerCharset = match.group(1).lower() - if isHtml and headerCharset \ - and headerCharset != BROWSER_DEFAULT_ENCODING.lower(): - if not re.search(r"]+charset\s*=", data, \ - re.IGNORECASE): - # Only apply the fix if there is no - # available on a page. - data = ("" % headerCharset) + data - return data - - # A strong reference to ResourceHandler must be kept - # during the request. Some helper functions for that. - # 1. Add reference in GetResourceHandler() - # 2. Release reference in ResourceHandler.ReadResponse() - # after request is completed. - - _resourceHandlers = {} - _resourceHandlerMaxId = 0 - - def _AddStrongReference(self, resHandler): - self._resourceHandlerMaxId += 1 - resHandler._resourceHandlerId = self._resourceHandlerMaxId - self._resourceHandlers[resHandler._resourceHandlerId] = resHandler - - def _ReleaseStrongReference(self, resHandler): - if resHandler._resourceHandlerId in self._resourceHandlers: - del self._resourceHandlers[resHandler._resourceHandlerId] - else: - print("_ReleaseStrongReference() FAILED: resource handler " \ - "not found, id = %s" % (resHandler._resourceHandlerId)) - -class ResourceHandler: - - # The methods of this class will always be called - # on the IO thread. - - _resourceHandlerId = None - _clientHandler = None - _browser = None - _frame = None - _request = None - _responseHeadersReadyCallback = None - _webRequest = None - _webRequestClient = None - _offsetRead = 0 - - def ProcessRequest(self, request, callback): - print("ProcessRequest()") - # 1. Start the request using WebRequest - # 2. Return True to handle the request - # 3. Once response headers are ready call - # callback.Continue() - self._responseHeadersReadyCallback = callback - self._webRequestClient = WebRequestClient() - self._webRequestClient._resourceHandler = self - # Need to set AllowCacheCredentials and AllowCookies for - # the cookies to work during POST requests (Issue 127). - # To skip cache set the SkipCache request flag. - request.SetFlags(cefpython.Request.Flags["AllowCachedCredentials"]\ - | cefpython.Request.Flags["AllowCookies"]) - # A strong reference to the WebRequest object must kept. - self._webRequest = cefpython.WebRequest.Create( - request, self._webRequestClient) - return True - - def GetResponseHeaders(self, response, responseLengthOut, redirectUrlOut): - print("GetResponseHeaders()") - # 1. If the response length is not known set - # responseLengthOut[0] to -1 and ReadResponse() - # will be called until it returns False. - # 2. If the response length is known set - # responseLengthOut[0] to a positive value - # and ReadResponse() will be called until it - # returns False or the specified number of bytes - # have been read. - # 3. Use the |response| object to set the mime type, - # http status code and other optional header values. - # 4. To redirect the request to a new URL set - # redirectUrlOut[0] to the new url. - assert self._webRequestClient._response, "Response object empty" - wrcResponse = self._webRequestClient._response - response.SetStatus(wrcResponse.GetStatus()) - response.SetStatusText(wrcResponse.GetStatusText()) - response.SetMimeType(wrcResponse.GetMimeType()) - if wrcResponse.GetHeaderMultimap(): - response.SetHeaderMultimap(wrcResponse.GetHeaderMultimap()) - print("headers: ") - print(wrcResponse.GetHeaderMap()) - responseLengthOut[0] = self._webRequestClient._dataLength - if not responseLengthOut[0]: - # Probably a cached page? Or a redirect? - pass - - def ReadResponse(self, dataOut, bytesToRead, bytesReadOut, callback): - # print("ReadResponse()") - # 1. If data is available immediately copy up to - # bytesToRead bytes into dataOut[0], set - # bytesReadOut[0] to the number of bytes copied, - # and return true. - # 2. To read the data at a later time set - # bytesReadOut[0] to 0, return true and call - # callback.Continue() when the data is available. - # 3. To indicate response completion return false. - if self._offsetRead < self._webRequestClient._dataLength: - dataChunk = self._webRequestClient._data[\ - self._offsetRead:(self._offsetRead + bytesToRead)] - self._offsetRead += len(dataChunk) - dataOut[0] = dataChunk - bytesReadOut[0] = len(dataChunk) - return True - self._clientHandler._ReleaseStrongReference(self) - print("no more data, return False") - return False - - def CanGetCookie(self, cookie): - # Return true if the specified cookie can be sent - # with the request or false otherwise. If false - # is returned for any cookie then no cookies will - # be sent with the request. - return True - - def CanSetCookie(self, cookie): - # Return true if the specified cookie returned - # with the response can be set or false otherwise. - return True - - def Cancel(self): - # Request processing has been canceled. - pass - -class WebRequestClient: - - _resourceHandler = None - _data = "" - _dataLength = -1 - _response = None - - def OnUploadProgress(self, webRequest, current, total): - pass - - def OnDownloadProgress(self, webRequest, current, total): - pass - - def OnDownloadData(self, webRequest, data): - # print("OnDownloadData()") - self._data += data - - def OnRequestComplete(self, webRequest): - print("OnRequestComplete()") - # cefpython.WebRequest.Status = {"Unknown", "Success", - # "Pending", "Canceled", "Failed"} - statusText = "Unknown" - if webRequest.GetRequestStatus() in cefpython.WebRequest.Status: - statusText = cefpython.WebRequest.Status[\ - webRequest.GetRequestStatus()] - print("status = %s" % statusText) - print("error code = %s" % webRequest.GetRequestError()) - # Emulate OnResourceResponse() in ClientHandler: - self._response = webRequest.GetResponse() - # Are webRequest.GetRequest() and - # self._resourceHandler._request the same? What if - # there was a redirect, what will GetUrl() return - # for both of them? - self._data = self._resourceHandler._clientHandler._OnResourceResponse( - self._resourceHandler._browser, - self._resourceHandler._frame, - webRequest.GetRequest(), - webRequest.GetRequestStatus(), - webRequest.GetRequestError(), - webRequest.GetResponse(), - self._data) - self._dataLength = len(self._data) - # ResourceHandler.GetResponseHeaders() will get called - # after _responseHeadersReadyCallback.Continue() is called. - self._resourceHandler._responseHeadersReadyCallback.Continue() - -# Which method to use for message loop processing. -# EVT_IDLE - wx application has priority (default) -# EVT_TIMER - cef browser has priority -# It seems that Flash content behaves better when using a timer. -# IMPORTANT! On Linux EVT_IDLE does not work, the events seems to -# be propagated only when you move your mouse, which is not the -# expected behavior, it is recommended to use EVT_TIMER on Linux, -# so set this value to False. -USE_EVT_IDLE = False - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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" (os._exit()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("cefpython: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainFrame(wx.Frame): - browser = None - mainPanel = None - - def __init__(self): - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, - title='wxPython CEF 3 example', size=(800,600)) - self.CreateMenu() - - # Cannot attach browser to the main frame as this will cause - # the menu not to work. - # -- - # You also have to set the wx.WANTS_CHARS style for - # all parent panels/controls, if it's deeply embedded. - self.mainPanel = wx.Panel(self, style=wx.WANTS_CHARS) - - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(self.mainPanel.GetGtkWidget()) - # Linux requires adding "file://" for local files, - # otherwise /home/some will be replaced as http://home/some - self.browser = cefpython.CreateBrowserSync( - windowInfo, - # If there are problems with Flash you can disable it here, - # by disabling all plugins. - browserSettings={"plugins_disabled": False, - "default_encoding": BROWSER_DEFAULT_ENCODING}, - navigateUrl="file://"+GetApplicationPath("example.html")) - - clientHandler = ClientHandler() - self.browser.SetClientHandler(clientHandler) - - self.Bind(wx.EVT_CLOSE, self.OnClose) - if USE_EVT_IDLE: - # Bind EVT_IDLE only for the main application frame. - self.Bind(wx.EVT_IDLE, self.OnIdle) - - def CreateMenu(self): - filemenu = wx.Menu() - filemenu.Append(1, "Open") - exit = filemenu.Append(2, "Exit") - self.Bind(wx.EVT_MENU, self.OnClose, exit) - aboutmenu = wx.Menu() - aboutmenu.Append(1, "CEF Python") - menubar = wx.MenuBar() - menubar.Append(filemenu,"&File") - menubar.Append(aboutmenu, "&About") - self.SetMenuBar(menubar) - - def OnClose(self, event): - # In wx.chromectrl calling browser.CloseBrowser() and/or - # self.Destroy() in OnClose is causing crashes when embedding - # multiple browser tabs. The solution is to call only - # browser.ParentWindowWillClose. Behavior of this example - # seems different as it extends wx.Frame, while ChromeWindow - # from chromectrl extends wx.Window. Calling CloseBrowser - # and Destroy does not cause crashes, but is not recommended. - # Call ParentWindowWillClose and event.Skip() instead. See - # also Issue 107. - self.browser.ParentWindowWillClose() - event.Skip() - - def OnIdle(self, event): - cefpython.MessageLoopWork() - -class MyApp(wx.App): - timer = None - timerID = 1 - timerCount = 0 - - def OnInit(self): - if not USE_EVT_IDLE: - self.CreateTimer() - frame = MainFrame() - self.SetTopWindow(frame) - frame.Show() - return True - - def CreateTimer(self): - # See "Making a render loop": - # http://wiki.wxwidgets.org/Making_a_render_loop - # Another approach is to use EVT_IDLE in MainFrame, - # see which one fits you better. - self.timer = wx.Timer(self, self.timerID) - self.timer.Start(10) # 10ms - wx.EVT_TIMER(self, self.timerID, self.OnTimer) - - def OnTimer(self, event): - self.timerCount += 1 - # print("wxpython.py: OnTimer() %d" % self.timerCount) - cefpython.MessageLoopWork() - - def OnExit(self): - # When app.MainLoop() returns, MessageLoopWork() should - # not be called anymore. - if not USE_EVT_IDLE: - self.timer.Stop() - -if __name__ == '__main__': - sys.excepthook = ExceptHook - settings = { - "debug": False, # cefpython debug messages in console and in log_file - "log_severity": cefpython.LOGSEVERITY_INFO, # LOGSEVERITY_VERBOSE - "log_file": GetApplicationPath("debug.log"), # Set to "" to disable. - # This directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory(), - "browser_subprocess_path": "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess") - } - # print("browser_subprocess_path="+settings["browser_subprocess_path"]) - cefpython.Initialize(settings) - print('wx.version=%s' % wx.version()) - app = MyApp(False) - app.MainLoop() - # Let wx.App destructor do the cleanup before calling cefpython.Shutdown(). - del app - cefpython.Shutdown() diff --git a/src/linux/binaries_64bit/deprecated/wxpython.html b/src/linux/binaries_64bit/deprecated/wxpython.html deleted file mode 100644 index caf056ff9..000000000 --- a/src/linux/binaries_64bit/deprecated/wxpython.html +++ /dev/null @@ -1,707 +0,0 @@ - - - - - wxPython CEF 3 example (utf-8: ąś) - - - - - - -Use the mouse context menu to go Back/Forward in history navigation. - -

      Table of contents

      -
        -
      1. Google search
      2. -
      3. User agent
      4. -
      5. Popups
      6. -
      7. HTML 5 video
      8. -
      9. Developer Tools
      10. -
      11. Downloads
      12. -
      13. HTML controls
      14. -
      15. Browser object
      16. -
      17. Frame object
      18. -
      19. Javascript bindings
      20. -
      21. Javascript callbacks
      22. -
      23. Python callbacks
      24. -
      25. Display handler
      26. -
      27. Keyboard handler
      28. -
      29. Request handler
      30. -
      31. Cookie tests
      32. -
      33. Load handler
      34. -
      35. Javascript Dialog handler
      36. -
      37. Other tests
      38. -
      - - - - - - -

      Google search

      - -http://www.google.com/ - - - - - - - -

      User agent

      - - - - - - - - - -

      Popups

      - -
        -
      1. - window.open('wxpython.html') -
      2. -
      3. - target=_blank href="wxpython.html" -
      4. -
      - -

      CreateAnotherBrowser

      - -This will create a window on its own and embed browser in it. -When using "window.open" the window is created implicitilly -by CEF. You can intercept such popup creation using the -OnBeforePopup callback in LifespanHandler. You can return -True in OnBeforePopup and create popup window on your own -using the CreateAnotherBrowser function. - - - - external.CreateAnotherBrowser() - - - - - - - -

      HTML5 video and accelerated content

      - - -HTML 5 video
      - - -Accelerated canvas
      - - -Accelerated layers
      - - - - - - -

      Developer Tools

      - -You can open devtools popup window in a few different ways: -
        -
      1. Call Browser.ShowDevTools() method: - - external.ShowDevTools()
      2. -
      3. Through mouse context menu
      4. -
      5. Through F12 key which is handled in KeyboardHandler.OnKeyEvent
      6. -
      - - - - - - -

      Downloads

      - -Download sample Ubuntu wallpapers:
      - - https://cefpython.googlecode.com/files/ubuntu-wallpapers2.zip - -

      -Notes: On Linux it seems that OnLoadError with errorCode = ERR_ABORTED -is called even for successful downloads, you can ignore this behavior. -The proper console messages about successful/aborted download originate -from C++ Browser process code, these are: -

      - -
      Browser: About to download file: ubuntu-wallpapers2.zip
      -Browser: Download completed, saved to: /Downloads/ubuntu-wallpapers2.zip
      -
      - -If download was aborted the messages will be: - -
      Browser: About to download file: ubuntu-wallpapers2.zip
      -Browser: Download was cancelled
      -
      - -

      -Additionally on Linux there are more errors reported by Chromium -about org.gnome.SessionManager.inhibit. These can be safely ignored as well. -

      - -A download handler with callbacks like `OnBeforeDownload` and -`OnDownloadUpdated` may be exposed to CEF Python in the future. - - - - - - -

      HTML controls

      - -

      Textarea

      - -
      - -

      Inputs

      -Text:
      -Password:
      - -

      Select

      - - -

      Buttons

      -Submit:
      -Button:
      - - - - - - -

      Browser object

      - -Tests for the Browser object methods. - -

      GoBack

      - -external.GoBack() - -

      GoForward

      - -external.GoForward() - -

      LoadUrl, GetUrl

      - - - window.open('data:text/html,Test#Browser.LoadUrl') - -

      ReloadIgnoreCache, StopLoad

      -Press F5 to reload page and ignore cache.
      -Press Esc during webpage loading to abort.
      - -Also, when Esc is pressed OnLoadError may get called. See how abort -of page loading or file download is handled: - - - - - - - -

      Frame object

      - -Tests for the Frame object methods. TODO. - - - - - - -

      Javascript bindings

      - -

      PyPrint

      - - - window.PyPrint('printing in python console from js') -
      - -

      Window properties

      - -
      jsBindings.SetProperty("pyProperty", "This was set in Python")
      -jsBindings.SetProperty("pyConfig", ["This was set in Python",
      -        {"name": "Nested dictionary", "isNested": True},
      -        [1,"2", None]])
      -
      - - - window.alert(window.pyProperty)
      - - window.alert(JSON.stringify(window.pyConfig)) -
      - -

      Print

      - - - - external.Print('printing again from js') -
      - -

      TestAllTypes

      - - - - external.TestAllTypes - (undefined, null, true, 1, - ((1<<31)>>>0), 2.14, 'Date not yet supported', 'string', - {key1: 1, key2: 2}, {key1: {'key1.1': 'nested object'}, 'key1.2': [1]}, - [1, 2], [1, [2.1, 'nested array']], [{key1: [{}]}]) -
      - -

      ExecuteFunction

      - - - -
      <script>
      -function JavascriptAlert(message) { window.alert(message); }
      -</script>
      -
      - - - - external.ExecuteFunction('JavascriptAlert', - 'python called from js and then js called from python') -
      - -

      GetSource, GetText

      - - - - - - - external.GetSource() -
      - - external.GetText() - - - - - - -

      Javascript callbacks

      - -

      TestJSCallback

      - - - -
      <script>
      -function JSCallback(arg1) {
      -    window.alert(arg1)
      -}
      -</script>
      -
      - - - - external.TestJSCallback(JSCallback) - -

      TestJSCallbackComplexArguments

      - - - -
      <script>
      -function JSCallback2() {
      -    window.alert(JSON.stringify(arguments))
      -}
      -</script>
      -
      - - - - external.TestJSCallbackComplexArguments({"myCallback": JSCallback2}) - - - - - - - -

      Python callbacks

      - -

      TestPythonCallback

      - - - -
      <script>
      -function JSCallback3(pyCallback) {
      -    pyCallback(1, 2.14, "string", [1, [2, {"key": "value"}]], {"list": [1,2]});
      -}
      -</script>
      -
      - - - - - - external.TestPythonCallback(JSCallback3) - - - - - - -

      Display handler

      - -

      OnAddressChange

      - -See messages in the console during loading of a webpage. - -

      OnTitleChange

      - -See messages in the console during loading of a webpage. - -

      OnTooltip

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

      OnStatusMessage

      - -See messages in the console when hovering over links. - -

      OnConsoleMessage

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

      Keyboard handler

      - -

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

      - - - - - - - - - -

      Request handler

      - -

      OnBeforeResourceLoad

      - -See messages in the console. - -

      OnResourceRedirect

      - -Try this: - - http://tinyurl.com/google404redirect - -

      GetAuthCredentials

      - -Try this: - - http://browserspy.dk/password-ok.php - -

      OnQuotaRequest

      - - - - -
      <script>
      -function DoRequestQuota() {
      -    // Request Quota (only for File System API)  
      -    try {
      -        navigator.webkitPersistentStorage.requestQuota(PERSISTENT, 1024*1024,
      -                function(bytes){ window.alert("Granted bytes: "+bytes);},
      -                function(error){ window.alert(error); });
      -    } catch(e) {
      -        navigator.webkitPersistentStorage.requestQuota(1024*1024,
      -                function(bytes){ window.alert("Granted bytes: "+bytes);},
      -                function(error){ window.alert(error); });
      -    }
      -}
      -</script>
      -
      - -Try this: - - https://googledrive.com/host/0B1di2XiBBfacMnhRRkI1YlotUEk/requestquota.html - -

      OnProtocolExecution

      - -Try this: - - magnet:?xt=urn:btih:a4224b45b27f436374391379cc5c7e629e2e5189 - -

      _OnBeforePluginLoad

      - -Try OnBeforePluginLoad() with Flash: - - http://www.adobe.com/software/flash/about/ - -

      _OnCertificateError

      - - -The url below won't be allowed. Click twice "Back" from context menu to return back -here after visiting the url:
      - - https://tv.eurosport.com/do-not-allow -
      - -This url will be allowed:
      - - https://tv.eurosport.com/ - -

      OnRendererProcessTerminated

      - -Try to terminate the "subprocess.exe" renderer process through -task manager. - -

      OnPluginCrashed

      - -No test for that yet. - - - - - - -

      Cookie tests

      - -See messages in the console. - -

      GetCookieManager

      - - - -RequestHandler.GetCookieManager() - an example of having an unique -cookie manager for each browser. -
        -
      1. Visit the url below and set some cookies. Use "Back" from - context menu to get back here (you might have to click "Back" - multiple times).
        - Visit it in the current browser:
        - - http://www.html-kit.com/tools/cookietester/ -
        - Or visit it in a js popup:
        - - javascript:window.open('http://www.html-kit.com/tools/cookietester/') -
      2. -
      3. Open cookietester in a popup:
        - - javascript:external.CreateAnotherBrowser('http://www.html-kit.com/tools/cookietester/') -
      4. -
      - -

      -Popup browsers created javascript's window.open share -the same renderer process and request context. If you want -to have separate cookie managers for popups created using -window.open then you have to implement the -LifespanHandler.`OnBeforePopup` callback. Return True in that -callback to cancel popup creation and instead create the -window on your own and embed browser in it. The CreateAnotherBrowser() -function from the wxpython example does that. -

      - -

      VisitAllCookies

      - -Visit all cookies: -external.VisitAllCookies() -

      - -Note: visit some http:// webpage first, otherwise cookie manager is not -yet created. -
      - -

      VisitUrlCookies

      - -Visit a subset of cookies for the given url: - - external.VisitUrlCookies("http://www.html-kit.com/tools/cookietester/") -
      - -

      SetCookie

      - -Set a cookie: -external.SetCookie() -
      - -

      DeleteCookies

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

      Load Handler

      - -See messages in the console during loading of a webpage. - -

      OnLoadingStateChange

      - - -

      OnLoadStart

      - - -

      OnLoadEnd

      - - -

      OnLoadError

      - -Try this: - - http://www.non-existent.nono/ -

      - -Note: after you see the custom error message you have to hit -twice the Back from the context menu, to get back to this page. - - - - - - -

      Javascript Dialog Handler

      - -See messages in the console. - -

      OnJavascriptDialog

      - - - alert('Test js dialog handler') - - -

      OnBeforeUnloadJavascriptDialog

      - - - -
      <script>
      -function TestOnBeforeUnloadJavascriptDialog() {
      -    window.onbeforeunload = function() {
      -        return 'Testing the OnBeforeUnloadJavascriptDialog() callback';
      -    }
      -    location.href = "wxpython.html";
      -}
      -</script>
      -
      - - - TestOnBeforeUnloadJavascriptDialog() - - -

      OnResetJavascriptDialogState

      - - -

      OnJavascriptDialogClosed

      - - - - - - - -

      Other tests

      - -

      HTTPS caching with SSL certificate errors

      -Set ApplicationSettings["ignore_certificate_errors"] to True. - - - - - - - - - - - - - diff --git a/src/linux/binaries_64bit/deprecated/wxpython.py b/src/linux/binaries_64bit/deprecated/wxpython.py deleted file mode 100644 index 6dee3c150..000000000 --- a/src/linux/binaries_64bit/deprecated/wxpython.py +++ /dev/null @@ -1,769 +0,0 @@ -# An example of embedding CEF browser in wxPython on Linux. -# Tested with wxPython 2.8.12.1 (gtk2-unicode). -# To install wxPython type "sudo apt-get install python-wxtools". - -# The official CEF Python binaries come with tcmalloc hook -# disabled. But if you've built custom binaries and kept tcmalloc -# hook enabled, then be aware that in such case it is required -# for the cefpython module to be the very first import in -# python scripts. See Issue 73 in the CEF Python Issue Tracker -# for more details. - -import ctypes, os, sys -libcef_so = os.path.join(os.path.dirname(os.path.abspath(__file__)),\ - 'libcef.so') -if os.path.exists(libcef_so): - # Import a local module - ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - if 0x02070000 <= sys.hexversion < 0x03000000: - import cefpython_py27 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import an installed package - from cefpython3 import cefpython - -import wx -import time -import re -import uuid -import platform -import inspect - -g_browserSettings = None - -# Which method to use for message loop processing. -# EVT_IDLE - wx application has priority (default) -# EVT_TIMER - cef browser has priority -# It seems that Flash content behaves better when using a timer. -# IMPORTANT! On Linux EVT_IDLE does not work, the events seems to -# be propagated only when you move your mouse, which is not the -# expected behavior, it is recommended to use EVT_TIMER on Linux, -# so set this value to False. -USE_EVT_IDLE = False - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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" (os._exit()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("[wxpython.py] WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainFrame(wx.Frame): - browser = None - mainPanel = None - - def __init__(self, url=None): - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, - title='wxPython CEF 3 example', size=(1024,768)) - if not url: - url = "file://"+GetApplicationPath("wxpython.html") - # Test hash in url. - # url += "#test-hash" - - self.CreateMenu() - - # Cannot attach browser to the main frame as this will cause - # the menu not to work. - # -- - # You also have to set the wx.WANTS_CHARS style for - # all parent panels/controls, if it's deeply embedded. - self.mainPanel = wx.Panel(self, style=wx.WANTS_CHARS) - - # Global client callbacks must be set before browser is created. - clientHandler = ClientHandler() - cefpython.SetGlobalClientCallback("OnCertificateError", - clientHandler._OnCertificateError) - cefpython.SetGlobalClientCallback("OnBeforePluginLoad", - clientHandler._OnBeforePluginLoad) - cefpython.SetGlobalClientCallback("OnAfterCreated", - clientHandler._OnAfterCreated) - - windowInfo = cefpython.WindowInfo() - # Must show window otherwise GetHandle() returns 0 - self.Show() - cefpython.WindowUtils.InstallX11ErrorHandlers() - windowInfo.SetAsChild(self.mainPanel.GetHandle(), - [0,0,0,0]) - # Linux requires adding "file://" for local files, - # otherwise /home/some will be replaced as http://home/some - self.browser = cefpython.CreateBrowserSync( - windowInfo, - # If there are problems with Flash you can disable it here, - # by disabling all plugins. - browserSettings=g_browserSettings, - navigateUrl=url) - - clientHandler.mainBrowser = self.browser - self.browser.SetClientHandler(clientHandler) - - jsBindings = cefpython.JavascriptBindings( - bindToFrames=False, bindToPopups=True) - jsBindings.SetFunction("PyPrint", PyPrint) - jsBindings.SetProperty("pyProperty", "This was set in Python") - jsBindings.SetProperty("pyConfig", ["This was set in Python", - {"name": "Nested dictionary", "isNested": True}, - [1,"2", None]]) - jsBindings.SetObject("external", JavascriptExternal(self.browser)) - jsBindings.SetProperty("sources", GetSources()) - self.browser.SetJavascriptBindings(jsBindings) - - self.Bind(wx.EVT_CLOSE, self.OnClose) - if USE_EVT_IDLE: - # Bind EVT_IDLE only for the main application frame. - self.Bind(wx.EVT_IDLE, self.OnIdle) - - def CreateMenu(self): - filemenu = wx.Menu() - filemenu.Append(1, "Open") - exit = filemenu.Append(2, "Exit") - self.Bind(wx.EVT_MENU, self.OnClose, exit) - aboutmenu = wx.Menu() - aboutmenu.Append(1, "CEF Python") - menubar = wx.MenuBar() - menubar.Append(filemenu,"&File") - menubar.Append(aboutmenu, "&About") - self.SetMenuBar(menubar) - - def OnClose(self, event): - # In wx.chromectrl calling browser.CloseBrowser() and/or - # self.Destroy() in OnClose is causing crashes when embedding - # multiple browser tabs. The solution is to call only - # browser.ParentWindowWillClose. Behavior of this example - # seems different as it extends wx.Frame, while ChromeWindow - # from chromectrl extends wx.Window. Calling CloseBrowser - # and Destroy does not cause crashes, but is not recommended. - # Call ParentWindowWillClose and event.Skip() instead. See - # also Issue 107. - self.browser.ParentWindowWillClose() - event.Skip() - - def OnIdle(self, event): - cefpython.MessageLoopWork() - -def PyPrint(message): - print("[wxpython.py] PyPrint: "+message) - -class JavascriptExternal: - mainBrowser = None - stringVisitor = None - - def __init__(self, mainBrowser): - self.mainBrowser = mainBrowser - - def GoBack(self): - self.mainBrowser.GoBack() - - def GoForward(self): - self.mainBrowser.GoForward() - - def CreateAnotherBrowser(self, url=None): - """ - TODO: There are errors in the console when closing the window: - >> Check failed: window - >> Gdk: _gdk_window_destroy_hierarchy: assertion `GDK_IS_WINDOW\ - >> (window)' failed - >> GLib-GObject: g_object_unref: assertion `G_IS_OBJECT (object)' failed - """ - frame = MainFrame(url=url) - frame.Show() - - def Print(self, message): - print("[wxpython.py] Print: "+message) - - def TestAllTypes(self, *args): - print("[wxpython.py] TestAllTypes: "+str(args)) - - def ExecuteFunction(self, *args): - self.mainBrowser.GetMainFrame().ExecuteFunction(*args) - - def TestJSCallback(self, jsCallback): - print("[wxpython.py] jsCallback.GetFunctionName() = %s"\ - % jsCallback.GetFunctionName()) - print("[wxpython.py] jsCallback.GetFrame().GetIdentifier() = %s" % \ - jsCallback.GetFrame().GetIdentifier()) - jsCallback.Call("This message was sent from python using js callback") - - def TestJSCallbackComplexArguments(self, jsObject): - jsCallback = jsObject["myCallback"]; - jsCallback.Call(1, None, 2.14, "string", ["list", ["nested list", \ - {"nested object":None}]], \ - {"nested list next":[{"deeply nested object":1}]}) - - def TestPythonCallback(self, jsCallback): - jsCallback.Call(self.PyCallback) - - def PyCallback(self, *args): - message = "PyCallback() was executed successfully! "\ - "Arguments: %s" % str(args) - print("[wxpython.py] "+message) - self.mainBrowser.GetMainFrame().ExecuteJavascript( - "window.alert(\"%s\")" % message) - - def GetSource(self): - # Must keep a strong reference to the StringVisitor object - # during the visit. - self.stringVisitor = StringVisitor() - self.mainBrowser.GetMainFrame().GetSource(self.stringVisitor) - - def GetText(self): - # Must keep a strong reference to the StringVisitor object - # during the visit. - self.stringVisitor = StringVisitor() - self.mainBrowser.GetMainFrame().GetText(self.stringVisitor) - - def ShowDevTools(self): - print("[wxpython.py] external.ShowDevTools called") - self.mainBrowser.ShowDevTools() - - # ------------------------------------------------------------------------- - # Cookies - # ------------------------------------------------------------------------- - cookieVisitor = None - - def VisitAllCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.VisitAllCookies(self.cookieVisitor) - - def VisitUrlCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.VisitUrlCookies( - "http://www.html-kit.com/tools/cookietester/", - False, self.cookieVisitor) - # .www.html-kit.com - - def SetCookie(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - "the cookietester website first and create some cookies") - return - cookie = cefpython.Cookie() - cookie.SetName("Created_Via_Python") - cookie.SetValue("yeah really") - cookieManager.SetCookie("http://www.html-kit.com/tools/cookietester/", - cookie) - print("\n[wxpython.py] Cookie created! Visit html-kit cookietester to"\ - " see it") - - def DeleteCookies(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.DeleteCookies( - "http://www.html-kit.com/tools/cookietester/", - "Created_Via_Python") - print("\n[wxpython.py] Cookie deleted! Visit html-kit cookietester "\ - "to see the result") - -class StringVisitor: - def Visit(self, string): - print("\n[wxpython.py] StringVisitor.Visit(): string:") - print("--------------------------------") - print(string) - print("--------------------------------") - -class CookieVisitor: - def Visit(self, cookie, count, total, deleteCookie): - if count == 0: - print("\n[wxpython.py] CookieVisitor.Visit(): total cookies: %s"\ - % total) - print("\n[wxpython.py] CookieVisitor.Visit(): cookie:") - print(" "+str(cookie.Get())) - # True to continue visiting cookies - return True - -class ClientHandler: - mainBrowser = None # May be None for global client callbacks. - - def __init__(self): - pass - - # ------------------------------------------------------------------------- - # DisplayHandler - # ------------------------------------------------------------------------- - - def OnAddressChange(self, browser, frame, url): - print("[wxpython.py] DisplayHandler::OnAddressChange()") - print(" url = %s" % url) - - def OnTitleChange(self, browser, title): - print("[wxpython.py] DisplayHandler::OnTitleChange()") - print(" title = %s" % title) - - def OnTooltip(self, browser, textOut): - # OnTooltip not yet implemented (both Linux and Windows), - # will be fixed in next CEF release, see Issue 783: - # https://code.google.com/p/chromiumembedded/issues/detail?id=783 - print("[wxpython.py] DisplayHandler::OnTooltip()") - print(" text = %s" % textOut[0]) - - statusMessageCount = 0 - def OnStatusMessage(self, browser, value): - if not value: - # Do not notify in the console about empty statuses. - return - self.statusMessageCount += 1 - if self.statusMessageCount > 3: - # Do not spam too much. - return - print("[wxpython.py] DisplayHandler::OnStatusMessage()") - print(" value = %s" % value) - - def OnConsoleMessage(self, browser, message, source, line): - print("[wxpython.py] DisplayHandler::OnConsoleMessage()") - print(" message = %s" % message) - print(" source = %s" % source) - print(" line = %s" % line) - - # ------------------------------------------------------------------------- - # KeyboardHandler - # ------------------------------------------------------------------------- - - def OnPreKeyEvent(self, browser, event, eventHandle, - isKeyboardShortcutOut): - - stype = event["type"] - if stype == cefpython.KEYEVENT_RAWKEYDOWN: - stype = "RAWKEYDOWN" - elif stype == cefpython.KEYEVENT_KEYDOWN: - stype = "KEYDOWN" - elif stype == cefpython.KEYEVENT_KEYUP: - stype = "KEYUP" - elif stype == cefpython.KEYEVENT_CHAR: - stype = "CHAR" - - print("[wxpython.py] KeyboardHandler::OnPreKeyEvent()") - print(" type=%s" % stype) - print(" modifiers=%s" % event["modifiers"]) - print(" windows_key_code=%s" % event["windows_key_code"]) - print(" native_key_code=%s" % event["native_key_code"]) - print(" is_system_key=%s" % event["is_system_key"]) - print(" character=%s" % event["character"]) - print(" unmodified_character=%s" % event["unmodified_character"]) - print(" focus_on_editable_field=%s"\ - % event["focus_on_editable_field"]) - - def OnKeyEvent(self, browser, event, eventHandle): - pass - - # ------------------------------------------------------------------------- - # RequestHandler - # ------------------------------------------------------------------------- - - def OnBeforeBrowse(self, browser, frame, request, isRedirect): - print("[wxpython.py] RequestHandler::OnBeforeBrowse()") - print(" url = %s" % request.GetUrl()[:100]) - return False - - def OnBeforeResourceLoad(self, browser, frame, request): - print("[wxpython.py] RequestHandler::OnBeforeResourceLoad()") - print(" url = %s" % request.GetUrl()[:100]) - return False - - def OnResourceRedirect(self, browser, frame, oldUrl, newUrlOut, request): - print("[wxpython.py] RequestHandler::OnResourceRedirect()") - print(" old url = %s" % oldUrl[:100]) - print(" new url = %s" % newUrlOut[0][:100]) - - def GetAuthCredentials(self, browser, frame, isProxy, host, port, realm, - scheme, callback): - # This callback is called on the IO thread, thus print messages - # may not be visible. - print("[wxpython.py] RequestHandler::GetAuthCredentials()") - print(" host = %s" % host) - print(" realm = %s" % realm) - callback.Continue(username="test", password="test") - return True - - def OnQuotaRequest(self, browser, originUrl, newSize, callback): - print("[wxpython.py] RequestHandler::OnQuotaRequest()") - print(" origin url = %s" % originUrl) - print(" new size = %s" % newSize) - callback.Continue(True) - return True - - def GetCookieManager(self, browser, mainUrl): - # Create unique cookie manager for each browser. - # You must set the "unique_request_context_per_browser" - # application setting to True for the cookie manager - # to work. - # Return None to have one global cookie manager for - # all CEF browsers. - if not browser: - # The browser param may be empty in some exceptional - # case, see docs. - return None - cookieManager = browser.GetUserData("cookieManager") - if cookieManager: - return cookieManager - else: - print("[wxpython.py] RequestHandler::GetCookieManager():"\ - " created cookie manager") - cookieManager = cefpython.CookieManager.CreateManager("") - browser.SetUserData("cookieManager", cookieManager) - return cookieManager - - def OnProtocolExecution(self, browser, url, allowExecutionOut): - # There's no default implementation for OnProtocolExecution on Linux, - # you have to make OS system call on your own. You probably also need - # to use LoadHandler::OnLoadError() when implementing this on Linux. - print("[wxpython.py] RequestHandler::OnProtocolExecution()") - print(" url = %s" % url) - if url.startswith("magnet:"): - print("[wxpython.py] Magnet link allowed!") - allowExecutionOut[0] = True - - def _OnBeforePluginLoad(self, browser, mimeType, pluginUrl, topOriginUrl, - info): - # This is a global callback set using SetGlobalClientCallback(). - # Plugins are loaded on demand, only when website requires it, - # the same plugin may be called multiple times. - # This callback is called on various threads, thus print messages - # may not be visible. - print("[wxpython.py] RequestHandler::_OnBeforePluginLoad()") - print(" mimeType = %s" % mimeType) - print(" pluginUrl = %s" % pluginUrl) - print(" topOriginUrl = %s" % topOriginUrl) - print(" info.GetName() = %s" % info.GetName()) - print(" info.GetPath() = %s" % info.GetPath()) - print(" info.GetVersion() = %s" % info.GetVersion()) - print(" info.GetDescription() = %s" % info.GetDescription()) - # False to allow, True to block plugin. - return False - - def _OnCertificateError(self, certError, requestUrl, callback): - # This is a global callback set using SetGlobalClientCallback(). - print("[wxpython.py] RequestHandler::_OnCertificateError()") - print(" certError = %s" % certError) - print(" requestUrl = %s" % requestUrl) - if requestUrl.startswith( - "https://tv.eurosport.com/do-not-allow"): - print(" Not allowed!") - return False - if requestUrl.startswith( - "https://tv.eurosport.com/"): - print(" Allowed!") - callback.Continue(True) - return True - return False - - def OnRendererProcessTerminated(self, browser, status): - print("[wxpython.py] RequestHandler::OnRendererProcessTerminated()") - statuses = { - cefpython.TS_ABNORMAL_TERMINATION: "TS_ABNORMAL_TERMINATION", - cefpython.TS_PROCESS_WAS_KILLED: "TS_PROCESS_WAS_KILLED", - cefpython.TS_PROCESS_CRASHED: "TS_PROCESS_CRASHED" - } - statusName = "Unknown" - if status in statuses: - statusName = statuses[status] - print(" status = %s" % statusName) - - def OnPluginCrashed(self, browser, pluginPath): - print("[wxpython.py] RequestHandler::OnPluginCrashed()") - print(" plugin path = %s" % pluginPath) - - # ------------------------------------------------------------------------- - # LoadHandler - # ------------------------------------------------------------------------- - - def OnLoadingStateChange(self, browser, isLoading, canGoBack, - canGoForward): - print("[wxpython.py] LoadHandler::OnLoadingStateChange()") - print(" isLoading = %s, canGoBack = %s, canGoForward = %s" \ - % (isLoading, canGoBack, canGoForward)) - - def OnLoadStart(self, browser, frame): - print("[wxpython.py] LoadHandler::OnLoadStart()") - print(" frame url = %s" % frame.GetUrl()[:100]) - - def OnLoadEnd(self, browser, frame, httpStatusCode): - print("[wxpython.py] LoadHandler::OnLoadEnd()") - print(" frame url = %s" % frame.GetUrl()[:100]) - # For file:// urls the status code = 0 - print(" http status code = %s" % httpStatusCode) - # Tests for the Browser object methods - self._Browser_LoadUrl(browser) - - def _Browser_LoadUrl(self, browser): - if browser.GetUrl() == "data:text/html,Test#Browser.LoadUrl": - browser.LoadUrl("file://"+GetApplicationPath("wxpython.html")) - - def OnLoadError(self, browser, frame, errorCode, errorTextList, failedUrl): - print("[wxpython.py] LoadHandler::OnLoadError()") - print(" frame url = %s" % frame.GetUrl()[:100]) - print(" error code = %s" % errorCode) - print(" error text = %s" % errorTextList[0]) - print(" failed url = %s" % failedUrl) - # Handle ERR_ABORTED error code, to handle the following cases: - # 1. Esc key was pressed which calls browser.StopLoad() in OnKeyEvent - # 2. Download of a file was aborted - if errorCode == cefpython.ERR_ABORTED: - print("[wxpython.py] LoadHandler::OnLoadError(): Ignoring load"\ - " error: Esc was pressed or file download was aborted") - return; - customErrorMessage = "My custom error message!" - frame.LoadUrl("data:text/html,%s" % customErrorMessage) - - # ------------------------------------------------------------------------- - # LifespanHandler - # ------------------------------------------------------------------------- - - # ** This callback is executed on the IO thread ** - # Empty place-holders: popupFeatures, client. - def OnBeforePopup(self, browser, frame, targetUrl, targetFrameName, - targetDisposition, userGesture, - popupFeatures, windowInfo, client, browserSettings, - noJavascriptAccess): - print("[wxpython.py] LifespanHandler::OnBeforePopup()") - print(" targetUrl = %s" % targetUrl) - # Custom browser settings for popups: - # > browserSettings[0] = {"plugins_disabled": True} - # Set WindowInfo object: - # > windowInfo[0] = cefpython.WindowInfo() - allowPopups = True - return not allowPopups - - def _OnAfterCreated(self, browser): - # This is a global callback set using SetGlobalClientCallback(). - print("[wxpython.py] LifespanHandler::_OnAfterCreated()") - print(" browserId=%s" % browser.GetIdentifier()) - - def DoClose(self, browser): - print("[wxpython.py] LifespanHandler::DoClose()") - print(" browserId=%s" % browser.GetIdentifier()) - - def OnBeforeClose(self, browser): - print("[wxpython.py] LifespanHandler::OnBeforeClose") - print(" browserId=%s" % browser.GetIdentifier()) - - # ------------------------------------------------------------------------- - # JavascriptDialogHandler - # ------------------------------------------------------------------------- - - def OnJavascriptDialog(self, browser, originUrl, dialogType, - messageText, defaultPromptText, callback, - suppressMessage): - print("[wxpython.py] JavascriptDialogHandler::OnJavascriptDialog()") - print(" originUrl="+originUrl) - print(" dialogType="+str(dialogType)) - print(" messageText="+messageText) - print(" defaultPromptText="+defaultPromptText) - # If you want to suppress the javascript dialog: - # suppressMessage[0] = True - return False - - def OnBeforeUnloadJavascriptDialog(self, browser, messageText, isReload, - callback): - print("[wxpython.py] OnBeforeUnloadJavascriptDialog()") - print(" messageText="+messageText) - print(" isReload="+str(isReload)) - # Return True if the application will use a custom dialog: - # callback.Continue(allow=True, userInput="") - # return True - return False - - def OnResetJavascriptDialogState(self, browser): - print("[wxpython.py] OnResetDialogState()") - - def OnJavascriptDialogClosed(self, browser): - print("[wxpython.py] OnDialogClosed()") - - -class MyApp(wx.App): - timer = None - timerID = 1 - timerCount = 0 - - def OnInit(self): - if not USE_EVT_IDLE: - self.CreateTimer() - frame = MainFrame() - self.SetTopWindow(frame) - frame.Show() - return True - - def CreateTimer(self): - # See "Making a render loop": - # http://wiki.wxwidgets.org/Making_a_render_loop - # Another approach is to use EVT_IDLE in MainFrame, - # see which one fits you better. - self.timer = wx.Timer(self, self.timerID) - self.timer.Start(10) # 10ms - wx.EVT_TIMER(self, self.timerID, self.OnTimer) - - def OnTimer(self, event): - self.timerCount += 1 - # print("[wxpython.py] OnTimer() %d" % self.timerCount) - cefpython.MessageLoopWork() - - def OnExit(self): - # When app.MainLoop() returns, MessageLoopWork() should - # not be called anymore. - if not USE_EVT_IDLE: - self.timer.Stop() - -def GetSources(): - # Get sources of all python functions and methods from this file. - # This is to provide sources preview to wxpython.html. - # The dictionary of functions is binded to "window.sources". - thisModule = sys.modules[__name__] - functions = inspect.getmembers(thisModule, inspect.isfunction) - classes = inspect.getmembers(thisModule, inspect.isclass) - sources = {} - for funcTuple in functions: - sources[funcTuple[0]] = inspect.getsource(funcTuple[1]) - for classTuple in classes: - className = classTuple[0] - classObject = classTuple[1] - methods = inspect.getmembers(classObject) - for methodTuple in methods: - try: - sources[methodTuple[0]] = inspect.getsource(\ - methodTuple[1]) - except: - pass - return sources - -if __name__ == '__main__': - print('[wxpython.py] wx.version=%s' % wx.version()) - - # Intercept python exceptions. Exit app immediately when exception - # happens on any of the threads. - sys.excepthook = ExceptHook - - # Application settings - settings = { - # CEF Python debug messages in console and in log_file - "debug": True, - # Set it to LOGSEVERITY_VERBOSE for more details - "log_severity": cefpython.LOGSEVERITY_INFO, - # Set to "" to disable logging to a file - "log_file": GetApplicationPath("debug.log"), - # These directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory(), - # The "subprocess" executable that launches the Renderer - # and GPU processes among others. You may rename that - # executable if you like. - "browser_subprocess_path": "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess"), - # This option is required for the GetCookieManager callback - # to work. It affects renderer processes, when this option - # is set to True. It will force a separate renderer process - # for each browser created using CreateBrowserSync. - "unique_request_context_per_browser": True, - # Downloads are handled automatically. A default SaveAs file - # dialog provided by OS will be displayed. - "downloads_enabled": True, - # Remote debugging port, required for Developer Tools support. - # A value of 0 will generate a random port. To disable devtools - # support set it to -1. - "remote_debugging_port": 0, - # Mouse context menu - "context_menu": { - "enabled": True, - "navigation": True, # Back, Forward, Reload - "print": True, - "view_source": True, - "external_browser": True, # Open in external browser - "devtools": True, # Developer Tools - }, - # See also OnCertificateError which allows you to ignore - # certificate errors for specific websites. - "ignore_certificate_errors": False, - } - - # Browser settings. You may have different settings for each - # browser, see the call to CreateBrowserSync. - g_browserSettings = { - # "plugins_disabled": True, - # "file_access_from_file_urls_allowed": True, - # "universal_access_from_file_urls_allowed": True, - } - - # Command line switches set programmatically - switches = { - # "proxy-server": "socks5://127.0.0.1:8888", - # "no-proxy-server": "", - # "enable-media-stream": "", - # "remote-debugging-port": "12345", - # "disable-gpu": "", - # "--invalid-switch": "" -> Invalid switch name - } - - cefpython.Initialize(settings, switches) - - app = MyApp(False) - app.MainLoop() - # Let wx.App destructor do the cleanup before calling cefpython.Shutdown(). - del app - - cefpython.Shutdown() diff --git a/src/linux/compile.py b/src/linux/compile.py deleted file mode 100644 index 16acf092d..000000000 --- a/src/linux/compile.py +++ /dev/null @@ -1,325 +0,0 @@ -""" -Build the cefpython module, install package and run example. - -Usage: - compile.py VERSION [--debug] [--fast] - -Options: - VERSION Version in format xx.xx - --debug Debug mode - --fast Fast mode, don't delete C++ .o .a files, nor the setup/build/ - directory, and disable optimization flags when building - the so/pyd module. - --kivy Run Kivy example -""" - -# TODO: Check Cython version using info from tools/requirements.txt - -import sys -import os -import glob -import shutil -import subprocess -import platform -import re -import struct - -# raw_input() was renamed to input() in Python 3 - -try: - # noinspection PyUnresolvedReferences - # noinspection PyShadowingBuiltins - input = raw_input -except NameError: - pass - - -def check_cython_version(): - with open("../../tools/requirements.txt", "r") as fileobj: - contents = fileobj.read() - match = re.search(r"cython\s*==\s*([\d.]+)", contents, - flags=re.IGNORECASE) - assert match, "cython package not found in requirements.txt" - require_version = match.group(1) - try: - import Cython - version = Cython.__version__ - except ImportError: - # noinspection PyUnusedLocal - Cython = None - print("ERROR: Cython is not installed ({0} required)" - .format(require_version)) - sys.exit(1) - if version != require_version: - print("ERROR: Wrong Cython version: {0}. Required: {1}" - .format(version, require_version)) - sys.exit(1) - print("Cython version: {0}".format(version)) - -check_cython_version() - -# This will not show "Segmentation fault" error message: -# | subprocess.call(["python", "./wxpython.py"]) -# You need to call it with shell=True for this kind of -# error message to be shown: -# | subprocess.call("python wxpython.py", shell=True) - -# How to debug: -# 1. Install "python-dbg" package -# 2. Install "python-wxgtk2.8-dbg" package -# 3. Run "python compile.py debug" -# 4. In cygdb type "cy run" -# 5. To display debug backtrace type "cy bt" -# 6. More commands: http://docs.cython.org/src/userguide/debugging.html - -# -- debug flag -if len(sys.argv) > 1 and "--debug" in sys.argv: - DEBUG_FLAG = True - print("DEBUG mode On") -else: - DEBUG_FLAG = False - -# --fast flag -if len(sys.argv) > 1 and "--fast" in sys.argv: - # Fast mode doesn't delete C++ .o .a files. - # Fast mode also disables optimization flags in setup/setup.py . - FAST_FLAG = True - print("FAST mode On") -else: - FAST_FLAG = False - -# --kivy flag -if len(sys.argv) > 1 and "--kivy" in sys.argv: - KIVY_FLAG = True - print("KIVY_FLAG flag enabled") -else: - KIVY_FLAG = False - - -# version arg -if len(sys.argv) > 1 and re.search(r"^\d+\.\d+$", sys.argv[1]): - VERSION = sys.argv[1] -else: - print("[compile.py] ERROR: expected first argument to be version number") - print(" Allowed version format: \\d+\.\\d+") - sys.exit(1) - -print("VERSION=%s" % VERSION) - -# Architecture and OS postfixes -ARCH32 = (8 * struct.calcsize('P') == 32) -ARCH64 = (8 * struct.calcsize('P') == 64) -OS_POSTFIX = ("win" if platform.system() == "Windows" else - "linux" if platform.system() == "Linux" else - "mac" if platform.system() == "Darwin" else "unknown") -OS_POSTFIX2 = "unknown" -if OS_POSTFIX == "win": - OS_POSTFIX2 = "win32" if ARCH32 else "win64" -elif OS_POSTFIX == "mac": - OS_POSTFIX2 = "mac32" if ARCH32 else "mac64" -elif OS_POSTFIX == "linux": - OS_POSTFIX2 = "linux32" if ARCH32 else "linux64" - -PYVERSION = str(sys.version_info[0])+str(sys.version_info[1]) -print("PYVERSION = %s" % PYVERSION) -print("OS_POSTFIX2 = %s" % OS_POSTFIX2) - -# Directories -LINUX_DIR = os.path.abspath(os.path.dirname(__file__)) -SRC_DIR = os.path.abspath(os.path.join(LINUX_DIR, "..")) -CPP_UTILS_DIR = os.path.abspath(os.path.join(SRC_DIR, "cpp_utils")) -CLIENT_HANDLER_DIR = os.path.abspath(os.path.join(SRC_DIR, "client_handler")) -SUBPROCESS_DIR = os.path.abspath(os.path.join(SRC_DIR, "subprocess")) -SETUP_DIR = os.path.abspath(os.path.join(LINUX_DIR, "setup")) -CEFPYTHON_DIR = os.path.abspath(os.path.join(SRC_DIR, "..")) -BUILD_DIR = os.path.abspath(os.path.join(CEFPYTHON_DIR, "build")) -CEF_BINARY = os.path.abspath(os.path.join(BUILD_DIR, "cef_"+OS_POSTFIX2)) -CEFPYTHON_BINARY = os.path.abspath(os.path.join(BUILD_DIR, - "cefpython_"+OS_POSTFIX2)) - -# Create directories if necessary -if not os.path.exists(CEFPYTHON_BINARY): - os.mkdir(CEFPYTHON_BINARY) - -# Check directories -assert os.path.exists(CEF_BINARY) -assert os.path.exists(CEFPYTHON_BINARY) - -print("Compiling C++ projects") - -# Need to allow continuing even when make fails, as it may -# fail because the "public" function declaration is not yet -# in "cefpython.h", but for it to be generated we need to run -# cython compiling, so in this case you continue even when make -# fails and then run the compile.py script again and this time -# make should succeed. - -# -------- CPP_UTILS_DIR - -os.chdir(CPP_UTILS_DIR) -if not FAST_FLAG: - subprocess.call("rm -f *.o *.a", shell=True) - -ret = subprocess.call("make -f Makefile", shell=True) -if ret != 0: - # noinspection PyUnboundLocalVariable - what = input("make failed, press 'y' to continue, 'n' to stop: ") - if what != "y": - sys.exit(1) - -# -------- CLIENT_HANDLER_DIR - -os.chdir(CLIENT_HANDLER_DIR) -if not FAST_FLAG: - subprocess.call("rm -f *.o *.a", shell=True) - -ret = subprocess.call("make -f Makefile", shell=True) -if ret != 0: - what = input("make failed, press 'y' to continue, 'n' to stop: ") - if what != "y": - sys.exit(1) - -# -------- SUBPROCESS_DIR - -os.chdir(SUBPROCESS_DIR) -if not FAST_FLAG: - subprocess.call("rm -f *.o *.a", shell=True) - subprocess.call("rm -f subprocess", shell=True) - -ret = subprocess.call("make -f Makefile-libcefpythonapp", shell=True) -if ret != 0: - what = input("make failed, press 'y' to continue, 'n' to stop: ") - if what != "y": - sys.exit(1) - -ret = subprocess.call("make -f Makefile", shell=True) -if ret != 0: - what = input("make failed, press 'y' to continue, 'n' to stop: ") - if what != "y": - sys.exit(1) -subprocess_exe = os.path.join(CEFPYTHON_BINARY, "subprocess") -if os.path.exists("./subprocess"): - # .copy() will also copy Permission bits - shutil.copy("./subprocess", subprocess_exe) - -# -------- LINUX_DIR - -os.chdir(LINUX_DIR) -try: - cefpython_module = os.path.join(CEFPYTHON_BINARY, - "cefpython_py{0}.so".format(PYVERSION)) - os.remove(cefpython_module) -except OSError: - pass - - -# -------- SETUP_DIR - -os.chdir(SETUP_DIR) - -os.system("rm -f ./cefpython_py*.so") - -pyx_files = glob.glob("./*.pyx") -for f in pyx_files: - os.remove(f) - -try: - if not FAST_FLAG: - shutil.rmtree(os.path.join(SETUP_DIR, "build")) -except OSError: - pass - -ret = subprocess.call("{python} fix_pyx_files.py" - .format(python=sys.executable), shell=True) -if ret != 0: - sys.exit("ERROR") - -# Create __version__.pyx after fix_pyx_files.py was called, -# as that script deletes old pyx files before copying new ones. -print("Creating __version__.pyx file") -with open("__version__.pyx", "w") as fo: - fo.write('__version__ = "{}"\n'.format(VERSION)) - -# if DEBUG_FLAG: -# ret = subprocess.call("python-dbg setup.py build_ext --inplace" -# " --cython-gdb", shell=True) -if FAST_FLAG: - ret = subprocess.call("{python} setup.py build_ext --inplace --fast" - .format(python=sys.executable), shell=True) -else: - ret = subprocess.call("{python} setup.py build_ext --inplace" - .format(python=sys.executable), shell=True) - -# if DEBUG_FLAG: -# shutil.rmtree("./../binaries_%s/cython_debug/" % BITS, -# ignore_errors=True) -# shutil.copytree("./cython_debug/", -# "./../binaries_%s/cython_debug/" % BITS) - -oldpyxfiles = glob.glob("./*.pyx") -print("Removing old pyx files in /setup/: %s" % oldpyxfiles) -for pyxfile in oldpyxfiles: - if os.path.exists(pyxfile): - os.remove(pyxfile) - -if ret != 0: - sys.exit("ERROR") - -exitcode = os.system("mv ./cefpython_py{pyver}*.so" - " {cefpython_binary}/cefpython_py{pyver}.so" - .format(pyver=PYVERSION, - cefpython_binary=CEFPYTHON_BINARY)) -if exitcode: - raise RuntimeError("Failed to move the cefpython module") - -print("DONE") - -# -------- LINUX_DIR - -os.chdir(LINUX_DIR) - -# if DEBUG_FLAG: -# os.chdir("./binaries_%s" % BITS) -# subprocess.call("cygdb . --args python-dbg wxpython.py", shell=True) - -print("Make installer and run setup.py install...") - -# Clean installer directory from previous run -exit_code = os.system("rm -rf ./installer/cefpython3-{ver}-*-setup/" - .format(ver=VERSION)) -if exit_code: - os.system("sudo rm -rf ./installer/cefpython3-{ver}-*-setup/" - .format(ver=VERSION)) - -# System python requires sudo when installing package -if sys.executable in ["/usr/bin/python", "/usr/bin/python3"]: - sudo = "sudo" -else: - sudo = "" - -# Make installer, install, run examples and unit tests, -# and return to src/linux/ dir. -if KIVY_FLAG: - run_examples = " && {python} ../src/linux/deprecated_64bit/kivy_.py" -else: - run_examples = (" && {python} hello_world.py" - " && {python} wxpython.py" - " && {python} gtk2.py" - " && {python} gtk2.py --message-loop-timer" - # " && {python} gtk3.py" - " && {python} tkinter_.py" - " && {python} qt.py pyqt" - " && {python} qt.py pyside" - " && {python} ../src/linux/deprecated_64bit/kivy_.py") -commands = ("cd ./installer/" - " && {python} make-setup.py --version {ver}" - " && cd cefpython3-{ver}-*-setup/" - " && {sudo} {python} setup.py install" - " && cd ../" - " && {sudo} rm -rf ./cefpython3-{ver}-*-setup/" - " && cd ../../../unittests/" - " && {python} _test_runner.py" - " && cd ../examples/" - + run_examples + - " && cd ../src/linux/") -os.system(commands.format(python=sys.executable, ver=VERSION, sudo=sudo)) diff --git a/src/linux/installer/.gitignore b/src/linux/deb_pkg_deprecated/.gitignore similarity index 100% rename from src/linux/installer/.gitignore rename to src/linux/deb_pkg_deprecated/.gitignore diff --git a/src/linux/installer/debian.postinst b/src/linux/deb_pkg_deprecated/debian.postinst similarity index 100% rename from src/linux/installer/debian.postinst rename to src/linux/deb_pkg_deprecated/debian.postinst diff --git a/src/linux/installer/deps.txt b/src/linux/deb_pkg_deprecated/deps.txt similarity index 100% rename from src/linux/installer/deps.txt rename to src/linux/deb_pkg_deprecated/deps.txt diff --git a/src/linux/installer/find-deps.py b/src/linux/deb_pkg_deprecated/find-deps.py similarity index 100% rename from src/linux/installer/find-deps.py rename to src/linux/deb_pkg_deprecated/find-deps.py diff --git a/src/linux/installer/make-deb.py b/src/linux/deb_pkg_deprecated/make-deb.py similarity index 100% rename from src/linux/installer/make-deb.py rename to src/linux/deb_pkg_deprecated/make-deb.py diff --git a/src/linux/installer/stdeb.cfg.template b/src/linux/deb_pkg_deprecated/stdeb.cfg.template similarity index 100% rename from src/linux/installer/stdeb.cfg.template rename to src/linux/deb_pkg_deprecated/stdeb.cfg.template diff --git a/src/linux/installer/README.txt b/src/linux/installer/README.txt deleted file mode 100644 index 8b481c2a8..000000000 --- a/src/linux/installer/README.txt +++ /dev/null @@ -1,20 +0,0 @@ -1. To install CEF Python 3 package type: - - sudo python setup.py install - - This will install the cefpython3 package to - /usr/local/lib/python2.7/dist-packages/ - -2. In the same directory that setup.py resides there is - an examples/ directory. Run some examples from there: - - cd examples/ - python pygtk_.py - python pyqt.py - python wxpython.py - python kivy_.py - - cd wx/ - python sample1.py - python sample2.py - python sample3.py diff --git a/src/linux/installer/__init__.py.template b/src/linux/installer/__init__.py.template deleted file mode 100644 index baebba0f2..000000000 --- a/src/linux/installer/__init__.py.template +++ /dev/null @@ -1,40 +0,0 @@ -__all__ = ["cefpython", "wx"] -__version__ = "%(APP_VERSION)s" -__author__ = "The CEF Python authors" - -import ctypes, os - -# If this is a debian package then package_dir returns: -# /usr/lib/pymodules/python2.7/cefpython3 -# The above path consists of symbolic links to the real directory: -# /usr/share/pyshared/cefpython3 - -# If package was installed using PIP or setup.py then package -# dir is here: -# /usr/local/lib/python2.7/dist-packages/cefpython3/ - -package_dir = os.path.dirname(os.path.abspath(__file__)) - -# This loads the libcef.so library for the subprocess executable. -os.environ["LD_LIBRARY_PATH"] = package_dir - -# This env variable will be returned by cefpython.GetModuleDirectory(). -os.environ["CEFPYTHON3_PATH"] = package_dir - -# This loads the libcef.so library for the main python executable. -# The libffmpegsumo.so library does not need to be loaded here, -# it may cause issues to load it here in the browser process. -libcef_so = os.path.join(package_dir, "libcef.so") -ctypes.CDLL(libcef_so, ctypes.RTLD_GLOBAL) - -import sys -if (2, 7) <= sys.version_info < (2, 8): - from . import cefpython_py27 as cefpython -elif (3, 4) <= sys.version_info < (3, 5): - from . import cefpython_py34 as cefpython -elif (3, 5) <= sys.version_info < (3, 6): - from . import cefpython_py35 as cefpython -elif (3, 6) <= sys.version_info < (3, 7): - from . import cefpython_py36 as cefpython -else: - raise Exception("Unsupported python version: " + sys.version) diff --git a/src/linux/installer/make-setup.py b/src/linux/installer/make-setup.py deleted file mode 100644 index bd016cb1a..000000000 --- a/src/linux/installer/make-setup.py +++ /dev/null @@ -1,222 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -# Create a setup package. - -import sys -import os -import re -import platform -import shutil -import glob -import sysconfig -import subprocess -import struct - -PACKAGE_NAME = "cefpython3" - -# Bits -BITS = platform.architecture()[0] -assert (BITS == "32bit" or BITS == "64bit") -if BITS == "32bit": - LINUX_BITS = "linux32" -else: - LINUX_BITS = "linux64" - -# Architecture and OS postfixes -ARCH32 = (8 * struct.calcsize('P') == 32) -ARCH64 = (8 * struct.calcsize('P') == 64) -OS_POSTFIX = ("win" if platform.system() == "Windows" else - "linux" if platform.system() == "Linux" else - "mac" if platform.system() == "Darwin" else "unknown") -OS_POSTFIX2 = "unknown" -if OS_POSTFIX == "win": - OS_POSTFIX2 = "win32" if ARCH32 else "win64" -elif OS_POSTFIX == "mac": - OS_POSTFIX2 = "mac32" if ARCH32 else "mac64" -elif OS_POSTFIX == "linux": - OS_POSTFIX2 = "linux32" if ARCH32 else "linux64" - -# Directories -INSTALLER_DIR = os.path.dirname(os.path.abspath(__file__)) -LINUX_DIR = os.path.abspath(os.path.join(INSTALLER_DIR, "..")) -SRC_DIR = os.path.abspath(os.path.join(LINUX_DIR, "..")) -CEFPYTHON_DIR = os.path.abspath(os.path.join(SRC_DIR, "..")) -BUILD_DIR = os.path.abspath(os.path.join(CEFPYTHON_DIR, "build")) -CEF_BINARY = os.path.abspath(os.path.join(BUILD_DIR, "cef_"+OS_POSTFIX2)) -CEFPYTHON_BINARY = os.path.abspath(os.path.join(BUILD_DIR, - "cefpython_"+OS_POSTFIX2)) - -# Check directories -assert os.path.exists(CEF_BINARY) -assert os.path.exists(CEFPYTHON_BINARY) - -README_FILE = os.getcwd()+r"/README.txt" -INIT_TEMPLATE = os.getcwd()+r"/__init__.py.template" -SETUP_TEMPLATE = os.getcwd()+r"/setup.py.template" -# SETUP_CFG_TEMPLATE = os.getcwd()+r"/setup.cfg.template" - - -def str_format(string, dictionary): - orig_string = string - for key, value in dictionary.items(): - string = string.replace("%("+key+")s", value) - if string == orig_string: - raise Exception("Nothing to format") - if re.search(r"%\([a-zA-Z0-9_]+\)s", string): - raise Exception("Not all strings formatted") - return string - - -def main(): - args = ' '.join(sys.argv) - match = re.search(r"\d+\.\d+", args) - if match: - version = match.group(0) - else: - print("Usage make-setup.py {version}") - sys.exit(1) - - template_vars = dict() - template_vars["APP_VERSION"] = version - template_vars["PLATFORM"] = sysconfig.get_platform() - template_vars["PY_VERSION_DIGITS_ONLY"] = ( - str(sys.version_info.major) + - str(sys.version_info.minor)) # e.g. "27" or "34" - - print("Reading template: %s" % README_FILE) - f = open(README_FILE) - README_CONTENT = f.read() - f.close() - - print("Reading template: %s" % INIT_TEMPLATE) - f = open(INIT_TEMPLATE) - INIT_CONTENT = str_format(f.read(), template_vars) - f.close() - - print("Reading template: %s" % SETUP_TEMPLATE) - f = open(SETUP_TEMPLATE) - SETUP_CONTENT = str_format(f.read(), template_vars) - f.close() - - # print("Reading template: %s" % SETUP_CFG_TEMPLATE) - # f = open(SETUP_CFG_TEMPLATE) - # SETUP_CFG_CONTENT = str_format(f.read(), template_vars) - # f.close() - - setup_dir = (INSTALLER_DIR + "/" + PACKAGE_NAME+"-" + - template_vars["APP_VERSION"] + "-" + OS_POSTFIX2 + "-setup") - print("Creating setup dir: "+setup_dir) - os.mkdir(setup_dir) - - package_dir = setup_dir+"/"+PACKAGE_NAME - print("Creating package dir") - os.mkdir(package_dir) - - print("Copying License file") - shutil.copy("../../../License", package_dir) - - print("Creating README.txt from template") - with open(setup_dir+"/README.txt", "w") as f: - f.write(README_CONTENT) - - print("Creating setup.py from template") - with open(setup_dir+"/setup.py", "w") as f: - f.write(SETUP_CONTENT) - - # print("Creating setup.cfg from template") - # with open(setup_dir+"/setup.cfg", "w") as f: - # f.write(SETUP_CFG_CONTENT) - - print("Copying binaries to package dir") - # Copy Kivy - old_binaries_dir = os.path.abspath(INSTALLER_DIR+"/../binaries_"+BITS+"/") - ret = os.system("cp -rf "+old_binaries_dir+"/kivy_.py "+package_dir) - assert ret == 0 - ret = os.system("cp -rf "+old_binaries_dir+"/kivy-select-boxes/ " - + package_dir) - assert ret == 0 - # Copy binaries - ret = os.system("cp -rf "+CEF_BINARY+"/*.txt "+package_dir) - assert ret == 0 - ret = os.system("cp -rf "+CEF_BINARY+"/bin/* "+package_dir) - assert ret == 0 - ret = os.system("cp -rf "+CEFPYTHON_BINARY+"/* "+package_dir) - assert ret == 0 - - os.chdir(package_dir) - print("Removing .log files from the package dir") - os.system("rm *.log") - # assert ret == 0 - if there are no .log files this assert would fail. - os.chdir(INSTALLER_DIR) - - print("Creating __init__.py from template") - with open(package_dir+"/__init__.py", "w") as f: - f.write(INIT_CONTENT) - - print("Creating examples dir in package dir") - os.mkdir(package_dir+"/examples/") - - print("Copying root examples/ directory") - ret = os.system("rm ../../../examples/*.log") - ret = os.system("cp -r ../../../examples/* "+package_dir+"/examples/") - assert ret == 0 - - print("Moving kivy-select-boxes dir to examples dir") - assert os.path.exists(package_dir+"/kivy-select-boxes") - shutil.move(package_dir+"/kivy-select-boxes", - package_dir+"/examples/kivy-select-boxes") - - print("Creating wx dir in package dir") - os.mkdir(package_dir+"/wx/") - - print("Moving example scripts from package dir to examples dir") - examples = glob.glob(package_dir+"/*.py") - for example in examples: - # Ignore: cefpython_py27.py - dummy API script - if os.path.basename(example).startswith("cefpython_"): - continue - # Ignore: __init__.py - if os.path.basename(example).startswith("__"): - continue - os.rename(example, package_dir+"/examples/"+os.path.basename(example)) - ret = os.system("mv "+package_dir+"/*.html "+package_dir+"/examples/") - # assert ret == 0 - ret = os.system("mv "+package_dir+"/*.js "+package_dir+"/examples/") - # assert ret == 0 - ret = os.system("mv "+package_dir+"/*.css "+package_dir+"/examples/") - # assert ret == 0 - - print("Copying wx/ to package dir") - wx_subpackage_dir = os.path.abspath(INSTALLER_DIR+"/../../cefpython3.wx/") - ret = os.system("cp -rf " + wx_subpackage_dir + "/* " + package_dir - + "/wx/") - assert ret == 0 - - # print("Moving wx examples from wx/examples to examples/wx") - # shutil.move(package_dir+"/wx/examples", package_dir+"/wx/wx/") - # shutil.move(package_dir+"/wx/wx/", package_dir+"/examples/") - - print("Copying package dir examples to setup dir") - ret = os.system("cp -rf "+package_dir+"/examples/ "+setup_dir+"/examples/") - assert ret == 0 - - # Create empty debug.log files so that package uninstalls cleanly - # in case examples were launched. Issue 149. - debug_log_dirs = [package_dir, - package_dir+"/examples/", - # package_dir+"/examples/wx/" - ] - for curdir in debug_log_dirs: - print("Creating empty debug.log in %s" % curdir) - with open(curdir+"/debug.log", "w") as f: - f.write("") - # Set write permissions so that Wheel package files have it - # right. So that examples may be run from package directory. - subprocess.call("chmod 666 %s/debug.log" % curdir, shell=True) - - print("Setup Package created successfully.") - -if __name__ == "__main__": - main() diff --git a/src/linux/installer/setup.cfg.template b/src/linux/installer/setup.cfg.template deleted file mode 100644 index 067dcbfda..000000000 --- a/src/linux/installer/setup.cfg.template +++ /dev/null @@ -1,2 +0,0 @@ -[bdist_wheel] -python-tag=cp%(PY_VERSION_DIGITS_ONLY)s diff --git a/src/linux/installer/setup.py.template b/src/linux/installer/setup.py.template deleted file mode 100644 index 91517037e..000000000 --- a/src/linux/installer/setup.py.template +++ /dev/null @@ -1,104 +0,0 @@ -try: - # The setuptools package is not installed by default - # on a clean Ubuntu. Might be also a case on Windows. - # Python Eggs and Wheels can be created only with setuptools. - from setuptools import setup - from setuptools.command.install import install as _install - from setuptools.dist import Distribution - print("[setup.py] Using setuptools") -except: - from distutils.core import setup - from distutils.command.install import install as _install - from distutils.dist import Distribution - print("[setup.py] Using distutils") - -import sys -import os -import subprocess - -def post_install(): - """ Post install tasks """ - print("[setup.py] post_install()") - - # Find package directory. - # Do not import from local cefpython3/ directory. - del sys.path[0] - sys.path.append('') - import cefpython3 - package_dir = os.path.dirname(cefpython3.__file__) - - # Make sure this is not a local package imported - print("[setup.py] package_dir = %s" % package_dir) - assert not package_dir.startswith( - os.path.dirname(os.path.abspath(__file__))) - - # Execute permissions for subprocess.exe and cefclient.exe - subprocess_exe = os.path.join(package_dir, "subprocess") - cefclient_exe = os.path.join(package_dir, "cefclient") - print("[setup.py] chmod +x " + subprocess_exe) - subprocess.call("chmod +x "+subprocess_exe, shell=True) - print("[setup.py] chmod +x " + cefclient_exe) - subprocess.call("chmod +x "+cefclient_exe, shell=True) - - # Write permissions for debug.log files - commands = [ - "chmod 666 %s/debug.log" % package_dir, - "chmod 666 %s/examples/debug.log" % package_dir, - # "chmod 666 %s/examples/wx/debug.log" % package_dir, - ] - for command in commands: - print("[setup.py] %s" % command) - subprocess.call(command, shell=True) - -class install(_install): - def run(self): - _install.run(self) - post_install() - -class BinaryDistribution(Distribution): - def is_pure(self): - return False - -setup( - distclass=BinaryDistribution, - cmdclass={'install': install}, - name='cefpython3', # No spaces here, so that it works with deb packages. - version='%(APP_VERSION)s', - description='Python bindings for the Chromium Embedded Framework', - license='BSD 3-Clause', - author='Czarek Tomczak', - author_email='czarek.tomczak@gmail.com', - url='http://code.google.com/p/cefpython/', - platforms=['%(PLATFORM)s'], - packages=['cefpython3', 'cefpython3.wx'], - package_data={'cefpython3': [ - 'examples/*.py', - 'examples/*.html', - 'examples/*.js', - 'examples/*.css', - 'examples/*.png', - 'examples/*.txt', - 'examples/kivy-select-boxes/*.html', - 'examples/kivy-select-boxes/*.js', - 'examples/kivy-select-boxes/*.css', - 'examples/kivy-select-boxes/*.md', - 'examples/resources/*.png', - # 'examples/wx/*.py', - # 'examples/wx/*.html', - # 'examples/wx/*.png', - 'locales/*.pak', - 'wx/*.txt', - 'wx/images/*.png', - '*.txt', - 'License', - 'cefclient', - 'subprocess', - '*.so', - '*.pak', - '*.bin', - '*.dat', - 'debug.log', - 'examples/debug.log', - # 'examples/wx/debug.log', - ]} -) diff --git a/src/linux/setup/.gitignore b/src/linux/setup/.gitignore deleted file mode 100644 index a9d6b1b30..000000000 --- a/src/linux/setup/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -build/ -cefpython.cpp -cython_debug/ -*.pyx -*.cpp -lib_64bit/ -lib_32bit/ diff --git a/src/linux/setup/cefpython.h b/src/linux/setup/cefpython.h deleted file mode 100644 index 2bdae4328..000000000 --- a/src/linux/setup/cefpython.h +++ /dev/null @@ -1,103 +0,0 @@ -/* Generated by Cython 0.25.2 */ - -#ifndef __PYX_HAVE__cefpython_py27 -#define __PYX_HAVE__cefpython_py27 - - -#ifndef __PYX_HAVE_API__cefpython_py27 - -#ifndef __PYX_EXTERN_C - #ifdef __cplusplus - #define __PYX_EXTERN_C extern "C" - #else - #define __PYX_EXTERN_C extern - #endif -#endif - -#ifndef DL_IMPORT - #define DL_IMPORT(_T) _T -#endif - -__PYX_EXTERN_C DL_IMPORT(void) PyBrowser_ShowDevTools(CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(void) PyTaskRunnable(int); -__PYX_EXTERN_C DL_IMPORT(void) RemovePythonCallbacksForFrame(int); -__PYX_EXTERN_C DL_IMPORT(bool) ExecutePythonCallback(CefRefPtr , int, CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(bool) CookieVisitor_Visit(int, CefCookie const &, int, int, bool &); -__PYX_EXTERN_C DL_IMPORT(void) StringVisitor_Visit(int, CefString const &); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnUploadProgress(int, CefRefPtr , int64, int64); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnDownloadProgress(int, CefRefPtr , int64, int64); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnDownloadData(int, CefRefPtr , void const *, size_t); -__PYX_EXTERN_C DL_IMPORT(void) WebRequestClient_OnRequestComplete(int, CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(void) App_OnBeforeCommandLineProcessing_BrowserProcess(CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(void) BrowserProcessHandler_OnRenderProcessThreadCreated(CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(void) BrowserProcessHandler_OnBeforeChildProcessLaunch(CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnAddressChange(CefRefPtr , CefRefPtr , CefString const &); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnTitleChange(CefRefPtr , CefString const &); -__PYX_EXTERN_C DL_IMPORT(bool) DisplayHandler_OnTooltip(CefRefPtr , CefString &); -__PYX_EXTERN_C DL_IMPORT(void) DisplayHandler_OnStatusMessage(CefRefPtr , CefString const &); -__PYX_EXTERN_C DL_IMPORT(bool) DisplayHandler_OnConsoleMessage(CefRefPtr , CefString const &, CefString const &, int); -__PYX_EXTERN_C DL_IMPORT(void) FocusHandler_OnTakeFocus(CefRefPtr , bool); -__PYX_EXTERN_C DL_IMPORT(bool) FocusHandler_OnSetFocus(CefRefPtr , cef_focus_source_t); -__PYX_EXTERN_C DL_IMPORT(void) FocusHandler_OnGotFocus(CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(bool) JavascriptDialogHandler_OnJavascriptDialog(CefRefPtr , CefString const &, cef_jsdialog_type_t, CefString const &, CefString const &, CefRefPtr , bool &); -__PYX_EXTERN_C DL_IMPORT(bool) JavascriptDialogHandler_OnBeforeUnloadJavascriptDialog(CefRefPtr , CefString const &, bool, CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(void) JavascriptDialogHandler_OnResetJavascriptDialogState(CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(void) JavascriptDialogHandler_OnJavascriptDialogClosed(CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(bool) KeyboardHandler_OnPreKeyEvent(CefRefPtr , CefKeyEvent const &, CefEventHandle, bool *); -__PYX_EXTERN_C DL_IMPORT(bool) KeyboardHandler_OnKeyEvent(CefRefPtr , CefKeyEvent const &, CefEventHandle); -__PYX_EXTERN_C DL_IMPORT(bool) LifespanHandler_OnBeforePopup(CefRefPtr , CefRefPtr , CefString const &, CefString const &, cef_window_open_disposition_t, bool, int const , CefWindowInfo &, CefRefPtr &, CefBrowserSettings &, bool *); -__PYX_EXTERN_C DL_IMPORT(void) LifespanHandler_OnAfterCreated(CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(bool) LifespanHandler_DoClose(CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(void) LifespanHandler_OnBeforeClose(CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(void) LoadHandler_OnLoadingStateChange(CefRefPtr , bool, bool, bool); -__PYX_EXTERN_C DL_IMPORT(void) LoadHandler_OnLoadStart(CefRefPtr , CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(void) LoadHandler_OnLoadEnd(CefRefPtr , CefRefPtr , int); -__PYX_EXTERN_C DL_IMPORT(void) LoadHandler_OnLoadError(CefRefPtr , CefRefPtr , cef_errorcode_t, CefString const &, CefString const &); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetRootScreenRect(CefRefPtr , CefRect &); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetViewRect(CefRefPtr , CefRect &); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetScreenRect(CefRefPtr , CefRect &); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetScreenPoint(CefRefPtr , int, int, int &, int &); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_GetScreenInfo(CefRefPtr , CefScreenInfo &); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnPopupShow(CefRefPtr , bool); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnPopupSize(CefRefPtr , CefRect const &); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnPaint(CefRefPtr , cef_paint_element_type_t, std::vector &, void const *, int, int); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnCursorChange(CefRefPtr , CefCursorHandle); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_OnScrollOffsetChanged(CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(bool) RenderHandler_StartDragging(CefRefPtr , CefRefPtr , PY_LONG_LONG, int, int); -__PYX_EXTERN_C DL_IMPORT(void) RenderHandler_UpdateDragCursor(CefRefPtr , PY_LONG_LONG); -__PYX_EXTERN_C DL_IMPORT(bool) ResourceHandler_ProcessRequest(int, CefRefPtr , CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(void) ResourceHandler_GetResponseHeaders(int, CefRefPtr , int64 &, CefString &); -__PYX_EXTERN_C DL_IMPORT(bool) ResourceHandler_ReadResponse(int, void *, int, int &, CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(bool) ResourceHandler_CanGetCookie(int, CefCookie const &); -__PYX_EXTERN_C DL_IMPORT(bool) ResourceHandler_CanSetCookie(int, CefCookie const &); -__PYX_EXTERN_C DL_IMPORT(void) ResourceHandler_Cancel(int); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnBeforeBrowse(CefRefPtr , CefRefPtr , CefRefPtr , bool); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnBeforeResourceLoad(CefRefPtr , CefRefPtr , CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(CefRefPtr ) RequestHandler_GetResourceHandler(CefRefPtr , CefRefPtr , CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(void) RequestHandler_OnResourceRedirect(CefRefPtr , CefRefPtr , CefString const &, CefString &, CefRefPtr , CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_GetAuthCredentials(CefRefPtr , CefRefPtr , bool, CefString const &, int, CefString const &, CefString const &, CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnQuotaRequest(CefRefPtr , CefString const &, int64, CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(CefRefPtr ) RequestHandler_GetCookieManager(CefRefPtr , CefString const &); -__PYX_EXTERN_C DL_IMPORT(void) RequestHandler_OnProtocolExecution(CefRefPtr , CefString const &, bool &); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnBeforePluginLoad(CefRefPtr , CefString const &, CefString const &, bool, CefString const &, CefRefPtr , cef_plugin_policy_t *); -__PYX_EXTERN_C DL_IMPORT(bool) RequestHandler_OnCertificateError(int, CefString const &, CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(void) RequestHandler_OnRendererProcessTerminated(CefRefPtr , cef_termination_status_t); -__PYX_EXTERN_C DL_IMPORT(void) RequestHandler_OnPluginCrashed(CefRefPtr , CefString const &); -__PYX_EXTERN_C DL_IMPORT(void) V8ContextHandler_OnContextCreated(CefRefPtr , CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(void) V8ContextHandler_OnContextReleased(int, int64); -__PYX_EXTERN_C DL_IMPORT(void) V8FunctionHandler_Execute(CefRefPtr , CefRefPtr , CefString &, CefRefPtr ); -__PYX_EXTERN_C DL_IMPORT(void) cefpython_GetDebugOptions(bool *, std::string *); -__PYX_EXTERN_C DL_IMPORT(bool) ApplicationSettings_GetBool(char const *); -__PYX_EXTERN_C DL_IMPORT(bool) ApplicationSettings_GetBoolFromDict(char const *, char const *); -__PYX_EXTERN_C DL_IMPORT(std::string) ApplicationSettings_GetString(char const *); -__PYX_EXTERN_C DL_IMPORT(int) CommandLineSwitches_GetInt(char const *); - -#endif /* !__PYX_HAVE_API__cefpython_py27 */ - -#if PY_MAJOR_VERSION < 3 -PyMODINIT_FUNC initcefpython_py27(void); -#else -PyMODINIT_FUNC PyInit_cefpython_py27(void); -#endif - -#endif /* !__PYX_HAVE__cefpython_py27 */ diff --git a/src/linux/setup/fix_pyx_files.py b/src/linux/setup/fix_pyx_files.py deleted file mode 100644 index 9c503ec40..000000000 --- a/src/linux/setup/fix_pyx_files.py +++ /dev/null @@ -1,131 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -# First, it copies all .pyx files from upper directory to setup/. -# Then, fixes repeating of "include" statements in pyx files. - -# Only the mainfile needs to have "include" statements, -# but we're using PyCharm and to get rid of "unresolved references" -# and other errors displayed in pycharm we are adding "include" -# statements in all of the pyx files. - -# I'm not 100% sure how includes work in Cython, but I suspect that -# a few includes of the same file will include the same content more -# than once, it should work, but function and variable definitions are -# duplicated, it is some kind of overhead and it could lead to some -# problems in the future, better to fix it now. - -# It also checks cdef & cpdef functions whether they are not missing "except *", -# it is required to add it when returning non-python type. - -import glob -import os -import re -import shutil -import sys - -def ExceptAllMissing(content): - - # This is not perfect, won't detect C++ custom types, but will find - # the built-in types, templates and pointers. - patterns = [] - patterns.append( - r"\bcp?def\s+" - "((int|short|long|double|char|unsigned|float|double|cpp_bool" - "|cpp_string|cpp_wstring|uint64_t|uintptr_t|void" - "|CefString)\s+)+" - "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") - patterns.append( - r"\bcp?def\s+" - # A template ends with bracket: CefRefPtr[CefBrowser] - # or a pointer ends with asterisk: CefBrowser* - "[^\s]+[\]*]\s+" - "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") - patterns.append( - r"\bcp?def\s+" - # A reference, eg. CefString& - "[^\s]+&\s+" - "\w+\([^)]*\)\s*(with\s+(gil|nogil))?\s*:") - - for pattern in patterns: - match = re.search(pattern, content) - if match: break - - if match: - lineNumber = (content.count("\n", 0, match.start()) + 1) - return lineNumber - -print("\n") -mainfile = "cefpython.pyx" - -pyxfiles = glob.glob("../../*.pyx") -if not len(pyxfiles): - print("ERROR: no .pyx files found in root") - sys.exit(1) -pyxfiles = [file for file in pyxfiles if file.find(mainfile) == -1] -# Now, pyxfiles contains all pyx files except the mainfile (cefpython.pyx), -# we do not fix includes in mainfile. - -pyxfiles2 = glob.glob("../../handlers/*.pyx") -if not len(pyxfiles2): - print("ERROR: no .pyx files found in handlers/") - sys.exit(1) - -pyxfiles = pyxfiles + pyxfiles2 - -# So that this is the right directory we're in. -if os.path.exists("setup"): - print("Wrong directory, we should be inside setup!") - sys.exit(1) - -# Remove old pyx files in setup directory. -oldpyxfiles = glob.glob("./*.pyx") -print("Removing old pyx files in /setup/: %s" % oldpyxfiles) -for pyxfile in oldpyxfiles: - if os.path.exists(pyxfile): - os.remove(pyxfile) - -# Copying pyxfiles and reading its contents. -print("Copying .pyx files to /setup/: %s" % pyxfiles) - -# Copying cefpython.pyx -# and Fix includes in cefpython.pyx -# * include "handlers/focus_handler.pyx" becomes include "focus_handler.pyx" -shutil.copy("../../%s" % mainfile, "./%s" % mainfile) -with open("./%s" % mainfile, "r") as fo: - content = fo.read() - (content, subs) = re.subn(r"^include \"handlers/", - "include \"", - content, - flags=re.MULTILINE) -with open("./%s" % mainfile, "w") as fo: - fo.write(content) - print("%s includes fixed in %s" % (subs, mainfile)) - - -# Rest of the files will be copied in for loop below. - -print("Fixing includes in .pyx files:") -for pyxfile in pyxfiles: - newfile = "./%s" % os.path.basename(pyxfile) - shutil.copy(pyxfile, newfile) - pyxfile = newfile - with open(pyxfile, "r") as pyxfileopened: - content = pyxfileopened.read() - lineNumber = ExceptAllMissing(content) - if lineNumber: - print("WARNING: 'except *' missing in a cdef/cpdef function, " - "in file %s on line %d" % (os.path.basename(pyxfile), lineNumber)) - sys.exit(1) - # Do not remove the newline - so that line numbers are exact with originals. - (content, subs) = re.subn(r"^include[\t ]+[\"'][^\"'\n\r]+[\"'][\t ]*", "", content, flags=re.MULTILINE) - if subs: - print("%s includes removed in: %s" % (subs, os.path.basename(pyxfile))) - # Reading and writing with the same handle using "r+" mode doesn't work, - # you need to seek(0) and write the same amount of bytes that was in the - # file, otherwise old data from the end of file stays. - with open(pyxfile, "w") as pyxfileopened: - pyxfileopened.write(content) - -print("\n") diff --git a/src/linux/setup/setup.py b/src/linux/setup/setup.py deleted file mode 100644 index d06a688fb..000000000 --- a/src/linux/setup/setup.py +++ /dev/null @@ -1,156 +0,0 @@ -from distutils.core import setup -# Use "Extension" from Cython.Distutils so that "cython_directives" works. -# from distutils.extension import Extension -from Cython.Distutils import build_ext, Extension -import sys -import platform -from Cython.Compiler import Options -import Cython -import os -import struct - -print("Cython version: %s" % Cython.__version__) - -if len(sys.argv) > 1 and "--fast" in sys.argv: - sys.argv.remove("--fast") - # Fast mode disables optimization flags - FAST = True - print("FAST mode On") - COMPILE_OPTIMIZE_FLAGS = ['-flto', '-std=gnu++11'] - LINK_OPTIMIZE_FLAGS = ['-flto'] -else: - FAST = False - # Fix "ImportError ... undefined symbol ..." caused by CEF's include/base/ - # headers by adding the -flto flag (Issue #230). Unfortunately -flto - # prolongs compilation time significantly. - # More on the other flags: https://stackoverflow.com/questions/6687630/ - COMPILE_OPTIMIZE_FLAGS = ['-flto', '-fdata-sections', '-ffunction-sections', - '-std=gnu++11'] - LINK_OPTIMIZE_FLAGS = ['-flto', '-Wl,--gc-sections'] - - -# Architecture and OS postfixes -ARCH32 = (8 * struct.calcsize('P') == 32) -ARCH64 = (8 * struct.calcsize('P') == 64) -OS_POSTFIX = ("win" if platform.system() == "Windows" else - "linux" if platform.system() == "Linux" else - "mac" if platform.system() == "Darwin" else "unknown") -OS_POSTFIX2 = "unknown" -if OS_POSTFIX == "win": - OS_POSTFIX2 = "win32" if ARCH32 else "win64" -elif OS_POSTFIX == "mac": - OS_POSTFIX2 = "mac32" if ARCH32 else "mac64" -elif OS_POSTFIX == "linux": - OS_POSTFIX2 = "linux32" if ARCH32 else "linux64" - -# Directories -SETUP_DIR = os.path.abspath(os.path.dirname(__file__)) -LINUX_DIR = os.path.abspath(os.path.join(SETUP_DIR, "..")) -SRC_DIR = os.path.abspath(os.path.join(LINUX_DIR, "..")) -CEFPYTHON_DIR = os.path.abspath(os.path.join(SRC_DIR, "..")) -BUILD_DIR = os.path.abspath(os.path.join(CEFPYTHON_DIR, "build")) -CEF_BINARY = os.path.abspath(os.path.join(BUILD_DIR, "cef_"+OS_POSTFIX2)) -CEFPYTHON_BINARY = os.path.abspath(os.path.join(BUILD_DIR, - "cefpython_"+OS_POSTFIX2)) - -# Stop on first error, otherwise hundreds of errors appear in the console. -Options.fast_fail = True - -# Python version string: "27" or "32". -PYTHON_VERSION = str(sys.version_info.major) + str(sys.version_info.minor) - - -def CompileTimeConstants(): - - print("Generating: compile_time_constants.pxi") - with open("./../../compile_time_constants.pxi", "w") as fd: - fd.write('# This file was generated by setup.py\n') - # A way around Python 3.2 bug: UNAME_SYSNAME is not set. - fd.write('DEF UNAME_SYSNAME = "%s"\n' % platform.uname()[0]) - fd.write('DEF PY_MAJOR_VERSION = %s\n' % sys.version_info.major) - -CompileTimeConstants() - -ext_modules = [Extension( - - "cefpython_py%s" % PYTHON_VERSION, - ["cefpython.pyx"], - - # Ignore the warning in the console: - # > C:\Python27\lib\distutils\extension.py:133: UserWarning: - # > Unknown Extension options: 'cython_directives' warnings.warn(msg) - cython_directives={ - # Any conversion to unicode must be explicit using .decode(). - "c_string_type": "bytes", - "c_string_encoding": "utf-8", - }, - - language='c++', - include_dirs=[ - r'./../', - r'./../../', - r'./../../common/', - r'./../../extern/', - r'./../../extern/cef/', - '/usr/include/gtk-2.0', - '/usr/include/glib-2.0', - '/usr/include/gtk-unix-print-2.0', - '/usr/include/cairo', - '/usr/include/pango-1.0', - '/usr/include/gdk-pixbuf-2.0', - '/usr/include/atk-1.0', - # Ubuntu - '/usr/lib/x86_64-linux-gnu/gtk-2.0/include', - '/usr/lib/x86_64-linux-gnu/gtk-unix-print-2.0', - '/usr/lib/x86_64-linux-gnu/glib-2.0/include', - '/usr/lib/i386-linux-gnu/gtk-2.0/include', - '/usr/lib/i386-linux-gnu/gtk-unix-print-2.0', - '/usr/lib/i386-linux-gnu/glib-2.0/include', - # Fedora - '/usr/lib64/gtk-2.0/include', - '/usr/lib64/gtk-unix-print-2.0', - '/usr/lib64/glib-2.0/include', - '/usr/lib/gtk-2.0/include', - '/usr/lib/gtk-2.0/gtk-unix-print-2.0', - '/usr/lib/glib-2.0/include', - ], - - library_dirs=[ - os.path.join(CEF_BINARY, "lib"), - r'./../../client_handler/', - r'./../../subprocess/', # libcefpythonapp - r'./../../cpp_utils/' - ], - - # Static libraries only. Order is important, if library A depends on B, - # then B must be included before A. - libraries=[ - 'X11', - 'gobject-2.0', - 'glib-2.0', - 'gtk-x11-2.0', - # CEF and CEF Python libraries - 'cef_dll_wrapper', - 'cefpythonapp', - 'client_handler', - 'cpp_utils', - ], - - # When you put "./" in here, loading of libcef.so will only work when - # running scripts from the same directory that libcef.so resides in. - # runtime_library_dirs=[ - # './' - # ], - - extra_compile_args=COMPILE_OPTIMIZE_FLAGS, - extra_link_args=LINK_OPTIMIZE_FLAGS, - - # Defining macros: - # define_macros = [("UNICODE","1"), ("_UNICODE","1"), ] -)] - -setup( - name='cefpython_py%s' % PYTHON_VERSION, - cmdclass={'build_ext': build_ext}, - ext_modules=ext_modules -) diff --git a/src/windows/deprecated_32bit/LICENSE.txt b/src/windows/deprecated_32bit/LICENSE.txt deleted file mode 100644 index 45e6f23ea..000000000 --- a/src/windows/deprecated_32bit/LICENSE.txt +++ /dev/null @@ -1,39 +0,0 @@ -Copyright (c) 2012 The CEF Python authors. All rights -reserved. Website: http://code.google.com/p/cefpython/ - -This product includes the following third party libraries: -* Chromium Embedded Framework licensed under the BSD 3-clause - license. Website: http://code.google.com/p/chromiumembedded/ - -Redistribution and use in source and binary forms, with -or without modification, are permitted provided that the -following conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of Google Inc. nor the name Chromium - Embedded Framework nor the name of CEF Python nor the - names of its contributors may be used to endorse or - promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/windows/deprecated_32bit/README.txt b/src/windows/deprecated_32bit/README.txt deleted file mode 100644 index 73fbae0cf..000000000 --- a/src/windows/deprecated_32bit/README.txt +++ /dev/null @@ -1,119 +0,0 @@ -Chromium Embedded Framework (CEF) Standard Binary Distribution for Windows -------------------------------------------------------------------------------- - -Date: August 08, 2014 - -CEF Version: 3.1650.1646 -CEF URL: http://chromiumembedded.googlecode.com/svn/branches/1650/cef3@1646 - -Chromium Verison: 31.0.1650.69 -Chromium URL: http://src.chromium.org/svn/branches/1650/src@241641 - -This distribution contains all components necessary to build and distribute an -application using CEF on the Windows platform. Please see the LICENSING -section of this document for licensing terms and conditions. - - -CONTENTS --------- - -cefclient Contains the cefclient sample application configured to build - using the files in this distribution. - -Debug Contains libcef.dll, libcef.lib and other components required to - build and run the debug version of CEF-based applications. By - default these files should be placed in the same directory as the - executable and will be copied there as part of the build process. - -include Contains all required CEF header files. - -libcef_dll Contains the source code for the libcef_dll_wrapper static library - that all applications using the CEF C++ API must link against. - -Release Contains libcef.dll, libcef.lib and other components required to - build and run the release version of CEF-based applications. By - default these files should be placed in the same directory as the - executable and will be copied there as part of the build process. - -Resources Contains resources required by libcef.dll. By default these files - should be placed in the same directory as libcef.dll. By default - these files should be placed in the same directory as libcef.dll - and will be copied there as part of the build process. - - -USAGE ------ - -Visual Studio 2012 and Visual Studio 2010: - Open the cefclient2010.sln solution in Visual Studio and build. - -Visual Studio 2008: - Open the cefclient2008.sln solution in Visual Studio and build. - -Visual Studio 2005: - 1. Open the cefclient.vcproj and libcef_dll_wrapper.vcproj files in a text - editor. Change Version="9.00" to Version="8.00". - 2. Open the cefclient2005.sln file in a text editor. Change "Version 9.00" to - "Version 8.00". - 3. Open the cefclient2005.sln solution in Visual Studio and build. - -Please visit the CEF Website for additional usage information. - -http://code.google.com/p/chromiumembedded - - -REDISTRIBUTION --------------- - -This binary distribution contains the below components. Components listed under -the "required" section must be redistributed with all applications using CEF. -Components listed under the "optional" section may be excluded if the related -features will not be used. - -Required components: - -* CEF core library - libcef.dll - -* Unicode support - icudt.dll - -Optional components: - -* Localized resources - locales/ - Note: Contains localized strings for WebKit UI controls. A .pak file is loaded - from this folder based on the CefSettings.locale value. Only configured - locales need to be distributed. If no locale is configured the default locale - of "en-US" will be used. Locale file loading can be disabled completely using - CefSettings.pack_loading_disabled. The locales folder path can be customized - using CefSettings.locales_dir_path. - -* Other resources - cef.pak - devtools_resources.pak - Note: Contains WebKit image and inspector resources. Pack file loading can be - disabled completely using CefSettings.pack_loading_disabled. The resources - directory path can be customized using CefSettings.resources_dir_path. - -* FFmpeg audio and video support - ffmpegsumo.dll - Note: Without this component HTML5 audio and video will not function. - -* Angle and Direct3D support - d3dcompiler_43.dll (required for Windows XP) - d3dcompiler_46.dll (required for Windows Vista and newer) - libEGL.dll - libGLESv2.dll - Note: Without these components HTML5 accelerated content like 2D canvas, 3D - CSS and WebGL will not function. - - -LICENSING ---------- - -The CEF project is BSD licensed. Please read the LICENSE.txt file included with -this binary distribution for licensing terms and conditions. Other software -included in this distribution is provided under other licenses. Please visit -"about:credits" in a CEF-based application for complete Chromium and third-party -licensing information. diff --git a/src/windows/deprecated_32bit/cefwindow.py b/src/windows/deprecated_32bit/cefwindow.py deleted file mode 100644 index fd0ac73ea..000000000 --- a/src/windows/deprecated_32bit/cefwindow.py +++ /dev/null @@ -1,205 +0,0 @@ -# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved. -# License: New BSD License. -# Website: http://code.google.com/p/cefpython/ - -import win32gui -import win32con -import win32api -import time -import math -import os -import sys -import re - -if sys.version_info.major == 2: - from urllib import pathname2url as urllib_pathname2url -else: - from urllib.request import pathname2url as urllib_pathname2url - -g_debug = False -g_windows = {} # windowID(int): className -g_registeredClasses = {} - -def Debug(msg): - - if not g_debug: - return - msg = "cefwindow: "+str(msg) - print(msg) - with open(GetRealPath("debug.log"), "a") as file: - file.write(msg+"\n") - -def GetRealPath(file=None, encodeURL=False): - - # This function is defined in 2 files: cefpython.pyx and cefwindow.py, if you make changes edit both files. - # If file is None return current directory, without trailing slash. - - # encodeURL param - will call urllib.pathname2url(), only when file is empty (current dir) - # or is relative path ("test.html", "some/test.html"), we need to encode it before passing - # to CreateBrowser(), otherwise it is encoded by CEF internally and becomes (chinese characters): - # >> %EF%BF%97%EF%BF%80%EF%BF%83%EF%BF%A6 - # but should be: - # >> %E6%A1%8C%E9%9D%A2 - - if file is None: file = "" - if file.find("/") != 0 and file.find("\\") != 0 and not re.search(r"^[a-zA-Z]+:[/\\]?", file): - # Execute this block only when relative path ("test.html", "some\test.html") or file is empty (current dir). - # 1. find != 0 >> not starting with / or \ (/ - linux absolute path, \ - just to be sure) - # 2. not re.search >> not (D:\\ or D:/ or D: or http:// or ftp:// or file://), - # "D:" is also valid absolute path ("D:cefpython" in chrome becomes "file:///D:/cefpython/") - if hasattr(sys, "frozen"): path = os.path.dirname(sys.executable) - elif "__file__" in globals(): path = os.path.dirname(os.path.realpath(__file__)) - else: path = os.getcwd() - path = path + os.sep + file - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) # directory without trailing slash. - if encodeURL: - return urllib_pathname2url(path) - else: - return path - return file - -def CreateWindow(title, className, width, height, xpos=None, ypos=None, icon=None, windowProc=None): - - """ - for key in g_windows: - if g_windows[key] == className: - raise Exception("There was already created a window with that className: %s." - "Each created window must have an unique className." % className) - """ - - if not windowProc: - windowProc = {win32con.WM_CLOSE: WM_CLOSE} - - bigIcon = "" - smallIcon = "" - - if icon: - icon = GetRealPath(icon) - - # Load small and big icon. - # WNDCLASSEX (along with hIconSm) is not supported by pywin32, - # we need to use WM_SETICON message after window creation. - - # http://stackoverflow.com/questions/2234988/how-to-set-hicon-on-a-window-ico-with-multiple-sizes - # http://blog.barthe.ph/2009/07/17/wmseticon/ - - bigX = win32api.GetSystemMetrics(win32con.SM_CXICON) - bigY = win32api.GetSystemMetrics(win32con.SM_CYICON) - bigIcon = win32gui.LoadImage(0, icon, win32con.IMAGE_ICON, bigX, bigY, win32con.LR_LOADFROMFILE) - smallX = win32api.GetSystemMetrics(win32con.SM_CXSMICON) - smallY = win32api.GetSystemMetrics(win32con.SM_CYSMICON) - smallIcon = win32gui.LoadImage(0, icon, win32con.IMAGE_ICON, smallX, smallY, win32con.LR_LOADFROMFILE) - - wndclass = win32gui.WNDCLASS() - wndclass.hInstance = win32api.GetModuleHandle(None) - wndclass.lpszClassName = className - wndclass.style = win32con.CS_VREDRAW | win32con.CS_HREDRAW - # win32con.CS_GLOBALCLASS - wndclass.hbrBackground = win32con.COLOR_WINDOW - wndclass.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW) - wndclass.lpfnWndProc = windowProc - - #noinspection PyUnusedLocal - global g_registeredClasses - if not className in g_registeredClasses: - g_registeredClasses[className] = True - atomclass = win32gui.RegisterClass(wndclass) - Debug("win32gui.RegisterClass(%s)" % className) - - if xpos is None or ypos is None: - # Center window on the screen. - Debug("Centering window on the screen.") - screenx = win32api.GetSystemMetrics(win32con.SM_CXSCREEN) - screeny = win32api.GetSystemMetrics(win32con.SM_CYSCREEN) - xpos = int(math.floor((screenx - width) / 2)) - ypos = int(math.floor((screeny - height) / 2)) - if xpos < 0: xpos = 0 - if ypos < 0: ypos = 0 - - windowID = win32gui.CreateWindow(className, title, - win32con.WS_OVERLAPPEDWINDOW | win32con.WS_CLIPCHILDREN | win32con.WS_VISIBLE, - xpos, ypos, width, height, # xpos, ypos, width, height - 0, 0, wndclass.hInstance, None) - g_windows[windowID] = className - - if icon: - if bigIcon: - win32api.SendMessage(windowID, win32con.WM_SETICON, win32con.ICON_BIG, bigIcon) - if smallIcon: - win32api.SendMessage(windowID, win32con.WM_SETICON, win32con.ICON_SMALL, smallIcon) - - Debug("windowID = %s" % windowID) - return windowID - - -# Memory error when calling win32gui.DestroyWindow() -# after we called cefpython.CloseBrowser() - -def DestroyWindow(windowID): - - win32gui.DestroyWindow(windowID) - #className = GetWindowClassName(windowID) - #win32gui.UnregisterClass(className, None) - #del g_windows[windowID] # Let window with this className be created again. - - -def GetWindowClassName(windowID): - - for key in g_windows: - if key == windowID: - return g_windows[key] - -def MoveWindow(windowID, xpos=None, ypos=None, width=None, height=None, center=None): - - (left, top, right, bottom) = win32gui.GetWindowRect(windowID) - if xpos is None and ypos is None: - xpos = left - ypos = top - if width is None and height is None: - width = right - left - height = bottom - top - # Case: only ypos provided - if xpos is None and ypos is not None: - xpos = left - if ypos is None and xpos is not None: - ypos = top - # Case: only height provided - if not width: - width = right - left - if not height: - height = bottom - top - if center: - screenx = win32api.GetSystemMetrics(win32con.SM_CXSCREEN) - screeny = win32api.GetSystemMetrics(win32con.SM_CYSCREEN) - xpos = int(math.floor((screenx - width) / 2)) - ypos = int(math.floor((screeny - height) / 2)) - if xpos < 0: xpos = 0 - if ypos < 0: ypos = 0 - win32gui.MoveWindow(windowID, xpos, ypos, width, height, 1) - - -#noinspection PyUnusedLocal -def WM_CLOSE(windowID, msg, wparam, lparam): - - DestroyWindow(windowID) - win32gui.PostQuitMessage(0) - - -def GetLastError(): - - code = win32api.GetLastError() - return "(%d) %s" % (code, win32api.FormatMessage(code)) - -#noinspection PyUnusedLocal -def MessageLoop(className): - - while not win32gui.PumpWaitingMessages(): - time.sleep(0.001) - - -if __name__ == "__main__": - - g_debug = True - hwnd = CreateWindow("Test window", "testwindow", 800, 600) - MessageLoop("testwindow") \ No newline at end of file diff --git a/src/windows/deprecated_32bit/example.html b/src/windows/deprecated_32bit/example.html deleted file mode 100644 index 96bbac9b3..000000000 --- a/src/windows/deprecated_32bit/example.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - - CEF Python 3 example (utf-8: ąś) - - - - - - -

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

      - - - -

      Google Search

      -https://www.google.com/ - - - -

      User agent

      - - - - -

      Popup

      - - window.open('example.html') - - - -

      HTML5 video and accelerated content

      - -HTML 5 video
      - -Accelerated canvas
      - -Accelerated layers
      - - - -

      Advanced example

      - -See the wxpython.py script for an advanced usage of CEF Python 3 -features - including javascript bindings, js and python callbacks, -client handlers and others. - - -



      -



      -



      -



      - - - diff --git a/src/windows/deprecated_32bit/icon.ico b/src/windows/deprecated_32bit/icon.ico deleted file mode 100644 index 435045aec271dc2677d61810be947aa2420cd76d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 198275 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 Jm0$eg{{a!zwfz79 diff --git a/src/windows/deprecated_32bit/prism.css b/src/windows/deprecated_32bit/prism.css deleted file mode 100644 index f94cca7c0..000000000 --- a/src/windows/deprecated_32bit/prism.css +++ /dev/null @@ -1,130 +0,0 @@ -/* http://prismjs.com/download.html?themes=prism&languages=clike+javascript+python */ -/** - * prism.js default theme for JavaScript, CSS and HTML - * Based on dabblet (http://dabblet.com) - * @author Lea Verou - */ - -code[class*="language-"], -pre[class*="language-"] { - color: black; - text-shadow: 0 1px white; - font-family: Consolas, Monaco, 'Andale Mono', monospace; - direction: ltr; - text-align: left; - white-space: pre; - word-spacing: normal; - word-break: normal; - - - -moz-tab-size: 4; - -o-tab-size: 4; - tab-size: 4; - - -webkit-hyphens: none; - -moz-hyphens: none; - -ms-hyphens: none; - hyphens: none; -} - -pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, -code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { - text-shadow: none; - background: #b3d4fc; -} - -pre[class*="language-"]::selection, pre[class*="language-"] ::selection, -code[class*="language-"]::selection, code[class*="language-"] ::selection { - text-shadow: none; - background: #b3d4fc; -} - -@media print { - code[class*="language-"], - pre[class*="language-"] { - text-shadow: none; - } -} - -/* Code blocks */ -pre[class*="language-"] { - padding: 1em; - margin: .5em 0; - overflow: auto; -} - -:not(pre) > code[class*="language-"], -pre[class*="language-"] { - background: #f5f2f0; -} - -/* Inline code */ -:not(pre) > code[class*="language-"] { - padding: .1em; - border-radius: .3em; -} - -.token.comment, -.token.prolog, -.token.doctype, -.token.cdata { - color: slategray; -} - -.token.punctuation { - color: #999; -} - -.namespace { - opacity: .7; -} - -.token.property, -.token.tag, -.token.boolean, -.token.number, -.token.constant, -.token.symbol { - color: #905; -} - -.token.selector, -.token.attr-name, -.token.string, -.token.builtin { - color: #690; -} - -.token.operator, -.token.entity, -.token.url, -.language-css .token.string, -.style .token.string, -.token.variable { - color: #a67f59; - background: hsla(0,0%,100%,.5); -} - -.token.atrule, -.token.attr-value, -.token.keyword { - color: #07a; -} - -.token.function { - color: #DD4A68; -} - -.token.regex, -.token.important { - color: #e90; -} - -.token.important { - font-weight: bold; -} - -.token.entity { - cursor: help; -} - diff --git a/src/windows/deprecated_32bit/prism.js b/src/windows/deprecated_32bit/prism.js deleted file mode 100644 index ebaa4b428..000000000 --- a/src/windows/deprecated_32bit/prism.js +++ /dev/null @@ -1,5 +0,0 @@ -/* http://prismjs.com/download.html?themes=prism&languages=clike+javascript+python */ -self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{};var Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content)):"Array"===t.util.type(e)?e.map(t.util.encode):e.replace(/&/g,"&").replace(/e.length)break e;if(!(f instanceof r)){l.lastIndex=0;var h=l.exec(f);if(h){c&&(g=h[1].length);var d=h.index-1+g,h=h[0].slice(g),p=h.length,m=d+p,v=f.slice(0,d+1),y=f.slice(m+1),k=[u,1];v&&k.push(v);var b=new r(o,s?t.tokenize(h,s):h);k.push(b),y&&k.push(y),Array.prototype.splice.apply(a,k)}}}}return a},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[],r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(r&&r.length)for(var a,i=0;a=r[i++];)a(n)}}},n=t.Token=function(e,t){this.type=e,this.content=t};if(n.stringify=function(e,r,a){if("string"==typeof e)return e;if("[object Array]"==Object.prototype.toString.call(e))return e.map(function(t){return n.stringify(t,r,e)}).join("");var i={type:e.type,content:n.stringify(e.content,r,a),tag:"span",classes:["token",e.type],attributes:{},language:r,parent:a};"comment"==i.type&&(i.attributes.spellcheck="true"),t.hooks.run("wrap",i);var o="";for(var l in i.attributes)o+=l+'="'+(i.attributes[l]||"")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'" '+o+">"+i.content+""},!self.document)return self.addEventListener?(self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,a=n.code;self.postMessage(JSON.stringify(t.tokenize(a,t.languages[r]))),self.close()},!1),self.Prism):self.Prism;var r=document.getElementsByTagName("script");return r=r[r.length-1],r&&(t.filename=r.src,document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)),self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism);; -Prism.languages.clike={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,lookbehind:!0},string:/("|')(\\?.)*?\1/g,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/gi,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g,"boolean":/\b(true|false)\b/g,"function":{pattern:/[a-z0-9_]+\(/gi,inside:{punctuation:/\(/}},number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,operator:/[-+]{1,2}|!|<=?|>=?|={1,3}|&{1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};; -Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|function|get|if|implements|import|in|instanceof|interface|let|new|null|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,lookbehind:!0}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/[\w\W]*?<\/script>/gi,inside:{tag:{pattern:/|<\/script>/gi,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}});; -Prism.languages.python={comment:{pattern:/(^|[^\\])#.*?(\r?\n|$)/g,lookbehind:!0},string:/"""[\s\S]+?"""|("|')(\\?.)*?\1/g,keyword:/\b(as|assert|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/g,"boolean":/\b(True|False)\b/g,number:/\b-?(0x)?\d*\.?[\da-f]+\b/g,operator:/[-+]{1,2}|=?<|=?>|!|={1,2}|(&){1,2}|(&){1,2}|\|?\||\?|\*|\/|~|\^|%|\b(or|and|not)\b/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};; diff --git a/src/windows/deprecated_32bit/pygtk_.py b/src/windows/deprecated_32bit/pygtk_.py deleted file mode 100644 index 85e4d4f75..000000000 --- a/src/windows/deprecated_32bit/pygtk_.py +++ /dev/null @@ -1,196 +0,0 @@ -# An example of embedding CEF browser in PyGTK on Windows. -# Tested with PyGTK 2.24.10 - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import a local module - if (2,7) <= sys.version_info < (2,8): - import cefpython_py27 as cefpython - elif (3,4) <= sys.version_info < (3,4): - import cefpython_py34 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import an installed package - from cefpython3 import cefpython - -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("[pygtk_.py]: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class PyGTKExample: - mainWindow = None - container = None - browser = None - exiting = None - searchEntry = None - - def __init__(self): - gobject.timeout_add(10, self.OnTimer) - - self.mainWindow = gtk.Window(gtk.WINDOW_TOPLEVEL) - self.mainWindow.connect('destroy', self.OnExit) - self.mainWindow.set_size_request(width=1024, height=768) - self.mainWindow.set_title('PyGTK CEF 3 example') - self.mainWindow.realize() - - self.container = gtk.DrawingArea() - self.container.set_property('can-focus', True) - self.container.connect('size-allocate', self.OnSize) - self.container.show() - - self.searchEntry = gtk.Entry() - # By default, clicking a GTK widget doesn't grab the focus away from a native Win32 control (browser). - self.searchEntry.connect('button-press-event', self.OnWidgetClick) - self.searchEntry.show() - - table = gtk.Table(3, 1, homogeneous=False) - self.mainWindow.add(table) - table.attach(self.CreateMenu(), 0, 1, 0, 1, yoptions=gtk.SHRINK) - table.attach(self.searchEntry, 0, 1, 1, 2, yoptions=gtk.SHRINK) - table.attach(self.container, 0, 1, 2, 3) - table.show() - - windowID = self.container.get_window().handle - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(windowID) - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings={}, - navigateUrl=GetApplicationPath('example.html')) - - self.mainWindow.show() - - # Browser took focus, we need to get it back and give to searchEntry. - self.mainWindow.get_window().focus() - self.searchEntry.grab_focus() - - def CreateMenu(self): - file = gtk.MenuItem('File') - file.show() - filemenu = gtk.Menu() - item = gtk.MenuItem('Open') - filemenu.append(item) - item.show() - item = gtk.MenuItem('Exit') - filemenu.append(item) - item.show() - file.set_submenu(filemenu) - about = gtk.MenuItem('About') - about.show() - menubar = gtk.MenuBar() - menubar.append(file) - menubar.append(about) - menubar.show() - return menubar - - def OnWidgetClick(self, widget, data): - self.mainWindow.get_window().focus() - - def OnTimer(self): - if self.exiting: - return False - cefpython.MessageLoopWork() - return True - - def OnFocusIn(self, widget, data): - # This function is currently not called by any of code, but if you would like - # for browser to have automatic focus add such line: - # self.mainWindow.connect('focus-in-event', self.OnFocusIn) - cefpython.WindowUtils.OnSetFocus(self.container.get_window().handle, 0, 0, 0) - - def OnSize(self, widget, sizeAlloc): - cefpython.WindowUtils.OnSize(self.container.get_window().handle, 0, 0, 0) - - def OnExit(self, widget, data=None): - self.exiting = True - gtk.main_quit() - -if __name__ == '__main__': - version = '.'.join(map(str, list(gtk.gtk_version))) - print('[pygtk_.py] GTK version: %s' % version) - - # Intercept python exceptions. Exit app immediately when exception - # happens on any of the threads. - sys.excepthook = ExceptHook - - # Application settings - settings = { - "debug": True, # cefpython debug messages in console and in log_file - "log_severity": cefpython.LOGSEVERITY_INFO, # LOGSEVERITY_VERBOSE - "log_file": GetApplicationPath("debug.log"), # Set to "" to disable - # This directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory(), - "browser_subprocess_path": "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess"), - } - - cefpython.Initialize(settings) - - gobject.threads_init() # Timer for the message loop - PyGTKExample() - gtk.main() - - cefpython.Shutdown() diff --git a/src/windows/deprecated_32bit/pyqt.py b/src/windows/deprecated_32bit/pyqt.py deleted file mode 100644 index ae7d7a850..000000000 --- a/src/windows/deprecated_32bit/pyqt.py +++ /dev/null @@ -1,190 +0,0 @@ -# An example of embedding CEF browser in a PyQt4 application. -# Tested with PyQt 4.10.3 (Qt 4.8.5). - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import a local module - if (2,7) <= sys.version_info < (2,8): - import cefpython_py27 as cefpython - elif (3,4) <= sys.version_info < (3,4): - import cefpython_py34 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import an installed package - from cefpython3 import cefpython - -from PyQt4 import QtGui -from PyQt4 import QtCore - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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" (os._exit()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("[pyqt.py] WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainWindow(QtGui.QMainWindow): - mainFrame = None - - def __init__(self): - super(MainWindow, self).__init__(None) - self.createMenu() - self.mainFrame = MainFrame(self) - self.setCentralWidget(self.mainFrame) - self.resize(1024, 768) - self.setWindowTitle('PyQT CEF 3 example') - self.setFocusPolicy(QtCore.Qt.StrongFocus) - - def createMenu(self): - menubar = self.menuBar() - filemenu = menubar.addMenu("&File") - filemenu.addAction(QtGui.QAction("Open", self)) - filemenu.addAction(QtGui.QAction("Exit", self)) - aboutmenu = menubar.addMenu("&About") - - def focusInEvent(self, event): - cefpython.WindowUtils.OnSetFocus(int(self.centralWidget().winId()), 0, 0, 0) - - def closeEvent(self, event): - self.mainFrame.browser.CloseBrowser() - -class MainFrame(QtGui.QWidget): - browser = None - - def __init__(self, parent=None): - super(MainFrame, self).__init__(parent) - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(int(self.winId())) - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings={}, - navigateUrl=GetApplicationPath("example.html")) - self.show() - - def moveEvent(self, event): - cefpython.WindowUtils.OnSize(int(self.winId()), 0, 0, 0) - - def resizeEvent(self, event): - cefpython.WindowUtils.OnSize(int(self.winId()), 0, 0, 0) - -class CefApplication(QtGui.QApplication): - timer = None - - def __init__(self, args): - super(CefApplication, self).__init__(args) - self.createTimer() - - def createTimer(self): - self.timer = QtCore.QTimer() - self.timer.timeout.connect(self.onTimer) - self.timer.start(10) - - def onTimer(self): - # The proper way of doing message loop should be: - # 1. In createTimer() call self.timer.start(0) - # 2. In onTimer() call MessageLoopWork() only when - # QtGui.QApplication.instance()->hasPendingEvents() returns False. - # But... there is a bug in Qt, hasPendingEvents() returns always true. - cefpython.MessageLoopWork() - - def stopTimer(self): - # Stop the timer after Qt message loop ended, calls to MessageLoopWork() - # should not happen anymore. - self.timer.stop() - -if __name__ == '__main__': - print("[pyqt.py] PyQt version: %s" % QtCore.PYQT_VERSION_STR) - print("[pyqt.py] QtCore version: %s" % QtCore.qVersion()) - - # Intercept python exceptions. Exit app immediately when exception - # happens on any of the threads. - sys.excepthook = ExceptHook - - # Application settings - settings = { - # "cache_path": "webcache/", # Disk cache - "debug": True, # cefpython debug messages in console and in log_file - "log_severity": cefpython.LOGSEVERITY_INFO, # LOGSEVERITY_VERBOSE - "log_file": GetApplicationPath("debug.log"), # Set to "" to disable. - # This directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory(), - "browser_subprocess_path": "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess") - } - - # Command line switches set programmatically - switches = { - # "proxy-server": "socks5://127.0.0.1:8888", - # "enable-media-stream": "", - # "--invalid-switch": "" -> Invalid switch name - } - - cefpython.Initialize(settings, switches) - - app = CefApplication(sys.argv) - mainWindow = MainWindow() - mainWindow.show() - app.exec_() - app.stopTimer() - - # Need to destroy QApplication(), otherwise Shutdown() fails. - # Unset main window also just to be safe. - del mainWindow - del app - - cefpython.Shutdown() diff --git a/src/windows/deprecated_32bit/pyside.py b/src/windows/deprecated_32bit/pyside.py deleted file mode 100644 index 9a5f68fe0..000000000 --- a/src/windows/deprecated_32bit/pyside.py +++ /dev/null @@ -1,188 +0,0 @@ -# An example of embedding CEF Python in PySide application. - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import a local module - if (2,7) <= sys.version_info < (2,8): - import cefpython_py27 as cefpython - elif (3,4) <= sys.version_info < (3,4): - import cefpython_py34 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import an installed package - from cefpython3 import cefpython - -import PySide -from PySide import QtGui -from PySide import QtCore -import ctypes - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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" (os._exit()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("cefpython: WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainWindow(QtGui.QMainWindow): - mainFrame = None - - def __init__(self): - super(MainWindow, self).__init__(None) - self.createMenu() - self.mainFrame = MainFrame(self) - self.setCentralWidget(self.mainFrame) - self.resize(1024, 768) - self.setWindowTitle('PySide example') - self.setFocusPolicy(QtCore.Qt.StrongFocus) - - def createMenu(self): - menubar = self.menuBar() - filemenu = menubar.addMenu("&File") - filemenu.addAction(QtGui.QAction("Open", self)) - filemenu.addAction(QtGui.QAction("Exit", self)) - aboutmenu = menubar.addMenu("&About") - - def focusInEvent(self, event): - cefpython.WindowUtils.OnSetFocus(int(self.centralWidget().winIdFixed()), 0, 0, 0) - - def closeEvent(self, event): - self.mainFrame.browser.CloseBrowser() - -class MainFrame(QtGui.QWidget): - browser = None - - def __init__(self, parent=None): - super(MainFrame, self).__init__(parent) - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(int(self.winIdFixed())) - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings={}, - navigateUrl=GetApplicationPath("example.html")) - self.show() - - def winIdFixed(self): - # PySide bug: QWidget.winId() returns , - # there is no easy way to convert it to int. - try: - return int(self.winId()) - except: - if sys.version_info[0] == 2: - ctypes.pythonapi.PyCObject_AsVoidPtr.restype = ctypes.c_void_p - ctypes.pythonapi.PyCObject_AsVoidPtr.argtypes = [ctypes.py_object] - return ctypes.pythonapi.PyCObject_AsVoidPtr(self.winId()) - elif sys.version_info[0] == 3: - ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p - ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object] - return ctypes.pythonapi.PyCapsule_GetPointer(self.winId(), None) - - def moveEvent(self, event): - cefpython.WindowUtils.OnSize(int(self.winIdFixed()), 0, 0, 0) - - def resizeEvent(self, event): - cefpython.WindowUtils.OnSize(int(self.winIdFixed()), 0, 0, 0) - -class CefApplication(QtGui.QApplication): - timer = None - - def __init__(self, args): - super(CefApplication, self).__init__(args) - self.createTimer() - - def createTimer(self): - self.timer = QtCore.QTimer() - self.timer.timeout.connect(self.onTimer) - self.timer.start(10) - - def onTimer(self): - # The proper way of doing message loop should be: - # 1. In createTimer() call self.timer.start(0) - # 2. In onTimer() call MessageLoopWork() only when - # QtGui.QApplication.instance()->hasPendingEvents() returns False. - # But... there is a bug in Qt, hasPendingEvents() returns always true. - cefpython.MessageLoopWork() - - def stopTimer(self): - # Stop the timer after Qt message loop ended, calls to MessageLoopWork() - # should not happen anymore. - self.timer.stop() - -if __name__ == '__main__': - print("PySide version: %s" % PySide.__version__) - print("QtCore version: %s" % QtCore.__version__) - - sys.excepthook = ExceptHook - settings = {} - settings["log_file"] = GetApplicationPath("debug.log") - settings["log_severity"] = cefpython.LOGSEVERITY_INFO - settings["browser_subprocess_path"] = "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess") - cefpython.Initialize(settings) - - app = CefApplication(sys.argv) - mainWindow = MainWindow() - mainWindow.show() - app.exec_() - app.stopTimer() - - # Need to destroy QApplication(), otherwise Shutdown() fails. - # Unset main window also just to be safe. - del mainWindow - del app - - cefpython.Shutdown() diff --git a/src/windows/deprecated_32bit/pywin32.py b/src/windows/deprecated_32bit/pywin32.py deleted file mode 100644 index 747762696..000000000 --- a/src/windows/deprecated_32bit/pywin32.py +++ /dev/null @@ -1,151 +0,0 @@ -# Example of embedding CEF browser using the PyWin32 extension. -# Tested with pywin32 version 218. - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import a local module - if (2,7) <= sys.version_info < (2,8): - import cefpython_py27 as cefpython - elif (3,4) <= sys.version_info < (3,4): - import cefpython_py34 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import an installed package - from cefpython3 import cefpython - -import cefwindow -import win32con -import win32gui -import win32api -import time - -DEBUG = True - -# ----------------------------------------------------------------------------- -# Helper functions. - -def Log(msg): - print("[pywin32.py] %s" % str(msg)) - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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" (os._exit()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("[pywin32.py] WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -# ----------------------------------------------------------------------------- - -def CefAdvanced(): - sys.excepthook = ExceptHook - - appSettings = dict() - # appSettings["cache_path"] = "webcache/" # Disk cache - if DEBUG: - # cefpython debug messages in console and in log_file - appSettings["debug"] = True - cefwindow.g_debug = True - appSettings["log_file"] = GetApplicationPath("debug.log") - appSettings["log_severity"] = cefpython.LOGSEVERITY_INFO - appSettings["browser_subprocess_path"] = "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess") - cefpython.Initialize(appSettings) - - wndproc = { - win32con.WM_CLOSE: CloseWindow, - win32con.WM_DESTROY: QuitApplication, - win32con.WM_SIZE: cefpython.WindowUtils.OnSize, - win32con.WM_SETFOCUS: cefpython.WindowUtils.OnSetFocus, - win32con.WM_ERASEBKGND: cefpython.WindowUtils.OnEraseBackground - } - - browserSettings = dict() - browserSettings["universal_access_from_file_urls_allowed"] = True - browserSettings["file_access_from_file_urls_allowed"] = True - - if os.path.exists("icon.ico"): - icon = os.path.abspath("icon.ico") - else: - icon = "" - - windowHandle = cefwindow.CreateWindow(title="pywin32 example", - className="cefpython3_example", width=1024, height=768, - icon=icon, windowProc=wndproc) - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(windowHandle) - browser = cefpython.CreateBrowserSync(windowInfo, browserSettings, - navigateUrl=GetApplicationPath("example.html")) - cefpython.MessageLoop() - cefpython.Shutdown() - -def CloseWindow(windowHandle, message, wparam, lparam): - browser = cefpython.GetBrowserByWindowHandle(windowHandle) - browser.CloseBrowser() - return win32gui.DefWindowProc(windowHandle, message, wparam, lparam) - -def QuitApplication(windowHandle, message, wparam, lparam): - win32gui.PostQuitMessage(0) - return 0 - -def GetPywin32Version(): - fixed_file_info = win32api.GetFileVersionInfo(win32api.__file__, '\\') - return fixed_file_info['FileVersionLS'] >> 16 - -if __name__ == "__main__": - Log("pywin32 version = %s" % GetPywin32Version()) - CefAdvanced() diff --git a/src/windows/deprecated_32bit/smoke.css b/src/windows/deprecated_32bit/smoke.css deleted file mode 100644 index 2936c818a..000000000 --- a/src/windows/deprecated_32bit/smoke.css +++ /dev/null @@ -1,110 +0,0 @@ -.smoke-base { - position: fixed; - top: 0; - left: 0; - bottom: 0; - right: 0; - visibility: hidden; - opacity: 0; -} - -.smoke-base.smoke-visible { - opacity: 1; - visibility: visible; -} - -.smokebg { - position: fixed; - top: 0; - left: 0; - bottom: 0; - right: 0; -} - -.smoke-base .dialog { - position: absolute; -} - -.dialog-prompt { - margin-top: 15px; - text-align: center; -} - -.dialog-buttons { - margin: 20px 0 5px 0 -} - -.smoke { -} - -.dialog-buttons button { - display: inline-block; - vertical-align: baseline; - cursor: pointer; - font-family: Menlo, 'Andale Mono', monospace; - font-style: normal; - text-decoration: none; - border: 0; - outline: 0; - margin: 0 5px; - -webkit-background-clip: padding-box; - font-size: 13px; - line-height: 13px; - font-weight: normal; - padding: 9px 12px; -} - -.dialog-prompt input { - margin: 0; - border: 0; - font-family: sans-serif; - outline: none; - font-family: Menlo, 'Andale Mono', monospace; - border: 1px solid #aaa; - width: 75%; - display: inline-block; - background-color: transparent; - font-size: 16px; - padding: 8px; -} - -.smoke-base { - background: rgba(0,0,0,.3); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#90000000,endColorstr=#900000000); -} - -.smoke-base .dialog { - top: 25%; - width: 40%; - left: 50%; - margin-left: -20%; -} - -.smoke-base .dialog-inner { - padding: 15px; - - color:#202020; -} - -.smoke { - background-color: rgba(255,255,255,0.95); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#ffffff,endColorstr=#ffffff); - box-shadow: 0 2px 8px #666; -} - - -.dialog-buttons button { - background-color: rgba(0,0,0,.85); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#222222,endColorstr=#222222); - border-radius: 0; - color: #fff; -} - -button.cancel { - background-color: rgba(0,0,0,.40); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#444444,endColorstr=#444444); -} - -.queue{ - display:none; -} diff --git a/src/windows/deprecated_32bit/smoke.min.js b/src/windows/deprecated_32bit/smoke.min.js deleted file mode 100644 index 61fb4f0c0..000000000 --- a/src/windows/deprecated_32bit/smoke.min.js +++ /dev/null @@ -1 +0,0 @@ -(function(e,t){var n={smoketimeout:[],init:false,zindex:1e3,i:0,bodyload:function(e){var r=t.createElement("div");r.setAttribute("id","smoke-out-"+e);r.className="smoke-base";r.style.zIndex=n.zindex;n.zindex++;t.body.appendChild(r)},newdialog:function(){var t=(new Date).getTime();t=Math.random(1,99)+t;if(!n.init){n.listen(e,"load",function(){n.bodyload(t)})}else{n.bodyload(t)}return t},forceload:function(){},build:function(t,r){n.i++;r.stack=n.i;t=t.replace(/\n/g,"
      ");t=t.replace(/\r/g,"
      ");var i="",s="OK",o="Cancel",u="",a="",f;if(r.type==="prompt"){i='

      "}if(r.params.ok){s=r.params.ok}if(r.params.cancel){o=r.params.cancel}if(r.params.classname){u=r.params.classname}if(r.type!=="signal"){a='
      ';if(r.type==="alert"){a+='"}else if(r.type==="quiz"){if(r.params.button_1){a+='"}if(r.params.button_2){a+='"}if(r.params.button_3){a+='"}if(r.params.button_cancel){a+='"}}else if(r.type==="prompt"||r.type==="confirm"){if(r.params.reverseButtons){a+='"+'"}else{a+='"+'"}}a+="
      "}f='
      '+'
      '+'
      '+t+i+a+"
      "+"
      ";if(!n.init){n.listen(e,"load",function(){n.finishbuild(t,r,f)})}else{n.finishbuild(t,r,f)}},finishbuild:function(e,r,i){var s=t.getElementById("smoke-out-"+r.newid);s.className="smoke-base smoke-visible smoke-"+r.type;s.innerHTML=i;while(s.innerHTML===""){s.innerHTML=i}if(n.smoketimeout[r.newid]){clearTimeout(n.smoketimeout[r.newid])}n.listen(t.getElementById("smoke-bg-"+r.newid),"click",function(){n.destroy(r.type,r.newid);if(r.type==="prompt"||r.type==="confirm"||r.type==="quiz"){r.callback(false)}else if(r.type==="alert"&&typeof r.callback!=="undefined"){r.callback()}});switch(r.type){case"alert":n.finishbuildAlert(e,r,i);break;case"confirm":n.finishbuildConfirm(e,r,i);break;case"quiz":n.finishbuildQuiz(e,r,i);break;case"prompt":n.finishbuildPrompt(e,r,i);break;case"signal":n.finishbuildSignal(e,r,i);break;default:throw"Unknown type: "+r.type}},finishbuildAlert:function(r,i,s){n.listen(t.getElementById("alert-ok-"+i.newid),"click",function(){n.destroy(i.type,i.newid);if(typeof i.callback!=="undefined"){i.callback()}});t.onkeyup=function(t){if(!t){t=e.event}if(t.keyCode===13||t.keyCode===32||t.keyCode===27){n.destroy(i.type,i.newid);if(typeof i.callback!=="undefined"){i.callback()}}}},finishbuildConfirm:function(r,i,s){n.listen(t.getElementById("confirm-cancel-"+i.newid),"click",function(){n.destroy(i.type,i.newid);i.callback(false)});n.listen(t.getElementById("confirm-ok-"+i.newid),"click",function(){n.destroy(i.type,i.newid);i.callback(true)});t.onkeyup=function(t){if(!t){t=e.event}if(t.keyCode===13||t.keyCode===32){n.destroy(i.type,i.newid);i.callback(true)}else if(t.keyCode===27){n.destroy(i.type,i.newid);i.callback(false)}}},finishbuildQuiz:function(r,i,s){var o,u,a;n.listen(t.getElementById("quiz-cancel-"+i.newid),"click",function(){n.destroy(i.type,i.newid);i.callback(false)});if(o=t.getElementById("quiz-ok1-"+i.newid))n.listen(o,"click",function(){n.destroy(i.type,i.newid);i.callback(o.innerHTML)});if(u=t.getElementById("quiz-ok2-"+i.newid))n.listen(u,"click",function(){n.destroy(i.type,i.newid);i.callback(u.innerHTML)});if(a=t.getElementById("quiz-ok3-"+i.newid))n.listen(a,"click",function(){n.destroy(i.type,i.newid);i.callback(a.innerHTML)});t.onkeyup=function(t){if(!t){t=e.event}if(t.keyCode===27){n.destroy(i.type,i.newid);i.callback(false)}}},finishbuildPrompt:function(r,i,s){var o=t.getElementById("dialog-input-"+i.newid);setTimeout(function(){o.focus();o.select()},100);n.listen(t.getElementById("prompt-cancel-"+i.newid),"click",function(){n.destroy(i.type,i.newid);i.callback(false)});n.listen(t.getElementById("prompt-ok-"+i.newid),"click",function(){n.destroy(i.type,i.newid);i.callback(o.value)});t.onkeyup=function(t){if(!t){t=e.event}if(t.keyCode===13){n.destroy(i.type,i.newid);i.callback(o.value)}else if(t.keyCode===27){n.destroy(i.type,i.newid);i.callback(false)}}},finishbuildSignal:function(r,i,s){t.onkeyup=function(t){if(!t){t=e.event}if(t.keyCode===27){n.destroy(i.type,i.newid);if(typeof i.callback!=="undefined"){i.callback()}}};n.smoketimeout[i.newid]=setTimeout(function(){n.destroy(i.type,i.newid);if(typeof i.callback!=="undefined"){i.callback()}},i.timeout)},destroy:function(e,r){var i=t.getElementById("smoke-out-"+r);if(e!=="quiz"){var s=t.getElementById(e+"-ok-"+r)}var o=t.getElementById(e+"-cancel-"+r);i.className="smoke-base";if(s){n.stoplistening(s,"click",function(){});t.onkeyup=null}if(e==="quiz"){var u=t.getElementsByClassName("quiz-button");for(var a=0;a - - - - wxPython CEF 3 example (utf-8: ąś) - - - - - - - - - -Use the mouse context menu to go Back/Forward in history navigation. - -

      Table of contents

      -
        -
      1. Google search
      2. -
      3. User agent
      4. -
      5. Popups
      6. -
      7. HTML 5 video
      8. -
      9. Developer Tools
      10. -
      11. Downloads
      12. -
      13. HTML controls
      14. -
      15. Browser object
      16. -
      17. Frame object
      18. -
      19. Javascript bindings
      20. -
      21. Javascript callbacks
      22. -
      23. Python callbacks
      24. -
      25. Display handler
      26. -
      27. Keyboard handler
      28. -
      29. Request handler
      30. -
      31. Cookie tests
      32. -
      33. Load handler
      34. -
      35. Javascript Dialog handler
      36. -
      37. Other tests
      38. -
      - - - - - - -

      Google search

      - -http://www.google.com/ - - - - - - - -

      User agent

      - - - - - - - - - -

      Popups

      - -
        -
      1. - window.open('wxpython.html') -
      2. -
      3. - target=_blank href="wxpython.html" -
      4. -
      5. - window.open('https://www.google.com/') -
      6. -
      - -There are problems with keyboard in wxPython when popup windows are created -by CEF ( -Issue 80). To create the popup window of our own, the -LifespanHandler::OnBeforePopup callback was implemented. Note that this has -its implications, the popup window and parent window will not be able to -script each other. There will be no "window.opener" property available -in the popup window. - -See its source: - - - - -

      CreateAnotherBrowser

      - -This will create a window on its own and embed browser in it. -When using "window.open" the window is created implicitilly -by CEF. You can intercept such popup creation using the -OnBeforePopup callback in LifespanHandler. You can return -True in OnBeforePopup and create popup window on your own -using the CreateAnotherBrowser function. - - - - external.CreateAnotherBrowser() - - - - - - - -

      HTML5 video and accelerated content

      - - -HTML 5 video
      - - -Accelerated canvas
      - - -Accelerated layers
      - - - - - - -

      Developer Tools

      - -You can open devtools popup window in a few different ways: -
        -
      1. Call Browser.ShowDevTools() method: - - external.ShowDevTools()
      2. -
      3. Through mouse context menu
      4. -
      5. Through F12 key which is handled in KeyboardHandler.OnKeyEvent
      6. -
      - - - - - - -

      Downloads

      - -Download sample Ubuntu wallpapers:
      - - https://cefpython.googlecode.com/files/ubuntu-wallpapers2.zip - -

      -Notes: On Linux it seems that OnLoadError with errorCode = ERR_ABORTED -is called even for successful downloads, you can ignore this behavior. -The proper console messages about successful/aborted download originate -from C++ Browser process code, these are: -

      - -
      Browser: About to download file: ubuntu-wallpapers2.zip
      -Browser: Download completed, saved to: /Downloads/ubuntu-wallpapers2.zip
      -
      - -If download was aborted the messages will be: - -
      Browser: About to download file: ubuntu-wallpapers2.zip
      -Browser: Download was cancelled
      -
      - -

      -Additionally on Linux there are more errors reported by Chromium -about org.gnome.SessionManager.inhibit. These can be safely ignored as well. -

      - -A download handler with callbacks like `OnBeforeDownload` and -`OnDownloadUpdated` may be exposed to CEF Python in the future. - - - - - - -

      HTML controls

      - -

      Textarea

      - -
      - -

      Inputs

      -Text:
      -Password:
      - -

      Select

      - - -

      Buttons

      -Submit:
      -Button:
      - - - - - - -

      Browser object

      - -Tests for the Browser object methods. - -

      GoBack

      - -external.GoBack() - -

      GoForward

      - -external.GoForward() - -

      LoadUrl, GetUrl

      - - - window.open('data:text/html,Test#Browser.LoadUrl') - -

      SetZoomLevel

      -(You must set ApplicationSettings.auto_zooming = "" for SetZoomLevel calls -to work)
      -external.SetZoomLevel(2.0)
      -external.SetZoomLevel(1.0) - -

      ReloadIgnoreCache, StopLoad

      -Press F5 to reload page and ignore cache.
      -Press Esc during webpage loading to abort.
      - -Also, when Esc is pressed OnLoadError may get called. See how abort -of page loading or file download is handled: - - - - - - - -

      Frame object

      - -Tests for the Frame object methods. TODO. - - - - - - -

      Javascript bindings

      - -

      PyPrint

      - - - window.PyPrint('printing in python console from js') -
      - -

      Window properties

      - -
      jsBindings.SetProperty("pyProperty", "This was set in Python")
      -jsBindings.SetProperty("pyConfig", ["This was set in Python",
      -        {"name": "Nested dictionary", "isNested": True},
      -        [1,"2", None]])
      -
      - - - window.alert(window.pyProperty)
      - - window.alert(JSON.stringify(window.pyConfig)) -
      - -

      Print

      - - - - external.Print('printing again from js') -
      - -

      TestAllTypes

      - - - - external.TestAllTypes - (undefined, null, true, 1, - ((1<<31)>>>0), 2.14, 'Date not yet supported', 'string', - {key1: 1, key2: 2}, {key1: {'key1.1': 'nested object'}, 'key1.2': [1]}, - [1, 2], [1, [2.1, 'nested array']], [{key1: [{}]}]) -
      - -

      ExecuteFunction

      - - - -
      <script>
      -function JavascriptAlert(message) { window.alert(message); }
      -</script>
      -
      - - - - external.ExecuteFunction('JavascriptAlert', - 'python called from js and then js called from python', 0, [1,2]) -
      - -

      GetSource, GetText

      - - - - - - - external.GetSource() -
      - - external.GetText() - - - - - - -

      Javascript callbacks

      - -

      TestJSCallback

      - - - -
      <script>
      -function JSCallback(arg1) {
      -    window.alert(arg1)
      -}
      -</script>
      -
      - - - - external.TestJSCallback(JSCallback) - -

      TestJSCallbackComplexArguments

      - - - -
      <script>
      -function JSCallback2() {
      -    window.alert(JSON.stringify(arguments))
      -}
      -</script>
      -
      - - - - external.TestJSCallbackComplexArguments({"myCallback": JSCallback2}) - - - - - - - -

      Python callbacks

      - -

      TestPythonCallback

      - - - -
      <script>
      -function JSCallback3(pyCallback) {
      -    pyCallback(1, 2.14, "string", [1, [2, {"key": "value"}]], {"list": [1,2]});
      -}
      -</script>
      -
      - - - - - - external.TestPythonCallback(JSCallback3) - - - - - - -

      Display handler

      - -

      OnAddressChange

      - -See messages in the console during loading of a webpage. - -

      OnTitleChange

      - -See messages in the console during loading of a webpage. - -

      OnTooltip

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

      OnStatusMessage

      - -See messages in the console when hovering over links. - -

      OnConsoleMessage

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

      Keyboard handler

      - -

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

      - - - - - - - - - -

      Request handler

      - -

      OnBeforeResourceLoad

      - -See messages in the console. - -

      OnResourceRedirect

      - -Try this: - - http://tinyurl.com/google404redirect - -

      GetAuthCredentials

      - -Try this: - - http://browserspy.dk/password-ok.php - -

      OnQuotaRequest

      - - - - -
      <script>
      -function DoRequestQuota() {
      -    // Request Quota (only for File System API)
      -    try {
      -        navigator.webkitPersistentStorage.requestQuota(PERSISTENT, 1024*1024,
      -                function(bytes){ window.alert("Granted bytes: "+bytes);},
      -                function(error){ window.alert(error); });
      -    } catch(e) {
      -        navigator.webkitPersistentStorage.requestQuota(1024*1024,
      -                function(bytes){ window.alert("Granted bytes: "+bytes);},
      -                function(error){ window.alert(error); });
      -    }
      -}
      -</script>
      -
      - -Try this: - - https://googledrive.com/host/0B1di2XiBBfacMnhRRkI1YlotUEk/requestquota.html - -

      OnProtocolExecution

      - - -Try magnet link to download a torrent: - - magnet:?xt=urn:btih:a4224b45b27f436374391379cc5c7e629e2e5189 - -

      _OnBeforePluginLoad

      - -Try OnBeforePluginLoad() with Flash: - - http://www.adobe.com/software/flash/about/ - -

      _OnCertificateError

      - - -The url below won't be allowed. Click twice "Back" from context menu -to return back here after visiting that url:
      - - https://testssl-expire.disig.sk/index.en.html -
      - -This url will be allowed:
      - - https://testssl-expire.disig.sk/index.en.html?allow=1 -
      -After you've clicked the second url, the first one will now be allowed, -as this is the same domain and it's cached now. - -

      OnRendererProcessTerminated

      - -Try to terminate the "subprocess.exe" renderer process through -task manager. - -

      OnPluginCrashed

      - -No test for that yet. - - - - - - -

      Cookie tests

      - -See messages in the console. - -

      GetCookieManager

      - - - -RequestHandler.GetCookieManager() - an example of having an unique -cookie manager for each browser. -
        -
      1. Visit the url below and set some cookies. Use "Back" from - context menu to get back here (you might have to click "Back" - multiple times).
        - Visit it in the current browser:
        - - http://www.html-kit.com/tools/cookietester/ -
      2. -
      3. Open cookietester in a popup - a separate cookie manager is used:
        - - javascript:external.CreateAnotherBrowser('http://www.html-kit.com/tools/cookietester/') -
      4. -
      - -

      -Popup browsers created javascript's window.open share -the same renderer process and request context. If you want -to have separate cookie managers for popups created using -window.open then you have to implement the -LifespanHandler.`OnBeforePopup` callback. Return True in that -callback to cancel popup creation and instead create the -window on your own and embed browser in it. The CreateAnotherBrowser() -function from the wxpython example does that. -

      - -

      VisitAllCookies

      - -Visit all cookies: -external.VisitAllCookies() -

      - -Note: visit some http:// webpage first, otherwise cookie manager is not -yet created. -
      - -

      VisitUrlCookies

      - -Visit a subset of cookies for the given url: - - external.VisitUrlCookies("http://www.html-kit.com/tools/cookietester/") -
      - -

      SetCookie

      - -Set a cookie on html-kit.com: -external.SetCookie() -
      -Go see the cookie that was created: - - http://www.html-kit.com/tools/cookietester/ - -

      DeleteCookies

      - -Delete the single cookie previously created via SetCookie(): - - external.DeleteCookies() -
      -Go check if cookie was deleted: - - http://www.html-kit.com/tools/cookietester/ - - - - - - -

      Load Handler

      - -See messages in the console during loading of a webpage. - -

      OnLoadingStateChange

      - - -

      OnLoadStart

      - - -

      OnLoadEnd

      - - -

      OnLoadError

      - -After you see the custom error message you have to hit -twice the Back from the context menu, to get back to this page. -
      -Try this: - - http://www.non-existent.nono/ -
      - - - - - - - - -

      Javascript Dialog Handler

      - -See messages in the console. - -

      OnJavascriptDialog

      - - - window.alert('Test js dialog handler') - - -

      OnBeforeUnloadJavascriptDialog

      - - - -
      <script>
      -function TestOnBeforeUnloadJavascriptDialog() {
      -    window.onbeforeunload = function() {
      -        return 'Testing the OnBeforeUnloadJavascriptDialog() callback';
      -    }
      -    location.href = "wxpython.html";
      -}
      -</script>
      -
      - - - TestOnBeforeUnloadJavascriptDialog() - - -

      OnResetJavascriptDialogState

      - - -

      OnJavascriptDialogClosed

      - - - - - - - -

      Other tests

      - -

      HTTPS caching with SSL certificate errors

      -Set ApplicationSettings["ignore_certificate_errors"] to True. - - - - - - - - - - - - - diff --git a/src/windows/deprecated_32bit/wxpython.py b/src/windows/deprecated_32bit/wxpython.py deleted file mode 100644 index ed6bb44bd..000000000 --- a/src/windows/deprecated_32bit/wxpython.py +++ /dev/null @@ -1,906 +0,0 @@ -# An example of embedding CEF browser in wxPython on Windows. -# Tested with wxPython 2.8.12.1 and 3.0.2.0. - -import os, sys -libcef_dll = os.path.join(os.path.dirname(os.path.abspath(__file__)), - 'libcef.dll') -if os.path.exists(libcef_dll): - # Import a local module - if (2,7) <= sys.version_info < (2,8): - import cefpython_py27 as cefpython - elif (3,4) <= sys.version_info < (3,4): - import cefpython_py34 as cefpython - else: - raise Exception("Unsupported python version: %s" % sys.version) -else: - # Import an installed package - from cefpython3 import cefpython - -import wx -import time -import re -import uuid -import platform -import inspect -import struct - -# ----------------------------------------------------------------------------- -# Globals - -g_applicationSettings = None -g_browserSettings = None -g_commandLineSwitches = None - -# Which method to use for message loop processing. -# EVT_IDLE - wx application has priority -# EVT_TIMER - cef browser has priority (default) -# It seems that Flash content behaves better when using a timer. -# Not sure if using EVT_IDLE is correct, it doesn't work on Linux, -# on Windows it works fine. See also the post by Robin Dunn: -# https://groups.google.com/d/msg/wxpython-users/hcNdMEx8u48/MD5Jgbm_k1kJ -USE_EVT_IDLE = False # If False then Timer will be used - -TEST_EMBEDDING_IN_PANEL = True - -# ----------------------------------------------------------------------------- - -def GetApplicationPath(file=None): - import re, os, platform - # On Windows after downloading file and calling Browser.GoForward(), - # current working directory is set to %UserProfile%. - # Calling os.path.dirname(os.path.realpath(__file__)) - # returns for eg. "C:\Users\user\Downloads". A solution - # is to cache path on first call. - if not hasattr(GetApplicationPath, "dir"): - if hasattr(sys, "frozen"): - dir = os.path.dirname(sys.executable) - elif "__file__" in globals(): - dir = os.path.dirname(os.path.realpath(__file__)) - else: - dir = os.getcwd() - GetApplicationPath.dir = dir - # If file is None return current directory without trailing slash. - if file is None: - file = "" - # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = GetApplicationPath.dir + os.sep + file - if platform.system() == "Windows": - path = re.sub(r"[/\\]+", re.escape(os.sep), path) - path = re.sub(r"[/\\]+$", "", path) - return path - return str(file) - -def ExceptHook(excType, excValue, traceObject): - import traceback, os, time, codecs - # 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" (os._exit()). - errorMsg = "\n".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetApplicationPath("error.log") - try: - appEncoding = cefpython.g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) - except: - print("[wxpython.py] WARNING: failed writing to error file: %s" % ( - errorFile)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg+"\n") - cefpython.QuitMessageLoop() - cefpython.Shutdown() - os._exit(1) - -class MainFrame(wx.Frame): - browser = None - mainPanel = None - - def GetHandleForBrowser(self): - if self.mainPanel: - return self.mainPanel.GetHandle() - else: - return self.GetHandle() - - def __init__(self, url=None, popup=False): - if popup: - title = "wxPython Popup" - else: - title = "wxPython CEF 3 example" - wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, - title=title) - size=(800,600) - - # This is an optional code to enable High DPI support. - if "auto_zooming" in g_applicationSettings \ - and g_applicationSettings["auto_zooming"] == "system_dpi": - # This utility function will adjust width/height using - # OS DPI settings. For 800/600 with Win7 DPI settings - # being set to "Larger 150%" will return 1200/900. - size = cefpython.DpiAware.CalculateWindowSize(size[0], size[1]) - - self.SetSize(size) - - if not url: - url = "file://"+GetApplicationPath("wxpython.html") - # Test hash in url. - # url += "#test-hash" - - self.CreateMenu() - - if TEST_EMBEDDING_IN_PANEL: - print("Embedding in a wx.Panel!") - # You also have to set the wx.WANTS_CHARS style for - # all parent panels/controls, if it's deeply embedded. - self.mainPanel = wx.Panel(self, style=wx.WANTS_CHARS) - - # Global client callbacks must be set before browser is created. - self.clientHandler = ClientHandler() - cefpython.SetGlobalClientCallback("OnCertificateError", - self.clientHandler._OnCertificateError) - cefpython.SetGlobalClientCallback("OnBeforePluginLoad", - self.clientHandler._OnBeforePluginLoad) - cefpython.SetGlobalClientCallback("OnAfterCreated", - self.clientHandler._OnAfterCreated) - - windowInfo = cefpython.WindowInfo() - windowInfo.SetAsChild(self.GetHandleForBrowser()) - self.browser = cefpython.CreateBrowserSync(windowInfo, - browserSettings=g_browserSettings, - navigateUrl=url) - - self.clientHandler.mainBrowser = self.browser - self.browser.SetClientHandler(self.clientHandler) - - jsBindings = cefpython.JavascriptBindings( - bindToFrames=False, bindToPopups=True) - jsBindings.SetFunction("PyPrint", PyPrint) - jsBindings.SetProperty("pyProperty", "This was set in Python") - jsBindings.SetProperty("pyConfig", ["This was set in Python", - {"name": "Nested dictionary", "isNested": True}, - [1,"2", None]]) - self.javascriptExternal = JavascriptExternal(self.browser) - jsBindings.SetObject("external", self.javascriptExternal) - jsBindings.SetProperty("sources", GetSources()) - self.browser.SetJavascriptBindings(jsBindings) - - if self.mainPanel: - self.mainPanel.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) - self.mainPanel.Bind(wx.EVT_SIZE, self.OnSize) - else: - self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) - self.Bind(wx.EVT_SIZE, self.OnSize) - - self.Bind(wx.EVT_CLOSE, self.OnClose) - if USE_EVT_IDLE and not popup: - # Bind EVT_IDLE only for the main application frame. - print("Using EVT_IDLE to execute the CEF message loop work") - self.Bind(wx.EVT_IDLE, self.OnIdle) - - def CreateMenu(self): - filemenu = wx.Menu() - filemenu.Append(1, "Open") - exit = filemenu.Append(2, "Exit") - self.Bind(wx.EVT_MENU, self.OnClose, exit) - aboutmenu = wx.Menu() - aboutmenu.Append(1, "CEF Python") - menubar = wx.MenuBar() - menubar.Append(filemenu,"&File") - menubar.Append(aboutmenu, "&About") - self.SetMenuBar(menubar) - - def OnSetFocus(self, event): - cefpython.WindowUtils.OnSetFocus(self.GetHandleForBrowser(), 0, 0, 0) - - def OnSize(self, event): - cefpython.WindowUtils.OnSize(self.GetHandleForBrowser(), 0, 0, 0) - - def OnClose(self, event): - # Remove all CEF browser references so that browser is closed - # cleanly. Otherwise there may be issues for example with cookies - # not being flushed to disk when closing app immediately - # (Issue 158). - del self.javascriptExternal.mainBrowser - del self.clientHandler.mainBrowser - del self.browser - - # Destroy wx frame, this will complete the destruction of CEF browser - self.Destroy() - - # In wx.chromectrl calling browser.CloseBrowser and/or self.Destroy - # may cause crashes when embedding multiple browsers in tab - # (Issue 107). In such case instead of calling CloseBrowser/Destroy - # try this code: - # | self.browser.ParentWindowWillClose() - # | event.Skip() - - def OnIdle(self, event): - cefpython.MessageLoopWork() - -def PyPrint(message): - print("[wxpython.py] PyPrint: "+message) - -class JavascriptExternal: - mainBrowser = None - stringVisitor = None - - def __init__(self, mainBrowser): - self.mainBrowser = mainBrowser - - def GoBack(self): - self.mainBrowser.GoBack() - - def GoForward(self): - self.mainBrowser.GoForward() - - def SetZoomLevel(self, zoomLevel): - self.mainBrowser.SetZoomLevel(zoomLevel) - - def CreateAnotherBrowser(self, url=None): - frame = MainFrame(url=url) - frame.Show() - - def Print(self, message): - print("[wxpython.py] Print: "+message) - - def TestAllTypes(self, *args): - print("[wxpython.py] TestAllTypes: "+str(args)) - - def ExecuteFunction(self, *args): - self.mainBrowser.ExecuteFunction(*args) - - def TestJSCallback(self, jsCallback): - print("[wxpython.py] jsCallback.GetFunctionName() = %s"\ - % jsCallback.GetFunctionName()) - print("[wxpython.py] jsCallback.GetFrame().GetIdentifier() = %s" % \ - jsCallback.GetFrame().GetIdentifier()) - jsCallback.Call("This message was sent from python using js callback") - - def TestJSCallbackComplexArguments(self, jsObject): - jsCallback = jsObject["myCallback"]; - jsCallback.Call(1, None, 2.14, "string", ["list", ["nested list", \ - {"nested object":None}]], \ - {"nested list next":[{"deeply nested object":1}]}) - - def TestPythonCallback(self, jsCallback): - jsCallback.Call(self.PyCallback) - - def PyCallback(self, *args): - message = "PyCallback() was executed successfully! "\ - "Arguments: %s" % str(args) - print("[wxpython.py] "+message) - self.mainBrowser.GetMainFrame().ExecuteJavascript( - "window.alert(\"%s\")" % message) - - def GetSource(self): - # Must keep a strong reference to the StringVisitor object - # during the visit. - self.stringVisitor = StringVisitor() - self.mainBrowser.GetMainFrame().GetSource(self.stringVisitor) - - def GetText(self): - # Must keep a strong reference to the StringVisitor object - # during the visit. - self.stringVisitor = StringVisitor() - self.mainBrowser.GetMainFrame().GetText(self.stringVisitor) - - def ShowDevTools(self): - print("[wxpython.py] external.ShowDevTools called") - self.mainBrowser.ShowDevTools() - - # ------------------------------------------------------------------------- - # Cookies - # ------------------------------------------------------------------------- - cookieVisitor = None - - def VisitAllCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.VisitAllCookies(self.cookieVisitor) - - def VisitUrlCookies(self): - # Need to keep the reference alive. - self.cookieVisitor = CookieVisitor() - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.VisitUrlCookies( - "http://www.html-kit.com/tools/cookietester/", - False, self.cookieVisitor) - # .www.html-kit.com - - def SetCookie(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - "the cookietester website first and create some cookies") - return - cookie = cefpython.Cookie() - cookie.SetName("Created_Via_Python") - cookie.SetValue("yeah really") - cookieManager.SetCookie("http://www.html-kit.com/tools/cookietester/", - cookie) - print("\n[wxpython.py] Cookie created! Visit html-kit cookietester to"\ - " see it") - - def DeleteCookies(self): - cookieManager = self.mainBrowser.GetUserData("cookieManager") - if not cookieManager: - print("\n[wxpython.py] Cookie manager not yet created! Visit"\ - " the cookietester website first and create some cookies") - return - cookieManager.DeleteCookies( - "http://www.html-kit.com/tools/cookietester/", - "Created_Via_Python") - print("\n[wxpython.py] Cookie deleted! Visit html-kit cookietester "\ - "to see the result") - -class StringVisitor: - def Visit(self, string): - print("\n[wxpython.py] StringVisitor.Visit(): string:") - print("--------------------------------") - print(string) - print("--------------------------------") - -class CookieVisitor: - def Visit(self, cookie, count, total, deleteCookie): - if count == 0: - print("\n[wxpython.py] CookieVisitor.Visit(): total cookies: %s"\ - % total) - print("\n[wxpython.py] CookieVisitor.Visit(): cookie:") - print(" "+str(cookie.Get())) - # True to continue visiting cookies - return True - -class ClientHandler: - mainBrowser = None # May be None for global client callbacks. - - def __init__(self): - pass - - # ------------------------------------------------------------------------- - # DisplayHandler - # ------------------------------------------------------------------------- - - def OnAddressChange(self, browser, frame, url): - print("[wxpython.py] DisplayHandler::OnAddressChange()") - print(" url = %s" % url) - - def OnTitleChange(self, browser, title): - print("[wxpython.py] DisplayHandler::OnTitleChange()") - print(" title = %s" % title) - - def OnTooltip(self, browser, textOut): - # OnTooltip not yet implemented (both Linux and Windows), - # will be fixed in next CEF release, see Issue 783: - # https://code.google.com/p/chromiumembedded/issues/detail?id=783 - print("[wxpython.py] DisplayHandler::OnTooltip()") - print(" text = %s" % textOut[0]) - - statusMessageCount = 0 - def OnStatusMessage(self, browser, value): - if not value: - # Do not notify in the console about empty statuses. - return - self.statusMessageCount += 1 - if self.statusMessageCount > 3: - # Do not spam too much. - return - print("[wxpython.py] DisplayHandler::OnStatusMessage()") - print(" value = %s" % value) - - def OnConsoleMessage(self, browser, message, source, line): - print("[wxpython.py] DisplayHandler::OnConsoleMessage()") - print(" message = %s" % message) - print(" source = %s" % source) - print(" line = %s" % line) - - # ------------------------------------------------------------------------- - # KeyboardHandler - # ------------------------------------------------------------------------- - - def OnPreKeyEvent(self, browser, event, eventHandle, - isKeyboardShortcutOut): - print("[wxpython.py] KeyboardHandler::OnPreKeyEvent()") - - def OnKeyEvent(self, browser, event, eventHandle): - if event["type"] == cefpython.KEYEVENT_KEYUP: - # OnKeyEvent is called twice for F5/Esc keys, with event - # type KEYEVENT_RAWKEYDOWN and KEYEVENT_KEYUP. - # Normal characters a-z should have KEYEVENT_CHAR. - return False - print("[wxpython.py] KeyboardHandler::OnKeyEvent()") - print(" type=%s" % event["type"]) - print(" modifiers=%s" % event["modifiers"]) - print(" windows_key_code=%s" % event["windows_key_code"]) - print(" native_key_code=%s" % event["native_key_code"]) - print(" is_system_key=%s" % event["is_system_key"]) - print(" character=%s" % event["character"]) - print(" unmodified_character=%s" % event["unmodified_character"]) - print(" focus_on_editable_field=%s" \ - % event["focus_on_editable_field"]) - linux = (platform.system() == "Linux") - windows = (platform.system() == "Windows") - # F5 - if (linux and event["native_key_code"] == 71) \ - or (windows and event["windows_key_code"] == 116): - print("[wxpython.py] F5 pressed, calling" - " browser.ReloadIgnoreCache()") - browser.ReloadIgnoreCache() - return True - # Escape - if (linux and event["native_key_code"] == 9) \ - or (windows and event["windows_key_code"] == 27): - print("[wxpython.py] Esc pressed, calling browser.StopLoad()") - browser.StopLoad() - return True - # F12 - if (linux and event["native_key_code"] == 96) \ - or (windows and event["windows_key_code"] == 123): - print("[wxpython.py] F12 pressed, calling" - " browser.ShowDevTools()") - browser.ShowDevTools() - return True - return False - - # ------------------------------------------------------------------------- - # RequestHandler - # ------------------------------------------------------------------------- - - def OnBeforeBrowse(self, browser, frame, request, isRedirect): - print("[wxpython.py] RequestHandler::OnBeforeBrowse()") - print(" url = %s" % request.GetUrl()[:100]) - # Handle "magnet:" links. - if request.GetUrl().startswith("magnet:"): - print("[wxpython.p] RequestHandler::OnBeforeBrowse(): " - "magnet link clicked, cancelling browse request") - return True - return False - - def OnBeforeResourceLoad(self, browser, frame, request): - print("[wxpython.py] RequestHandler::OnBeforeResourceLoad()") - print(" url = %s" % request.GetUrl()[:100]) - return False - - def OnResourceRedirect(self, browser, frame, oldUrl, newUrlOut, request): - print("[wxpython.py] RequestHandler::OnResourceRedirect()") - print(" old url = %s" % oldUrl[:100]) - print(" new url = %s" % newUrlOut[0][:100]) - - def GetAuthCredentials(self, browser, frame, isProxy, host, port, realm, - scheme, callback): - # This callback is called on the IO thread, thus print messages - # may not be visible. - print("[wxpython.py] RequestHandler::GetAuthCredentials()") - print(" host = %s" % host) - print(" realm = %s" % realm) - callback.Continue(username="test", password="test") - return True - - def OnQuotaRequest(self, browser, originUrl, newSize, callback): - print("[wxpython.py] RequestHandler::OnQuotaRequest()") - print(" origin url = %s" % originUrl) - print(" new size = %s" % newSize) - callback.Continue(True) - return True - - def GetCookieManager(self, browser, mainUrl): - # Create unique cookie manager for each browser. - # You must set the "unique_request_context_per_browser" - # application setting to True for the cookie manager - # to work. - # Return None to have one global cookie manager for - # all CEF browsers. - if not browser: - # The browser param may be empty in some exceptional - # case, see docs. - return None - cookieManager = browser.GetUserData("cookieManager") - if cookieManager: - return cookieManager - else: - print("[wxpython.py] RequestHandler::GetCookieManager():"\ - " created cookie manager") - cookieManager = cefpython.CookieManager.CreateManager("") - if "cache_path" in g_applicationSettings: - path = g_applicationSettings["cache_path"] - # path = os.path.join(path, "cookies_browser_{}".format( - # browser.GetIdentifier())) - cookieManager.SetStoragePath(path) - browser.SetUserData("cookieManager", cookieManager) - return cookieManager - - def OnProtocolExecution(self, browser, url, allowExecutionOut): - # There's no default implementation for OnProtocolExecution on Linux, - # you have to make OS system call on your own. You probably also need - # to use LoadHandler::OnLoadError() when implementing this on Linux. - print("[wxpython.py] RequestHandler::OnProtocolExecution()") - print(" url = %s" % url) - if url.startswith("magnet:"): - print("[wxpython.py] Magnet link allowed!") - allowExecutionOut[0] = True - - def _OnBeforePluginLoad(self, browser, mimeType, pluginUrl, topOriginUrl, - info): - # This is a global callback set using SetGlobalClientCallback(). - # Plugins are loaded on demand, only when website requires it, - # the same plugin may be called multiple times. - # This callback is called on various threads, thus print messages - # may not be visible. - print("[wxpython.py] RequestHandler::_OnBeforePluginLoad()") - print(" mimeType = %s" % mimeType) - print(" pluginUrl = %s" % pluginUrl) - print(" topOriginUrl = %s" % topOriginUrl) - print(" info.GetName() = %s" % info.GetName()) - print(" info.GetPath() = %s" % info.GetPath()) - print(" info.GetVersion() = %s" % info.GetVersion()) - print(" info.GetDescription() = %s" % info.GetDescription()) - # False to allow, True to block plugin. - return False - - def _OnCertificateError(self, certError, requestUrl, callback): - # This is a global callback set using SetGlobalClientCallback(). - print("[wxpython.py] RequestHandler::_OnCertificateError()") - print(" certError = %s" % certError) - print(" requestUrl = %s" % requestUrl) - if requestUrl == "https://testssl-expire.disig.sk/index.en.html": - print(" Not allowed!") - return False - if requestUrl \ - == "https://testssl-expire.disig.sk/index.en.html?allow=1": - print(" Allowed!") - callback.Continue(True) - return True - return False - - def OnRendererProcessTerminated(self, browser, status): - print("[wxpython.py] RequestHandler::OnRendererProcessTerminated()") - statuses = { - cefpython.TS_ABNORMAL_TERMINATION: "TS_ABNORMAL_TERMINATION", - cefpython.TS_PROCESS_WAS_KILLED: "TS_PROCESS_WAS_KILLED", - cefpython.TS_PROCESS_CRASHED: "TS_PROCESS_CRASHED" - } - statusName = "Unknown" - if status in statuses: - statusName = statuses[status] - print(" status = %s" % statusName) - - def OnPluginCrashed(self, browser, pluginPath): - print("[wxpython.py] RequestHandler::OnPluginCrashed()") - print(" plugin path = %s" % pluginPath) - - # ------------------------------------------------------------------------- - # LoadHandler - # ------------------------------------------------------------------------- - - def OnLoadingStateChange(self, browser, isLoading, canGoBack, - canGoForward): - print("[wxpython.py] LoadHandler::OnLoadingStateChange()") - print(" isLoading = %s, canGoBack = %s, canGoForward = %s" \ - % (isLoading, canGoBack, canGoForward)) - - def OnLoadStart(self, browser, frame): - print("[wxpython.py] LoadHandler::OnLoadStart()") - print(" frame url = %s" % frame.GetUrl()[:100]) - - def OnLoadEnd(self, browser, frame, httpStatusCode): - print("[wxpython.py] LoadHandler::OnLoadEnd()") - print(" frame url = %s" % frame.GetUrl()[:100]) - # For file:// urls the status code = 0 - print(" http status code = %s" % httpStatusCode) - # Tests for the Browser object methods - self._Browser_LoadUrl(browser) - - def _Browser_LoadUrl(self, browser): - if browser.GetUrl() == "data:text/html,Test#Browser.LoadUrl": - browser.LoadUrl("file://"+GetApplicationPath("wxpython.html")) - - def OnLoadError(self, browser, frame, errorCode, errorTextList, failedUrl): - print("[wxpython.py] LoadHandler::OnLoadError()") - print(" frame url = %s" % frame.GetUrl()[:100]) - print(" error code = %s" % errorCode) - print(" error text = %s" % errorTextList[0]) - print(" failed url = %s" % failedUrl) - # Handle ERR_ABORTED error code, to handle the following cases: - # 1. Esc key was pressed which calls browser.StopLoad() in OnKeyEvent - # 2. Download of a file was aborted - # 3. Certificate error - if errorCode == cefpython.ERR_ABORTED: - print("[wxpython.py] LoadHandler::OnLoadError(): Ignoring load " - "error: Esc was pressed or file download was aborted, " - "or there was certificate error") - return; - customErrorMessage = "My custom error message!" - frame.LoadUrl("data:text/html,%s" % customErrorMessage) - - # ------------------------------------------------------------------------- - # LifespanHandler - # ------------------------------------------------------------------------- - - # ** This callback is executed on the IO thread ** - # Empty place-holders: popupFeatures, client. - def OnBeforePopup(self, browser, frame, targetUrl, targetFrameName, - targetDisposition, userGesture, - popupFeatures, windowInfo, client, browserSettings, - noJavascriptAccess): - print("[wxpython.py] LifespanHandler::OnBeforePopup()") - print(" targetUrl = %s" % targetUrl) - - # Custom browser settings for popups: - # > browserSettings[0] = {"plugins_disabled": True} - - # Set WindowInfo object: - # > windowInfo[0] = cefpython.WindowInfo() - - # On Windows there are keyboard problems in popups, when popup - # is created using "window.open" or "target=blank". This issue - # occurs only in wxPython. PyGTK or PyQt do not require this fix. - # The solution is to create window explicitilly, and not depend - # on CEF to create window internally. See Issue 80 for details: - # https://github.com/cztomczak/cefpython/issues/80 - - # If you set allowPopups=True then CEF will create popup window. - # The wx.Frame cannot be created here, as this callback is - # executed on the IO thread. Window should be created on the UI - # thread. One solution is to call cefpython.CreateBrowser() - # which runs asynchronously and can be called on any thread. - # The other solution is to post a task on the UI thread, so - # that cefpython.CreateBrowserSync() can be used. - - # Note that if you return True and create the popup window yourself, - # then the popup window and parent window will not be able to script - # each other. There will be no "window.opener" property available - # in the popup window. - - cefpython.PostTask(cefpython.TID_UI, self._CreatePopup, targetUrl) - - allowPopups = False - return not allowPopups - - def _CreatePopup(self, url): - frame = MainFrame(url=url, popup=True) - frame.Show() - - def _OnAfterCreated(self, browser): - # This is a global callback set using SetGlobalClientCallback(). - print("[wxpython.py] LifespanHandler::_OnAfterCreated()") - print(" browserId=%s" % browser.GetIdentifier()) - - def DoClose(self, browser): - print("[wxpython.py] LifespanHandler::DoClose()") - print(" browserId=%s" % browser.GetIdentifier()) - - def OnBeforeClose(self, browser): - print("[wxpython.py] LifespanHandler::OnBeforeClose") - print(" browserId=%s" % browser.GetIdentifier()) - - # ------------------------------------------------------------------------- - # JavascriptDialogHandler - # ------------------------------------------------------------------------- - - def OnJavascriptDialog(self, browser, originUrl, dialogType, - messageText, defaultPromptText, callback, - suppressMessage): - print("[wxpython.py] JavascriptDialogHandler::OnJavascriptDialog()") - print(" originUrl="+originUrl) - print(" dialogType="+str(dialogType)) - print(" messageText="+messageText) - print(" defaultPromptText="+defaultPromptText) - # If you want to suppress the javascript dialog: - # suppressMessage[0] = True - return False - - def OnBeforeUnloadJavascriptDialog(self, browser, messageText, isReload, - callback): - print("[wxpython.py] OnBeforeUnloadJavascriptDialog()") - print(" messageText="+messageText) - print(" isReload="+str(isReload)) - # Return True if the application will use a custom dialog: - # callback.Continue(allow=True, userInput="") - # return True - return False - - def OnResetJavascriptDialogState(self, browser): - print("[wxpython.py] OnResetDialogState()") - - def OnJavascriptDialogClosed(self, browser): - print("[wxpython.py] OnDialogClosed()") - - -class MyApp(wx.App): - timer = None - timerID = 1 - mainFrame = None - - def OnInit(self): - if not USE_EVT_IDLE: - print("[wxpython.py] Using TIMER to run CEF message loop") - self.CreateTimer() - self.mainFrame = MainFrame() - self.SetTopWindow(self.mainFrame) - self.mainFrame.Show() - return True - - def CreateTimer(self): - # See "Making a render loop": - # http://wiki.wxwidgets.org/Making_a_render_loop - # Another approach is to use EVT_IDLE in MainFrame, - # see which one fits you better. - self.timer = wx.Timer(self, self.timerID) - self.timer.Start(10) # 10ms - wx.EVT_TIMER(self, self.timerID, self.OnTimer) - - def OnTimer(self, event): - cefpython.MessageLoopWork() - - def OnExit(self): - # When app.MainLoop() returns, MessageLoopWork() should - # not be called anymore. - print("[wxpython.py] MyApp.OnExit") - if not USE_EVT_IDLE: - self.timer.Stop() - - -def GetSources(): - # Get sources of all python functions and methods from this file. - # This is to provide sources preview to wxpython.html. - # The dictionary of functions is binded to "window.sources". - thisModule = sys.modules[__name__] - functions = inspect.getmembers(thisModule, inspect.isfunction) - classes = inspect.getmembers(thisModule, inspect.isclass) - sources = {} - for funcTuple in functions: - sources[funcTuple[0]] = inspect.getsource(funcTuple[1]) - for classTuple in classes: - className = classTuple[0] - classObject = classTuple[1] - methods = inspect.getmembers(classObject) - for methodTuple in methods: - try: - sources[methodTuple[0]] = inspect.getsource(\ - methodTuple[1]) - except: - pass - return sources - - -if __name__ == '__main__': - print('[wxpython.py] architecture=%s-bit' % (8 * struct.calcsize("P"))) - print('[wxpython.py] wx.version=%s' % wx.version()) - - # Intercept python exceptions. Exit app immediately when exception - # happens on any of the threads. - sys.excepthook = ExceptHook - - # Application settings - g_applicationSettings = { - # Disk cache - # "cache_path": "webcache/", - - # CEF Python debug messages in console and in log_file - "debug": True, - # Set it to LOGSEVERITY_VERBOSE for more details - "log_severity": cefpython.LOGSEVERITY_INFO, - # Set to "" to disable logging to a file - "log_file": GetApplicationPath("debug.log"), - - # These directories must be set on Linux - "locales_dir_path": cefpython.GetModuleDirectory()+"/locales", - "resources_dir_path": cefpython.GetModuleDirectory(), - # The "subprocess" executable that launches the Renderer - # and GPU processes among others. You may rename that - # executable if you like. - "browser_subprocess_path": "%s/%s" % ( - cefpython.GetModuleDirectory(), "subprocess"), - - # This option is required for the GetCookieManager callback - # to work. It affects renderer processes, when this option - # is set to True. It will force a separate renderer process - # for each browser created using CreateBrowserSync. - "unique_request_context_per_browser": True, - # Downloads are handled automatically. A default SaveAs file - # dialog provided by OS will be displayed. - - "downloads_enabled": True, - # Remote debugging port, required for Developer Tools support. - # A value of 0 will generate a random port. To disable devtools - # support set it to -1. - "remote_debugging_port": 0, - # Mouse context menu - "context_menu": { - "enabled": True, - "navigation": True, # Back, Forward, Reload - "print": True, - "view_source": True, - "external_browser": True, # Open in external browser - "devtools": True, # Developer Tools - }, - - # See also OnCertificateError which allows you to ignore - # certificate errors for specific websites. - "ignore_certificate_errors": True, - } - - # You can comment out the code below if you do not want High - # DPI support. If you disable it text will look fuzzy on - # high DPI displays. - # - # Enabling High DPI support in app can be done by - # embedding a DPI awareness xml manifest in executable - # (see Issue 112 comment #2), or by calling SetProcessDpiAware - # function. Embedding xml manifest is the most reliable method. - # The downside of calling SetProcessDpiAware is that scrollbar - # in CEF browser is smaller than it should be. This is because - # DPI awareness was set too late, after the CEF dll was loaded. - # To fix that embed DPI awareness xml manifest in the .exe file. - # - # There is one bug when enabling High DPI support - fonts in - # javascript dialogs (alert) are tiny. However, you can implement - # custom javascript dialogs using JavascriptDialogHandler. - # - # Additionally you have to set "auto_zomming" application - # setting. High DPI support is available only on Windows. - # You may set auto_zooming to "system_dpi" and browser - # contents will be zoomed using OS DPI settings. On Win7 - # these can be set in: Control Panel > Appearance and - # Personalization > Display. - # - # Example values for auto_zooming are: - # "system_dpi", "0.0" (96 DPI), "1.0" (120 DPI), - # "2.0" (144 DPI), "-1.0" (72 DPI) - # Numeric value means a zoom level. - # Example values that can be set in Win7 DPI settings: - # Smaller 100% (Default) = 96 DPI = 0.0 zoom level - # Medium 125% = 120 DPI = 1.0 zoom level - # Larger 150% = 144 DPI = 2.0 zoom level - # Custom 75% = 72 DPI = -1.0 zoom level - g_applicationSettings["auto_zooming"] = "system_dpi" - print("[wxpython.py] Calling SetProcessDpiAware") - cefpython.DpiAware.SetProcessDpiAware() - - # Browser settings. You may have different settings for each - # browser, see the call to CreateBrowserSync. - g_browserSettings = { - # "plugins_disabled": True, - # "file_access_from_file_urls_allowed": True, - # "universal_access_from_file_urls_allowed": True, - } - - # Command line switches set programmatically - g_commandLineSwitches = { - # "proxy-server": "socks5://127.0.0.1:8888", - # "no-proxy-server": "", - # "enable-media-stream": "", - # "disable-gpu": "", - - } - - cefpython.Initialize(g_applicationSettings, g_commandLineSwitches) - - app = MyApp(False) - app.MainLoop() - - # Let wx.App destructor do the cleanup before calling - # cefpython.Shutdown(). This is to ensure reliable CEF shutdown. - del app - - cefpython.Shutdown() - diff --git a/tools/common.py b/tools/common.py index 3df0404b9..f710b4d95 100644 --- a/tools/common.py +++ b/tools/common.py @@ -320,7 +320,7 @@ def get_cefpython_binary_basename(postfix2, ignore_error=False): def get_setup_installer_basename(version, postfix2): - setup_basename = ("cefpython3-{version}-{os}-setup" + setup_basename = ("cefpython3_{version}_{os}" .format(version=version, os=postfix2)) return setup_basename From 1fa43af99f3b273989d5594b54413218590c748d Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 20 Mar 2017 11:45:09 +0100 Subject: [PATCH 183/557] Fix build.py tool broken in previous commit --- tools/build.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/build.py b/tools/build.py index 7debfffcb..1d32dcf1d 100644 --- a/tools/build.py +++ b/tools/build.py @@ -806,9 +806,8 @@ def install_and_run(): os.chdir(BUILD_DIR) # Setup installer directory - setup_installer_dir = ("./cefpython3-{version}-{os}-setup/" - .format(version=VERSION, os=OS_POSTFIX2)) - setup_installer_dir = os.path.join(BUILD_DIR, setup_installer_dir) + setup_basename = get_setup_installer_basename(VERSION, OS_POSTFIX2) + setup_installer_dir = os.path.join(BUILD_DIR, setup_basename) # Delete setup installer directory if exists if os.path.exists(setup_installer_dir): From 9537590c8ff11d21a516de68464465f706b4b646 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 20 Mar 2017 13:14:26 +0100 Subject: [PATCH 184/557] Fix v56.1 build on Mac (#335) --- src/client_handler/js_dialog_handler.cpp | 6 ++++++ src/compile_time_constants.pxi | 4 ++-- tools/automate.py | 2 +- tools/build_distrib.py | 14 +++++++++----- tools/common.py | 10 ++++++---- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/client_handler/js_dialog_handler.cpp b/src/client_handler/js_dialog_handler.cpp index 3d3ecd09f..15dfc848e 100644 --- a/src/client_handler/js_dialog_handler.cpp +++ b/src/client_handler/js_dialog_handler.cpp @@ -27,12 +27,14 @@ bool JSDialogHandler::OnJSDialog(CefRefPtr browser, dialog_type, message_text, default_prompt_text, callback, suppress_message); +#if defined(OS_LINUX) if (!ret) { // Default implementation return dialog_handler_->OnJSDialog(browser, origin_url, dialog_type, message_text, default_prompt_text, callback, suppress_message); } +#endif return ret; } @@ -47,11 +49,13 @@ bool JSDialogHandler::OnBeforeUnloadDialog( bool ret = JavascriptDialogHandler_OnBeforeUnloadJavascriptDialog( browser, message_text, is_reload, callback); +#if defined(OS_LINUX) if (!ret) { // Default implementation return dialog_handler_->OnBeforeUnloadDialog(browser, message_text, is_reload, callback); } +#endif return ret; } @@ -59,8 +63,10 @@ bool JSDialogHandler::OnBeforeUnloadDialog( void JSDialogHandler::OnResetDialogState(CefRefPtr browser) { REQUIRE_UI_THREAD(); +#if defined(OS_LINUX) // Default implementation dialog_handler_->OnResetDialogState(browser); +#endif // User implementation JavascriptDialogHandler_OnResetJavascriptDialogState(browser); } diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 35f850027..457e4a580 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 = "Darwin" +DEF PY_MAJOR_VERSION = 3 diff --git a/tools/automate.py b/tools/automate.py index 1a12398e5..9e192eb1c 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -598,7 +598,7 @@ def build_wrapper_library_mac(): # from cefclient. cmake_wrapper = prepare_build_command(build_lib=True) cmake_wrapper.extend(["cmake", "-G", "Ninja", - "-DPROJECT_ARCH=x86_64" + "-DPROJECT_ARCH=x86_64", "-DCMAKE_CXX_FLAGS=-stdlib=libc++", "-DCMAKE_BUILD_TYPE=" + Options.build_type, ".."]) diff --git a/tools/build_distrib.py b/tools/build_distrib.py index a88f059cc..7466caf89 100644 --- a/tools/build_distrib.py +++ b/tools/build_distrib.py @@ -6,8 +6,6 @@ Build distribution packages for all architectures and all supported python versions. -TODO: Mac support. Currently runs only on Windows/Linux. - Usage: build_distrib.py VERSION [--no-run-examples] [--no-rebuild] @@ -24,9 +22,11 @@ 1. Expects that all supported python versions are installed a) On Windows search for Pythons in the multiple default install locations - b) On Mac use system Python 2.7 and Python 3 from ~/.pyenv/versions/ + b) On Linux use only Pythons from ~/.pyenv/versions/ directory - c) On Linux use only Pythons from ~/.pyenv/versions/ directory + c) On Mac use Pythons from ~/.pyenv/versions/ and /usr/local/bin/python + For example will use Python 2.7.13 from /usr/local/bin/ only + when 2.7 was not found in ~/.pyenv/versions/. 2. Expects that all python compilers for supported python versions are installed. See docs/Build-instructions.md > Requirements. 3. Expects cef_binary*/ directories from Spotify Automated Builds @@ -83,6 +83,10 @@ LINUX=[ "%PYENV_ROOT%/versions/*/bin", ], + MAC=[ + "%PYENV_ROOT%/versions/*/bin", + "/usr/local/bin", + ], ) @@ -516,7 +520,7 @@ def test_wheel_packages(pythons): print("[build_distrib.py] Test wheel package (install, unittests) for" " {python_name}".format(python_name=python["name"])) platform_tag = get_pypi_postfix2_for_arch(python["arch"]) - whl_pattern = (r"*-{platform_tag}.whl" + whl_pattern = (r"*{platform_tag}.whl" .format(platform_tag=platform_tag)) wheels = glob.glob(os.path.join(DISTRIB_DIR, whl_pattern)) assert len(wheels) == 1, ("No wheels found in distrib dir for %s" diff --git a/tools/common.py b/tools/common.py index f710b4d95..c6b886480 100644 --- a/tools/common.py +++ b/tools/common.py @@ -47,24 +47,26 @@ # Platforms SYSTEM = platform.system().upper() +if SYSTEM == "DARWIN": + SYSTEM = "MAC" WINDOWS = SYSTEM if SYSTEM == "WINDOWS" else False LINUX = SYSTEM if SYSTEM == "LINUX" else False -MAC = SYSTEM if SYSTEM == "DARWIN" else False +MAC = SYSTEM if SYSTEM == "MAC" else False OS_POSTFIX2_ARCH = dict( WINDOWS={"32bit": "win32", "64bit": "win64"}, LINUX={"32bit": "linux32", "64bit": "linux64"}, - DARWIN={"32bit": "mac32", "64bit": "mac64"}, + MAC={"32bit": "mac32", "64bit": "mac64"}, ) CEF_POSTFIX2_ARCH = dict( WINDOWS={"32bit": "windows32", "64bit": "windows64"}, LINUX={"32bit": "linux32", "64bit": "linux64"}, - DARWIN={"64bit": "macosx64"}, + MAC={"64bit": "macosx64"}, ) PYPI_POSTFIX2_ARCH = dict( WINDOWS={"32bit": "win32", "64bit": "win_amd64"}, LINUX={"32bit": "manylinux1_i686", "64bit": "manylinux1_x86_64"}, - DARWIN={"64bit": "x86_64"}, + MAC={"64bit": "x86_64"}, ) # Python version eg. 27 From 264ce187a3bf14670f91002911f2628139cf6f28 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 20 Mar 2017 20:41:22 +0100 Subject: [PATCH 185/557] Update README - add support matrixes and install/examples sections --- README.md | 55 +++++++++++++++++++++++++------------ examples/Examples-README.md | 9 +++--- 2 files changed, 41 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index a656c62da..56654a93b 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,11 @@ Table of contents: * [Introduction](#introduction) +* [Install](#install) +* [Examples](#examples) * [Support](#support) * [Releases](#releases) - * [v50+ releases](#v50-releases) + * [v56+ releases](#v56-releases) * [v31 release](#v31-release) * [Support development](#support-development) * [Thanks](#thanks) @@ -38,6 +40,21 @@ applications. You can use it for web scraping or as a web crawler, or other kind of internet bots. +## Install + +You can install with pip. On Linux pip 8.1+ is required. You can +also download packages for offline installation available on the +[GitHub Releases](../../releases) pages. + +``` +pip install cefpython3==56.1 +``` + +## Examples + +See the [Examples-README.md](examples/Examples-README.md) file. + + ## Support - Ask questions, report problems and issues on the [Forum](https://groups.google.com/group/cefpython) @@ -49,28 +66,30 @@ or other kind of internet bots. ## Releases -### v50+ releases +Information on supported platforms, python versions, architectures +and requirements. If you want to support old operating systems then +choose the v31 release. -- Can be installed on all platforms using `pip install cefpython3` command -- Downloads are available on [GitHub Releases](../../releases) pages -- Windows support: 32-bit and 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 - (requirements: Windows 7+) -- Linux support: 32-bit and 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 - (requirements: Debian 7+ / Ubuntu 12.04+) -- Mac support: 64-bit, Python 2.7 / 3.4 / 3.5 / 3.6 - (requirements: MacOS 10.9+) -- Documentation is in the [docs/](docs) directory -- API reference is in the [api/](api) directory -- Additional documentation is in issues labelled [Knowledge Base](../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) +### v56+ releases + +OS | Py2 | Py3 | 32bit | 64bit | Requirements +--- | --- | --- | --- | --- | --- +Windows | 2.7 | 3.4 / 3.5 / 3.6 | Yes | Yes | Windows 7+ +Linux | 2.7 | 3.4 / 3.5 / 3.6 | Yes | Yes | Debian 7+ / Ubuntu 12.04+ +Mac | 2.7 | 3.4 / 3.5 / 3.6 | No | Yes | MacOS 10.9+ ### v31 release +OS | Py2 | Py3 | 32bit | 64bit | Requirements +--- | --- | --- | --- | --- | --- +Windows | 2.7 | No | Yes | Yes | Windows XP+ +Linux | 2.7 | No | Yes | Yes | Debian 7+ / Ubuntu 12.04+ +Mac | 2.7 | No | Yes | Yes | MacOS 10.7+ + +Additional information for v31.2 release: +- On Windows/Mac you can install with command: `pip install cefpython3==31.2` - Downloads are available on [wiki pages](../../wiki#downloads) - and on GH Releases tagged [v31.2](../../releases/tag/v31.2) -- Supports only Python 2.7 -- Windows support: 32-bit and 64-bit (requirements: Windows XP+) -- Linux support: 32-bit and 64-bit (requirements: Debian 7+ / Ubuntu 12.04+) -- Mac support: 32-bit and 64-bit (requirements: MacOS 10.7+) + and on GitHub Releases tagged [v31.2](../../releases/tag/v31.2). - Documentation is on [wiki pages](../../wiki) - API reference is available in revision [169a1b2](../../tree/169a1b20d3cd09879070d41aab28cfa195d2a7d5/docs/api) diff --git a/examples/Examples-README.md b/examples/Examples-README.md index d7bb153cb..a611d860b 100644 --- a/examples/Examples-README.md +++ b/examples/Examples-README.md @@ -12,15 +12,14 @@ maintained: - [gtk2.py](gtk2.py): example for [PyGTK](http://www.pygtk.org/) library (GTK 2) -- [gtk3.py](gtk3.py): example for [PyGObject/PyGI] - (https://wiki.gnome.org/Projects/PyGObject) library (GTK 3). - Currently broken on Linux/Mac, see top comments in sources. +- [gtk3.py](gtk3.py): example for [PyGObject/PyGI](https://wiki.gnome.org/Projects/PyGObject) + library (GTK 3). Currently broken on Linux/Mac, see top comments in sources. - [hello_world.py](hello_world.py): doesn't require any third party GUI framework - [qt4.py](qt4.py): example for [PyQt4](https://wiki.python.org/moin/PyQt4) and [PySide](https://wiki.qt.io/PySide) libraries (Qt 4) -- [tkinter_.py](tkinter_.py): example for [Tkinter] - (https://wiki.python.org/moin/TkInter). Currently broken on Mac. +- [tkinter_.py](tkinter_.py): example for [Tkinter](https://wiki.python.org/moin/TkInter). + Currently broken on Mac. - [wxpython.py](wxpython.py): example for [wxPython](https://wxpython.org/) If there are any issues in examples read top comments in sources From 0d5afb5dffd36cbb959b152ab69cac326e0593db Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 20 Mar 2017 20:56:18 +0100 Subject: [PATCH 186/557] Update README - add info on ARM and Android --- README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 56654a93b..8690e61e2 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Table of contents: * [Examples](#examples) * [Support](#support) * [Releases](#releases) - * [v56+ releases](#v56-releases) + * [Latest release](#latest-release) * [v31 release](#v31-release) * [Support development](#support-development) * [Thanks](#thanks) @@ -70,7 +70,7 @@ Information on supported platforms, python versions, architectures and requirements. If you want to support old operating systems then choose the v31 release. -### v56+ releases +### Latest release OS | Py2 | Py3 | 32bit | 64bit | Requirements --- | --- | --- | --- | --- | --- @@ -78,6 +78,13 @@ Windows | 2.7 | 3.4 / 3.5 / 3.6 | Yes | Yes | Windows 7+ Linux | 2.7 | 3.4 / 3.5 / 3.6 | Yes | Yes | Debian 7+ / Ubuntu 12.04+ Mac | 2.7 | 3.4 / 3.5 / 3.6 | No | Yes | MacOS 10.9+ +These platforms are not yet supported: + +OS | More info +--- | --- +ARM | [Issue #267](../../issues/267) +Android | [Issue #303](../../issues/303) + ### v31 release OS | Py2 | Py3 | 32bit | 64bit | Requirements From ea14b98cb4a6a71dd3d4f32a037c55848e3b8f9a Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 20 Mar 2017 20:57:32 +0100 Subject: [PATCH 187/557] Fix link in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8690e61e2..0bfae188e 100644 --- a/README.md +++ b/README.md @@ -78,12 +78,12 @@ Windows | 2.7 | 3.4 / 3.5 / 3.6 | Yes | Yes | Windows 7+ Linux | 2.7 | 3.4 / 3.5 / 3.6 | Yes | Yes | Debian 7+ / Ubuntu 12.04+ Mac | 2.7 | 3.4 / 3.5 / 3.6 | No | Yes | MacOS 10.9+ -These platforms are not yet supported: +These platforms are not supported yet: OS | More info --- | --- ARM | [Issue #267](../../issues/267) -Android | [Issue #303](../../issues/303) +Android | [Issue #307](../../issues/307) ### v31 release From ee46c0f965e7f8754b349f8d01beb6a13c8d6f57 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Tue, 21 Mar 2017 12:56:43 +0100 Subject: [PATCH 188/557] Update README's - hello world example and documentation search --- README.md | 3 +++ examples/Examples-README.md | 18 ++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0bfae188e..e5c2c7d7e 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,9 @@ See the [Examples-README.md](examples/Examples-README.md) file. - Documentation is in the [docs/](docs) directory - API reference is in the [api/](api) directory - Additional documentation is 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 left pane. - Wiki pages are deprecated and for v31 only diff --git a/examples/Examples-README.md b/examples/Examples-README.md index a611d860b..974ddd21d 100644 --- a/examples/Examples-README.md +++ b/examples/Examples-README.md @@ -1,26 +1,40 @@ # Examples README Table of contents: +* [Hello World!](#hello-world) * [Supported examples](#supported-examples) * [More examples](#more-examples) +## Hello World! + +Instructions to install the cefpython3 package, clone the repository +and run the hello_world.py example: + +``` +pip install cefpython3==56.1 +git clone https://github.com/cztomczak/cefpython.git +cd cefpython/ +python hello_world.py +``` + ## Supported examples Examples provided in the examples/ root directory are actively maintained: +- [hello_world.py](hello_world.py): basic example, doesn't require any + third party GUI framework to run - [gtk2.py](gtk2.py): example for [PyGTK](http://www.pygtk.org/) library (GTK 2) - [gtk3.py](gtk3.py): example for [PyGObject/PyGI](https://wiki.gnome.org/Projects/PyGObject) library (GTK 3). Currently broken on Linux/Mac, see top comments in sources. -- [hello_world.py](hello_world.py): doesn't require any third party - GUI framework - [qt4.py](qt4.py): example for [PyQt4](https://wiki.python.org/moin/PyQt4) and [PySide](https://wiki.qt.io/PySide) libraries (Qt 4) - [tkinter_.py](tkinter_.py): example for [Tkinter](https://wiki.python.org/moin/TkInter). Currently broken on Mac. - [wxpython.py](wxpython.py): example for [wxPython](https://wxpython.org/) + toolkit If there are any issues in examples read top comments in sources to see whether this is a known issue with available workarounds. From 4b2b8de61c5a91db3935da6fc723c5b4404e7026 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Tue, 21 Mar 2017 12:58:43 +0100 Subject: [PATCH 189/557] Fix typo in README --- examples/Examples-README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Examples-README.md b/examples/Examples-README.md index 974ddd21d..6e76fb4d7 100644 --- a/examples/Examples-README.md +++ b/examples/Examples-README.md @@ -13,7 +13,7 @@ and run the hello_world.py example: ``` pip install cefpython3==56.1 git clone https://github.com/cztomczak/cefpython.git -cd cefpython/ +cd cefpython/examples/ python hello_world.py ``` From 14342b3b9feaa3d22779ab197a5e003ad186a1a5 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 22 Mar 2017 17:35:20 +0100 Subject: [PATCH 190/557] Update README - minor fix --- README.md | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index e5c2c7d7e..299271fd6 100644 --- a/README.md +++ b/README.md @@ -82,11 +82,8 @@ Linux | 2.7 | 3.4 / 3.5 / 3.6 | Yes | Yes | Debian 7+ / Ubuntu 12.04+ Mac | 2.7 | 3.4 / 3.5 / 3.6 | No | Yes | MacOS 10.9+ These platforms are not supported yet: - -OS | More info ---- | --- -ARM | [Issue #267](../../issues/267) -Android | [Issue #307](../../issues/307) +- ARM - see [Issue #267](../../issues/267) +- Android - see [Issue #307](../../issues/307) ### v31 release @@ -111,12 +108,11 @@ by making a donation please click the Paypal Donate button: - +

      -At this time CEF Python is unable to accept donations that sponsor the -development of specific features. However you can make a donation with -a comment that you would like to see some feature implemented and it will -give it a higher priority. +If you would like to see some feature implemented you can make +a comment about that when making a donation. It will give it +a higher priority. If you are interested in sponsorship opportunities please contact Czarek directly. From b3ad7baa853896f2593520411b889716719e70b7 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 22 Mar 2017 17:51:55 +0100 Subject: [PATCH 191/557] Update README - minor fixes --- README.md | 9 ++------- tools/toc.py | 5 +++++ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 299271fd6..d624fb587 100644 --- a/README.md +++ b/README.md @@ -6,14 +6,9 @@ Table of contents: * [Examples](#examples) * [Support](#support) * [Releases](#releases) - * [Latest release](#latest-release) - * [v31 release](#v31-release) * [Support development](#support-development) * [Thanks](#thanks) * [Quick links](#quick-links) - * [Docs](#docs) - * [API categories](#api-categories) - * [API index](#api-index) ## Introduction @@ -73,7 +68,7 @@ Information on supported platforms, python versions, architectures and requirements. If you want to support old operating systems then choose the v31 release. -### Latest release +**Latest release** OS | Py2 | Py3 | 32bit | 64bit | Requirements --- | --- | --- | --- | --- | --- @@ -85,7 +80,7 @@ These platforms are not supported yet: - ARM - see [Issue #267](../../issues/267) - Android - see [Issue #307](../../issues/307) -### v31 release +**v31 release** OS | Py2 | Py3 | 32bit | 64bit | Requirements --- | --- | --- | --- | --- | --- diff --git a/tools/toc.py b/tools/toc.py index b7f64c1be..a9749d35a 100644 --- a/tools/toc.py +++ b/tools/toc.py @@ -113,6 +113,11 @@ def create_toc(contents, file_): contents += os.linesep + toc + os.linesep + os.linesep toc_inserted = True contents += line + os.linesep + # Special case for README.md - remove Quick Links toc for subheadings + re_find = (r" \* \[Docs\]\(#docs\)[\r\n]+" + r" \* \[API categories\]\(#api-categories\)[\r\n]+" + r" \* \[API index\]\(#api-index\)\r?\n?") + contents = re.sub(re_find, "", contents) return tocsize, contents, warnings From de9b0b2b37e2634b4ae589e29379322aa8a8dcef Mon Sep 17 00:00:00 2001 From: cztomczak Date: Thu, 23 Mar 2017 21:10:51 +0100 Subject: [PATCH 192/557] Fix CEF warnings/errors not saved to debug.log when --debug flag is specified. --- Authors | 2 +- src/cefpython.pyx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Authors b/Authors index 89576d339..28a008d75 100644 --- a/Authors +++ b/Authors @@ -1,5 +1,5 @@ Core developers: -Czarek Tomczak +Czarek Tomczak Contributors: 老农 cjjer diff --git a/src/cefpython.pyx b/src/cefpython.pyx index 64b1fe7c9..9a492764c 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -612,6 +612,7 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): global g_debugFile if "--debug" in sys.argv: application_settings["debug"] = True + application_settings["log_file"] = "debug.log" application_settings["log_severity"] = LOGSEVERITY_WARNING sys.argv.remove("--debug") if "debug" in application_settings: From 4301258755182d53b7d5fadacc64bed17b7deb0d Mon Sep 17 00:00:00 2001 From: cztomczak Date: Fri, 24 Mar 2017 19:17:49 +0100 Subject: [PATCH 193/557] Complete Migration Guide document (#293) --- README.md | 2 +- docs/Examples.md | 2 +- docs/Migration-guide.md | 215 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 211 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d624fb587..2dda89340 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ See the [Examples-README.md](examples/Examples-README.md) file. - Additional documentation is 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 left pane. + "Markdown" in the right pane. - Wiki pages are deprecated and for v31 only diff --git a/docs/Examples.md b/docs/Examples.md index aa2af612e..9aa065e59 100644 --- a/docs/Examples.md +++ b/docs/Examples.md @@ -1,4 +1,4 @@ # Examples Examples are available in the examples/ root directory. See -[Examples-README.md](../examples/Examples-README.md). +the [Examples-README.md](../examples/Examples-README.md) file. diff --git a/docs/Migration-guide.md b/docs/Migration-guide.md index 9a1ceeea7..0ee6ca991 100644 --- a/docs/Migration-guide.md +++ b/docs/Migration-guide.md @@ -1,12 +1,44 @@ -# Migration guide from v31 to latest v55+ (STILL UNDER WORKS.. #293) +# Migration guide + +This migration guide will get you through to make your code work +with latest CEF Python. This document includes notable changes +that were introduced to cefpython and each topic is prefixed +with version number in which a change was introduced. +This migration guide doesn't cover all changes required for your +software to run smoothly. Some changes depend on the GUI framework +you are using and this guide doesn't cover these. You will have +to go to the examples/ root directory and see the example for your +GUI framework. The new examples are very straightforward and include +many useful comments explaining whys. You will have to get through +its code and see if anything changed that also requires changes +in your application. Table of contents: -* [Distribution packages](#distribution-packages) -* [Handlers' callbacks and other interfaces](#handlers-callbacks-and-other-interfaces) +* [v50+ Distribution packages](#v50-distribution-packages) +* [v50+ Importing the cefpython3 package on Linux](#v50-importing-the-cefpython3-package-on-linux) +* [v50+ Install X11 error handlers on Linux](#v50-install-x11-error-handlers-on-linux) +* [v50+ Set window bounds on Linux](#v50-set-window-bounds-on-linux) +* [v50+ Notify CEF on move or resize events](#v50-notify-cef-on-move-or-resize-events) +* [v50+ Keyboard focus issues on Linux](#v50-keyboard-focus-issues-on-linux) +* [v50+ Windows XP and Vista are no more supported](#v50-windows-xp-and-vista-are-no-more-supported) +* [v50+ Mac 32-bit is no more supported](#v50-mac-32-bit-is-no-more-supported) +* [v50+ cefbuilds.com is deprected, use Spotify Automated CEF Builds](#v50-cefbuildscom-is-deprected-use-spotify-automated-cef-builds) +* [v50+ Build instructions and build tools](#v50-build-instructions-and-build-tools) +* [v51+ Off-screen-rendering: new option "windowless_rendering_enabled"](#v51-off-screen-rendering-new-option-windowless_rendering_enabled) +* [v51+ Remove LifespanHandler.RunModal](#v51-remove-lifespanhandlerrunmodal) +* [v51+: BrowserSettings options removed](#v51-browsersettings-options-removed) +* [v51+ cef.Request.Flags changed](#v51-cefrequestflags-changed) +* [v51+ Request.GetHeaderMap and SetHeaderMap change](#v51-requestgetheadermap-and-setheadermap-change) +* [v54+ GTK 3 example doesn't work anymore on Linux](#v54-gtk-3-example-doesnt-work-anymore-on-linux) +* [v54+ libcef.so library is stripped from symbols on Linux](#v54-libcefso-library-is-stripped-from-symbols-on-linux) +* [v55+ HTTPS cache problems on pages with certificate errors](#v55-https-cache-problems-on-pages-with-certificate-errors) +* [v55.3+ Handlers' callbacks and other interfaces](#v553-handlers-callbacks-and-other-interfaces) +* [v56+ MacOS 10.9+ required to run](#v56-macos-109-required-to-run) + -## Distribution packages +## v50+ Distribution packages In latest CEF Python there are only two distribution packages available. The first one is a wheel package distributed through @@ -15,10 +47,14 @@ on Linux). The second one is a setup package available for download on the GitHub Releases pages, instructions on how to install it are provided in README.txt. +**Windows** + On Windows many of the distribution packages such as MSI, EXE, ZIP and InnoSetup files, are no more available. It is too much hassle to support these. +**Linux debian package** + On Linux the debian package is not supported anymore. Since pip 8.1+ added support for manylinux1 wheel packages, you can now easily install cefpython on Linux using the pip tool. @@ -31,7 +67,173 @@ in an automated manner, it might be reconsidered in the future to provide debian packages again. -## Handlers' callbacks and other interfaces +## v50+ Importing the cefpython3 package on Linux + +In the past on Linux it was required for the cefpython3 package +to be imported before any other packages due to tcmalloc global +hook being loaded. This is not required anymore, tcmalloc is +disabled by default. + + +## v50+ Install X11 error handlers on Linux + +It is required to install X11 error handlers on Linux, otherwise +you will see 'BadWindow' errors happening - sometimes randomly - +which will cause application to terminate. Since v56+ x11 error +handlers are installed automatically by default during the call +to cef.Initialize(). However sometimes that is not enough like +for example in the wxpython.py example which requires the x11 +error handlers to be installed manually after wx was initialized, +and that is because wx initialization had reset x11 error handlers +that were installed earlier during cef initialization (Issue [#334](../../../issues/334)). + +You can install X11 error handlers by calling: +``` +WindowUtils = cef.WindowUtils() +WindowUtils.InstallX11ErrorHandlers() +``` + +API ref: WindowUtils.[InstallX11ErrorHandlers()](../api/WindowUtils.md#installx11errorhandlers-linux) + + +## v50+ Set window bounds on Linux + +It is now required to set window bounds during window "resize", +"move" and "configure" events on Linux. You can do so by calling: + +``` +browser.SetBounds(x, y, width, height) +``` + +API ref: Browser.[SetBounds()](../api/Browser.md#setbounds) + + +## v50+ Notify CEF on move or resize events + +It is required to notify the browser on move or resize events +so that popup widgets (e.g. \) are displayed in the correct +location and dismissed when the window moves. Also so that +drag & drop areas are updated accordingly. + +``` +browser.NotifyMoveOrResizeStarted() +``` + +API ref: Browser.[NotifyMoveOrResizeStarted()](../api/Browser.md#notifymoveorresizestarted) + + +## v50+ Keyboard focus issues on Linux + +There several keyboard focus issues on Linux since CEF library +replaced GTK library with X11 library. Most of these issues are +fixed in examples by calling SetFocus in LoadHandler.OnLoadStart +during initial app loading and/or by calling SetFocus in +FocusHandler.OnGotFocus. This keyboard focus issues need to be +fixed in usptream CEF. For more details see Issue [#284](../../../issues/284). + + +## v50+ Windows XP and Vista are no more supported + +CEF Python v31.2 was the last version to support Windows XP. +This is due to Chromium/CEF dropping XP support, last version +that supported XP was CEF v49. + + +## v50+ Mac 32-bit is no more supported + +CEF Python v31.2 was the last version to support Mac 32-bit. +This is due to CEF/Chromium dropping 32-bit support, last version +that supported 32-bit was CEF v38. + + +## v50+ cefbuilds.com is deprected, use Spotify Automated CEF Builds + +The cefbuilds.com site with CEF prebuilt binaries is now deprecated. +From now on download prebuilt CEF binaries from the Spotify Automated +CEF Builds: + +http://opensource.spotify.com/cefbuilds/index.html + + +## v50+ Build instructions and build tools + +Many changes in regards to building CEF and CEF Python has changed. +There are now new tools in the tools/ root directory that fully +automate building CEF and CEF Python. CEF Python now provides +upstream CEF prebuilt binaries and libraries on GitHub Releases +tagged eg. "v56-upstream". With these binaries you can build +CEF Python from sources in less than 10 minutes. See the new +[Build instructions](Build-instructions.md) document. + + +## v51+ Off-screen-rendering: new option "windowless_rendering_enabled" + +When using off-screen-rendering you must set the ApplicationSettings +"windowless_rendering_enabled" option to True. This applies to +examples such as: Kivy, Panda3D and screenshot example. + +API ref: ApplicationSettings.[windowless_rendering_enabled](../api/ApplicationSettings.md#windowless_rendering_enabled) + + +## v51+ Remove LifespanHandler.RunModal + +LifespanHandler.RunModal callback is no more available. + + +## v51+: BrowserSettings options removed + +The following options were removed from BrowserSettings: +- user_style_sheet_location +- java_disabled +- accelerated_compositing +- author_and_user_styles_disabled + + +## v51+ cef.Request.Flags changed + +The following flags were removed from cef.Request.Flags: +- AllowCookies +- ReportLoadTiming +- ReportRawHeaders + +API ref: Request.[GetFlags](../api/Request.md#getflags) + + +## v51+ Request.GetHeaderMap and SetHeaderMap change + +GetHeaderMap() will not include the Referer value if any +and SetHeaderMap() will ignore the Referer value. + +API ref: Request.[GetHeaderMap](../api/Request.md#getheadermap) + + +## v54+ GTK 3 example doesn't work anymore on Linux + +Currently GTK 3 example is broken on Linux. You can either +downgrade to an old cefpython v53 (available on GitHub release +page) or use GTK 2 example. For more details on the problem see +Issue [#261](../../../issues/261). + + +## v54+ libcef.so library is stripped from symbols on Linux + +Symbols useful for debugging are no more available in libcef.so +shipped with distribution packages on Linux. This is explained +in details in Issue [#262](../../../issues/262). + + +## v55+ HTTPS cache problems on pages with certificate errors + +The fix for HTTPS cache problems on pages with certificate errors +is no more applied on Windows. + +Soon this will fix also won't be applied on Linux anymore when +cefpython starts using CEF prebuilt binaries from Spotify. + +See Issue [#125](../../../issues/125) for more details. + + +## v55.3+ Handlers' callbacks and other interfaces Since v55.3 all handlers' callbacks and other interfaces such as CookieVisitor, StringVisitor and WebRequestClient, are now called @@ -77,5 +279,6 @@ your code will definitely break, unless you've also used "http_code" for argument name. +## v56+ MacOS 10.9+ required to run - +CEF v55 was the last version to support MacOS 10.7. From 77c506b7c337a83aabda51f00df9f6a17c47d75e Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 25 Mar 2017 13:18:47 +0100 Subject: [PATCH 194/557] Fix Printing in the hello_world.py and tkinter_.py examples. Minor fixes. Added some code for testing CEF views. --- docs/Migration-guide.md | 6 +- examples/gtk2.py | 10 +-- src/browser.pyx | 1 - src/cefpython.pyx | 62 ++++++++++++++++- src/client_handler/dialog_handler_gtk.cpp | 4 ++ src/common/cefpython_public_api.h | 12 ++-- src/compile_time_constants.pxi | 4 +- src/extern/cef/cef_types.pxd | 9 +++ src/extern/cef/cef_views.pxd | 84 +++++++++++++++++++++++ src/frame.pyx | 1 - src/handlers/request_handler.pyx | 9 +++ src/linux/binaries_64bit/kivy_.py | 6 +- src/settings.pyx | 5 +- src/subprocess/cefpython_app.cpp | 13 ++++ src/subprocess/cefpython_app.h | 4 -- src/window_info.pyx | 7 +- 16 files changed, 208 insertions(+), 29 deletions(-) create mode 100644 src/extern/cef/cef_views.pxd diff --git a/docs/Migration-guide.md b/docs/Migration-guide.md index 0ee6ca991..3bab17bc4 100644 --- a/docs/Migration-guide.md +++ b/docs/Migration-guide.md @@ -27,7 +27,7 @@ Table of contents: * [v50+ Build instructions and build tools](#v50-build-instructions-and-build-tools) * [v51+ Off-screen-rendering: new option "windowless_rendering_enabled"](#v51-off-screen-rendering-new-option-windowless_rendering_enabled) * [v51+ Remove LifespanHandler.RunModal](#v51-remove-lifespanhandlerrunmodal) -* [v51+: BrowserSettings options removed](#v51-browsersettings-options-removed) +* [v51+ BrowserSettings options removed](#v51-browsersettings-options-removed) * [v51+ cef.Request.Flags changed](#v51-cefrequestflags-changed) * [v51+ Request.GetHeaderMap and SetHeaderMap change](#v51-requestgetheadermap-and-setheadermap-change) * [v54+ GTK 3 example doesn't work anymore on Linux](#v54-gtk-3-example-doesnt-work-anymore-on-linux) @@ -157,7 +157,7 @@ http://opensource.spotify.com/cefbuilds/index.html ## v50+ Build instructions and build tools -Many changes in regards to building CEF and CEF Python has changed. +There were many changes in regards to building CEF and CEF Python. There are now new tools in the tools/ root directory that fully automate building CEF and CEF Python. CEF Python now provides upstream CEF prebuilt binaries and libraries on GitHub Releases @@ -180,7 +180,7 @@ API ref: ApplicationSettings.[windowless_rendering_enabled](../api/ApplicationSe LifespanHandler.RunModal callback is no more available. -## v51+: BrowserSettings options removed +## v51+ BrowserSettings options removed The following options were removed from BrowserSettings: - user_style_sheet_location diff --git a/examples/gtk2.py b/examples/gtk2.py index 2f8821819..99d7cc140 100644 --- a/examples/gtk2.py +++ b/examples/gtk2.py @@ -49,10 +49,10 @@ def main(): def check_versions(): - print("[gkt2.py] CEF Python {ver}".format(ver=cef.__version__)) - print("[gkt2.py] Python {ver} {arch}".format( + print("[gtk2.py] CEF Python {ver}".format(ver=cef.__version__)) + print("[gtk2.py] Python {ver} {arch}".format( ver=platform.python_version(), arch=platform.architecture()[0])) - print("[gkt2.py] GTK {ver}".format(ver='.'.join( + print("[gtk2.py] GTK {ver}".format(ver='.'.join( map(str, list(gtk.gtk_version))))) assert cef.__version__ >= "55.3", "CEF Python v55.3+ required to run this" pygtk.require('2.0') @@ -64,11 +64,11 @@ def configure_message_loop(): print("[gtk2.py] Force --message-loop-cef flag on Mac") sys.argv.append("--message-loop-cef") if "--message-loop-cef" in sys.argv: - print("[gkt2.py] Message loop mode: CEF (best performance)") + print("[gtk2.py] Message loop mode: CEF (best performance)") g_message_loop = MESSAGE_LOOP_CEF sys.argv.remove("--message-loop-cef") else: - print("[gkt2.py] Message loop mode: TIMER") + print("[gtk2.py] Message loop mode: TIMER") g_message_loop = MESSAGE_LOOP_TIMER diff --git a/src/browser.pyx b/src/browser.pyx index 59c1aaf1e..edb3071a9 100644 --- a/src/browser.pyx +++ b/src/browser.pyx @@ -42,7 +42,6 @@ cdef PyBrowser GetPyBrowser(CefRefPtr[CefBrowser] cefBrowser, global g_pyBrowsers - # This probably ain't needed, but just to be sure. if cefBrowser == NULL or not cefBrowser.get(): raise Exception("{caller}: CefBrowser reference is NULL" .format(caller=callerIdStr)) diff --git a/src/cefpython.pyx b/src/cefpython.pyx index 9a492764c..7e5283cfd 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -384,7 +384,7 @@ cdef extern from *: # cannot cimport *, that would cause name conflicts with constants # noinspection PyUnresolvedReferences from cef_types cimport ( - CefSettings, CefBrowserSettings, CefRect, CefPoint, + CefSettings, CefBrowserSettings, CefRect, CefSize, CefPoint, CefKeyEvent, CefMouseEvent, CefScreenInfo, PathKey, PK_DIR_EXE, PK_DIR_MODULE, int32, uint32, int64, uint64, @@ -433,6 +433,8 @@ from cef_path_util cimport * from cef_drag_data cimport * from cef_image cimport * from main_message_loop cimport * +# noinspection PyUnresolvedReferences +from cef_views cimport * # ----------------------------------------------------------------------------- # GLOBAL VARIABLES @@ -775,6 +777,46 @@ def CreateBrowserSync(windowInfo=None, assert IsThread(TID_UI), ( "cefpython.CreateBrowserSync() may only be called on the UI thread") + """ + # CEF views + # noinspection PyUnresolvedReferences + cdef CefRefPtr[CefWindow] cef_window + # noinspection PyUnresolvedReferences + cdef CefRefPtr[CefBoxLayout] cef_box_layout + cdef CefBoxLayoutSettings cef_box_layout_settings + cdef CefRefPtr[CefPanel] cef_panel + if not windowInfo and browserSettings \ + and "window_title" in browserSettings: + # noinspection PyUnresolvedReferences + cef_window = CefWindow.CreateTopLevelWindow( + NULL) + Debug("CefWindow.GetChildViewCount = " + +str(cef_window.get().GetChildViewCount())) + + cef_window.get().CenterWindow(CefSize(800, 600)) + cef_window.get().SetBounds(CefRect(0, 0, 800, 600)) + # noinspection PyUnresolvedReferences + #cef_box_layout = cef_window.get().SetToBoxLayout( + # cef_box_layout_settings) + #cef_box_layout.get().SetFlexForView(cef_window, 1) + cef_window.get().SetToFillLayout() + # noinspection PyUnresolvedReferences + cef_panel = CefPanel.CreatePanel(NULL) + cef_window.get().AddChildView(cef_panel) + cef_window.get().Layout() + cef_window.get().SetVisible(True) + cef_window.get().Show() + cef_window.get().RequestFocus() + windowInfo = WindowInfo() + windowInfo.SetAsChild(cef_window.get().GetWindowHandle()) + Debug("CefWindow handle = "+str(cef_window.get().GetWindowHandle())) + """ + + # Only title was set in hello_world.py example + if windowInfo and not windowInfo.windowType: + windowInfo.SetAsChild(0) + + # No window info provided if not windowInfo: windowInfo = WindowInfo() windowInfo.SetAsChild(0) @@ -831,6 +873,9 @@ def CreateBrowserSync(windowInfo=None, else: Debug("CefBrowser::CreateBrowserSync() succeeded") + Debug("CefBrowser window handle = " + +str(cefBrowser.get().GetHost().get().GetWindowHandle())) + # Request context - part 2/2. if g_applicationSettings["unique_request_context_per_browser"]: requestContextHandler.get().SetBrowser(cefBrowser) @@ -842,6 +887,21 @@ def CreateBrowserSync(windowInfo=None, pyBrowser.SetUserData("__outerWindowHandle", int(windowInfo.parentWindowHandle)) + """ + if cef_window.get(): + cef_window.get().ReorderChildView(cef_panel, -1) + cef_window.get().Layout() + cef_window.get().Show() + cef_window.get().RequestFocus() + """ + + if windowInfo.parentWindowHandle == 0 and windowInfo.windowType == "child": + # Set window title in hello_world.py example + IF UNAME_SYSNAME == "Linux": + pass + ELIF UNAME_SYSNAME == "Darwin": + pass + return pyBrowser def MessageLoop(): diff --git a/src/client_handler/dialog_handler_gtk.cpp b/src/client_handler/dialog_handler_gtk.cpp index 1db132907..76bf18513 100644 --- a/src/client_handler/dialog_handler_gtk.cpp +++ b/src/client_handler/dialog_handler_gtk.cpp @@ -11,12 +11,15 @@ #include #include #include +#include #include #include "include/cef_browser.h" #include "include/cef_parser.h" #include "include/wrapper/cef_helpers.h" +#include "LOG_DEBUG.h" + #include "dialog_handler_gtk.h" #include "x11.h" @@ -156,6 +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"; gtk_init(0, NULL); InstallX11ErrorHandlers(); // Now the display is available diff --git a/src/common/cefpython_public_api.h b/src/common/cefpython_public_api.h index 7de519527..0fa115d41 100644 --- a/src/common/cefpython_public_api.h +++ b/src/common/cefpython_public_api.h @@ -9,6 +9,12 @@ #ifndef CEFPYTHON_PUBLIC_API_H #define CEFPYTHON_PUBLIC_API_H +// Includes required by "cefpython_fixed.h". +#include "include/cef_client.h" +#include "include/cef_urlrequest.h" +#include "include/cef_command_line.h" +#include "util.h" + #if defined(OS_WIN) #pragma warning(disable:4190) // cefpython API extern C-linkage warnings #endif @@ -24,12 +30,6 @@ #define DL_EXPORT(RTYPE) RTYPE #endif -// Includes required by "cefpython_fixed.h". -#include "include/cef_client.h" -#include "include/cef_urlrequest.h" -#include "include/cef_command_line.h" -#include "util.h" - #if PY_MAJOR_VERSION == 2 #if PY_MINOR_VERSION == 7 #include "../../build/build_cefpython/cefpython_py27_fixed.h" diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 457e4a580..35f850027 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 = "Darwin" -DEF PY_MAJOR_VERSION = 3 +DEF UNAME_SYSNAME = "Linux" +DEF PY_MAJOR_VERSION = 2 diff --git a/src/extern/cef/cef_types.pxd b/src/extern/cef/cef_types.pxd index 78484f6e0..60ace4f39 100644 --- a/src/extern/cef/cef_types.pxd +++ b/src/extern/cef/cef_types.pxd @@ -15,9 +15,13 @@ from libc.limits cimport UINT_MAX cdef extern from "include/internal/cef_types.h": + # noinspection PyUnresolvedReferences ctypedef int32_t int32 + # noinspection PyUnresolvedReferences ctypedef uint32_t uint32 + # noinspection PyUnresolvedReferences ctypedef int64_t int64 + # noinspection PyUnresolvedReferences ctypedef uint64_t uint64 IF UNAME_SYSNAME == "Windows": @@ -97,6 +101,11 @@ cdef extern from "include/internal/cef_types.h": CefRect() CefRect(int x, int y, int width, int height) + cdef cppclass CefSize: + int width, height + CefSize() + CefSize(int width, int height) + cdef cppclass CefPoint: pass diff --git a/src/extern/cef/cef_views.pxd b/src/extern/cef/cef_views.pxd new file mode 100644 index 000000000..09763a071 --- /dev/null +++ b/src/extern/cef/cef_views.pxd @@ -0,0 +1,84 @@ +# 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 + +from cef_ptr cimport CefRefPtr +from cef_browser cimport CefWindowHandle +from cef_types cimport CefRect, CefSize +from libcpp cimport bool as cpp_bool + + +cdef extern from "include/internal/cef_types.h": + ctypedef struct cef_insets_t: + int top; + int left; + int bottom; + int right; + + ctypedef enum cef_main_axis_alignment_t: + CEF_MAIN_AXIS_ALIGNMENT_START, + CEF_MAIN_AXIS_ALIGNMENT_CENTER, + CEF_MAIN_AXIS_ALIGNMENT_END, + + ctypedef enum cef_cross_axis_alignment_t: + CEF_CROSS_AXIS_ALIGNMENT_STRETCH, + CEF_CROSS_AXIS_ALIGNMENT_START, + CEF_CROSS_AXIS_ALIGNMENT_CENTER, + CEF_CROSS_AXIS_ALIGNMENT_END, + + ctypedef struct CefBoxLayoutSettings: + int horizontal; + int inside_border_horizontal_spacing; + int inside_border_vertical_spacing; + cef_insets_t inside_border_insets; + int between_child_spacing; + cef_main_axis_alignment_t main_axis_alignment; + cef_cross_axis_alignment_t cross_axis_alignment; + int minimum_cross_axis_size; + int default_flex; + +cdef extern from "include/views/cef_box_layout.h": + cdef cppclass CefBoxLayout: + void SetFlexForView(CefRefPtr[CefWindow] view, int flex) + +cdef extern from "include/views/cef_window_delegate.h": + cdef cppclass CefWindowDelegate: + pass + +cdef extern from "include/views/cef_view.h": + cdef cppclass CefView: + pass + +cdef extern from "include/views/cef_panel_delegate.h": + cdef cppclass CefPanelDelegate: + pass + +cdef extern from "include/views/cef_panel.h": + cdef cppclass CefPanel: + @staticmethod + CefRefPtr[CefPanel] CreatePanel(CefRefPtr[CefPanelDelegate] delegate) + + +cdef extern from "include/views/cef_fill_layout.h": + cdef cppclass CefFillLayout: + pass + +cdef extern from "include/views/cef_window.h": + cdef cppclass CefWindow: + @staticmethod + CefRefPtr[CefWindow] CreateTopLevelWindow( + CefRefPtr[CefWindowDelegate] delegate) + void Show() + CefWindowHandle GetWindowHandle() + void SetBounds(const CefRect& bounds) + void CenterWindow(const CefSize& size) + void SetVisible(cpp_bool visible) + void Layout() + CefRefPtr[CefFillLayout] SetToFillLayout() + CefRefPtr[CefBoxLayout] SetToBoxLayout( + const CefBoxLayoutSettings& settings) + void RequestFocus() + void RemoveAllChildViews() + size_t GetChildViewCount() + void AddChildView(CefRefPtr[CefPanel] view) + void ReorderChildView(CefRefPtr[CefPanel] view, int index) diff --git a/src/frame.pyx b/src/frame.pyx index 9342719c6..6535791dc 100644 --- a/src/frame.pyx +++ b/src/frame.pyx @@ -19,7 +19,6 @@ cdef PyFrame GetPyFrameById(int browserId, object frameId): cdef PyFrame GetPyFrame(CefRefPtr[CefFrame] cefFrame): global g_pyFrames - # This code probably ain't needed, but just to be sure. if cefFrame == NULL or not cefFrame.get(): raise Exception("GetPyFrame(): CefFrame reference is NULL") diff --git a/src/handlers/request_handler.pyx b/src/handlers/request_handler.pyx index b2cadbe7d..0df1d8670 100644 --- a/src/handlers/request_handler.pyx +++ b/src/handlers/request_handler.pyx @@ -358,6 +358,15 @@ cdef public cpp_bool RequestHandler_OnBeforePluginLoad( cdef py_bool returnValue cdef object clientCallback try: + # OnBeforePluginLoad is called from RequestContexthandler. + # The Browser object might not be available, because it is + # being set synchronously during CreateBrowserSync, after + # Browser is created. From testing it always works, however + # better be safe. + if not browser.get(): + Debug("WARNING: RequestHandler_OnBeforePluginLoad() failed," + " Browser object is not available") + return False py_browser = GetPyBrowser(browser, "OnBeforePluginLoad") py_plugin_info = CreatePyWebPluginInfo(plugin_info) clientCallback = GetGlobalClientCallback("OnBeforePluginLoad") diff --git a/src/linux/binaries_64bit/kivy_.py b/src/linux/binaries_64bit/kivy_.py index 477c4975f..7d7ef4cc0 100644 --- a/src/linux/binaries_64bit/kivy_.py +++ b/src/linux/binaries_64bit/kivy_.py @@ -187,9 +187,9 @@ def start_cef(self): # Start idle - CEF message loop work. Clock.schedule_once(self._message_loop_work, 0) - # CEF needs a valid window handle passed to SetAsOffscreen() - # for Printing to work. There is no API to get Kivy's window - # handle so creating a dummy hidden Window using GTK. + # TODO: For printing to work in off-screen-rendering mode + # it is enough to call gtk_init(). It is not required + # to provide window handle when calling SetAsOffscreen(). gtkwin = gtk.Window() gtkwin.realize() diff --git a/src/settings.pyx b/src/settings.pyx index 79efe6799..aeb663531 100644 --- a/src/settings.pyx +++ b/src/settings.pyx @@ -133,7 +133,10 @@ cdef void SetBrowserSettings( cdef CefString* cefString for key in browserSettings: - if key == "accept_language_list": + if key == "window_title": + # CEF Python only options. These are not to be found in CEF. + continue + elif key == "accept_language_list": cefString = new CefString(&cefBrowserSettings.accept_language_list) PyToCefStringPointer(browserSettings[key], cefString) del cefString diff --git a/src/subprocess/cefpython_app.cpp b/src/subprocess/cefpython_app.cpp index 9dd456a0d..63f9ad3ec 100644 --- a/src/subprocess/cefpython_app.cpp +++ b/src/subprocess/cefpython_app.cpp @@ -9,6 +9,12 @@ #include "common/cefpython_public_api.h" #endif +#if defined(OS_LINUX) +#include +#include +#include "print_handler_gtk.h" +#endif + #include "cefpython_app.h" #include "util.h" #include "include/wrapper/cef_closure_task.h" @@ -95,6 +101,13 @@ void CefPythonApp::OnContextInitialized() { #ifdef BROWSER_PROCESS REQUIRE_UI_THREAD(); #if defined(OS_LINUX) + // For print handler to work GTK must be initialized. This is + // required for hello_world.py example to work. + GdkDisplay* gdk_display = gdk_display_get_default(); + if (!gdk_display) { + LOG_DEBUG << "Initialize GTK"; + gtk_init(0, NULL); + } print_handler_ = new ClientPrintHandlerGtk(); #endif // OS_LINUX #endif // BROWSER_PROCESS diff --git a/src/subprocess/cefpython_app.h b/src/subprocess/cefpython_app.h index 63e30225c..e76b2691c 100644 --- a/src/subprocess/cefpython_app.h +++ b/src/subprocess/cefpython_app.h @@ -6,10 +6,6 @@ #include "include/cef_app.h" #include "include/cef_print_handler.h" -#if defined(OS_LINUX) -#include "print_handler_gtk.h" -#endif - #include // CefPythonApp class is instantiated in subprocess and in diff --git a/src/window_info.pyx b/src/window_info.pyx index 9cfe17fbd..2ac24df76 100644 --- a/src/window_info.pyx +++ b/src/window_info.pyx @@ -76,8 +76,10 @@ cdef class WindowInfo: cdef public py_string windowName cdef public py_bool transparentPainting - def __init__(self): + def __init__(self, title=""): self.transparentPainting = False + if title: + self.windowName = title cpdef py_void SetAsChild(self, WindowHandle parentWindowHandle, list windowRect=None): @@ -117,7 +119,8 @@ cdef class WindowInfo: % parentWindowHandle) self.parentWindowHandle = parentWindowHandle self.windowType = "popup" - self.windowName = str(windowName) + if windowName: + self.windowName = str(windowName) cpdef py_void SetAsOffscreen(self, WindowHandle parentWindowHandle): From 8315fb0ce7c42b68db8f1b53436fae13ada0d062 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 25 Mar 2017 16:29:25 +0100 Subject: [PATCH 195/557] Support for setting window title in hello_world.py example on Linux. Initialize GTK only when Print dialog is launched. --- api/cefpython.md | 20 ++++++++---------- examples/hello_world.py | 5 +++-- src/cefpython.pyx | 14 +++++++++++-- src/client_handler/util_mac.mm | 6 ++++++ src/client_handler/x11.cpp | 36 ++++++++++++++++---------------- src/client_handler/x11.h | 6 ++++++ src/extern/x11.pxd | 1 + src/subprocess/cefpython_app.cpp | 16 +++++++------- src/window_utils_linux.pyx | 3 --- 9 files changed, 64 insertions(+), 43 deletions(-) diff --git a/api/cefpython.md b/api/cefpython.md index d994c9443..3af53001f 100644 --- a/api/cefpython.md +++ b/api/cefpython.md @@ -48,22 +48,20 @@ synchronously. The async call to CefCreateBrowser is yet TODO. | window_info | [WindowInfo](WindowInfo.md) | | [settings](BrowserSettings.md) | [BrowserSettings](BrowserSettings.md) | | url | string | -| request_context | void | +| window_title | string | | __Return__ | [Browser](Browser.md) | -This function should only be called on the UI thread. The 'request_context' parameter is not yet implemented. You must first create a window and initialize 'window_info' by calling WindowInfo.SetAsChild(). +All parameters are optional. -After the call to CreateBrowserSync() the page is not yet loaded, if you want your next lines of code to do some stuff on the webpage you will have to implement [LoadHandler](LoadHandler.md).OnLoadEnd() callback, see example below: +This function can only be called on the UI thread. -```python -def OnLoadEnd(browser, frame, httpCode): - if frame == browser.GetMainFrame(): - print("Finished loading main frame: %s (http code = %d)" - % (frame.GetUrl(), httpCode)) +The "window_title" parameter will be used only +when parent window provided in window_info was set to 0. -browser = cefpython.CreateBrowserSync(windowInfo, settings, url) -browser.SetClientCallback("OnLoadEnd", OnLoadEnd) -``` +After the call to CreateBrowserSync() the page is not yet loaded, +if you want your next lines of code to do some stuff on the webpage +you will have to implement LoadHandler.[OnLoadEnd]((LoadHandler.md#onloadend)) +callback. ### ExceptHook diff --git a/examples/hello_world.py b/examples/hello_world.py index c29a2669f..bcacf379f 100644 --- a/examples/hello_world.py +++ b/examples/hello_world.py @@ -10,7 +10,8 @@ def main(): check_versions() sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error cef.Initialize() - cef.CreateBrowserSync(url="https://www.google.com/") + cef.CreateBrowserSync(window_title="Hello World!", + url="https://www.google.com/") cef.MessageLoop() cef.Shutdown() @@ -18,7 +19,7 @@ def main(): def check_versions(): print("[hello_world.py] CEF Python {ver}".format(ver=cef.__version__)) print("[hello_world.py] Python {ver} {arch}".format( - ver=platform.python_version(), arch=platform.architecture()[0])) + ver=platform.python_version(), arch=platform.architecture()[0])) assert cef.__version__ >= "55.3", "CEF Python v55.3+ required to run this" diff --git a/src/cefpython.pyx b/src/cefpython.pyx index 7e5283cfd..3863f0941 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -376,6 +376,9 @@ ELIF UNAME_SYSNAME == "Darwin": from cpp_utils cimport * from task cimport * +IF UNAME_SYSNAME == "Linux": + cimport x11 + from cef_string cimport * cdef extern from *: # noinspection PyUnresolvedReferences @@ -764,6 +767,7 @@ def CreateBrowser(**kwargs): def CreateBrowserSync(windowInfo=None, browserSettings=None, navigateUrl="", + window_title="", **kwargs): # Alternative names for existing parameters if "window_info" in kwargs: @@ -823,6 +827,9 @@ def CreateBrowserSync(windowInfo=None, elif not isinstance(windowInfo, WindowInfo): raise Exception("CreateBrowserSync() failed: windowInfo: invalid object") + if window_title and windowInfo.parentWindowHandle == 0: + windowInfo.windowName = window_title + if not browserSettings: browserSettings = {} @@ -895,10 +902,13 @@ def CreateBrowserSync(windowInfo=None, cef_window.get().RequestFocus() """ - if windowInfo.parentWindowHandle == 0 and windowInfo.windowType == "child": + if windowInfo.parentWindowHandle == 0\ + and windowInfo.windowType == "child"\ + and windowInfo.windowName: # Set window title in hello_world.py example IF UNAME_SYSNAME == "Linux": - pass + x11.SetX11WindowTitle(cefBrowser, + PyStringToChar(windowInfo.windowName)) ELIF UNAME_SYSNAME == "Darwin": pass diff --git a/src/client_handler/util_mac.mm b/src/client_handler/util_mac.mm index c0adfa09b..b1afa8f99 100644 --- a/src/client_handler/util_mac.mm +++ b/src/client_handler/util_mac.mm @@ -7,6 +7,7 @@ #include #include "include/cef_app.h" #include "include/cef_application_mac.h" +#include "include/cef_browser.h" namespace { @@ -64,3 +65,8 @@ - (void)_swizzled_terminate:(id)sender { void MacInitialize() { [NSApplication sharedApplication]; } + +void MacSetTitle(CefRefPtr browser, char* title) { + NSView* view = browser->GetHost()->GetWindowHandle(); + view.window!.title = title; +} diff --git a/src/client_handler/x11.cpp b/src/client_handler/x11.cpp index 9199f4c95..0c37bff40 100644 --- a/src/client_handler/x11.cpp +++ b/src/client_handler/x11.cpp @@ -2,23 +2,22 @@ // All rights reserved. Licensed under BSD 3-clause license. // Project website: https://github.com/cztomczak/cefpython -#include +#include "x11.h" #include "LOG_DEBUG.h" -#include "include/cef_browser.h" int XErrorHandlerImpl(Display *display, XErrorEvent *event) { - LOG_DEBUG + LOG_DEBUG << "X error received: " << "type " << event->type << ", " << "serial " << event->serial << ", " << "error_code " << static_cast(event->error_code) << ", " << "request_code " << static_cast(event->request_code) << ", " << "minor_code " << static_cast(event->minor_code); - return 0; + return 0; } int XIOErrorHandlerImpl(Display *display) { - return 0; + return 0; } void InstallX11ErrorHandlers() { @@ -29,20 +28,21 @@ void InstallX11ErrorHandlers() { XSetIOErrorHandler(XIOErrorHandlerImpl); } -void SetXWindowBounds(::Window xwindow, - int x, int y, size_t width, size_t height) { - ::Display* xdisplay = cef_get_xdisplay(); - XWindowChanges changes = {0}; - changes.x = x; - changes.y = y; - changes.width = static_cast(width); - changes.height = static_cast(height); - XConfigureWindow(xdisplay, xwindow, - CWX | CWY | CWHeight | CWWidth, &changes); -} - void SetX11WindowBounds(CefRefPtr browser, int x, int y, int width, int height) { ::Window xwindow = browser->GetHost()->GetWindowHandle(); - SetXWindowBounds(xwindow, x, y, width, height); + ::Display* xdisplay = cef_get_xdisplay(); + XWindowChanges changes = {0}; + changes.x = x; + changes.y = y; + changes.width = static_cast(width); + changes.height = static_cast(height); + XConfigureWindow(xdisplay, xwindow, + CWX | CWY | CWHeight | CWWidth, &changes); +} + +void SetX11WindowTitle(CefRefPtr browser, char* title) { + ::Window xwindow = browser->GetHost()->GetWindowHandle(); + ::Display* xdisplay = cef_get_xdisplay(); + XStoreName(xdisplay, xwindow, title); } diff --git a/src/client_handler/x11.h b/src/client_handler/x11.h index 863296fed..cd5931875 100644 --- a/src/client_handler/x11.h +++ b/src/client_handler/x11.h @@ -2,6 +2,12 @@ // All rights reserved. Licensed under BSD 3-clause license. // Project website: https://github.com/cztomczak/cefpython +#pragma once + +#include +#include "include/cef_browser.h" + void InstallX11ErrorHandlers(); void SetX11WindowBounds(CefRefPtr browser, int x, int y, int width, int height); +void SetX11WindowTitle(CefRefPtr browser, char* title); diff --git a/src/extern/x11.pxd b/src/extern/x11.pxd index 5963a1317..4e481f246 100644 --- a/src/extern/x11.pxd +++ b/src/extern/x11.pxd @@ -10,3 +10,4 @@ cdef extern from "client_handler/x11.h" nogil: void InstallX11ErrorHandlers() void SetX11WindowBounds(CefRefPtr[CefBrowser] browser, int x, int y, int width, int height) + void SetX11WindowTitle(CefRefPtr[CefBrowser] browser, char* title) diff --git a/src/subprocess/cefpython_app.cpp b/src/subprocess/cefpython_app.cpp index 63f9ad3ec..738728d86 100644 --- a/src/subprocess/cefpython_app.cpp +++ b/src/subprocess/cefpython_app.cpp @@ -101,13 +101,6 @@ void CefPythonApp::OnContextInitialized() { #ifdef BROWSER_PROCESS REQUIRE_UI_THREAD(); #if defined(OS_LINUX) - // For print handler to work GTK must be initialized. This is - // required for hello_world.py example to work. - GdkDisplay* gdk_display = gdk_display_get_default(); - if (!gdk_display) { - LOG_DEBUG << "Initialize GTK"; - gtk_init(0, NULL); - } print_handler_ = new ClientPrintHandlerGtk(); #endif // OS_LINUX #endif // BROWSER_PROCESS @@ -140,6 +133,15 @@ void CefPythonApp::OnRenderProcessThreadCreated( } CefRefPtr CefPythonApp::GetPrintHandler() { +#if defined(OS_LINUX) + // For print handler to work GTK must be initialized. This is + // required for some of the examples. + GdkDisplay* gdk_display = gdk_display_get_default(); + if (!gdk_display) { + LOG_DEBUG << "Initialize GTK"; + gtk_init(0, NULL); + } +#endif return print_handler_; } diff --git a/src/window_utils_linux.pyx b/src/window_utils_linux.pyx index ccd628e1c..63dda9c86 100644 --- a/src/window_utils_linux.pyx +++ b/src/window_utils_linux.pyx @@ -4,9 +4,6 @@ include "cefpython.pyx" -IF UNAME_SYSNAME == "Linux": - cimport x11 - class WindowUtils: # You have to overwrite this class and provide implementations # for these methods. From 90452e39b76fa3061d2f590248587d446c2d6081 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 25 Mar 2017 16:57:24 +0100 Subject: [PATCH 196/557] Support window title in hello_world.py example on Mac (#339) --- src/cefpython.pyx | 8 +++++--- src/client_handler/util_mac.h | 2 ++ src/client_handler/util_mac.mm | 5 +++-- src/compile_time_constants.pxi | 2 +- src/extern/mac.pxd | 6 +++++- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/cefpython.pyx b/src/cefpython.pyx index 3863f0941..f50919a8b 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -813,7 +813,8 @@ def CreateBrowserSync(windowInfo=None, cef_window.get().RequestFocus() windowInfo = WindowInfo() windowInfo.SetAsChild(cef_window.get().GetWindowHandle()) - Debug("CefWindow handle = "+str(cef_window.get().GetWindowHandle())) + Debug("CefWindow handle = " + +str(cef_window.get().GetWindowHandle())) """ # Only title was set in hello_world.py example @@ -881,7 +882,7 @@ def CreateBrowserSync(windowInfo=None, Debug("CefBrowser::CreateBrowserSync() succeeded") Debug("CefBrowser window handle = " - +str(cefBrowser.get().GetHost().get().GetWindowHandle())) + +str(cefBrowser.get().GetHost().get().GetWindowHandle())) # Request context - part 2/2. if g_applicationSettings["unique_request_context_per_browser"]: @@ -910,7 +911,8 @@ def CreateBrowserSync(windowInfo=None, x11.SetX11WindowTitle(cefBrowser, PyStringToChar(windowInfo.windowName)) ELIF UNAME_SYSNAME == "Darwin": - pass + MacSetWindowTitle(cefBrowser, + PyStringToChar(windowInfo.windowName)) return pyBrowser diff --git a/src/client_handler/util_mac.h b/src/client_handler/util_mac.h index 5641a1206..37ec7266b 100644 --- a/src/client_handler/util_mac.h +++ b/src/client_handler/util_mac.h @@ -8,7 +8,9 @@ #include #include "include/cef_base.h" #include "include/cef_app.h" +#include "include/cef_browser.h" void MacInitialize(); +void MacSetWindowTitle(CefRefPtr browser, char* title); #endif // CEFPYTHON_UTIL_MAC_H_ diff --git a/src/client_handler/util_mac.mm b/src/client_handler/util_mac.mm index b1afa8f99..f2e14cd1b 100644 --- a/src/client_handler/util_mac.mm +++ b/src/client_handler/util_mac.mm @@ -66,7 +66,8 @@ void MacInitialize() { [NSApplication sharedApplication]; } -void MacSetTitle(CefRefPtr browser, char* title) { +void MacSetWindowTitle(CefRefPtr browser, char* title) { NSView* view = browser->GetHost()->GetWindowHandle(); - view.window!.title = title; + NSString* nstitle = [NSString stringWithFormat:@"%s" , title]; + view.window.title = nstitle; } diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 35f850027..05306be6d 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 UNAME_SYSNAME = "Darwin" DEF PY_MAJOR_VERSION = 2 diff --git a/src/extern/mac.pxd b/src/extern/mac.pxd index 6d6b73a85..cca038b98 100644 --- a/src/extern/mac.pxd +++ b/src/extern/mac.pxd @@ -2,5 +2,9 @@ # All rights reserved. Licensed under BSD 3-clause license. # Project website: https://github.com/cztomczak/cefpython +from cef_ptr cimport CefRefPtr +from cef_browser cimport CefBrowser + cdef extern from "client_handler/util_mac.h": - cdef void MacInitialize() + void MacInitialize() + void MacSetWindowTitle(CefRefPtr[CefBrowser] browser, char* title) From b1156d389b613950109c3e24cbcc21fd9951263c Mon Sep 17 00:00:00 2001 From: cztomczak Date: Mon, 27 Mar 2017 11:11:48 +0200 Subject: [PATCH 197/557] Update docs for gtk functions in WindowUtils. --- api/WindowUtils.md | 7 ++++--- src/compile_time_constants.pxi | 2 +- src/settings.pyx | 5 +---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/api/WindowUtils.md b/api/WindowUtils.md index 4d292132e..a21d05b90 100644 --- a/api/WindowUtils.md +++ b/api/WindowUtils.md @@ -115,7 +115,7 @@ On Linux and Mac this method always returns True. @TODO. | long GdkNativeWindow | long | | __Return__ | void | -Linux-only. This method is utilized in the PyQt example. +Linux-only. ### gtk_widget_show (Linux) @@ -125,7 +125,7 @@ Linux-only. This method is utilized in the PyQt example. | long GtkWidget* | long | | __Return__ | void | -Linux-only. This method is utilized in the PyQt example. +Linux-only. ### InstallX11ErrorHandlers (Linux) @@ -139,4 +139,5 @@ won't be terminated on non-fatal errors. Must be done after initializing GTK. CEF Python calls this function automatically during a call to -Initialize, so there is no need to call it manually anymore. +Initialize, so there is no more need to call it manually in +most cases. diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 05306be6d..35f850027 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 = "Darwin" +DEF UNAME_SYSNAME = "Linux" DEF PY_MAJOR_VERSION = 2 diff --git a/src/settings.pyx b/src/settings.pyx index aeb663531..79efe6799 100644 --- a/src/settings.pyx +++ b/src/settings.pyx @@ -133,10 +133,7 @@ cdef void SetBrowserSettings( cdef CefString* cefString for key in browserSettings: - if key == "window_title": - # CEF Python only options. These are not to be found in CEF. - continue - elif key == "accept_language_list": + if key == "accept_language_list": cefString = new CefString(&cefBrowserSettings.accept_language_list) PyToCefStringPointer(browserSettings[key], cefString) del cefString From 9853a1edc5ed67dca17abc68395849bd9e117fa9 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 5 Apr 2017 07:12:02 +0200 Subject: [PATCH 198/557] Fix build on Linux --- docs/Build-instructions.md | 9 +++------ src/subprocess/cefpython_app.cpp | 7 ++++++- tools/automate.py | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index 3281810eb..c35ac91ab 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -183,7 +183,7 @@ requirements common for all platforms. ### Linux -* Install packages: `sudo apt-get install python-dev cmake g++ libgtk2.0-dev libgtkglext1-dev` +* Install packages: `sudo apt-get install cmake g++ libgtk2.0-dev libgtkglext1-dev` * If building CEF from sources: * Official binaries are built on Ubuntu 14.04 (cmake 2.8.12, g++ 4.8.4) * Download [ninja](http://martine.github.io/ninja/) 1.7.1 or later @@ -200,11 +200,8 @@ requirements common for all platforms. [cef/BuildingOnDebian7.md](https://bitbucket.org/chromiumembedded/cef/wiki/BuildingOnDebian7.md) and [cef/#1575](https://bitbucket.org/chromiumembedded/cef/issues/1575), and [cef/#1697](https://bitbucket.org/chromiumembedded/cef/issues/1697) -* If building CEF from sources, 32-bit on 64-bit machine: - * Follow the configuration [here](https://bitbucket.org/chromiumembedded/cef/wiki/AutomatedBuildSetup.md#markdown-header-linux-configuration) - * To perform a 32-bit Linux build on a 64-bit Linux system see - Linux configuration in upstream cef/AutomatedBuildSetup.md. See also - [cef/#1804](https://bitbucket.org/chromiumembedded/cef/issues/1804). +* Building CEF 32-bit is only possible using cross-compiling on + 64-bit machine. See [Issue #328](https://github.com/cztomczak/cefpython/issues/328). * Sometimes it is also required to install these packages (eg. chroot): `sudo apt-get install libnss3 libnspr4 libxss1 libgconf-2-4` diff --git a/src/subprocess/cefpython_app.cpp b/src/subprocess/cefpython_app.cpp index 738728d86..1f51ba270 100644 --- a/src/subprocess/cefpython_app.cpp +++ b/src/subprocess/cefpython_app.cpp @@ -9,11 +9,14 @@ #include "common/cefpython_public_api.h" #endif -#if defined(OS_LINUX) +#ifdef BROWSER_PROCESS +#ifdef OS_LINUX #include +#include #include #include "print_handler_gtk.h" #endif +#endif #include "cefpython_app.h" #include "util.h" @@ -133,6 +136,7 @@ void CefPythonApp::OnRenderProcessThreadCreated( } CefRefPtr CefPythonApp::GetPrintHandler() { +#ifdef BROWSER_PROCESS #if defined(OS_LINUX) // For print handler to work GTK must be initialized. This is // required for some of the examples. @@ -141,6 +145,7 @@ CefRefPtr CefPythonApp::GetPrintHandler() { LOG_DEBUG << "Initialize GTK"; gtk_init(0, NULL); } +#endif #endif return print_handler_; } diff --git a/tools/automate.py b/tools/automate.py index 9e192eb1c..cb97d8d2f 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -30,7 +30,7 @@ [--force-chromium-update FORCE_CHROMIUM_UPDATE] [--no-cef-update NO_CEF_UPDATE] [--cef-branch BRANCH] [--cef-commit COMMIT] - [--build-dir BUILD_DIR] [--cef-build-dir CEF_BUIL_DDIR] + [--build-dir BUILD_DIR] [--cef-build-dir CEF_BUILD_DIR] [--ninja-jobs JOBS] [--gyp-generators GENERATORS] [--gyp-msvs-version MSVS] automate.py (-h | --help) [type -h to show full description for options] @@ -900,7 +900,7 @@ def run_command(command, working_dir, env=None): env = getenv() # When passing list of args shell cannot be True on eg. Linux, read # notes in build.py - shell=(platform.system() == "Windows") + shell = (platform.system() == "Windows") return subprocess.check_call(args, cwd=working_dir, env=env, shell=shell) From 850ac552d58b02038d80e4ca921105c823414ae0 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Thu, 6 Apr 2017 22:16:06 +0200 Subject: [PATCH 199/557] Tutorial is almost complete (#256) Detect invalid arguments passed to cef.Initialize and cef.CreateBrowserSync. --- .gitignore | 1 + README.md | 16 +- api/API-categories.md | 2 +- api/ApplicationSettings.md | 6 +- api/JavascriptBindings.md | 6 - api/cefpython.md | 47 ++-- docs/Tutorial.md | 483 ++++++++++++++++++++++++++++-------- examples/Examples-README.md | 5 + examples/hello_world.py | 4 +- examples/tutorial.py | 104 ++++++++ src/cefpython.pyx | 9 + src/helpers.pyx | 55 ++-- 12 files changed, 574 insertions(+), 164 deletions(-) create mode 100644 examples/tutorial.py diff --git a/.gitignore b/.gitignore index 43cf72378..74815a1c6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ build/ __pycache__/ *.pyc cefclient +webcache/ diff --git a/README.md b/README.md index 2dda89340..29ab84797 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,11 @@ also download packages for offline installation available on the pip install cefpython3==56.1 ``` +## Tutorial + +See the [Tutorial.md](docs/Tutorial.md) file. + + ## Examples See the [Examples-README.md](examples/Examples-README.md) file. @@ -53,8 +58,15 @@ See the [Examples-README.md](examples/Examples-README.md) file. ## Support - Ask questions, report problems and issues on the [Forum](https://groups.google.com/group/cefpython) -- Documentation is in the [docs/](docs) directory -- API reference is in the [api/](api) directory +- 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) + - [Migration guide](docs/Migration-guide.md) + - [Tutorial](docs/Tutorial.md) +- 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) - To search documentation use GitHub "This repository" search at the top. To narrow results to documentation only select diff --git a/api/API-categories.md b/api/API-categories.md index cceb66fe7..1f4fc9922 100644 --- a/api/API-categories.md +++ b/api/API-categories.md @@ -36,7 +36,7 @@ * [WindowUtils](WindowUtils.md#windowutils-class) class -### Handlers (interfaces) +### Client handlers (interfaces) * [DisplayHandler](DisplayHandler.md#displayhandler-interface) * [DownloadHandler](DownloadHandler.md#downloadhandler) diff --git a/api/ApplicationSettings.md b/api/ApplicationSettings.md index f651941b8..390b3905a 100644 --- a/api/ApplicationSettings.md +++ b/api/ApplicationSettings.md @@ -447,9 +447,9 @@ default User-Agent string will be used. Also configurable using the (string) The location where user data such as spell checking dictionary files will be stored on disk. If empty then the default platform-specific user data -directory will be used ("~/.cef_user_data" directory on Linux, -"~/Library/Application Support/CEF/User Data" directory on Mac OS X, -"Local Settings\Application Data\CEF\User Data" directory under the user +directory will be used (`"~/.cef_user_data"` directory on Linux, +`"~/Library/Application Support/CEF/User Data"` directory on Mac OS X, +`"Local Settings\Application Data\CEF\User Data"` directory under the user profile directory on Windows). diff --git a/api/JavascriptBindings.md b/api/JavascriptBindings.md index b00aa9527..7083cd880 100644 --- a/api/JavascriptBindings.md +++ b/api/JavascriptBindings.md @@ -29,12 +29,6 @@ In CEF 3 communication between javascript and python can only be asynchronous. I There are plans to support binding data by reference (a list, dict or object's properties). This would be possible with the use of CefRegisterExtension(). -## Example usage - -See the [wxpython.py](../src/windows/binaries_32bit/wxpython.py) example for an example usage of javascript bindings, javascript callbacks and python callbacks. - - - ## Methods diff --git a/api/cefpython.md b/api/cefpython.md index 3af53001f..3409d8b48 100644 --- a/api/cefpython.md +++ b/api/cefpython.md @@ -55,12 +55,14 @@ All parameters are optional. This function can only be called on the UI thread. -The "window_title" parameter will be used only -when parent window provided in window_info was set to 0. +The "window_title" parameter will be used only when parent +window provided in window_info was set to 0. This is for use +with hello_world.py and tutorial.py examples which don't use +any third party GUI framework for creation of top-level window. After the call to CreateBrowserSync() the page is not yet loaded, -if you want your next lines of code to do some stuff on the webpage -you will have to implement LoadHandler.[OnLoadEnd]((LoadHandler.md#onloadend)) +if you want your next lines of code to do some stuff on the +webpage you will have to implement LoadHandler.[OnLoadingStateChange]((LoadHandler.md#onloadingstatechange)) callback. @@ -68,10 +70,10 @@ callback. | Parameter | Type | | --- | --- | -| excType | - | -| excValue | - | -| traceObject | - | -| __Return__ | string | +| exc_type | - | +| exc_value | - | +| exc_trace | - | +| __Return__ | void | Global except hook to exit app cleanly on error. CEF has a multiprocess architecture and when exiting you need to close all processes (main Browser @@ -99,6 +101,7 @@ to Initialize(). Returns None if key is not found. | | | | --- | --- | +| file_ (optional) | string | | __Return__ | string | Get path to where application resides. @@ -181,18 +184,7 @@ Returns true if called on the specified thread. CEF maintains multiple internal threads that are used for handling different types of tasks. The UI thread creates the browser window and is used for all interaction with the webkit rendering engine and V8 Javascript engine. The UI thread will be the same as the main application thread if CefInitialize() is called with an [ApplicationSettings](ApplicationSettings.md) 'multi_threaded_message_loop' option set to false. The IO thread is used for handling schema and network requests. The FILE thread is used for the application cache and other miscellaneous activities. -List of threads in the Browser process. These are constants defined in the cefpython module: - -* TID_UI: The main thread in the browser. This will be the same as the main application thread if cefpython.Initialize() is called with a ApplicationSettings.multi_threaded_message_loop value of false. -* TID_DB: Used to interact with the database. -* TID_FILE: Used to interact with the file system. -* TID_FILE_USER_BLOCKING: Used for file system operations that block user interactions. Responsiveness of this thread affects users. -* TID_PROCESS_LAUNCHER: Used to launch and terminate browser processes. -* TID_CACHE: Used to handle slow HTTP cache operations. -* TID_IO: Used to process IPC and network messages. - -List of threads in the Renderer process: -* TID_RENDERER: The main thread in the renderer. Used for all webkit and V8 interaction. +See PostTask() for a list of threads. ### MessageLoop @@ -244,10 +236,23 @@ Description from upstream CEF: | ... | *args | | __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, see IsThread() for a list of available threads and their descriptions. +Post a task for execution on the thread associated with this task runner. Execution will occur asynchronously. Only Browser process threads are allowed. An example usage is in the wxpython.py example on Windows, in implementation of LifespanHandler.OnBeforePopup(). +List of threads in the Browser process: +* cef.TID_UI: The main thread in the browser. This will be the same as the main application thread if cefpython.Initialize() is called with a ApplicationSettings.multi_threaded_message_loop value of false. +* cef.TID_DB: Used to interact with the database. +* cef.TID_FILE: Used to interact with the file system. +* cef.TID_FILE_USER_BLOCKING: Used for file system operations that block user interactions. Responsiveness of this thread affects users. +* cef.TID_PROCESS_LAUNCHER: Used to launch and terminate browser processes. +* cef.TID_CACHE: Used to handle slow HTTP cache operations. +* cef.TID_IO: Used to process IPC and network messages. + +List of threads in the Renderer process: +* cef.TID_RENDERER: The main thread in the renderer. Used for all webkit and V8 interaction. + + ### QuitMessageLoop diff --git a/docs/Tutorial.md b/docs/Tutorial.md index e659b2632..adc50a1a8 100644 --- a/docs/Tutorial.md +++ b/docs/Tutorial.md @@ -1,189 +1,472 @@ -# Tutorial (STILL A WORK IN PROGRESS.. #256) +# Tutorial -This tutorial is for v50+ versions of CEF Python, which are currently -available only for Linux. +With CEF Python you can embed a web browser control based +on Chromium in a Python application. You can also use it to +create a HTML 5 based GUI in an application that can act as +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) +file, but these examples are out of scope for this tutorial. Table of contents: -* [Install and download examples](#install-and-download-examples) +* [Install and run example](#install-and-run-example) * [Hello world](#hello-world) -* [CEF's multiprocess architecture](#cefs-multiprocess-architecture) +* [Architecture](#architecture) * [Handling Python exceptions](#handling-python-exceptions) * [Message loop](#message-loop) * [Settings](#settings) -* [Handlers](#handlers) +* [Client handlers](#client-handlers) * [Javascript integration](#javascript-integration) -* [Plugins](#plugins) -* [Helper functions](#helper-functions) +* [Javascript exceptions and Python exceptions](#javascript-exceptions-and-python-exceptions) +* [Plugins and Flash support](#plugins-and-flash-support) * [Build executable](#build-executable) -* [What's next?](#whats-next) +* [Support and documentation](#support-and-documentation) -## Install and download examples +## Install and run example -The easy way to install CEF Python is through PyPI, using the pip tool, -which is bundled with all recent versions of Python. On Linux pip 8.1+ -is required. To check version and install CEF Python type: +You can install with pip. On Linux pip 8.1+ is required. Alternatively +you can download packages for offline installation from [GitHub Releases](../../../releases). -``` -pip --version -pip install cefpython3 -``` - -Alternatively you can download the setup package from -[GitHub Releases](../../../releases) and install it by following -the instructions in README.txt. - -Now let's download examples by cloning the GitHub repository. After -that, enter the "cefpython/examples/" directory. In that directory -you will find all the examples from this Tutorial, their names -start with a "tutorial_" prefix, except for the hello world example -which is just named "hello_world.py". +Run the commands below to install the cefpython3 package, clone +the github repository, enter the examples/ directory and run the +Hello World example: ``` +pip install cefpython3==56.1 git clone https://github.com/cztomczak/cefpython.git cd cefpython/examples/ +python hello_world.py ``` +The hello_world.py example's source code will be analyzed line +by line in the next section of this Tutorial. + +This tutorial in its further sections will also reference the +tutorial.py example which will show how to use more advanced +CEF Python features. The tutorial.py example is also available +in the examples/ directory. + ## Hello world The [hello_world.py](../examples/hello_world.py) example is the -most basic example. It doesn't depend on any third party GUI frameworks. +most basic example. It doesn't depend on any third party GUI framework. It creates a browser widget without providing any window information -(parent window not specified), thus CEF automatically takes care of creating -a top-level window for us, and in that window a Chromium widget is embedded. -When creating the browser, an "url" parameter is specified, which causes the -browser to initially navigate to the Google website. Let's explain the code -from this example: +(parent window is not specified), thus CEF automatically takes care of +creating a top-level window, and in that window a Chromium widget +is being embedded. When creating the browser, the "url" parameter is +specified, which causes the browser to initially navigate to +Google website. Let's analyze the code from that example: 1. `from cefpython3 import cefpython as cef` - Import the cefpython - module and bind it to a shorter name "cef". + module and make a short "cef" alias 2. `sys.excepthook = cef.ExceptHook` - Overwrite Python's default - exception handler so that all CEF processes are terminated when - Python exception occurs. To understand this better read the - "CEF's multiprocess architecture" and "Handling Python exceptions" - sections further down in this Tutorial. + exception handler so that all CEF sub-processes are terminated + when Python exception occurs. To understand this better read the + "Architecture" and "Handling Python exceptions" sections + further down in this Tutorial. 3. `cef.Initialize()` - Initialize CEF. This function must be called somewhere in the beginning of your code. It must be called before - any app window is created. It must be called only once during app's - lifetime and must have a corresponding Shutdown() call. -4. `cef.CreateBrowserSync(url="https://www.google.com/")` - Create - a browser synchronously, this function returns the Browser object. + any application window is created. It must be called only once + during app's lifetime and must have a corresponding Shutdown() + call. +4. `cef.CreateBrowserSync(url="https://www.google.com/", ...)` - Create + a browser synchronously, this function returns a Browser object. 5. `cef.MessageLoop()` - Run CEF message loop. All desktop GUI programs run some message loop that waits and dispatches events or messages. + Read more on message loop in the "Message loop" section further + down in this tutorial. 6. `cef.Shutdown()` - Shut down CEF. This function must be called for - CEF to shut down cleanly. It will free CEF system resources, it - will terminate all subprocesses, and it will flush to disk any + CEF to shut down cleanly. It will free system resources acquired + by CEF and terminate all sub-processes, and it will flush to disk any yet unsaved data like for example cookies and/or local storage. Call this function at the very end of your program execution. When using third party GUI frameworks such as Qt/wxWidgets, CEF should be shut down after these frameworks' shutdown procedures were called. For example in Qt, shut down CEF only after QApplication object was destroyed. -Documentation for the functions from this example can be found in -API docs (the api/ directory in GitHub's repository): +Documentation for the functions referenced in this example can +be found in API reference - the [api/](../api) root directory in GitHub's +repository: * [ExceptHook](../api/cefpython.md#excepthook) -* [Initialize()](../api/cefpython.md#initialize) -* [CreateBrowserSync()](../api/cefpython.md#createbrowsersync) +* [Initialize](../api/cefpython.md#initialize) +* [CreateBrowserSync](../api/cefpython.md#createbrowsersync) * [Browser](../api/Browser.md) object -* [MessageLoop()](../api/cefpython.md#messageloop) -* [Shutdown()](../api/cefpython.md#shutdown) +* [MessageLoop](../api/cefpython.md#messageloop) +* [Shutdown](../api/cefpython.md#shutdown) + + +## Architecture + +- CEF uses multi-process architecture + - The main application process is called the “Browser” + process. In CEF Python this is the same process in + which Python is running. + - CEF Python uses a separate executable called "subprocess" + for running sub-processes. Sub-processes will be created + for renderers, plugins, GPU, etc. + - In future CEF Python might allow to run Python also in + sub-processes, for example in the Renderer process which + would allow to access more CEF API ([Issue #320](../../../issues/320)) +- Most processes in CEF have multiple threads + - Handlers' callbacks and other interfaces callbacks may + be called on various threads, this is stated in API reference + - Some functions may only be used on particular threads, + this is stated in API reference + - CEF Python provides cef.[PostTask](../api/cefpython.md#posttask) + function for posting tasks between these various threads + - The "UI" thread is application main thread unless you + use ApplicationSettings.[multi_threaded_message_loop](../api/ApplicationSettings.md#multi_threaded_messge_loop) + option on Windows in which case the UI thread will no more + be application main thread + - Do not perform blocking operations on any CEF thread other + than the Browser process FILE thread. Otherwise this can + lead to serious performance issues. -## CEF's multiprocess architecture +## Handling Python exceptions -... +Due to CEF multi-process architecture Python exceptions need +special handling. When Python exception occurs then main process +is terminated. For CEF this means that the Browser process is +terminated, however there may still be running CEF sub-processes +like Renderer process, GPU process, etc. To terminate these +sub-processes cef.[Shutdown](../api/cefpython.md#shutdown) +must be called and if running CEF message loop then it must be +stopped first. In all CEF Python examples you can find such +a line that overwrites the default exception handler in Python: +``` +sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error +``` -## Handling Python exceptions -... +See Python docs for [sys.excepthook](https://docs.python.org/2/library/sys.html#sys.excepthook). + +The cef.ExceptHook helper function does the following: +1. Calls cef.[QuitMessageLoop](../api/cefpython.md#quitmessageloop) +2. Calls cef.[Shutdown](../api/cefpython.md#shutdown) +3. Writes exception to "error.log" file +4. Prints exception +5. Calls [os._exit(1)](https://docs.python.org/2/library/os.html#os._exit) - + which exits the process with status 1, without calling + cleanup handlers, flushing stdio buffers, etc. + +See CEF Python's ExceptHook source code [here](../../../search?utf8=%E2%9C%93&q=%22def+excepthook%28exc_type%22&type=). ## Message loop Message loop is a programming construct that waits for and dispatches events or messages in a program. All desktop GUI -programs must run some kind of message loop. -The hello_world.py example doesn't depend on any third party GUI -framework and thus can run CEF message loop directly by calling call -cef.MessageLoop(). However in most of other examples that show how -to embed CEF Python browser inside GUI frameworks such as -Qt/wxPython/Tkinter, you can't call cef.MessageLoop(), because these -frameworks run a message loop of its own. For such cases CEF provides -cef.MessageLoopWork() which is for integrating CEF message loop into -existing application message loop. Usually cef.MessageLoopWork() is -called in a 10ms timer. +programs must run some kind of message loop. The hello_world.py +example doesn't depend on any third party GUI framework and thus +can run CEF message loop directly by calling cef.MessageLoop(). +However in other examples that embed CEF browser with GUI frameworks +such as Qt/wxPython/Tkinter you can't call cef.MessageLoop(), because +these frameworks run a message loop of its own. For such cases CEF +provides cef.MessageLoopWork() which is for integrating CEF message +loop into existing application message loop. Usually +cef.MessageLoopWork() is called in a 10ms timer. + +**Performance** Calling cef.MessageLoopWork() in a timer is not the best performant way to run CEF message loop, also there are known bugs on some -platforms when calling message loop work in a timer. CEF provides -ApplicationSettings.[external_message_pump](../api/ApplicationSettings.md#external_message_pump) -option for running an external message pump that you should use for -best performance and to get rid of some bugs. However this option is -still experimental, as during testing on Linux it actually made app -x2 slower - it's a bug in upstream CEF that was reported. See -[Issue #246](../../../issues/246) for more details. On Windows/Mac -external message pump should work good, but it wasn't yet tested -with CEF Python. +platforms when calling message loop work in a timer. There are two +options to increase performance depending on platform. On Windows +use a multi-threaded message loop for best performance. On Mac use +an external message pump for best performance. + +**Windows: multi-threaded message loop** On Windows for best performance a multi-threaded message loop should -be used, instead of cef.MessageLoopWork / external message pump. To do -so, set -ApplicationSettings.[multi_threaded_message_loop](../ApplicationSettings.md#multi_threaded_message_loop) +be used instead of cef.MessageLoopWork() or external message pump. To do +so, set ApplicationSettings.[multi_threaded_message_loop](../ApplicationSettings.md#multi_threaded_message_loop) to True and run a native message loop in your app. Don't call CEF's -message loop. Create browser using -cef.PostTask(cef.TID_UI, cef.CreateBrowserSync, ...). +message loop. Create browser using `cef.PostTask(cef.TID_UI, cef.CreateBrowserSync, ...)`. Note that when using multi-threaded message loop, CEF's UI thread is no more application's main thread, and that makes it a bit harder to correctly use CEF API. API docs explain on which threads a function may be called and in case of handlers' callbacks (and other interfaces) -it is stated on which thread a callback will be called. -See also [Issue #133](../../../issues/133). +it is stated on which thread a callback will be called. See also +[Issue #133](../../../issues/133). + +**Mac: external message pump** + +CEF provides ApplicationSettings.[external_message_pump](../api/ApplicationSettings.md#external_message_pump) +option for running an external message pump that you should use for +best performance and to get rid of some bugs that appear when using +cef.MessageLoopWork() in a timer. + +This option is currently marked experimental as it wasn't yet fully +tested. This option should work good on Mac - in upstream CEF it was +tested mainly on Mac. If you've successfully used this option on Mac +please let us know on the Forum. + +**Linux** + +External message pump option is not recommended to use on Linux, +as during testing it actually made app x2 slower - it's a bug in +upstream CEF. See [Issue #246](../../../issues/246) for more details. ## Settings -ApplicationSettings, BrowserSettings, CommandLineSwitches, Chromium -Preferences (not implemented yet) ... +CEF settings are provided in multiple ways. There are global +[application settings](../api/ApplicationSettings.md#application-settings) +and [command line switches](../api/CommandLineSwitches.md#command-line-switches) +that can be passed to cef.[Initialize](../api/cefpython.md#initialize). +There are also [browser settings](../api/BrowserSettings.md#browser-settings) +that can be passed to cef.[CreateBrowserSync](../api/cefpython.md#createbrowsersync). +Finally there are Chromium preferences, but these are not yet +implemented. See below for details on each of these settings. + +**Application settings** + +A dict of [application settings](../api/ApplicationSettings.md#application-settings) +can be passed to cef.[Initialize](../api/cefpython.md#initialize). +Here are some settings worth noting: +- [cache_path](../api/ApplicationSettings.md#cache_path) - set + a directory path so that web cache data is persisted, otherwise + an in-memory cache is used. Cookies and HTML 5 databases such + as local storage will only persist if this option is set. +- [context_menu](../api/ApplicationSettings.md#context_menu) - + customize context menu +- [locale](../api/ApplicationSettings.md#locale) - set language + for localized resources + +To enable debugging set these settings: +``` +settings = { + "debug": True, + "log_severity": cef.LOGSEVERITY_WARNING, + "log_file": "debug.log", +} +cef.Initialize(settings=settings) +``` + +Alternatively you can pass `--debug` flag on the command line +and these settings will be set automatically. + +**Browser settings** + +A dict of [browser settings](../api/BrowserSettings.md#browser-settings) +can be passed to cef.[CreateBrowserSync](../api/cefpython.md#createbrowsersync). + +**Command line switches** +A dict of [command line switches](../api/CommandLineSwitches.md) +can be passed to cef.[Initialize](../api/cefpython.md#initialize). +Examples switches: +- "enable-media-stream" - to enable media (WebRTC audio/video) streaming +- "proxy-server" - to set proxy server +- "disable-gpu" - use only CPU software rendering + +Example code: + +``` +switches = { + "enable-media-stream": "", + "proxy-server": "socks5://127.0.0.1:8888", + "disable-gpu": "", +} +cef.Initialize(switches=switches) +``` -## Handlers +Note that when setting switch that doesn't accept value then +must pass an empty string as value. + +**Chromium preferences** + +There are lots of more settings that can be set using Chromium +preferences (and even changed during runtime), however this API +wasn't yet exposed to CEF Python, see [Issue #244](../../../issues/244) +for details. + + +## Client handlers + +In CEF [client handlers](../api/API-categories.md#client-handlers-interfaces) +provide a way to be notified of Chromium events. There are client +handlers like DisplayHandler, LoadHandler, RequestHandler, etc. +These handlers are class interfaces for which you provide +implementation. We will refer to the methods of these objects +as "callbacks". You can set a client handler by calling +Browser.[SetClientHandler](../api/Browser.md#setclienthandler). +You are not required to implement whole interface, you can implement +only some callbacks. Some handlers due to cefpython limitations +have callbacks that can only be set globally by calling +cef.[SetGlobalClientCallback](../api/cefpython.md#setglobalclientcallback). +In API reference such global client callbacks are marked with an +underscore in its name. + +The [tutorial.py](../examples/tutorial.py) example shows how to +implement client handlers like [DisplayHandler](../api/DisplayHandler.md) +and [LoadHandler](../api/LoadHandler.md). It also shows how to +implement a global client callback LifespanHandler.[_OnAfterCreated](../api/LifespanHandler.md#_onaftercreated). Here is some source code: + +``` +set_client_handlers(browser) ... +def set_client_handlers(browser): + client_handlers = [LoadHandler(), DisplayHandler()] + for handler in client_handlers: + browser.SetClientHandler(handler) +... +class LoadHandler(object): + def OnLoadingStateChange(self, browser, is_loading, **_): + if not is_loading: + # Loading is complete + js_print(browser, "Python: LoadHandler.OnLoadingStateChange:" + "loading is complete") +``` ## Javascript integration +Python code is running in the main process (the Browser process), +while Javascript is running in the Renderer sub-process. Communication +between Python and Javascript is possible either using inter-process +asynchronous messaging or through http requests (both sync and +async possible). + +**Asynchronous inter-process messaging** + +Python and Javascript can communicate using inter-process +messaging: + - Use the [JavascriptBindings](../api/JavascriptBindings.md) + class methods to to expose Python functions, objects and properties + to Javascript: [SetFunction](../api/JavascriptBindings.md#setfunctions), + [SetObject](../api/JavascriptBindings.md#setobject) + and [SetProperty](../api/JavascriptBindings.md#setproperty) + - To initiate communication from the Python side call + Browser object methods: [ExecuteJavascript](../api/Browser.md#executejavascript) + or [ExecuteFunction](../api/Browser.md#executefunction). + Frame object also has the same methods. + - To initiate communication from the Javascript side first + you have to bind Python functions/objects using the + JavascriptBindings class mentioned earlier. Then you call + these functions/objects. + - You can pass Javascript callbacks to Python. Just pass a + javascript function as an argument when calling Python + function/object. On the Python side that javascript function + will be converted to [JavascriptCallback](../api/JavascriptCallback.md) + object. Execute the [Call](../api/JavascriptCallback.md#call) + method on it to call the javascript function asynchronously. + - You can pass Python callbacks to Javascript, however you + can do so only after the communication was initiated from + the Javascript side and a javascript callback was passed. + When executing JavascriptCallback.[Call](../api/JavascriptCallback.md#call) + method you can pass Python callbacks to Javascript. In + javascript these Python callbacks will act as native + javascript functions, so call them as usual. + - Note that when executing Browser.[ExecuteFunction](../api/Browser.md#executefunction) method you cannot pass Python functions + nor objects here. Such feature is not yet supported. You can + however pass Python functions when executing javascript + callbacks mentioned earlier. + +In tutorial.py example you will find example code that uses +javascript bindings and other APIs mentioned above. + +... ... -## Plugins +**Communication using http requests** -... +Python and Javascript can also communicate using http requests +by running an internal web-server. See for example [SimpleHTTPServer](https://docs.python.org/2/library/simplehttpserver.html) +in Python docs. + +With http requests it is possible for synchronous +communication from Javascript to Python by performing +synchronous AJAX requests. + +To initiate communication from the Python side call +Browser object methods: [ExecuteJavascript](../api/Browser.md#executejavascript) +or [ExecuteFunction](../api/Browser.md#executefunction). +Frame object also has the same methods. + +You can also serve requests directly in CEF using for example +[ResourceHandler](../api/ResourceHandler.md) object. You can find +an example usage of this object in one of examples listed in +the [Examples-README.md](../examples/Examples-README.md) file. +On a side note, upstream CEF also supports custom scheme handlers, +however these APIs were not yet exposed to CEF Python. -## Helper functions -GetApplicationPath... -GetModulePath... -others... +## Javascript exceptions and Python exceptions + +There are cases when executing Javascript code may end up with +Python exception being thrown: + +1. When a Python function is invoked from Javascript and it fails, + a Python exception will be thrown +2. When Python executes a Javascript callback and it fails, + a Python exception will be thrown + +In other cases to see Javascript exceptions open Developer Tools +window using mouse context menu and switch to Console tab. + +There are multiple ways to catch/intercept javascript exceptions: + +1. In Javascript you can register "window.onerror" event to + catch all Javascript exceptions +2. In Python you can intercept Javascript exceptions using + DisplayHandler.[OnConsoleMessage](../api/DisplayHandler.md#onconsolemessage) +3. In upstream CEF there is also CefRenderProcessHandler::OnUncaughtException + callback for catching Javascript exceptions, however this + wasn't yet exposed to CEF Python + + +## Plugins and Flash support + +Latest CEF supports only [PPAPI plugins](https://www.chromium.org/developers/design-documents/pepper-plugin-implementation). +NPAPI plugins are no more supported. + +Instructions for enabling Flash support are available in [Issue #235](../../../issues/235) ("Flash support in CEF 51+"). + +For the old CEF Python v31 release instructions for enabling Flash +support are available on Wiki pages. + ## Build executable -Examples for building an executable are yet to be created: +There are no official examples for building executable using +python packaging tools, however some resources and tips are +available, see these issues in the tracker: + +* Pyinstaller - see [Issue #135](../../../issues/135) +* py2exe - see [Issue #35](../../../issues/35) +* py2app - see [Issue #337](../../../issues/337) +* cx_Freeze - see [Issue #338](../../../issues/338) + +If you have any problems building executable ask on the [Forum](https://groups.google.com/group/cefpython). + +**Files in the cefpython3 package** + +The cefpython3 package has the following components: +1. The CEF Python modules (cefpython_pyxx.pyd on Windows, + cefpython_pyxx.so on Linux/Mac) +2. The CEF dynamic library (libcef.dll on Windows, libcef.so on Linux, + “Chromium Embedded Framework.framework” on OS X). +3. Other dynamic libraries CEF depends on (libEGL, libGLES, + d3dcompiler, etc.) and some optional (widevinecdmadapter, etc.) +4. Support files (*.pak, *.dat, *.bin, etc). -* On Windows use py2exe ([#35](../../../issues/35)) - or pyinstaller ([#135](../../../issues/135)) -* On Mac use py2app or pyinstaller -* On Linux use pyinstaller or cx_freeze +See README.txt in the cefpython3 package which provides +extended details about all CEF binary files. -## What's next? +## Support and documentation -See more examples in the examples/ directory -See API docs in the api/ directory -Example usage of most of API is available in the unittests/ directory -See the Knowledge base document -Ask questions and report problems on the Forum +For support and documentation see the [Support](../README.md#support) +section in README. diff --git a/examples/Examples-README.md b/examples/Examples-README.md index 6e76fb4d7..3b93066cb 100644 --- a/examples/Examples-README.md +++ b/examples/Examples-README.md @@ -39,6 +39,11 @@ maintained: If there are any issues in examples read top comments in sources to see whether this is a known issue with available workarounds. +**Unit tests** + +There are also available unit tests and its usage of the API can +be of some use. See [main_test.py](../unittests/main_test.py). + ## More examples diff --git a/examples/hello_world.py b/examples/hello_world.py index bcacf379f..0157267f5 100644 --- a/examples/hello_world.py +++ b/examples/hello_world.py @@ -10,8 +10,8 @@ def main(): check_versions() sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error cef.Initialize() - cef.CreateBrowserSync(window_title="Hello World!", - url="https://www.google.com/") + cef.CreateBrowserSync(url="https://www.google.com/", + window_title="Hello World!") cef.MessageLoop() cef.Shutdown() diff --git a/examples/tutorial.py b/examples/tutorial.py new file mode 100644 index 000000000..be85b3d4d --- /dev/null +++ b/examples/tutorial.py @@ -0,0 +1,104 @@ +# Tutorial example. +# Tested with CEF Python v56.1+ + +from cefpython3 import cefpython as cef +import base64 +import platform +import sys + +# HTML code. Browser will navigate to a Data uri created +# from this html code. +HTML_code = """ +test +""" + + +def main(): + check_versions() + sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error + settings = {"cache_path": "webcache"} + cef.Initialize(settings=settings) + set_global_handler() + browser = cef.CreateBrowserSync(url=html_to_data_uri(HTML_code), + window_title="Hello World!") + set_client_handlers(browser) + set_javascript_bindings(browser) + cef.MessageLoop() + cef.Shutdown() + + +def check_versions(): + print("[tutorial.py] CEF Python {ver}".format(ver=cef.__version__)) + print("[tutorial.py] Python {ver} {arch}".format( + ver=platform.python_version(), arch=platform.architecture()[0])) + assert cef.__version__ >= "56.1", "CEF Python v56.1+ required to run this" + + +def html_to_data_uri(html): + html = html.encode("utf-8", "replace") + b64 = base64.b64encode(html).decode("utf-8", "replace") + return "data:text/html;base64,{data}".format(data=b64) + + +def set_global_handler(): + # A global handler is a special handler for callbacks that + # must be set before Browser is created using + # SetGlobalClientCallback() method. + global_handler = GlobalHandler() + cef.SetGlobalClientCallback("OnAfterCreated", + global_handler.OnAfterCreated) + + +def set_client_handlers(browser): + client_handlers = [LoadHandler(), DisplayHandler()] + for handler in client_handlers: + browser.SetClientHandler(handler) + + +def set_javascript_bindings(browser): + external = External(browser) + bindings = cef.JavascriptBindings( + bindToFrames=False, bindToPopups=False) + bindings.SetFunction("html_to_data_uri", html_to_data_uri) + bindings.SetProperty("test_property", "This property was set in Python") + bindings.SetObject("external", external) + browser.SetJavascriptBindings(bindings) + + +def js_print(browser, msg): + browser.ExecuteFunction("js_print", msg) + + +class GlobalHandler(object): + def OnAfterCreated(self, browser, **_): + js_print(browser, + "Python: GlobalHandler._OnAfterCreated: browser id={id}" + .format(id=browser.GetIdentifier())) + + +class LoadHandler(object): + def OnLoadingStateChange(self, browser, is_loading, **_): + if not is_loading: + # Loading is complete + js_print(browser, "Python: LoadHandler.OnLoadingStateChange:" + "loading is complete") + + +class DisplayHandler(object): + def OnConsoleMessage(self, browser, message, **_): + if "error" in message.lower() or "uncaught" in message.lower(): + js_print(browser, "Python: LoadHandler.OnConsoleMessage: " + "intercepted Javascript error: {error}" + .format(error=message)) + + +class External(object): + def __init__(self, browser): + self.browser = browser + + def test_function(self): + pass + + +if __name__ == '__main__': + main() diff --git a/src/cefpython.pyx b/src/cefpython.pyx index f50919a8b..dc7a672e1 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -593,9 +593,13 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): if "settings" in kwargs: assert not applicationSettings, "Bad arguments" application_settings = kwargs["settings"] + del kwargs["settings"] if "switches" in kwargs: assert not command_line_switches, "Bad arguments" command_line_switches = kwargs["switches"] + del kwargs["switches"] + for kwarg in kwargs: + raise Exception("Invalid argument: "+kwarg) IF UNAME_SYSNAME == "Linux": # Fix Issue #231 - Discovery of the "icudtl.dat" file fails on Linux. @@ -772,10 +776,15 @@ def CreateBrowserSync(windowInfo=None, # Alternative names for existing parameters if "window_info" in kwargs: windowInfo = kwargs["window_info"] + del kwargs["window_info"] if "settings" in kwargs: browserSettings = kwargs["settings"] + del kwargs["settings"] if "url" in kwargs: navigateUrl = kwargs["url"] + del kwargs["url"] + for kwarg in kwargs: + raise Exception("Invalid argument: "+kwarg) Debug("CreateBrowserSync() called") assert IsThread(TID_UI), ( diff --git a/src/helpers.pyx b/src/helpers.pyx index 595d2cd09..dbfb22e8b 100644 --- a/src/helpers.pyx +++ b/src/helpers.pyx @@ -32,7 +32,7 @@ cpdef str GetModuleDirectory(): g_GetAppPath_dir = None -cpdef str GetAppPath(file=None): +cpdef str GetAppPath(file_=None): """Get application path.""" # On Windows after downloading file and calling Browser.GoForward(), # current working directory is set to %UserProfile%. @@ -47,49 +47,46 @@ cpdef str GetAppPath(file=None): global g_GetAppPath_dir g_GetAppPath_dir = adir # If file is None return current directory without trailing slash. - if file is None: - file = "" + if file_ is None: + file_ = "" # Only when relative path. - if not file.startswith("/") and not file.startswith("\\") and ( - not re.search(r"^[\w-]+:", file)): - path = g_GetAppPath_dir + os.sep + file + if not file_.startswith("/") and not file_.startswith("\\") and ( + not re.search(r"^[\w-]+:", file_)): + path = g_GetAppPath_dir + os.sep + file_ if platform.system() == "Windows": path = re.sub(r"[/\\]+", re.escape(os.sep), path) path = re.sub(r"[/\\]+$", "", path) return path - return str(file) + return str(file_) -cpdef py_void ExceptHook(excType, excValue, traceObject): - """Global except hook to exit app cleanly on error.""" - # 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()). - print("[CEF Python] ExceptHook: catched exception, will shutdown CEF now") +def ExceptHook(exc_type, exc_value, exc_trace): + """Global except hook to exit app cleanly on error. + 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()). + """ + print("[CEF Python] ExceptHook: catched exception, will shutdown CEF") QuitMessageLoop() Shutdown() - print("[CEF Python] ExceptHook: see the catched exception below:") - errorMsg = "".join(traceback.format_exception(excType, excValue, - traceObject)) - errorFile = GetAppPath("error.log") + msg = "".join(traceback.format_exception(exc_type, exc_value, + exc_trace)) + error_file = GetAppPath("error.log") + encoding = GetAppSetting("string_encoding") or "utf-8" + if type(msg) == bytes: + msg = msg.decode(encoding=encoding, errors="replace") try: - appEncoding = g_applicationSettings["string_encoding"] - except: - appEncoding = "utf-8" - if type(errorMsg) == bytes: - errorMsg = errorMsg.decode(encoding=appEncoding, errors="replace") - try: - with codecs.open(errorFile, mode="a", encoding=appEncoding) as fp: + with codecs.open(error_file, mode="a", encoding=encoding) as fp: fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), errorMsg)) + time.strftime("%Y-%m-%d %H:%M:%S"), msg)) except: print("[CEF Python] WARNING: failed writing to error file: %s" % ( - errorFile)) + error_file)) # Convert error message to ascii before printing, otherwise # you may get error like this: # | UnicodeEncodeError: 'charmap' codec can't encode characters - errorMsg = errorMsg.encode("ascii", errors="replace") - errorMsg = errorMsg.decode("ascii", errors="replace") - print("\n"+errorMsg) + msg = msg.encode("ascii", errors="replace") + msg = msg.decode("ascii", errors="replace") + print("\n"+msg) # noinspection PyProtectedMember os._exit(1) From bc4e03893c00efab22e46f993ec681154e092f39 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Fri, 7 Apr 2017 10:56:55 +0200 Subject: [PATCH 200/557] Complete Tutorial (#256) and fix #344. Do not inherit client handlers nor javascript bindings in DevTools windows (#344). --- README.md | 1 + api/JavascriptBindings.md | 1 - docs/Tutorial.md | 52 +++++++++++++-- examples/tutorial.py | 132 ++++++++++++++++++++++++++++++++------ src/browser.pyx | 8 +-- src/helpers.pyx | 64 +++++++++--------- 6 files changed, 194 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 29ab84797..bcf0ec45d 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ Table of contents: * [Introduction](#introduction) * [Install](#install) +* [Tutorial](#tutorial) * [Examples](#examples) * [Support](#support) * [Releases](#releases) diff --git a/api/JavascriptBindings.md b/api/JavascriptBindings.md index 7083cd880..ccfc51e2f 100644 --- a/api/JavascriptBindings.md +++ b/api/JavascriptBindings.md @@ -6,7 +6,6 @@ Table of contents: * [Introduction](#introduction) -* [Example usage](#example-usage) * [Methods](#methods) * [\_\_init\_\_()](#__init__) * [IsValueAllowed](#isvalueallowed) diff --git a/docs/Tutorial.md b/docs/Tutorial.md index adc50a1a8..21869177b 100644 --- a/docs/Tutorial.md +++ b/docs/Tutorial.md @@ -157,7 +157,7 @@ The cef.ExceptHook helper function does the following: which exits the process with status 1, without calling cleanup handlers, flushing stdio buffers, etc. -See CEF Python's ExceptHook source code [here](../../../search?utf8=%E2%9C%93&q=%22def+excepthook%28exc_type%22&type=). +See CEF Python's ExceptHook source code in src/[helpers.pyx](../src/helpers.pyx). ## Message loop @@ -322,10 +322,17 @@ def set_client_handlers(browser): ... class LoadHandler(object): def OnLoadingStateChange(self, browser, is_loading, **_): + # Issue #344 will fix this in next release, so that client + # handlers are not called for Developer Tools windows. + if browser.GetUrl().startswith("chrome-devtools://"): + return + # This callback is called twice, once when loading starts + # (is_loading=True) and second time when loading ends + # (is_loading=False). if not is_loading: - # Loading is complete - js_print(browser, "Python: LoadHandler.OnLoadingStateChange:" - "loading is complete") + # Loading is complete. DOM is ready. + js_print(browser, "Python", "OnLoadingStateChange", + "Loading is complete") ``` @@ -372,12 +379,43 @@ messaging: however pass Python functions when executing javascript callbacks mentioned earlier. -In tutorial.py example you will find example code that uses -javascript bindings and other APIs mentioned above. +In [tutorial.py](../examples/tutorial.py) example you will find +example usage of javascript bindings, javascript callbacks +and python callbacks. Here is some source code: +``` +set_javascript_bindings(browser) ... +def set_javascript_bindings(browser): + bindings = cef.JavascriptBindings( + bindToFrames=False, bindToPopups=False) + bindings.SetFunction("html_to_data_uri", html_to_data_uri) + browser.SetJavascriptBindings(bindings) ... - +def html_to_data_uri(html, js_callback=None): + # This function is called in two ways: + # 1. From Python: in this case value is returned + # 2. From Javascript: in this case value cannot be returned because + # inter-process messaging is asynchronous, so must return value + # by calling js_callback. + html = html.encode("utf-8", "replace") + b64 = base64.b64encode(html).decode("utf-8", "replace") + ret = "data:text/html;base64,{data}".format(data=b64) + if js_callback: + js_print(js_callback.GetFrame().GetBrowser(), + "Python", "html_to_data_uri", + "Called from Javascript. Will call Javascript callback now.") + js_callback.Call(ret) + else: + return ret +... + +``` **Communication using http requests** diff --git a/examples/tutorial.py b/examples/tutorial.py index be85b3d4d..88304abf3 100644 --- a/examples/tutorial.py +++ b/examples/tutorial.py @@ -5,19 +5,60 @@ import base64 import platform import sys +import threading # HTML code. Browser will navigate to a Data uri created # from this html code. HTML_code = """ -test + + + + + + + + +

      Tutorial example

      +
      + + """ def main(): check_versions() sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error - settings = {"cache_path": "webcache"} - cef.Initialize(settings=settings) + cef.Initialize() set_global_handler() browser = cef.CreateBrowserSync(url=html_to_data_uri(HTML_code), window_title="Hello World!") @@ -34,10 +75,22 @@ def check_versions(): assert cef.__version__ >= "56.1", "CEF Python v56.1+ required to run this" -def html_to_data_uri(html): +def html_to_data_uri(html, js_callback=None): + # This function is called in two ways: + # 1. From Python: in this case value is returned + # 2. From Javascript: in this case value cannot be returned because + # inter-process messaging is asynchronous, so must return value + # by calling js_callback. html = html.encode("utf-8", "replace") b64 = base64.b64encode(html).decode("utf-8", "replace") - return "data:text/html;base64,{data}".format(data=b64) + ret = "data:text/html;base64,{data}".format(data=b64) + if js_callback: + js_print(js_callback.GetFrame().GetBrowser(), + "Python", "html_to_data_uri", + "Called from Javascript. Will call Javascript callback now.") + js_callback.Call(ret) + else: + return ret def set_global_handler(): @@ -59,45 +112,86 @@ def set_javascript_bindings(browser): external = External(browser) bindings = cef.JavascriptBindings( bindToFrames=False, bindToPopups=False) + bindings.SetProperty("python_property", "This property was set in Python") bindings.SetFunction("html_to_data_uri", html_to_data_uri) - bindings.SetProperty("test_property", "This property was set in Python") bindings.SetObject("external", external) browser.SetJavascriptBindings(bindings) -def js_print(browser, msg): - browser.ExecuteFunction("js_print", msg) +def js_print(browser, lang, event, msg): + # Execute Javascript function "js_print" + browser.ExecuteFunction("js_print", lang, event, msg) class GlobalHandler(object): def OnAfterCreated(self, browser, **_): - js_print(browser, - "Python: GlobalHandler._OnAfterCreated: browser id={id}" - .format(id=browser.GetIdentifier())) + # Issue #344 will fix this in next release, so that client + # handlers are not called for Developer Tools windows. + if browser.GetUrl().startswith("chrome-devtools://"): + return + # DOM is not yet loaded. Using js_print at this moment will + # throw an error: "Uncaught ReferenceError: js_print is not defined". + # We make this error on purpose. This error will be intercepted + # in DisplayHandler.OnConsoleMessage. + js_print(browser, "Python", "OnAfterCreated", + "This will probably never display as DOM is not yet loaded") + # Delay print by 0.5 sec, because js_print is not available yet + args = [browser, "Python", "OnAfterCreated", + "(Delayed) Browser id="+str(browser.GetIdentifier())] + threading.Timer(0.5, js_print, args).start() class LoadHandler(object): def OnLoadingStateChange(self, browser, is_loading, **_): + # Issue #344 will fix this in next release, so that client + # handlers are not called for Developer Tools windows. + if browser.GetUrl().startswith("chrome-devtools://"): + return + # This callback is called twice, once when loading starts + # (is_loading=True) and second time when loading ends + # (is_loading=False). if not is_loading: - # Loading is complete - js_print(browser, "Python: LoadHandler.OnLoadingStateChange:" - "loading is complete") + # Loading is complete. DOM is ready. + js_print(browser, "Python", "OnLoadingStateChange", + "Loading is complete") class DisplayHandler(object): def OnConsoleMessage(self, browser, message, **_): + # Issue #344 will fix this in next release, so that client + # handlers are not called for Developer Tools windows. + if browser.GetUrl().startswith("chrome-devtools://"): + return + # This will intercept js errors, see comments in OnAfterCreated if "error" in message.lower() or "uncaught" in message.lower(): - js_print(browser, "Python: LoadHandler.OnConsoleMessage: " - "intercepted Javascript error: {error}" - .format(error=message)) + # Prevent infinite recurrence in case something went wrong + if "js_print is not defined" in message.lower(): + if hasattr(self, "js_print_is_not_defined"): + print("Python: OnConsoleMessage: " + "Intercepted Javascript error: "+message) + return + else: + self.js_print_is_not_defined = True + # Delay print by 0.5 sec, because js_print may not be + # available yet due to DOM not ready. + args = [browser, "Python", "OnConsoleMessage", + "(Delayed) Intercepted Javascript error: {error}" + .format(error=message)] + threading.Timer(0.5, js_print, args).start() class External(object): def __init__(self, browser): self.browser = browser - def test_function(self): - pass + def test_multiple_callbacks(self, js_callback): + """Test both javascript and python callbacks.""" + js_print(self.browser, "Python", "test_multiple_callbacks", + "Called from Javascript. Will call Javascript callback now.") + + def py_callback(msg_from_js): + js_print(self.browser, "Python", "py_callback", msg_from_js) + js_callback.Call("String sent from Python", py_callback) if __name__ == '__main__': diff --git a/src/browser.pyx b/src/browser.pyx index edb3071a9..406a01c90 100644 --- a/src/browser.pyx +++ b/src/browser.pyx @@ -101,8 +101,8 @@ cdef PyBrowser GetPyBrowser(CefRefPtr[CefBrowser] cefBrowser, # - Popups inherit javascript bindings only when "bindToPopups" # constructor param was set to True. - if pyBrowser.IsPopup() and \ - not pyBrowser.GetUserData("__outerWindowHandle"): + if pyBrowser.IsPopup()\ + and not pyBrowser.GetUserData("__outerWindowHandle"): openerHandle = pyBrowser.GetOpenerWindowHandle() for identifier, tempPyBrowser in g_pyBrowsers.items(): if tempPyBrowser.GetWindowHandle() == openerHandle: @@ -457,12 +457,10 @@ cdef class PyBrowser: window_info.SetAsPopup( self.GetOpenerWindowHandle(), PyToCefStringValue("DevTools")) - cdef CefRefPtr[ClientHandler] client_handler =\ - new ClientHandler() cdef CefBrowserSettings settings cdef CefPoint inspect_element_at self.GetCefBrowserHost().get().ShowDevTools( - window_info, client_handler, settings, + window_info, NULL, settings, inspect_element_at) cpdef py_void StopLoad(self): diff --git a/src/helpers.pyx b/src/helpers.pyx index dbfb22e8b..ea8d5e8b8 100644 --- a/src/helpers.pyx +++ b/src/helpers.pyx @@ -12,6 +12,38 @@ import time import codecs +def ExceptHook(exc_type, exc_value, exc_trace): + """Global except hook to exit app cleanly on error. + 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()). + """ + print("[CEF Python] ExceptHook: catched exception, will shutdown CEF") + QuitMessageLoop() + Shutdown() + msg = "".join(traceback.format_exception(exc_type, exc_value, + exc_trace)) + error_file = GetAppPath("error.log") + encoding = GetAppSetting("string_encoding") or "utf-8" + if type(msg) == bytes: + msg = msg.decode(encoding=encoding, errors="replace") + try: + with codecs.open(error_file, mode="a", encoding=encoding) as fp: + fp.write("\n[%s] %s\n" % ( + time.strftime("%Y-%m-%d %H:%M:%S"), msg)) + except: + print("[CEF Python] WARNING: failed writing to error file: %s" % ( + error_file)) + # Convert error message to ascii before printing, otherwise + # you may get error like this: + # | UnicodeEncodeError: 'charmap' codec can't encode characters + msg = msg.encode("ascii", errors="replace") + msg = msg.decode("ascii", errors="replace") + print("\n"+msg) + # noinspection PyProtectedMember + os._exit(1) + + cpdef str GetModuleDirectory(): """Get path to the cefpython module (so/pyd).""" if platform.system() == "Linux" and os.getenv("CEFPYTHON3_PATH"): @@ -58,35 +90,3 @@ cpdef str GetAppPath(file_=None): path = re.sub(r"[/\\]+$", "", path) return path return str(file_) - - -def ExceptHook(exc_type, exc_value, exc_trace): - """Global except hook to exit app cleanly on error. - 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()). - """ - print("[CEF Python] ExceptHook: catched exception, will shutdown CEF") - QuitMessageLoop() - Shutdown() - msg = "".join(traceback.format_exception(exc_type, exc_value, - exc_trace)) - error_file = GetAppPath("error.log") - encoding = GetAppSetting("string_encoding") or "utf-8" - if type(msg) == bytes: - msg = msg.decode(encoding=encoding, errors="replace") - try: - with codecs.open(error_file, mode="a", encoding=encoding) as fp: - fp.write("\n[%s] %s\n" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), msg)) - except: - print("[CEF Python] WARNING: failed writing to error file: %s" % ( - error_file)) - # Convert error message to ascii before printing, otherwise - # you may get error like this: - # | UnicodeEncodeError: 'charmap' codec can't encode characters - msg = msg.encode("ascii", errors="replace") - msg = msg.decode("ascii", errors="replace") - print("\n"+msg) - # noinspection PyProtectedMember - os._exit(1) From bacb63587edcaed65fc8a859692d618d8acd1600 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Fri, 7 Apr 2017 11:08:33 +0200 Subject: [PATCH 201/557] Fix links --- docs/Tutorial.md | 21 +++++++++++---------- examples/Examples-README.md | 1 + examples/tutorial.py | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/docs/Tutorial.md b/docs/Tutorial.md index 21869177b..9abd7c13a 100644 --- a/docs/Tutorial.md +++ b/docs/Tutorial.md @@ -36,7 +36,7 @@ Run the commands below to install the cefpython3 package, clone the github repository, enter the examples/ directory and run the Hello World example: -``` +```commandline pip install cefpython3==56.1 git clone https://github.com/cztomczak/cefpython.git cd cefpython/examples/ @@ -142,7 +142,7 @@ must be called and if running CEF message loop then it must be stopped first. In all CEF Python examples you can find such a line that overwrites the default exception handler in Python: -``` +```python sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error ``` @@ -187,7 +187,7 @@ an external message pump for best performance. On Windows for best performance a multi-threaded message loop should be used instead of cef.MessageLoopWork() or external message pump. To do -so, set ApplicationSettings.[multi_threaded_message_loop](../ApplicationSettings.md#multi_threaded_message_loop) +so, set ApplicationSettings.[multi_threaded_message_loop](../api/ApplicationSettings.md#multi_threaded_message_loop) to True and run a native message loop in your app. Don't call CEF's message loop. Create browser using `cef.PostTask(cef.TID_UI, cef.CreateBrowserSync, ...)`. Note that when using multi-threaded message loop, CEF's UI thread @@ -242,7 +242,7 @@ Here are some settings worth noting: for localized resources To enable debugging set these settings: -``` +```python settings = { "debug": True, "log_severity": cef.LOGSEVERITY_WARNING, @@ -270,7 +270,7 @@ Examples switches: Example code: -``` +```python switches = { "enable-media-stream": "", "proxy-server": "socks5://127.0.0.1:8888", @@ -310,9 +310,10 @@ underscore in its name. The [tutorial.py](../examples/tutorial.py) example shows how to implement client handlers like [DisplayHandler](../api/DisplayHandler.md) and [LoadHandler](../api/LoadHandler.md). It also shows how to -implement a global client callback LifespanHandler.[_OnAfterCreated](../api/LifespanHandler.md#_onaftercreated). Here is some source code: +implement a global client callback LifespanHandler.[_OnAfterCreated](../api/LifespanHandler.md#_onaftercreated). Here is part of its +source code: -``` +```python set_client_handlers(browser) ... def set_client_handlers(browser): @@ -350,7 +351,7 @@ Python and Javascript can communicate using inter-process messaging: - Use the [JavascriptBindings](../api/JavascriptBindings.md) class methods to to expose Python functions, objects and properties - to Javascript: [SetFunction](../api/JavascriptBindings.md#setfunctions), + to Javascript: [SetFunction](../api/JavascriptBindings.md#setfunction), [SetObject](../api/JavascriptBindings.md#setobject) and [SetProperty](../api/JavascriptBindings.md#setproperty) - To initiate communication from the Python side call @@ -381,9 +382,9 @@ messaging: In [tutorial.py](../examples/tutorial.py) example you will find example usage of javascript bindings, javascript callbacks -and python callbacks. Here is some source code: +and python callbacks. Here is part of its source code: -``` +```python set_javascript_bindings(browser) ... def set_javascript_bindings(browser): diff --git a/examples/Examples-README.md b/examples/Examples-README.md index 3b93066cb..2fae3e14a 100644 --- a/examples/Examples-README.md +++ b/examples/Examples-README.md @@ -25,6 +25,7 @@ maintained: - [hello_world.py](hello_world.py): basic example, doesn't require any third party GUI framework to run +- [tutorial.py](tutorial.py): example from [Tutorial](../docs/Tutorial.md) - [gtk2.py](gtk2.py): example for [PyGTK](http://www.pygtk.org/) library (GTK 2) - [gtk3.py](gtk3.py): example for [PyGObject/PyGI](https://wiki.gnome.org/Projects/PyGObject) diff --git a/examples/tutorial.py b/examples/tutorial.py index 88304abf3..28d69ddb7 100644 --- a/examples/tutorial.py +++ b/examples/tutorial.py @@ -1,4 +1,4 @@ -# Tutorial example. +# Tutorial example. Doesn't depend on any third party GUI framework. # Tested with CEF Python v56.1+ from cefpython3 import cefpython as cef From 73c84b20106699db2a15bcc2b46e4b7b51d9131c Mon Sep 17 00:00:00 2001 From: cztomczak Date: Tue, 11 Apr 2017 20:35:40 +0200 Subject: [PATCH 202/557] 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 bcf0ec45d..626e25b1b 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 58e566980..623e5c53b 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 97b3bc063..9f98f2726 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 c35ac91ab..1b1811f21 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 9abd7c13a..f78757826 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 203/557] 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 626e25b1b..be05b9e2f 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 df2dc4bd2..a1ab99c2c 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 623e5c53b..807b0cd1f 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 3409d8b48..d93a16e38 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 fb9ea8658..83d4b6798 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 204/557] 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 83d4b6798..93733cd3f 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 a9749d35a..e00754c1b 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 205/557] 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 93733cd3f..5361122dc 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 206/557] 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 cb97d8d2f..741242b8a 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 207/557] 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 2ac24df76..a2e0f251b 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 208/557] 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 be05b9e2f..114d2d358 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 35f850027..632aab59c 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 1d32dcf1d..3e4f0f8ba 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 7466caf89..f2635df2b 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 a4a1f0bbb..241a94173 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 209/557] 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 f78757826..bbd3054b3 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 bc5ccf495..4dc733b43 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 210/557] 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 99d7cc140..981c422ea 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 4dc733b43..069a312b1 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 211/557] 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 069a312b1..416805cea 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 212/557] 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 416805cea..2a5fbafe9 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 632aab59c..457e4a580 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 c6b886480..386979c98 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 213/557] 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 2a5fbafe9..01536a87d 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 214/557] 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 01536a87d..f03da5e09 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 215/557] 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 390b3905a..4dc0ff113 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 5361122dc..af38bd945 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 bbd3054b3..91cc029a1 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 416805cea..b3b5f0f69 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 dc7a672e1..7b5755eb1 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 13586c8ed..bdb2ee728 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 000000000..62ef9ba81 --- /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 000000000..094bc7194 --- /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 f14fbaf85..f55da8123 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 1304e8035..e6be3986b 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 76bf18513..3d53e78a6 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 fae9b3138..9e887e467 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 6c8a9213b..48e2a13f7 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 0cfd2d1b1..d54f5f0a5 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 ef7cc8b9b..bf816cf51 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 699043776..c06e098d3 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 0c37bff40..18f7ce030 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 4c5419a6b..000000000 --- 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 672ad25e1..000000000 --- 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 632aab59c..35f850027 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 000000000..04a32cfbd --- /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 5847d6700..09463b0ef 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 7d7ef4cc0..c980aa9f6 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 1f51ba270..950777027 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 e76b2691c..f9336ba3c 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 fd9f55e5d..9aeaf80ca 100644 --- a/src/subprocess/javascript_callback.cpp +++ b/src/subprocess/javascript_callback.cpp @@ -5,9 +5,9 @@ #include "javascript_callback.h" #include #include -#include "DebugLog.h" #include "v8utils.h" #include "cefpython_app.h" +#include "include/base/cef_logging.h" template inline std::string AnyToString(const T& value) @@ -49,17 +49,18 @@ CefString PutJavascriptCallback( bool ExecuteJavascriptCallback(int callbackId, CefRefPtr args) { if (g_jsCallbackMap.empty()) { - DebugLog("Renderer: ExecuteJavascriptCallback() FAILED: " \ - "callback map is empty"); + LOG(ERROR) << "[Renderer process] ExecuteJavascriptCallback():" + " callback map is empty"; return false; } JavascriptCallbackMap::const_iterator it = g_jsCallbackMap.find( callbackId); if (it == g_jsCallbackMap.end()) { - std::string logMessage = "Renderer: ExecuteJavascriptCallback() " - "FAILED: callback not found, id="; + std::string logMessage = "[Renderer process]" + " ExecuteJavascriptCallback():" + " callback not found, id="; logMessage.append(AnyToString(callbackId)); - DebugLog(logMessage.c_str()); + LOG(ERROR) << logMessage.c_str(); return false; } CefRefPtr frame = it->second.first; @@ -74,8 +75,8 @@ bool ExecuteJavascriptCallback(int callbackId, CefRefPtr args) { return true; } else { context->Exit(); - DebugLog("Renderer: ExecuteJavascriptCallback() FAILED: " \ - "callback->ExecuteFunction() FAILED"); + LOG(ERROR) << "[Renderer process] ExecuteJavascriptCallback():" + " callback->ExecuteFunction() failed"; return false; } } @@ -95,8 +96,9 @@ void RemoveJavascriptCallbacksForFrame(CefRefPtr frame) { // | ++it; // This would cause an infinite loop. g_jsCallbackMap.erase(it++); - DebugLog("Renderer: RemoveJavascriptCallbacksForFrame(): " \ - "removed js callback from the map"); + LOG(INFO) << "[Renderer process]" + " RemoveJavascriptCallbacksForFrame():" + " removed js callback from the map"; } else { ++it; } diff --git a/src/subprocess/v8function_handler.cpp b/src/subprocess/v8function_handler.cpp index 508a78bbf..0ce3a980b 100644 --- a/src/subprocess/v8function_handler.cpp +++ b/src/subprocess/v8function_handler.cpp @@ -4,7 +4,7 @@ #include "cefpython_app.h" #include "v8utils.h" -#include "DebugLog.h" +#include "include/base/cef_logging.h" bool V8FunctionHandler::Execute(const CefString& functionName, CefRefPtr thisObject, @@ -14,15 +14,16 @@ bool V8FunctionHandler::Execute(const CefString& functionName, if (!CefV8Context::InContext()) { // CefV8Context::GetCurrentContext may not be called when // not in a V8 context. - DebugLog("Renderer: V8FunctionHandler::Execute() FAILED:"\ - " not inside a V8 context"); + LOG(ERROR) << "[Renderer process] V8FunctionHandler::Execute():" + " not inside a V8 context"; return false; } CefRefPtr context = CefV8Context::GetCurrentContext(); CefRefPtr browser = context.get()->GetBrowser(); CefRefPtr frame = context.get()->GetFrame(); if (pythonCallbackId_) { - DebugLog("Renderer: V8FunctionHandler::Execute(): python callback"); + LOG(INFO) << "[Renderer process] V8FunctionHandler::Execute():" + " python callback"; CefRefPtr functionArguments = V8ValueListToCefListValue( v8Arguments); CefRefPtr processMessage = \ @@ -35,7 +36,8 @@ bool V8FunctionHandler::Execute(const CefString& functionName, returnValue = CefV8Value::CreateNull(); return true; } else { - DebugLog("Renderer: V8FunctionHandler::Execute(): js binding"); + LOG(INFO) << "[Renderer process] V8FunctionHandler::Execute():" + " js binding"; if (!(cefPythonApp_.get() \ && cefPythonApp_->BindedFunctionExists( \ browser, functionName))) { diff --git a/src/subprocess/v8utils.cpp b/src/subprocess/v8utils.cpp index e53d46a41..684f8c4ec 100644 --- a/src/subprocess/v8utils.cpp +++ b/src/subprocess/v8utils.cpp @@ -9,7 +9,7 @@ #include "v8utils.h" #include "javascript_callback.h" -#include "DebugLog.h" +#include "include/base/cef_logging.h" #include "cefpython_app.h" #include @@ -33,12 +33,13 @@ void V8ValueAppendToCefListValue(CefRefPtr v8Value, CefRefPtr listValue, int nestingLevel) { if (!v8Value->IsValid()) { - DebugLog("V8ValueAppendToCefListValue(): IsValid() FAILED"); + LOG(ERROR) << "[Renderer process] V8ValueAppendToCefListValue():" + " IsValid() failed"; return; } if (nestingLevel > 8) { - DebugLog("V8ValueAppendToCefListValue(): WARNING: max nesting level (8) " \ - "exceeded"); + LOG(ERROR) << "[Renderer process] V8ValueAppendToCefListValue():" + " max nesting level (8) exceeded"; return; } if (v8Value->IsUndefined() || v8Value->IsNull()) { @@ -53,7 +54,8 @@ void V8ValueAppendToCefListValue(CefRefPtr v8Value, &uint32_value, sizeof(uint32_value)); listValue->SetBinary((int)listValue->GetSize(), binaryValue); } else if (v8Value->IsDouble()) { - listValue->SetDouble((int)listValue->GetSize(), v8Value->GetDoubleValue()); + listValue->SetDouble((int)listValue->GetSize(), + v8Value->GetDoubleValue()); } else if (v8Value->IsDate()) { // TODO: in time_utils.pyx there are already functions for // converting cef_time_t to python DateTime, we could easily @@ -86,8 +88,9 @@ void V8ValueAppendToCefListValue(CefRefPtr v8Value, listValue->SetString((int)listValue->GetSize(), strCallbackId); } else { listValue->SetNull((int)listValue->GetSize()); - DebugLog("V8ValueAppendToCefListValue() FAILED: not in V8 context" - " , FATAL ERROR!"); + LOG(ERROR) << "[Renderer process] V8ValueAppendToCefListValue():" + " not in V8 context"; + return; } } else if (v8Value->IsObject()) { // Check for IsObject() must happen after the IsArray() @@ -96,7 +99,8 @@ void V8ValueAppendToCefListValue(CefRefPtr v8Value, V8ObjectToCefDictionaryValue(v8Value, nestingLevel + 1)); } else { listValue->SetNull((int)listValue->GetSize()); - DebugLog("V8ValueAppendToCefListValue() FAILED: unknown V8 type"); + LOG(ERROR) << "[Renderer process] V8ValueAppendToCefListValue():" + " unknown V8 type"; } } @@ -104,22 +108,25 @@ CefRefPtr V8ObjectToCefDictionaryValue( CefRefPtr v8Object, int nestingLevel) { if (!v8Object->IsValid()) { - DebugLog("V8ObjectToCefDictionaryValue(): IsValid() FAILED"); + LOG(ERROR) << "[Renderer process] V8ObjectToCefDictionaryValue():" + " IsValid() failed"; return CefDictionaryValue::Create(); } if (nestingLevel > 8) { - DebugLog("V8ObjectToCefDictionaryValue(): WARNING: " \ - "max nesting level (8) exceeded"); + LOG(ERROR) << "[Renderer process] V8ObjectToCefDictionaryValue():" + " max nesting level (8) exceeded"; return CefDictionaryValue::Create(); } if (!v8Object->IsObject()) { - DebugLog("V8ObjectToCefDictionaryValue(): IsObject() FAILED"); + LOG(ERROR) << "[Renderer process] V8ObjectToCefDictionaryValue():" + " IsObject() failed"; return CefDictionaryValue::Create(); } CefRefPtr ret = CefDictionaryValue::Create(); std::vector keys; if (!v8Object->GetKeys(keys)) { - DebugLog("V8ObjectToCefDictionaryValue(): GetKeys() FAILED"); + LOG(ERROR) << "[Renderer process] V8ObjectToCefDictionaryValue():" + " GetKeys() failed"; return ret; } for (std::vector::iterator it = keys.begin(); \ @@ -172,8 +179,9 @@ CefRefPtr V8ObjectToCefDictionaryValue( ret->SetString(key, strCallbackId); } else { ret->SetNull(key); - DebugLog("V8ObjectToCefDictionaryValue() FAILED: " \ - "not in V8 context FATAL ERROR!"); + LOG(ERROR) << "[Renderer process]" + " V8ObjectToCefDictionaryValue():" + " not in V8 context"; } } else if (v8Value->IsObject()) { // Check for IsObject() must happen after the IsArray() @@ -182,7 +190,8 @@ CefRefPtr V8ObjectToCefDictionaryValue( V8ObjectToCefDictionaryValue(v8Value, nestingLevel + 1)); } else { ret->SetNull(key); - DebugLog("V8ObjectToCefDictionaryValue() FAILED: unknown V8 type"); + LOG(ERROR) << "[Renderer process] V8ObjectToCefDictionaryValue():" + " unknown V8 type"; } } return ret; @@ -223,13 +232,13 @@ CefRefPtr CefListValueToV8Value( CefRefPtr listValue, int nestingLevel) { if (!listValue->IsValid()) { - DebugLog("CefListValueToV8Value() FAILED: " \ - "CefDictionaryValue is invalid"); + LOG(ERROR) << "[Renderer process] CefListValueToV8Value():" + " CefDictionaryValue is invalid"; return CefV8Value::CreateNull(); } if (nestingLevel > 8) { - DebugLog("CefListValueToV8Value(): WARNING: " \ - "max nesting level (8) exceeded"); + LOG(ERROR) << "[Renderer process] CefListValueToV8Value():" + " max nesting level (8) exceeded"; return CefV8Value::CreateNull(); } int listSize = (int)listValue->GetSize(); @@ -269,8 +278,8 @@ CefRefPtr CefListValueToV8Value( CefV8Value::CreateFunction( callbackName, v8FunctionHandler)); } else { - DebugLog("CefListValueToV8Value(): WARNING: " \ - "unknown binary value, setting value to null"); + LOG(ERROR) << "[Renderer process] CefListValueToV8Value():" + " unknown binary value, setting value to null"; success = ret->SetValue(key, CefV8Value::CreateNull()); } } else if (valueType == VTYPE_DICTIONARY) { @@ -284,14 +293,14 @@ CefRefPtr CefListValueToV8Value( listValue->GetList(key), nestingLevel + 1)); } else { - DebugLog("CefListValueToV8Value(): WARNING: " \ - "unknown type, setting value to null"); + LOG(ERROR) << "[Renderer process] CefListValueToV8Value():" + " unknown type, setting value to null"; success = ret->SetValue(key, CefV8Value::CreateNull()); } if (!success) { - DebugLog("CefListValueToV8Value(): WARNING: " \ - "ret->SetValue() failed"); + LOG(ERROR) << "[Renderer process] CefListValueToV8Value():" + " ret->SetValue() failed"; } } return ret; @@ -301,19 +310,19 @@ CefRefPtr CefDictionaryValueToV8Value( CefRefPtr dictValue, int nestingLevel) { if (!dictValue->IsValid()) { - DebugLog("CefDictionaryValueToV8Value() FAILED: " \ - "CefDictionaryValue is invalid"); + LOG(ERROR) << "[Renderer process] CefDictionaryValueToV8Value():" + " CefDictionaryValue is invalid"; return CefV8Value::CreateNull(); } if (nestingLevel > 8) { - DebugLog("CefDictionaryValueToV8Value(): WARNING: " \ - "max nesting level (8) exceeded"); + LOG(ERROR) << "[Renderer process] CefDictionaryValueToV8Value():" + " max nesting level (8) exceeded"; return CefV8Value::CreateNull(); } std::vector keys; if (!dictValue->GetKeys(keys)) { - DebugLog("CefDictionaryValueToV8Value() FAILED: " \ - "dictValue->GetKeys() failed"); + LOG(ERROR) << "[Renderer process] CefDictionaryValueToV8Value():" + " dictValue->GetKeys() failed"; return CefV8Value::CreateNull(); } CefRefPtr ret = CefV8Value::CreateObject(NULL, NULL); @@ -360,8 +369,8 @@ CefRefPtr CefDictionaryValueToV8Value( callbackName, v8FunctionHandler), V8_PROPERTY_ATTRIBUTE_NONE); } else { - DebugLog("CefListValueToV8Value(): WARNING: " \ - "unknown binary value, setting value to null"); + LOG(ERROR) << "[Renderer process] CefListValueToV8Value():" + " unknown binary value, setting value to null"; success = ret->SetValue(key, CefV8Value::CreateNull(), V8_PROPERTY_ATTRIBUTE_NONE); @@ -379,15 +388,15 @@ CefRefPtr CefDictionaryValueToV8Value( nestingLevel + 1), V8_PROPERTY_ATTRIBUTE_NONE); } else { - DebugLog("CefDictionaryValueToV8Value(): WARNING: " \ - "unknown type, setting value to null"); + LOG(ERROR) << "[Renderer process] CefDictionaryValueToV8Value():" + " unknown type, setting value to null"; success = ret->SetValue(key, CefV8Value::CreateNull(), V8_PROPERTY_ATTRIBUTE_NONE); } if (!success) { - DebugLog("CefDictionaryValueToV8Value(): WARNING: " \ - "ret->SetValue() failed"); + LOG(ERROR) << "[Renderer process] CefDictionaryValueToV8Value():" + " ret->SetValue() failed"; } } return ret; diff --git a/src/utils.pyx b/src/utils.pyx index 3f51b25ae..62781196a 100644 --- a/src/utils.pyx +++ b/src/utils.pyx @@ -43,22 +43,17 @@ cpdef py_bool IsThread(int threadID): cpdef object Debug(py_string msg): """Print debug message. Will be shown only when settings.debug=True.""" - if not g_debug: - return # In Python 3 str or bytes may be passed if type(msg) != str and type(msg) == bytes: msg = msg.decode("utf-8", "replace") # Convert to str in case other kind of object was passed msg = str(msg) - msg = "[CEF Python] "+msg - print(msg) - if g_debugFile: - try: - with open(g_debugFile, "a") as file_: - file_.write(msg+"\n") - except: - print("[CEF Python] WARNING: failed writing to debug file: %s" % ( - g_debugFile)) + msg = "[Browser process] " + msg + # CEF logging is initialized only after CEF was initialized. + # Otherwise the default is LOGSEVERITY_INFO and log_file is + # none. + if g_cef_initialized or g_debug: + cef_log_info(msg) cdef void NonCriticalError(py_string msg) except *: """Notify about error gently. Does not terminate application.""" @@ -67,15 +62,8 @@ cdef void NonCriticalError(py_string msg) except *: msg = msg.decode("utf-8", "replace") # Convert to str in case other kind of object was passed msg = str(msg) - msg = "[CEF Python] ERROR: "+msg - print(msg) - if g_debugFile: - try: - with open(g_debugFile, "a") as file_: - file_.write(msg+"\n") - except: - print("[CEF Python] WARNING: failed writing to debug file: %s" % ( - g_debugFile)) + msg = "[Browser process] " + msg + cef_log_error(PyStringToChar(msg)) cpdef str GetSystemError(): IF UNAME_SYSNAME == "Windows": diff --git a/tools/cython_setup.py b/tools/cython_setup.py index 368d5ccc3..29baa755a 100644 --- a/tools/cython_setup.py +++ b/tools/cython_setup.py @@ -171,21 +171,21 @@ def set_compiler_options(options): if LINUX: os.environ["CC"] = "g++" os.environ["CXX"] = "g++" + extra_compile_args.extend(["-std=gnu++11"]) + + # Fix "ImportError ... undefined symbol ..." caused by CEF's + # include/base/ headers by adding the -flto flag (Issue #230). + # Unfortunately -flto prolongs compilation time significantly. + # More on the other flags: https://stackoverflow.com/questions/ + # 6687630/ . if FAST_FLAG: - extra_compile_args.extend(["-flto", - "-std=gnu++11"]) + extra_compile_args.extend(["-flto"]) extra_link_args.extend(["-flto"]) else: - # Fix "ImportError ... undefined symbol ..." caused by CEF's - # include/base/ headers by adding the -flto flag (Issue #230). - # Unfortunately -flto prolongs compilation time significantly. - # More on the other flags: https://stackoverflow.com/questions/ - # 6687630/ . extra_compile_args.extend(["-flto", "-fdata-sections", - "-ffunction-sections", - "-std=gnu++11"]) + "-ffunction-sections"]) extra_link_args.extend(["-flto", "-Wl,--gc-sections"]) From eeae125d59727ce5c77355128353741e5f8b4db3 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 19 Apr 2017 19:12:45 +0200 Subject: [PATCH 216/557] Fix build on Linux and fix logging function on Python 3 (#352). --- src/client_handler/client_handler.h | 2 -- src/common/cefpython_public_api.h | 15 +++++++++------ src/compile_time_constants.pxi | 2 +- src/utils.pyx | 2 +- tools/build.py | 19 +++++++++++++++---- 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/client_handler/client_handler.h b/src/client_handler/client_handler.h index 4a5c29b7c..3e9e3917b 100644 --- a/src/client_handler/client_handler.h +++ b/src/client_handler/client_handler.h @@ -10,8 +10,6 @@ #include #endif -#include "common/cefpython_public_api.h" - #include "context_menu_handler.h" #include "dialog_handler.h" #include "display_handler.h" diff --git a/src/common/cefpython_public_api.h b/src/common/cefpython_public_api.h index 0fa115d41..0fbd60a56 100644 --- a/src/common/cefpython_public_api.h +++ b/src/common/cefpython_public_api.h @@ -9,18 +9,21 @@ #ifndef CEFPYTHON_PUBLIC_API_H #define CEFPYTHON_PUBLIC_API_H -// Includes required by "cefpython_fixed.h". -#include "include/cef_client.h" -#include "include/cef_urlrequest.h" -#include "include/cef_command_line.h" -#include "util.h" - #if defined(OS_WIN) #pragma warning(disable:4190) // cefpython API extern C-linkage warnings #endif +// Python.h must be included first otherwise error on Linux: +// >> error: "_POSIX_C_SOURCE" redefined #include "Python.h" + +// Includes required by "cefpython_fixed.h". +#include "include/cef_client.h" +#include "include/cef_urlrequest.h" +#include "include/cef_command_line.h" +#include "util.h" + // cefpython_fixed.h declares public functions using DL_IMPORT and these // macros are not available in Python 3. #ifndef DL_IMPORT diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 35f850027..47dedaecd 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 PY_MAJOR_VERSION = 3 diff --git a/src/utils.pyx b/src/utils.pyx index 62781196a..e253e9f74 100644 --- a/src/utils.pyx +++ b/src/utils.pyx @@ -53,7 +53,7 @@ cpdef object Debug(py_string msg): # Otherwise the default is LOGSEVERITY_INFO and log_file is # none. if g_cef_initialized or g_debug: - cef_log_info(msg) + cef_log_info(PyStringToChar(msg)) cdef void NonCriticalError(py_string msg) except *: """Notify about error gently. Does not terminate application.""" diff --git a/tools/build.py b/tools/build.py index 3e4f0f8ba..1ae47b737 100644 --- a/tools/build.py +++ b/tools/build.py @@ -41,6 +41,14 @@ # function then you can't pass shell=True on Linux. If you pass # then it will execute args[0] and ignore others args. +# NOTE 2: When calling os.system() returned value may be 256 when eg. +# when running unit tests fail. If you pass 256 to sys.exit +# an undefined result will occur. In my case on Linux it caused +# that other script that called it sys.exit(256) was interpreted +# for the script execute successfully. So never pass to sys.exit +# a value returned from os.system. Check the value and call +# sys.exit(1). + # How to debug on Linux (OLD unsupported). # 1. Install "python-dbg" package # 2. Install "python-wxgtk2.8-dbg" package @@ -753,7 +761,10 @@ def build_cefpython_module(): args.extend(sys.argv[1:]) command = " ".join(args) ret = subprocess.call(command, shell=True) - sys.exit(ret) + # Always pass fixed value to sys.exit, read note at + # the top of the script about os.system and sys.exit + # issue. + sys.exit(0 if ret == 0 else 1) else: print("[build.py] ERROR: failed to build the cefpython module") sys.exit(1) @@ -823,7 +834,7 @@ def install_and_run(): ret = os.system(command) if ret != 0: print("[build.py] ERROR while making installer package") - sys.exit(ret) + sys.exit(1) # Install print("[build.py] Install the cefpython package") @@ -834,7 +845,7 @@ def install_and_run(): ret = os.system(command) if ret != 0: print("[build.py] ERROR while installing package") - sys.exit(ret) + sys.exit(1) os.chdir(BUILD_DIR) # Delete setup installer directory after the package was installed @@ -849,7 +860,7 @@ def install_and_run(): ret = os.system(command) if ret != 0: print("[build.py] ERROR while running unit tests") - sys.exit(ret) + sys.exit(1) # Run examples if not NO_RUN_EXAMPLES: From 321b34abe4067195ed3d042beef211f2546182b1 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Wed, 19 Apr 2017 21:29:10 +0200 Subject: [PATCH 217/557] Update docs for 56.2 release. Do not call client handlers nor javascript bindings in DevTools windows (#344). Update Tutorial and tutorial.py example. --- README.md | 2 +- docs/Migration-guide.md | 11 +++++------ docs/Tutorial.md | 6 +----- examples/Examples-README.md | 2 +- examples/tutorial.py | 18 +++--------------- 5 files changed, 11 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 114d2d358..7b4bbfaae 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ also download packages for offline installation available on the [GitHub Releases](../../releases) pages. ``` -pip install cefpython3==56.1 +pip install cefpython3==56.2 ``` ## Tutorial diff --git a/docs/Migration-guide.md b/docs/Migration-guide.md index 3bab17bc4..d938e70d2 100644 --- a/docs/Migration-guide.md +++ b/docs/Migration-guide.md @@ -40,12 +40,11 @@ Table of contents: ## v50+ Distribution packages -In latest CEF Python there are only two distribution packages -available. The first one is a wheel package distributed through -PyPI, which you can install using the pip tool (8.1+ required -on Linux). The second one is a setup package available for -download on the GitHub Releases pages, instructions on how to -install it are provided in README.txt. +In latest CEF Python there is only one distribution package +available: a wheel package. Wheel packages are distributed on +[PyPI](https://pypi.python.org/pypi/cefpython3) and you can +install it using the pip tool (8.1+ required on Linux). You +can also download wheel packages from [GitHub Releases](../../../releases). **Windows** diff --git a/docs/Tutorial.md b/docs/Tutorial.md index 91cc029a1..c4a38ec25 100644 --- a/docs/Tutorial.md +++ b/docs/Tutorial.md @@ -36,7 +36,7 @@ Run the commands below to install the cefpython3 package, clone the repository and run the Hello World example: ```commandline -pip install cefpython3==56.1 +pip install cefpython3==56.2 git clone https://github.com/cztomczak/cefpython.git cd cefpython/examples/ python hello_world.py @@ -320,10 +320,6 @@ def set_client_handlers(browser): ... class LoadHandler(object): def OnLoadingStateChange(self, browser, is_loading, **_): - # Issue #344 will fix this in next release, so that client - # handlers are not called for Developer Tools windows. - if browser.GetUrl().startswith("chrome-devtools://"): - return # This callback is called twice, once when loading starts # (is_loading=True) and second time when loading ends # (is_loading=False). diff --git a/examples/Examples-README.md b/examples/Examples-README.md index 2fae3e14a..7be26d960 100644 --- a/examples/Examples-README.md +++ b/examples/Examples-README.md @@ -11,7 +11,7 @@ Instructions to install the cefpython3 package, clone the repository and run the hello_world.py example: ``` -pip install cefpython3==56.1 +pip install cefpython3==56.2 git clone https://github.com/cztomczak/cefpython.git cd cefpython/examples/ python hello_world.py diff --git a/examples/tutorial.py b/examples/tutorial.py index 28d69ddb7..a2b04ca89 100644 --- a/examples/tutorial.py +++ b/examples/tutorial.py @@ -1,5 +1,5 @@ # Tutorial example. Doesn't depend on any third party GUI framework. -# Tested with CEF Python v56.1+ +# Tested with CEF Python v56.2+ from cefpython3 import cefpython as cef import base64 @@ -61,7 +61,7 @@ def main(): cef.Initialize() set_global_handler() browser = cef.CreateBrowserSync(url=html_to_data_uri(HTML_code), - window_title="Hello World!") + window_title="Tutorial") set_client_handlers(browser) set_javascript_bindings(browser) cef.MessageLoop() @@ -72,7 +72,7 @@ def check_versions(): print("[tutorial.py] CEF Python {ver}".format(ver=cef.__version__)) print("[tutorial.py] Python {ver} {arch}".format( ver=platform.python_version(), arch=platform.architecture()[0])) - assert cef.__version__ >= "56.1", "CEF Python v56.1+ required to run this" + assert cef.__version__ >= "56.2", "CEF Python v56.2+ required to run this" def html_to_data_uri(html, js_callback=None): @@ -125,10 +125,6 @@ def js_print(browser, lang, event, msg): class GlobalHandler(object): def OnAfterCreated(self, browser, **_): - # Issue #344 will fix this in next release, so that client - # handlers are not called for Developer Tools windows. - if browser.GetUrl().startswith("chrome-devtools://"): - return # DOM is not yet loaded. Using js_print at this moment will # throw an error: "Uncaught ReferenceError: js_print is not defined". # We make this error on purpose. This error will be intercepted @@ -143,10 +139,6 @@ def OnAfterCreated(self, browser, **_): class LoadHandler(object): def OnLoadingStateChange(self, browser, is_loading, **_): - # Issue #344 will fix this in next release, so that client - # handlers are not called for Developer Tools windows. - if browser.GetUrl().startswith("chrome-devtools://"): - return # This callback is called twice, once when loading starts # (is_loading=True) and second time when loading ends # (is_loading=False). @@ -158,10 +150,6 @@ def OnLoadingStateChange(self, browser, is_loading, **_): class DisplayHandler(object): def OnConsoleMessage(self, browser, message, **_): - # Issue #344 will fix this in next release, so that client - # handlers are not called for Developer Tools windows. - if browser.GetUrl().startswith("chrome-devtools://"): - return # This will intercept js errors, see comments in OnAfterCreated if "error" in message.lower() or "uncaught" in message.lower(): # Prevent infinite recurrence in case something went wrong From 91ec299744c7854fb8eca5f4881274a925c1a4bd Mon Sep 17 00:00:00 2001 From: cztomczak Date: Thu, 20 Apr 2017 15:15:26 +0200 Subject: [PATCH 218/557] Update to Chromium 57.0.2987.133 on Linux (incomplete) (#341). CEF 3.2987.1601.gf035232 Update patches. --- patches/issue125.patch | 4 +- patches/issue231.patch | 8 +- patches/issue251.patch | 16 +- src/extern/cef/cef_base.pxd | 10 - src/include/base/cef_build.h | 9 + src/include/cef_app.h | 4 +- src/include/cef_auth_callback.h | 2 +- src/include/cef_base.h | 17 +- src/include/cef_browser.h | 12 +- src/include/cef_browser_process_handler.h | 2 +- src/include/cef_callback.h | 4 +- src/include/cef_client.h | 2 +- src/include/cef_command_line.h | 2 +- src/include/cef_context_menu_handler.h | 6 +- src/include/cef_cookie.h | 8 +- src/include/cef_dialog_handler.h | 4 +- src/include/cef_display_handler.h | 2 +- src/include/cef_dom.h | 6 +- src/include/cef_download_handler.h | 6 +- src/include/cef_download_item.h | 2 +- src/include/cef_drag_data.h | 2 +- src/include/cef_drag_handler.h | 2 +- src/include/cef_find_handler.h | 2 +- src/include/cef_focus_handler.h | 2 +- src/include/cef_frame.h | 2 +- src/include/cef_geolocation.h | 2 +- src/include/cef_geolocation_handler.h | 4 +- src/include/cef_image.h | 2 +- src/include/cef_jsdialog_handler.h | 4 +- src/include/cef_keyboard_handler.h | 2 +- src/include/cef_life_span_handler.h | 2 +- src/include/cef_load_handler.h | 2 +- src/include/cef_menu_model.h | 87 ++++- src/include/cef_menu_model_delegate.h | 26 +- src/include/cef_navigation_entry.h | 2 +- src/include/cef_print_handler.h | 6 +- src/include/cef_print_settings.h | 2 +- src/include/cef_process_message.h | 2 +- src/include/cef_render_handler.h | 2 +- src/include/cef_render_process_handler.h | 2 +- src/include/cef_request.h | 6 +- src/include/cef_request_context.h | 4 +- src/include/cef_request_context_handler.h | 2 +- src/include/cef_request_handler.h | 6 +- src/include/cef_resource_bundle.h | 2 +- src/include/cef_resource_bundle_handler.h | 2 +- src/include/cef_resource_handler.h | 2 +- src/include/cef_response.h | 2 +- src/include/cef_response_filter.h | 2 +- src/include/cef_scheme.h | 31 +- src/include/cef_ssl_info.h | 2 +- src/include/cef_ssl_status.h | 2 +- src/include/cef_stream.h | 8 +- src/include/cef_string_visitor.h | 2 +- src/include/cef_task.h | 4 +- src/include/cef_thread.h | 2 +- src/include/cef_trace.h | 2 +- src/include/cef_urlrequest.h | 4 +- src/include/cef_v8.h | 20 +- src/include/cef_values.h | 8 +- src/include/cef_waitable_event.h | 2 +- src/include/cef_web_plugin.h | 8 +- src/include/cef_x509_certificate.h | 4 +- src/include/cef_xml_reader.h | 2 +- src/include/cef_zip_reader.h | 2 +- src/include/internal/cef_ptr.h | 85 +++- src/include/internal/cef_string_types.h | 11 + src/include/internal/cef_types.h | 20 + src/include/internal/cef_types_wrappers.h | 2 + src/include/test/cef_translator_test.h | 409 +++++++++++++++++--- src/include/views/cef_browser_view.h | 12 + src/include/views/cef_button.h | 6 + src/include/views/cef_button_delegate.h | 6 + src/include/views/cef_display.h | 2 +- src/include/views/cef_layout.h | 2 +- src/include/views/cef_menu_button.h | 7 + src/include/views/cef_view.h | 16 +- src/include/views/cef_view_delegate.h | 14 +- src/include/views/cef_window.h | 24 ++ src/include/views/cef_window_delegate.h | 19 + src/include/wrapper/cef_byte_read_handler.h | 4 +- src/include/wrapper/cef_closure_task.h | 2 +- src/include/wrapper/cef_message_router.h | 2 +- src/include/wrapper/cef_zip_archive.h | 2 +- 84 files changed, 836 insertions(+), 223 deletions(-) delete mode 100644 src/extern/cef/cef_base.pxd diff --git a/patches/issue125.patch b/patches/issue125.patch index 1cde324ae..4c9f304ac 100644 --- a/patches/issue125.patch +++ b/patches/issue125.patch @@ -1,8 +1,8 @@ diff --git http_cache_transaction.cc http_cache_transaction.cc -index 717522eb6951..e92ba22a9ca9 100644 +index 24002d75215d..2a44a6368558 100644 --- http_cache_transaction.cc +++ http_cache_transaction.cc -@@ -2554,7 +2554,8 @@ int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { +@@ -2601,7 +2601,8 @@ int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { // blocking page is shown. An alternative would be to reverse-map the cert // status to a net error and replay the net error. if ((response_.headers->HasHeaderValue("cache-control", "no-store")) || diff --git a/patches/issue231.patch b/patches/issue231.patch index c265759bc..6e62498ed 100644 --- a/patches/issue231.patch +++ b/patches/issue231.patch @@ -83,10 +83,10 @@ index 6a759309..ad620d7f 100644 + return PathService::Override(pref_key, file_path); +} diff --git libcef_dll/libcef_dll.cc libcef_dll/libcef_dll.cc -index 1f037f92..b0274ad8 100644 +index 096eede2..05ecf9bd 100644 --- libcef_dll/libcef_dll.cc +++ libcef_dll/libcef_dll.cc -@@ -927,6 +927,23 @@ CEF_EXPORT int cef_get_path(cef_path_key_t key, cef_string_t* path) { +@@ -959,6 +959,23 @@ CEF_EXPORT int cef_get_path(cef_path_key_t key, cef_string_t* path) { return _retval; } @@ -111,10 +111,10 @@ index 1f037f92..b0274ad8 100644 // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING diff --git libcef_dll/wrapper/libcef_dll_wrapper.cc libcef_dll/wrapper/libcef_dll_wrapper.cc -index c4a1b559..a0b7765b 100644 +index 15026ab5..a3d21052 100644 --- libcef_dll/wrapper/libcef_dll_wrapper.cc +++ libcef_dll/wrapper/libcef_dll_wrapper.cc -@@ -848,6 +848,23 @@ CEF_GLOBAL bool CefGetPath(PathKey key, CefString& path) { +@@ -880,6 +880,23 @@ CEF_GLOBAL bool CefGetPath(PathKey key, CefString& path) { return _retval?true:false; } diff --git a/patches/issue251.patch b/patches/issue251.patch index e1e9bc4ea..1a7b51538 100644 --- a/patches/issue251.patch +++ b/patches/issue251.patch @@ -1,5 +1,5 @@ diff --git include/capi/cef_drag_data_capi.h include/capi/cef_drag_data_capi.h -index 2e84df8f..5b17e212 100644 +index e1fcfd8c..fc388247 100644 --- include/capi/cef_drag_data_capi.h +++ include/capi/cef_drag_data_capi.h @@ -39,6 +39,7 @@ @@ -34,7 +34,7 @@ index 2e84df8f..5b17e212 100644 diff --git include/cef_drag_data.h include/cef_drag_data.h -index 8f8094b4..8b4602b1 100644 +index 29b85e84..e3c9c2df 100644 --- include/cef_drag_data.h +++ include/cef_drag_data.h @@ -39,6 +39,7 @@ @@ -45,7 +45,7 @@ index 8f8094b4..8b4602b1 100644 #include "include/cef_stream.h" #include -@@ -193,6 +194,24 @@ class CefDragData : public virtual CefBase { +@@ -193,6 +194,24 @@ class CefDragData : public virtual CefBaseRefCounted { /// /*--cef(optional_param=display_name)--*/ virtual void AddFile(const CefString& path, const CefString& display_name) =0; @@ -181,7 +181,7 @@ index 64f29ed3..98707262 100644 // True if this object is read-only. bool read_only_; diff --git libcef_dll/cpptoc/drag_data_cpptoc.cc libcef_dll/cpptoc/drag_data_cpptoc.cc -index ffad1755..70a6c5c2 100644 +index 381b88b9..6f4925a0 100644 --- libcef_dll/cpptoc/drag_data_cpptoc.cc +++ libcef_dll/cpptoc/drag_data_cpptoc.cc @@ -11,6 +11,7 @@ @@ -254,9 +254,9 @@ index ffad1755..70a6c5c2 100644 + GetStruct()->has_image = drag_data_has_image; } - template<> CefRefPtr CefCppToC CefRefPtr CefCppToCRefCounted 199711L || \ + (defined(_MSC_VER) && _MSC_VER >= 1800) || \ + (defined(__GNUC__) && \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ >= 40700)) +#define HAS_CPP11_TEMPLATE_ALIAS_SUPPORT +#endif + #endif // CEF_INCLUDE_BASE_CEF_BUILD_H_ diff --git a/src/include/cef_app.h b/src/include/cef_app.h index 098b6d756..5aca29b30 100644 --- a/src/include/cef_app.h +++ b/src/include/cef_app.h @@ -143,7 +143,7 @@ void CefEnableHighDPISupport(); // called by the process and/or thread indicated. /// /*--cef(source=client,no_debugct_check)--*/ -class CefApp : public virtual CefBase { +class CefApp : public virtual CefBaseRefCounted { public: /// // Provides an opportunity to view and/or modify command-line arguments before @@ -170,7 +170,7 @@ class CefApp : public virtual CefBase { /// /*--cef()--*/ virtual void OnRegisterCustomSchemes( - CefRefPtr registrar) { + CefRawPtr registrar) { } /// diff --git a/src/include/cef_auth_callback.h b/src/include/cef_auth_callback.h index 86d249ad3..ca511fdc4 100644 --- a/src/include/cef_auth_callback.h +++ b/src/include/cef_auth_callback.h @@ -45,7 +45,7 @@ // requests. /// /*--cef(source=library)--*/ -class CefAuthCallback : public virtual CefBase { +class CefAuthCallback : public virtual CefBaseRefCounted { public: /// // Continue the authentication request. diff --git a/src/include/cef_base.h b/src/include/cef_base.h index c9213588a..c152cf06d 100644 --- a/src/include/cef_base.h +++ b/src/include/cef_base.h @@ -48,10 +48,9 @@ #endif /// -// Interface defining the reference count implementation methods. All framework -// classes must extend the CefBase class. +// All ref-counted framework classes must extend this class. /// -class CefBase { +class CefBaseRefCounted { public: /// // Called to increment the reference count for the object. Should be called @@ -71,7 +70,15 @@ class CefBase { virtual bool HasOneRef() const =0; protected: - virtual ~CefBase() {} + virtual ~CefBaseRefCounted() {} +}; + +/// +// All scoped framework classes must extend this class. +/// +class CefBaseScoped { + public: + virtual ~CefBaseScoped() {} }; /// @@ -141,7 +148,7 @@ class CefRefCount { // #include "include/base/cef_lock.h" // // // Class declaration. -// class MyClass : public CefBase { +// class MyClass : public CefBaseRefCounted { // public: // MyClass() : value_(0) {} // // Method that may be called on multiple threads. diff --git a/src/include/cef_browser.h b/src/include/cef_browser.h index 2d4d8abb7..3b4ed1617 100644 --- a/src/include/cef_browser.h +++ b/src/include/cef_browser.h @@ -58,7 +58,7 @@ class CefClient; // this class may only be called on the main thread. /// /*--cef(source=library)--*/ -class CefBrowser : public virtual CefBase { +class CefBrowser : public virtual CefBaseRefCounted { public: /// // Returns the browser host object. This method can only be called in the @@ -197,7 +197,7 @@ class CefBrowser : public virtual CefBase { // class will be called on the browser process UI thread. /// /*--cef(source=client)--*/ -class CefRunFileDialogCallback : public virtual CefBase { +class CefRunFileDialogCallback : public virtual CefBaseRefCounted { public: /// // Called asynchronously after the file dialog is dismissed. @@ -218,7 +218,7 @@ class CefRunFileDialogCallback : public virtual CefBase { // this class will be called on the browser process UI thread. /// /*--cef(source=client)--*/ -class CefNavigationEntryVisitor : public virtual CefBase { +class CefNavigationEntryVisitor : public virtual CefBaseRefCounted { public: /// // Method that will be executed. Do not keep a reference to |entry| outside of @@ -240,7 +240,7 @@ class CefNavigationEntryVisitor : public virtual CefBase { // will be called on the browser process UI thread. /// /*--cef(source=client)--*/ -class CefPdfPrintCallback : public virtual CefBase { +class CefPdfPrintCallback : public virtual CefBaseRefCounted { public: /// // Method that will be executed when the PDF printing has completed. |path| @@ -257,7 +257,7 @@ class CefPdfPrintCallback : public virtual CefBase { // class will be called on the browser process UI thread. /// /*--cef(source=client)--*/ -class CefDownloadImageCallback : public virtual CefBase { +class CefDownloadImageCallback : public virtual CefBaseRefCounted { public: /// // Method that will be executed when the image download has completed. @@ -280,7 +280,7 @@ class CefDownloadImageCallback : public virtual CefBase { // comments. /// /*--cef(source=library)--*/ -class CefBrowserHost : public virtual CefBase { +class CefBrowserHost : public virtual CefBaseRefCounted { public: typedef cef_drag_operations_mask_t DragOperationsMask; typedef cef_file_dialog_mode_t FileDialogMode; diff --git a/src/include/cef_browser_process_handler.h b/src/include/cef_browser_process_handler.h index 9045d09a9..e65503fbd 100644 --- a/src/include/cef_browser_process_handler.h +++ b/src/include/cef_browser_process_handler.h @@ -48,7 +48,7 @@ // will be called on the browser process main thread unless otherwise indicated. /// /*--cef(source=client)--*/ -class CefBrowserProcessHandler : public virtual CefBase { +class CefBrowserProcessHandler : public virtual CefBaseRefCounted { public: /// // Called on the browser process UI thread immediately after the CEF context diff --git a/src/include/cef_callback.h b/src/include/cef_callback.h index e5efebd2d..5be51e941 100644 --- a/src/include/cef_callback.h +++ b/src/include/cef_callback.h @@ -44,7 +44,7 @@ // Generic callback interface used for asynchronous continuation. /// /*--cef(source=library)--*/ -class CefCallback : public virtual CefBase { +class CefCallback : public virtual CefBaseRefCounted { public: /// // Continue processing. @@ -63,7 +63,7 @@ class CefCallback : public virtual CefBase { // Generic callback interface used for asynchronous completion. /// /*--cef(source=client)--*/ -class CefCompletionCallback : public virtual CefBase { +class CefCompletionCallback : public virtual CefBaseRefCounted { public: /// // Method that will be called once the task is complete. diff --git a/src/include/cef_client.h b/src/include/cef_client.h index 81a67ebae..9421c7c08 100644 --- a/src/include/cef_client.h +++ b/src/include/cef_client.h @@ -59,7 +59,7 @@ // Implement this interface to provide handler implementations. /// /*--cef(source=client,no_debugct_check)--*/ -class CefClient : public virtual CefBase { +class CefClient : public virtual CefBaseRefCounted { public: /// // Return the handler for context menus. If no handler is provided the default diff --git a/src/include/cef_command_line.h b/src/include/cef_command_line.h index 96241cf43..5e581b6e0 100644 --- a/src/include/cef_command_line.h +++ b/src/include/cef_command_line.h @@ -53,7 +53,7 @@ // used before CefInitialize() is called. /// /*--cef(source=library,no_debugct_check)--*/ -class CefCommandLine : public virtual CefBase { +class CefCommandLine : public virtual CefBaseRefCounted { public: typedef std::vector ArgumentList; typedef std::map SwitchMap; diff --git a/src/include/cef_context_menu_handler.h b/src/include/cef_context_menu_handler.h index 2bad463b1..7619b8ed0 100644 --- a/src/include/cef_context_menu_handler.h +++ b/src/include/cef_context_menu_handler.h @@ -50,7 +50,7 @@ class CefContextMenuParams; // Callback interface used for continuation of custom context menu display. /// /*--cef(source=library)--*/ -class CefRunContextMenuCallback : public virtual CefBase { +class CefRunContextMenuCallback : public virtual CefBaseRefCounted { public: typedef cef_event_flags_t EventFlags; @@ -74,7 +74,7 @@ class CefRunContextMenuCallback : public virtual CefBase { // class will be called on the UI thread. /// /*--cef(source=client)--*/ -class CefContextMenuHandler : public virtual CefBase { +class CefContextMenuHandler : public virtual CefBaseRefCounted { public: typedef cef_event_flags_t EventFlags; @@ -139,7 +139,7 @@ class CefContextMenuHandler : public virtual CefBase { // can only be accessed on browser process the UI thread. /// /*--cef(source=library)--*/ -class CefContextMenuParams : public virtual CefBase { +class CefContextMenuParams : public virtual CefBaseRefCounted { public: typedef cef_context_menu_type_flags_t TypeFlags; typedef cef_context_menu_media_type_t MediaType; diff --git a/src/include/cef_cookie.h b/src/include/cef_cookie.h index b4cb33cb5..28f056d8a 100644 --- a/src/include/cef_cookie.h +++ b/src/include/cef_cookie.h @@ -51,7 +51,7 @@ class CefDeleteCookiesCallback; // any thread unless otherwise indicated. /// /*--cef(source=library,no_debugct_check)--*/ -class CefCookieManager : public virtual CefBase { +class CefCookieManager : public virtual CefBaseRefCounted { public: /// // Returns the global cookie manager. By default data will be stored at @@ -171,7 +171,7 @@ class CefCookieManager : public virtual CefBase { // will always be called on the IO thread. /// /*--cef(source=client)--*/ -class CefCookieVisitor : public virtual CefBase { +class CefCookieVisitor : public virtual CefBaseRefCounted { public: /// // Method that will be called once for each cookie. |count| is the 0-based @@ -191,7 +191,7 @@ class CefCookieVisitor : public virtual CefBase { // CefCookieManager::SetCookie(). /// /*--cef(source=client)--*/ -class CefSetCookieCallback : public virtual CefBase { +class CefSetCookieCallback : public virtual CefBaseRefCounted { public: /// // Method that will be called upon completion. |success| will be true if the @@ -207,7 +207,7 @@ class CefSetCookieCallback : public virtual CefBase { // CefCookieManager::DeleteCookies(). /// /*--cef(source=client)--*/ -class CefDeleteCookiesCallback : public virtual CefBase { +class CefDeleteCookiesCallback : public virtual CefBaseRefCounted { public: /// // Method that will be called upon completion. |num_deleted| will be the diff --git a/src/include/cef_dialog_handler.h b/src/include/cef_dialog_handler.h index 93cd5de7c..3ca98fb51 100644 --- a/src/include/cef_dialog_handler.h +++ b/src/include/cef_dialog_handler.h @@ -45,7 +45,7 @@ // Callback interface for asynchronous continuation of file dialog requests. /// /*--cef(source=library)--*/ -class CefFileDialogCallback : public virtual CefBase { +class CefFileDialogCallback : public virtual CefBaseRefCounted { public: /// // Continue the file selection. |selected_accept_filter| should be the 0-based @@ -72,7 +72,7 @@ class CefFileDialogCallback : public virtual CefBase { // will be called on the browser process UI thread. /// /*--cef(source=client)--*/ -class CefDialogHandler : public virtual CefBase { +class CefDialogHandler : public virtual CefBaseRefCounted { public: typedef cef_file_dialog_mode_t FileDialogMode; diff --git a/src/include/cef_display_handler.h b/src/include/cef_display_handler.h index 3f0646102..6147cc799 100644 --- a/src/include/cef_display_handler.h +++ b/src/include/cef_display_handler.h @@ -47,7 +47,7 @@ // The methods of this class will be called on the UI thread. /// /*--cef(source=client)--*/ -class CefDisplayHandler : public virtual CefBase { +class CefDisplayHandler : public virtual CefBaseRefCounted { public: /// // Called when a frame's address has changed. diff --git a/src/include/cef_dom.h b/src/include/cef_dom.h index 65933b758..f653a074f 100644 --- a/src/include/cef_dom.h +++ b/src/include/cef_dom.h @@ -49,7 +49,7 @@ class CefDOMNode; // be called on the render process main thread. /// /*--cef(source=client)--*/ -class CefDOMVisitor : public virtual CefBase { +class CefDOMVisitor : public virtual CefBaseRefCounted { public: /// // Method executed for visiting the DOM. The document object passed to this @@ -68,7 +68,7 @@ class CefDOMVisitor : public virtual CefBase { // be called on the render process main thread thread. /// /*--cef(source=library)--*/ -class CefDOMDocument : public virtual CefBase { +class CefDOMDocument : public virtual CefBaseRefCounted { public: typedef cef_dom_document_type_t Type; @@ -164,7 +164,7 @@ class CefDOMDocument : public virtual CefBase { // called on the render process main thread. /// /*--cef(source=library)--*/ -class CefDOMNode : public virtual CefBase { +class CefDOMNode : public virtual CefBaseRefCounted { public: typedef std::map AttributeMap; typedef cef_dom_node_type_t Type; diff --git a/src/include/cef_download_handler.h b/src/include/cef_download_handler.h index 4f58af485..b32c248e5 100644 --- a/src/include/cef_download_handler.h +++ b/src/include/cef_download_handler.h @@ -47,7 +47,7 @@ // Callback interface used to asynchronously continue a download. /// /*--cef(source=library)--*/ -class CefBeforeDownloadCallback : public virtual CefBase { +class CefBeforeDownloadCallback : public virtual CefBaseRefCounted { public: /// // Call to continue the download. Set |download_path| to the full file path @@ -64,7 +64,7 @@ class CefBeforeDownloadCallback : public virtual CefBase { // Callback interface used to asynchronously cancel a download. /// /*--cef(source=library)--*/ -class CefDownloadItemCallback : public virtual CefBase { +class CefDownloadItemCallback : public virtual CefBaseRefCounted { public: /// // Call to cancel the download. @@ -91,7 +91,7 @@ class CefDownloadItemCallback : public virtual CefBase { // on the browser process UI thread. /// /*--cef(source=client)--*/ -class CefDownloadHandler : public virtual CefBase { +class CefDownloadHandler : public virtual CefBaseRefCounted { public: /// // Called before a download begins. |suggested_name| is the suggested name for diff --git a/src/include/cef_download_item.h b/src/include/cef_download_item.h index 988ef6bde..b0ea797ff 100644 --- a/src/include/cef_download_item.h +++ b/src/include/cef_download_item.h @@ -44,7 +44,7 @@ // Class used to represent a download item. /// /*--cef(source=library)--*/ -class CefDownloadItem : public virtual CefBase { +class CefDownloadItem : public virtual CefBaseRefCounted { public: /// // Returns true if this object is valid. Do not call any other methods if this diff --git a/src/include/cef_drag_data.h b/src/include/cef_drag_data.h index 8b4602b1b..e3c9c2df9 100644 --- a/src/include/cef_drag_data.h +++ b/src/include/cef_drag_data.h @@ -48,7 +48,7 @@ // on any thread. /// /*--cef(source=library)--*/ -class CefDragData : public virtual CefBase { +class CefDragData : public virtual CefBaseRefCounted { public: /// // Create a new CefDragData object. diff --git a/src/include/cef_drag_handler.h b/src/include/cef_drag_handler.h index 3e26f9755..aee013668 100644 --- a/src/include/cef_drag_handler.h +++ b/src/include/cef_drag_handler.h @@ -47,7 +47,7 @@ // this class will be called on the UI thread. /// /*--cef(source=client)--*/ -class CefDragHandler : public virtual CefBase { +class CefDragHandler : public virtual CefBaseRefCounted { public: typedef cef_drag_operations_mask_t DragOperationsMask; diff --git a/src/include/cef_find_handler.h b/src/include/cef_find_handler.h index 410cf5fec..a9cac0a1e 100644 --- a/src/include/cef_find_handler.h +++ b/src/include/cef_find_handler.h @@ -46,7 +46,7 @@ // methods of this class will be called on the UI thread. /// /*--cef(source=client)--*/ -class CefFindHandler : public virtual CefBase { +class CefFindHandler : public virtual CefBaseRefCounted { public: /// // Called to report find results returned by CefBrowserHost::Find(). diff --git a/src/include/cef_focus_handler.h b/src/include/cef_focus_handler.h index 1d91c42ab..27352fa2b 100644 --- a/src/include/cef_focus_handler.h +++ b/src/include/cef_focus_handler.h @@ -48,7 +48,7 @@ // this class will be called on the UI thread. /// /*--cef(source=client)--*/ -class CefFocusHandler : public virtual CefBase { +class CefFocusHandler : public virtual CefBaseRefCounted { public: typedef cef_focus_source_t FocusSource; diff --git a/src/include/cef_frame.h b/src/include/cef_frame.h index 1ea172f1b..bcf680d63 100644 --- a/src/include/cef_frame.h +++ b/src/include/cef_frame.h @@ -54,7 +54,7 @@ class CefV8Context; // methods of this class may only be called on the main thread. /// /*--cef(source=library)--*/ -class CefFrame : public virtual CefBase { +class CefFrame : public virtual CefBaseRefCounted { public: /// // True if this object is currently attached to a valid frame. diff --git a/src/include/cef_geolocation.h b/src/include/cef_geolocation.h index 69c08779c..32005a430 100644 --- a/src/include/cef_geolocation.h +++ b/src/include/cef_geolocation.h @@ -45,7 +45,7 @@ // class will be called on the browser process UI thread. /// /*--cef(source=client)--*/ -class CefGetGeolocationCallback : public virtual CefBase { +class CefGetGeolocationCallback : public virtual CefBaseRefCounted { public: /// // Called with the 'best available' location information or, if the location diff --git a/src/include/cef_geolocation_handler.h b/src/include/cef_geolocation_handler.h index dda52834a..b2a722cea 100644 --- a/src/include/cef_geolocation_handler.h +++ b/src/include/cef_geolocation_handler.h @@ -46,7 +46,7 @@ // permission requests. /// /*--cef(source=library)--*/ -class CefGeolocationCallback : public virtual CefBase { +class CefGeolocationCallback : public virtual CefBaseRefCounted { public: /// // Call to allow or deny geolocation access. @@ -62,7 +62,7 @@ class CefGeolocationCallback : public virtual CefBase { // thread. /// /*--cef(source=client)--*/ -class CefGeolocationHandler : public virtual CefBase { +class CefGeolocationHandler : public virtual CefBaseRefCounted { public: /// // Called when a page requests permission to access geolocation information. diff --git a/src/include/cef_image.h b/src/include/cef_image.h index 170a23758..71f69ab61 100644 --- a/src/include/cef_image.h +++ b/src/include/cef_image.h @@ -50,7 +50,7 @@ // be called on the browser process UI thread. /// /*--cef(source=library)--*/ -class CefImage : public virtual CefBase { +class CefImage : public virtual CefBaseRefCounted { public: /// // Create a new CefImage. It will initially be empty. Use the Add*() methods diff --git a/src/include/cef_jsdialog_handler.h b/src/include/cef_jsdialog_handler.h index fecaa7f78..4596430cc 100644 --- a/src/include/cef_jsdialog_handler.h +++ b/src/include/cef_jsdialog_handler.h @@ -46,7 +46,7 @@ // requests. /// /*--cef(source=library)--*/ -class CefJSDialogCallback : public virtual CefBase { +class CefJSDialogCallback : public virtual CefBaseRefCounted { public: /// // Continue the JS dialog request. Set |success| to true if the OK button was @@ -63,7 +63,7 @@ class CefJSDialogCallback : public virtual CefBase { // methods of this class will be called on the UI thread. /// /*--cef(source=client)--*/ -class CefJSDialogHandler : public virtual CefBase { +class CefJSDialogHandler : public virtual CefBaseRefCounted { public: typedef cef_jsdialog_type_t JSDialogType; diff --git a/src/include/cef_keyboard_handler.h b/src/include/cef_keyboard_handler.h index 0346aa4ac..cd4c4d0ef 100644 --- a/src/include/cef_keyboard_handler.h +++ b/src/include/cef_keyboard_handler.h @@ -46,7 +46,7 @@ // methods of this class will be called on the UI thread. /// /*--cef(source=client)--*/ -class CefKeyboardHandler : public virtual CefBase { +class CefKeyboardHandler : public virtual CefBaseRefCounted { public: /// // Called before a keyboard event is sent to the renderer. |event| contains diff --git a/src/include/cef_life_span_handler.h b/src/include/cef_life_span_handler.h index 6967e3e8e..b1acc4d7c 100644 --- a/src/include/cef_life_span_handler.h +++ b/src/include/cef_life_span_handler.h @@ -49,7 +49,7 @@ class CefClient; // indicated. /// /*--cef(source=client)--*/ -class CefLifeSpanHandler : public virtual CefBase { +class CefLifeSpanHandler : public virtual CefBaseRefCounted { public: typedef cef_window_open_disposition_t WindowOpenDisposition; diff --git a/src/include/cef_load_handler.h b/src/include/cef_load_handler.h index 1494a844b..99696ed89 100644 --- a/src/include/cef_load_handler.h +++ b/src/include/cef_load_handler.h @@ -48,7 +48,7 @@ // render process main thread (TID_RENDERER). /// /*--cef(source=client)--*/ -class CefLoadHandler : public virtual CefBase { +class CefLoadHandler : public virtual CefBaseRefCounted { public: typedef cef_errorcode_t ErrorCode; typedef cef_transition_type_t TransitionType; diff --git a/src/include/cef_menu_model.h b/src/include/cef_menu_model.h index beb95fb75..b039119ac 100644 --- a/src/include/cef_menu_model.h +++ b/src/include/cef_menu_model.h @@ -48,7 +48,7 @@ // this class can only be accessed on the browser process the UI thread. /// /*--cef(source=library)--*/ -class CefMenuModel : public virtual CefBase { +class CefMenuModel : public virtual CefBaseRefCounted { public: typedef cef_menu_item_type_t MenuItemType; @@ -59,6 +59,12 @@ class CefMenuModel : public virtual CefBase { static CefRefPtr CreateMenuModel( CefRefPtr delegate); + /// + // Returns true if this menu is a submenu. + /// + /*--cef()--*/ + virtual bool IsSubMenu() =0; + /// // Clears the menu. Returns true on success. /// @@ -405,6 +411,85 @@ class CefMenuModel : public virtual CefBase { bool& shift_pressed, bool& ctrl_pressed, bool& alt_pressed) =0; + + /// + // Set the explicit color for |command_id| and |color_type| to |color|. + // Specify a |color| value of 0 to remove the explicit color. If no explicit + // color or default color is set for |color_type| then the system color will + // be used. Returns true on success. + /// + /*--cef()--*/ + virtual bool SetColor(int command_id, + cef_menu_color_type_t color_type, + cef_color_t color) =0; + + /// + // Set the explicit color for |command_id| and |index| to |color|. Specify a + // |color| value of 0 to remove the explicit color. Specify an |index| value + // of -1 to set the default color for items that do not have an explicit + // color set. If no explicit color or default color is set for |color_type| + // then the system color will be used. Returns true on success. + /// + /*--cef()--*/ + virtual bool SetColorAt(int index, + cef_menu_color_type_t color_type, + cef_color_t color) =0; + + /// + // Returns in |color| the color that was explicitly set for |command_id| and + // |color_type|. If a color was not set then 0 will be returned in |color|. + // Returns true on success. + /// + /*--cef()--*/ + virtual bool GetColor(int command_id, + cef_menu_color_type_t color_type, + cef_color_t& color) =0; + + /// + // Returns in |color| the color that was explicitly set for |command_id| and + // |color_type|. Specify an |index| value of -1 to return the default color + // in |color|. If a color was not set then 0 will be returned in |color|. + // Returns true on success. + /// + /*--cef()--*/ + virtual bool GetColorAt(int index, + cef_menu_color_type_t color_type, + cef_color_t& color) =0; + + /// + // Sets the font list for the specified |command_id|. If |font_list| is empty + // the system font will be used. Returns true on success. The format is + // ",[STYLES] ", where: + // - FONT_FAMILY_LIST is a comma-separated list of font family names, + // - STYLES is an optional space-separated list of style names (case-sensitive + // "Bold" and "Italic" are supported), and + // - SIZE is an integer font size in pixels with the suffix "px". + // + // Here are examples of valid font description strings: + // - "Arial, Helvetica, Bold Italic 14px" + // - "Arial, 14px" + /// + /*--cef(optional_param=font_list)--*/ + virtual bool SetFontList(int command_id, + const CefString& font_list) =0; + + /// + // Sets the font list for the specified |index|. Specify an |index| value of + // -1 to set the default font. If |font_list| is empty the system font will + // be used. Returns true on success. The format is + // ",[STYLES] ", where: + // - FONT_FAMILY_LIST is a comma-separated list of font family names, + // - STYLES is an optional space-separated list of style names (case-sensitive + // "Bold" and "Italic" are supported), and + // - SIZE is an integer font size in pixels with the suffix "px". + // + // Here are examples of valid font description strings: + // - "Arial, Helvetica, Bold Italic 14px" + // - "Arial, 14px" + /// + /*--cef(optional_param=font_list)--*/ + virtual bool SetFontListAt(int index, + const CefString& font_list) =0; }; #endif // CEF_INCLUDE_CEF_MENU_MODEL_H_ diff --git a/src/include/cef_menu_model_delegate.h b/src/include/cef_menu_model_delegate.h index 84ebae18e..d05b580a6 100644 --- a/src/include/cef_menu_model_delegate.h +++ b/src/include/cef_menu_model_delegate.h @@ -48,7 +48,7 @@ class CefMenuModel; // indicated. /// /*--cef(source=client)--*/ -class CefMenuModelDelegate : public virtual CefBase { +class CefMenuModelDelegate : public virtual CefBaseRefCounted { public: /// // Perform the action associated with the specified |command_id| and @@ -59,6 +59,30 @@ class CefMenuModelDelegate : public virtual CefBase { int command_id, cef_event_flags_t event_flags) =0; + /// + // Called when the user moves the mouse outside the menu and over the owning + // window. + /// + /*--cef()--*/ + virtual void MouseOutsideMenu(CefRefPtr menu_model, + const CefPoint& screen_point) {} + + /// + // Called on unhandled open submenu keyboard commands. |is_rtl| will be true + // if the menu is displaying a right-to-left language. + /// + /*--cef()--*/ + virtual void UnhandledOpenSubmenu(CefRefPtr menu_model, + bool is_rtl) {} + + /// + // Called on unhandled close submenu keyboard commands. |is_rtl| will be true + // if the menu is displaying a right-to-left language. + /// + /*--cef()--*/ + virtual void UnhandledCloseSubmenu(CefRefPtr menu_model, + bool is_rtl) {} + /// // The menu is about to show. /// diff --git a/src/include/cef_navigation_entry.h b/src/include/cef_navigation_entry.h index 6dc3a4c57..9c86a338a 100644 --- a/src/include/cef_navigation_entry.h +++ b/src/include/cef_navigation_entry.h @@ -45,7 +45,7 @@ // Class used to represent an entry in navigation history. /// /*--cef(source=library)--*/ -class CefNavigationEntry : public virtual CefBase { +class CefNavigationEntry : public virtual CefBaseRefCounted { public: typedef cef_transition_type_t TransitionType; diff --git a/src/include/cef_print_handler.h b/src/include/cef_print_handler.h index cac16244b..50519c4fe 100644 --- a/src/include/cef_print_handler.h +++ b/src/include/cef_print_handler.h @@ -46,7 +46,7 @@ // Callback interface for asynchronous continuation of print dialog requests. /// /*--cef(source=library)--*/ -class CefPrintDialogCallback : public virtual CefBase { +class CefPrintDialogCallback : public virtual CefBaseRefCounted { public: /// // Continue printing with the specified |settings|. @@ -65,7 +65,7 @@ class CefPrintDialogCallback : public virtual CefBase { // Callback interface for asynchronous continuation of print job requests. /// /*--cef(source=library)--*/ -class CefPrintJobCallback : public virtual CefBase { +class CefPrintJobCallback : public virtual CefBaseRefCounted { public: /// // Indicate completion of the print job. @@ -80,7 +80,7 @@ class CefPrintJobCallback : public virtual CefBase { // class will be called on the browser process UI thread. /// /*--cef(source=client)--*/ -class CefPrintHandler : public virtual CefBase { +class CefPrintHandler : public virtual CefBaseRefCounted { public: /// // Called when printing has started for the specified |browser|. This method diff --git a/src/include/cef_print_settings.h b/src/include/cef_print_settings.h index 709d36b39..0fe2a0ba0 100644 --- a/src/include/cef_print_settings.h +++ b/src/include/cef_print_settings.h @@ -46,7 +46,7 @@ // Class representing print settings. /// /*--cef(source=library)--*/ -class CefPrintSettings : public virtual CefBase { +class CefPrintSettings : public virtual CefBaseRefCounted { public: typedef cef_color_model_t ColorModel; typedef cef_duplex_mode_t DuplexMode; diff --git a/src/include/cef_process_message.h b/src/include/cef_process_message.h index 1e27bd681..a6b6a18aa 100644 --- a/src/include/cef_process_message.h +++ b/src/include/cef_process_message.h @@ -47,7 +47,7 @@ typedef cef_process_id_t CefProcessId; // Class representing a message. Can be used on any process and thread. /// /*--cef(source=library)--*/ -class CefProcessMessage : public virtual CefBase { +class CefProcessMessage : public virtual CefBaseRefCounted { public: /// // Create a new CefProcessMessage object with the specified name. diff --git a/src/include/cef_render_handler.h b/src/include/cef_render_handler.h index 0f857b07d..9c253535e 100644 --- a/src/include/cef_render_handler.h +++ b/src/include/cef_render_handler.h @@ -49,7 +49,7 @@ // The methods of this class will be called on the UI thread. /// /*--cef(source=client)--*/ -class CefRenderHandler : public virtual CefBase { +class CefRenderHandler : public virtual CefBaseRefCounted { public: typedef cef_cursor_type_t CursorType; typedef cef_drag_operations_mask_t DragOperation; diff --git a/src/include/cef_render_process_handler.h b/src/include/cef_render_process_handler.h index 98ab391bc..ecf6fc59e 100644 --- a/src/include/cef_render_process_handler.h +++ b/src/include/cef_render_process_handler.h @@ -53,7 +53,7 @@ // otherwise indicated. /// /*--cef(source=client)--*/ -class CefRenderProcessHandler : public virtual CefBase { +class CefRenderProcessHandler : public virtual CefBaseRefCounted { public: typedef cef_navigation_type_t NavigationType; diff --git a/src/include/cef_request.h b/src/include/cef_request.h index a4626aa02..8d48f41d9 100644 --- a/src/include/cef_request.h +++ b/src/include/cef_request.h @@ -50,7 +50,7 @@ class CefPostDataElement; // called on any thread. /// /*--cef(source=library,no_debugct_check)--*/ -class CefRequest : public virtual CefBase { +class CefRequest : public virtual CefBaseRefCounted { public: typedef std::multimap HeaderMap; typedef cef_referrer_policy_t ReferrerPolicy; @@ -207,7 +207,7 @@ class CefRequest : public virtual CefBase { // class may be called on any thread. /// /*--cef(source=library,no_debugct_check)--*/ -class CefPostData : public virtual CefBase { +class CefPostData : public virtual CefBaseRefCounted { public: typedef std::vector > ElementVector; @@ -270,7 +270,7 @@ class CefPostData : public virtual CefBase { // methods of this class may be called on any thread. /// /*--cef(source=library,no_debugct_check)--*/ -class CefPostDataElement : public virtual CefBase { +class CefPostDataElement : public virtual CefBaseRefCounted { public: /// // Post data elements may represent either bytes or files. diff --git a/src/include/cef_request_context.h b/src/include/cef_request_context.h index 8892d5f7f..3f6d8fd4c 100644 --- a/src/include/cef_request_context.h +++ b/src/include/cef_request_context.h @@ -52,7 +52,7 @@ class CefSchemeHandlerFactory; // Callback interface for CefRequestContext::ResolveHost. /// /*--cef(source=client)--*/ -class CefResolveCallback : public virtual CefBase { +class CefResolveCallback : public virtual CefBaseRefCounted { public: /// // Called after the ResolveHost request has completed. |result| will be the @@ -83,7 +83,7 @@ class CefResolveCallback : public virtual CefBase { // all other request context objects will be ignored. /// /*--cef(source=library,no_debugct_check)--*/ -class CefRequestContext : public virtual CefBase { +class CefRequestContext : public virtual CefBaseRefCounted { public: /// // Returns the global context object. diff --git a/src/include/cef_request_context_handler.h b/src/include/cef_request_context_handler.h index 6996d9ede..26864e88b 100644 --- a/src/include/cef_request_context_handler.h +++ b/src/include/cef_request_context_handler.h @@ -48,7 +48,7 @@ // been destroyed. /// /*--cef(source=client,no_debugct_check)--*/ -class CefRequestContextHandler : public virtual CefBase { +class CefRequestContextHandler : public virtual CefBaseRefCounted { public: typedef cef_plugin_policy_t PluginPolicy; diff --git a/src/include/cef_request_handler.h b/src/include/cef_request_handler.h index 69334397a..c44a3dfaa 100644 --- a/src/include/cef_request_handler.h +++ b/src/include/cef_request_handler.h @@ -55,7 +55,7 @@ // Callback interface used for asynchronous continuation of url requests. /// /*--cef(source=library)--*/ -class CefRequestCallback : public virtual CefBase { +class CefRequestCallback : public virtual CefBaseRefCounted { public: /// // Continue the url request. If |allow| is true the request will be continued. @@ -76,7 +76,7 @@ class CefRequestCallback : public virtual CefBase { // Callback interface used to select a client certificate for authentication. /// /*--cef(source=library)--*/ -class CefSelectClientCertificateCallback : public virtual CefBase { +class CefSelectClientCertificateCallback : public virtual CefBaseRefCounted { public: /// // Chooses the specified certificate for client certificate authentication. @@ -92,7 +92,7 @@ class CefSelectClientCertificateCallback : public virtual CefBase { // methods of this class will be called on the thread indicated. /// /*--cef(source=client)--*/ -class CefRequestHandler : public virtual CefBase { +class CefRequestHandler : public virtual CefBaseRefCounted { public: typedef cef_return_value_t ReturnValue; typedef cef_termination_status_t TerminationStatus; diff --git a/src/include/cef_resource_bundle.h b/src/include/cef_resource_bundle.h index 3b064ffec..3fda8998e 100644 --- a/src/include/cef_resource_bundle.h +++ b/src/include/cef_resource_bundle.h @@ -48,7 +48,7 @@ // on any thread unless otherwise indicated. /// /*--cef(source=library,no_debugct_check)--*/ -class CefResourceBundle : public virtual CefBase { +class CefResourceBundle : public virtual CefBaseRefCounted { public: typedef cef_scale_factor_t ScaleFactor; diff --git a/src/include/cef_resource_bundle_handler.h b/src/include/cef_resource_bundle_handler.h index afc46da74..932ef9f5b 100644 --- a/src/include/cef_resource_bundle_handler.h +++ b/src/include/cef_resource_bundle_handler.h @@ -46,7 +46,7 @@ // this class may be called on multiple threads. /// /*--cef(source=client)--*/ -class CefResourceBundleHandler : public virtual CefBase { +class CefResourceBundleHandler : public virtual CefBaseRefCounted { public: typedef cef_scale_factor_t ScaleFactor; diff --git a/src/include/cef_resource_handler.h b/src/include/cef_resource_handler.h index 19913c756..abe7196dc 100644 --- a/src/include/cef_resource_handler.h +++ b/src/include/cef_resource_handler.h @@ -50,7 +50,7 @@ // this class will always be called on the IO thread. /// /*--cef(source=client)--*/ -class CefResourceHandler : public virtual CefBase { +class CefResourceHandler : public virtual CefBaseRefCounted { public: /// // Begin processing the request. To handle the request return true and call diff --git a/src/include/cef_response.h b/src/include/cef_response.h index 6fcb4e236..cd7356efd 100644 --- a/src/include/cef_response.h +++ b/src/include/cef_response.h @@ -46,7 +46,7 @@ // called on any thread. /// /*--cef(source=library,no_debugct_check)--*/ -class CefResponse : public virtual CefBase { +class CefResponse : public virtual CefBaseRefCounted { public: typedef std::multimap HeaderMap; diff --git a/src/include/cef_response_filter.h b/src/include/cef_response_filter.h index 55e667770..58c978ea1 100644 --- a/src/include/cef_response_filter.h +++ b/src/include/cef_response_filter.h @@ -45,7 +45,7 @@ // this class will be called on the browser process IO thread. /// /*--cef(source=client)--*/ -class CefResponseFilter : public virtual CefBase { +class CefResponseFilter : public virtual CefBaseRefCounted { public: typedef cef_response_filter_status_t FilterStatus; diff --git a/src/include/cef_scheme.h b/src/include/cef_scheme.h index a966a9a79..d4b1ac0c5 100644 --- a/src/include/cef_scheme.h +++ b/src/include/cef_scheme.h @@ -82,7 +82,7 @@ bool CefClearSchemeHandlerFactories(); // Class that manages custom scheme registrations. /// /*--cef(source=library)--*/ -class CefSchemeRegistrar : public virtual CefBase { +class CefSchemeRegistrar : public CefBaseScoped { public: /// // Register a custom scheme. This method should not be called for the built-in @@ -111,9 +111,9 @@ class CefSchemeRegistrar : public virtual CefBase { // as-is. For example, "scheme:///some%20text" will remain the same. // Non-standard scheme URLs cannot be used as a target for form submission. // - // If |is_local| is true the scheme will be treated as local (i.e., with the - // same security rules as those applied to "file" URLs). Normal pages cannot - // link to or access local URLs. Also, by default, local URLs can only perform + // If |is_local| is true the scheme will be treated with the same security + // rules as those applied to "file" URLs. Normal pages cannot link to or + // access local URLs. Also, by default, local URLs can only perform // XMLHttpRequest calls to the same URL (origin + path) that originated the // request. To allow XMLHttpRequest calls from a local URL to other URLs with // the same origin set the CefSettings.file_access_from_file_urls_allowed @@ -121,10 +121,19 @@ class CefSchemeRegistrar : public virtual CefBase { // origins set the CefSettings.universal_access_from_file_urls_allowed value // to true. // - // If |is_display_isolated| is true the scheme will be treated as display- - // isolated. This means that pages cannot display these URLs unless they are - // from the same scheme. For example, pages in another origin cannot create - // iframes or hyperlinks to URLs with this scheme. + // If |is_display_isolated| is true the scheme can only be displayed from + // other content hosted with the same scheme. For example, pages in other + // origins cannot create iframes or hyperlinks to URLs with the scheme. For + // schemes that must be accessible from other schemes set this value to false, + // set |is_cors_enabled| to true, and use CORS "Access-Control-Allow-Origin" + // headers to further restrict access. + // + // If |is_secure| is true the scheme will be treated with the same security + // rules as those applied to "https" URLs. For example, loading this scheme + // from other secure schemes will not trigger mixed content warnings. + // + // If |is_cors_enabled| is true the scheme that can be sent CORS requests. + // This value should be true in most cases where |is_standard| is true. // // This function may be called on any thread. It should only be called once // per unique |scheme_name| value. If |scheme_name| is already registered or @@ -134,7 +143,9 @@ class CefSchemeRegistrar : public virtual CefBase { virtual bool AddCustomScheme(const CefString& scheme_name, bool is_standard, bool is_local, - bool is_display_isolated) =0; + bool is_display_isolated, + bool is_secure, + bool is_cors_enabled) =0; }; @@ -143,7 +154,7 @@ class CefSchemeRegistrar : public virtual CefBase { // The methods of this class will always be called on the IO thread. /// /*--cef(source=client)--*/ -class CefSchemeHandlerFactory : public virtual CefBase { +class CefSchemeHandlerFactory : public virtual CefBaseRefCounted { public: /// // Return a new resource handler instance to handle the request or an empty diff --git a/src/include/cef_ssl_info.h b/src/include/cef_ssl_info.h index 732171889..db075cabc 100644 --- a/src/include/cef_ssl_info.h +++ b/src/include/cef_ssl_info.h @@ -47,7 +47,7 @@ // Class representing SSL information. /// /*--cef(source=library)--*/ -class CefSSLInfo : public virtual CefBase { +class CefSSLInfo : public virtual CefBaseRefCounted { public: /// // Returns a bitmask containing any and all problems verifying the server diff --git a/src/include/cef_ssl_status.h b/src/include/cef_ssl_status.h index 614a607d5..3a5f39501 100644 --- a/src/include/cef_ssl_status.h +++ b/src/include/cef_ssl_status.h @@ -46,7 +46,7 @@ // Class representing the SSL information for a navigation entry. /// /*--cef(source=library)--*/ -class CefSSLStatus : public virtual CefBase { +class CefSSLStatus : public virtual CefBaseRefCounted { public: /// // Returns true if the status is related to a secure SSL/TLS connection. diff --git a/src/include/cef_stream.h b/src/include/cef_stream.h index 3d0633c25..81b0b9164 100644 --- a/src/include/cef_stream.h +++ b/src/include/cef_stream.h @@ -44,7 +44,7 @@ // methods of this class may be called on any thread. /// /*--cef(source=client)--*/ -class CefReadHandler : public virtual CefBase { +class CefReadHandler : public virtual CefBaseRefCounted { public: /// // Read raw binary data. @@ -87,7 +87,7 @@ class CefReadHandler : public virtual CefBase { // called on any thread. /// /*--cef(source=library)--*/ -class CefStreamReader : public virtual CefBase { +class CefStreamReader : public virtual CefBaseRefCounted { public: /// // Create a new CefStreamReader object from a file. @@ -147,7 +147,7 @@ class CefStreamReader : public virtual CefBase { // methods of this class may be called on any thread. /// /*--cef(source=client)--*/ -class CefWriteHandler : public virtual CefBase { +class CefWriteHandler : public virtual CefBaseRefCounted { public: /// // Write raw binary data. @@ -190,7 +190,7 @@ class CefWriteHandler : public virtual CefBase { // on any thread. /// /*--cef(source=library)--*/ -class CefStreamWriter : public virtual CefBase { +class CefStreamWriter : public virtual CefBaseRefCounted { public: /// // Create a new CefStreamWriter object for a file. diff --git a/src/include/cef_string_visitor.h b/src/include/cef_string_visitor.h index 549371473..36a97ba35 100644 --- a/src/include/cef_string_visitor.h +++ b/src/include/cef_string_visitor.h @@ -43,7 +43,7 @@ // Implement this interface to receive string values asynchronously. /// /*--cef(source=client)--*/ -class CefStringVisitor : public virtual CefBase { +class CefStringVisitor : public virtual CefBaseRefCounted { public: /// // Method that will be executed. diff --git a/src/include/cef_task.h b/src/include/cef_task.h index 0ecaa7526..ea3b2d96b 100644 --- a/src/include/cef_task.h +++ b/src/include/cef_task.h @@ -50,7 +50,7 @@ typedef cef_thread_id_t CefThreadId; // task object destructor. /// /*--cef(source=client)--*/ -class CefTask : public virtual CefBase { +class CefTask : public virtual CefBaseRefCounted { public: /// // Method that will be executed on the target thread. @@ -69,7 +69,7 @@ class CefTask : public virtual CefBase { // other CEF threads as appropriate (for example, V8 WebWorker threads). /// /*--cef(source=library)--*/ -class CefTaskRunner : public virtual CefBase { +class CefTaskRunner : public virtual CefBaseRefCounted { public: /// // Returns the task runner for the current thread. Only CEF threads will have diff --git a/src/include/cef_thread.h b/src/include/cef_thread.h index a0e78c493..dfe652d2e 100644 --- a/src/include/cef_thread.h +++ b/src/include/cef_thread.h @@ -53,7 +53,7 @@ // see cef_task.h for details. /// /*--cef(source=library)--*/ -class CefThread : public CefBase { +class CefThread : public CefBaseRefCounted { public: /// // Create and start a new thread. This method does not block waiting for the diff --git a/src/include/cef_trace.h b/src/include/cef_trace.h index 5b977c6e5..fa7f62781 100644 --- a/src/include/cef_trace.h +++ b/src/include/cef_trace.h @@ -49,7 +49,7 @@ // The methods of this class will be called on the browser process UI thread. /// /*--cef(source=client)--*/ -class CefEndTracingCallback : public virtual CefBase { +class CefEndTracingCallback : public virtual CefBaseRefCounted { public: /// // Called after all processes have sent their trace data. |tracing_file| is diff --git a/src/include/cef_urlrequest.h b/src/include/cef_urlrequest.h index 5b58b6349..23bc821ec 100644 --- a/src/include/cef_urlrequest.h +++ b/src/include/cef_urlrequest.h @@ -54,7 +54,7 @@ class CefURLRequestClient; // on the same thread that created it. /// /*--cef(source=library)--*/ -class CefURLRequest : public virtual CefBase { +class CefURLRequest : public virtual CefBaseRefCounted { public: typedef cef_urlrequest_status_t Status; typedef cef_errorcode_t ErrorCode; @@ -127,7 +127,7 @@ class CefURLRequest : public virtual CefBase { // request unless otherwise documented. /// /*--cef(source=client)--*/ -class CefURLRequestClient : public virtual CefBase { +class CefURLRequestClient : public virtual CefBaseRefCounted { public: /// // Notifies the client that the request has completed. Use the diff --git a/src/include/cef_v8.h b/src/include/cef_v8.h index f33090a46..2ec4feb8e 100644 --- a/src/include/cef_v8.h +++ b/src/include/cef_v8.h @@ -124,7 +124,7 @@ bool CefRegisterExtension(const CefString& extension_name, // the CefV8Context::GetTaskRunner() method. /// /*--cef(source=library)--*/ -class CefV8Context : public virtual CefBase { +class CefV8Context : public virtual CefBaseRefCounted { public: /// // Returns the current (top) context object in the V8 context stack. @@ -229,7 +229,7 @@ typedef std::vector > CefV8ValueList; // of this class will be called on the thread associated with the V8 function. /// /*--cef(source=client)--*/ -class CefV8Handler : public virtual CefBase { +class CefV8Handler : public virtual CefBaseRefCounted { public: /// // Handle execution of the function identified by |name|. |object| is the @@ -252,7 +252,7 @@ class CefV8Handler : public virtual CefBase { // of this class will be called on the thread associated with the V8 accessor. /// /*--cef(source=client)--*/ -class CefV8Accessor : public virtual CefBase { +class CefV8Accessor : public virtual CefBaseRefCounted { public: /// // Handle retrieval the accessor value identified by |name|. |object| is the @@ -290,7 +290,7 @@ class CefV8Accessor : public virtual CefBase { // by integer. /// /*--cef(source=client)--*/ -class CefV8Interceptor : public virtual CefBase { +class CefV8Interceptor : public virtual CefBaseRefCounted { public: /// // Handle retrieval of the interceptor value identified by |name|. |object| is @@ -354,7 +354,7 @@ class CefV8Interceptor : public virtual CefBase { // any render process thread. /// /*--cef(source=library)--*/ -class CefV8Exception : public virtual CefBase { +class CefV8Exception : public virtual CefBaseRefCounted { public: /// // Returns the exception message. @@ -419,7 +419,7 @@ class CefV8Exception : public virtual CefBase { // the CefV8Context::GetTaskRunner() method. /// /*--cef(source=library)--*/ -class CefV8Value : public virtual CefBase { +class CefV8Value : public virtual CefBaseRefCounted { public: typedef cef_v8_accesscontrol_t AccessControl; typedef cef_v8_propertyattribute_t PropertyAttribute; @@ -759,13 +759,13 @@ class CefV8Value : public virtual CefBase { // on user created objects. /// /*--cef(optional_param=user_data)--*/ - virtual bool SetUserData(CefRefPtr user_data) =0; + virtual bool SetUserData(CefRefPtr user_data) =0; /// // Returns the user data, if any, assigned to this object. /// /*--cef()--*/ - virtual CefRefPtr GetUserData() =0; + virtual CefRefPtr GetUserData() =0; /// // Returns the amount of externally allocated memory registered for the @@ -850,7 +850,7 @@ class CefV8Value : public virtual CefBase { // retrieved via the CefV8Context::GetTaskRunner() method. /// /*--cef(source=library)--*/ -class CefV8StackTrace : public virtual CefBase { +class CefV8StackTrace : public virtual CefBaseRefCounted { public: /// // Returns the stack trace for the currently active context. |frame_limit| is @@ -888,7 +888,7 @@ class CefV8StackTrace : public virtual CefBase { // retrieved via the CefV8Context::GetTaskRunner() method. /// /*--cef(source=library)--*/ -class CefV8StackFrame : public virtual CefBase { +class CefV8StackFrame : public virtual CefBaseRefCounted { public: /// // Returns true if the underlying handle is valid and it can be accessed on diff --git a/src/include/cef_values.h b/src/include/cef_values.h index 86fa40ef6..6bbd1e27d 100644 --- a/src/include/cef_values.h +++ b/src/include/cef_values.h @@ -53,7 +53,7 @@ typedef cef_value_type_t CefValueType; // process and thread. /// /*--cef(source=library)--*/ -class CefValue : public virtual CefBase { +class CefValue : public virtual CefBaseRefCounted { public: /// // Creates a new object. @@ -234,7 +234,7 @@ class CefValue : public virtual CefBase { // Class representing a binary value. Can be used on any process and thread. /// /*--cef(source=library)--*/ -class CefBinaryValue : public virtual CefBase { +class CefBinaryValue : public virtual CefBaseRefCounted { public: /// // Creates a new object that is not owned by any other object. The specified @@ -300,7 +300,7 @@ class CefBinaryValue : public virtual CefBase { // Class representing a dictionary value. Can be used on any process and thread. /// /*--cef(source=library)--*/ -class CefDictionaryValue : public virtual CefBase { +class CefDictionaryValue : public virtual CefBaseRefCounted { public: typedef std::vector KeyList; @@ -533,7 +533,7 @@ class CefDictionaryValue : public virtual CefBase { // Class representing a list value. Can be used on any process and thread. /// /*--cef(source=library)--*/ -class CefListValue : public virtual CefBase { +class CefListValue : public virtual CefBaseRefCounted { public: /// // Creates a new object that is not owned by any other object. diff --git a/src/include/cef_waitable_event.h b/src/include/cef_waitable_event.h index 4a4e9950c..070ca6813 100644 --- a/src/include/cef_waitable_event.h +++ b/src/include/cef_waitable_event.h @@ -52,7 +52,7 @@ // process UI or IO threads. /// /*--cef(source=library)--*/ -class CefWaitableEvent : public CefBase { +class CefWaitableEvent : public CefBaseRefCounted { public: /// // Create a new waitable event. If |automatic_reset| is true then the event diff --git a/src/include/cef_web_plugin.h b/src/include/cef_web_plugin.h index 731be7b94..3eea54130 100644 --- a/src/include/cef_web_plugin.h +++ b/src/include/cef_web_plugin.h @@ -45,7 +45,7 @@ class CefBrowser; // Information about a specific web plugin. /// /*--cef(source=library)--*/ -class CefWebPluginInfo : public virtual CefBase { +class CefWebPluginInfo : public virtual CefBaseRefCounted { public: /// // Returns the plugin name (i.e. Flash). @@ -77,7 +77,7 @@ class CefWebPluginInfo : public virtual CefBase { // this class will be called on the browser process UI thread. /// /*--cef(source=client)--*/ -class CefWebPluginInfoVisitor : public virtual CefBase { +class CefWebPluginInfoVisitor : public virtual CefBaseRefCounted { public: /// // Method that will be called once for each plugin. |count| is the 0-based @@ -124,7 +124,7 @@ void CefRegisterWebPluginCrash(const CefString& path); // of this class will be called on the browser process IO thread. /// /*--cef(source=client)--*/ -class CefWebPluginUnstableCallback : public virtual CefBase { +class CefWebPluginUnstableCallback : public virtual CefBaseRefCounted { public: /// // Method that will be called for the requested plugin. |unstable| will be @@ -150,7 +150,7 @@ void CefIsWebPluginUnstable(const CefString& path, // UI thread. /// /*--cef(source=client)--*/ -class CefRegisterCdmCallback : public virtual CefBase { +class CefRegisterCdmCallback : public virtual CefBaseRefCounted { public: /// // Method that will be called when CDM registration is complete. |result| diff --git a/src/include/cef_x509_certificate.h b/src/include/cef_x509_certificate.h index f036ab5ed..c784ce1b0 100644 --- a/src/include/cef_x509_certificate.h +++ b/src/include/cef_x509_certificate.h @@ -47,7 +47,7 @@ // Class representing the issuer or subject field of an X.509 certificate. /// /*--cef(source=library)--*/ -class CefX509CertPrincipal : public virtual CefBase { +class CefX509CertPrincipal : public virtual CefBaseRefCounted { public: /// // Returns a name that can be used to represent the issuer. It tries in this @@ -110,7 +110,7 @@ class CefX509CertPrincipal : public virtual CefBase { // Class representing a X.509 certificate. /// /*--cef(source=library)--*/ -class CefX509Certificate : public virtual CefBase { +class CefX509Certificate : public virtual CefBaseRefCounted { public: typedef std::vector > IssuerChainBinaryList; diff --git a/src/include/cef_xml_reader.h b/src/include/cef_xml_reader.h index 86be8bac7..ab5244e34 100644 --- a/src/include/cef_xml_reader.h +++ b/src/include/cef_xml_reader.h @@ -47,7 +47,7 @@ // the object. /// /*--cef(source=library)--*/ -class CefXmlReader : public virtual CefBase { +class CefXmlReader : public virtual CefBaseRefCounted { public: typedef cef_xml_encoding_type_t EncodingType; typedef cef_xml_node_type_t NodeType; diff --git a/src/include/cef_zip_reader.h b/src/include/cef_zip_reader.h index 5d8788e94..80640087f 100644 --- a/src/include/cef_zip_reader.h +++ b/src/include/cef_zip_reader.h @@ -46,7 +46,7 @@ // the object. /// /*--cef(source=library)--*/ -class CefZipReader : public virtual CefBase { +class CefZipReader : public virtual CefBaseRefCounted { public: /// // Create a new CefZipReader object. The returned object's methods can only diff --git a/src/include/internal/cef_ptr.h b/src/include/internal/cef_ptr.h index e38543911..25ce74557 100644 --- a/src/include/internal/cef_ptr.h +++ b/src/include/internal/cef_ptr.h @@ -32,8 +32,15 @@ #define CEF_INCLUDE_INTERNAL_CEF_PTR_H_ #pragma once +#include "include/base/cef_build.h" #include "include/base/cef_ref_counted.h" +#if defined(USING_CHROMIUM_INCLUDES) +#include // For std::unique_ptr. +#else +#include "include/base/cef_scoped_ptr.h" +#endif + /// // Smart pointer implementation that is an alias of scoped_refptr from // include/base/cef_ref_counted.h. @@ -43,7 +50,7 @@ // avoid common memory leaks caused by forgetting to Release an object // reference. Sample usage: //
      -//   class MyFoo : public CefBase {
      +//   class MyFoo : public CefBaseRefCounted {
       //    ...
       //   };
       //
      @@ -143,19 +150,83 @@
       // 
      //

      /// +#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 ab21fe84c..062065709 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 01ef7d1ae..b275079db 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 0c125c965..da41f8d32 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 c9398dad9..29d1da262 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 2ae068d96..db622d4d1 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 2feda9a63..db3db7d62 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 99bd126e8..ec33d9be7 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 d9da06029..e3a84561d 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 d820a2753..5f1fcf4ef 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 4ae8c4f3a..60f803c47 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 b6f321e01..78422fecd 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 70fd176c5..523b05282 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 b6ec638ec..a89ab63a4 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 19deae72a..a50e1fc41 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 559cdd818..bf593d0ab 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 8828c6566..d9b559b6f 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 2a6fcfe6f..23510ddcb 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 7ad10bda8..5de0960fc 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 219/557] 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 7b3516a2c..fe591eeda 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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

      D@1|QmjDw zbsYnMT09x{osChf4cCTY^fczbJQAG=p{#ul3 zS?vsl7|?oE#ZUV!MVGizkE*RdOlZKK)?&)JYp6NobDDDY|&E%5AO7!iu-VRIoF)nv~0mz{~+g4hEC<3P!e^Mty4 z_5%dcE0R%&u&a>(Sq_FRef|JuCq+lx2S#S?u7@f3BqN{6n!U)LMmg5Gbj$-ZlmauB z=*US~EVE^hx$)*`sj%BMGaPbLhchC+)}z|!4Hds-P~Gk9g=AtjZic2xt~%Xa^AJ2b z4$PRMg)@Y@)^J7Ak&8QSu9CL1X(|^QCg5Gp+47ZM>ix`?EGFfotZfEk@T{gW6VkM= z>a^eBcJPe_F)tlbGsV)YOiGRH>Kl zTEcp!RbK{ zKC}UNIxMV%;QcZ{V_`u@Api&{gBA<0cv$?OK Date: Thu, 20 Apr 2017 15:27:48 +0200 Subject: [PATCH 220/557] Rename qt4.py to qt.py, as it now supports Qt 5 as well (#325). Update docs and tools. --- examples/Examples-README.md | 5 +++-- examples/{qt4.py => qt.py} | 18 +++++++++--------- tools/run_examples.py | 22 +++++++++++++++------- 3 files changed, 27 insertions(+), 18 deletions(-) rename examples/{qt4.py => qt.py} (96%) diff --git a/examples/Examples-README.md b/examples/Examples-README.md index 7be26d960..9b0ad482a 100644 --- a/examples/Examples-README.md +++ b/examples/Examples-README.md @@ -30,8 +30,9 @@ maintained: library (GTK 2) - [gtk3.py](gtk3.py): example for [PyGObject/PyGI](https://wiki.gnome.org/Projects/PyGObject) library (GTK 3). Currently broken on Linux/Mac, see top comments in sources. -- [qt4.py](qt4.py): example for [PyQt4](https://wiki.python.org/moin/PyQt4) - and [PySide](https://wiki.qt.io/PySide) libraries (Qt 4) +- [qt.py](qt.py): example for [PyQt4](https://wiki.python.org/moin/PyQt4), + [PyQt5](https://pypi.python.org/pypi/PyQt5) + and [PySide](https://wiki.qt.io/PySide) libraries - [tkinter_.py](tkinter_.py): example for [Tkinter](https://wiki.python.org/moin/TkInter). Currently broken on Mac. - [wxpython.py](wxpython.py): example for [wxPython](https://wxpython.org/) diff --git a/examples/qt4.py b/examples/qt.py similarity index 96% rename from examples/qt4.py rename to examples/qt.py index fe591eeda..0a551b246 100644 --- a/examples/qt4.py +++ b/examples/qt.py @@ -43,9 +43,9 @@ from PySide.QtCore import * else: print("USAGE:") - print(" qt4.py pyqt4") - print(" qt4.py pyqt5") - print(" qt4.py pyside") + print(" qt.py pyqt4") + print(" qt.py pyqt5") + print(" qt.py pyside") sys.exit(1) # Fix for PyCharm hints warnings when using static methods @@ -83,14 +83,14 @@ def main(): def check_versions(): - print("[qt4.py] CEF Python {ver}".format(ver=cef.__version__)) - print("[qt4.py] Python {ver} {arch}".format( + print("[qt.py] CEF Python {ver}".format(ver=cef.__version__)) + print("[qt.py] Python {ver} {arch}".format( ver=platform.python_version(), arch=platform.architecture()[0])) if PYQT4 or PYQT5: - print("[qt4.py] PyQt {v1} (qt {v2})".format( + print("[qt.py] PyQt {v1} (qt {v2})".format( v1=PYQT_VERSION_STR, v2=qVersion())) elif PYSIDE: - print("[qt4.py] PySide {v1} (qt {v2})".format( + print("[qt.py] PySide {v1} (qt {v2})".format( v1=PySide.__version__, v2=QtCore.__version__)) # CEF Python version requirement assert cef.__version__ >= "55.4", "CEF Python v55.4+ required to run this" @@ -265,7 +265,7 @@ def OnLoadStart(self, browser, **_): self.navigation_bar.cef_widget.setFocus() # Temporary fix no. 2 for focus issue on Linux (Issue #284) if LINUX: - print("[qt4.py] LoadHandler.OnLoadStart:" + print("[qt.py] LoadHandler.OnLoadStart:" " keyboard focus fix no. 2 (Issue #284)") browser.SetFocus(True) self.initial_app_loading = False @@ -281,7 +281,7 @@ def OnSetFocus(self, **_): def OnGotFocus(self, browser, **_): # Temporary fix no. 1 for focus issues on Linux (Issue #284) if LINUX: - print("[qt4.py] FocusHandler.OnGotFocus:" + print("[qt.py] FocusHandler.OnGotFocus:" " keyboard focus fix no. 1 (Issue #284)") browser.SetFocus(True) diff --git a/tools/run_examples.py b/tools/run_examples.py index 241a94173..afc061a26 100644 --- a/tools/run_examples.py +++ b/tools/run_examples.py @@ -72,19 +72,26 @@ def main(): print("[run_examples.py] PASS: gtk3.py (Gtk 3 not installed)") passed.append("gtk3.py") - # pyqt + # pyqt4 if packages["PyQt4"]: - examples.append("qt4.py pyqt") + examples.append("qt.py pyqt4") else: - print("[run_examples.py] PASS: qt4.py pyqt (PyQt4 not installed)") - passed.append("qt4.py pyqt") + print("[run_examples.py] PASS: qt.py pyqt4 (PyQt4 not installed)") + passed.append("qt.py pyqt4") + + # pyqt5 + if packages["PyQt5"]: + examples.append("qt.py pyqt5") + else: + print("[run_examples.py] PASS: qt.py pyqt5 (PyQt5 not installed)") + passed.append("qt.py pyqt5") # pyside if packages["PySide"]: - examples.append("qt4.py pyside") + examples.append("qt.py pyside") else: - print("[run_examples.py] PASS: qt4.py pyside (PySide not installed)") - passed.append("qt4.py pyside") + print("[run_examples.py] PASS: qt.py pyside (PySide not installed)") + passed.append("qt.py pyside") # tkinter if MAC: @@ -160,6 +167,7 @@ def check_installed_packages(): "gi": False, "kivy": False, "PyQt4": False, + "PyQt5": False, "PySide": False, "tkinter": False, "Tkinter": False, From c07c099e83762b67ee7f24c038b047b4f0822b0b Mon Sep 17 00:00:00 2001 From: cztomczak Date: Thu, 20 Apr 2017 22:16:10 +0200 Subject: [PATCH 221/557] Update to Chromium 57.0.2987.133 on Linux PART 2 (#341) --- src/compile_time_constants.pxi | 2 +- src/subprocess/cefpython_app.cpp | 2 +- src/subprocess/cefpython_app.h | 2 +- src/version/cef_version_linux.h | 20 ++++++++++---------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 47dedaecd..35f850027 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 = 3 +DEF PY_MAJOR_VERSION = 2 diff --git a/src/subprocess/cefpython_app.cpp b/src/subprocess/cefpython_app.cpp index 950777027..867f0646d 100644 --- a/src/subprocess/cefpython_app.cpp +++ b/src/subprocess/cefpython_app.cpp @@ -85,7 +85,7 @@ void CefPythonApp::OnBeforeCommandLineProcessing( } void CefPythonApp::OnRegisterCustomSchemes( - CefRefPtr registrar) { + CefRawPtr registrar) { } CefRefPtr CefPythonApp::GetResourceBundleHandler() { diff --git a/src/subprocess/cefpython_app.h b/src/subprocess/cefpython_app.h index f9336ba3c..e12fd570b 100644 --- a/src/subprocess/cefpython_app.h +++ b/src/subprocess/cefpython_app.h @@ -30,7 +30,7 @@ class CefPythonApp : CefRefPtr command_line) override; void OnRegisterCustomSchemes( - CefRefPtr registrar) override; + CefRawPtr registrar) override; CefRefPtr GetResourceBundleHandler() override; diff --git a/src/version/cef_version_linux.h b/src/version/cef_version_linux.h index 5e718118b..11454273f 100644 --- a/src/version/cef_version_linux.h +++ b/src/version/cef_version_linux.h @@ -35,16 +35,16 @@ #ifndef CEF_INCLUDE_CEF_VERSION_H_ #define CEF_INCLUDE_CEF_VERSION_H_ -#define CEF_VERSION "3.2924.1575.g97389a9" +#define CEF_VERSION "3.2987.1601.gf035232" #define CEF_VERSION_MAJOR 3 -#define CEF_COMMIT_NUMBER 1575 -#define CEF_COMMIT_HASH "97389a92ee2309ded830338d6afd61ba109d31d8" +#define CEF_COMMIT_NUMBER 1601 +#define CEF_COMMIT_HASH "f035232c082f837d2b85bd7821a93a54fc742775" #define COPYRIGHT_YEAR 2017 -#define CHROME_VERSION_MAJOR 56 +#define CHROME_VERSION_MAJOR 57 #define CHROME_VERSION_MINOR 0 -#define CHROME_VERSION_BUILD 2924 -#define CHROME_VERSION_PATCH 76 +#define CHROME_VERSION_BUILD 2987 +#define CHROME_VERSION_PATCH 133 #define DO_MAKE_STRING(p) #p #define MAKE_STRING(p) DO_MAKE_STRING(p) @@ -63,13 +63,13 @@ extern "C" { // universal hash value will change if any platform is affected whereas the // platform hash values will change only if that particular platform is // affected. -#define CEF_API_HASH_UNIVERSAL "66de193ba22e1d92a99bb29d60f3107709aeefda" +#define CEF_API_HASH_UNIVERSAL "b0a24e3e202f3d8b72f2fbc1ebc5864f96ec16ae" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "8055740cd08db66cefe838a826dc90806fadfb33" +#define CEF_API_HASH_PLATFORM "1c6a27f840ac87c8c971350c907edbe2c5fa0387" #elif defined(OS_MACOSX) -#define CEF_API_HASH_PLATFORM "12d8ab423df369b68d37c3667123a1812bc0d345" +#define CEF_API_HASH_PLATFORM "1567db600ee83cc2a59bb8c17ca416d11a7c9b8a" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "86ab23c0d7dafbdff7f66764cf8dac5ec1712af4" +#define CEF_API_HASH_PLATFORM "1f9f9e15bf7cf13de2557ddd411dfc9f694503b0" #endif // Returns CEF version information for the libcef library. The |entry| From b89b93ff9ea63e0b2fbffa9ddaa0b7e4b849dd53 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Fri, 21 Apr 2017 07:58:47 +0200 Subject: [PATCH 222/557] Update distrib directory names on various platforms --- tools/automate.py | 6 +++--- tools/common.py | 22 +++++++++++++++++----- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/tools/automate.py b/tools/automate.py index 741242b8a..19289aed9 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -224,11 +224,11 @@ def build_cef(): % Options.binary_distrib) if Options.x86: - print("[automate.py] INFO: to build CEF projects and create prebuilt" - " binaries you have to use 32-bit chroot. Copy the binary" + print("[automate.py] INFO: Build CEF projects and create prebuilt" + " binaries on Linux 32-bit using eg. VirtualBox. Copy the binary" " distrib's cef_binary_*/ directory (path displayed above) to" " cefpython's build/ directory. Then run automate.py" - " --prebuilt-cef using 32-bit chroot.") + " --prebuilt-cef on Linux 32-bit.") sys.exit(0) else: # Build cefclient, cefsimple, ceftests, libcef_dll_wrapper diff --git a/tools/common.py b/tools/common.py index 386979c98..4ca34d73e 100644 --- a/tools/common.py +++ b/tools/common.py @@ -27,8 +27,14 @@ ARCH_STR = platform.architecture()[0] # OS_POSTFIX is for directories/files names in cefpython sources +# and doesn't include architecture type, just OS name. + # OS_POSTFIX2 is for platform name in cefpython binaries +# and includes architecture type (32bit/64bit). + # CEF_POSTFIX2 is for platform name in upstream CEF binaries +# and includes architecture type (32bit/64bit). + OS_POSTFIX = ("win" if platform.system() == "Windows" else "linux" if platform.system() == "Linux" else "mac" if platform.system() == "Darwin" else "unknown") @@ -353,17 +359,23 @@ def _detect_distrib_dir(): # Will only be set when called from scripts that had version # number arg passed on command line: build.py, build_distrib.py, # make_installer.py, etc. - if LINUX: - # On Linux buildig 32bit and 64bit separately, so don't + if LINUX or MAC: + # - On Linux buildig 32bit and 64bit separately, so don't # delete eg. 64bit distrib when building 32bit distrib. # Keep them in different directories. + # - On Mac only 64bit is supported. dirname = ("distrib_{version}_{postfix2}" .format(version=version, postfix2=OS_POSTFIX2)) - else: + elif WINDOWS: # On Windows both 32bit and 64bit distribs are built at # the same time. - # On Mac only 64bit is supported. - dirname = "distrib_{version}".format(version=version) + dirname = ("distrib_{version}_{win32}_{win64}" + .format(version=version, + win32=OS_POSTFIX2_ARCH[WINDOWS]["32bit"], + win64=OS_POSTFIX2_ARCH[WINDOWS]["64bit"])) + else: + dirname = ("distrib_{version}_{postfix}" + .format(version=version, postfix=OS_POSTFIX)) DISTRIB_DIR = os.path.join(BUILD_DIR, dirname) From cd9613ffa581e2e3245e9cc741a8f0e384293313 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Fri, 21 Apr 2017 09:44:41 +0200 Subject: [PATCH 223/557] Update to Chromium v57 on Mac (#341). Print user agent and cefpython version in tutorial.py example. Print various version info in main_test.py. --- examples/tutorial.py | 3 +++ src/compile_time_constants.pxi | 4 ++-- src/version/cef_version_mac.h | 20 ++++++++++---------- unittests/main_test.py | 8 +++++++- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/examples/tutorial.py b/examples/tutorial.py index a2b04ca89..d770de8f3 100644 --- a/examples/tutorial.py +++ b/examples/tutorial.py @@ -42,6 +42,8 @@ window.onload = function(){ js_print("Javascript", "window.onload", "Called"); js_print("Javascript", "python_property", python_property); + js_print("Javascript", "navigator.userAgent", navigator.userAgent); + js_print("Javascript", "cefpython_version", cefpython_version.version); html_to_data_uri("test", js_callback_1); external.test_multiple_callbacks(js_callback_2); }; @@ -113,6 +115,7 @@ def set_javascript_bindings(browser): bindings = cef.JavascriptBindings( bindToFrames=False, bindToPopups=False) bindings.SetProperty("python_property", "This property was set in Python") + bindings.SetProperty("cefpython_version", cef.GetVersion()) bindings.SetFunction("html_to_data_uri", html_to_data_uri) bindings.SetObject("external", external) browser.SetJavascriptBindings(bindings) diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 35f850027..457e4a580 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 = "Darwin" +DEF PY_MAJOR_VERSION = 3 diff --git a/src/version/cef_version_mac.h b/src/version/cef_version_mac.h index 5e718118b..11454273f 100644 --- a/src/version/cef_version_mac.h +++ b/src/version/cef_version_mac.h @@ -35,16 +35,16 @@ #ifndef CEF_INCLUDE_CEF_VERSION_H_ #define CEF_INCLUDE_CEF_VERSION_H_ -#define CEF_VERSION "3.2924.1575.g97389a9" +#define CEF_VERSION "3.2987.1601.gf035232" #define CEF_VERSION_MAJOR 3 -#define CEF_COMMIT_NUMBER 1575 -#define CEF_COMMIT_HASH "97389a92ee2309ded830338d6afd61ba109d31d8" +#define CEF_COMMIT_NUMBER 1601 +#define CEF_COMMIT_HASH "f035232c082f837d2b85bd7821a93a54fc742775" #define COPYRIGHT_YEAR 2017 -#define CHROME_VERSION_MAJOR 56 +#define CHROME_VERSION_MAJOR 57 #define CHROME_VERSION_MINOR 0 -#define CHROME_VERSION_BUILD 2924 -#define CHROME_VERSION_PATCH 76 +#define CHROME_VERSION_BUILD 2987 +#define CHROME_VERSION_PATCH 133 #define DO_MAKE_STRING(p) #p #define MAKE_STRING(p) DO_MAKE_STRING(p) @@ -63,13 +63,13 @@ extern "C" { // universal hash value will change if any platform is affected whereas the // platform hash values will change only if that particular platform is // affected. -#define CEF_API_HASH_UNIVERSAL "66de193ba22e1d92a99bb29d60f3107709aeefda" +#define CEF_API_HASH_UNIVERSAL "b0a24e3e202f3d8b72f2fbc1ebc5864f96ec16ae" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "8055740cd08db66cefe838a826dc90806fadfb33" +#define CEF_API_HASH_PLATFORM "1c6a27f840ac87c8c971350c907edbe2c5fa0387" #elif defined(OS_MACOSX) -#define CEF_API_HASH_PLATFORM "12d8ab423df369b68d37c3667123a1812bc0d345" +#define CEF_API_HASH_PLATFORM "1567db600ee83cc2a59bb8c17ca416d11a7c9b8a" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "86ab23c0d7dafbdff7f66764cf8dac5ec1712af4" +#define CEF_API_HASH_PLATFORM "1f9f9e15bf7cf13de2557ddd411dfc9f694503b0" #endif // Returns CEF version information for the libcef library. The |entry| diff --git a/unittests/main_test.py b/unittests/main_test.py index a75b4a9e6..d7a2fbf95 100644 --- a/unittests/main_test.py +++ b/unittests/main_test.py @@ -14,7 +14,7 @@ import sys # To show the window for an extended period of time increase this number. -MESSAGE_LOOP_RANGE = 100 # each iteration is 0.01 sec +MESSAGE_LOOP_RANGE = 200 # each iteration is 0.01 sec g_datauri_data = """ @@ -36,6 +36,11 @@ window.onload = function(){ print("window.onload() ok"); + version = cefpython_version + print("CEF Python: "+version.version+""); + print("Chrome: "+version.chrome_version+""); + print("CEF: "+version.cef_version+""); + // Test binding property: test_property1 if (test_property1 == "Test binding property to the 'window' object") { print("test_property_1 ok"); @@ -140,6 +145,7 @@ def test_main(self): bindings.SetFunction("test_function", external.test_function) bindings.SetProperty("test_property1", external.test_property1) bindings.SetProperty("test_property2", external.test_property2) + bindings.SetProperty("cefpython_version", cef.GetVersion()) bindings.SetObject("external", external) browser.SetJavascriptBindings(bindings) subtest_message("browser.SetJavascriptBindings() ok") From 79a8ebcc51ab7e96adbb8d0d44eec4c89c7c1cc9 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Fri, 21 Apr 2017 14:50:17 +0100 Subject: [PATCH 224/557] Update to Chromium v57 on Win (#341) and fix PyQt5 example on Win (#325). Fix PyQt5 support on Windows in qt.py example (#325). Update automate.py to use --ninja-jobs also when building CEF projects. Default jobs ninja uses is very CPU intensive and can cause much lag in OS. --- examples/qt.py | 21 +++++++++++++++++---- src/compile_time_constants.pxi | 4 ++-- src/version/cef_version_win.h | 20 ++++++++++---------- tools/automate.py | 13 +++++++++---- 4 files changed, 38 insertions(+), 20 deletions(-) diff --git a/examples/qt.py b/examples/qt.py index 0a551b246..47348a42f 100644 --- a/examples/qt.py +++ b/examples/qt.py @@ -3,7 +3,7 @@ # bar and a browser. # # Tested configurations: -# - PyQt 5.8.2 on Linux +# - PyQt 5.8.2 on Windows/Linux/Mac # - PyQt 4.11 (qt 4.8) on Windows/Linux # - PySide 1.2 (qt 4.8) on Windows/Linux/Mac # - CEF Python v55.4+ @@ -124,9 +124,22 @@ def setupLayout(self): frame = QFrame() frame.setLayout(layout) self.setCentralWidget(frame) + + if PYQT5 and WINDOWS: + # On Windows with PyQt5 main window must be shown first + # before CEF browser is embedded, otherwise window is + # not resized and application hangs during resize. + self.show() + # Browser can be embedded only after layout was set up self.cef_widget.embedBrowser() - if LINUX and PYQT5: + + if PYQT5 and LINUX: + # On Linux with PyQt5 the QX11EmbedContainer widget is + # no more available. An equivalent in Qt5 is to create + # a hidden window, embed CEF browser in it and then + # create a container for that hidden window and replace + # cef widget in the layout with the container. self.container = QWidget.createWindowContainer( self.cef_widget.hidden_window, parent=self) layout.addWidget(self.container, 1, 0) @@ -166,7 +179,7 @@ def focusOutEvent(self, event): self.browser.SetFocus(False) def embedBrowser(self): - if LINUX and PYQT5: + if PYQT5 and LINUX: self.hidden_window = QWindow() window_info = cef.WindowInfo() rect = [0, 0, self.width(), self.height()] @@ -177,8 +190,8 @@ def embedBrowser(self): self.browser.SetClientHandler(FocusHandler(self)) def getHandle(self): - # PyQt5 on Linux if self.hidden_window: + # PyQt5 on Linux return int(self.hidden_window.winId()) try: # PyQt4 and PyQt5 diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 457e4a580..10ec798af 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 = "Darwin" -DEF PY_MAJOR_VERSION = 3 +DEF UNAME_SYSNAME = "Windows" +DEF PY_MAJOR_VERSION = 2 diff --git a/src/version/cef_version_win.h b/src/version/cef_version_win.h index 5e718118b..11454273f 100644 --- a/src/version/cef_version_win.h +++ b/src/version/cef_version_win.h @@ -35,16 +35,16 @@ #ifndef CEF_INCLUDE_CEF_VERSION_H_ #define CEF_INCLUDE_CEF_VERSION_H_ -#define CEF_VERSION "3.2924.1575.g97389a9" +#define CEF_VERSION "3.2987.1601.gf035232" #define CEF_VERSION_MAJOR 3 -#define CEF_COMMIT_NUMBER 1575 -#define CEF_COMMIT_HASH "97389a92ee2309ded830338d6afd61ba109d31d8" +#define CEF_COMMIT_NUMBER 1601 +#define CEF_COMMIT_HASH "f035232c082f837d2b85bd7821a93a54fc742775" #define COPYRIGHT_YEAR 2017 -#define CHROME_VERSION_MAJOR 56 +#define CHROME_VERSION_MAJOR 57 #define CHROME_VERSION_MINOR 0 -#define CHROME_VERSION_BUILD 2924 -#define CHROME_VERSION_PATCH 76 +#define CHROME_VERSION_BUILD 2987 +#define CHROME_VERSION_PATCH 133 #define DO_MAKE_STRING(p) #p #define MAKE_STRING(p) DO_MAKE_STRING(p) @@ -63,13 +63,13 @@ extern "C" { // universal hash value will change if any platform is affected whereas the // platform hash values will change only if that particular platform is // affected. -#define CEF_API_HASH_UNIVERSAL "66de193ba22e1d92a99bb29d60f3107709aeefda" +#define CEF_API_HASH_UNIVERSAL "b0a24e3e202f3d8b72f2fbc1ebc5864f96ec16ae" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "8055740cd08db66cefe838a826dc90806fadfb33" +#define CEF_API_HASH_PLATFORM "1c6a27f840ac87c8c971350c907edbe2c5fa0387" #elif defined(OS_MACOSX) -#define CEF_API_HASH_PLATFORM "12d8ab423df369b68d37c3667123a1812bc0d345" +#define CEF_API_HASH_PLATFORM "1567db600ee83cc2a59bb8c17ca416d11a7c9b8a" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "86ab23c0d7dafbdff7f66764cf8dac5ec1712af4" +#define CEF_API_HASH_PLATFORM "1f9f9e15bf7cf13de2557ddd411dfc9f694503b0" #endif // Returns CEF version information for the libcef library. The |entry| diff --git a/tools/automate.py b/tools/automate.py index 19289aed9..45a592d2c 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -201,6 +201,7 @@ def setup_options(docopt_args): Options.ninja_jobs = int(multiprocessing.cpu_count() / 2) if Options.ninja_jobs < 1: Options.ninja_jobs = 1 + Options.ninja_jobs = str(Options.ninja_jobs) def build_cef(): @@ -410,9 +411,11 @@ def build_cef_projects(): # > cefclient_mac.mm:22:29: error: property 'mainMenu' not found if MAC: # Build only cefsimple - command.extend(["ninja", "cefsimple"]) + command.extend(["ninja", "-j", Options.ninja_jobs, + "cefsimple"]) else: - command.extend(["ninja", "cefclient", "cefsimple", "ceftests"]) + command.extend(["ninja", "-j", Options.ninja_jobs, + "cefclient", "cefsimple", "ceftests"]) run_command(command, build_cefclient_dir) print("[automate.py] OK") assert os.path.exists(cefclient_exe) @@ -507,7 +510,8 @@ def build_wrapper_library_windows(runtime_library, msvs, vcvars): # Run ninja ninja_wrapper = prepare_build_command(build_lib=True, vcvars=vcvars) - ninja_wrapper.extend(["ninja", "libcef_dll_wrapper"]) + ninja_wrapper.extend(["ninja", "-j", Options.ninja_jobs, + "libcef_dll_wrapper"]) run_command(ninja_wrapper, working_dir=build_wrapper_dir) print("[automate.py] ninja OK") assert os.path.exists(wrapper_lib) @@ -630,7 +634,8 @@ def build_wrapper_library_mac(): print("[automate.py] cmake OK") # Ninja ninja_wrapper = prepare_build_command(build_lib=True) - ninja_wrapper.extend(["ninja", "libcef_dll_wrapper"]) + ninja_wrapper.extend(["ninja", "-j", Options.ninja_jobs, + "libcef_dll_wrapper"]) run_command(ninja_wrapper, build_wrapper_dir) print("[automate.py] ninja OK") assert os.path.exists(wrapper_lib) From 940c28ab9c8c1eaf960907a238f8ea1e7ce25048 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Fri, 21 Apr 2017 15:53:26 +0200 Subject: [PATCH 225/557] Update docs for v57.0 release --- README.md | 2 +- docs/Tutorial.md | 2 +- examples/Examples-README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7b4bbfaae..5918fff98 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ also download packages for offline installation available on the [GitHub Releases](../../releases) pages. ``` -pip install cefpython3==56.2 +pip install cefpython3==57.0 ``` ## Tutorial diff --git a/docs/Tutorial.md b/docs/Tutorial.md index c4a38ec25..f52769b36 100644 --- a/docs/Tutorial.md +++ b/docs/Tutorial.md @@ -36,7 +36,7 @@ Run the commands below to install the cefpython3 package, clone the repository and run the Hello World example: ```commandline -pip install cefpython3==56.2 +pip install cefpython3==57.0 git clone https://github.com/cztomczak/cefpython.git cd cefpython/examples/ python hello_world.py diff --git a/examples/Examples-README.md b/examples/Examples-README.md index 9b0ad482a..e2b4ee93a 100644 --- a/examples/Examples-README.md +++ b/examples/Examples-README.md @@ -11,7 +11,7 @@ Instructions to install the cefpython3 package, clone the repository and run the hello_world.py example: ``` -pip install cefpython3==56.2 +pip install cefpython3==57.0 git clone https://github.com/cztomczak/cefpython.git cd cefpython/examples/ python hello_world.py From ac701e3186a4ccaa222fac227b5f8a865c21efdc Mon Sep 17 00:00:00 2001 From: cztomczak Date: Fri, 21 Apr 2017 15:54:04 +0200 Subject: [PATCH 226/557] Merge branch 'master' of https://github.com/cztomczak/cefpython --- examples/qt.py | 21 +++++++++++++++++---- examples/tutorial.py | 3 +++ src/compile_time_constants.pxi | 2 +- src/version/cef_version_mac.h | 20 ++++++++++---------- src/version/cef_version_win.h | 20 ++++++++++---------- tools/automate.py | 13 +++++++++---- unittests/main_test.py | 8 +++++++- 7 files changed, 57 insertions(+), 30 deletions(-) diff --git a/examples/qt.py b/examples/qt.py index 0a551b246..47348a42f 100644 --- a/examples/qt.py +++ b/examples/qt.py @@ -3,7 +3,7 @@ # bar and a browser. # # Tested configurations: -# - PyQt 5.8.2 on Linux +# - PyQt 5.8.2 on Windows/Linux/Mac # - PyQt 4.11 (qt 4.8) on Windows/Linux # - PySide 1.2 (qt 4.8) on Windows/Linux/Mac # - CEF Python v55.4+ @@ -124,9 +124,22 @@ def setupLayout(self): frame = QFrame() frame.setLayout(layout) self.setCentralWidget(frame) + + if PYQT5 and WINDOWS: + # On Windows with PyQt5 main window must be shown first + # before CEF browser is embedded, otherwise window is + # not resized and application hangs during resize. + self.show() + # Browser can be embedded only after layout was set up self.cef_widget.embedBrowser() - if LINUX and PYQT5: + + if PYQT5 and LINUX: + # On Linux with PyQt5 the QX11EmbedContainer widget is + # no more available. An equivalent in Qt5 is to create + # a hidden window, embed CEF browser in it and then + # create a container for that hidden window and replace + # cef widget in the layout with the container. self.container = QWidget.createWindowContainer( self.cef_widget.hidden_window, parent=self) layout.addWidget(self.container, 1, 0) @@ -166,7 +179,7 @@ def focusOutEvent(self, event): self.browser.SetFocus(False) def embedBrowser(self): - if LINUX and PYQT5: + if PYQT5 and LINUX: self.hidden_window = QWindow() window_info = cef.WindowInfo() rect = [0, 0, self.width(), self.height()] @@ -177,8 +190,8 @@ def embedBrowser(self): self.browser.SetClientHandler(FocusHandler(self)) def getHandle(self): - # PyQt5 on Linux if self.hidden_window: + # PyQt5 on Linux return int(self.hidden_window.winId()) try: # PyQt4 and PyQt5 diff --git a/examples/tutorial.py b/examples/tutorial.py index a2b04ca89..d770de8f3 100644 --- a/examples/tutorial.py +++ b/examples/tutorial.py @@ -42,6 +42,8 @@ window.onload = function(){ js_print("Javascript", "window.onload", "Called"); js_print("Javascript", "python_property", python_property); + js_print("Javascript", "navigator.userAgent", navigator.userAgent); + js_print("Javascript", "cefpython_version", cefpython_version.version); html_to_data_uri("test", js_callback_1); external.test_multiple_callbacks(js_callback_2); }; @@ -113,6 +115,7 @@ def set_javascript_bindings(browser): bindings = cef.JavascriptBindings( bindToFrames=False, bindToPopups=False) bindings.SetProperty("python_property", "This property was set in Python") + bindings.SetProperty("cefpython_version", cef.GetVersion()) bindings.SetFunction("html_to_data_uri", html_to_data_uri) bindings.SetObject("external", external) browser.SetJavascriptBindings(bindings) diff --git a/src/compile_time_constants.pxi b/src/compile_time_constants.pxi index 35f850027..10ec798af 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 UNAME_SYSNAME = "Windows" DEF PY_MAJOR_VERSION = 2 diff --git a/src/version/cef_version_mac.h b/src/version/cef_version_mac.h index 5e718118b..11454273f 100644 --- a/src/version/cef_version_mac.h +++ b/src/version/cef_version_mac.h @@ -35,16 +35,16 @@ #ifndef CEF_INCLUDE_CEF_VERSION_H_ #define CEF_INCLUDE_CEF_VERSION_H_ -#define CEF_VERSION "3.2924.1575.g97389a9" +#define CEF_VERSION "3.2987.1601.gf035232" #define CEF_VERSION_MAJOR 3 -#define CEF_COMMIT_NUMBER 1575 -#define CEF_COMMIT_HASH "97389a92ee2309ded830338d6afd61ba109d31d8" +#define CEF_COMMIT_NUMBER 1601 +#define CEF_COMMIT_HASH "f035232c082f837d2b85bd7821a93a54fc742775" #define COPYRIGHT_YEAR 2017 -#define CHROME_VERSION_MAJOR 56 +#define CHROME_VERSION_MAJOR 57 #define CHROME_VERSION_MINOR 0 -#define CHROME_VERSION_BUILD 2924 -#define CHROME_VERSION_PATCH 76 +#define CHROME_VERSION_BUILD 2987 +#define CHROME_VERSION_PATCH 133 #define DO_MAKE_STRING(p) #p #define MAKE_STRING(p) DO_MAKE_STRING(p) @@ -63,13 +63,13 @@ extern "C" { // universal hash value will change if any platform is affected whereas the // platform hash values will change only if that particular platform is // affected. -#define CEF_API_HASH_UNIVERSAL "66de193ba22e1d92a99bb29d60f3107709aeefda" +#define CEF_API_HASH_UNIVERSAL "b0a24e3e202f3d8b72f2fbc1ebc5864f96ec16ae" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "8055740cd08db66cefe838a826dc90806fadfb33" +#define CEF_API_HASH_PLATFORM "1c6a27f840ac87c8c971350c907edbe2c5fa0387" #elif defined(OS_MACOSX) -#define CEF_API_HASH_PLATFORM "12d8ab423df369b68d37c3667123a1812bc0d345" +#define CEF_API_HASH_PLATFORM "1567db600ee83cc2a59bb8c17ca416d11a7c9b8a" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "86ab23c0d7dafbdff7f66764cf8dac5ec1712af4" +#define CEF_API_HASH_PLATFORM "1f9f9e15bf7cf13de2557ddd411dfc9f694503b0" #endif // Returns CEF version information for the libcef library. The |entry| diff --git a/src/version/cef_version_win.h b/src/version/cef_version_win.h index 5e718118b..11454273f 100644 --- a/src/version/cef_version_win.h +++ b/src/version/cef_version_win.h @@ -35,16 +35,16 @@ #ifndef CEF_INCLUDE_CEF_VERSION_H_ #define CEF_INCLUDE_CEF_VERSION_H_ -#define CEF_VERSION "3.2924.1575.g97389a9" +#define CEF_VERSION "3.2987.1601.gf035232" #define CEF_VERSION_MAJOR 3 -#define CEF_COMMIT_NUMBER 1575 -#define CEF_COMMIT_HASH "97389a92ee2309ded830338d6afd61ba109d31d8" +#define CEF_COMMIT_NUMBER 1601 +#define CEF_COMMIT_HASH "f035232c082f837d2b85bd7821a93a54fc742775" #define COPYRIGHT_YEAR 2017 -#define CHROME_VERSION_MAJOR 56 +#define CHROME_VERSION_MAJOR 57 #define CHROME_VERSION_MINOR 0 -#define CHROME_VERSION_BUILD 2924 -#define CHROME_VERSION_PATCH 76 +#define CHROME_VERSION_BUILD 2987 +#define CHROME_VERSION_PATCH 133 #define DO_MAKE_STRING(p) #p #define MAKE_STRING(p) DO_MAKE_STRING(p) @@ -63,13 +63,13 @@ extern "C" { // universal hash value will change if any platform is affected whereas the // platform hash values will change only if that particular platform is // affected. -#define CEF_API_HASH_UNIVERSAL "66de193ba22e1d92a99bb29d60f3107709aeefda" +#define CEF_API_HASH_UNIVERSAL "b0a24e3e202f3d8b72f2fbc1ebc5864f96ec16ae" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "8055740cd08db66cefe838a826dc90806fadfb33" +#define CEF_API_HASH_PLATFORM "1c6a27f840ac87c8c971350c907edbe2c5fa0387" #elif defined(OS_MACOSX) -#define CEF_API_HASH_PLATFORM "12d8ab423df369b68d37c3667123a1812bc0d345" +#define CEF_API_HASH_PLATFORM "1567db600ee83cc2a59bb8c17ca416d11a7c9b8a" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "86ab23c0d7dafbdff7f66764cf8dac5ec1712af4" +#define CEF_API_HASH_PLATFORM "1f9f9e15bf7cf13de2557ddd411dfc9f694503b0" #endif // Returns CEF version information for the libcef library. The |entry| diff --git a/tools/automate.py b/tools/automate.py index 19289aed9..45a592d2c 100644 --- a/tools/automate.py +++ b/tools/automate.py @@ -201,6 +201,7 @@ def setup_options(docopt_args): Options.ninja_jobs = int(multiprocessing.cpu_count() / 2) if Options.ninja_jobs < 1: Options.ninja_jobs = 1 + Options.ninja_jobs = str(Options.ninja_jobs) def build_cef(): @@ -410,9 +411,11 @@ def build_cef_projects(): # > cefclient_mac.mm:22:29: error: property 'mainMenu' not found if MAC: # Build only cefsimple - command.extend(["ninja", "cefsimple"]) + command.extend(["ninja", "-j", Options.ninja_jobs, + "cefsimple"]) else: - command.extend(["ninja", "cefclient", "cefsimple", "ceftests"]) + command.extend(["ninja", "-j", Options.ninja_jobs, + "cefclient", "cefsimple", "ceftests"]) run_command(command, build_cefclient_dir) print("[automate.py] OK") assert os.path.exists(cefclient_exe) @@ -507,7 +510,8 @@ def build_wrapper_library_windows(runtime_library, msvs, vcvars): # Run ninja ninja_wrapper = prepare_build_command(build_lib=True, vcvars=vcvars) - ninja_wrapper.extend(["ninja", "libcef_dll_wrapper"]) + ninja_wrapper.extend(["ninja", "-j", Options.ninja_jobs, + "libcef_dll_wrapper"]) run_command(ninja_wrapper, working_dir=build_wrapper_dir) print("[automate.py] ninja OK") assert os.path.exists(wrapper_lib) @@ -630,7 +634,8 @@ def build_wrapper_library_mac(): print("[automate.py] cmake OK") # Ninja ninja_wrapper = prepare_build_command(build_lib=True) - ninja_wrapper.extend(["ninja", "libcef_dll_wrapper"]) + ninja_wrapper.extend(["ninja", "-j", Options.ninja_jobs, + "libcef_dll_wrapper"]) run_command(ninja_wrapper, build_wrapper_dir) print("[automate.py] ninja OK") assert os.path.exists(wrapper_lib) diff --git a/unittests/main_test.py b/unittests/main_test.py index a75b4a9e6..d7a2fbf95 100644 --- a/unittests/main_test.py +++ b/unittests/main_test.py @@ -14,7 +14,7 @@ import sys # To show the window for an extended period of time increase this number. -MESSAGE_LOOP_RANGE = 100 # each iteration is 0.01 sec +MESSAGE_LOOP_RANGE = 200 # each iteration is 0.01 sec g_datauri_data = """ @@ -36,6 +36,11 @@ window.onload = function(){ print("window.onload() ok"); + version = cefpython_version + print("CEF Python: "+version.version+""); + print("Chrome: "+version.chrome_version+""); + print("CEF: "+version.cef_version+""); + // Test binding property: test_property1 if (test_property1 == "Test binding property to the 'window' object") { print("test_property_1 ok"); @@ -140,6 +145,7 @@ def test_main(self): bindings.SetFunction("test_function", external.test_function) bindings.SetProperty("test_property1", external.test_property1) bindings.SetProperty("test_property2", external.test_property2) + bindings.SetProperty("cefpython_version", cef.GetVersion()) bindings.SetObject("external", external) browser.SetJavascriptBindings(bindings) subtest_message("browser.SetJavascriptBindings() ok") From 804a0a121787c2c9e745cbf8e72ed1664fa32ef3 Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 22 Apr 2017 08:13:16 +0200 Subject: [PATCH 227/557] Fix PyCharm warnings in qt.py and update tested configurat. in gtk3.py --- README.md | 5 +++-- examples/gtk3.py | 17 +++++++---------- examples/qt.py | 30 ++++++++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 5918fff98..314dfc13d 100644 --- a/README.md +++ b/README.md @@ -38,9 +38,10 @@ or other kind of internet bots. ## Install -You can install with pip. On Linux pip 8.1+ is required. You can +You can install [pypi/cefpython3](https://pypi.python.org/pypi/cefpython3) +package using pip tool. On Linux pip 8.1+ is required. You can also download packages for offline installation available on the -[GitHub Releases](../../releases) pages. +[GitHub Releases](../../releases) pages. Command to install with pip: ``` pip install cefpython3==57.0 diff --git a/examples/gtk3.py b/examples/gtk3.py index 6e0032600..acc2ee075 100644 --- a/examples/gtk3.py +++ b/examples/gtk3.py @@ -1,16 +1,13 @@ # Example of embedding CEF Python browser using PyGObject/PyGI (GTK 3). # -# Mac note: This example crashes on Mac with error message: -# > _createMenuRef called with existing principal MenuRef.. -# Reported as Issue #310. -# -# Linux note: This example is currently broken in v54+ on Linux (Issue #261). -# It works fine with cefpython v53. -# # Tested configurations: -# - GTK 3.18 on Windows -# - GTK 3.10 on Linux -# - CEF Python v53.1+ +# - GTK 3.18 on Windows (cefpython v53.1+) +# - GTK 3.10 on Linux (works with cefpython v53.1 and v57.0+) +# +# Mac crash: This example crashes on Mac with error message: +# > _createMenuRef called with existing principal MenuRef.. +# Reported as Issue #310. + from cefpython3 import cefpython as cef import ctypes diff --git a/examples/qt.py b/examples/qt.py index 47348a42f..37478844e 100644 --- a/examples/qt.py +++ b/examples/qt.py @@ -24,22 +24,29 @@ PYQT5 = False PYSIDE = False -# PyQt imports if "pyqt4" in sys.argv: PYQT4 = True + # noinspection PyUnresolvedReferences from PyQt4.QtGui import * + # noinspection PyUnresolvedReferences from PyQt4.QtCore import * elif "pyqt5" in sys.argv: PYQT5 = True + # noinspection PyUnresolvedReferences from PyQt5.QtGui import * + # noinspection PyUnresolvedReferences from PyQt5.QtCore import * + # noinspection PyUnresolvedReferences from PyQt5.QtWidgets import * -# PySide imports elif "pyside" in sys.argv: PYSIDE = True + # noinspection PyUnresolvedReferences import PySide + # noinspection PyUnresolvedReferences from PySide import QtCore + # noinspection PyUnresolvedReferences from PySide.QtGui import * + # noinspection PyUnresolvedReferences from PySide.QtCore import * else: print("USAGE:") @@ -63,6 +70,7 @@ # OS differences CefWidgetParent = QWidget if LINUX and (PYQT4 or PYSIDE): + # noinspection PyUnresolvedReferences CefWidgetParent = QX11EmbedContainer @@ -98,6 +106,7 @@ def check_versions(): class MainWindow(QMainWindow): def __init__(self): + # noinspection PyArgumentList super(MainWindow, self).__init__(None) self.cef_widget = None self.navigation_bar = None @@ -115,12 +124,15 @@ def setupLayout(self): self.cef_widget = CefWidget(self) self.navigation_bar = NavigationBar(self.cef_widget) layout = QGridLayout() + # noinspection PyArgumentList layout.addWidget(self.navigation_bar, 0, 0) + # noinspection PyArgumentList layout.addWidget(self.cef_widget, 1, 0) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) layout.setRowStretch(0, 0) layout.setRowStretch(1, 1) + # noinspection PyArgumentList frame = QFrame() frame.setLayout(layout) self.setCentralWidget(frame) @@ -140,8 +152,10 @@ def setupLayout(self): # a hidden window, embed CEF browser in it and then # create a container for that hidden window and replace # cef widget in the layout with the container. + # noinspection PyUnresolvedReferences, PyArgumentList self.container = QWidget.createWindowContainer( self.cef_widget.hidden_window, parent=self) + # noinspection PyArgumentList layout.addWidget(self.container, 1, 0) def closeEvent(self, event): @@ -158,6 +172,7 @@ def clear_browser_references(self): class CefWidget(CefWidgetParent): def __init__(self, parent=None): + # noinspection PyArgumentList super(CefWidget, self).__init__(parent) self.parent = parent self.browser = None @@ -180,6 +195,7 @@ def focusOutEvent(self, event): def embedBrowser(self): if PYQT5 and LINUX: + # noinspection PyUnresolvedReferences self.hidden_window = QWindow() window_info = cef.WindowInfo() rect = [0, 0, self.width(), self.height()] @@ -246,6 +262,7 @@ def __init__(self, args): def createTimer(self): timer = QTimer() + # noinspection PyUnresolvedReferences timer.timeout.connect(self.onTimer) timer.start(10) return timer @@ -301,6 +318,7 @@ def OnGotFocus(self, browser, **_): class NavigationBar(QFrame): def __init__(self, cef_widget): + # noinspection PyArgumentList super(NavigationBar, self).__init__() self.cef_widget = cef_widget @@ -311,22 +329,30 @@ def __init__(self, cef_widget): # Back button self.back = self.createButton("back") + # noinspection PyUnresolvedReferences self.back.clicked.connect(self.onBack) + # noinspection PyArgumentList layout.addWidget(self.back, 0, 0) # Forward button self.forward = self.createButton("forward") + # noinspection PyUnresolvedReferences self.forward.clicked.connect(self.onForward) + # noinspection PyArgumentList layout.addWidget(self.forward, 0, 1) # Reload button self.reload = self.createButton("reload") + # noinspection PyUnresolvedReferences self.reload.clicked.connect(self.onReload) + # noinspection PyArgumentList layout.addWidget(self.reload, 0, 2) # Url input self.url = QLineEdit("") + # noinspection PyUnresolvedReferences self.url.returnPressed.connect(self.onGoUrl) + # noinspection PyArgumentList layout.addWidget(self.url, 0, 3) # Layout From b1f53487e65300f44fd760ac5ba67b08e9f3b52e Mon Sep 17 00:00:00 2001 From: cztomczak Date: Sat, 22 Apr 2017 19:39:17 +0200 Subject: [PATCH 228/557] Add screenshot.py example and off-screen rendering section in Tutorial. Add screenshot.py, a simple example of off-screen rendering (#287). --- api/RenderHandler.md | 11 +- docs/Tutorial.md | 159 +++++++++++++++++++++++++-- examples/Examples-README.md | 20 ++-- examples/screenshot.py | 209 ++++++++++++++++++++++++++++++++++++ examples/tutorial.py | 6 +- 5 files changed, 386 insertions(+), 19 deletions(-) create mode 100644 examples/screenshot.py diff --git a/api/RenderHandler.md b/api/RenderHandler.md index 428120209..bb25ac01d 100644 --- a/api/RenderHandler.md +++ b/api/RenderHandler.md @@ -129,7 +129,7 @@ Called when the browser wants to move or resize the popup widget. | Parameter | Type | | --- | --- | | browser | [Browser](Browser.md) | -| element_type | int | +| element_type | PaintElementType | | dirty_rects | list[[x,y,width,height],[..]] | | paint_buffer | [PaintBuffer](PaintBuffer.md) | | width | int | @@ -145,9 +145,12 @@ of rectangles in pixel coordinates that need to be repainted. |buffer| will be |width|*|height|*4 bytes in size and represents a BGRA image with an upper-left origin. -`paintElementType` constants in the cefpython module: -* PET_VIEW -* PET_POPUP +**Important:** Do not keep reference to |paint_buffer| after this +method returns. + +`PaintElementType` enum: +* cef.PET_VIEW +* cef.PET_POPUP ### OnCursorChange diff --git a/docs/Tutorial.md b/docs/Tutorial.md index f52769b36..0065f7aa6 100644 --- a/docs/Tutorial.md +++ b/docs/Tutorial.md @@ -5,9 +5,10 @@ on Chromium in a Python application. You can also use it to create a HTML 5 based GUI in an application that can act as 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 many +basics. This tutorial will discuss the three featured examples: +[hello_world.py](../examples/hello_world.py), +[tutorial.py](../examples/tutorial.py) +and [screenshot.py](../examples/screenshot.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. @@ -23,6 +24,7 @@ Table of contents: * [Javascript integration](#javascript-integration) * [Javascript exceptions and Python exceptions](#javascript-exceptions-and-python-exceptions) * [Plugins and Flash support](#plugins-and-flash-support) +* [Off-screen rendering](#off-screen-rendering) * [Build executable](#build-executable) * [Support and documentation](#support-and-documentation) @@ -46,9 +48,9 @@ The hello_world.py example's source code will be analyzed line by line in the next section of this Tutorial. This tutorial in its further sections will also reference the -tutorial.py example which will show how to use more advanced -CEF Python features. The tutorial.py example is also available -in the examples/ directory. +tutorial.py and screenshot.py examples which will show how to +use more advanced CEF Python features. All these examples are +available in the examples/ root directory. ## Hello world @@ -470,6 +472,151 @@ For the old CEF Python v31 release instructions for enabling Flash support are available on Wiki pages. +## Off-screen rendering + +Off-screen rendering, in short OSR, also known as windowless +rendering, is a method of rendering pages into a memory buffer +without creating an actual visible window. This method of +rendering has its uses, some pluses and some minuses. Its main +use is so that web page rendering can be integrated into apps +that have its own rendering systems and they can draw web browser +contents only if they are provided a pixel buffer to draw. CEF Python +provides a few examples of integrating CEF off-screen rendering +with frameworks such as Kivy, Panda3D and Pygame/PyOpenGl. + +In this tutorial it will be discussed [screenshot.py](../examples/screenshot.py) +example which is a very basic example of off-screen rendering. +This example creates a screenshot of a web page with viewport +size set to 800px width and 5000px height which is an equivalent +of scrolling down page multiple times, but you get all this in +one single screenshot. + +Before running this script you must install PIL image library: + +```text +pip install PIL +``` + +This example accepts optional arguments so that you can change +url and viewport size. Example usage: + +```text +python screenshot.py +python screenshot.py https://github.com/cztomczak/cefpython 1024 5000 +python screenshot.py https://www.google.com/ 800 600 +``` + +Let's discuss code in this example. + +To be able to use off-screen rendering mode in CEF you have to set +[windowless_rendering_enabled](../api/ApplicationSettings.md#windowless_rendering_enabled) +option to True, eg.: + +```Python +cef.Initialize(settings={"windowless_rendering_enabled": True}) +``` + +Do not enable this value if the application does not use off-screen +rendering as it may reduce rendering performance on some systems. + +Another thing that distincts windowed rendering from off-screen +rendering is that when creating browser you have to call SetAsOffscreen +method on the WindowInfo object. Code from the example: + +```Python +parent_window_handle = 0 +window_info = cef.WindowInfo() +window_info.SetAsOffscreen(parent_window_handle) +browser = cef.CreateBrowserSync(window_info=window_info, + url=URL) +``` + +Also after creating browser it is required to let CEF know that +viewport size is available and that OnPaint callback may be called +(this callback will be explained in a moment) by calling +WasResized method: + +```Python +browser.WasResized() +``` + +Off-screen rendering requires implementing [RenderHandler](../api/RenderHandler.md#renderhandler-interface) +which is one of client handlers and how to use them was +explained earlier in the tutorial in the [Client handlers](#client-handlers) +section. For basic off-screen rendering it is enough to +implement only two methods: [GetViewRect](../api/RenderHandler.md#getviewrect) +and [OnPaint](../api/RenderHandler.md#onpaint). In the GetViewRect +callback information on viewport size will be provided to CEF: + +```Python +def GetViewRect(self, rect_out, **_): + rect_out.extend([0, 0, VIEWPORT_SIZE[0], VIEWPORT_SIZE[1]]) + return True +``` + +In this callback viewport size is returned via |rect_out| which +is of type "list" and thus is passed by reference. Additionally +a True value is returned by function to notify CEF that rectangle +was provided. + +In the OnPaint callback CEF provides a [PaintBufer](../api/PaintBuffer.md#paintbuffer-object) object, which is a pixel buffer of the +browser view. This object has [GetIntPointer](../api/PaintBuffer.md#getintpointer) +and [GetString](../api/PaintBuffer.md#getstring) methods. In the +example the latter method is used which returns bytes. The method +name is a bit confusing for Python 3 users, but in Python 2 bytes +were strings and thus the name. Here is the code: + +```Python +def OnPaint(self, browser, element_type, paint_buffer, **_): + if element_type == cef.PET_VIEW: + buffer_string = paint_buffer.GetString(mode="rgba", + origin="top-left") + browser.SetUserData("OnPaint.buffer_string", buffer_string) +``` + +The |element_type| argument can be either of cef.PET_VIEW +(main view) or cef.PET_POPUP (for drawing popup widgets like +`