cef linux64 2454

git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@64340 954022d7-b5bf-4e40-9824-e11837661b57
This commit is contained in:
Oleg.Korshul
2015-08-26 14:48:08 +00:00
committed by Alexander Trofimov
parent 44f3ab4124
commit a8deb86c9c
479 changed files with 83689 additions and 0 deletions

81
.gitattributes vendored
View File

@ -689,6 +689,69 @@ DesktopEditor/ChromiumBasedEditors svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2 svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/app svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64 svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/cef.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/cef_100_percent.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/cef_200_percent.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/cef_extensions.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/chrome-sandbox svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/devtools_resources.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/icudtl.dat svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/am.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ar.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/bg.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/bn.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ca.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/cs.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/da.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/de.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/el.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/en-GB.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/en-US.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/es-419.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/es.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/et.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/fa.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/fi.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/fil.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/fr.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/gu.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/he.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/hi.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/hr.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/hu.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/id.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/it.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ja.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/kn.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ko.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/lt.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/lv.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ml.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/mr.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ms.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/nb.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/nl.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/pl.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/pt-BR.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/pt-PT.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ro.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ru.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/sk.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/sl.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/sr.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/sv.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/sw.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/ta.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/te.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/th.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/tr.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/uk.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/vi.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/zh-CN.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/locales/zh-TW.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/linux64/snapshot_blob.bin svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/win32 svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/win32/cef.pak svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/app/cefbuilds/win32/cef_100_percent.pak svn_mime_002dtype=application%2Foctet-stream
@ -896,6 +959,24 @@ DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/qcefview svnc_tsvn_003alogminsize=
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/cefclient svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/cefclient/browser svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/cefclient/common svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/cefclient/renderer svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/cefclient/resources svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/cefclient/resources/logo.png svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/cefclient/resources/pdf.pdf svn_mime_002dtype=application%2Foctet-stream
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/include svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/include/base svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/include/base/internal svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/include/capi svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/include/internal svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/include/wrapper svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/libcef_dll svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/libcef_dll/base svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/libcef_dll/cpptoc svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/libcef_dll/ctocpp svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/linux/libcef_dll/wrapper svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/mac svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/windows svnc_tsvn_003alogminsize=5
DesktopEditor/ChromiumBasedEditors[!!-~]2/lib/src/cef/windows/cefclient svnc_tsvn_003alogminsize=5

View File

@ -0,0 +1,421 @@
# 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.
#
# Source files.
#
# cefclient browser sources.
set(CEFCLIENT_BROWSER_BROWSER_SRCS
browser/binding_test.cc
browser/binding_test.h
browser/browser_window.cc
browser/browser_window.h
browser/bytes_write_handler.cc
browser/bytes_write_handler.h
browser/client_app_browser.cc
browser/client_app_browser.h
browser/client_app_delegates_browser.cc
browser/client_handler.cc
browser/client_handler.h
browser/client_handler_osr.cc
browser/client_handler_osr.h
browser/client_handler_std.cc
browser/client_handler_std.h
browser/client_types.h
browser/dialog_test.cc
browser/dialog_test.h
browser/geometry_util.cc
browser/geometry_util.h
browser/main_context.cc
browser/main_context.h
browser/main_context_impl.cc
browser/main_context_impl.h
browser/main_message_loop.cc
browser/main_message_loop.h
browser/main_message_loop_std.cc
browser/main_message_loop_std.h
browser/osr_dragdrop_events.h
browser/osr_renderer.cc
browser/osr_renderer.h
browser/resource.h
browser/resource_util.h
browser/root_window.cc
browser/root_window.h
browser/root_window_manager.cc
browser/root_window_manager.h
browser/scheme_test.cc
browser/scheme_test.h
browser/temp_window.h
browser/test_runner.cc
browser/test_runner.h
browser/urlrequest_test.cc
browser/urlrequest_test.h
browser/window_test.cc
browser/window_test.h
)
source_group(cefclient\\\\browser FILES ${CEFCLIENT_BROWSER_BROWSER_SRCS})
set(CEFCLIENT_BROWSER_SRCS
${CEFCLIENT_BROWSER_BROWSER_SRCS}
)
# cefclient common sources.
set(CEFCLIENT_COMMON_COMMON_SRCS
common/client_app.cc
common/client_app.h
common/client_app_delegates_common.cc
common/client_app_other.cc
common/client_app_other.h
common/client_switches.cc
common/client_switches.h
common/scheme_test_common.cc
common/scheme_test_common.h
)
source_group(cefclient\\\\common FILES ${CEFCLIENT_COMMON_COMMON_SRCS})
set(CEFCLIENT_COMMON_SRCS
${CEFCLIENT_COMMON_COMMON_SRCS}
)
# cefclient renderer sources.
set(CEFCLIENT_RENDERER_RENDERER_SRCS
renderer/client_app_delegates_renderer.cc
renderer/client_app_renderer.cc
renderer/client_app_renderer.h
renderer/client_renderer.cc
renderer/client_renderer.h
renderer/performance_test.cc
renderer/performance_test.h
renderer/performance_test_setup.h
renderer/performance_test_tests.cc
)
source_group(cefclient\\\\renderer FILES ${CEFCLIENT_RENDERER_RENDERER_SRCS})
set(CEFCLIENT_RENDERER_SRCS
${CEFCLIENT_RENDERER_RENDERER_SRCS}
)
#cefclient Linux sources
set(CEFCLIENT_LINUX_SRCS
cefclient_gtk.cc
)
source_group(cefclient FILES ${CEFCLIENT_LINUX_SRCS})
set(CEFCLIENT_LINUX_BROWSER_SRCS
browser/browser_window_osr_gtk.cc
browser/browser_window_osr_gtk.h
browser/browser_window_std_gtk.cc
browser/browser_window_std_gtk.h
browser/dialog_handler_gtk.cc
browser/dialog_handler_gtk.h
browser/main_context_impl_posix.cc
browser/print_handler_gtk.cc
browser/print_handler_gtk.h
browser/resource_util_linux.cc
browser/resource_util_posix.cc
browser/root_window_gtk.cc
browser/root_window_gtk.h
browser/temp_window_x11.cc
browser/temp_window_x11.h
browser/window_test_gtk.cc
)
source_group(cefclient\\\\browser FILES ${CEFCLIENT_LINUX_BROWSER_SRCS})
set(CEFCLIENT_LINUX_SRCS
${CEFCLIENT_LINUX_SRCS}
${CEFCLIENT_LINUX_BROWSER_SRCS}
)
#cefclient Mac OS X sources
set(CEFCLIENT_MACOSX_SRCS
cefclient_mac.mm
)
source_group(cefclient FILES ${CEFCLIENT_MACOSX_SRCS})
set(CEFCLIENT_MACOSX_BROWSER_SRCS
browser/browser_window_osr_mac.h
browser/browser_window_osr_mac.mm
browser/browser_window_std_mac.h
browser/browser_window_std_mac.mm
browser/main_context_impl_posix.cc
browser/resource_util_mac.mm
browser/resource_util_posix.cc
browser/root_window_mac.h
browser/root_window_mac.mm
browser/temp_window_mac.h
browser/temp_window_mac.mm
browser/window_test_mac.mm
)
source_group(cefclient\\\\browser FILES ${CEFCLIENT_MACOSX_BROWSER_SRCS})
set(CEFCLIENT_MACOSX_SRCS
${CEFCLIENT_MACOSX_SRCS}
${CEFCLIENT_MACOSX_BROWSER_SRCS}
)
# cefclient Mac OS X helper sources.
set(CEFCLIENT_HELPER_SRCS
process_helper_mac.cc
)
source_group(cefclient FILES ${CEFCLIENT_HELPER_SRCS})
set(CEFCLIENT_MACOSX_HELPER_SRCS
${CEFCLIENT_HELPER_SRCS}
)
#cefclient Windows sources
set(CEFCLIENT_WINDOWS_SRCS
cefclient_win.cc
)
source_group(cefclient FILES ${CEFCLIENT_WINDOWS_SRCS})
set(CEFCLIENT_WINDOWS_BROWSER_SRCS
browser/browser_window_osr_win.cc
browser/browser_window_osr_win.h
browser/browser_window_std_win.cc
browser/browser_window_std_win.h
browser/main_context_impl_win.cc
browser/main_message_loop_multithreaded_win.cc
browser/main_message_loop_multithreaded_win.h
browser/osr_dragdrop_win.cc
browser/osr_dragdrop_win.h
browser/osr_window_win.cc
browser/osr_window_win.h
browser/resource_util_win.cc
browser/root_window_win.cc
browser/root_window_win.h
browser/temp_window_win.cc
browser/temp_window_win.h
browser/util_win.cc
browser/util_win.h
browser/window_test_win.cc
)
source_group(cefclient\\\\browser FILES ${CEFCLIENT_WINDOWS_BROWSER_SRCS})
set(CEFCLIENT_WINDOWS_RESOURCES_WIN_SRCS
resources/win/cefclient.exe.manifest
resources/win/cefclient.ico
resources/win/cefclient.rc
resources/win/small.ico
)
source_group(cefclient\\\\resources\\\\win FILES ${CEFCLIENT_WINDOWS_RESOURCES_WIN_SRCS})
set(CEFCLIENT_WINDOWS_SRCS
${CEFCLIENT_WINDOWS_SRCS}
${CEFCLIENT_WINDOWS_BROWSER_SRCS}
${CEFCLIENT_WINDOWS_RESOURCES_WIN_SRCS}
)
# cefclient resources.
set(CEFCLIENT_RESOURCES_RESOURCES_SRCS
resources/binding.html
resources/dialogs.html
resources/localstorage.html
resources/logo.png
resources/osr_test.html
resources/other_tests.html
resources/pdf.html
resources/pdf.pdf
resources/performance.html
resources/performance2.html
resources/transparency.html
resources/urlrequest.html
resources/window.html
resources/xmlhttprequest.html
)
source_group(cefclient\\\\resources FILES ${CEFCLIENT_RESOURCES_RESOURCES_SRCS})
set(CEFCLIENT_RESOURCES_RESOURCES_MAC_SRCS_MACOSX
resources/mac/Info.plist
resources/mac/cefclient.icns
)
APPEND_PLATFORM_SOURCES(CEFCLIENT_RESOURCES_RESOURCES_MAC_SRCS)
source_group(cefclient\\\\resources\\\\mac FILES ${CEFCLIENT_RESOURCES_RESOURCES_MAC_SRCS})
set(CEFCLIENT_RESOURCES_RESOURCES_MAC_ENGLISH_LPROJ_SRCS_MACOSX
resources/mac/English.lproj/InfoPlist.strings
resources/mac/English.lproj/MainMenu.xib
)
APPEND_PLATFORM_SOURCES(CEFCLIENT_RESOURCES_RESOURCES_MAC_ENGLISH_LPROJ_SRCS)
source_group(cefclient\\\\resources\\\\mac\\\\English.lproj FILES ${CEFCLIENT_RESOURCES_RESOURCES_MAC_ENGLISH_LPROJ_SRCS})
set(CEFCLIENT_RESOURCES_SRCS
${CEFCLIENT_RESOURCES_RESOURCES_SRCS}
${CEFCLIENT_RESOURCES_RESOURCES_MAC_SRCS}
${CEFCLIENT_RESOURCES_RESOURCES_MAC_ENGLISH_LPROJ_SRCS}
)
#
# Shared configuration.
#
# Target executable names.
set(CEF_TARGET "cefclient")
if(OS_MACOSX)
set(CEF_HELPER_TARGET "cefclient Helper")
endif()
# Logical target used to link the libcef library.
ADD_LOGICAL_TARGET("libcef_lib" "${CEF_LIB_DEBUG}" "${CEF_LIB_RELEASE}")
# Determine the target output directory.
SET_CEF_TARGET_OUT_DIR()
#
# Linux configuration.
#
if(OS_LINUX)
# All sources required by the "cefclient" target. Generates an executable that
# is used for all processes.
set(CEFCLIENT_SRCS
${CEFCLIENT_BROWSER_SRCS}
${CEFCLIENT_COMMON_SRCS}
${CEFCLIENT_RENDERER_SRCS}
${CEFCLIENT_RESOURCES_SRCS}
${CEFCLIENT_LINUX_SRCS}
)
# Find required libraries and update compiler/linker variables.
FIND_LINUX_LIBRARIES("gmodule-2.0 gtk+-2.0 gthread-2.0 gtk+-unix-print-2.0 gtkglext-1.0")
# Executable target.
add_executable(${CEF_TARGET} ${CEFCLIENT_SRCS})
add_dependencies(${CEF_TARGET} libcef_dll_wrapper)
target_link_libraries(${CEF_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS})
# Set rpath so that libraries can be placed next to the executable.
set_target_properties(${CEF_TARGET} PROPERTIES INSTALL_RPATH "$ORIGIN")
set_target_properties(${CEF_TARGET} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE)
set_target_properties(${CEF_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CEF_TARGET_OUT_DIR})
# Copy CEF binary and resource files to the target output directory.
COPY_FILES("${CEF_TARGET}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CEF_TARGET_OUT_DIR}")
COPY_FILES("${CEF_TARGET}" "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CEF_TARGET_OUT_DIR}")
# Copy cefclient resource files to the target output directory.
COPY_FILES("${CEF_TARGET}" "${CEFCLIENT_RESOURCES_SRCS}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CEF_TARGET_OUT_DIR}")
# Rename the "res" directory to "files".
RENAME_DIRECTORY("${CEF_TARGET}" "${CEF_TARGET_OUT_DIR}/resources" "${CEF_TARGET_OUT_DIR}/files")
# Set SUID permissions on the chrome-sandbox target.
SET_LINUX_SUID_PERMISSIONS("${CEF_TARGET}" "${CEF_TARGET_OUT_DIR}/chrome-sandbox")
endif()
#
# Mac OS X configuration.
#
if(OS_MACOSX)
# All sources required by the "cefclient" target. Generates an app bundle that
# is used only for the browser process.
set(CEFCLIENT_SRCS
${CEFCLIENT_BROWSER_SRCS}
${CEFCLIENT_COMMON_SRCS}
${CEFCLIENT_RESOURCES_SRCS}
${CEFCLIENT_MACOSX_SRCS}
)
# All sources required by the "cefclient Helper" target. Generates an app
# bundle that is used only for non-browser processes.
set(CEFCLIENT_HELPER_SRCS
${CEFCLIENT_COMMON_SRCS}
${CEFCLIENT_RENDERER_SRCS}
${CEFCLIENT_MACOSX_HELPER_SRCS}
)
# Output paths for the app bundles.
set(CEF_APP "${CEF_TARGET_OUT_DIR}/${CEF_TARGET}.app")
set(CEF_HELPER_APP "${CEF_TARGET_OUT_DIR}/${CEF_HELPER_TARGET}.app")
# Variable referenced from Info.plist files.
set(PRODUCT_NAME "${CEF_TARGET}")
# Helper executable target.
add_executable(${CEF_HELPER_TARGET} MACOSX_BUNDLE ${CEFCLIENT_HELPER_SRCS})
add_dependencies(${CEF_HELPER_TARGET} libcef_dll_wrapper)
target_link_libraries(${CEF_HELPER_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS})
set_target_properties(${CEF_HELPER_TARGET} PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/resources/mac/helper-Info.plist
)
# Fix the framework link in the helper executable.
FIX_MACOSX_HELPER_FRAMEWORK_LINK(${CEF_HELPER_TARGET} ${CEF_HELPER_APP})
# Main executable target.
add_executable(${CEF_TARGET} MACOSX_BUNDLE ${CEFCLIENT_RESOURCES_SRCS} ${CEFCLIENT_SRCS})
add_dependencies(${CEF_TARGET} libcef_dll_wrapper "${CEF_HELPER_TARGET}")
target_link_libraries(${CEF_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS} "-framework OpenGL")
set_target_properties(${CEF_TARGET} PROPERTIES
RESOURCE "${CEFCLIENT_RESOURCES_SRCS}"
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/resources/mac/Info.plist
)
# Copy files into the main app bundle.
add_custom_command(
TARGET ${CEF_TARGET}
POST_BUILD
# Copy the helper app bundle into the Frameworks directory.
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CEF_HELPER_APP}"
"${CEF_APP}/Contents/Frameworks/${CEF_HELPER_TARGET}.app"
# Copy the CEF framework into the Frameworks directory.
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CEF_BINARY_DIR}/Chromium Embedded Framework.framework"
"${CEF_APP}/Contents/Frameworks/Chromium Embedded Framework.framework"
VERBATIM
)
# Fix the framework link in the main executable.
FIX_MACOSX_MAIN_FRAMEWORK_LINK(${CEF_TARGET} ${CEF_APP})
# Make the other helper app bundles.
MAKE_MACOSX_HELPERS(${CEF_TARGET} ${CEF_APP})
if(NOT ${CMAKE_GENERATOR} STREQUAL "Xcode")
# Manually process and copy over resource files.
# The Xcode generator handles this via the set_target_properties RESOURCE directive.
set(PREFIXES "resources/mac/" "resources/") # Remove these prefixes from input file paths.
COPY_MACOSX_RESOURCES("${CEFCLIENT_RESOURCES_SRCS}" "${PREFIXES}" "${CEF_TARGET}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CEF_APP}")
endif()
endif()
#
# Windows configuration.
#
if(OS_WINDOWS)
# All sources required by the "cefclient" target. Generates an executable that
# is used for all processes.
set(CEFCLIENT_SRCS
${CEFCLIENT_BROWSER_SRCS}
${CEFCLIENT_COMMON_SRCS}
${CEFCLIENT_RENDERER_SRCS}
${CEFCLIENT_RESOURCES_SRCS}
${CEFCLIENT_WINDOWS_SRCS}
)
# Executable target.
add_executable(${CEF_TARGET} WIN32 ${CEFCLIENT_SRCS})
add_dependencies(${CEF_TARGET} libcef_dll_wrapper)
target_link_libraries(${CEF_TARGET} libcef_lib libcef_dll_wrapper ${CEF_STANDARD_LIBS} "glu32.lib" "opengl32.lib")
if(USE_SANDBOX)
# Logical target used to link the cef_sandbox library.
ADD_LOGICAL_TARGET("cef_sandbox_lib" "${CEF_SANDBOX_LIB_DEBUG}" "${CEF_SANDBOX_LIB_RELEASE}")
target_link_libraries(${CEF_TARGET} cef_sandbox_lib ${CEF_SANDBOX_STANDARD_LIBS})
endif()
# Add the custom manifest files to the executable.
ADD_WINDOWS_MANIFEST("${CMAKE_CURRENT_SOURCE_DIR}/resources/win" "${CEF_TARGET}")
# Copy CEF binary and resource files to the target output directory.
COPY_FILES("${CEF_TARGET}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CEF_TARGET_OUT_DIR}")
COPY_FILES("${CEF_TARGET}" "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CEF_TARGET_OUT_DIR}")
endif()

View File

@ -0,0 +1,57 @@
// Copyright (c) 2012 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 "cefclient/browser/binding_test.h"
#include <algorithm>
#include <string>
#include "include/wrapper/cef_stream_resource_handler.h"
namespace client {
namespace binding_test {
namespace {
const char kTestUrl[] = "http://tests/binding";
const char kTestMessageName[] = "BindingTest";
// Handle messages in the browser process.
class Handler : public CefMessageRouterBrowserSide::Handler {
public:
Handler() {}
// Called due to cefQuery execution in binding.html.
virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int64 query_id,
const CefString& request,
bool persistent,
CefRefPtr<Callback> callback) OVERRIDE {
// Only handle messages from the test URL.
const std::string& url = frame->GetURL();
if (url.find(kTestUrl) != 0)
return false;
const std::string& message_name = request;
if (message_name.find(kTestMessageName) == 0) {
// Reverse the string and return.
std::string result = message_name.substr(sizeof(kTestMessageName));
std::reverse(result.begin(), result.end());
callback->Success(result);
return true;
}
return false;
}
};
} // namespace
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
handlers.insert(new Handler());
}
} // namespace binding_test
} // namespace client

View File

@ -0,0 +1,20 @@
// Copyright (c) 2012 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_BINDING_TEST_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_BINDING_TEST_H_
#pragma once
#include "cefclient/browser/test_runner.h"
namespace client {
namespace binding_test {
// Create message handlers. Called from test_runner.cc.
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers);
} // namespace binding_test
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_BINDING_TEST_H_

View File

@ -0,0 +1,89 @@
// 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 "cefclient/browser/browser_window.h"
#include "include/base/cef_bind.h"
#include "cefclient/browser/main_message_loop.h"
namespace client {
BrowserWindow::BrowserWindow(Delegate* delegate)
: delegate_(delegate),
is_closing_(false) {
DCHECK(delegate_);
}
void BrowserWindow::SetDeviceScaleFactor(float device_scale_factor) {
}
float BrowserWindow::GetDeviceScaleFactor() const {
return 1.0f;
}
CefRefPtr<CefBrowser> BrowserWindow::GetBrowser() const {
REQUIRE_MAIN_THREAD();
return browser_;
}
bool BrowserWindow::IsClosing() const {
REQUIRE_MAIN_THREAD();
return is_closing_;
}
void BrowserWindow::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
REQUIRE_MAIN_THREAD();
DCHECK(!browser_);
browser_ = browser;
delegate_->OnBrowserCreated(browser);
}
void BrowserWindow::OnBrowserClosing(CefRefPtr<CefBrowser> browser) {
REQUIRE_MAIN_THREAD();
DCHECK_EQ(browser->GetIdentifier(), browser_->GetIdentifier());
is_closing_ = true;
}
void BrowserWindow::OnBrowserClosed(CefRefPtr<CefBrowser> browser) {
REQUIRE_MAIN_THREAD();
DCHECK_EQ(browser->GetIdentifier(), browser_->GetIdentifier());
browser_ = NULL;
client_handler_->DetachDelegate();
client_handler_ = NULL;
// |this| may be deleted.
delegate_->OnBrowserWindowDestroyed();
}
void BrowserWindow::OnSetAddress(const std::string& url) {
REQUIRE_MAIN_THREAD();
delegate_->OnSetAddress(url);
}
void BrowserWindow::OnSetTitle(const std::string& title) {
REQUIRE_MAIN_THREAD();
delegate_->OnSetTitle(title);
}
void BrowserWindow::OnSetFullscreen(bool fullscreen) {
REQUIRE_MAIN_THREAD();
delegate_->OnSetFullscreen(fullscreen);
}
void BrowserWindow::OnSetLoadingState(bool isLoading,
bool canGoBack,
bool canGoForward) {
REQUIRE_MAIN_THREAD();
delegate_->OnSetLoadingState(isLoading, canGoBack, canGoForward);
}
void BrowserWindow::OnSetDraggableRegions(
const std::vector<CefDraggableRegion>& regions) {
REQUIRE_MAIN_THREAD();
delegate_->OnSetDraggableRegions(regions);
}
} // namespace client

View File

@ -0,0 +1,134 @@
// 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_BROWSER_WINDOW_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_H_
#pragma once
#include "include/base/cef_scoped_ptr.h"
#include "include/cef_browser.h"
#include "cefclient/browser/client_handler.h"
#include "cefclient/browser/client_types.h"
namespace client {
// Represents a native child window hosting a single browser instance. The
// methods of this class must be called on the main thread unless otherwise
// indicated.
class BrowserWindow : public ClientHandler::Delegate {
public:
// This interface is implemented by the owner of the BrowserWindow. The
// methods of this class will be called on the main thread.
class Delegate {
public:
// Called when the browser has been created.
virtual void OnBrowserCreated(CefRefPtr<CefBrowser> browser) = 0;
// Called when the BrowserWindow has been destroyed.
virtual void OnBrowserWindowDestroyed() = 0;
// Set the window URL address.
virtual void OnSetAddress(const std::string& url) = 0;
// Set the window title.
virtual void OnSetTitle(const std::string& title) = 0;
// Set fullscreen mode.
virtual void OnSetFullscreen(bool fullscreen) = 0;
// Set the loading state.
virtual void OnSetLoadingState(bool isLoading,
bool canGoBack,
bool canGoForward) = 0;
// Set the draggable regions.
virtual void OnSetDraggableRegions(
const std::vector<CefDraggableRegion>& regions) = 0;
protected:
virtual ~Delegate() {}
};
// Create a new browser and native window.
virtual void CreateBrowser(ClientWindowHandle parent_handle,
const CefRect& rect,
const CefBrowserSettings& settings,
CefRefPtr<CefRequestContext> request_context) = 0;
// Retrieve the configuration that will be used when creating a popup window.
// The popup browser will initially be parented to |temp_handle| which should
// be a pre-existing hidden window. The native window will be created later
// after the browser has been created. This method may be called on any
// thread.
virtual void GetPopupConfig(CefWindowHandle temp_handle,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) = 0;
// Show the popup window with correct parent and bounds in parent coordinates.
virtual void ShowPopup(ClientWindowHandle parent_handle,
int x, int y, size_t width, size_t height) = 0;
// Show the window.
virtual void Show() = 0;
// Hide the window.
virtual void Hide() = 0;
// Set the window bounds in parent coordinates.
virtual void SetBounds(int x, int y, size_t width, size_t height) = 0;
// Set focus to the window.
virtual void SetFocus(bool focus) = 0;
// Set the device scale factor. Only used in combination with off-screen
// rendering.
virtual void SetDeviceScaleFactor(float device_scale_factor);
// Returns the device scale factor. Only used in combination with off-screen
// rendering.
virtual float GetDeviceScaleFactor() const;
// Returns the window handle.
virtual ClientWindowHandle GetWindowHandle() const = 0;
// Returns the browser owned by the window.
CefRefPtr<CefBrowser> GetBrowser() const;
// Returns true if the browser is closing.
bool IsClosing() const;
protected:
// Allow deletion via scoped_ptr only.
friend struct base::DefaultDeleter<BrowserWindow>;
// Constructor may be called on any thread.
// |delegate| must outlive this object.
explicit BrowserWindow(Delegate* delegate);
// ClientHandler::Delegate methods.
void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
void OnBrowserClosing(CefRefPtr<CefBrowser> browser) OVERRIDE;
void OnBrowserClosed(CefRefPtr<CefBrowser> browser) OVERRIDE;
void OnSetAddress(const std::string& url) OVERRIDE;
void OnSetTitle(const std::string& title) OVERRIDE;
void OnSetFullscreen(bool fullscreen) OVERRIDE;
void OnSetLoadingState(bool isLoading,
bool canGoBack,
bool canGoForward) OVERRIDE;
void OnSetDraggableRegions(
const std::vector<CefDraggableRegion>& regions) OVERRIDE;
Delegate* delegate_;
CefRefPtr<CefBrowser> browser_;
CefRefPtr<ClientHandler> client_handler_;
bool is_closing_;
private:
DISALLOW_COPY_AND_ASSIGN(BrowserWindow);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_H_

View File

@ -0,0 +1,127 @@
// 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_BROWSER_WINDOW_OSR_GTK_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_OSR_GTK_H_
#pragma once
#include "cefclient/browser/browser_window.h"
#include "cefclient/browser/client_handler_osr.h"
#include "cefclient/browser/osr_renderer.h"
namespace client {
// Represents a native child window hosting a single off-screen browser
// instance. The methods of this class must be called on the main thread unless
// otherwise indicated.
class BrowserWindowOsrGtk : public BrowserWindow,
public ClientHandlerOsr::OsrDelegate {
public:
// Constructor may be called on any thread.
// |delegate| must outlive this object.
BrowserWindowOsrGtk(BrowserWindow::Delegate* delegate,
const std::string& startup_url,
const OsrRenderer::Settings& settings);
// BrowserWindow methods.
void CreateBrowser(ClientWindowHandle parent_handle,
const CefRect& rect,
const CefBrowserSettings& settings,
CefRefPtr<CefRequestContext> request_context) OVERRIDE;
void GetPopupConfig(CefWindowHandle temp_handle,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) OVERRIDE;
void ShowPopup(ClientWindowHandle parent_handle,
int x, int y, size_t width, size_t height) OVERRIDE;
void Show() OVERRIDE;
void Hide() OVERRIDE;
void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
void SetFocus(bool focus) OVERRIDE;
void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE;
float GetDeviceScaleFactor() const OVERRIDE;
ClientWindowHandle GetWindowHandle() const OVERRIDE;
// ClientHandlerOsr::OsrDelegate methods.
void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
bool GetRootScreenRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) OVERRIDE;
bool GetViewRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) OVERRIDE;
bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
int viewX,
int viewY,
int& screenX,
int& screenY) OVERRIDE;
bool GetScreenInfo(CefRefPtr<CefBrowser> browser,
CefScreenInfo& screen_info) OVERRIDE;
void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) OVERRIDE;
void OnPopupSize(CefRefPtr<CefBrowser> browser,
const CefRect& rect) OVERRIDE;
void OnPaint(CefRefPtr<CefBrowser> browser,
CefRenderHandler::PaintElementType type,
const CefRenderHandler::RectList& dirtyRects,
const void* buffer,
int width,
int height) OVERRIDE;
void OnCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor,
CefRenderHandler::CursorType type,
const CefCursorInfo& custom_cursor_info) OVERRIDE;
bool StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
int x, int y) OVERRIDE;
void UpdateDragCursor(CefRefPtr<CefBrowser> browser,
CefRenderHandler::DragOperation operation) OVERRIDE;
private:
// Create the GTK GlArea.
void Create(ClientWindowHandle parent_handle);
// Signal handlers for the GTK GlArea.
static gint SizeAllocation(GtkWidget* widget,
GtkAllocation* allocation,
BrowserWindowOsrGtk* self);
static gint ClickEvent(GtkWidget* widget,
GdkEventButton* event,
BrowserWindowOsrGtk* self);
static gint KeyEvent(GtkWidget* widget,
GdkEventKey* event,
BrowserWindowOsrGtk* self);
static gint MoveEvent(GtkWidget* widget,
GdkEventMotion* event,
BrowserWindowOsrGtk* self);
static gint ScrollEvent(GtkWidget* widget,
GdkEventScroll* event,
BrowserWindowOsrGtk* self);
static gint FocusEvent(GtkWidget* widget,
GdkEventFocus* event,
BrowserWindowOsrGtk* self);
bool IsOverPopupWidget(int x, int y) const;
int GetPopupXOffset() const;
int GetPopupYOffset() const;
void ApplyPopupOffset(int& x, int& y) const;
void EnableGL();
void DisableGL();
// The below members will only be accessed on the main thread which should be
// the same as the CEF UI thread.
OsrRenderer renderer_;
ClientWindowHandle glarea_;
bool hidden_;
bool gl_enabled_;
bool painting_popup_;
float device_scale_factor_;
DISALLOW_COPY_AND_ASSIGN(BrowserWindowOsrGtk);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_OSR_GTK_H_

View File

@ -0,0 +1,179 @@
// 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 "cefclient/browser/browser_window_std_gtk.h"
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <X11/Xlib.h>
#undef Success // Definition conflicts with cef_message_router.h
#undef RootWindow // Definition conflicts with root_window.h
#include "include/base/cef_logging.h"
#include "cefclient/browser/client_handler_std.h"
#include "cefclient/browser/main_message_loop.h"
namespace client {
namespace {
::Window GetXWindowForWidget(GtkWidget* widget) {
// The GTK window must be visible before we can retrieve the XID.
::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(widget));
DCHECK(xwindow);
return xwindow;
}
void SetXWindowVisible(::Window xwindow, bool visible) {
::Display* xdisplay = cef_get_xdisplay();
// Retrieve the atoms required by the below XChangeProperty call.
const char* kAtoms[] = {
"_NET_WM_STATE",
"ATOM",
"_NET_WM_STATE_HIDDEN"
};
Atom atoms[3];
int result = XInternAtoms(xdisplay, const_cast<char**>(kAtoms), 3, false,
atoms);
if (!result)
NOTREACHED();
if (!visible) {
// Set the hidden property state value.
scoped_ptr<Atom[]> data(new Atom[1]);
data[0] = atoms[2];
XChangeProperty(xdisplay,
xwindow,
atoms[0], // name
atoms[1], // type
32, // size in bits of items in 'value'
PropModeReplace,
reinterpret_cast<const unsigned char*>(data.get()),
1); // num items
} else {
// Set an empty array of property state values.
XChangeProperty(xdisplay,
xwindow,
atoms[0], // name
atoms[1], // type
32, // size in bits of items in 'value'
PropModeReplace,
NULL,
0); // num items
}
}
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<int>(width);
changes.height = static_cast<int>(height);
XConfigureWindow(xdisplay, xwindow,
CWX | CWY | CWHeight | CWWidth, &changes);
}
} // namespace
BrowserWindowStdGtk::BrowserWindowStdGtk(Delegate* delegate,
const std::string& startup_url)
: BrowserWindow(delegate) {
client_handler_ = new ClientHandlerStd(this, startup_url);
}
void BrowserWindowStdGtk::CreateBrowser(
ClientWindowHandle parent_handle,
const CefRect& rect,
const CefBrowserSettings& settings,
CefRefPtr<CefRequestContext> request_context) {
REQUIRE_MAIN_THREAD();
CefWindowInfo window_info;
window_info.SetAsChild(GetXWindowForWidget(parent_handle), rect);
CefBrowserHost::CreateBrowser(window_info, client_handler_,
client_handler_->startup_url(),
settings, request_context);
}
void BrowserWindowStdGtk::GetPopupConfig(CefWindowHandle temp_handle,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) {
// Note: This method may be called on any thread.
// The window will be properly sized after the browser is created.
windowInfo.SetAsChild(temp_handle, CefRect());
client = client_handler_;
}
void BrowserWindowStdGtk::ShowPopup(ClientWindowHandle parent_handle,
int x, int y, size_t width, size_t height) {
REQUIRE_MAIN_THREAD();
if (browser_) {
::Window parent_xwindow = GetXWindowForWidget(parent_handle);
::Display* xdisplay = cef_get_xdisplay();
::Window xwindow = browser_->GetHost()->GetWindowHandle();
DCHECK(xwindow);
XReparentWindow(xdisplay, xwindow, parent_xwindow, x, y);
SetXWindowBounds(xwindow, x, y, width, height);
SetXWindowVisible(xwindow, true);
}
}
void BrowserWindowStdGtk::Show() {
REQUIRE_MAIN_THREAD();
if (browser_) {
::Window xwindow = browser_->GetHost()->GetWindowHandle();
DCHECK(xwindow);
SetXWindowVisible(xwindow, true);
}
}
void BrowserWindowStdGtk::Hide() {
REQUIRE_MAIN_THREAD();
if (browser_) {
::Window xwindow = browser_->GetHost()->GetWindowHandle();
DCHECK(xwindow);
SetXWindowVisible(xwindow, false);
}
}
void BrowserWindowStdGtk::SetBounds(int x, int y, size_t width, size_t height) {
REQUIRE_MAIN_THREAD();
if (browser_) {
::Window xwindow = browser_->GetHost()->GetWindowHandle();
DCHECK(xwindow);
SetXWindowBounds(xwindow, x, y, width, height);
}
}
void BrowserWindowStdGtk::SetFocus(bool focus) {
REQUIRE_MAIN_THREAD();
if (browser_)
browser_->GetHost()->SetFocus(focus);
}
ClientWindowHandle BrowserWindowStdGtk::GetWindowHandle() const {
REQUIRE_MAIN_THREAD();
// There is no GtkWidget* representation of this object.
NOTREACHED();
return NULL;
}
} // namespace client

View File

@ -0,0 +1,46 @@
// 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_BROWSER_WINDOW_STD_GTK_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_STD_GTK_H_
#pragma once
#include "cefclient/browser/browser_window.h"
namespace client {
// Represents a native child window hosting a single windowed browser instance.
// The methods of this class must be called on the main thread unless otherwise
// indicated.
class BrowserWindowStdGtk : public BrowserWindow {
public:
// Constructor may be called on any thread.
// |delegate| must outlive this object.
BrowserWindowStdGtk(Delegate* delegate,
const std::string& startup_url);
// BrowserWindow methods.
void CreateBrowser(ClientWindowHandle parent_handle,
const CefRect& rect,
const CefBrowserSettings& settings,
CefRefPtr<CefRequestContext> request_context) OVERRIDE;
void GetPopupConfig(CefWindowHandle temp_handle,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) OVERRIDE;
void ShowPopup(ClientWindowHandle parent_handle,
int x, int y, size_t width, size_t height) OVERRIDE;
void Show() OVERRIDE;
void Hide() OVERRIDE;
void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
void SetFocus(bool focus) OVERRIDE;
ClientWindowHandle GetWindowHandle() const OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(BrowserWindowStdGtk);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_STD_GTK_H_

View File

@ -0,0 +1,98 @@
// 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.
#include "cefclient/browser/bytes_write_handler.h"
#include <cstdio>
#include <cstdlib>
#include "include/wrapper/cef_helpers.h"
namespace client {
BytesWriteHandler::BytesWriteHandler(size_t grow)
: grow_(grow),
datasize_(grow),
offset_(0) {
DCHECK_GT(grow, 0U);
data_ = malloc(grow);
DCHECK(data_ != NULL);
}
BytesWriteHandler::~BytesWriteHandler() {
if (data_)
free(data_);
}
size_t BytesWriteHandler::Write(const void* ptr, size_t size, size_t n) {
base::AutoLock lock_scope(lock_);
size_t rv;
if (offset_ + static_cast<int64>(size * n) >= datasize_ &&
Grow(size * n) == 0) {
rv = 0;
} else {
memcpy(reinterpret_cast<char*>(data_) + offset_, ptr, size * n);
offset_ += size * n;
rv = n;
}
return rv;
}
int BytesWriteHandler::Seek(int64 offset, int whence) {
int rv = -1L;
base::AutoLock lock_scope(lock_);
switch (whence) {
case SEEK_CUR:
if (offset_ + offset > datasize_ || offset_ + offset < 0)
break;
offset_ += offset;
rv = 0;
break;
case SEEK_END: {
int64 offset_abs = std::abs(offset);
if (offset_abs > datasize_)
break;
offset_ = datasize_ - offset_abs;
rv = 0;
break;
}
case SEEK_SET:
if (offset > datasize_ || offset < 0)
break;
offset_ = offset;
rv = 0;
break;
}
return rv;
}
int64 BytesWriteHandler::Tell() {
base::AutoLock lock_scope(lock_);
return offset_;
}
int BytesWriteHandler::Flush() {
return 0;
}
size_t BytesWriteHandler::Grow(size_t size) {
base::AutoLock lock_scope(lock_);
size_t rv;
size_t s = (size > grow_ ? size : grow_);
void* tmp = realloc(data_, datasize_ + s);
DCHECK(tmp != NULL);
if (tmp) {
data_ = tmp;
datasize_ += s;
rv = datasize_;
} else {
rv = 0;
}
return rv;
}
} // namespace client

View File

@ -0,0 +1,44 @@
// 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.
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_BYTES_WRITE_HANDLER_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_BYTES_WRITE_HANDLER_H_
#pragma once
#include "include/base/cef_lock.h"
#include "include/cef_stream.h"
namespace client {
class BytesWriteHandler : public CefWriteHandler {
public:
explicit BytesWriteHandler(size_t grow);
~BytesWriteHandler();
size_t Write(const void* ptr, size_t size, size_t n) OVERRIDE;
int Seek(int64 offset, int whence) OVERRIDE;
int64 Tell() OVERRIDE;
int Flush() OVERRIDE;
bool MayBlock() OVERRIDE { return false; }
void* GetData() { return data_; }
int64 GetDataSize() { return offset_; }
private:
size_t Grow(size_t size);
size_t grow_;
void* data_;
int64 datasize_;
int64 offset_;
base::Lock lock_;
IMPLEMENT_REFCOUNTING(BytesWriteHandler);
DISALLOW_COPY_AND_ASSIGN(BytesWriteHandler);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_BYTES_WRITE_HANDLER_H_

View File

@ -0,0 +1,82 @@
// Copyright (c) 2013 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 "cefclient/browser/client_app_browser.h"
#include "include/base/cef_logging.h"
#include "include/cef_cookie.h"
#include "cefclient/common/client_switches.h"
namespace client {
ClientAppBrowser::ClientAppBrowser() {
}
void ClientAppBrowser::OnBeforeCommandLineProcessing(
const CefString& process_type,
CefRefPtr<CefCommandLine> command_line) {
// Pass additional command-line flags to the browser process.
if (process_type.empty()) {
// Pass additional command-line flags when off-screen rendering is enabled.
if (command_line->HasSwitch(switches::kOffScreenRenderingEnabled)) {
// If the PDF extension is enabled then cc Surfaces must be disabled for
// PDFs to render correctly.
// See https://bitbucket.org/chromiumembedded/cef/issues/1689 for details.
if (!command_line->HasSwitch("disable-extensions") &&
!command_line->HasSwitch("disable-pdf-extension")) {
command_line->AppendSwitch("disable-surfaces");
}
// Use software rendering and compositing (disable GPU) for increased FPS
// and decreased CPU usage. This will also disable WebGL so remove these
// switches if you need that capability.
// See https://bitbucket.org/chromiumembedded/cef/issues/1257 for details.
if (!command_line->HasSwitch(switches::kEnableGPU)) {
command_line->AppendSwitch("disable-gpu");
command_line->AppendSwitch("disable-gpu-compositing");
}
// Synchronize the frame rate between all processes. This results in
// decreased CPU usage by avoiding the generation of extra frames that
// would otherwise be discarded. The frame rate can be set at browser
// creation time via CefBrowserSettings.windowless_frame_rate or changed
// dynamically using CefBrowserHost::SetWindowlessFrameRate. In cefclient
// it can be set via the command-line using `--off-screen-frame-rate=XX`.
// See https://bitbucket.org/chromiumembedded/cef/issues/1368 for details.
command_line->AppendSwitch("enable-begin-frame-scheduling");
}
}
}
void ClientAppBrowser::OnContextInitialized() {
CreateDelegates(delegates_);
// Register cookieable schemes with the global cookie manager.
CefRefPtr<CefCookieManager> manager =
CefCookieManager::GetGlobalManager(NULL);
DCHECK(manager.get());
manager->SetSupportedSchemes(cookieable_schemes_, NULL);
print_handler_ = CreatePrintHandler();
DelegateSet::iterator it = delegates_.begin();
for (; it != delegates_.end(); ++it)
(*it)->OnContextInitialized(this);
}
void ClientAppBrowser::OnBeforeChildProcessLaunch(
CefRefPtr<CefCommandLine> command_line) {
DelegateSet::iterator it = delegates_.begin();
for (; it != delegates_.end(); ++it)
(*it)->OnBeforeChildProcessLaunch(this, command_line);
}
void ClientAppBrowser::OnRenderProcessThreadCreated(
CefRefPtr<CefListValue> extra_info) {
DelegateSet::iterator it = delegates_.begin();
for (; it != delegates_.end(); ++it)
(*it)->OnRenderProcessThreadCreated(this, extra_info);
}
} // namespace client

View File

@ -0,0 +1,77 @@
// Copyright (c) 2013 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_CLIENT_APP_BROWSER_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_APP_BROWSER_H_
#pragma once
#include <set>
#include "cefclient/common/client_app.h"
namespace client {
// Client app implementation for the browser process.
class ClientAppBrowser : public ClientApp,
public CefBrowserProcessHandler {
public:
// Interface for browser delegates. All Delegates must be returned via
// CreateDelegates. Do not perform work in the Delegate
// constructor. See CefBrowserProcessHandler for documentation.
class Delegate : public virtual CefBase {
public:
virtual void OnContextInitialized(CefRefPtr<ClientApp> app) {}
virtual void OnBeforeChildProcessLaunch(
CefRefPtr<ClientAppBrowser> app,
CefRefPtr<CefCommandLine> command_line) {}
virtual void OnRenderProcessThreadCreated(
CefRefPtr<ClientAppBrowser> app,
CefRefPtr<CefListValue> extra_info) {}
};
typedef std::set<CefRefPtr<Delegate> > DelegateSet;
ClientAppBrowser();
private:
// Creates all of the Delegate objects. Implemented by cefclient in
// client_app_delegates_browser.cc
static void CreateDelegates(DelegateSet& delegates);
// Create the Linux print handler. Implemented by cefclient in
// client_app_delegates_browser.cc
static CefRefPtr<CefPrintHandler> CreatePrintHandler();
// CefApp methods.
void OnBeforeCommandLineProcessing(
const CefString& process_type,
CefRefPtr<CefCommandLine> command_line) OVERRIDE;
CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() OVERRIDE {
return this;
}
// CefBrowserProcessHandler methods.
void OnContextInitialized() OVERRIDE;
void OnBeforeChildProcessLaunch(
CefRefPtr<CefCommandLine> command_line) OVERRIDE;
void OnRenderProcessThreadCreated(
CefRefPtr<CefListValue> extra_info) OVERRIDE;
CefRefPtr<CefPrintHandler> GetPrintHandler() OVERRIDE {
return print_handler_;
}
// Set of supported Delegates.
DelegateSet delegates_;
CefRefPtr<CefPrintHandler> print_handler_;
IMPLEMENT_REFCOUNTING(ClientAppBrowser);
DISALLOW_COPY_AND_ASSIGN(ClientAppBrowser);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_APP_BROWSER_H_

View File

@ -0,0 +1,26 @@
// Copyright (c) 2012 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 "cefclient/browser/client_app_browser.h"
#if defined(OS_LINUX)
#include "cefclient/browser/print_handler_gtk.h"
#endif
namespace client {
// static
void ClientAppBrowser::CreateDelegates(DelegateSet& delegates) {
}
// static
CefRefPtr<CefPrintHandler> ClientAppBrowser::CreatePrintHandler() {
#if defined(OS_LINUX)
return new ClientPrintHandlerGtk();
#else
return NULL;
#endif
}
} // namespace client

View File

@ -0,0 +1,770 @@
// Copyright (c) 2013 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 "cefclient/browser/client_handler.h"
#include <stdio.h>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include "include/base/cef_bind.h"
#include "include/cef_browser.h"
#include "include/cef_frame.h"
#include "include/cef_parser.h"
#include "include/wrapper/cef_closure_task.h"
#include "cefclient/browser/main_context.h"
#include "cefclient/browser/resource_util.h"
#include "cefclient/browser/root_window_manager.h"
#include "cefclient/browser/test_runner.h"
#include "cefclient/common/client_switches.h"
namespace client {
#if defined(OS_WIN)
#define NEWLINE "\r\n"
#else
#define NEWLINE "\n"
#endif
namespace {
// Custom menu command Ids.
enum client_menu_ids {
CLIENT_ID_SHOW_DEVTOOLS = MENU_ID_USER_FIRST,
CLIENT_ID_CLOSE_DEVTOOLS,
CLIENT_ID_INSPECT_ELEMENT,
CLIENT_ID_TESTMENU_SUBMENU,
CLIENT_ID_TESTMENU_CHECKITEM,
CLIENT_ID_TESTMENU_RADIOITEM1,
CLIENT_ID_TESTMENU_RADIOITEM2,
CLIENT_ID_TESTMENU_RADIOITEM3,
};
// Musr match the value in client_renderer.cc.
const char kFocusedNodeChangedMessage[] = "ClientRenderer.FocusedNodeChanged";
std::string GetTimeString(const CefTime& value) {
if (value.GetTimeT() == 0)
return "Unspecified";
static const char* kMonths[] = {
"January", "February", "March", "April", "May", "June", "July", "August",
"September", "October", "November", "December"
};
std::string month;
if (value.month >= 1 && value.month <= 12)
month = kMonths[value.month - 1];
else
month = "Invalid";
std::stringstream ss;
ss << month << " " << value.day_of_month << ", " << value.year << " " <<
std::setfill('0') << std::setw(2) << value.hour << ":" <<
std::setfill('0') << std::setw(2) << value.minute << ":" <<
std::setfill('0') << std::setw(2) << value.second;
return ss.str();
}
std::string GetBinaryString(CefRefPtr<CefBinaryValue> value) {
if (!value.get())
return "&nbsp;";
// Retrieve the value.
const size_t size = value->GetSize();
std::string src;
src.resize(size);
value->GetData(const_cast<char*>(src.data()), size, 0);
// Encode the value.
return CefBase64Encode(src.data(), src.size());
}
// Load a data: URI containing the error message.
void LoadErrorPage(CefRefPtr<CefFrame> frame,
const std::string& failed_url,
cef_errorcode_t error_code,
const std::string& other_info) {
std::stringstream ss;
ss << "<html><head><title>Page failed to load</title></head>"
"<body bgcolor=\"white\">"
"<h3>Page failed to load.</h3>"
"URL: <a href=\"" << failed_url << "\">"<< failed_url << "</a>"
"<br/>Error: " << test_runner::GetErrorString(error_code) <<
" (" << error_code << ")";
if (!other_info.empty())
ss << "<br/>" << other_info;
ss << "</body></html>";
frame->LoadURL(test_runner::GetDataURI(ss.str(), "text/html"));
}
} // namespace
ClientHandler::ClientHandler(Delegate* delegate,
bool is_osr,
const std::string& startup_url)
: is_osr_(is_osr),
startup_url_(startup_url),
delegate_(delegate),
browser_count_(0),
console_log_file_(MainContext::Get()->GetConsoleLogPath()),
first_console_message_(true),
focus_on_editable_field_(false) {
DCHECK(!console_log_file_.empty());
#if defined(OS_LINUX)
// Provide the GTK-based dialog implementation on Linux.
dialog_handler_ = new ClientDialogHandlerGtk();
#endif
resource_manager_ = new CefResourceManager();
test_runner::SetupResourceManager(resource_manager_);
// Read command line settings.
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
mouse_cursor_change_disabled_ =
command_line->HasSwitch(switches::kMouseCursorChangeDisabled);
}
void ClientHandler::DetachDelegate() {
if (!CURRENTLY_ON_MAIN_THREAD()) {
// Execute this method on the main thread.
MAIN_POST_CLOSURE(base::Bind(&ClientHandler::DetachDelegate, this));
return;
}
DCHECK(delegate_);
delegate_ = NULL;
}
bool ClientHandler::OnProcessMessageReceived(
CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) {
CEF_REQUIRE_UI_THREAD();
if (message_router_->OnProcessMessageReceived(browser, source_process,
message)) {
return true;
}
// Check for messages from the client renderer.
std::string message_name = message->GetName();
if (message_name == kFocusedNodeChangedMessage) {
// A message is sent from ClientRenderDelegate to tell us whether the
// currently focused DOM node is editable. Use of |focus_on_editable_field_|
// is redundant with CefKeyEvent.focus_on_editable_field in OnPreKeyEvent
// but is useful for demonstration purposes.
focus_on_editable_field_ = message->GetArgumentList()->GetBool(0);
return true;
}
return false;
}
void ClientHandler::OnBeforeContextMenu(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
CefRefPtr<CefMenuModel> model) {
CEF_REQUIRE_UI_THREAD();
if ((params->GetTypeFlags() & (CM_TYPEFLAG_PAGE | CM_TYPEFLAG_FRAME)) != 0) {
// Add a separator if the menu already has items.
if (model->GetCount() > 0)
model->AddSeparator();
// Add DevTools items to all context menus.
model->AddItem(CLIENT_ID_SHOW_DEVTOOLS, "&Show DevTools");
model->AddItem(CLIENT_ID_CLOSE_DEVTOOLS, "Close DevTools");
model->AddSeparator();
model->AddItem(CLIENT_ID_INSPECT_ELEMENT, "Inspect Element");
// Test context menu features.
BuildTestMenu(model);
}
}
bool ClientHandler::OnContextMenuCommand(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
int command_id,
EventFlags event_flags) {
CEF_REQUIRE_UI_THREAD();
switch (command_id) {
case CLIENT_ID_SHOW_DEVTOOLS:
ShowDevTools(browser, CefPoint());
return true;
case CLIENT_ID_CLOSE_DEVTOOLS:
CloseDevTools(browser);
return true;
case CLIENT_ID_INSPECT_ELEMENT:
ShowDevTools(browser, CefPoint(params->GetXCoord(), params->GetYCoord()));
return true;
default: // Allow default handling, if any.
return ExecuteTestMenu(command_id);
}
}
void ClientHandler::OnAddressChange(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& url) {
CEF_REQUIRE_UI_THREAD();
// Only update the address for the main (top-level) frame.
if (frame->IsMain())
NotifyAddress(url);
}
void ClientHandler::OnTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title) {
CEF_REQUIRE_UI_THREAD();
NotifyTitle(title);
}
void ClientHandler::OnFullscreenModeChange(CefRefPtr<CefBrowser> browser,
bool fullscreen) {
CEF_REQUIRE_UI_THREAD();
NotifyFullscreen(fullscreen);
}
bool ClientHandler::OnConsoleMessage(CefRefPtr<CefBrowser> browser,
const CefString& message,
const CefString& source,
int line) {
CEF_REQUIRE_UI_THREAD();
FILE* file = fopen(console_log_file_.c_str(), "a");
if (file) {
std::stringstream ss;
ss << "Message: " << message.ToString() << NEWLINE <<
"Source: " << source.ToString() << NEWLINE <<
"Line: " << line << NEWLINE <<
"-----------------------" << NEWLINE;
fputs(ss.str().c_str(), file);
fclose(file);
if (first_console_message_) {
test_runner::Alert(
browser, "Console messages written to \"" + console_log_file_ + "\"");
first_console_message_ = false;
}
}
return false;
}
void ClientHandler::OnBeforeDownload(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDownloadItem> download_item,
const CefString& suggested_name,
CefRefPtr<CefBeforeDownloadCallback> callback) {
CEF_REQUIRE_UI_THREAD();
// Continue the download and show the "Save As" dialog.
callback->Continue(MainContext::Get()->GetDownloadPath(suggested_name), true);
}
void ClientHandler::OnDownloadUpdated(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDownloadItem> download_item,
CefRefPtr<CefDownloadItemCallback> callback) {
CEF_REQUIRE_UI_THREAD();
if (download_item->IsComplete()) {
test_runner::Alert(
browser,
"File \"" + download_item->GetFullPath().ToString() +
"\" downloaded successfully.");
}
}
bool ClientHandler::OnDragEnter(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> dragData,
CefDragHandler::DragOperationsMask mask) {
CEF_REQUIRE_UI_THREAD();
// Forbid dragging of link URLs.
if (mask & DRAG_OPERATION_LINK)
return true;
return false;
}
void ClientHandler::OnDraggableRegionsChanged(
CefRefPtr<CefBrowser> browser,
const std::vector<CefDraggableRegion>& regions) {
CEF_REQUIRE_UI_THREAD();
NotifyDraggableRegions(regions);
}
bool ClientHandler::OnRequestGeolocationPermission(
CefRefPtr<CefBrowser> browser,
const CefString& requesting_url,
int request_id,
CefRefPtr<CefGeolocationCallback> callback) {
CEF_REQUIRE_UI_THREAD();
// Allow geolocation access from all websites.
callback->Continue(true);
return true;
}
bool ClientHandler::OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
const CefKeyEvent& event,
CefEventHandle os_event,
bool* is_keyboard_shortcut) {
CEF_REQUIRE_UI_THREAD();
if (!event.focus_on_editable_field && event.windows_key_code == 0x20) {
// Special handling for the space character when an input element does not
// have focus. Handling the event in OnPreKeyEvent() keeps the event from
// being processed in the renderer. If we instead handled the event in the
// OnKeyEvent() method the space key would cause the window to scroll in
// addition to showing the alert box.
if (event.type == KEYEVENT_RAWKEYDOWN)
test_runner::Alert(browser, "You pressed the space bar!");
return true;
}
return false;
}
bool ClientHandler::OnBeforePopup(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& target_url,
const CefString& target_frame_name,
CefLifeSpanHandler::WindowOpenDisposition target_disposition,
bool user_gesture,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings,
bool* no_javascript_access) {
CEF_REQUIRE_IO_THREAD();
// Return true to cancel the popup window.
return !CreatePopupWindow(browser, false, popupFeatures, windowInfo, client,
settings);
}
void ClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();
browser_count_++;
if (!message_router_) {
// Create the browser-side router for query handling.
CefMessageRouterConfig config;
message_router_ = CefMessageRouterBrowserSide::Create(config);
// Register handlers with the router.
test_runner::CreateMessageHandlers(message_handler_set_);
MessageHandlerSet::const_iterator it = message_handler_set_.begin();
for (; it != message_handler_set_.end(); ++it)
message_router_->AddHandler(*(it), false);
}
// Disable mouse cursor change if requested via the command-line flag.
if (mouse_cursor_change_disabled_)
browser->GetHost()->SetMouseCursorChangeDisabled(true);
NotifyBrowserCreated(browser);
}
bool ClientHandler::DoClose(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();
NotifyBrowserClosing(browser);
// Allow the close. For windowed browsers this will result in the OS close
// event being sent.
return false;
}
void ClientHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();
if (--browser_count_ == 0) {
// Remove and delete message router handlers.
MessageHandlerSet::const_iterator it =
message_handler_set_.begin();
for (; it != message_handler_set_.end(); ++it) {
message_router_->RemoveHandler(*(it));
delete *(it);
}
message_handler_set_.clear();
message_router_ = NULL;
}
NotifyBrowserClosed(browser);
}
void ClientHandler::OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
bool isLoading,
bool canGoBack,
bool canGoForward) {
CEF_REQUIRE_UI_THREAD();
NotifyLoadingState(isLoading, canGoBack, canGoForward);
}
void ClientHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) {
CEF_REQUIRE_UI_THREAD();
// Don't display an error for downloaded files.
if (errorCode == ERR_ABORTED)
return;
// Don't display an error for external protocols that we allow the OS to
// handle. See OnProtocolExecution().
if (errorCode == ERR_UNKNOWN_URL_SCHEME) {
std::string urlStr = frame->GetURL();
if (urlStr.find("spotify:") == 0)
return;
}
// Load the error page.
LoadErrorPage(frame, failedUrl, errorCode, errorText);
}
bool ClientHandler::OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool is_redirect) {
CEF_REQUIRE_UI_THREAD();
message_router_->OnBeforeBrowse(browser, frame);
return false;
}
bool ClientHandler::OnOpenURLFromTab(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& target_url,
CefRequestHandler::WindowOpenDisposition target_disposition,
bool user_gesture) {
if (user_gesture && target_disposition == WOD_NEW_BACKGROUND_TAB) {
// Handle middle-click and ctrl + left-click by opening the URL in a new
// browser window.
MainContext::Get()->GetRootWindowManager()->CreateRootWindow(
true, is_osr(), CefRect(), target_url);
return true;
}
// Open the URL in the current browser window.
return false;
}
cef_return_value_t ClientHandler::OnBeforeResourceLoad(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefRequestCallback> callback) {
CEF_REQUIRE_IO_THREAD();
return resource_manager_->OnBeforeResourceLoad(browser, frame, request,
callback);
}
CefRefPtr<CefResourceHandler> ClientHandler::GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) {
CEF_REQUIRE_IO_THREAD();
return resource_manager_->GetResourceHandler(browser, frame, request);
}
bool ClientHandler::OnQuotaRequest(CefRefPtr<CefBrowser> browser,
const CefString& origin_url,
int64 new_size,
CefRefPtr<CefRequestCallback> callback) {
CEF_REQUIRE_IO_THREAD();
static const int64 max_size = 1024 * 1024 * 20; // 20mb.
// Grant the quota request if the size is reasonable.
callback->Continue(new_size <= max_size);
return true;
}
void ClientHandler::OnProtocolExecution(CefRefPtr<CefBrowser> browser,
const CefString& url,
bool& allow_os_execution) {
CEF_REQUIRE_UI_THREAD();
std::string urlStr = url;
// Allow OS execution of Spotify URIs.
if (urlStr.find("spotify:") == 0)
allow_os_execution = true;
}
bool ClientHandler::OnCertificateError(
CefRefPtr<CefBrowser> browser,
ErrorCode cert_error,
const CefString& request_url,
CefRefPtr<CefSSLInfo> ssl_info,
CefRefPtr<CefRequestCallback> callback) {
CEF_REQUIRE_UI_THREAD();
CefRefPtr<CefSSLCertPrincipal> subject = ssl_info->GetSubject();
CefRefPtr<CefSSLCertPrincipal> issuer = ssl_info->GetIssuer();
// Build a table showing certificate information.
std::stringstream ss;
ss << "X.509 Certificate Information:"
"<table border=1><tr><th>Field</th><th>Value</th></tr>" <<
"<tr><td>Subject</td><td>" <<
(subject.get() ? subject->GetDisplayName().ToString() : "&nbsp;") <<
"</td></tr>"
"<tr><td>Issuer</td><td>" <<
(issuer.get() ? issuer->GetDisplayName().ToString() : "&nbsp;") <<
"</td></tr>"
"<tr><td>Serial #*</td><td>" <<
GetBinaryString(ssl_info->GetSerialNumber()) << "</td></tr>"
"<tr><td>Valid Start</td><td>" <<
GetTimeString(ssl_info->GetValidStart()) << "</td></tr>"
"<tr><td>Valid Expiry</td><td>" <<
GetTimeString(ssl_info->GetValidExpiry()) << "</td></tr>"
"<tr><td>DER Encoded*</td>"
"<td style=\"max-width:800px;overflow:scroll;\">" <<
GetBinaryString(ssl_info->GetDEREncoded()) << "</td></tr>"
"<tr><td>PEM Encoded*</td>"
"<td style=\"max-width:800px;overflow:scroll;\">" <<
GetBinaryString(ssl_info->GetPEMEncoded()) << "</td></tr>"
"</table> * Displayed value is base64 encoded.";
// Load the error page.
LoadErrorPage(browser->GetMainFrame(), request_url, cert_error, ss.str());
return false; // Cancel the request.
}
void ClientHandler::OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
TerminationStatus status) {
CEF_REQUIRE_UI_THREAD();
message_router_->OnRenderProcessTerminated(browser);
// Don't reload if there's no start URL, or if the crash URL was specified.
if (startup_url_.empty() || startup_url_ == "chrome://crash")
return;
CefRefPtr<CefFrame> frame = browser->GetMainFrame();
std::string url = frame->GetURL();
// Don't reload if the termination occurred before any URL had successfully
// loaded.
if (url.empty())
return;
std::string start_url = startup_url_;
// Convert URLs to lowercase for easier comparison.
std::transform(url.begin(), url.end(), url.begin(), tolower);
std::transform(start_url.begin(), start_url.end(), start_url.begin(),
tolower);
// Don't reload the URL that just resulted in termination.
if (url.find(start_url) == 0)
return;
frame->LoadURL(startup_url_);
}
int ClientHandler::GetBrowserCount() const {
CEF_REQUIRE_UI_THREAD();
return browser_count_;
}
void ClientHandler::ShowDevTools(CefRefPtr<CefBrowser> browser,
const CefPoint& inspect_element_at) {
CefWindowInfo windowInfo;
CefRefPtr<CefClient> client;
CefBrowserSettings settings;
if (CreatePopupWindow(browser, true, CefPopupFeatures(), windowInfo, client,
settings)) {
browser->GetHost()->ShowDevTools(windowInfo, client, settings,
inspect_element_at);
}
}
void ClientHandler::CloseDevTools(CefRefPtr<CefBrowser> browser) {
browser->GetHost()->CloseDevTools();
}
bool ClientHandler::CreatePopupWindow(
CefRefPtr<CefBrowser> browser,
bool is_devtools,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) {
// Note: This method will be called on multiple threads.
// The popup browser will be parented to a new native window.
// Don't show URL bar and navigation buttons on DevTools windows.
MainContext::Get()->GetRootWindowManager()->CreateRootWindowAsPopup(
!is_devtools, is_osr(), popupFeatures, windowInfo, client, settings);
return true;
}
void ClientHandler::NotifyBrowserCreated(CefRefPtr<CefBrowser> browser) {
if (!CURRENTLY_ON_MAIN_THREAD()) {
// Execute this method on the main thread.
MAIN_POST_CLOSURE(
base::Bind(&ClientHandler::NotifyBrowserCreated, this, browser));
return;
}
if (delegate_)
delegate_->OnBrowserCreated(browser);
}
void ClientHandler::NotifyBrowserClosing(CefRefPtr<CefBrowser> browser) {
if (!CURRENTLY_ON_MAIN_THREAD()) {
// Execute this method on the main thread.
MAIN_POST_CLOSURE(
base::Bind(&ClientHandler::NotifyBrowserClosing, this, browser));
return;
}
if (delegate_)
delegate_->OnBrowserClosing(browser);
}
void ClientHandler::NotifyBrowserClosed(CefRefPtr<CefBrowser> browser) {
if (!CURRENTLY_ON_MAIN_THREAD()) {
// Execute this method on the main thread.
MAIN_POST_CLOSURE(
base::Bind(&ClientHandler::NotifyBrowserClosed, this, browser));
return;
}
if (delegate_)
delegate_->OnBrowserClosed(browser);
}
void ClientHandler::NotifyAddress(const CefString& url) {
if (!CURRENTLY_ON_MAIN_THREAD()) {
// Execute this method on the main thread.
MAIN_POST_CLOSURE(
base::Bind(&ClientHandler::NotifyAddress, this, url));
return;
}
if (delegate_)
delegate_->OnSetAddress(url);
}
void ClientHandler::NotifyTitle(const CefString& title) {
if (!CURRENTLY_ON_MAIN_THREAD()) {
// Execute this method on the main thread.
MAIN_POST_CLOSURE(
base::Bind(&ClientHandler::NotifyTitle, this, title));
return;
}
if (delegate_)
delegate_->OnSetTitle(title);
}
void ClientHandler::NotifyFullscreen(bool fullscreen) {
if (!CURRENTLY_ON_MAIN_THREAD()) {
// Execute this method on the main thread.
MAIN_POST_CLOSURE(
base::Bind(&ClientHandler::NotifyFullscreen, this, fullscreen));
return;
}
if (delegate_)
delegate_->OnSetFullscreen(fullscreen);
}
void ClientHandler::NotifyLoadingState(bool isLoading,
bool canGoBack,
bool canGoForward) {
if (!CURRENTLY_ON_MAIN_THREAD()) {
// Execute this method on the main thread.
MAIN_POST_CLOSURE(
base::Bind(&ClientHandler::NotifyLoadingState, this,
isLoading, canGoBack, canGoForward));
return;
}
if (delegate_)
delegate_->OnSetLoadingState(isLoading, canGoBack, canGoForward);
}
void ClientHandler::NotifyDraggableRegions(
const std::vector<CefDraggableRegion>& regions) {
if (!CURRENTLY_ON_MAIN_THREAD()) {
// Execute this method on the main thread.
MAIN_POST_CLOSURE(
base::Bind(&ClientHandler::NotifyDraggableRegions, this, regions));
return;
}
if (delegate_)
delegate_->OnSetDraggableRegions(regions);
}
void ClientHandler::BuildTestMenu(CefRefPtr<CefMenuModel> model) {
if (model->GetCount() > 0)
model->AddSeparator();
// Build the sub menu.
CefRefPtr<CefMenuModel> submenu =
model->AddSubMenu(CLIENT_ID_TESTMENU_SUBMENU, "Context Menu Test");
submenu->AddCheckItem(CLIENT_ID_TESTMENU_CHECKITEM, "Check Item");
submenu->AddRadioItem(CLIENT_ID_TESTMENU_RADIOITEM1, "Radio Item 1", 0);
submenu->AddRadioItem(CLIENT_ID_TESTMENU_RADIOITEM2, "Radio Item 2", 0);
submenu->AddRadioItem(CLIENT_ID_TESTMENU_RADIOITEM3, "Radio Item 3", 0);
// Check the check item.
if (test_menu_state_.check_item)
submenu->SetChecked(CLIENT_ID_TESTMENU_CHECKITEM, true);
// Check the selected radio item.
submenu->SetChecked(
CLIENT_ID_TESTMENU_RADIOITEM1 + test_menu_state_.radio_item, true);
}
bool ClientHandler::ExecuteTestMenu(int command_id) {
if (command_id == CLIENT_ID_TESTMENU_CHECKITEM) {
// Toggle the check item.
test_menu_state_.check_item ^= 1;
return true;
} else if (command_id >= CLIENT_ID_TESTMENU_RADIOITEM1 &&
command_id <= CLIENT_ID_TESTMENU_RADIOITEM3) {
// Store the selected radio item.
test_menu_state_.radio_item = (command_id - CLIENT_ID_TESTMENU_RADIOITEM1);
return true;
}
// Allow default handling to proceed.
return false;
}
} // namespace client

View File

@ -0,0 +1,352 @@
// 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_BROWSER_CLIENT_HANDLER_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_HANDLER_H_
#pragma once
#include <set>
#include <string>
#include "include/cef_client.h"
#include "include/wrapper/cef_helpers.h"
#include "include/wrapper/cef_message_router.h"
#include "include/wrapper/cef_resource_manager.h"
#include "cefclient/browser/client_types.h"
#if defined(OS_LINUX)
#include "cefclient/browser/dialog_handler_gtk.h"
#endif
namespace client {
// Client handler abstract base class. Provides common functionality shared by
// all concrete client handler implementations.
class ClientHandler : public CefClient,
public CefContextMenuHandler,
public CefDisplayHandler,
public CefDownloadHandler,
public CefDragHandler,
public CefGeolocationHandler,
public CefKeyboardHandler,
public CefLifeSpanHandler,
public CefLoadHandler,
public CefRequestHandler {
public:
// Implement this interface to receive notification of ClientHandler
// events. The methods of this class will be called on the main thread.
class Delegate {
public:
// Called when the browser is created.
virtual void OnBrowserCreated(CefRefPtr<CefBrowser> browser) = 0;
// Called when the browser is closing.
virtual void OnBrowserClosing(CefRefPtr<CefBrowser> browser) = 0;
// Called when the browser has been closed.
virtual void OnBrowserClosed(CefRefPtr<CefBrowser> browser) = 0;
// Set the window URL address.
virtual void OnSetAddress(const std::string& url) = 0;
// Set the window title.
virtual void OnSetTitle(const std::string& title) = 0;
// Set fullscreen mode.
virtual void OnSetFullscreen(bool fullscreen) = 0;
// Set the loading state.
virtual void OnSetLoadingState(bool isLoading,
bool canGoBack,
bool canGoForward) = 0;
// Set the draggable regions.
virtual void OnSetDraggableRegions(
const std::vector<CefDraggableRegion>& regions) = 0;
protected:
virtual ~Delegate() {}
};
typedef std::set<CefMessageRouterBrowserSide::Handler*> MessageHandlerSet;
// Constructor may be called on any thread.
// |delegate| must outlive this object or DetachDelegate() must be called.
ClientHandler(Delegate* delegate,
bool is_osr,
const std::string& startup_url);
// This object may outlive the Delegate object so it's necessary for the
// Delegate to detach itself before destruction.
void DetachDelegate();
// CefClient methods
CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() OVERRIDE {
return this;
}
CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
return this;
}
CefRefPtr<CefDownloadHandler> GetDownloadHandler() OVERRIDE {
return this;
}
CefRefPtr<CefDragHandler> GetDragHandler() OVERRIDE {
return this;
}
CefRefPtr<CefGeolocationHandler> GetGeolocationHandler() OVERRIDE {
return this;
}
CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() OVERRIDE {
return this;
}
CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
return this;
}
CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE {
return this;
}
CefRefPtr<CefRequestHandler> GetRequestHandler() OVERRIDE {
return this;
}
bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) OVERRIDE;
#if defined(OS_LINUX)
CefRefPtr<CefDialogHandler> GetDialogHandler() OVERRIDE {
return dialog_handler_;
}
CefRefPtr<CefJSDialogHandler> GetJSDialogHandler() OVERRIDE {
return dialog_handler_;
}
#endif
// CefContextMenuHandler methods
void OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
CefRefPtr<CefMenuModel> model) OVERRIDE;
bool OnContextMenuCommand(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
int command_id,
EventFlags event_flags) OVERRIDE;
// CefDisplayHandler methods
void OnAddressChange(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& url) OVERRIDE;
void OnTitleChange(CefRefPtr<CefBrowser> browser,
const CefString& title) OVERRIDE;
void OnFullscreenModeChange(CefRefPtr<CefBrowser> browser,
bool fullscreen) OVERRIDE;
bool OnConsoleMessage(CefRefPtr<CefBrowser> browser,
const CefString& message,
const CefString& source,
int line) OVERRIDE;
// CefDownloadHandler methods
void OnBeforeDownload(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDownloadItem> download_item,
const CefString& suggested_name,
CefRefPtr<CefBeforeDownloadCallback> callback) OVERRIDE;
void OnDownloadUpdated(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDownloadItem> download_item,
CefRefPtr<CefDownloadItemCallback> callback) OVERRIDE;
// CefDragHandler methods
bool OnDragEnter(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> dragData,
CefDragHandler::DragOperationsMask mask) OVERRIDE;
void OnDraggableRegionsChanged(
CefRefPtr<CefBrowser> browser,
const std::vector<CefDraggableRegion>& regions) OVERRIDE;
// CefGeolocationHandler methods
bool OnRequestGeolocationPermission(
CefRefPtr<CefBrowser> browser,
const CefString& requesting_url,
int request_id,
CefRefPtr<CefGeolocationCallback> callback) OVERRIDE;
// CefKeyboardHandler methods
bool OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
const CefKeyEvent& event,
CefEventHandle os_event,
bool* is_keyboard_shortcut) OVERRIDE;
// CefLifeSpanHandler methods
bool OnBeforePopup(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& target_url,
const CefString& target_frame_name,
CefLifeSpanHandler::WindowOpenDisposition target_disposition,
bool user_gesture,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings,
bool* no_javascript_access) OVERRIDE;
void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
// CefLoadHandler methods
void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
bool isLoading,
bool canGoBack,
bool canGoForward) OVERRIDE;
void OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) OVERRIDE;
// CefRequestHandler methods
bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool is_redirect) OVERRIDE;
bool OnOpenURLFromTab(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& target_url,
CefRequestHandler::WindowOpenDisposition target_disposition,
bool user_gesture) OVERRIDE;
cef_return_value_t OnBeforeResourceLoad(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefRequestCallback> callback) OVERRIDE;
CefRefPtr<CefResourceHandler> GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) OVERRIDE;
bool OnQuotaRequest(CefRefPtr<CefBrowser> browser,
const CefString& origin_url,
int64 new_size,
CefRefPtr<CefRequestCallback> callback) OVERRIDE;
void OnProtocolExecution(CefRefPtr<CefBrowser> browser,
const CefString& url,
bool& allow_os_execution) OVERRIDE;
bool OnCertificateError(
CefRefPtr<CefBrowser> browser,
ErrorCode cert_error,
const CefString& request_url,
CefRefPtr<CefSSLInfo> ssl_info,
CefRefPtr<CefRequestCallback> callback) OVERRIDE;
void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
TerminationStatus status) OVERRIDE;
// Returns the number of browsers currently using this handler. Can only be
// called on the CEF UI thread.
int GetBrowserCount() const;
// Show a new DevTools popup window.
void ShowDevTools(CefRefPtr<CefBrowser> browser,
const CefPoint& inspect_element_at);
// Close the existing DevTools popup window, if any.
void CloseDevTools(CefRefPtr<CefBrowser> browser);
// Returns the startup URL.
std::string startup_url() const { return startup_url_; }
// Returns true if this handler uses off-screen rendering.
bool is_osr() const { return is_osr_; }
private:
// Create a new popup window using the specified information. |is_devtools|
// will be true if the window will be used for DevTools. Return true to
// proceed with popup browser creation or false to cancel the popup browser.
// May be called on any thead.
bool CreatePopupWindow(
CefRefPtr<CefBrowser> browser,
bool is_devtools,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings);
// Execute Delegate notifications on the main thread.
void NotifyBrowserCreated(CefRefPtr<CefBrowser> browser);
void NotifyBrowserClosing(CefRefPtr<CefBrowser> browser);
void NotifyBrowserClosed(CefRefPtr<CefBrowser> browser);
void NotifyAddress(const CefString& url);
void NotifyTitle(const CefString& title);
void NotifyFullscreen(bool fullscreen);
void NotifyLoadingState(bool isLoading,
bool canGoBack,
bool canGoForward);
void NotifyDraggableRegions(
const std::vector<CefDraggableRegion>& regions);
// Test context menu creation.
void BuildTestMenu(CefRefPtr<CefMenuModel> model);
bool ExecuteTestMenu(int command_id);
// THREAD SAFE MEMBERS
// The following members may be accessed from any thread.
// True if this handler uses off-screen rendering.
const bool is_osr_;
// The startup URL.
const std::string startup_url_;
// True if mouse cursor change is disabled.
bool mouse_cursor_change_disabled_;
#if defined(OS_LINUX)
// Custom dialog handler for GTK.
CefRefPtr<ClientDialogHandlerGtk> dialog_handler_;
#endif
// Handles the browser side of query routing. The renderer side is handled
// in client_renderer.cc.
CefRefPtr<CefMessageRouterBrowserSide> message_router_;
// Manages the registration and delivery of resources.
CefRefPtr<CefResourceManager> resource_manager_;
// MAIN THREAD MEMBERS
// The following members will only be accessed on the main thread. This will
// be the same as the CEF UI thread except when using multi-threaded message
// loop mode on Windows.
Delegate* delegate_;
// UI THREAD MEMBERS
// The following members will only be accessed on the CEF UI thread.
// Track state information for the text context menu.
struct TestMenuState {
TestMenuState() : check_item(true), radio_item(0) {}
bool check_item;
int radio_item;
} test_menu_state_;
// The current number of browsers using this handler.
int browser_count_;
// Console logging state.
const std::string console_log_file_;
bool first_console_message_;
// True if an editable field currently has focus.
bool focus_on_editable_field_;
// Set of Handlers registered with the message router.
MessageHandlerSet message_handler_set_;
DISALLOW_COPY_AND_ASSIGN(ClientHandler);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_HANDLER_H_

View File

@ -0,0 +1,138 @@
// 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 "cefclient/browser/client_handler_osr.h"
#include "include/base/cef_bind.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_helpers.h"
namespace client {
ClientHandlerOsr::ClientHandlerOsr(Delegate* delegate,
OsrDelegate* osr_delegate,
const std::string& startup_url)
: ClientHandler(delegate, true, startup_url),
osr_delegate_(osr_delegate) {
DCHECK(osr_delegate_);
}
void ClientHandlerOsr::DetachOsrDelegate() {
if (!CefCurrentlyOn(TID_UI)) {
// Execute this method on the UI thread.
CefPostTask(TID_UI, base::Bind(&ClientHandlerOsr::DetachOsrDelegate, this));
return;
}
DCHECK(osr_delegate_);
osr_delegate_ = NULL;
}
void ClientHandlerOsr::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();
if (osr_delegate_)
osr_delegate_->OnAfterCreated(browser);
ClientHandler::OnAfterCreated(browser);
}
void ClientHandlerOsr::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();
if (osr_delegate_)
osr_delegate_->OnBeforeClose(browser);
ClientHandler::OnBeforeClose(browser);
}
bool ClientHandlerOsr::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) {
CEF_REQUIRE_UI_THREAD();
if (!osr_delegate_)
return false;
return osr_delegate_->GetRootScreenRect(browser, rect);
}
bool ClientHandlerOsr::GetViewRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) {
CEF_REQUIRE_UI_THREAD();
if (!osr_delegate_)
return false;
return osr_delegate_->GetViewRect(browser, rect);
}
bool ClientHandlerOsr::GetScreenPoint(CefRefPtr<CefBrowser> browser,
int viewX,
int viewY,
int& screenX,
int& screenY) {
CEF_REQUIRE_UI_THREAD();
if (!osr_delegate_)
return false;
return osr_delegate_->GetScreenPoint(browser, viewX, viewY, screenX, screenY);
}
bool ClientHandlerOsr::GetScreenInfo(CefRefPtr<CefBrowser> browser,
CefScreenInfo& screen_info) {
CEF_REQUIRE_UI_THREAD();
if (!osr_delegate_)
return false;
return osr_delegate_->GetScreenInfo(browser, screen_info);
}
void ClientHandlerOsr::OnPopupShow(CefRefPtr<CefBrowser> browser,
bool show) {
CEF_REQUIRE_UI_THREAD();
if (!osr_delegate_)
return;
return osr_delegate_->OnPopupShow(browser, show);
}
void ClientHandlerOsr::OnPopupSize(CefRefPtr<CefBrowser> browser,
const CefRect& rect) {
CEF_REQUIRE_UI_THREAD();
if (!osr_delegate_)
return;
return osr_delegate_->OnPopupSize(browser, rect);
}
void ClientHandlerOsr::OnPaint(CefRefPtr<CefBrowser> browser,
PaintElementType type,
const RectList& dirtyRects,
const void* buffer,
int width,
int height) {
CEF_REQUIRE_UI_THREAD();
if (!osr_delegate_)
return;
osr_delegate_->OnPaint(browser, type, dirtyRects, buffer, width, height);
}
void ClientHandlerOsr::OnCursorChange(
CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor,
CursorType type,
const CefCursorInfo& custom_cursor_info) {
CEF_REQUIRE_UI_THREAD();
if (!osr_delegate_)
return;
osr_delegate_->OnCursorChange(browser, cursor, type, custom_cursor_info);
}
bool ClientHandlerOsr::StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
int x, int y) {
CEF_REQUIRE_UI_THREAD();
if (!osr_delegate_)
return false;
return osr_delegate_->StartDragging(browser, drag_data, allowed_ops, x, y);
}
void ClientHandlerOsr::UpdateDragCursor(CefRefPtr<CefBrowser> browser,
CefRenderHandler::DragOperation operation) {
CEF_REQUIRE_UI_THREAD();
if (!osr_delegate_)
return;
osr_delegate_->UpdateDragCursor(browser, operation);
}
} // namespace client

View File

@ -0,0 +1,124 @@
// 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_CLIENT_HANDLER_OSR_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_HANDLER_OSR_H_
#pragma once
#include "cefclient/browser/client_handler.h"
namespace client {
// Client handler implementation for windowless browsers. There will only ever
// be one browser per handler instance.
class ClientHandlerOsr : public ClientHandler,
public CefRenderHandler {
public:
// Implement this interface to receive notification of ClientHandlerOsr
// events. The methods of this class will be called on the CEF UI thread.
class OsrDelegate {
public:
// These methods match the CefLifeSpanHandler interface.
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) = 0;
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) = 0;
// These methods match the CefRenderHandler interface.
virtual bool GetRootScreenRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) = 0;
virtual bool GetViewRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) = 0;
virtual bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
int viewX,
int viewY,
int& screenX,
int& screenY) = 0;
virtual bool GetScreenInfo(CefRefPtr<CefBrowser> browser,
CefScreenInfo& screen_info) = 0;
virtual void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) = 0;
virtual void OnPopupSize(CefRefPtr<CefBrowser> browser,
const CefRect& rect) = 0;
virtual void OnPaint(CefRefPtr<CefBrowser> browser,
PaintElementType type,
const RectList& dirtyRects,
const void* buffer,
int width,
int height) = 0;
virtual void OnCursorChange(
CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor,
CefRenderHandler::CursorType type,
const CefCursorInfo& custom_cursor_info) = 0;
virtual bool StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
int x, int y) = 0;
virtual void UpdateDragCursor(
CefRefPtr<CefBrowser> browser,
CefRenderHandler::DragOperation operation) = 0;
protected:
virtual ~OsrDelegate() {}
};
ClientHandlerOsr(Delegate* delegate,
OsrDelegate* osr_delegate,
const std::string& startup_url);
// This object may outlive the OsrDelegate object so it's necessary for the
// OsrDelegate to detach itself before destruction.
void DetachOsrDelegate();
// CefClient methods.
CefRefPtr<CefRenderHandler> GetRenderHandler() OVERRIDE {
return this;
}
// CefLifeSpanHandler methods.
void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
// CefRenderHandler methods.
bool GetRootScreenRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) OVERRIDE;
bool GetViewRect(CefRefPtr<CefBrowser> browser,
CefRect& rect) OVERRIDE;
bool GetScreenPoint(CefRefPtr<CefBrowser> browser,
int viewX,
int viewY,
int& screenX,
int& screenY) OVERRIDE;
bool GetScreenInfo(CefRefPtr<CefBrowser> browser,
CefScreenInfo& screen_info) OVERRIDE;
void OnPopupShow(CefRefPtr<CefBrowser> browser, bool show) OVERRIDE;
void OnPopupSize(CefRefPtr<CefBrowser> browser,
const CefRect& rect) OVERRIDE;
void OnPaint(CefRefPtr<CefBrowser> browser,
CefRenderHandler::PaintElementType type,
const CefRenderHandler::RectList& dirtyRects,
const void* buffer,
int width,
int height) OVERRIDE;
void OnCursorChange(CefRefPtr<CefBrowser> browser,
CefCursorHandle cursor,
CursorType type,
const CefCursorInfo& custom_cursor_info) OVERRIDE;
bool StartDragging(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDragData> drag_data,
CefRenderHandler::DragOperationsMask allowed_ops,
int x, int y) OVERRIDE;
void UpdateDragCursor(CefRefPtr<CefBrowser> browser,
CefRenderHandler::DragOperation operation) OVERRIDE;
private:
// Only accessed on the UI thread.
OsrDelegate* osr_delegate_;
// Include the default reference counting implementation.
IMPLEMENT_REFCOUNTING(ClientHandlerOsr);
DISALLOW_COPY_AND_ASSIGN(ClientHandlerOsr);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_HANDLER_OSR_H_

View File

@ -0,0 +1,14 @@
// 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 "cefclient/browser/client_handler_std.h"
namespace client {
ClientHandlerStd::ClientHandlerStd(Delegate* delegate,
const std::string& startup_url)
: ClientHandler(delegate, false, startup_url) {
}
} // namespace client

View File

@ -0,0 +1,28 @@
// 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_CLIENT_HANDLER_STD_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_HANDLER_STD_H_
#pragma once
#include "cefclient/browser/client_handler.h"
namespace client {
// Client handler implementation for windowed browsers. There will only ever be
// one browser per handler instance.
class ClientHandlerStd : public ClientHandler {
public:
ClientHandlerStd(Delegate* delegate,
const std::string& startup_url);
private:
// Include the default reference counting implementation.
IMPLEMENT_REFCOUNTING(ClientHandlerStd);
DISALLOW_COPY_AND_ASSIGN(ClientHandlerStd);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_HANDLER_STD_H_

View File

@ -0,0 +1,33 @@
// 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_CLIENT_TYPES_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_TYPES_H_
#pragma once
#include "include/cef_base.h"
#if defined(OS_LINUX)
#include <gtk/gtk.h>
// The Linux client uses GTK instead of the underlying platform type (X11).
#define ClientWindowHandle GtkWidget*
#else
#define ClientWindowHandle CefWindowHandle
#endif
#if defined(OS_MACOSX)
// Forward declaration of ObjC types used by cefclient and not provided by
// include/internal/cef_types_mac.h.
#ifdef __cplusplus
#ifdef __OBJC__
@class NSWindow;
#else
class NSWindow;
#endif
#endif
#endif // defined OS_MACOSX
#endif // CEF_TESTS_CEFCLIENT_BROWSER_CLIENT_TYPES_H_

View File

@ -0,0 +1,431 @@
// 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 "cefclient/browser/dialog_handler_gtk.h"
#include <libgen.h>
#include <sys/stat.h>
#include "include/cef_browser.h"
#include "include/cef_parser.h"
#include "include/wrapper/cef_helpers.h"
#include "cefclient/browser/root_window.h"
namespace client {
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<GtkWidget*>(
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<CefString>& accept_filters,
bool include_all_files,
std::vector<GtkFileFilter*>* 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<std::string> 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<CefString> 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);
}
}
GtkWidget* GetWindow(CefRefPtr<CefBrowser> browser) {
scoped_refptr<RootWindow> root_window =
RootWindow::GetForBrowser(browser->GetIdentifier());
if (root_window.get())
return root_window->GetWindowHandle();
return NULL;
}
} // namespace
ClientDialogHandlerGtk::ClientDialogHandlerGtk()
: gtk_dialog_(NULL) {
}
bool ClientDialogHandlerGtk::OnFileDialog(
CefRefPtr<CefBrowser> browser,
FileDialogMode mode,
const CefString& title,
const CefString& default_file_path,
const std::vector<CefString>& accept_filters,
int selected_accept_filter,
CefRefPtr<CefFileDialogCallback> callback) {
std::vector<CefString> files;
GtkFileChooserAction action;
const gchar* accept_button;
// Remove any modifier flags.
FileDialogMode mode_type =
static_cast<FileDialogMode>(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;
}
}
GtkWidget* window = GetWindow(browser);
DCHECK(window);
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()) {
const std::string& file_path = default_file_path;
bool exists = false;
if (mode_type == FILE_DIALOG_SAVE) {
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<char*>(file_name_str.data()));
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), file_name);
}
}
std::vector<GtkFileFilter*> filters;
AddFilters(GTK_FILE_CHOOSER(dialog), accept_filters, true, &filters);
if (selected_accept_filter < static_cast<int>(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<char*>(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<CefBrowser> browser,
const CefString& origin_url,
const CefString& accept_lang,
JSDialogType dialog_type,
const CefString& message_text,
const CefString& default_prompt_text,
CefRefPtr<CefJSDialogCallback> 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 = "JavaScript Alert";
break;
case JSDIALOGTYPE_CONFIRM:
buttons = GTK_BUTTONS_CANCEL;
gtk_message_type = GTK_MESSAGE_QUESTION;
title = "JavaScript Confirm";
break;
case JSDIALOGTYPE_PROMPT:
buttons = GTK_BUTTONS_CANCEL;
gtk_message_type = GTK_MESSAGE_QUESTION;
title = "JavaScript Prompt";
break;
}
js_dialog_callback_ = callback;
if (!origin_url.empty()) {
title += " - ";
title += origin_url.ToString();
}
GtkWidget* window = GetWindow(browser);
DCHECK(window);
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<CefBrowser> browser,
const CefString& message_text,
bool is_reload,
CefRefPtr<CefJSDialogCallback> 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(), CefString(), JSDIALOGTYPE_CONFIRM,
new_message_text, CefString(), callback, suppress_message);
}
void ClientDialogHandlerGtk::OnResetDialogState(CefRefPtr<CefBrowser> 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);
}
} // namespace client

View File

@ -0,0 +1,60 @@
// 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 <gtk/gtk.h>
#include "include/cef_dialog_handler.h"
#include "include/cef_jsdialog_handler.h"
namespace client {
class ClientDialogHandlerGtk : public CefDialogHandler,
public CefJSDialogHandler {
public:
ClientDialogHandlerGtk();
// CefDialogHandler methods.
bool OnFileDialog(CefRefPtr<CefBrowser> browser,
FileDialogMode mode,
const CefString& title,
const CefString& default_file_path,
const std::vector<CefString>& accept_filters,
int selected_accept_filter,
CefRefPtr<CefFileDialogCallback> callback) OVERRIDE;
// CefJSDialogHandler methods.
bool OnJSDialog(CefRefPtr<CefBrowser> browser,
const CefString& origin_url,
const CefString& accept_lang,
JSDialogType dialog_type,
const CefString& message_text,
const CefString& default_prompt_text,
CefRefPtr<CefJSDialogCallback> callback,
bool& suppress_message) OVERRIDE;
bool OnBeforeUnloadDialog(
CefRefPtr<CefBrowser> browser,
const CefString& message_text,
bool is_reload,
CefRefPtr<CefJSDialogCallback> callback) OVERRIDE;
void OnResetDialogState(CefRefPtr<CefBrowser> browser) OVERRIDE;
private:
static void OnDialogResponse(GtkDialog *dialog,
gint response_id,
ClientDialogHandlerGtk* handler);
GtkWidget* gtk_dialog_;
CefRefPtr<CefJSDialogCallback> js_dialog_callback_;
IMPLEMENT_REFCOUNTING(ClientDialogHandlerGtk);
DISALLOW_COPY_AND_ASSIGN(ClientDialogHandlerGtk);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_DIALOG_HANDLER_GTK_H_

View File

@ -0,0 +1,187 @@
// Copyright (c) 2012 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 "cefclient/browser/dialog_test.h"
#include <string>
#include "include/cef_browser.h"
#include "include/wrapper/cef_helpers.h"
namespace client {
namespace dialog_test {
namespace {
const char kTestUrl[] = "http://tests/dialogs";
const char kFileOpenMessageName[] = "DialogTest.FileOpen";
const char kFileOpenMultipleMessageName[] = "DialogTest.FileOpenMultiple";
const char kFileOpenFolderMessageName[] = "DialogTest.FileOpenFolder";
const char kFileSaveMessageName[] = "DialogTest.FileSave";
#if defined(OS_WIN)
#define PATH_SEP '\\'
#else
#define PATH_SEP '/'
#endif
// Store persistent dialog state information.
class DialogState : public base::RefCountedThreadSafe<DialogState> {
public:
DialogState()
: mode_(FILE_DIALOG_OPEN),
last_selected_filter_(0),
pending_(false) {}
cef_file_dialog_mode_t mode_;
int last_selected_filter_;
CefString last_file_;
bool pending_;
DISALLOW_COPY_AND_ASSIGN(DialogState);
};
// Callback executed when the file dialog is dismissed.
class DialogCallback : public CefRunFileDialogCallback {
public:
DialogCallback(
CefRefPtr<CefMessageRouterBrowserSide::Callback> router_callback,
scoped_refptr<DialogState> dialog_state)
: router_callback_(router_callback),
dialog_state_(dialog_state) {
}
virtual void OnFileDialogDismissed(
int last_selected_filter,
const std::vector<CefString>& file_paths) OVERRIDE {
CEF_REQUIRE_UI_THREAD();
DCHECK(dialog_state_->pending_);
if (!file_paths.empty()) {
if (dialog_state_->mode_ != FILE_DIALOG_OPEN_FOLDER)
dialog_state_->last_selected_filter_ = last_selected_filter;
dialog_state_->last_file_ = file_paths[0];
if (dialog_state_->mode_ == FILE_DIALOG_OPEN_FOLDER) {
std::string last_file = dialog_state_->last_file_;
if (last_file[last_file.length() - 1] != PATH_SEP) {
// Add a trailing slash so we know it's a directory. Otherwise, file
// dialogs will think the last path component is a file name.
last_file += PATH_SEP;
dialog_state_->last_file_ = last_file;
}
}
}
// Send a message back to the render process with the list of file paths.
std::string response;
for (int i = 0; i < static_cast<int>(file_paths.size()); ++i) {
if (!response.empty())
response += "|"; // Use a delimiter disallowed in file paths.
response += file_paths[i];
}
router_callback_->Success(response);
router_callback_ = NULL;
dialog_state_->pending_ = false;
dialog_state_ = NULL;
}
private:
CefRefPtr<CefMessageRouterBrowserSide::Callback> router_callback_;
scoped_refptr<DialogState> dialog_state_;
IMPLEMENT_REFCOUNTING(DialogCallback);
DISALLOW_COPY_AND_ASSIGN(DialogCallback);
};
// Handle messages in the browser process.
class Handler : public CefMessageRouterBrowserSide::Handler {
public:
Handler() {}
// Called due to cefQuery execution in dialogs.html.
virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int64 query_id,
const CefString& request,
bool persistent,
CefRefPtr<Callback> callback) OVERRIDE {
CEF_REQUIRE_UI_THREAD();
// Only handle messages from the test URL.
const std::string& url = frame->GetURL();
if (url.find(kTestUrl) != 0)
return false;
if (!dialog_state_.get())
dialog_state_ = new DialogState;
// Make sure we're only running one dialog at a time.
DCHECK(!dialog_state_->pending_);
std::vector<CefString> accept_filters;
std::string title;
const std::string& message_name = request;
if (message_name == kFileOpenMessageName) {
dialog_state_->mode_ = FILE_DIALOG_OPEN;
title = "My Open Dialog";
} else if (message_name == kFileOpenMultipleMessageName) {
dialog_state_->mode_ = FILE_DIALOG_OPEN_MULTIPLE;
title = "My Open Multiple Dialog";
} else if (message_name == kFileOpenFolderMessageName) {
dialog_state_->mode_ = FILE_DIALOG_OPEN_FOLDER;
title = "My Open Folder Dialog";
} else if (message_name == kFileSaveMessageName) {
dialog_state_->mode_ = static_cast<cef_file_dialog_mode_t>(
FILE_DIALOG_SAVE | FILE_DIALOG_OVERWRITEPROMPT_FLAG);
title = "My Save Dialog";
} else {
NOTREACHED();
return true;
}
if (dialog_state_->mode_ != FILE_DIALOG_OPEN_FOLDER) {
// Build filters based on mime time.
accept_filters.push_back("text/*");
// Build filters based on file extension.
accept_filters.push_back(".log");
accept_filters.push_back(".patch");
// Add specific filters as-is.
accept_filters.push_back("Document Files|.doc;.odt");
accept_filters.push_back("Image Files|.png;.jpg;.gif");
accept_filters.push_back("PDF Files|.pdf");
}
dialog_state_->pending_ = true;
browser->GetHost()->RunFileDialog(
dialog_state_->mode_,
title,
dialog_state_->last_file_,
accept_filters,
dialog_state_->last_selected_filter_,
new DialogCallback(callback, dialog_state_));
return true;
}
private:
scoped_refptr<DialogState> dialog_state_;
DISALLOW_COPY_AND_ASSIGN(Handler);
};
} // namespace
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
handlers.insert(new Handler());
}
} // namespace dialog_test
} // namespace client

View File

@ -0,0 +1,20 @@
// Copyright (c) 2012 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_TEST_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_DIALOG_TEST_H_
#pragma once
#include "cefclient/browser/test_runner.h"
namespace client {
namespace dialog_test {
// Create message handlers. Called from test_runner.cc.
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers);
} // namespace dialog_test
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_DIALOG_TEST_H_

View File

@ -0,0 +1,33 @@
// 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 "cefclient/browser/geometry_util.h"
#include <cmath>
namespace client {
int LogicalToDevice(int value, float device_scale_factor) {
float scaled_val = static_cast<float>(value) * device_scale_factor;
return static_cast<int>(std::floor(scaled_val));
}
CefRect LogicalToDevice(const CefRect& value, float device_scale_factor) {
return CefRect(LogicalToDevice(value.x, device_scale_factor),
LogicalToDevice(value.y, device_scale_factor),
LogicalToDevice(value.width, device_scale_factor),
LogicalToDevice(value.height, device_scale_factor));
}
int DeviceToLogical(int value, float device_scale_factor) {
float scaled_val = static_cast<float>(value) / device_scale_factor;
return static_cast<int>(std::floor(scaled_val));
}
void DeviceToLogical(CefMouseEvent& value, float device_scale_factor) {
value.x = DeviceToLogical(value.x, device_scale_factor);
value.y = DeviceToLogical(value.y, device_scale_factor);
}
} // namespace client

View File

@ -0,0 +1,23 @@
// 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_GEOMETRY_UTIL_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_GEOMETRY_UTIL_H_
#pragma once
#include "include/internal/cef_types_wrappers.h"
namespace client {
// Convert |value| from logical coordinates to device coordinates.
int LogicalToDevice(int value, float device_scale_factor);
CefRect LogicalToDevice(const CefRect& value, float device_scale_factor);
// Convert |value| from device coordinates to logical coordinates.
int DeviceToLogical(int value, float device_scale_factor);
void DeviceToLogical(CefMouseEvent& value, float device_scale_factor);
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_GEOMETRY_UTIL_H_

View File

@ -0,0 +1,33 @@
// 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 "cefclient/browser/main_context.h"
#include "include/base/cef_logging.h"
namespace client {
namespace {
MainContext* g_main_context = NULL;
} // namespace
// static
MainContext* MainContext::Get() {
DCHECK(g_main_context);
return g_main_context;
}
MainContext::MainContext() {
DCHECK(!g_main_context);
g_main_context = this;
}
MainContext::~MainContext() {
g_main_context = NULL;
}
} // namespace client

View File

@ -0,0 +1,59 @@
// 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_MAIN_CONTEXT_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_MAIN_CONTEXT_H_
#pragma once
#include <string>
#include "include/base/cef_ref_counted.h"
#include "include/internal/cef_types_wrappers.h"
#include "cefclient/browser/osr_renderer.h"
namespace client {
class RootWindowManager;
// Used to store global context in the browser process. The methods of this
// class are thread-safe unless otherwise indicated.
class MainContext {
public:
// Returns the singleton instance of this object.
static MainContext* Get();
// Returns the full path to the console log file.
virtual std::string GetConsoleLogPath() = 0;
// Returns the full path to |file_name|.
virtual std::string GetDownloadPath(const std::string& file_name) = 0;
// Returns the app working directory including trailing path separator.
virtual std::string GetAppWorkingDirectory() = 0;
// Returns the main application URL.
virtual std::string GetMainURL() = 0;
// Returns the background color.
virtual cef_color_t GetBackgroundColor() = 0;
// Populate |settings| based on command-line arguments.
virtual void PopulateSettings(CefSettings* settings) = 0;
virtual void PopulateBrowserSettings(CefBrowserSettings* settings) = 0;
virtual void PopulateOsrSettings(OsrRenderer::Settings* settings) = 0;
// Returns the object used to create/manage RootWindow instances.
virtual RootWindowManager* GetRootWindowManager() = 0;
protected:
MainContext();
virtual ~MainContext();
private:
DISALLOW_COPY_AND_ASSIGN(MainContext);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_MAIN_CONTEXT_H_

View File

@ -0,0 +1,127 @@
// 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 "cefclient/browser/main_context_impl.h"
#include "include/cef_parser.h"
#include "cefclient/common/client_switches.h"
namespace client {
namespace {
// The default URL to load in a browser window.
const char kDefaultUrl[] = "http://www.google.com";
} // namespace
MainContextImpl::MainContextImpl(CefRefPtr<CefCommandLine> command_line,
bool terminate_when_all_windows_closed)
: command_line_(command_line),
terminate_when_all_windows_closed_(terminate_when_all_windows_closed),
initialized_(false),
shutdown_(false),
background_color_(CefColorSetARGB(255, 255, 255, 255)) {
DCHECK(command_line_.get());
// Set the main URL.
if (command_line_->HasSwitch(switches::kUrl))
main_url_ = command_line_->GetSwitchValue(switches::kUrl);
if (main_url_.empty())
main_url_ = kDefaultUrl;
if (command_line_->HasSwitch(switches::kBackgroundColor)) {
// Parse the background color value.
CefParseCSSColor(command_line_->GetSwitchValue(switches::kBackgroundColor),
false, background_color_);
}
}
MainContextImpl::~MainContextImpl() {
// The context must either not have been initialized, or it must have also
// been shut down.
DCHECK(!initialized_ || shutdown_);
}
std::string MainContextImpl::GetConsoleLogPath() {
return GetAppWorkingDirectory() + "console.log";
}
std::string MainContextImpl::GetMainURL() {
return main_url_;
}
cef_color_t MainContextImpl::GetBackgroundColor() {
return background_color_;
}
void MainContextImpl::PopulateSettings(CefSettings* settings) {
#if defined(OS_WIN)
settings->multi_threaded_message_loop =
command_line_->HasSwitch(switches::kMultiThreadedMessageLoop);
#endif
CefString(&settings->cache_path) =
command_line_->GetSwitchValue(switches::kCachePath);
if (command_line_->HasSwitch(switches::kOffScreenRenderingEnabled))
settings->windowless_rendering_enabled = true;
settings->background_color = background_color_;
}
void MainContextImpl::PopulateBrowserSettings(CefBrowserSettings* settings) {
if (command_line_->HasSwitch(switches::kOffScreenFrameRate)) {
settings->windowless_frame_rate = atoi(command_line_->
GetSwitchValue(switches::kOffScreenFrameRate).ToString().c_str());
}
}
void MainContextImpl::PopulateOsrSettings(OsrRenderer::Settings* settings) {
settings->transparent =
command_line_->HasSwitch(switches::kTransparentPaintingEnabled);
settings->show_update_rect =
command_line_->HasSwitch(switches::kShowUpdateRect);
settings->background_color = background_color_;
}
RootWindowManager* MainContextImpl::GetRootWindowManager() {
DCHECK(InValidState());
return root_window_manager_.get();
}
bool MainContextImpl::Initialize(const CefMainArgs& args,
const CefSettings& settings,
CefRefPtr<CefApp> application,
void* windows_sandbox_info) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!initialized_);
DCHECK(!shutdown_);
if (!CefInitialize(args, settings, application, windows_sandbox_info))
return false;
// Need to create the RootWindowManager after calling CefInitialize because
// TempWindowX11 uses cef_get_xdisplay().
root_window_manager_.reset(
new RootWindowManager(terminate_when_all_windows_closed_));
initialized_ = true;
return true;
}
void MainContextImpl::Shutdown() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(initialized_);
DCHECK(!shutdown_);
root_window_manager_.reset();
CefShutdown();
shutdown_ = true;
}
} // namespace client

View File

@ -0,0 +1,80 @@
// 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_MAIN_CONTEXT_IMPL_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_MAIN_CONTEXT_IMPL_H_
#pragma once
#include "include/base/cef_scoped_ptr.h"
#include "include/base/cef_thread_checker.h"
#include "include/cef_app.h"
#include "include/cef_command_line.h"
#include "cefclient/browser/main_context.h"
#include "cefclient/browser/root_window_manager.h"
namespace client {
// Used to store global context in the browser process.
class MainContextImpl : public MainContext {
public:
MainContextImpl(CefRefPtr<CefCommandLine> command_line,
bool terminate_when_all_windows_closed);
// MainContext members.
std::string GetConsoleLogPath() OVERRIDE;
std::string GetDownloadPath(const std::string& file_name) OVERRIDE;
std::string GetAppWorkingDirectory() OVERRIDE;
std::string GetMainURL() OVERRIDE;
cef_color_t GetBackgroundColor() OVERRIDE;
void PopulateSettings(CefSettings* settings) OVERRIDE;
void PopulateBrowserSettings(CefBrowserSettings* settings) OVERRIDE;
void PopulateOsrSettings(OsrRenderer::Settings* settings) OVERRIDE;
RootWindowManager* GetRootWindowManager() OVERRIDE;
// Initialize CEF and associated main context state. This method must be
// called on the same thread that created this object.
bool Initialize(const CefMainArgs& args,
const CefSettings& settings,
CefRefPtr<CefApp> application,
void* windows_sandbox_info);
// Shut down CEF and associated context state. This method must be called on
// the same thread that created this object.
void Shutdown();
private:
// Allow deletion via scoped_ptr only.
friend struct base::DefaultDeleter<MainContextImpl>;
~MainContextImpl();
// Returns true if the context is in a valid state (initialized and not yet
// shut down).
bool InValidState() const {
return initialized_ && !shutdown_;
}
CefRefPtr<CefCommandLine> command_line_;
const bool terminate_when_all_windows_closed_;
// Track context state. Accessing these variables from multiple threads is
// safe because only a single thread will exist at the time that they're set
// (during context initialization and shutdown).
bool initialized_;
bool shutdown_;
std::string main_url_;
cef_color_t background_color_;
scoped_ptr<RootWindowManager> root_window_manager_;
// Used to verify that methods are called on the correct thread.
base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(MainContextImpl);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_MAIN_CONTEXT_IMPL_H_

View File

@ -0,0 +1,28 @@
// 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 "cefclient/browser/main_context_impl.h"
#include <unistd.h>
namespace client {
std::string MainContextImpl::GetDownloadPath(const std::string& file_name) {
return std::string();
}
std::string MainContextImpl::GetAppWorkingDirectory() {
char szWorkingDir[256];
if (getcwd(szWorkingDir, sizeof(szWorkingDir) - 1) == NULL) {
szWorkingDir[0] = 0;
} else {
// Add trailing path separator.
size_t len = strlen(szWorkingDir);
szWorkingDir[len] = '/';
szWorkingDir[len + 1] = 0;
}
return szWorkingDir;
}
} // namespace client

View File

@ -0,0 +1,37 @@
// 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 "cefclient/browser/main_message_loop.h"
#include "include/cef_task.h"
#include "include/wrapper/cef_closure_task.h"
namespace client {
namespace {
MainMessageLoop* g_main_message_loop = NULL;
} // namespace
MainMessageLoop::MainMessageLoop() {
DCHECK(!g_main_message_loop);
g_main_message_loop = this;
}
MainMessageLoop::~MainMessageLoop() {
g_main_message_loop = NULL;
}
// static
MainMessageLoop* MainMessageLoop::Get() {
DCHECK(g_main_message_loop);
return g_main_message_loop;
}
void MainMessageLoop::PostClosure(const base::Closure& closure) {
PostTask(CefCreateClosureTask(closure));
}
} // namespace client

View File

@ -0,0 +1,108 @@
// 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_MAIN_MESSAGE_LOOP_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_MAIN_MESSAGE_LOOP_H_
#pragma once
#include "include/base/cef_bind.h"
#include "include/base/cef_scoped_ptr.h"
#include "include/cef_task.h"
#if defined(OS_WIN)
#include <windows.h>
#endif
namespace client {
// Represents the message loop running on the main application thread in the
// browser process. This will be the same as the CEF UI thread on Linux, OS X
// and Windows when not using multi-threaded message loop mode. The methods of
// this class are thread-safe unless otherwise indicated.
class MainMessageLoop {
public:
// Returns the singleton instance of this object.
static MainMessageLoop* Get();
// Run the message loop. The thread that this method is called on will be
// considered the main thread. This blocks until Quit() is called.
virtual int Run() = 0;
// Quit the message loop.
virtual void Quit() = 0;
// Post a task for execution on the main message loop.
virtual void PostTask(CefRefPtr<CefTask> task) = 0;
// Returns true if this message loop runs tasks on the current thread.
virtual bool RunsTasksOnCurrentThread() const = 0;
#if defined(OS_WIN)
// Set the current modeless dialog on Windows for proper delivery of dialog
// messages when using multi-threaded message loop mode. This method must be
// called from the main thread. See http://support.microsoft.com/kb/71450 for
// background.
virtual void SetCurrentModelessDialog(HWND hWndDialog) = 0;
#endif
// Post a closure for execution on the main message loop.
void PostClosure(const base::Closure& closure);
protected:
// Only allow deletion via scoped_ptr.
friend struct base::DefaultDeleter<MainMessageLoop>;
MainMessageLoop();
virtual ~MainMessageLoop();
private:
DISALLOW_COPY_AND_ASSIGN(MainMessageLoop);
};
#define CURRENTLY_ON_MAIN_THREAD() \
client::MainMessageLoop::Get()->RunsTasksOnCurrentThread()
#define REQUIRE_MAIN_THREAD() DCHECK(CURRENTLY_ON_MAIN_THREAD())
#define MAIN_POST_TASK(task) \
client::MainMessageLoop::Get()->PostTask(task)
#define MAIN_POST_CLOSURE(closure) \
client::MainMessageLoop::Get()->PostClosure(closure)
// Use this struct in conjuction with RefCountedThreadSafe to ensure that an
// object is deleted on the main thread. For example:
//
// class Foo : public base::RefCountedThreadSafe<Foo, DeleteOnMainThread> {
// public:
// Foo();
// void DoSomething();
//
// private:
// // Allow deletion via scoped_refptr only.
// friend struct DeleteOnMainThread;
// friend class base::RefCountedThreadSafe<Foo, DeleteOnMainThread>;
//
// virtual ~Foo() {}
// };
//
// base::scoped_refptr<Foo> foo = new Foo();
// foo->DoSomething();
// foo = NULL; // Deletion of |foo| will occur on the main thread.
//
struct DeleteOnMainThread {
template<typename T>
static void Destruct(const T* x) {
if (CURRENTLY_ON_MAIN_THREAD()) {
delete x;
} else {
client::MainMessageLoop::Get()->PostClosure(
base::Bind(&DeleteOnMainThread::Destruct<T>, x));
}
}
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_MAIN_MESSAGE_LOOP_H_

View File

@ -0,0 +1,38 @@
// 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 "cefclient/browser/main_message_loop_std.h"
#include "include/cef_app.h"
namespace client {
MainMessageLoopStd::MainMessageLoopStd() {
}
int MainMessageLoopStd::Run() {
CefRunMessageLoop();
return 0;
}
void MainMessageLoopStd::Quit() {
CefQuitMessageLoop();
}
void MainMessageLoopStd::PostTask(CefRefPtr<CefTask> task) {
CefPostTask(TID_UI, task);
}
bool MainMessageLoopStd::RunsTasksOnCurrentThread() const {
return CefCurrentlyOn(TID_UI);
}
#if defined(OS_WIN)
void MainMessageLoopStd::SetCurrentModelessDialog(HWND hWndDialog) {
// Nothing to do here. The Chromium message loop implementation will
// internally route dialog messages.
}
#endif
} // namespace client

View File

@ -0,0 +1,35 @@
// 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_MAIN_MESSAGE_LOOP_STD_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_MAIN_MESSAGE_LOOP_STD_H_
#pragma once
#include "cefclient/browser/main_message_loop.h"
namespace client {
// Represents the main message loop in the browser process. This implementation
// is a light-weight wrapper around the Chromium UI thread.
class MainMessageLoopStd : public MainMessageLoop {
public:
MainMessageLoopStd();
// MainMessageLoop methods.
int Run() OVERRIDE;
void Quit() OVERRIDE;
void PostTask(CefRefPtr<CefTask> task) OVERRIDE;
bool RunsTasksOnCurrentThread() const OVERRIDE;
#if defined(OS_WIN)
void SetCurrentModelessDialog(HWND hWndDialog) OVERRIDE;
#endif
private:
DISALLOW_COPY_AND_ASSIGN(MainMessageLoopStd);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_MAIN_MESSAGE_LOOP_STD_H_

View File

@ -0,0 +1,37 @@
// 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.
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_OSR_DRAGDROP_EVENTS_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_OSR_DRAGDROP_EVENTS_H_
#pragma once
#include "include/cef_render_handler.h"
#include "cefclient/browser/client_handler.h"
namespace client {
class OsrDragEvents {
public:
virtual CefBrowserHost::DragOperationsMask OnDragEnter(
CefRefPtr<CefDragData> drag_data,
CefMouseEvent ev,
CefBrowserHost::DragOperationsMask effect) = 0;
virtual CefBrowserHost::DragOperationsMask OnDragOver(
CefMouseEvent ev,
CefBrowserHost::DragOperationsMask effect) = 0;
virtual void OnDragLeave() = 0;
virtual CefBrowserHost::DragOperationsMask OnDrop(
CefMouseEvent ev,
CefBrowserHost::DragOperationsMask effect) = 0;
protected:
virtual ~OsrDragEvents() {}
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_OSR_DRAGDROP_EVENTS_H_

View File

@ -0,0 +1,350 @@
// Copyright (c) 2012 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 "cefclient/browser/osr_renderer.h"
#if defined(OS_WIN)
#include <gl/gl.h>
#include <gl/glu.h>
#elif defined(OS_MACOSX)
#include <OpenGL/gl.h>
#elif defined(OS_LINUX)
#include <GL/gl.h>
#include <GL/glu.h>
#else
#error Platform is not supported.
#endif
#include "include/wrapper/cef_helpers.h"
#ifndef GL_BGR
#define GL_BGR 0x80E0
#endif
#ifndef GL_BGRA
#define GL_BGRA 0x80E1
#endif
#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
#endif
// DCHECK on gl errors.
#ifndef NDEBUG
#define VERIFY_NO_ERROR { \
int _gl_error = glGetError(); \
DCHECK(_gl_error == GL_NO_ERROR) << \
"glGetError returned " << _gl_error; \
}
#else
#define VERIFY_NO_ERROR
#endif
namespace client {
OsrRenderer::Settings::Settings()
: transparent(false),
show_update_rect(false),
background_color(CefColorSetARGB(255, 255, 255, 255)) {
}
OsrRenderer::OsrRenderer(const Settings& settings)
: settings_(settings),
initialized_(false),
texture_id_(0),
view_width_(0),
view_height_(0),
spin_x_(0),
spin_y_(0) {
}
OsrRenderer::~OsrRenderer() {
Cleanup();
}
void OsrRenderer::Initialize() {
if (initialized_)
return;
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); VERIFY_NO_ERROR;
glClearColor(float(CefColorGetR(settings_.background_color)) / 255.0f,
float(CefColorGetG(settings_.background_color)) / 255.0f,
float(CefColorGetB(settings_.background_color)) / 255.0f,
1.0f); VERIFY_NO_ERROR;
// Necessary for non-power-of-2 textures to render correctly.
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); VERIFY_NO_ERROR;
// Create the texture.
glGenTextures(1, &texture_id_); VERIFY_NO_ERROR;
DCHECK_NE(texture_id_, 0U); VERIFY_NO_ERROR;
glBindTexture(GL_TEXTURE_2D, texture_id_); VERIFY_NO_ERROR;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST); VERIFY_NO_ERROR;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST); VERIFY_NO_ERROR;
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); VERIFY_NO_ERROR;
initialized_ = true;
}
void OsrRenderer::Cleanup() {
if (texture_id_ != 0)
glDeleteTextures(1, &texture_id_);
}
void OsrRenderer::Render() {
if (view_width_ == 0 || view_height_ == 0)
return;
DCHECK(initialized_);
struct {
float tu, tv;
float x, y, z;
} static vertices[] = {
{0.0f, 1.0f, -1.0f, -1.0f, 0.0f},
{1.0f, 1.0f, 1.0f, -1.0f, 0.0f},
{1.0f, 0.0f, 1.0f, 1.0f, 0.0f},
{0.0f, 0.0f, -1.0f, 1.0f, 0.0f}
};
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); VERIFY_NO_ERROR;
glMatrixMode(GL_MODELVIEW); VERIFY_NO_ERROR;
glLoadIdentity(); VERIFY_NO_ERROR;
// Match GL units to screen coordinates.
glViewport(0, 0, view_width_, view_height_); VERIFY_NO_ERROR;
glMatrixMode(GL_PROJECTION); VERIFY_NO_ERROR;
glLoadIdentity(); VERIFY_NO_ERROR;
// Draw the background gradient.
glPushAttrib(GL_ALL_ATTRIB_BITS); VERIFY_NO_ERROR;
// Don't check for errors until glEnd().
glBegin(GL_QUADS);
glColor4f(1.0, 0.0, 0.0, 1.0); // red
glVertex2f(-1.0, -1.0);
glVertex2f(1.0, -1.0);
glColor4f(0.0, 0.0, 1.0, 1.0); // blue
glVertex2f(1.0, 1.0);
glVertex2f(-1.0, 1.0);
glEnd(); VERIFY_NO_ERROR;
glPopAttrib(); VERIFY_NO_ERROR;
// Rotate the view based on the mouse spin.
if (spin_x_ != 0) {
glRotatef(-spin_x_, 1.0f, 0.0f, 0.0f); VERIFY_NO_ERROR;
}
if (spin_y_ != 0) {
glRotatef(-spin_y_, 0.0f, 1.0f, 0.0f); VERIFY_NO_ERROR;
}
if (settings_.transparent) {
// Alpha blending style. Texture values have premultiplied alpha.
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); VERIFY_NO_ERROR;
// Enable alpha blending.
glEnable(GL_BLEND); VERIFY_NO_ERROR;
}
// Enable 2D textures.
glEnable(GL_TEXTURE_2D); VERIFY_NO_ERROR;
// Draw the facets with the texture.
DCHECK_NE(texture_id_, 0U); VERIFY_NO_ERROR;
glBindTexture(GL_TEXTURE_2D, texture_id_); VERIFY_NO_ERROR;
glInterleavedArrays(GL_T2F_V3F, 0, vertices); VERIFY_NO_ERROR;
glDrawArrays(GL_QUADS, 0, 4); VERIFY_NO_ERROR;
// Disable 2D textures.
glDisable(GL_TEXTURE_2D); VERIFY_NO_ERROR;
if (settings_.transparent) {
// Disable alpha blending.
glDisable(GL_BLEND); VERIFY_NO_ERROR;
}
// Draw a rectangle around the update region.
if (settings_.show_update_rect && !update_rect_.IsEmpty()) {
int left = update_rect_.x;
int right = update_rect_.x + update_rect_.width;
int top = update_rect_.y;
int bottom = update_rect_.y + update_rect_.height;
#if defined(OS_LINUX)
// Shrink the box so that top & right sides are drawn.
top += 1;
right -= 1;
#else
// Shrink the box so that left & bottom sides are drawn.
left += 1;
bottom -= 1;
#endif
glPushAttrib(GL_ALL_ATTRIB_BITS); VERIFY_NO_ERROR
glMatrixMode(GL_PROJECTION); VERIFY_NO_ERROR;
glPushMatrix(); VERIFY_NO_ERROR;
glLoadIdentity(); VERIFY_NO_ERROR;
glOrtho(0, view_width_, view_height_, 0, 0, 1); VERIFY_NO_ERROR;
glLineWidth(1); VERIFY_NO_ERROR;
glColor3f(1.0f, 0.0f, 0.0f); VERIFY_NO_ERROR;
// Don't check for errors until glEnd().
glBegin(GL_LINE_STRIP);
glVertex2i(left, top);
glVertex2i(right, top);
glVertex2i(right, bottom);
glVertex2i(left, bottom);
glVertex2i(left, top);
glEnd(); VERIFY_NO_ERROR;
glPopMatrix(); VERIFY_NO_ERROR;
glPopAttrib(); VERIFY_NO_ERROR;
}
}
void OsrRenderer::OnPopupShow(CefRefPtr<CefBrowser> browser,
bool show) {
if (!show) {
// Clear the popup rectangle.
ClearPopupRects();
}
}
void OsrRenderer::OnPopupSize(CefRefPtr<CefBrowser> browser,
const CefRect& rect) {
if (rect.width <= 0 || rect.height <= 0)
return;
original_popup_rect_ = rect;
popup_rect_ = GetPopupRectInWebView(original_popup_rect_);
}
CefRect OsrRenderer::GetPopupRectInWebView(const CefRect& original_rect) {
CefRect rc(original_rect);
// if x or y are negative, move them to 0.
if (rc.x < 0)
rc.x = 0;
if (rc.y < 0)
rc.y = 0;
// if popup goes outside the view, try to reposition origin
if (rc.x + rc.width > view_width_)
rc.x = view_width_ - rc.width;
if (rc.y + rc.height > view_height_)
rc.y = view_height_ - rc.height;
// if x or y became negative, move them to 0 again.
if (rc.x < 0)
rc.x = 0;
if (rc.y < 0)
rc.y = 0;
return rc;
}
void OsrRenderer::ClearPopupRects() {
popup_rect_.Set(0, 0, 0, 0);
original_popup_rect_.Set(0, 0, 0, 0);
}
void OsrRenderer::OnPaint(CefRefPtr<CefBrowser> browser,
CefRenderHandler::PaintElementType type,
const CefRenderHandler::RectList& dirtyRects,
const void* buffer, int width, int height) {
if (!initialized_)
Initialize();
if (settings_.transparent) {
// Enable alpha blending.
glEnable(GL_BLEND); VERIFY_NO_ERROR;
}
// Enable 2D textures.
glEnable(GL_TEXTURE_2D); VERIFY_NO_ERROR;
DCHECK_NE(texture_id_, 0U);
glBindTexture(GL_TEXTURE_2D, texture_id_); VERIFY_NO_ERROR;
if (type == PET_VIEW) {
int old_width = view_width_;
int old_height = view_height_;
view_width_ = width;
view_height_ = height;
if (settings_.show_update_rect)
update_rect_ = dirtyRects[0];
glPixelStorei(GL_UNPACK_ROW_LENGTH, view_width_); VERIFY_NO_ERROR;
if (old_width != view_width_ || old_height != view_height_ ||
(dirtyRects.size() == 1 &&
dirtyRects[0] == CefRect(0, 0, view_width_, view_height_))) {
// Update/resize the whole texture.
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); VERIFY_NO_ERROR;
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); VERIFY_NO_ERROR;
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA, view_width_, view_height_, 0,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer); VERIFY_NO_ERROR;
} else {
// Update just the dirty rectangles.
CefRenderHandler::RectList::const_iterator i = dirtyRects.begin();
for (; i != dirtyRects.end(); ++i) {
const CefRect& rect = *i;
DCHECK(rect.x + rect.width <= view_width_);
DCHECK(rect.y + rect.height <= view_height_);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, rect.x); VERIFY_NO_ERROR;
glPixelStorei(GL_UNPACK_SKIP_ROWS, rect.y); VERIFY_NO_ERROR;
glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x, rect.y, rect.width,
rect.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
buffer); VERIFY_NO_ERROR;
}
}
} else if (type == PET_POPUP && popup_rect_.width > 0 &&
popup_rect_.height > 0) {
int skip_pixels = 0, x = popup_rect_.x;
int skip_rows = 0, y = popup_rect_.y;
int w = width;
int h = height;
// Adjust the popup to fit inside the view.
if (x < 0) {
skip_pixels = -x;
x = 0;
}
if (y < 0) {
skip_rows = -y;
y = 0;
}
if (x + w > view_width_)
w -= x + w - view_width_;
if (y + h > view_height_)
h -= y + h - view_height_;
// Update the popup rectangle.
glPixelStorei(GL_UNPACK_ROW_LENGTH, width); VERIFY_NO_ERROR;
glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); VERIFY_NO_ERROR;
glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows); VERIFY_NO_ERROR;
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_BGRA,
GL_UNSIGNED_INT_8_8_8_8_REV, buffer); VERIFY_NO_ERROR;
}
// Disable 2D textures.
glDisable(GL_TEXTURE_2D); VERIFY_NO_ERROR;
if (settings_.transparent) {
// Disable alpha blending.
glDisable(GL_BLEND); VERIFY_NO_ERROR;
}
}
void OsrRenderer::SetSpin(float spinX, float spinY) {
spin_x_ = spinX;
spin_y_ = spinY;
}
void OsrRenderer::IncrementSpin(float spinDX, float spinDY) {
spin_x_ -= spinDX;
spin_y_ -= spinDY;
}
} // namespace client

View File

@ -0,0 +1,86 @@
// Copyright (c) 2012 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_OSR_RENDERER_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_OSR_RENDERER_H_
#pragma once
#include "include/cef_browser.h"
#include "include/cef_render_handler.h"
namespace client {
class OsrRenderer {
public:
struct Settings {
Settings();
// If true use transparent rendering.
bool transparent;
// If true draw a border around update rectangles.
bool show_update_rect;
// Background color.
cef_color_t background_color;
};
explicit OsrRenderer(const Settings& settings);
~OsrRenderer();
// Initialize the OpenGL environment.
void Initialize();
// Clean up the OpenGL environment.
void Cleanup();
// Render to the screen.
void Render();
// Forwarded from CefRenderHandler callbacks.
void OnPopupShow(CefRefPtr<CefBrowser> browser,
bool show);
// |rect| must be in pixel coordinates.
void OnPopupSize(CefRefPtr<CefBrowser> browser,
const CefRect& rect);
void OnPaint(CefRefPtr<CefBrowser> browser,
CefRenderHandler::PaintElementType type,
const CefRenderHandler::RectList& dirtyRects,
const void* buffer, int width, int height);
// Apply spin.
void SetSpin(float spinX, float spinY);
void IncrementSpin(float spinDX, float spinDY);
bool IsTransparent() const { return settings_.transparent; }
cef_color_t GetBackgroundColor() const { return settings_.background_color; }
int GetViewWidth() const { return view_width_; }
int GetViewHeight() const { return view_height_; }
const CefRect& popup_rect() const { return popup_rect_; }
const CefRect& original_popup_rect() const { return original_popup_rect_; }
CefRect GetPopupRectInWebView(const CefRect& original_rect);
void ClearPopupRects();
private:
const Settings settings_;
bool initialized_;
unsigned int texture_id_;
int view_width_;
int view_height_;
CefRect popup_rect_;
CefRect original_popup_rect_;
float spin_x_;
float spin_y_;
CefRect update_rect_;
DISALLOW_COPY_AND_ASSIGN(OsrRenderer);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_OSR_RENDERER_H_

View File

@ -0,0 +1,537 @@
// Copyright (c) 2014 The Chromium Embedded Framework Authors.
// Portions Copyright (c) 2012 The Chromium 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 "cefclient/browser/print_handler_gtk.h"
#include <vector>
#include "include/base/cef_logging.h"
#include "include/base/cef_macros.h"
#include "include/wrapper/cef_helpers.h"
namespace client {
namespace {
// CUPS Duplex attribute and values.
const char kCUPSDuplex[] = "cups-Duplex";
const char kDuplexNone[] = "None";
const char kDuplexTumble[] = "DuplexTumble";
const char kDuplexNoTumble[] = "DuplexNoTumble";
// CUPS color mode attribute and values.
const char kCUPSColorMode[] = "cups-ColorMode";
const char kCUPSColorModel[] = "cups-ColorModel";
const char kCUPSPrintoutMode[] = "cups-PrintoutMode";
const char kCUPSProcessColorModel[] = "cups-ProcessColorModel";
const char kBlack[] = "Black";
const char kCMYK[] = "CMYK";
const char kCMY_K[] = "CMY+K";
const char kCMY[] = "CMY";
const char kColor[] = "Color";
const char kGray[] = "Gray";
const char kGrayscale[] = "Grayscale";
const char kGreyscale[] = "Greyscale";
const char kMonochrome[] = "Monochrome";
const char kNormal[] = "Normal";
const char kNormalGray[] = "Normal.Gray";
const char kRGB[] = "RGB";
const char kRGBA[] = "RGBA";
const char kRGB16[] = "RGB16";
// Default margin settings.
const double kTopMarginInInch = 0.25;
const double kBottomMarginInInch = 0.56;
const double kLeftMarginInInch = 0.25;
const double kRightMarginInInch = 0.25;
// Length of an inch in CSS's 1px unit.
// http://dev.w3.org/csswg/css3-values/#the-px-unit
const int kPixelsPerInch = 96;
// LETTER: 8.5 x 11 inches
const float kLetterWidthInch = 8.5f;
const float kLetterHeightInch = 11.0f;
class StickyPrintSettingGtk {
public:
StickyPrintSettingGtk() : last_used_settings_(gtk_print_settings_new()) {
}
~StickyPrintSettingGtk() {
NOTREACHED(); // The instance is intentionally leaked.
}
GtkPrintSettings* settings() {
return last_used_settings_;
}
void SetLastUsedSettings(GtkPrintSettings* settings) {
DCHECK(last_used_settings_);
g_object_unref(last_used_settings_);
last_used_settings_ = gtk_print_settings_copy(settings);
}
private:
GtkPrintSettings* last_used_settings_;
DISALLOW_COPY_AND_ASSIGN(StickyPrintSettingGtk);
};
// Lazily initialize the singleton instance.
StickyPrintSettingGtk* GetLastUsedSettings() {
static StickyPrintSettingGtk* settings = NULL;
if (!settings)
settings = new StickyPrintSettingGtk();
return settings;
}
// Helper class to track GTK printers.
class GtkPrinterList {
public:
GtkPrinterList() : default_printer_(NULL) {
gtk_enumerate_printers(SetPrinter, this, NULL, TRUE);
}
~GtkPrinterList() {
for (std::vector<GtkPrinter*>::iterator it = printers_.begin();
it < printers_.end(); ++it) {
g_object_unref(*it);
}
}
// Can return NULL if there's no default printer. E.g. Printer on a laptop
// is "home_printer", but the laptop is at work.
GtkPrinter* default_printer() {
return default_printer_;
}
// Can return NULL if the printer cannot be found due to:
// - Printer list out of sync with printer dialog UI.
// - Querying for non-existant printers like 'Print to PDF'.
GtkPrinter* GetPrinterWithName(const std::string& name) {
if (name.empty())
return NULL;
for (std::vector<GtkPrinter*>::iterator it = printers_.begin();
it < printers_.end(); ++it) {
if (gtk_printer_get_name(*it) == name) {
return *it;
}
}
return NULL;
}
private:
// Callback function used by gtk_enumerate_printers() to get all printer.
static gboolean SetPrinter(GtkPrinter* printer, gpointer data) {
GtkPrinterList* printer_list = reinterpret_cast<GtkPrinterList*>(data);
if (gtk_printer_is_default(printer))
printer_list->default_printer_ = printer;
g_object_ref(printer);
printer_list->printers_.push_back(printer);
return FALSE;
}
std::vector<GtkPrinter*> printers_;
GtkPrinter* default_printer_;
};
void GetColorModelForMode(CefPrintSettings::ColorModel color_mode,
std::string* color_setting_name,
std::string* color_value) {
color_setting_name->assign(kCUPSColorModel);
switch (color_mode) {
case COLOR_MODEL_COLOR:
color_value->assign(kColor);
break;
case COLOR_MODEL_CMYK:
color_value->assign(kCMYK);
break;
case COLOR_MODEL_PRINTOUTMODE_NORMAL:
color_value->assign(kNormal);
color_setting_name->assign(kCUPSPrintoutMode);
break;
case COLOR_MODEL_PRINTOUTMODE_NORMAL_GRAY:
color_value->assign(kNormalGray);
color_setting_name->assign(kCUPSPrintoutMode);
break;
case COLOR_MODEL_RGB16:
color_value->assign(kRGB16);
break;
case COLOR_MODEL_RGBA:
color_value->assign(kRGBA);
break;
case COLOR_MODEL_RGB:
color_value->assign(kRGB);
break;
case COLOR_MODEL_CMY:
color_value->assign(kCMY);
break;
case COLOR_MODEL_CMY_K:
color_value->assign(kCMY_K);
break;
case COLOR_MODEL_BLACK:
color_value->assign(kBlack);
break;
case COLOR_MODEL_GRAY:
color_value->assign(kGray);
break;
case COLOR_MODEL_COLORMODE_COLOR:
color_setting_name->assign(kCUPSColorMode);
color_value->assign(kColor);
break;
case COLOR_MODEL_COLORMODE_MONOCHROME:
color_setting_name->assign(kCUPSColorMode);
color_value->assign(kMonochrome);
break;
case COLOR_MODEL_HP_COLOR_COLOR:
color_setting_name->assign(kColor);
color_value->assign(kColor);
break;
case COLOR_MODEL_HP_COLOR_BLACK:
color_setting_name->assign(kColor);
color_value->assign(kBlack);
break;
case COLOR_MODEL_PROCESSCOLORMODEL_CMYK:
color_setting_name->assign(kCUPSProcessColorModel);
color_value->assign(kCMYK);
break;
case COLOR_MODEL_PROCESSCOLORMODEL_GREYSCALE:
color_setting_name->assign(kCUPSProcessColorModel);
color_value->assign(kGreyscale);
break;
case COLOR_MODEL_PROCESSCOLORMODEL_RGB:
color_setting_name->assign(kCUPSProcessColorModel);
color_value->assign(kRGB);
break;
default:
color_value->assign(kGrayscale);
break;
}
}
void InitPrintSettings(GtkPrintSettings* settings,
GtkPageSetup* page_setup,
CefRefPtr<CefPrintSettings> print_settings) {
DCHECK(settings);
DCHECK(page_setup);
std::string device_name;
const gchar* name = gtk_print_settings_get_printer(settings);
if (name)
device_name = name;
print_settings->SetDeviceName(device_name);
CefSize physical_size_device_units;
CefRect printable_area_device_units;
int dpi = gtk_print_settings_get_resolution(settings);
if (dpi) {
// Initialize page_setup_device_units_.
physical_size_device_units.Set(
gtk_page_setup_get_paper_width(page_setup, GTK_UNIT_INCH) * dpi,
gtk_page_setup_get_paper_height(page_setup, GTK_UNIT_INCH) * dpi);
printable_area_device_units.Set(
gtk_page_setup_get_left_margin(page_setup, GTK_UNIT_INCH) * dpi,
gtk_page_setup_get_top_margin(page_setup, GTK_UNIT_INCH) * dpi,
gtk_page_setup_get_page_width(page_setup, GTK_UNIT_INCH) * dpi,
gtk_page_setup_get_page_height(page_setup, GTK_UNIT_INCH) * dpi);
} else {
// Use default values if we cannot get valid values from the print dialog.
dpi = kPixelsPerInch;
double page_width_in_pixel = kLetterWidthInch * dpi;
double page_height_in_pixel = kLetterHeightInch * dpi;
physical_size_device_units.Set(
static_cast<int>(page_width_in_pixel),
static_cast<int>(page_height_in_pixel));
printable_area_device_units.Set(
static_cast<int>(kLeftMarginInInch * dpi),
static_cast<int>(kTopMarginInInch * dpi),
page_width_in_pixel - (kLeftMarginInInch + kRightMarginInInch) * dpi,
page_height_in_pixel - (kTopMarginInInch + kBottomMarginInInch) * dpi);
}
print_settings->SetDPI(dpi);
// Note: With the normal GTK print dialog, when the user selects the landscape
// orientation, all that does is change the paper size. Which seems to be
// enough to render the right output and send it to the printer.
// The orientation value stays as portrait and does not actually affect
// printing.
// Thus this is only useful in print preview mode, where we manually set the
// orientation and change the paper size ourselves.
GtkPageOrientation orientation = gtk_print_settings_get_orientation(settings);
// Set before SetPrinterPrintableArea to make it flip area if necessary.
print_settings->SetOrientation(orientation == GTK_PAGE_ORIENTATION_LANDSCAPE);
print_settings->SetPrinterPrintableArea(physical_size_device_units,
printable_area_device_units,
true);
}
} // namespace
ClientPrintHandlerGtk::ClientPrintHandlerGtk()
: dialog_(NULL),
gtk_settings_(NULL),
page_setup_(NULL),
printer_(NULL) {
}
void ClientPrintHandlerGtk::OnPrintSettings(
CefRefPtr<CefPrintSettings> settings,
bool get_defaults) {
if (get_defaults) {
DCHECK(!page_setup_);
DCHECK(!printer_);
// |gtk_settings_| is a new copy.
gtk_settings_ =
gtk_print_settings_copy(GetLastUsedSettings()->settings());
page_setup_ = gtk_page_setup_new();
} else {
if (!gtk_settings_) {
gtk_settings_ =
gtk_print_settings_copy(GetLastUsedSettings()->settings());
}
GtkPrinterList* printer_list = new GtkPrinterList;
printer_ = printer_list->GetPrinterWithName(settings->GetDeviceName());
if (printer_) {
g_object_ref(printer_);
gtk_print_settings_set_printer(gtk_settings_,
gtk_printer_get_name(printer_));
if (!page_setup_) {
page_setup_ = gtk_printer_get_default_page_size(printer_);
}
}
gtk_print_settings_set_n_copies(gtk_settings_, settings->GetCopies());
gtk_print_settings_set_collate(gtk_settings_, settings->WillCollate());
std::string color_value;
std::string color_setting_name;
GetColorModelForMode(settings->GetColorModel(), &color_setting_name,
&color_value);
gtk_print_settings_set(gtk_settings_, color_setting_name.c_str(),
color_value.c_str());
if (settings->GetDuplexMode() != DUPLEX_MODE_UNKNOWN) {
const char* cups_duplex_mode = NULL;
switch (settings->GetDuplexMode()) {
case DUPLEX_MODE_LONG_EDGE:
cups_duplex_mode = kDuplexNoTumble;
break;
case DUPLEX_MODE_SHORT_EDGE:
cups_duplex_mode = kDuplexTumble;
break;
case DUPLEX_MODE_SIMPLEX:
cups_duplex_mode = kDuplexNone;
break;
default: // UNKNOWN_DUPLEX_MODE
NOTREACHED();
break;
}
gtk_print_settings_set(gtk_settings_, kCUPSDuplex, cups_duplex_mode);
}
if (!page_setup_)
page_setup_ = gtk_page_setup_new();
gtk_print_settings_set_orientation(
gtk_settings_,
settings->IsLandscape() ? GTK_PAGE_ORIENTATION_LANDSCAPE :
GTK_PAGE_ORIENTATION_PORTRAIT);
delete printer_list;
}
InitPrintSettings(gtk_settings_, page_setup_, settings);
}
bool ClientPrintHandlerGtk::OnPrintDialog(
bool has_selection,
CefRefPtr<CefPrintDialogCallback> callback) {
dialog_callback_ = callback;
// TODO(cef): Identify the correct parent window.
GtkWindow* parent = NULL;
// TODO(estade): We need a window title here.
dialog_ = gtk_print_unix_dialog_new(NULL, parent);
g_signal_connect(dialog_, "delete-event",
G_CALLBACK(gtk_widget_hide_on_delete), NULL);
// Set modal so user cannot focus the same tab and press print again.
gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);
// Since we only generate PDF, only show printers that support PDF.
// TODO(thestig) Add more capabilities to support?
GtkPrintCapabilities cap = static_cast<GtkPrintCapabilities>(
GTK_PRINT_CAPABILITY_GENERATE_PDF |
GTK_PRINT_CAPABILITY_PAGE_SET |
GTK_PRINT_CAPABILITY_COPIES |
GTK_PRINT_CAPABILITY_COLLATE |
GTK_PRINT_CAPABILITY_REVERSE);
gtk_print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(dialog_),
cap);
gtk_print_unix_dialog_set_embed_page_setup(GTK_PRINT_UNIX_DIALOG(dialog_),
TRUE);
gtk_print_unix_dialog_set_support_selection(GTK_PRINT_UNIX_DIALOG(dialog_),
TRUE);
gtk_print_unix_dialog_set_has_selection(GTK_PRINT_UNIX_DIALOG(dialog_),
has_selection);
gtk_print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(dialog_),
gtk_settings_);
g_signal_connect(dialog_, "response", G_CALLBACK(OnDialogResponseThunk),
this);
gtk_widget_show(dialog_);
return true;
}
bool ClientPrintHandlerGtk::OnPrintJob(
const CefString& document_name,
const CefString& pdf_file_path,
CefRefPtr<CefPrintJobCallback> callback) {
// If |printer_| is NULL then somehow the GTK printer list changed out under
// us. In which case, just bail out.
if (!printer_)
return false;
job_callback_ = callback;
// Save the settings for next time.
GetLastUsedSettings()->SetLastUsedSettings(gtk_settings_);
GtkPrintJob* print_job = gtk_print_job_new(
document_name.ToString().c_str(),
printer_,
gtk_settings_,
page_setup_);
gtk_print_job_set_source_file(print_job,
pdf_file_path.ToString().c_str(),
NULL);
gtk_print_job_send(print_job, OnJobCompletedThunk, this, NULL);
return true;
}
void ClientPrintHandlerGtk::OnPrintReset() {
if (dialog_) {
gtk_widget_destroy(dialog_);
dialog_ = NULL;
}
if (gtk_settings_) {
g_object_unref(gtk_settings_);
gtk_settings_ = NULL;
}
if (page_setup_) {
g_object_unref(page_setup_);
page_setup_ = NULL;
}
if (printer_) {
g_object_unref(printer_);
printer_ = NULL;
}
}
CefSize ClientPrintHandlerGtk::GetPdfPaperSize(int device_units_per_inch) {
GtkPageSetup* page_setup = gtk_page_setup_new();
float width = gtk_page_setup_get_paper_width(page_setup, GTK_UNIT_INCH);
float height = gtk_page_setup_get_paper_height(page_setup, GTK_UNIT_INCH);
g_object_unref(page_setup);
return CefSize(width * device_units_per_inch, height * device_units_per_inch);
}
void ClientPrintHandlerGtk::OnDialogResponse(GtkDialog *dialog,
gint response_id) {
int num_matched_handlers = g_signal_handlers_disconnect_by_func(
dialog_, reinterpret_cast<gpointer>(&OnDialogResponseThunk), this);
DCHECK_EQ(1, num_matched_handlers);
gtk_widget_hide(dialog_);
switch (response_id) {
case GTK_RESPONSE_OK: {
if (gtk_settings_)
g_object_unref(gtk_settings_);
gtk_settings_ = gtk_print_unix_dialog_get_settings(
GTK_PRINT_UNIX_DIALOG(dialog_));
if (printer_)
g_object_unref(printer_);
printer_ = gtk_print_unix_dialog_get_selected_printer(
GTK_PRINT_UNIX_DIALOG(dialog_));
g_object_ref(printer_);
if (page_setup_)
g_object_unref(page_setup_);
page_setup_ = gtk_print_unix_dialog_get_page_setup(
GTK_PRINT_UNIX_DIALOG(dialog_));
g_object_ref(page_setup_);
// Handle page ranges.
CefPrintSettings::PageRangeList ranges_vector;
gint num_ranges;
bool print_selection_only = false;
switch (gtk_print_settings_get_print_pages(gtk_settings_)) {
case GTK_PRINT_PAGES_RANGES: {
GtkPageRange* gtk_range =
gtk_print_settings_get_page_ranges(gtk_settings_, &num_ranges);
if (gtk_range) {
for (int i = 0; i < num_ranges; ++i) {
ranges_vector.push_back(
CefPageRange(gtk_range[i].start, gtk_range[i].end));
}
g_free(gtk_range);
}
break;
}
case GTK_PRINT_PAGES_SELECTION:
print_selection_only = true;
break;
case GTK_PRINT_PAGES_ALL:
// Leave |ranges_vector| empty to indicate print all pages.
break;
case GTK_PRINT_PAGES_CURRENT:
default:
NOTREACHED();
break;
}
CefRefPtr<CefPrintSettings> settings = CefPrintSettings::Create();
settings->SetPageRanges(ranges_vector);
settings->SetSelectionOnly(print_selection_only);
InitPrintSettings(gtk_settings_, page_setup_, settings);
dialog_callback_->Continue(settings);
dialog_callback_ = NULL;
return;
}
case GTK_RESPONSE_DELETE_EVENT: // Fall through.
case GTK_RESPONSE_CANCEL: {
dialog_callback_->Cancel();
dialog_callback_ = NULL;
return;
}
case GTK_RESPONSE_APPLY:
default: {
NOTREACHED();
}
}
}
void ClientPrintHandlerGtk::OnJobCompleted(GtkPrintJob* print_job,
GError* error) {
job_callback_->Continue();
job_callback_ = NULL;
}
} // namespace client

View File

@ -0,0 +1,67 @@
// Copyright (c) 2014 The Chromium Embedded Framework Authors.
// Portions Copyright (c) 2012 The Chromium 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_PRINT_HANDLER_GTK_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_PRINT_HANDLER_GTK_H_
#pragma once
#include <gtk/gtk.h>
#include <gtk/gtkunixprint.h>
#include "include/cef_print_handler.h"
namespace client {
class ClientPrintHandlerGtk : public CefPrintHandler {
public:
ClientPrintHandlerGtk();
// CefPrintHandler methods.
void OnPrintSettings(CefRefPtr<CefPrintSettings> settings,
bool get_defaults) OVERRIDE;
bool OnPrintDialog(
bool has_selection,
CefRefPtr<CefPrintDialogCallback> callback) OVERRIDE;
bool OnPrintJob(const CefString& document_name,
const CefString& pdf_file_path,
CefRefPtr<CefPrintJobCallback> callback) OVERRIDE;
void OnPrintReset() OVERRIDE;
CefSize GetPdfPaperSize(int device_units_per_inch) OVERRIDE;
private:
void OnDialogResponse(GtkDialog *dialog,
gint response_id);
void OnJobCompleted(GtkPrintJob* print_job,
GError* error);
static void OnDialogResponseThunk(GtkDialog *dialog,
gint response_id,
ClientPrintHandlerGtk* handler) {
handler->OnDialogResponse(dialog, response_id);
}
static void OnJobCompletedThunk(GtkPrintJob* print_job,
void* handler,
GError* error) {
static_cast<ClientPrintHandlerGtk*>(handler)->
OnJobCompleted(print_job, error);
}
// Print dialog settings. ClientPrintHandlerGtk owns |dialog_| and holds
// references to the other objects.
GtkWidget* dialog_;
GtkPrintSettings* gtk_settings_;
GtkPageSetup* page_setup_;
GtkPrinter* printer_;
CefRefPtr<CefPrintDialogCallback> dialog_callback_;
CefRefPtr<CefPrintJobCallback> job_callback_;
IMPLEMENT_REFCOUNTING(ClientPrintHandlerGtk);
DISALLOW_COPY_AND_ASSIGN(ClientPrintHandlerGtk);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_PRINT_HANDLER_GTK_H_

View File

@ -0,0 +1,71 @@
// Copyright (c) 2013 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.
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by cefclient.rc
//
#define BINARY 256
#define IDC_MYICON 2
#define IDD_CEFCLIENT_DIALOG 102
#define IDS_APP_TITLE 103
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDI_CEFCLIENT 107
#define IDI_SMALL 108
#define IDC_CEFCLIENT 109
#define IDS_OSR_WIDGET_CLASS 110
#define IDR_MAINFRAME 128
#define IDC_NAV_BACK 200
#define IDC_NAV_FORWARD 201
#define IDC_NAV_RELOAD 202
#define IDC_NAV_STOP 203
#define ID_QUIT 32500
#define ID_FIND 32501
#define ID_TESTS_FIRST 32700
#define ID_TESTS_GETSOURCE 32700
#define ID_TESTS_GETTEXT 32701
#define ID_TESTS_OTHER_TESTS 32702
#define ID_TESTS_PLUGIN_INFO 32703
#define ID_TESTS_WINDOW_NEW 32704
#define ID_TESTS_WINDOW_POPUP 32705
#define ID_TESTS_PRINT 32706
#define ID_TESTS_REQUEST 32707
#define ID_TESTS_TRACING_BEGIN 32708
#define ID_TESTS_TRACING_END 32709
#define ID_TESTS_ZOOM_IN 32710
#define ID_TESTS_ZOOM_OUT 32711
#define ID_TESTS_ZOOM_RESET 32712
#define ID_TESTS_OSR_FPS 32713
#define ID_TESTS_OSR_DSF 32714
#define ID_TESTS_PRINT_TO_PDF 32715
#define ID_TESTS_LAST 32715
#define IDC_STATIC -1
#define IDS_BINDING_HTML 1000
#define IDS_DIALOGS_HTML 1001
#define IDS_LOCALSTORAGE_HTML 1002
#define IDS_LOGO_PNG 1003
#define IDS_OSRTEST_HTML 1004
#define IDS_OTHER_TESTS_HTML 1005
#define IDS_PDF_HTML 1006
#define IDS_PDF_PDF 1007
#define IDS_PERFORMANCE_HTML 1008
#define IDS_PERFORMANCE2_HTML 1009
#define IDS_TRANSPARENCY_HTML 1010
#define IDS_URLREQUEST_HTML 1011
#define IDS_WINDOW_HTML 1012
#define IDS_XMLHTTPREQUEST_HTML 1013
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 130
#define _APS_NEXT_COMMAND_VALUE 32774
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 111
#endif
#endif

View File

@ -0,0 +1,37 @@
// Copyright (c) 2013 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_RESOURCE_UTIL_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_RESOURCE_UTIL_H_
#pragma once
#include <string>
#include "include/cef_stream.h"
#if defined(OS_WIN)
#include "include/wrapper/cef_resource_manager.h"
#endif
namespace client {
#if defined(OS_POSIX)
// Returns the directory containing resource files.
bool GetResourceDir(std::string& dir);
#endif
// Retrieve a resource as a string.
bool LoadBinaryResource(const char* resource_name, std::string& resource_data);
// Retrieve a resource as a steam reader.
CefRefPtr<CefStreamReader> GetBinaryResourceReader(const char* resource_name);
#if defined(OS_WIN)
// Create a new provider for loading binary resources.
CefResourceManager::Provider* CreateBinaryResourceProvider(
const std::string& url_path);
#endif
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_RESOURCE_UTIL_H_

View File

@ -0,0 +1,35 @@
// Copyright (c) 2013 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2011 The Chromium 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 "cefclient/browser/resource_util.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
namespace client {
bool GetResourceDir(std::string& dir) {
char buff[1024];
// Retrieve the executable path.
ssize_t len = readlink("/proc/self/exe", buff, sizeof(buff)-1);
if (len == -1)
return false;
buff[len] = 0;
// Remove the executable name from the path.
char* pos = strrchr(buff, '/');
if (!pos)
return false;
// Add "files" to the path.
strcpy(pos+1, "files"); // NOLINT(runtime/printf)
dir = std::string(buff);
return true;
}
} // namespace client

View File

@ -0,0 +1,64 @@
// Copyright (c) 2013 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 "cefclient/browser/resource_util.h"
#include <stdio.h>
namespace client {
namespace {
bool FileExists(const char* path) {
FILE* f = fopen(path, "rb");
if (f) {
fclose(f);
return true;
}
return false;
}
bool ReadFileToString(const char* path, std::string& data) {
// Implementation adapted from base/file_util.cc
FILE* file = fopen(path, "rb");
if (!file)
return false;
char buf[1 << 16];
size_t len;
while ((len = fread(buf, 1, sizeof(buf), file)) > 0)
data.append(buf, len);
fclose(file);
return true;
}
} // namespace
bool LoadBinaryResource(const char* resource_name, std::string& resource_data) {
std::string path;
if (!GetResourceDir(path))
return false;
path.append("/");
path.append(resource_name);
return ReadFileToString(path.c_str(), resource_data);
}
CefRefPtr<CefStreamReader> GetBinaryResourceReader(const char* resource_name) {
std::string path;
if (!GetResourceDir(path))
return NULL;
path.append("/");
path.append(resource_name);
if (!FileExists(path.c_str()))
return NULL;
return CefStreamReader::CreateForFile(path);
}
} // namespace client

View File

@ -0,0 +1,18 @@
// 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 "cefclient/browser/root_window.h"
#include "cefclient/browser/main_context.h"
#include "cefclient/browser/root_window_manager.h"
namespace client {
// static
scoped_refptr<RootWindow> RootWindow::GetForBrowser(int browser_id) {
return MainContext::Get()->GetRootWindowManager()->GetWindowForBrowser(
browser_id);
}
} // namespace client

View File

@ -0,0 +1,130 @@
// 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_ROOT_WINDOW_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_H_
#pragma once
#include <string>
#include "include/base/cef_ref_counted.h"
#include "include/cef_browser.h"
#include "cefclient/browser/client_types.h"
#include "cefclient/browser/main_message_loop.h"
namespace client {
// Represents a top-level native window in the browser process. While references
// to this object are thread-safe the methods must be called on the main thread
// unless otherwise indicated.
class RootWindow :
public base::RefCountedThreadSafe<RootWindow, DeleteOnMainThread> {
public:
// This interface is implemented by the owner of the RootWindow. The methods
// of this class will be called on the main thread.
class Delegate {
public:
// Called to retrieve the CefRequestContext for browser. Only called for
// non-popup browsers. May return NULL.
virtual CefRefPtr<CefRequestContext> GetRequestContext(
RootWindow* root_window) = 0;
// Called to execute a test. See resource.h for |test_id| values.
virtual void OnTest(RootWindow* root_window, int test_id) = 0;
// Called to exit the application.
virtual void OnExit(RootWindow* root_window) = 0;
// Called when the RootWindow has been destroyed.
virtual void OnRootWindowDestroyed(RootWindow* root_window) = 0;
protected:
virtual ~Delegate() {}
};
// Create a new RootWindow object. This method may be called on any thread.
// Use RootWindowManager::CreateRootWindow() or CreateRootWindowAsPopup()
// instead of calling this method directly.
static scoped_refptr<RootWindow> Create();
// Returns the RootWindow associated with the specified |browser_id|. Must be
// called on the main thread.
static scoped_refptr<RootWindow> GetForBrowser(int browser_id);
#if defined(OS_MACOSX)
// Returns the RootWindow associated with the specified |window|. Must be
// called on the main thread.
static scoped_refptr<RootWindow> GetForNSWindow(NSWindow* window);
#endif
// Initialize as a normal window. This will create and show a native window
// hosting a single browser instance. This method may be called on any thread.
// |delegate| must be non-NULL and outlive this object.
// Use RootWindowManager::CreateRootWindow() instead of calling this method
// directly.
virtual void Init(RootWindow::Delegate* delegate,
bool with_controls,
bool with_osr,
const CefRect& bounds,
const CefBrowserSettings& settings,
const std::string& url) = 0;
// Initialize as a popup window. This is used to attach a new native window to
// a single browser instance that will be created later. The native window
// will be created and shown once the browser is available. This method may be
// called on any thread. |delegate| must be non-NULL and outlive this object.
// Use RootWindowManager::CreateRootWindowAsPopup() instead of calling this
// method directly.
virtual void InitAsPopup(RootWindow::Delegate* delegate,
bool with_controls,
bool with_osr,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) = 0;
enum ShowMode {
ShowNormal,
ShowMinimized,
ShowMaximized,
};
// Show the window.
virtual void Show(ShowMode mode) = 0;
// Hide the window.
virtual void Hide() = 0;
// Set the window bounds in screen coordinates.
virtual void SetBounds(int x, int y, size_t width, size_t height) = 0;
// Close the window. If |force| is true onunload handlers will not be
// executed.
virtual void Close(bool force) = 0;
// Set the device scale factor. Only used in combination with off-screen
// rendering.
virtual void SetDeviceScaleFactor(float device_scale_factor) = 0;
// Returns the device scale factor. Only used in combination with off-screen
// rendering.
virtual float GetDeviceScaleFactor() const = 0;
// Returns the browser that this window contains, if any.
virtual CefRefPtr<CefBrowser> GetBrowser() const = 0;
// Returns the native handle for this window, if any.
virtual ClientWindowHandle GetWindowHandle() const = 0;
protected:
// Allow deletion via scoped_refptr only.
friend struct DeleteOnMainThread;
friend class base::RefCountedThreadSafe<RootWindow, DeleteOnMainThread>;
virtual ~RootWindow() {}
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_H_

View File

@ -0,0 +1,665 @@
// 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 "cefclient/browser/root_window_gtk.h"
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <X11/Xlib.h>
#undef Success // Definition conflicts with cef_message_router.h
#undef RootWindow // Definition conflicts with root_window.h
#include "include/base/cef_bind.h"
#include "include/cef_app.h"
#include "cefclient/browser/browser_window_osr_gtk.h"
#include "cefclient/browser/browser_window_std_gtk.h"
#include "cefclient/browser/main_context.h"
#include "cefclient/browser/main_message_loop.h"
#include "cefclient/browser/resource.h"
#include "cefclient/browser/temp_window.h"
#include "cefclient/browser/window_test.h"
#include "cefclient/common/client_switches.h"
namespace client {
namespace {
const char kMenuIdKey[] = "menu_id";
bool IsWindowMaximized(GtkWindow* window) {
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
gint state = gdk_window_get_state(gdk_window);
return (state & GDK_WINDOW_STATE_MAXIMIZED) ? true : false;
}
void MinimizeWindow(GtkWindow* window) {
// Unmaximize the window before minimizing so restore behaves correctly.
if (IsWindowMaximized(window))
gtk_window_unmaximize(window);
gtk_window_iconify(window);
}
void MaximizeWindow(GtkWindow* window) {
gtk_window_maximize(window);
}
} // namespace
RootWindowGtk::RootWindowGtk()
: delegate_(NULL),
with_controls_(false),
with_osr_(false),
is_popup_(false),
initialized_(false),
window_(NULL),
back_button_(NULL),
forward_button_(NULL),
reload_button_(NULL),
stop_button_(NULL),
url_entry_(NULL),
toolbar_height_(0),
menubar_height_(0),
force_close_(false),
window_destroyed_(false),
browser_destroyed_(false) {
}
RootWindowGtk::~RootWindowGtk() {
REQUIRE_MAIN_THREAD();
// The window and browser should already have been destroyed.
DCHECK(window_destroyed_);
DCHECK(browser_destroyed_);
}
void RootWindowGtk::Init(RootWindow::Delegate* delegate,
bool with_controls,
bool with_osr,
const CefRect& bounds,
const CefBrowserSettings& settings,
const std::string& url) {
DCHECK(delegate);
DCHECK(!initialized_);
delegate_ = delegate;
with_controls_ = with_controls;
with_osr_ = with_osr;
start_rect_ = bounds;
CreateBrowserWindow(url);
initialized_ = true;
// Create the native root window on the main thread.
if (CURRENTLY_ON_MAIN_THREAD()) {
CreateRootWindow(settings);
} else {
MAIN_POST_CLOSURE(
base::Bind(&RootWindowGtk::CreateRootWindow, this, settings));
}
}
void RootWindowGtk::InitAsPopup(RootWindow::Delegate* delegate,
bool with_controls,
bool with_osr,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) {
DCHECK(delegate);
DCHECK(!initialized_);
delegate_ = delegate;
with_controls_ = with_controls;
with_osr_ = with_osr;
is_popup_ = true;
if (popupFeatures.xSet)
start_rect_.x = popupFeatures.x;
if (popupFeatures.ySet)
start_rect_.y = popupFeatures.y;
if (popupFeatures.widthSet)
start_rect_.width = popupFeatures.width;
if (popupFeatures.heightSet)
start_rect_.height = popupFeatures.height;
CreateBrowserWindow(std::string());
initialized_ = true;
// The new popup is initially parented to a temporary window. The native root
// window will be created after the browser is created and the popup window
// will be re-parented to it at that time.
browser_window_->GetPopupConfig(TempWindow::GetWindowHandle(),
windowInfo, client, settings);
}
void RootWindowGtk::Show(ShowMode mode) {
REQUIRE_MAIN_THREAD();
if (!window_)
return;
// Show the GTK window.
gtk_widget_show_all(window_);
if (mode == ShowMinimized)
MinimizeWindow(GTK_WINDOW(window_));
else if (mode == ShowMaximized)
MaximizeWindow(GTK_WINDOW(window_));
}
void RootWindowGtk::Hide() {
REQUIRE_MAIN_THREAD();
if (window_)
gtk_widget_hide(window_);
}
void RootWindowGtk::SetBounds(int x, int y, size_t width, size_t height) {
REQUIRE_MAIN_THREAD();
if (!window_)
return;
GtkWindow* window = GTK_WINDOW(window_);
GdkWindow* gdk_window = gtk_widget_get_window(window_);
// Make sure the window isn't minimized or maximized.
if (IsWindowMaximized(window))
gtk_window_unmaximize(window);
else
gtk_window_present(window);
// Retrieve information about the display that contains the window.
GdkScreen* screen = gdk_screen_get_default();
const gint monitor = gdk_screen_get_monitor_at_window(screen, gdk_window);
GdkRectangle rect;
gdk_screen_get_monitor_geometry(screen, monitor, &rect);
gdk_window_move_resize(gdk_window, rect.x, rect.y, rect.width, rect.height);
}
void RootWindowGtk::Close(bool force) {
REQUIRE_MAIN_THREAD();
if (window_) {
force_close_ = force;
gtk_widget_destroy(window_);
}
}
void RootWindowGtk::SetDeviceScaleFactor(float device_scale_factor) {
REQUIRE_MAIN_THREAD();
if (browser_window_)
browser_window_->SetDeviceScaleFactor(device_scale_factor);
}
float RootWindowGtk::GetDeviceScaleFactor() const {
REQUIRE_MAIN_THREAD();
if (browser_window_)
return browser_window_->GetDeviceScaleFactor();
return 1.0f;
}
CefRefPtr<CefBrowser> RootWindowGtk::GetBrowser() const {
REQUIRE_MAIN_THREAD();
if (browser_window_)
return browser_window_->GetBrowser();
return NULL;
}
ClientWindowHandle RootWindowGtk::GetWindowHandle() const {
REQUIRE_MAIN_THREAD();
return window_;
}
void RootWindowGtk::CreateBrowserWindow(const std::string& startup_url) {
if (with_osr_) {
OsrRenderer::Settings settings;
MainContext::Get()->PopulateOsrSettings(&settings);
browser_window_.reset(new BrowserWindowOsrGtk(this, startup_url, settings));
} else {
browser_window_.reset(new BrowserWindowStdGtk(this, startup_url));
}
}
void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings) {
REQUIRE_MAIN_THREAD();
DCHECK(!window_);
// TODO(port): If no x,y position is specified the window will always appear
// in the upper-left corner. Maybe there's a better default place to put it?
int x = start_rect_.x;
int y = start_rect_.y;
int width, height;
if (start_rect_.IsEmpty()) {
// TODO(port): Also, maybe there's a better way to choose the default size.
width = 800;
height = 600;
} else {
width = start_rect_.width;
height = start_rect_.height;
}
window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window_), width, height);
g_signal_connect(G_OBJECT(window_), "focus-in-event",
G_CALLBACK(&RootWindowGtk::WindowFocusIn), this);
g_signal_connect(G_OBJECT(window_), "window-state-event",
G_CALLBACK(&RootWindowGtk::WindowState), this);
g_signal_connect(G_OBJECT(window_), "configure-event",
G_CALLBACK(&RootWindowGtk::WindowConfigure), this);
g_signal_connect(G_OBJECT(window_), "destroy",
G_CALLBACK(&RootWindowGtk::WindowDestroy), this);
g_signal_connect(G_OBJECT(window_), "delete_event",
G_CALLBACK(&RootWindowGtk::WindowDelete), this);
const cef_color_t background_color = MainContext::Get()->GetBackgroundColor();
GdkColor color = {0};
color.red = CefColorGetR(background_color) * 65535 / 255;
color.green = CefColorGetG(background_color) * 65535 / 255;
color.blue = CefColorGetB(background_color) * 65535 / 255;
gtk_widget_modify_bg(window_, GTK_STATE_NORMAL, &color);
GtkWidget* vbox = gtk_vbox_new(FALSE, 0);
g_signal_connect(vbox, "size-allocate",
G_CALLBACK(&RootWindowGtk::VboxSizeAllocated), this);
gtk_container_add(GTK_CONTAINER(window_), vbox);
if (with_controls_) {
GtkWidget* menu_bar = CreateMenuBar();
g_signal_connect(menu_bar, "size-allocate",
G_CALLBACK(&RootWindowGtk::MenubarSizeAllocated), this);
gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 0);
GtkWidget* toolbar = gtk_toolbar_new();
// Turn off the labels on the toolbar buttons.
gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
g_signal_connect(toolbar, "size-allocate",
G_CALLBACK(&RootWindowGtk::ToolbarSizeAllocated), this);
back_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_GO_BACK);
g_signal_connect(back_button_, "clicked",
G_CALLBACK(&RootWindowGtk::BackButtonClicked), this);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), back_button_, -1 /* append */);
forward_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_GO_FORWARD);
g_signal_connect(forward_button_, "clicked",
G_CALLBACK(&RootWindowGtk::ForwardButtonClicked), this);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), forward_button_, -1 /* append */);
reload_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_REFRESH);
g_signal_connect(reload_button_, "clicked",
G_CALLBACK(&RootWindowGtk::ReloadButtonClicked), this);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), reload_button_, -1 /* append */);
stop_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_STOP);
g_signal_connect(stop_button_, "clicked",
G_CALLBACK(&RootWindowGtk::StopButtonClicked), this);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), stop_button_, -1 /* append */);
url_entry_ = gtk_entry_new();
g_signal_connect(url_entry_, "activate",
G_CALLBACK(&RootWindowGtk::URLEntryActivate), this);
g_signal_connect(url_entry_, "button-press-event",
G_CALLBACK(&RootWindowGtk::URLEntryButtonPress), this);
GtkToolItem* tool_item = gtk_tool_item_new();
gtk_container_add(GTK_CONTAINER(tool_item), url_entry_);
gtk_tool_item_set_expand(tool_item, TRUE);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_item, -1); // append
gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
}
// Realize (show) the GTK widget. This must be done before the browser is
// created because the underlying X11 Window is required. |browser_bounds_|
// will be set at this point based on the GTK *SizeAllocated signal callbacks.
Show(ShowNormal);
// Most window managers ignore requests for initial window positions (instead
// using a user-defined placement algorithm) and honor requests after the
// window has already been shown.
gtk_window_move(GTK_WINDOW(window_), x, y);
// Windowed browsers are parented to the X11 Window underlying the GtkWindow*
// and must be sized manually. The OSR GTK widget, on the other hand, can be
// added to the Vbox container for automatic layout-based sizing.
GtkWidget* parent = with_osr_ ? vbox : window_;
if (!is_popup_) {
// Create the browser window.
browser_window_->CreateBrowser(parent, browser_bounds_, settings,
delegate_->GetRequestContext(this));
} else {
// With popups we already have a browser window. Parent the browser window
// to the root window and show it in the correct location.
browser_window_->ShowPopup(parent, browser_bounds_.x, browser_bounds_.y,
browser_bounds_.width, browser_bounds_.height);
}
}
void RootWindowGtk::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
REQUIRE_MAIN_THREAD();
// For popup browsers create the root window once the browser has been
// created.
if (is_popup_)
CreateRootWindow(CefBrowserSettings());
}
void RootWindowGtk::OnBrowserWindowDestroyed() {
REQUIRE_MAIN_THREAD();
browser_window_.reset();
if (!window_destroyed_) {
// The browser was destroyed first. This could be due to the use of
// off-screen rendering or execution of JavaScript window.close().
// Close the RootWindow.
Close(true);
}
browser_destroyed_ = true;
NotifyDestroyedIfDone();
}
void RootWindowGtk::OnSetAddress(const std::string& url) {
REQUIRE_MAIN_THREAD();
if (url_entry_) {
std::string urlStr(url);
gtk_entry_set_text(GTK_ENTRY(url_entry_), urlStr.c_str());
}
}
void RootWindowGtk::OnSetTitle(const std::string& title) {
REQUIRE_MAIN_THREAD();
if (window_) {
std::string titleStr(title);
gtk_window_set_title(GTK_WINDOW(window_), titleStr.c_str());
}
}
void RootWindowGtk::OnSetFullscreen(bool fullscreen) {
REQUIRE_MAIN_THREAD();
CefRefPtr<CefBrowser> browser = GetBrowser();
if (browser) {
if (fullscreen)
window_test::Maximize(browser);
else
window_test::Restore(browser);
}
}
void RootWindowGtk::OnSetLoadingState(bool isLoading,
bool canGoBack,
bool canGoForward) {
REQUIRE_MAIN_THREAD();
if (with_controls_) {
gtk_widget_set_sensitive(GTK_WIDGET(stop_button_), isLoading);
gtk_widget_set_sensitive(GTK_WIDGET(reload_button_), !isLoading);
gtk_widget_set_sensitive(GTK_WIDGET(back_button_), canGoBack);
gtk_widget_set_sensitive(GTK_WIDGET(forward_button_), canGoForward);
}
}
void RootWindowGtk::OnSetDraggableRegions(
const std::vector<CefDraggableRegion>& regions) {
REQUIRE_MAIN_THREAD();
// TODO(cef): Implement support for draggable regions on this platform.
}
void RootWindowGtk::NotifyDestroyedIfDone() {
// Notify once both the window and the browser have been destroyed.
if (window_destroyed_ && browser_destroyed_)
delegate_->OnRootWindowDestroyed(this);
}
// static
gboolean RootWindowGtk::WindowFocusIn(GtkWidget* widget,
GdkEventFocus* event,
RootWindowGtk* self) {
if (event->in && self->browser_window_.get()) {
self->browser_window_->SetFocus(true);
// Return true for a windowed browser so that focus is not passed to GTK.
return self->with_osr_ ? FALSE : TRUE;
}
return FALSE;
}
// static
gboolean RootWindowGtk::WindowState(GtkWidget* widget,
GdkEventWindowState* event,
RootWindowGtk* self) {
// Called when the root window is iconified or restored. Hide the browser
// window when the root window is iconified to reduce resource usage.
if ((event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) &&
self->browser_window_.get()) {
if (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED)
self->browser_window_->Hide();
else
self->browser_window_->Show();
}
return TRUE;
}
// static
gboolean RootWindowGtk::WindowConfigure(GtkWindow* window,
GdkEvent* event,
RootWindowGtk* self) {
// Called when size, position or stack order changes.
CefRefPtr<CefBrowser> browser = self->GetBrowser();
if (browser.get()) {
// Notify the browser of move/resize events so that:
// - Popup windows are displayed in the correct location and dismissed
// when the window moves.
// - Drag&drop areas are updated accordingly.
browser->GetHost()->NotifyMoveOrResizeStarted();
}
return FALSE; // Don't stop this message.
}
// static
void RootWindowGtk::WindowDestroy(GtkWidget* widget, RootWindowGtk* self) {
// Called when the root window is destroyed.
self->window_destroyed_ = true;
self->NotifyDestroyedIfDone();
}
// static
gboolean RootWindowGtk::WindowDelete(GtkWidget* widget,
GdkEvent* event,
RootWindowGtk* self) {
// Called to query whether the root window should be closed.
if (self->force_close_)
return FALSE; // Allow the close.
if (self->browser_window_.get() && !self->browser_window_->IsClosing()) {
CefRefPtr<CefBrowser> browser = self->GetBrowser();
if (browser) {
// Notify the browser window that we would like to close it. This
// will result in a call to ClientHandler::DoClose() if the
// JavaScript 'onbeforeunload' event handler allows it.
browser->GetHost()->CloseBrowser(false);
// Cancel the close.
return TRUE;
}
}
// Allow the close.
return FALSE;
}
// static
void RootWindowGtk::VboxSizeAllocated(GtkWidget* widget,
GtkAllocation* allocation,
RootWindowGtk* self) {
// Offset browser positioning by any controls that will appear in the client
// area.
const int ux_height = self->toolbar_height_ + self->menubar_height_;
const int x = allocation->x;
const int y = allocation->y + ux_height;
const int width = allocation->width;
const int height = allocation->height - ux_height;
// Size the browser window to match the GTK widget.
self->browser_bounds_ = CefRect(x, y, width, height);
if (self->browser_window_.get())
self->browser_window_->SetBounds(x, y, width, height);
}
// static
void RootWindowGtk::MenubarSizeAllocated(GtkWidget* widget,
GtkAllocation* allocation,
RootWindowGtk* self) {
self->menubar_height_ = allocation->height;
}
// static
gboolean RootWindowGtk::MenuItemActivated(GtkWidget* widget,
RootWindowGtk* self) {
// Retrieve the menu ID set in AddMenuEntry.
int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), kMenuIdKey));
// Run the test.
if (self->delegate_)
self->delegate_->OnTest(self, id);
return FALSE; // Don't stop this message.
}
// static
void RootWindowGtk::ToolbarSizeAllocated(GtkWidget* widget,
GtkAllocation* allocation,
RootWindowGtk* self) {
self->toolbar_height_ = allocation->height;
}
// static
void RootWindowGtk::BackButtonClicked(GtkButton* button,
RootWindowGtk* self) {
CefRefPtr<CefBrowser> browser = self->GetBrowser();
if (browser.get())
browser->GoBack();
}
// static
void RootWindowGtk::ForwardButtonClicked(GtkButton* button,
RootWindowGtk* self) {
CefRefPtr<CefBrowser> browser = self->GetBrowser();
if (browser.get())
browser->GoForward();
}
// static
void RootWindowGtk::StopButtonClicked(GtkButton* button,
RootWindowGtk* self) {
CefRefPtr<CefBrowser> browser = self->GetBrowser();
if (browser.get())
browser->StopLoad();
}
// static
void RootWindowGtk::ReloadButtonClicked(GtkButton* button,
RootWindowGtk* self) {
CefRefPtr<CefBrowser> browser = self->GetBrowser();
if (browser.get())
browser->Reload();
}
// static
void RootWindowGtk::URLEntryActivate(GtkEntry* entry,
RootWindowGtk* self) {
CefRefPtr<CefBrowser> browser = self->GetBrowser();
if (browser.get()) {
const gchar* url = gtk_entry_get_text(entry);
browser->GetMainFrame()->LoadURL(std::string(url).c_str());
}
}
// static
gboolean RootWindowGtk::URLEntryButtonPress(GtkWidget* widget,
GdkEventButton* event,
RootWindowGtk* self) {
// Give focus to the GTK window. This is a work-around for bad focus-related
// interaction between the root window managed by GTK and the browser managed
// by X11.
GtkWidget* window = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
GdkWindow* gdk_window = gtk_widget_get_window(window);
::Display* xdisplay = GDK_WINDOW_XDISPLAY(gdk_window);
::Window xwindow = GDK_WINDOW_XID(gdk_window);
XSetInputFocus(xdisplay, xwindow, RevertToParent, CurrentTime);
return FALSE;
}
GtkWidget* RootWindowGtk::CreateMenuBar() {
GtkWidget* menu_bar = gtk_menu_bar_new();
// Create the test menu.
GtkWidget* test_menu = CreateMenu(menu_bar, "Tests");
AddMenuEntry(test_menu, "Get Source", ID_TESTS_GETSOURCE);
AddMenuEntry(test_menu, "Get Text", ID_TESTS_GETTEXT);
AddMenuEntry(test_menu, "New Window", ID_TESTS_WINDOW_NEW);
AddMenuEntry(test_menu, "Popup Window", ID_TESTS_WINDOW_POPUP);
AddMenuEntry(test_menu, "Request", ID_TESTS_REQUEST);
AddMenuEntry(test_menu, "Plugin Info", ID_TESTS_PLUGIN_INFO);
AddMenuEntry(test_menu, "Zoom In", ID_TESTS_ZOOM_IN);
AddMenuEntry(test_menu, "Zoom Out", ID_TESTS_ZOOM_OUT);
AddMenuEntry(test_menu, "Zoom Reset", ID_TESTS_ZOOM_RESET);
if (with_osr_) {
AddMenuEntry(test_menu, "Set FPS", ID_TESTS_OSR_FPS);
AddMenuEntry(test_menu, "Set Scale Factor", ID_TESTS_OSR_DSF);
}
AddMenuEntry(test_menu, "Begin Tracing", ID_TESTS_TRACING_BEGIN);
AddMenuEntry(test_menu, "End Tracing", ID_TESTS_TRACING_END);
AddMenuEntry(test_menu, "Print", ID_TESTS_PRINT);
AddMenuEntry(test_menu, "Print to PDF", ID_TESTS_PRINT_TO_PDF);
AddMenuEntry(test_menu, "Other Tests", ID_TESTS_OTHER_TESTS);
return menu_bar;
}
GtkWidget* RootWindowGtk::CreateMenu(GtkWidget* menu_bar, const char* text) {
GtkWidget* menu_widget = gtk_menu_new();
GtkWidget* menu_header = gtk_menu_item_new_with_label(text);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_header), menu_widget);
gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), menu_header);
return menu_widget;
}
GtkWidget* RootWindowGtk::AddMenuEntry(GtkWidget* menu_widget,
const char* text,
int id) {
GtkWidget* entry = gtk_menu_item_new_with_label(text);
g_signal_connect(entry, "activate",
G_CALLBACK(&RootWindowGtk::MenuItemActivated), this);
// Set the menu ID that will be retrieved in MenuItemActivated.
g_object_set_data(G_OBJECT(entry), kMenuIdKey, GINT_TO_POINTER(id));
gtk_menu_shell_append(GTK_MENU_SHELL(menu_widget), entry);
return entry;
}
// static
scoped_refptr<RootWindow> RootWindow::Create() {
return new RootWindowGtk();
}
} // namespace client

View File

@ -0,0 +1,157 @@
// 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_ROOT_WINDOW_GTK_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_GTK_H_
#pragma once
#include <gtk/gtk.h>
#include <string>
#include "include/base/cef_scoped_ptr.h"
#include "cefclient/browser/browser_window.h"
#include "cefclient/browser/root_window.h"
namespace client {
// GTK implementation of a top-level native window in the browser process.
// The methods of this class must be called on the main thread unless otherwise
// indicated.
class RootWindowGtk : public RootWindow,
public BrowserWindow::Delegate {
public:
// Constructor may be called on any thread.
RootWindowGtk();
~RootWindowGtk();
// RootWindow methods.
void Init(RootWindow::Delegate* delegate,
bool with_controls,
bool with_osr,
const CefRect& rect,
const CefBrowserSettings& settings,
const std::string& url) OVERRIDE;
void InitAsPopup(RootWindow::Delegate* delegate,
bool with_controls,
bool with_osr,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) OVERRIDE;
void Show(ShowMode mode) OVERRIDE;
void Hide() OVERRIDE;
void SetBounds(int x, int y, size_t width, size_t height) OVERRIDE;
void Close(bool force) OVERRIDE;
void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE;
float GetDeviceScaleFactor() const OVERRIDE;
CefRefPtr<CefBrowser> GetBrowser() const OVERRIDE;
ClientWindowHandle GetWindowHandle() const OVERRIDE;
private:
void CreateBrowserWindow(const std::string& startup_url);
void CreateRootWindow(const CefBrowserSettings& settings);
// BrowserWindow::Delegate methods.
void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
void OnBrowserWindowDestroyed() OVERRIDE;
void OnSetAddress(const std::string& url) OVERRIDE;
void OnSetTitle(const std::string& title) OVERRIDE;
void OnSetFullscreen(bool fullscreen) OVERRIDE;
void OnSetLoadingState(bool isLoading,
bool canGoBack,
bool canGoForward) OVERRIDE;
void OnSetDraggableRegions(
const std::vector<CefDraggableRegion>& regions) OVERRIDE;
void NotifyDestroyedIfDone();
GtkWidget* CreateMenuBar();
GtkWidget* CreateMenu(GtkWidget* menu_bar, const char* text);
GtkWidget* AddMenuEntry(GtkWidget* menu_widget, const char* text, int id);
// Signal handlers for the top-level GTK window.
static gboolean WindowFocusIn(GtkWidget* widget,
GdkEventFocus* event,
RootWindowGtk* self);
static gboolean WindowState(GtkWidget* widget,
GdkEventWindowState* event,
RootWindowGtk* self);
static gboolean WindowConfigure(GtkWindow* window,
GdkEvent* event,
RootWindowGtk* self);
static void WindowDestroy(GtkWidget* widget, RootWindowGtk* self);
static gboolean WindowDelete(GtkWidget* widget,
GdkEvent* event,
RootWindowGtk* self);
// Signal handlers for the GTK Vbox containing all UX elements.
static void VboxSizeAllocated(GtkWidget* widget,
GtkAllocation* allocation,
RootWindowGtk* self);
// Signal handlers for the GTK menu bar.
static void MenubarSizeAllocated(GtkWidget* widget,
GtkAllocation* allocation,
RootWindowGtk* self);
static gboolean MenuItemActivated(GtkWidget* widget,
RootWindowGtk* self);
// Signal handlers for the GTK toolbar.
static void ToolbarSizeAllocated(GtkWidget* widget,
GtkAllocation* allocation,
RootWindowGtk* self);
static void BackButtonClicked(GtkButton* button,
RootWindowGtk* self);
static void ForwardButtonClicked(GtkButton* button,
RootWindowGtk* self);
static void StopButtonClicked(GtkButton* button,
RootWindowGtk* self);
static void ReloadButtonClicked(GtkButton* button,
RootWindowGtk* self);
// Signal handlers for the GTK URL entry field.
static void URLEntryActivate(GtkEntry* entry,
RootWindowGtk* self);
static gboolean URLEntryButtonPress(GtkWidget* widget,
GdkEventButton* event,
RootWindowGtk* self);
// After initialization all members are only accessed on the main thread.
// Members set during initialization.
RootWindow::Delegate* delegate_;
bool with_controls_;
bool with_osr_;
bool is_popup_;
CefRect start_rect_;
scoped_ptr<BrowserWindow> browser_window_;
bool initialized_;
// Main window.
GtkWidget* window_;
// Buttons.
GtkToolItem* back_button_;
GtkToolItem* forward_button_;
GtkToolItem* reload_button_;
GtkToolItem* stop_button_;
// URL text field.
GtkWidget* url_entry_;
// Height of UX controls that affect browser window placement.
int toolbar_height_;
int menubar_height_;
CefRect browser_bounds_;
bool force_close_;
bool window_destroyed_;
bool browser_destroyed_;
DISALLOW_COPY_AND_ASSIGN(RootWindowGtk);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_GTK_H_

View File

@ -0,0 +1,164 @@
// 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 "cefclient/browser/root_window_manager.h"
#include <sstream>
#include "include/base/cef_bind.h"
#include "include/base/cef_logging.h"
#include "include/wrapper/cef_helpers.h"
#include "cefclient/browser/main_context.h"
#include "cefclient/browser/test_runner.h"
#include "cefclient/common/client_switches.h"
namespace client {
RootWindowManager::RootWindowManager(bool terminate_when_all_windows_closed)
: terminate_when_all_windows_closed_(terminate_when_all_windows_closed) {
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
DCHECK(command_line.get());
request_context_per_browser_ =
command_line->HasSwitch(switches::kRequestContextPerBrowser);
}
RootWindowManager::~RootWindowManager() {
// All root windows should already have been destroyed.
DCHECK(root_windows_.empty());
}
scoped_refptr<RootWindow> RootWindowManager::CreateRootWindow(
bool with_controls,
bool with_osr,
const CefRect& bounds,
const std::string& url) {
CefBrowserSettings settings;
MainContext::Get()->PopulateBrowserSettings(&settings);
scoped_refptr<RootWindow> root_window = RootWindow::Create();
root_window->Init(this, with_controls, with_osr, bounds, settings,
url.empty() ? MainContext::Get()->GetMainURL() : url);
// Store a reference to the root window on the main thread.
OnRootWindowCreated(root_window);
return root_window;
}
scoped_refptr<RootWindow> RootWindowManager::CreateRootWindowAsPopup(
bool with_controls,
bool with_osr,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) {
MainContext::Get()->PopulateBrowserSettings(&settings);
scoped_refptr<RootWindow> root_window = RootWindow::Create();
root_window->InitAsPopup(this, with_controls, with_osr,
popupFeatures, windowInfo, client, settings);
// Store a reference to the root window on the main thread.
OnRootWindowCreated(root_window);
return root_window;
}
scoped_refptr<RootWindow> RootWindowManager::GetWindowForBrowser(
int browser_id) {
REQUIRE_MAIN_THREAD();
RootWindowSet::const_iterator it = root_windows_.begin();
for (; it != root_windows_.end(); ++it) {
CefRefPtr<CefBrowser> browser = (*it)->GetBrowser();
if (browser.get() && browser->GetIdentifier() == browser_id)
return *it;
}
return NULL;
}
void RootWindowManager::CloseAllWindows(bool force) {
if (!CURRENTLY_ON_MAIN_THREAD()) {
// Execute this method on the main thread.
MAIN_POST_CLOSURE(
base::Bind(&RootWindowManager::CloseAllWindows, base::Unretained(this),
force));
return;
}
if (root_windows_.empty())
return;
RootWindowSet::const_iterator it = root_windows_.begin();
for (; it != root_windows_.end(); ++it)
(*it)->Close(force);
}
void RootWindowManager::OnRootWindowCreated(
scoped_refptr<RootWindow> root_window) {
if (!CURRENTLY_ON_MAIN_THREAD()) {
// Execute this method on the main thread.
MAIN_POST_CLOSURE(
base::Bind(&RootWindowManager::OnRootWindowCreated,
base::Unretained(this), root_window));
return;
}
root_windows_.insert(root_window);
}
CefRefPtr<CefRequestContext> RootWindowManager::GetRequestContext(
RootWindow* root_window) {
REQUIRE_MAIN_THREAD();
if (request_context_per_browser_) {
// Create a new request context for each browser.
CefRequestContextSettings settings;
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
if (command_line->HasSwitch(switches::kCachePath)) {
// If a global cache path value is specified then give each browser a
// unique cache path.
std::stringstream ss;
ss << command_line->GetSwitchValue(switches::kCachePath).ToString() <<
time(NULL);
CefString(&settings.cache_path) = ss.str();
}
return CefRequestContext::CreateContext(settings, NULL);
}
// All browsers will share the global request context.
return NULL;
}
void RootWindowManager::OnTest(RootWindow* root_window, int test_id) {
REQUIRE_MAIN_THREAD();
test_runner::RunTest(root_window->GetBrowser(), test_id);
}
void RootWindowManager::OnExit(RootWindow* root_window) {
REQUIRE_MAIN_THREAD();
CloseAllWindows(false);
}
void RootWindowManager::OnRootWindowDestroyed(RootWindow* root_window) {
REQUIRE_MAIN_THREAD();
RootWindowSet::iterator it = root_windows_.find(root_window);
DCHECK(it != root_windows_.end());
if (it != root_windows_.end())
root_windows_.erase(it);
if (terminate_when_all_windows_closed_ && root_windows_.empty()) {
// Quit the main message loop after all windows have closed.
MainMessageLoop::Get()->Quit();
}
}
} // namespace client

View File

@ -0,0 +1,88 @@
// 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_ROOT_WINDOW_MANAGER_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_MANAGER_H_
#pragma once
#include <set>
#include "include/base/cef_scoped_ptr.h"
#include "include/cef_command_line.h"
#include "cefclient/browser/root_window.h"
#include "cefclient/browser/temp_window.h"
namespace client {
// Used to create/manage RootWindow instances. The methods of this class can be
// called from any browser process thread unless otherwise indicated.
class RootWindowManager : public RootWindow::Delegate {
public:
// If |terminate_when_all_windows_closed| is true quit the main message loop
// after all windows have closed.
explicit RootWindowManager(bool terminate_when_all_windows_closed);
// Create a new top-level native window that loads |url|.
// If |with_controls| is true the window will show controls.
// If |with_osr| is true the window will use off-screen rendering.
// If |bounds| is empty the default window size and location will be used.
// This method can be called from anywhere to create a new top-level window.
scoped_refptr<RootWindow> CreateRootWindow(
bool with_controls,
bool with_osr,
const CefRect& bounds,
const std::string& url);
// Create a new native popup window.
// If |with_controls| is true the window will show controls.
// If |with_osr| is true the window will use off-screen rendering.
// This method is called from ClientHandler::CreatePopupWindow() to
// create a new popup or DevTools window.
scoped_refptr<RootWindow> CreateRootWindowAsPopup(
bool with_controls,
bool with_osr,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings);
// Returns the RootWindow associated with the specified browser ID. Must be
// called on the main thread.
scoped_refptr<RootWindow> GetWindowForBrowser(int browser_id);
// Close all existing windows. If |force| is true onunload handlers will not
// be executed.
void CloseAllWindows(bool force);
private:
// Allow deletion via scoped_ptr only.
friend struct base::DefaultDeleter<RootWindowManager>;
~RootWindowManager();
void OnRootWindowCreated(scoped_refptr<RootWindow> root_window);
// RootWindow::Delegate methods.
CefRefPtr<CefRequestContext> GetRequestContext(
RootWindow* root_window) OVERRIDE;
void OnTest(RootWindow* root_window, int test_id) OVERRIDE;
void OnExit(RootWindow* root_window) OVERRIDE;
void OnRootWindowDestroyed(RootWindow* root_window) OVERRIDE;
const bool terminate_when_all_windows_closed_;
bool request_context_per_browser_;
// Existing root windows. Only accessed on the main thread.
typedef std::set<scoped_refptr<RootWindow> > RootWindowSet;
RootWindowSet root_windows_;
// Singleton window used as the temporary parent for popup browsers.
TempWindow temp_window_;
DISALLOW_COPY_AND_ASSIGN(RootWindowManager);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_ROOT_WINDOW_MANAGER_H_

View File

@ -0,0 +1,155 @@
// Copyright (c) 2012 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 "cefclient/browser/scheme_test.h"
#include <algorithm>
#include <string>
#include "include/cef_browser.h"
#include "include/cef_callback.h"
#include "include/cef_frame.h"
#include "include/cef_resource_handler.h"
#include "include/cef_response.h"
#include "include/cef_request.h"
#include "include/cef_scheme.h"
#include "include/wrapper/cef_helpers.h"
#include "cefclient/browser/resource_util.h"
#include "cefclient/browser/test_runner.h"
namespace client {
namespace scheme_test {
namespace {
// Implementation of the schema handler for client:// requests.
class ClientSchemeHandler : public CefResourceHandler {
public:
ClientSchemeHandler() : offset_(0) {}
virtual bool ProcessRequest(CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback)
OVERRIDE {
CEF_REQUIRE_IO_THREAD();
bool handled = false;
std::string url = request->GetURL();
if (strstr(url.c_str(), "handler.html") != NULL) {
// Build the response html
data_ = "<html><head><title>Client Scheme Handler</title></head>"
"<body bgcolor=\"white\">"
"This contents of this page page are served by the "
"ClientSchemeHandler class handling the client:// protocol."
"<br/>You should see an image:"
"<br/><img src=\"client://tests/logo.png\"><pre>";
// Output a string representation of the request
const std::string& dump = test_runner::DumpRequestContents(request);
data_.append(dump);
data_.append("</pre><br/>Try the test form:"
"<form method=\"POST\" action=\"handler.html\">"
"<input type=\"text\" name=\"field1\">"
"<input type=\"text\" name=\"field2\">"
"<input type=\"submit\">"
"</form></body></html>");
handled = true;
// Set the resulting mime type
mime_type_ = "text/html";
} else if (strstr(url.c_str(), "logo.png") != NULL) {
// Load the response image
if (LoadBinaryResource("logo.png", data_)) {
handled = true;
// Set the resulting mime type
mime_type_ = "image/png";
}
}
if (handled) {
// Indicate the headers are available.
callback->Continue();
return true;
}
return false;
}
virtual void GetResponseHeaders(CefRefPtr<CefResponse> response,
int64& response_length,
CefString& redirectUrl) OVERRIDE {
CEF_REQUIRE_IO_THREAD();
DCHECK(!data_.empty());
response->SetMimeType(mime_type_);
response->SetStatus(200);
// Set the resulting response length
response_length = data_.length();
}
virtual void Cancel() OVERRIDE {
CEF_REQUIRE_IO_THREAD();
}
virtual bool ReadResponse(void* data_out,
int bytes_to_read,
int& bytes_read,
CefRefPtr<CefCallback> callback)
OVERRIDE {
CEF_REQUIRE_IO_THREAD();
bool has_data = false;
bytes_read = 0;
if (offset_ < data_.length()) {
// Copy the next block of data into the buffer.
int transfer_size =
std::min(bytes_to_read, static_cast<int>(data_.length() - offset_));
memcpy(data_out, data_.c_str() + offset_, transfer_size);
offset_ += transfer_size;
bytes_read = transfer_size;
has_data = true;
}
return has_data;
}
private:
std::string data_;
std::string mime_type_;
size_t offset_;
IMPLEMENT_REFCOUNTING(ClientSchemeHandler);
};
// Implementation of the factory for for creating schema handlers.
class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory {
public:
// Return a new scheme handler instance to handle the request.
virtual CefRefPtr<CefResourceHandler> Create(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& scheme_name,
CefRefPtr<CefRequest> request)
OVERRIDE {
CEF_REQUIRE_IO_THREAD();
return new ClientSchemeHandler();
}
IMPLEMENT_REFCOUNTING(ClientSchemeHandlerFactory);
};
} // namespace
void RegisterSchemeHandlers() {
CefRegisterSchemeHandlerFactory("client", "tests",
new ClientSchemeHandlerFactory());
}
} // namespace scheme_test
} // namespace client

View File

@ -0,0 +1,20 @@
// Copyright (c) 2009 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_SCHEME_TEST_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_SCHEME_TEST_H_
#pragma once
namespace client {
namespace scheme_test {
// Create and register the custom scheme handler. See
// common/scheme_handler_common.h for registration of the custom scheme
// name/type which must occur in all processes. Called from test_runner.cc.
void RegisterSchemeHandlers();
} // namespace scheme_test
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_SCHEME_TEST_H_

View File

@ -0,0 +1,31 @@
// 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_TEMP_WINDOW_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_TEMP_WINDOW_H_
#pragma once
#include "cefclient/browser/client_types.h"
#if defined(OS_WIN)
#include "cefclient/browser/temp_window_win.h"
#elif defined(OS_LINUX)
#include "cefclient/browser/temp_window_x11.h"
#elif defined(OS_MACOSX)
#include "cefclient/browser/temp_window_mac.h"
#endif
namespace client {
#if defined(OS_WIN)
typedef TempWindowWin TempWindow;
#elif defined(OS_LINUX)
typedef TempWindowX11 TempWindow;
#elif defined(OS_MACOSX)
typedef TempWindowMac TempWindow;
#endif
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_TEMP_WINDOW_H_

View File

@ -0,0 +1,69 @@
// 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 "cefclient/browser/temp_window_x11.h"
#include <X11/Xlib.h>
#include "include/base/cef_logging.h"
#include "include/cef_app.h"
namespace client {
namespace {
// Create the temp window.
::Window CreateTempWindow() {
::Display* xdisplay = cef_get_xdisplay();
::Window parent_xwindow = DefaultRootWindow(xdisplay);
XSetWindowAttributes swa;
memset(&swa, 0, sizeof(swa));
swa.background_pixmap = None;
swa.override_redirect = false;
return XCreateWindow(
xdisplay, parent_xwindow,
0, 0, 1, 1, // size (1x1px)
0, // border width
CopyFromParent, // depth
InputOutput,
CopyFromParent, // visual
CWBackPixmap | CWOverrideRedirect,
&swa);
}
// Close the temp window.
void CloseTempWindow(::Window xwindow) {
::Display* xdisplay = cef_get_xdisplay();
XDestroyWindow(xdisplay, xwindow);
}
TempWindowX11* g_temp_window = NULL;
} // namespace
TempWindowX11::TempWindowX11()
: xwindow_(kNullWindowHandle) {
DCHECK(!g_temp_window);
g_temp_window = this;
xwindow_ = CreateTempWindow();
CHECK(xwindow_);
}
TempWindowX11::~TempWindowX11() {
g_temp_window = NULL;
DCHECK(xwindow_);
CloseTempWindow(xwindow_);
}
// static
CefWindowHandle TempWindowX11::GetWindowHandle() {
DCHECK(g_temp_window);
return g_temp_window->xwindow_;
}
} // namespace client

View File

@ -0,0 +1,34 @@
// 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_TEMP_WINDOW_X11_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_TEMP_WINDOW_X11_H_
#pragma once
#include "include/cef_base.h"
namespace client {
// Represents a singleton hidden window that acts at temporary parent for
// popup browsers.
class TempWindowX11 {
public:
// Returns the singleton window handle.
static CefWindowHandle GetWindowHandle();
private:
// A single instance will be created/owned by RootWindowManager.
friend class RootWindowManager;
TempWindowX11();
~TempWindowX11();
CefWindowHandle xwindow_;
DISALLOW_COPY_AND_ASSIGN(TempWindowX11);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_TEMP_WINDOW_X11_H_

View File

@ -0,0 +1,723 @@
// 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 "cefclient/browser/test_runner.h"
#include <sstream>
#include "include/base/cef_bind.h"
#include "include/cef_parser.h"
#include "include/cef_task.h"
#include "include/cef_trace.h"
#include "include/cef_web_plugin.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_stream_resource_handler.h"
#include "cefclient/browser/binding_test.h"
#include "cefclient/browser/dialog_test.h"
#include "cefclient/browser/main_context.h"
#include "cefclient/browser/resource.h"
#include "cefclient/browser/resource_util.h"
#include "cefclient/browser/root_window_manager.h"
#include "cefclient/browser/scheme_test.h"
#include "cefclient/browser/urlrequest_test.h"
#include "cefclient/browser/window_test.h"
namespace client {
namespace test_runner {
namespace {
const char kTestOrigin[] = "http://tests/";
// Replace all instances of |from| with |to| in |str|.
std::string StringReplace(const std::string& str, const std::string& from,
const std::string& to) {
std::string result = str;
std::string::size_type pos = 0;
std::string::size_type from_len = from.length();
std::string::size_type to_len = to.length();
do {
pos = result.find(from, pos);
if (pos != std::string::npos) {
result.replace(pos, from_len, to);
pos += to_len;
}
} while (pos != std::string::npos);
return result;
}
void RunGetSourceTest(CefRefPtr<CefBrowser> browser) {
class Visitor : public CefStringVisitor {
public:
explicit Visitor(CefRefPtr<CefBrowser> browser) : browser_(browser) {}
virtual void Visit(const CefString& string) OVERRIDE {
std::string source = StringReplace(string, "<", "&lt;");
source = StringReplace(source, ">", "&gt;");
std::stringstream ss;
ss << "<html><body bgcolor=\"white\">Source:<pre>" << source <<
"</pre></body></html>";
browser_->GetMainFrame()->LoadString(ss.str(), "http://tests/getsource");
}
private:
CefRefPtr<CefBrowser> browser_;
IMPLEMENT_REFCOUNTING(Visitor);
};
browser->GetMainFrame()->GetSource(new Visitor(browser));
}
void RunGetTextTest(CefRefPtr<CefBrowser> browser) {
class Visitor : public CefStringVisitor {
public:
explicit Visitor(CefRefPtr<CefBrowser> browser) : browser_(browser) {}
virtual void Visit(const CefString& string) OVERRIDE {
std::string text = StringReplace(string, "<", "&lt;");
text = StringReplace(text, ">", "&gt;");
std::stringstream ss;
ss << "<html><body bgcolor=\"white\">Text:<pre>" << text <<
"</pre></body></html>";
browser_->GetMainFrame()->LoadString(ss.str(), "http://tests/gettext");
}
private:
CefRefPtr<CefBrowser> browser_;
IMPLEMENT_REFCOUNTING(Visitor);
};
browser->GetMainFrame()->GetText(new Visitor(browser));
}
void RunRequestTest(CefRefPtr<CefBrowser> browser) {
// Create a new request
CefRefPtr<CefRequest> request(CefRequest::Create());
// Set the request URL
request->SetURL("http://tests/request");
// Add post data to the request. The correct method and content-
// type headers will be set by CEF.
CefRefPtr<CefPostDataElement> postDataElement(CefPostDataElement::Create());
std::string data = "arg1=val1&arg2=val2";
postDataElement->SetToBytes(data.length(), data.c_str());
CefRefPtr<CefPostData> postData(CefPostData::Create());
postData->AddElement(postDataElement);
request->SetPostData(postData);
// Add a custom header
CefRequest::HeaderMap headerMap;
headerMap.insert(
std::make_pair("X-My-Header", "My Header Value"));
request->SetHeaderMap(headerMap);
// Load the request
browser->GetMainFrame()->LoadRequest(request);
}
void RunNewWindowTest(CefRefPtr<CefBrowser> browser) {
MainContext::Get()->GetRootWindowManager()->CreateRootWindow(
true, // Show controls.
browser->GetHost()->IsWindowRenderingDisabled(),
CefRect(), // Use default system size.
std::string()); // Use default URL.
}
void RunPopupWindowTest(CefRefPtr<CefBrowser> browser) {
browser->GetMainFrame()->ExecuteJavaScript(
"window.open('http://www.google.com');", "about:blank", 0);
}
void RunPluginInfoTest(CefRefPtr<CefBrowser> browser) {
class Visitor : public CefWebPluginInfoVisitor {
public:
explicit Visitor(CefRefPtr<CefBrowser> browser)
: browser_(browser) {
html_ = "<html><head><title>Plugin Info Test</title></head>"
"<body bgcolor=\"white\">"
"\n<b>Installed plugins:</b>";
}
~Visitor() {
html_ += "\n</body></html>";
// Load the html in the browser.
browser_->GetMainFrame()->LoadString(html_, "http://tests/plugin_info");
}
virtual bool Visit(CefRefPtr<CefWebPluginInfo> info, int count, int total)
OVERRIDE {
html_ += "\n<br/><br/>Name: " + info->GetName().ToString() +
"\n<br/>Description: " + info->GetDescription().ToString() +
"\n<br/>Version: " + info->GetVersion().ToString() +
"\n<br/>Path: " + info->GetPath().ToString();
return true;
}
private:
std::string html_;
CefRefPtr<CefBrowser> browser_;
IMPLEMENT_REFCOUNTING(Visitor);
};
CefVisitWebPluginInfo(new Visitor(browser));
}
void ModifyZoom(CefRefPtr<CefBrowser> browser, double delta) {
if (!CefCurrentlyOn(TID_UI)) {
// Execute on the UI thread.
CefPostTask(TID_UI, base::Bind(&ModifyZoom, browser, delta));
return;
}
browser->GetHost()->SetZoomLevel(
browser->GetHost()->GetZoomLevel() + delta);
}
const char kPrompt[] = "Prompt.";
const char kPromptFPS[] = "FPS";
const char kPromptDSF[] = "DSF";
// Handles execution of prompt results.
class PromptHandler : public CefMessageRouterBrowserSide::Handler {
public:
PromptHandler() {}
// Called due to cefQuery execution.
virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int64 query_id,
const CefString& request,
bool persistent,
CefRefPtr<Callback> callback) OVERRIDE {
// Parse |request| which takes the form "Prompt.[type]:[value]".
const std::string& request_str = request;
if (request_str.find(kPrompt) != 0)
return false;
std::string type = request_str.substr(sizeof(kPrompt) - 1);
size_t delim = type.find(':');
if (delim == std::string::npos)
return false;
const std::string& value = type.substr(delim + 1);
type = type.substr(0, delim);
// Canceling the prompt dialog returns a value of "null".
if (value != "null") {
if (type == kPromptFPS)
SetFPS(browser, atoi(value.c_str()));
else if (type == kPromptDSF)
SetDSF(browser, static_cast<float>(atof(value.c_str())));
}
// Nothing is done with the response.
callback->Success(CefString());
return true;
}
private:
void SetFPS(CefRefPtr<CefBrowser> browser, int fps) {
if (fps <= 0) {
// Reset to the default value.
CefBrowserSettings settings;
MainContext::Get()->PopulateBrowserSettings(&settings);
fps = settings.windowless_frame_rate;
}
browser->GetHost()->SetWindowlessFrameRate(fps);
}
void SetDSF(CefRefPtr<CefBrowser> browser, float dsf) {
MainMessageLoop::Get()->PostClosure(
base::Bind(&PromptHandler::SetDSFOnMainThread, browser, dsf));
}
static void SetDSFOnMainThread(CefRefPtr<CefBrowser> browser, float dsf) {
RootWindow::GetForBrowser(browser->GetIdentifier())->
SetDeviceScaleFactor(dsf);
}
};
void Prompt(CefRefPtr<CefBrowser> browser,
const std::string& type,
const std::string& label,
const std::string& default_value) {
// Prompt the user for a new value. Works as follows:
// 1. Show a prompt() dialog via JavaScript.
// 2. Pass the result to window.cefQuery().
// 3. Handle the result in PromptHandler::OnQuery.
const std::string& code =
"window.cefQuery({'request': '" + std::string(kPrompt) + type +
":' + prompt('" + label + "', '" + default_value + "')});";
browser->GetMainFrame()->ExecuteJavaScript(
code, browser->GetMainFrame()->GetURL(), 0);
}
void PromptFPS(CefRefPtr<CefBrowser> browser) {
if (!CefCurrentlyOn(TID_UI)) {
// Execute on the UI thread.
CefPostTask(TID_UI, base::Bind(&PromptFPS, browser));
return;
}
// Format the default value string.
std::stringstream ss;
ss << browser->GetHost()->GetWindowlessFrameRate();
Prompt(browser, kPromptFPS, "Enter FPS", ss.str());
}
void PromptDSF(CefRefPtr<CefBrowser> browser) {
if (!MainMessageLoop::Get()->RunsTasksOnCurrentThread()) {
// Execute on the main thread.
MainMessageLoop::Get()->PostClosure(base::Bind(&PromptDSF, browser));
return;
}
// Format the default value string.
std::stringstream ss;
ss << RootWindow::GetForBrowser(browser->GetIdentifier())->
GetDeviceScaleFactor();
Prompt(browser, kPromptDSF, "Enter Device Scale Factor", ss.str());
}
void BeginTracing() {
if (!CefCurrentlyOn(TID_UI)) {
// Execute on the UI thread.
CefPostTask(TID_UI, base::Bind(&BeginTracing));
return;
}
CefBeginTracing(CefString(), NULL);
}
void EndTracing(CefRefPtr<CefBrowser> browser) {
if (!CefCurrentlyOn(TID_UI)) {
// Execute on the UI thread.
CefPostTask(TID_UI, base::Bind(&EndTracing, browser));
return;
}
class Client : public CefEndTracingCallback,
public CefRunFileDialogCallback {
public:
explicit Client(CefRefPtr<CefBrowser> browser)
: browser_(browser) {
RunDialog();
}
void RunDialog() {
static const char kDefaultFileName[] = "trace.txt";
std::string path = MainContext::Get()->GetDownloadPath(kDefaultFileName);
if (path.empty())
path = kDefaultFileName;
// Results in a call to OnFileDialogDismissed.
browser_->GetHost()->RunFileDialog(
static_cast<cef_file_dialog_mode_t>(
FILE_DIALOG_SAVE | FILE_DIALOG_OVERWRITEPROMPT_FLAG),
CefString(), // title
path,
std::vector<CefString>(), // accept_filters
0, // selected_accept_filter
this);
}
void OnFileDialogDismissed(
int selected_accept_filter,
const std::vector<CefString>& file_paths) OVERRIDE {
if (!file_paths.empty()) {
// File selected. Results in a call to OnEndTracingComplete.
CefEndTracing(file_paths.front(), this);
} else {
// No file selected. Discard the trace data.
CefEndTracing(CefString(), NULL);
}
}
void OnEndTracingComplete(
const CefString& tracing_file) OVERRIDE {
Alert(browser_,
"File \"" + tracing_file.ToString() + "\" saved successfully.");
}
private:
CefRefPtr<CefBrowser> browser_;
IMPLEMENT_REFCOUNTING(Client);
};
new Client(browser);
}
void PrintToPDF(CefRefPtr<CefBrowser> browser) {
if (!CefCurrentlyOn(TID_UI)) {
// Execute on the UI thread.
CefPostTask(TID_UI, base::Bind(&PrintToPDF, browser));
return;
}
class Client : public CefPdfPrintCallback,
public CefRunFileDialogCallback {
public:
explicit Client(CefRefPtr<CefBrowser> browser)
: browser_(browser) {
RunDialog();
}
void RunDialog() {
static const char kDefaultFileName[] = "output.pdf";
std::string path = MainContext::Get()->GetDownloadPath(kDefaultFileName);
if (path.empty())
path = kDefaultFileName;
std::vector<CefString> accept_filters;
accept_filters.push_back(".pdf");
// Results in a call to OnFileDialogDismissed.
browser_->GetHost()->RunFileDialog(
static_cast<cef_file_dialog_mode_t>(
FILE_DIALOG_SAVE | FILE_DIALOG_OVERWRITEPROMPT_FLAG),
CefString(), // title
path,
accept_filters,
0, // selected_accept_filter
this);
}
void OnFileDialogDismissed(
int selected_accept_filter,
const std::vector<CefString>& file_paths) OVERRIDE {
if (!file_paths.empty()) {
CefPdfPrintSettings settings;
// Show the URL in the footer.
settings.header_footer_enabled = true;
CefString(&settings.header_footer_url) =
browser_->GetMainFrame()->GetURL();
// Print to the selected PDF file.
browser_->GetHost()->PrintToPDF(file_paths[0], settings, this);
}
}
void OnPdfPrintFinished(const CefString& path, bool ok) OVERRIDE {
Alert(browser_, "File \"" + path.ToString() +"\" " +
(ok ? "saved successfully." : "failed to save."));
}
private:
CefRefPtr<CefBrowser> browser_;
IMPLEMENT_REFCOUNTING(Client);
};
new Client(browser);
}
void RunOtherTests(CefRefPtr<CefBrowser> browser) {
browser->GetMainFrame()->LoadURL("http://tests/other_tests");
}
// Provider that dumps the request contents.
class RequestDumpResourceProvider : public CefResourceManager::Provider {
public:
explicit RequestDumpResourceProvider(const std::string& url)
: url_(url) {
DCHECK(!url.empty());
}
bool OnRequest(scoped_refptr<CefResourceManager::Request> request) OVERRIDE {
CEF_REQUIRE_IO_THREAD();
const std::string& url = request->url();
if (url != url_) {
// Not handled by this provider.
return false;
}
const std::string& dump = DumpRequestContents(request->request());
std::string str = "<html><body bgcolor=\"white\"><pre>" + dump +
"</pre></body></html>";
CefRefPtr<CefStreamReader> stream =
CefStreamReader::CreateForData(
static_cast<void*>(const_cast<char*>(str.c_str())),
str.size());
DCHECK(stream.get());
request->Continue(new CefStreamResourceHandler("text/html", stream));
return true;
}
private:
std::string url_;
DISALLOW_COPY_AND_ASSIGN(RequestDumpResourceProvider);
};
// Add a file extension to |url| if none is currently specified.
std::string RequestUrlFilter(const std::string& url) {
if (url.find(kTestOrigin) != 0U) {
// Don't filter anything outside of the test origin.
return url;
}
// Identify where the query or fragment component, if any, begins.
size_t suffix_pos = url.find('?');
if (suffix_pos == std::string::npos)
suffix_pos = url.find('#');
std::string url_base, url_suffix;
if (suffix_pos == std::string::npos) {
url_base = url;
} else {
url_base = url.substr(0, suffix_pos);
url_suffix = url.substr(suffix_pos);
}
// Identify the last path component.
size_t path_pos = url_base.rfind('/');
if (path_pos == std::string::npos)
return url;
const std::string& path_component = url_base.substr(path_pos);
// Identify if a file extension is currently specified.
size_t ext_pos = path_component.rfind(".");
if (ext_pos != std::string::npos)
return url;
// Rebuild the URL with a file extension.
return url_base + ".html" + url_suffix;
}
} // namespace
void RunTest(CefRefPtr<CefBrowser> browser, int id) {
if (!browser)
return;
switch (id) {
case ID_TESTS_GETSOURCE:
RunGetSourceTest(browser);
break;
case ID_TESTS_GETTEXT:
RunGetTextTest(browser);
break;
case ID_TESTS_WINDOW_NEW:
RunNewWindowTest(browser);
break;
case ID_TESTS_WINDOW_POPUP:
RunPopupWindowTest(browser);
break;
case ID_TESTS_REQUEST:
RunRequestTest(browser);
break;
case ID_TESTS_PLUGIN_INFO:
RunPluginInfoTest(browser);
break;
case ID_TESTS_ZOOM_IN:
ModifyZoom(browser, 0.5);
break;
case ID_TESTS_ZOOM_OUT:
ModifyZoom(browser, -0.5);
break;
case ID_TESTS_ZOOM_RESET:
browser->GetHost()->SetZoomLevel(0.0);
break;
case ID_TESTS_OSR_FPS:
PromptFPS(browser);
break;
case ID_TESTS_OSR_DSF:
PromptDSF(browser);
break;
case ID_TESTS_TRACING_BEGIN:
BeginTracing();
break;
case ID_TESTS_TRACING_END:
EndTracing(browser);
break;
case ID_TESTS_PRINT:
browser->GetHost()->Print();
break;
case ID_TESTS_PRINT_TO_PDF:
PrintToPDF(browser);
break;
case ID_TESTS_OTHER_TESTS:
RunOtherTests(browser);
break;
}
}
std::string DumpRequestContents(CefRefPtr<CefRequest> request) {
std::stringstream ss;
ss << "URL: " << std::string(request->GetURL());
ss << "\nMethod: " << std::string(request->GetMethod());
CefRequest::HeaderMap headerMap;
request->GetHeaderMap(headerMap);
if (headerMap.size() > 0) {
ss << "\nHeaders:";
CefRequest::HeaderMap::const_iterator it = headerMap.begin();
for (; it != headerMap.end(); ++it) {
ss << "\n\t" << std::string((*it).first) << ": " <<
std::string((*it).second);
}
}
CefRefPtr<CefPostData> postData = request->GetPostData();
if (postData.get()) {
CefPostData::ElementVector elements;
postData->GetElements(elements);
if (elements.size() > 0) {
ss << "\nPost Data:";
CefRefPtr<CefPostDataElement> element;
CefPostData::ElementVector::const_iterator it = elements.begin();
for (; it != elements.end(); ++it) {
element = (*it);
if (element->GetType() == PDE_TYPE_BYTES) {
// the element is composed of bytes
ss << "\n\tBytes: ";
if (element->GetBytesCount() == 0) {
ss << "(empty)";
} else {
// retrieve the data.
size_t size = element->GetBytesCount();
char* bytes = new char[size];
element->GetBytes(size, bytes);
ss << std::string(bytes, size);
delete [] bytes;
}
} else if (element->GetType() == PDE_TYPE_FILE) {
ss << "\n\tFile: " << std::string(element->GetFile());
}
}
}
}
return ss.str();
}
std::string GetDataURI(const std::string& data,
const std::string& mime_type) {
return "data:" + mime_type + ";base64," +
CefURIEncode(CefBase64Encode(data.data(), data.size()), false).ToString();
}
std::string GetErrorString(cef_errorcode_t code) {
// Case condition that returns |code| as a string.
#define CASE(code) case code: return #code
switch (code) {
CASE(ERR_NONE);
CASE(ERR_FAILED);
CASE(ERR_ABORTED);
CASE(ERR_INVALID_ARGUMENT);
CASE(ERR_INVALID_HANDLE);
CASE(ERR_FILE_NOT_FOUND);
CASE(ERR_TIMED_OUT);
CASE(ERR_FILE_TOO_BIG);
CASE(ERR_UNEXPECTED);
CASE(ERR_ACCESS_DENIED);
CASE(ERR_NOT_IMPLEMENTED);
CASE(ERR_CONNECTION_CLOSED);
CASE(ERR_CONNECTION_RESET);
CASE(ERR_CONNECTION_REFUSED);
CASE(ERR_CONNECTION_ABORTED);
CASE(ERR_CONNECTION_FAILED);
CASE(ERR_NAME_NOT_RESOLVED);
CASE(ERR_INTERNET_DISCONNECTED);
CASE(ERR_SSL_PROTOCOL_ERROR);
CASE(ERR_ADDRESS_INVALID);
CASE(ERR_ADDRESS_UNREACHABLE);
CASE(ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
CASE(ERR_TUNNEL_CONNECTION_FAILED);
CASE(ERR_NO_SSL_VERSIONS_ENABLED);
CASE(ERR_SSL_VERSION_OR_CIPHER_MISMATCH);
CASE(ERR_SSL_RENEGOTIATION_REQUESTED);
CASE(ERR_CERT_COMMON_NAME_INVALID);
CASE(ERR_CERT_DATE_INVALID);
CASE(ERR_CERT_AUTHORITY_INVALID);
CASE(ERR_CERT_CONTAINS_ERRORS);
CASE(ERR_CERT_NO_REVOCATION_MECHANISM);
CASE(ERR_CERT_UNABLE_TO_CHECK_REVOCATION);
CASE(ERR_CERT_REVOKED);
CASE(ERR_CERT_INVALID);
CASE(ERR_CERT_END);
CASE(ERR_INVALID_URL);
CASE(ERR_DISALLOWED_URL_SCHEME);
CASE(ERR_UNKNOWN_URL_SCHEME);
CASE(ERR_TOO_MANY_REDIRECTS);
CASE(ERR_UNSAFE_REDIRECT);
CASE(ERR_UNSAFE_PORT);
CASE(ERR_INVALID_RESPONSE);
CASE(ERR_INVALID_CHUNKED_ENCODING);
CASE(ERR_METHOD_NOT_SUPPORTED);
CASE(ERR_UNEXPECTED_PROXY_AUTH);
CASE(ERR_EMPTY_RESPONSE);
CASE(ERR_RESPONSE_HEADERS_TOO_BIG);
CASE(ERR_CACHE_MISS);
CASE(ERR_INSECURE_RESPONSE);
default:
return "UNKNOWN";
}
}
void SetupResourceManager(CefRefPtr<CefResourceManager> resource_manager) {
const std::string& test_origin = kTestOrigin;
// Add the URL filter.
resource_manager->SetUrlFilter(base::Bind(RequestUrlFilter));
// Add provider for resource dumps.
resource_manager->AddProvider(
new RequestDumpResourceProvider(test_origin + "request.html"),
0, std::string());
// Add provider for bundled resource files.
#if defined(OS_WIN)
// Read resources from the binary.
resource_manager->AddProvider(CreateBinaryResourceProvider(test_origin),
100, std::string());
#elif defined(OS_POSIX)
// Read resources from a directory on disk.
std::string resource_dir;
if (GetResourceDir(resource_dir)) {
resource_manager->AddDirectoryProvider(test_origin, resource_dir,
100, std::string());
}
#endif
}
void Alert(CefRefPtr<CefBrowser> browser, const std::string& message) {
// Escape special characters in the message.
std::string msg = StringReplace(message, "\\", "\\\\");
msg = StringReplace(msg, "'", "\\'");
// Execute a JavaScript alert().
CefRefPtr<CefFrame> frame = browser->GetMainFrame();
frame->ExecuteJavaScript("alert('" + msg + "');", frame->GetURL(), 0);
}
void CreateMessageHandlers(MessageHandlerSet& handlers) {
handlers.insert(new PromptHandler);
// Create the dialog test handlers.
dialog_test::CreateMessageHandlers(handlers);
// Create the binding test handlers.
binding_test::CreateMessageHandlers(handlers);
// Create the urlrequest test handlers.
urlrequest_test::CreateMessageHandlers(handlers);
// Create the window test handlers.
window_test::CreateMessageHandlers(handlers);
}
void RegisterSchemeHandlers() {
// Register the scheme handler.
scheme_test::RegisterSchemeHandlers();
}
} // namespace test_runner
} // namespace client

View File

@ -0,0 +1,50 @@
// 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_TEST_RUNNER_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_TEST_RUNNER_H_
#pragma once
#include <set>
#include <string>
#include "include/cef_browser.h"
#include "include/cef_request.h"
#include "include/wrapper/cef_message_router.h"
#include "include/wrapper/cef_resource_manager.h"
namespace client {
namespace test_runner {
// Run a test.
void RunTest(CefRefPtr<CefBrowser> browser, int id);
// Returns the contents of the CefRequest as a string.
std::string DumpRequestContents(CefRefPtr<CefRequest> request);
// Returns a data: URI with the specified contents.
std::string GetDataURI(const std::string& data,
const std::string& mime_type);
// Returns the string representation of the specified error code.
std::string GetErrorString(cef_errorcode_t code);
// Set up the resource manager for tests.
void SetupResourceManager(CefRefPtr<CefResourceManager> resource_manager);
// Show a JS alert message.
void Alert(CefRefPtr<CefBrowser> browser, const std::string& message);
// Create all CefMessageRouterBrowserSide::Handler objects. They will be
// deleted when the ClientHandler is destroyed.
typedef std::set<CefMessageRouterBrowserSide::Handler*> MessageHandlerSet;
void CreateMessageHandlers(MessageHandlerSet& handlers);
// Register scheme handlers for tests.
void RegisterSchemeHandlers();
} // namespace test_runner
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_TEST_RUNNER_H_

View File

@ -0,0 +1,190 @@
// 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 "cefclient/browser/urlrequest_test.h"
#include <string>
#include "include/base/cef_bind.h"
#include "include/base/cef_callback.h"
#include "include/base/cef_logging.h"
#include "include/cef_urlrequest.h"
#include "include/wrapper/cef_helpers.h"
namespace client {
namespace urlrequest_test {
namespace {
const char kTestUrl[] = "http://tests/urlrequest";
const char kTestMessageName[] = "URLRequestTest";
// Implementation of CefURLRequestClient that stores response information. Only
// accessed on the UI thread.
class RequestClient : public CefURLRequestClient {
public:
// Callback to be executed on request completion.
typedef base::Callback<void(CefURLRequest::ErrorCode /*error_code*/,
const std::string& /*download_data*/)> Callback;
explicit RequestClient(const Callback& callback)
: callback_(callback) {
CEF_REQUIRE_UI_THREAD();
DCHECK(!callback_.is_null());
}
void Detach() {
CEF_REQUIRE_UI_THREAD();
if (!callback_.is_null())
callback_.Reset();
}
void OnRequestComplete(CefRefPtr<CefURLRequest> request) OVERRIDE {
CEF_REQUIRE_UI_THREAD();
if (!callback_.is_null()) {
callback_.Run(request->GetRequestError(), download_data_);
callback_.Reset();
}
}
void OnUploadProgress(CefRefPtr<CefURLRequest> request,
int64 current,
int64 total) OVERRIDE {
}
void OnDownloadProgress(CefRefPtr<CefURLRequest> request,
int64 current,
int64 total) OVERRIDE {
}
void OnDownloadData(CefRefPtr<CefURLRequest> request,
const void* data,
size_t data_length) OVERRIDE {
CEF_REQUIRE_UI_THREAD();
download_data_ += std::string(static_cast<const char*>(data), data_length);
}
bool GetAuthCredentials(bool isProxy,
const CefString& host,
int port,
const CefString& realm,
const CefString& scheme,
CefRefPtr<CefAuthCallback> callback) OVERRIDE {
return false;
}
private:
Callback callback_;
std::string download_data_;
IMPLEMENT_REFCOUNTING(RequestClient);
DISALLOW_COPY_AND_ASSIGN(RequestClient);
};
// Handle messages in the browser process. Only accessed on the UI thread.
class Handler : public CefMessageRouterBrowserSide::Handler {
public:
Handler() {
CEF_REQUIRE_UI_THREAD();
}
~Handler() {
CancelPendingRequest();
}
// Called due to cefQuery execution in urlrequest.html.
bool OnQuery(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int64 query_id,
const CefString& request,
bool persistent,
CefRefPtr<Callback> callback) OVERRIDE {
CEF_REQUIRE_UI_THREAD();
// Only handle messages from the test URL.
std::string url = frame->GetURL();
if (url.find(kTestUrl) != 0)
return false;
const std::string& message_name = request;
if (message_name.find(kTestMessageName) == 0) {
url = message_name.substr(sizeof(kTestMessageName));
CancelPendingRequest();
DCHECK(!callback_.get());
DCHECK(!urlrequest_.get());
callback_ = callback;
// Create a CefRequest for the specified URL.
CefRefPtr<CefRequest> cef_request = CefRequest::Create();
cef_request->SetURL(url);
cef_request->SetMethod("GET");
// Callback to be executed on request completion.
// It's safe to use base::Unretained() here because there is only one
// RequestClient pending at any given time and we explicitly detach the
// callback in the Handler destructor.
const RequestClient::Callback& request_callback =
base::Bind(&Handler::OnRequestComplete, base::Unretained(this));
// Create and start the new CefURLRequest.
urlrequest_ = CefURLRequest::Create(cef_request,
new RequestClient(request_callback),
NULL);
return true;
}
return false;
}
private:
// Cancel the currently pending URL request, if any.
void CancelPendingRequest() {
CEF_REQUIRE_UI_THREAD();
if (urlrequest_.get()) {
// Don't execute the callback when we explicitly cancel the request.
static_cast<RequestClient*>(urlrequest_->GetClient().get())->Detach();
urlrequest_->Cancel();
urlrequest_ = NULL;
}
if (callback_.get()) {
// Must always execute |callback_| before deleting it.
callback_->Failure(ERR_ABORTED, test_runner::GetErrorString(ERR_ABORTED));
callback_ = NULL;
}
}
void OnRequestComplete(CefURLRequest::ErrorCode error_code,
const std::string& download_data) {
CEF_REQUIRE_UI_THREAD();
if (error_code == ERR_NONE)
callback_->Success(download_data);
else
callback_->Failure(error_code, test_runner::GetErrorString(error_code));
callback_ = NULL;
urlrequest_ = NULL;
}
CefRefPtr<Callback> callback_;
CefRefPtr<CefURLRequest> urlrequest_;
DISALLOW_COPY_AND_ASSIGN(Handler);
};
} // namespace
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
handlers.insert(new Handler());
}
} // namespace urlrequest_test
} // namespace client

View File

@ -0,0 +1,20 @@
// 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_URLREQUEST_TEST_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_URLREQUEST_TEST_H_
#pragma once
#include "cefclient/browser/test_runner.h"
namespace client {
namespace urlrequest_test {
// Create message handlers. Called from test_runner.cc.
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers);
} // namespace urlrequest_test
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_URLREQUEST_TEST_H_

View File

@ -0,0 +1,110 @@
// Copyright (c) 2013 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 "cefclient/browser/window_test.h"
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include "include/base/cef_bind.h"
#include "include/wrapper/cef_stream_resource_handler.h"
#include "cefclient/browser/main_message_loop.h"
namespace client {
namespace window_test {
namespace {
const char kTestUrl[] = "http://tests/window";
const char kMessagePositionName[] = "WindowTest.Position";
const char kMessageMinimizeName[] = "WindowTest.Minimize";
const char kMessageMaximizeName[] = "WindowTest.Maximize";
const char kMessageRestoreName[] = "WindowTest.Restore";
// Handle messages in the browser process.
class Handler : public CefMessageRouterBrowserSide::Handler {
public:
Handler() {}
// Called due to cefBroadcast execution in window.html.
virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int64 query_id,
const CefString& request,
bool persistent,
CefRefPtr<Callback> callback) OVERRIDE {
// Only handle messages from the test URL.
const std::string& url = frame->GetURL();
if (url.find(kTestUrl) != 0)
return false;
const std::string& message_name = request;
if (message_name.find(kMessagePositionName) == 0) {
// Parse the comma-delimited list of integer values.
std::vector<int> vec;
const std::string& vals =
message_name.substr(sizeof(kMessagePositionName));
std::stringstream ss(vals);
int i;
while (ss >> i) {
vec.push_back(i);
if (ss.peek() == ',')
ss.ignore();
}
if (vec.size() == 4) {
// Execute SetPos() on the main thread.
MAIN_POST_CLOSURE(base::Bind(&SetPos, browser,
vec[0], vec[1], vec[2], vec[3]));
}
} else if (message_name == kMessageMinimizeName) {
// Execute Minimize() on the main thread.
MAIN_POST_CLOSURE(base::Bind(&Minimize, browser));
} else if (message_name == kMessageMaximizeName) {
// Execute Maximize() on the main thread.
MAIN_POST_CLOSURE(base::Bind(&Maximize, browser));
} else if (message_name == kMessageRestoreName) {
// Execute Restore() on the main thread.
MAIN_POST_CLOSURE(base::Bind(&Restore, browser));
} else {
NOTREACHED();
}
callback->Success("");
return true;
}
};
} // namespace
void ModifyBounds(const CefRect& display, CefRect& window) {
window.x += display.x;
window.y += display.y;
if (window.x < display.x)
window.x = display.x;
if (window.y < display.y)
window.y = display.y;
if (window.width < 100)
window.width = 100;
else if (window.width >= display.width)
window.width = display.width;
if (window.height < 100)
window.height = 100;
else if (window.height >= display.height)
window.height = display.height;
if (window.x + window.width >= display.x + display.width)
window.x = display.x + display.width - window.width;
if (window.y + window.height >= display.y + display.height)
window.y = display.y + display.height - window.height;
}
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
handlers.insert(new Handler());
}
} // namespace window_test
} // namespace client

View File

@ -0,0 +1,31 @@
// Copyright (c) 2013 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_WINDOW_TEST_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_TEST_H_
#pragma once
#include "cefclient/browser/test_runner.h"
namespace client {
namespace window_test {
// Create message handlers. Called from test_runner.cc.
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers);
// Fit |window| inside |display|. Coordinates are relative to the upper-left
// corner of the display.
void ModifyBounds(const CefRect& display, CefRect& window);
// Platform implementations.
void SetPos(CefRefPtr<CefBrowser> browser,
int x, int y, int width, int height);
void Minimize(CefRefPtr<CefBrowser> browser);
void Maximize(CefRefPtr<CefBrowser> browser);
void Restore(CefRefPtr<CefBrowser> browser);
} // namespace window_test
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_WINDOW_TEST_H_

View File

@ -0,0 +1,81 @@
// Copyright (c) 2013 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 "cefclient/browser/window_test.h"
#include <gtk/gtk.h>
#include "cefclient/browser/root_window.h"
namespace client {
namespace window_test {
namespace {
GtkWindow* GetWindow(CefRefPtr<CefBrowser> browser) {
scoped_refptr<RootWindow> root_window =
RootWindow::GetForBrowser(browser->GetIdentifier());
if (root_window.get())
return GTK_WINDOW(root_window->GetWindowHandle());
return NULL;
}
bool IsMaximized(GtkWindow* window) {
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
gint state = gdk_window_get_state(gdk_window);
return (state & GDK_WINDOW_STATE_MAXIMIZED) ? true : false;
}
} // namespace
void SetPos(CefRefPtr<CefBrowser> browser, int x, int y, int width,
int height) {
GtkWindow* window = GetWindow(browser);
GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window));
// Make sure the window isn't minimized or maximized.
if (IsMaximized(window))
gtk_window_unmaximize(window);
else
gtk_window_present(window);
// Retrieve information about the display that contains the window.
GdkScreen* screen = gdk_screen_get_default();
gint monitor = gdk_screen_get_monitor_at_window(screen, gdk_window);
GdkRectangle rect;
gdk_screen_get_monitor_geometry(screen, monitor, &rect);
// Make sure the window is inside the display.
CefRect display_rect(rect.x, rect.y, rect.width, rect.height);
CefRect window_rect(x, y, width, height);
ModifyBounds(display_rect, window_rect);
gdk_window_move_resize(gdk_window, window_rect.x, window_rect.y,
window_rect.width, window_rect.height);
}
void Minimize(CefRefPtr<CefBrowser> browser) {
GtkWindow* window = GetWindow(browser);
// Unmaximize the window before minimizing so restore behaves correctly.
if (IsMaximized(window))
gtk_window_unmaximize(window);
gtk_window_iconify(window);
}
void Maximize(CefRefPtr<CefBrowser> browser) {
gtk_window_maximize(GetWindow(browser));
}
void Restore(CefRefPtr<CefBrowser> browser) {
GtkWindow* window = GetWindow(browser);
if (IsMaximized(window))
gtk_window_unmaximize(window);
else
gtk_window_present(window);
}
} // namespace window_test
} // namespace client

View File

@ -0,0 +1,143 @@
// Copyright (c) 2013 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 <gtk/gtk.h>
#include <gtk/gtkgl.h>
#include <X11/Xlib.h>
#undef Success // Definition conflicts with cef_message_router.h
#undef RootWindow // Definition conflicts with root_window.h
#include <stdlib.h>
#include <unistd.h>
#include <string>
#include "include/base/cef_logging.h"
#include "include/base/cef_scoped_ptr.h"
#include "include/cef_app.h"
#include "include/cef_command_line.h"
#include "include/wrapper/cef_helpers.h"
#include "cefclient/browser/client_app_browser.h"
#include "cefclient/browser/main_context_impl.h"
#include "cefclient/browser/main_message_loop_std.h"
#include "cefclient/browser/test_runner.h"
#include "cefclient/common/client_app_other.h"
#include "cefclient/renderer/client_app_renderer.h"
namespace client {
namespace {
int XErrorHandlerImpl(Display *display, XErrorEvent *event) {
LOG(WARNING)
<< "X error received: "
<< "type " << event->type << ", "
<< "serial " << event->serial << ", "
<< "error_code " << static_cast<int>(event->error_code) << ", "
<< "request_code " << static_cast<int>(event->request_code) << ", "
<< "minor_code " << static_cast<int>(event->minor_code);
return 0;
}
int XIOErrorHandlerImpl(Display *display) {
return 0;
}
void TerminationSignalHandler(int signatl) {
LOG(ERROR) << "Received termination signal: " << signatl;
MainContext::Get()->GetRootWindowManager()->CloseAllWindows(true);
}
int RunMain(int argc, char* argv[]) {
// Create a copy of |argv| on Linux because Chromium mangles the value
// internally (see issue #620).
CefScopedArgArray scoped_arg_array(argc, argv);
char** argv_copy = scoped_arg_array.array();
CefMainArgs main_args(argc, argv);
// Parse command-line arguments.
CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
command_line->InitFromArgv(argc, argv);
// Create a ClientApp of the correct type.
CefRefPtr<CefApp> app;
ClientApp::ProcessType process_type = ClientApp::GetProcessType(command_line);
if (process_type == ClientApp::BrowserProcess) {
app = new ClientAppBrowser();
} else if (process_type == ClientApp::RendererProcess ||
process_type == ClientApp::ZygoteProcess) {
// On Linux the zygote process is used to spawn other process types. Since
// we don't know what type of process it will be give it the renderer
// client.
app = new ClientAppRenderer();
} else if (process_type == ClientApp::OtherProcess) {
app = new ClientAppOther();
}
// Execute the secondary process, if any.
int exit_code = CefExecuteProcess(main_args, app, NULL);
if (exit_code >= 0)
return exit_code;
// Create the main context object.
scoped_ptr<MainContextImpl> context(new MainContextImpl(command_line, true));
CefSettings settings;
// Populate the settings based on command line arguments.
context->PopulateSettings(&settings);
// Install xlib error handlers so that the application won't be terminated
// on non-fatal errors.
XSetErrorHandler(XErrorHandlerImpl);
XSetIOErrorHandler(XIOErrorHandlerImpl);
// Create the main message loop object.
scoped_ptr<MainMessageLoop> message_loop(new MainMessageLoopStd);
// Initialize CEF.
context->Initialize(main_args, settings, app, NULL);
// The Chromium sandbox requires that there only be a single thread during
// initialization. Therefore initialize GTK after CEF.
gtk_init(&argc, &argv_copy);
// Perform gtkglext initialization required by the OSR example.
gtk_gl_init(&argc, &argv_copy);
// Install a signal handler so we clean up after ourselves.
signal(SIGINT, TerminationSignalHandler);
signal(SIGTERM, TerminationSignalHandler);
// Register scheme handlers.
test_runner::RegisterSchemeHandlers();
// Create the first window.
context->GetRootWindowManager()->CreateRootWindow(
true, // Show controls.
settings.windowless_rendering_enabled ? true : false,
CefRect(), // Use default system size.
std::string()); // Use default URL.
// Run the message loop. This will block until Quit() is called.
int result = message_loop->Run();
// Shut down CEF.
context->Shutdown();
// Release objects in reverse order of creation.
message_loop.reset();
context.reset();
return result;
}
} // namespace
} // namespace client
// Program entry point function.
int main(int argc, char* argv[]) {
return client::RunMain(argc, argv);
}

View File

@ -0,0 +1,49 @@
// Copyright (c) 2013 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 "cefclient/common/client_app.h"
#include "include/cef_command_line.h"
namespace client {
namespace {
// These flags must match the Chromium values.
const char kProcessType[] = "type";
const char kRendererProcess[] = "renderer";
#if defined(OS_LINUX)
const char kZygoteProcess[] = "zygote";
#endif
} // namespace
ClientApp::ClientApp() {
}
// static
ClientApp::ProcessType ClientApp::GetProcessType(
CefRefPtr<CefCommandLine> command_line) {
// The command-line flag won't be specified for the browser process.
if (!command_line->HasSwitch(kProcessType))
return BrowserProcess;
const std::string& process_type = command_line->GetSwitchValue(kProcessType);
if (process_type == kRendererProcess)
return RendererProcess;
#if defined(OS_LINUX)
else if (process_type == kZygoteProcess)
return ZygoteProcess;
#endif
return OtherProcess;
}
void ClientApp::OnRegisterCustomSchemes(
CefRefPtr<CefSchemeRegistrar> registrar) {
RegisterCustomSchemes(registrar, cookieable_schemes_);
}
} // namespace client

View File

@ -0,0 +1,49 @@
// Copyright (c) 2013 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_COMMON_CLIENT_APP_H_
#define CEF_TESTS_CEFCLIENT_COMMON_CLIENT_APP_H_
#pragma once
#include <vector>
#include "include/cef_app.h"
namespace client {
// Base class for customizing process-type-based behavior.
class ClientApp : public CefApp {
public:
ClientApp();
enum ProcessType {
BrowserProcess,
RendererProcess,
ZygoteProcess,
OtherProcess,
};
// Determine the process type based on command-line arguments.
static ProcessType GetProcessType(CefRefPtr<CefCommandLine> command_line);
protected:
// Schemes that will be registered with the global cookie manager.
std::vector<CefString> cookieable_schemes_;
private:
// Registers custom schemes. Implemented by cefclient in
// client_app_delegates_common.cc
static void RegisterCustomSchemes(CefRefPtr<CefSchemeRegistrar> registrar,
std::vector<CefString>& cookiable_schemes);
// CefApp methods.
void OnRegisterCustomSchemes(
CefRefPtr<CefSchemeRegistrar> registrar) OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(ClientApp);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_COMMON_CLIENT_APP_H_

View File

@ -0,0 +1,17 @@
// Copyright (c) 2012 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 "cefclient/common/client_app.h"
#include "cefclient/common/scheme_test_common.h"
namespace client {
// static
void ClientApp::RegisterCustomSchemes(
CefRefPtr<CefSchemeRegistrar> registrar,
std::vector<CefString>& cookiable_schemes) {
scheme_test::RegisterCustomSchemes(registrar, cookiable_schemes);
}
} // namespace client

View File

@ -0,0 +1,14 @@
// 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 "cefclient/common/client_app_other.h"
#include "include/cef_command_line.h"
namespace client {
ClientAppOther::ClientAppOther() {
}
} // namespace client

View File

@ -0,0 +1,25 @@
// 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_COMMON_CLIENT_APP_OTHER_H_
#define CEF_TESTS_CEFCLIENT_COMMON_CLIENT_APP_OTHER_H_
#pragma once
#include "cefclient/common/client_app.h"
namespace client {
// Client app implementation for other process types.
class ClientAppOther : public ClientApp {
public:
ClientAppOther();
private:
IMPLEMENT_REFCOUNTING(ClientAppOther);
DISALLOW_COPY_AND_ASSIGN(ClientAppOther);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_COMMON_CLIENT_APP_OTHER_H_

View File

@ -0,0 +1,33 @@
// Copyright (c) 2013 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 "cefclient/common/client_switches.h"
namespace client {
namespace switches {
// CEF and Chromium support a wide range of command-line switches. This file
// only contains command-line switches specific to the cefclient application.
// View CEF/Chromium documentation or search for *_switches.cc files in the
// Chromium source code to identify other existing command-line switches.
// Below is a partial listing of relevant *_switches.cc files:
// base/base_switches.cc
// cef/libcef/common/cef_switches.cc
// chrome/common/chrome_switches.cc (not all apply)
// content/public/common/content_switches.cc
const char kMultiThreadedMessageLoop[] = "multi-threaded-message-loop";
const char kCachePath[] = "cache-path";
const char kUrl[] = "url";
const char kOffScreenRenderingEnabled[] = "off-screen-rendering-enabled";
const char kOffScreenFrameRate[] = "off-screen-frame-rate";
const char kTransparentPaintingEnabled[] = "transparent-painting-enabled";
const char kShowUpdateRect[] = "show-update-rect";
const char kMouseCursorChangeDisabled[] = "mouse-cursor-change-disabled";
const char kRequestContextPerBrowser[] = "request-context-per-browser";
const char kBackgroundColor[] = "background-color";
const char kEnableGPU[] = "enable-gpu";
} // namespace switches
} // namespace client

View File

@ -0,0 +1,29 @@
// Copyright (c) 2013 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.
// Defines all of the command line switches used by cefclient.
#ifndef CEF_TESTS_CEFCLIENT_CEFCLIENT_COMMON_SWITCHES_H_
#define CEF_TESTS_CEFCLIENT_CEFCLIENT_COMMON_SWITCHES_H_
#pragma once
namespace client {
namespace switches {
extern const char kMultiThreadedMessageLoop[];
extern const char kCachePath[];
extern const char kUrl[];
extern const char kOffScreenRenderingEnabled[];
extern const char kOffScreenFrameRate[];
extern const char kTransparentPaintingEnabled[];
extern const char kShowUpdateRect[];
extern const char kMouseCursorChangeDisabled[];
extern const char kRequestContextPerBrowser[];
extern const char kBackgroundColor[];
extern const char kEnableGPU[];
} // namespace switches
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_CEFCLIENT_COMMON_SWITCHES_H_

View File

@ -0,0 +1,18 @@
// Copyright (c) 2012 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 "cefclient/common/scheme_test_common.h"
#include "include/cef_scheme.h"
namespace client {
namespace scheme_test {
void RegisterCustomSchemes(CefRefPtr<CefSchemeRegistrar> registrar,
std::vector<CefString>& cookiable_schemes) {
registrar->AddCustomScheme("client", true, false, false);
}
} // namespace scheme_test
} // namespace client

View File

@ -0,0 +1,26 @@
// Copyright (c) 2009 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_COMMON_SCHEME_TEST_COMMON_H_
#define CEF_TESTS_CEFCLIENT_COMMON_SCHEME_TEST_COMMON_H_
#pragma once
#include <vector>
#include "include/cef_scheme.h"
namespace client {
namespace scheme_test {
// Register the custom scheme name/type. This must be done in all processes.
// See browser/scheme_test.h for creation/registration of the custom scheme
// handler which only occurs in the browser process. Called from
// client_app_delegates_common.cc.
void RegisterCustomSchemes(CefRefPtr<CefSchemeRegistrar> registrar,
std::vector<CefString>& cookiable_schemes);
} // namespace scheme_test
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_COMMON_SCHEME_TEST_COMMON_H_

View File

@ -0,0 +1,17 @@
// Copyright (c) 2012 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 "cefclient/renderer/client_app_renderer.h"
#include "cefclient/renderer/client_renderer.h"
#include "cefclient/renderer/performance_test.h"
namespace client {
// static
void ClientAppRenderer::CreateDelegates(DelegateSet& delegates) {
renderer::CreateDelegates(delegates);
performance_test::CreateDelegates(delegates);
}
} // namespace client

View File

@ -0,0 +1,120 @@
// Copyright (c) 2013 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 "cefclient/renderer/client_app_renderer.h"
#include "include/base/cef_logging.h"
namespace client {
ClientAppRenderer::ClientAppRenderer() {
}
void ClientAppRenderer::OnRenderThreadCreated(
CefRefPtr<CefListValue> extra_info) {
CreateDelegates(delegates_);
DelegateSet::iterator it = delegates_.begin();
for (; it != delegates_.end(); ++it)
(*it)->OnRenderThreadCreated(this, extra_info);
}
void ClientAppRenderer::OnWebKitInitialized() {
DelegateSet::iterator it = delegates_.begin();
for (; it != delegates_.end(); ++it)
(*it)->OnWebKitInitialized(this);
}
void ClientAppRenderer::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
DelegateSet::iterator it = delegates_.begin();
for (; it != delegates_.end(); ++it)
(*it)->OnBrowserCreated(this, browser);
}
void ClientAppRenderer::OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) {
DelegateSet::iterator it = delegates_.begin();
for (; it != delegates_.end(); ++it)
(*it)->OnBrowserDestroyed(this, browser);
}
CefRefPtr<CefLoadHandler> ClientAppRenderer::GetLoadHandler() {
CefRefPtr<CefLoadHandler> load_handler;
DelegateSet::iterator it = delegates_.begin();
for (; it != delegates_.end() && !load_handler.get(); ++it)
load_handler = (*it)->GetLoadHandler(this);
return load_handler;
}
bool ClientAppRenderer::OnBeforeNavigation(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
NavigationType navigation_type,
bool is_redirect) {
DelegateSet::iterator it = delegates_.begin();
for (; it != delegates_.end(); ++it) {
if ((*it)->OnBeforeNavigation(this, browser, frame, request,
navigation_type, is_redirect)) {
return true;
}
}
return false;
}
void ClientAppRenderer::OnContextCreated(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) {
DelegateSet::iterator it = delegates_.begin();
for (; it != delegates_.end(); ++it)
(*it)->OnContextCreated(this, browser, frame, context);
}
void ClientAppRenderer::OnContextReleased(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) {
DelegateSet::iterator it = delegates_.begin();
for (; it != delegates_.end(); ++it)
(*it)->OnContextReleased(this, browser, frame, context);
}
void ClientAppRenderer::OnUncaughtException(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) {
DelegateSet::iterator it = delegates_.begin();
for (; it != delegates_.end(); ++it) {
(*it)->OnUncaughtException(this, browser, frame, context, exception,
stackTrace);
}
}
void ClientAppRenderer::OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefDOMNode> node) {
DelegateSet::iterator it = delegates_.begin();
for (; it != delegates_.end(); ++it)
(*it)->OnFocusedNodeChanged(this, browser, frame, node);
}
bool ClientAppRenderer::OnProcessMessageReceived(
CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) {
DCHECK_EQ(source_process, PID_BROWSER);
bool handled = false;
DelegateSet::iterator it = delegates_.begin();
for (; it != delegates_.end() && !handled; ++it) {
handled = (*it)->OnProcessMessageReceived(this, browser, source_process,
message);
}
return handled;
}
} // namespace client

View File

@ -0,0 +1,138 @@
// Copyright (c) 2013 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_RENDERER_CLIENT_APP_RENDERER_H_
#define CEF_TESTS_CEFCLIENT_RENDERER_CLIENT_APP_RENDERER_H_
#pragma once
#include <set>
#include "cefclient/common/client_app.h"
namespace client {
// Client app implementation for the renderer process.
class ClientAppRenderer : public ClientApp,
public CefRenderProcessHandler {
public:
// Interface for renderer delegates. All Delegates must be returned via
// CreateDelegates. Do not perform work in the Delegate
// constructor. See CefRenderProcessHandler for documentation.
class Delegate : public virtual CefBase {
public:
virtual void OnRenderThreadCreated(CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefListValue> extra_info) {}
virtual void OnWebKitInitialized(CefRefPtr<ClientAppRenderer> app) {}
virtual void OnBrowserCreated(CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefBrowser> browser) {}
virtual void OnBrowserDestroyed(CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefBrowser> browser) {}
virtual CefRefPtr<CefLoadHandler> GetLoadHandler(
CefRefPtr<ClientAppRenderer> app) {
return NULL;
}
virtual bool OnBeforeNavigation(CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
cef_navigation_type_t navigation_type,
bool is_redirect) {
return false;
}
virtual void OnContextCreated(CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) {}
virtual void OnContextReleased(CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) {}
virtual void OnUncaughtException(CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) {}
virtual void OnFocusedNodeChanged(CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefDOMNode> node) {}
// Called when a process message is received. Return true if the message was
// handled and should not be passed on to other handlers. Delegates
// should check for unique message names to avoid interfering with each
// other.
virtual bool OnProcessMessageReceived(
CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) {
return false;
}
};
typedef std::set<CefRefPtr<Delegate> > DelegateSet;
ClientAppRenderer();
private:
// Creates all of the Delegate objects. Implemented by cefclient in
// client_app_delegates_renderer.cc
static void CreateDelegates(DelegateSet& delegates);
// CefApp methods.
CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() OVERRIDE {
return this;
}
// CefRenderProcessHandler methods.
void OnRenderThreadCreated(CefRefPtr<CefListValue> extra_info) OVERRIDE;
void OnWebKitInitialized() OVERRIDE;
void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
void OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) OVERRIDE;
CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE;
bool OnBeforeNavigation(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
NavigationType navigation_type,
bool is_redirect) OVERRIDE;
void OnContextCreated(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) OVERRIDE;
void OnContextReleased(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) OVERRIDE;
void OnUncaughtException(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) OVERRIDE;
void OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefDOMNode> node) OVERRIDE;
bool OnProcessMessageReceived(
CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) OVERRIDE;
private:
// Set of supported Delegates.
DelegateSet delegates_;
IMPLEMENT_REFCOUNTING(ClientAppRenderer);
DISALLOW_COPY_AND_ASSIGN(ClientAppRenderer);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_RENDERER_CLIENT_APP_RENDERER_H_

View File

@ -0,0 +1,88 @@
// Copyright (c) 2012 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 "cefclient/renderer/client_renderer.h"
#include <sstream>
#include <string>
#include "include/cef_dom.h"
#include "include/wrapper/cef_helpers.h"
#include "include/wrapper/cef_message_router.h"
namespace client {
namespace renderer {
namespace {
// Must match the value in client_handler.cc.
const char kFocusedNodeChangedMessage[] = "ClientRenderer.FocusedNodeChanged";
class ClientRenderDelegate : public ClientAppRenderer::Delegate {
public:
ClientRenderDelegate()
: last_node_is_editable_(false) {
}
virtual void OnWebKitInitialized(CefRefPtr<ClientAppRenderer> app) OVERRIDE {
// Create the renderer-side router for query handling.
CefMessageRouterConfig config;
message_router_ = CefMessageRouterRendererSide::Create(config);
}
virtual void OnContextCreated(CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) OVERRIDE {
message_router_->OnContextCreated(browser, frame, context);
}
virtual void OnContextReleased(CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) OVERRIDE {
message_router_->OnContextReleased(browser, frame, context);
}
virtual void OnFocusedNodeChanged(CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefDOMNode> node) OVERRIDE {
bool is_editable = (node.get() && node->IsEditable());
if (is_editable != last_node_is_editable_) {
// Notify the browser of the change in focused element type.
last_node_is_editable_ = is_editable;
CefRefPtr<CefProcessMessage> message =
CefProcessMessage::Create(kFocusedNodeChangedMessage);
message->GetArgumentList()->SetBool(0, is_editable);
browser->SendProcessMessage(PID_BROWSER, message);
}
}
virtual bool OnProcessMessageReceived(
CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) OVERRIDE {
return message_router_->OnProcessMessageReceived(
browser, source_process, message);
}
private:
bool last_node_is_editable_;
// Handles the renderer side of query routing.
CefRefPtr<CefMessageRouterRendererSide> message_router_;
IMPLEMENT_REFCOUNTING(ClientRenderDelegate);
};
} // namespace
void CreateDelegates(ClientAppRenderer::DelegateSet& delegates) {
delegates.insert(new ClientRenderDelegate);
}
} // namespace renderer
} // namespace client

View File

@ -0,0 +1,21 @@
// Copyright (c) 2012 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_RENDERER_CLIENT_RENDERER_H_
#define CEF_TESTS_CEFCLIENT_RENDERER_CLIENT_RENDERER_H_
#pragma once
#include "include/cef_base.h"
#include "cefclient/renderer/client_app_renderer.h"
namespace client {
namespace renderer {
// Create the renderer delegate. Called from client_app_delegates_renderer.cc.
void CreateDelegates(ClientAppRenderer::DelegateSet& delegates);
} // namespace renderer
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_RENDERER_CLIENT_RENDERER_H_

View File

@ -0,0 +1,165 @@
// Copyright (c) 2012 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 "cefclient/renderer/performance_test.h"
#include <algorithm>
#include <string>
#include "include/wrapper/cef_stream_resource_handler.h"
#include "cefclient/renderer/performance_test_setup.h"
namespace client {
namespace performance_test {
// Use more interations for a Release build.
#ifdef NDEBUG
const int kDefaultIterations = 100000;
#else
const int kDefaultIterations = 10000;
#endif
namespace {
const char kGetPerfTests[] = "GetPerfTests";
const char kRunPerfTest[] = "RunPerfTest";
const char kPerfTestReturnValue[] = "PerfTestReturnValue";
class V8Handler : public CefV8Handler {
public:
V8Handler() {
}
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) {
if (name == kRunPerfTest) {
if (arguments.size() == 1 && arguments[0]->IsString()) {
// Run the specified perf test.
bool found = false;
std::string test = arguments[0]->GetStringValue();
for (int i = 0; i < kPerfTestsCount; ++i) {
if (test == kPerfTests[i].name) {
// Execute the test.
int64 delta = kPerfTests[i].test(kPerfTests[i].iterations);
retval = CefV8Value::CreateInt(delta);
found = true;
break;
}
}
if (!found) {
std::string msg = "Unknown test: ";
msg.append(test);
exception = msg;
}
} else {
exception = "Invalid function parameters";
}
} else if (name == kGetPerfTests) {
// Retrieve the list of perf tests.
retval = CefV8Value::CreateArray(kPerfTestsCount);
for (int i = 0; i < kPerfTestsCount; ++i) {
CefRefPtr<CefV8Value> val = CefV8Value::CreateArray(2);
val->SetValue(0, CefV8Value::CreateString(kPerfTests[i].name));
val->SetValue(1, CefV8Value::CreateUInt(kPerfTests[i].iterations));
retval->SetValue(i, val);
}
} else if (name == kPerfTestReturnValue) {
if (arguments.size() == 0) {
retval = CefV8Value::CreateInt(1);
} else if (arguments.size() == 1 && arguments[0]->IsInt()) {
int32 type = arguments[0]->GetIntValue();
CefTime date;
switch (type) {
case 0:
retval = CefV8Value::CreateUndefined();
break;
case 1:
retval = CefV8Value::CreateNull();
break;
case 2:
retval = CefV8Value::CreateBool(true);
break;
case 3:
retval = CefV8Value::CreateInt(1);
break;
case 4:
retval = CefV8Value::CreateUInt(1);
break;
case 5:
retval = CefV8Value::CreateDouble(1.234);
break;
case 6:
date.Now();
retval = CefV8Value::CreateDate(date);
break;
case 7:
retval = CefV8Value::CreateString("Hello, world!");
break;
case 8:
retval = CefV8Value::CreateObject(NULL);
break;
case 9:
retval = CefV8Value::CreateArray(8);
break;
case 10:
// retval = CefV8Value::CreateFunction(...);
exception = "Not implemented";
break;
default:
exception = "Not supported";
}
}
}
return true;
}
private:
IMPLEMENT_REFCOUNTING(V8Handler);
};
// Handle bindings in the render process.
class RenderDelegate : public ClientAppRenderer::Delegate {
public:
RenderDelegate() {
}
virtual void OnContextCreated(CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) OVERRIDE {
CefRefPtr<CefV8Value> object = context->GetGlobal();
CefRefPtr<CefV8Handler> handler = new V8Handler();
// Bind test functions.
object->SetValue(kGetPerfTests,
CefV8Value::CreateFunction(kGetPerfTests, handler),
V8_PROPERTY_ATTRIBUTE_READONLY);
object->SetValue(kRunPerfTest,
CefV8Value::CreateFunction(kRunPerfTest, handler),
V8_PROPERTY_ATTRIBUTE_READONLY);
object->SetValue(kPerfTestReturnValue,
CefV8Value::CreateFunction(kPerfTestReturnValue, handler),
V8_PROPERTY_ATTRIBUTE_READONLY);
}
private:
IMPLEMENT_REFCOUNTING(RenderDelegate);
};
} // namespace
void CreateDelegates(ClientAppRenderer::DelegateSet& delegates) {
delegates.insert(new RenderDelegate);
}
} // namespace performance_test
} // namespace client

View File

@ -0,0 +1,20 @@
// Copyright (c) 2012 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_RENDERER_PERFORMANCE_TEST_H_
#define CEF_TESTS_CEFCLIENT_RENDERER_PERFORMANCE_TEST_H_
#pragma once
#include "cefclient/renderer/client_app_renderer.h"
namespace client {
namespace performance_test {
// Create the renderer delegate. Called from client_app_delegates_renderer.cc.
void CreateDelegates(ClientAppRenderer::DelegateSet& delegates);
} // namespace performance_test
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_RENDERER_PERFORMANCE_TEST_H_

View File

@ -0,0 +1,104 @@
// Copyright (c) 2012 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_RENDERER_PERFORMANCE_TEST_SETUP_H_
#define CEF_TESTS_CEFCLIENT_RENDERER_PERFORMANCE_TEST_SETUP_H_
#pragma once
#include "include/base/cef_macros.h"
#include "include/base/cef_logging.h"
namespace client {
namespace performance_test {
// Default number of iterations.
extern const int kDefaultIterations;
// Test name.
#define PERF_TEST_NAME(name) PerfTest##name
// Entry in test array.
#define PERF_TEST_ENTRY_EX(name, iterations) \
{ #name, PERF_TEST_NAME(name), iterations }
#define PERF_TEST_ENTRY(name) PERF_TEST_ENTRY_EX(name, kDefaultIterations)
// Test function declaration.
#define PERF_TEST_RESULT int64
#define PERF_TEST_PARAM_ITERATIONS iterations
#define PERF_TEST_PARAMS int PERF_TEST_PARAM_ITERATIONS
#define PERF_TEST_FUNC(name) \
PERF_TEST_RESULT PERF_TEST_NAME(name)(PERF_TEST_PARAMS)
// Typedef for test pointers.
typedef PERF_TEST_RESULT(PerfTest(PERF_TEST_PARAMS));
class CefTimer {
public:
CefTimer() : running_(false) {
}
bool IsRunning() { return running_; }
void Start() {
DCHECK(!running_);
running_ = true;
start_.Now();
}
void Stop() {
stop_.Now();
DCHECK(running_);
running_ = false;
}
int64 Delta() {
DCHECK(!running_);
return start_.Delta(stop_);
}
private:
bool running_;
CefTime start_;
CefTime stop_;
DISALLOW_COPY_AND_ASSIGN(CefTimer);
};
// Peform test iterations using a user-provided timing result variable.
#define PERF_ITERATIONS_START_EX() \
{ \
CefTimer _timer; \
_timer.Start(); \
for (int _i = 0; _i < PERF_TEST_PARAM_ITERATIONS; ++_i) {
#define PERF_ITERATIONS_END_EX(result) \
} \
_timer.Stop(); \
result = _timer.Delta(); \
}
// Perform test iterations and return the timing result.
#define PERF_ITERATIONS_START() \
int64 _result = 0; \
PERF_ITERATIONS_START_EX()
#define PERF_ITERATIONS_END() \
PERF_ITERATIONS_END_EX(_result) \
return _result;
// Perf test entry structure.
struct PerfTestEntry {
const char* name;
PerfTest* test;
int iterations;
};
// Array of perf tests.
extern const PerfTestEntry kPerfTests[];
extern const int kPerfTestsCount;
} // namespace performance_test
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_RENDERER_PERFORMANCE_TEST_H_

View File

@ -0,0 +1,330 @@
// Copyright (c) 2012 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 "cefclient/renderer/performance_test.h"
#include "cefclient/renderer/performance_test_setup.h"
#include "include/cef_v8.h"
namespace client {
namespace performance_test {
namespace {
// Test function implementations.
PERF_TEST_FUNC(V8NullCreate) {
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> value = CefV8Value::CreateNull();
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8BoolCreate) {
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> value = CefV8Value::CreateBool(true);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8IntCreate) {
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> value = CefV8Value::CreateInt(-5);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8UIntCreate) {
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> value = CefV8Value::CreateUInt(10);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8DoubleCreate) {
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> value = CefV8Value::CreateDouble(12.432);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8DateCreate) {
static cef_time_t time = {2012, 1, 0, 1};
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> value = CefV8Value::CreateDate(time);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8StringCreate) {
CefString str = "test string";
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> value = CefV8Value::CreateString(str);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8ArrayCreate) {
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> value = CefV8Value::CreateArray(1);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8ArraySetValue) {
CefRefPtr<CefV8Value> val = CefV8Value::CreateBool(true);
CefRefPtr<CefV8Value> array = CefV8Value::CreateArray(1);
array->SetValue(0, val);
PERF_ITERATIONS_START()
array->SetValue(0, val);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8ArrayGetValue) {
CefRefPtr<CefV8Value> val = CefV8Value::CreateBool(true);
CefRefPtr<CefV8Value> array = CefV8Value::CreateArray(1);
array->SetValue(0, val);
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> ret = array->GetValue(0);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8FunctionCreate) {
class Handler : public CefV8Handler {
public:
Handler() {}
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE { return false; }
IMPLEMENT_REFCOUNTING(Handler);
};
CefString name = "name";
CefRefPtr<CefV8Handler> handler = new Handler();
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> value = CefV8Value::CreateFunction(name, handler);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8FunctionExecute) {
class Handler : public CefV8Handler {
public:
Handler() {}
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE { return true; }
IMPLEMENT_REFCOUNTING(Handler);
};
CefString name = "name";
CefRefPtr<CefV8Handler> handler = new Handler();
CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction(name, handler);
CefRefPtr<CefV8Value> obj = CefV8Context::GetCurrentContext()->GetGlobal();
CefV8ValueList args;
PERF_ITERATIONS_START()
func->ExecuteFunction(obj, args);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8FunctionExecuteWithContext) {
class Handler : public CefV8Handler {
public:
Handler() {}
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE { return true; }
IMPLEMENT_REFCOUNTING(Handler);
};
CefString name = "name";
CefRefPtr<CefV8Handler> handler = new Handler();
CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction(name, handler);
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
CefRefPtr<CefV8Value> obj = context->GetGlobal();
CefV8ValueList args;
PERF_ITERATIONS_START()
func->ExecuteFunctionWithContext(context, obj, args);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8ObjectCreate) {
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> value = CefV8Value::CreateObject(NULL);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8ObjectCreateWithAccessor) {
class Accessor : public CefV8Accessor {
public:
Accessor() {}
virtual bool Get(const CefString& name,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
return true;
}
virtual bool Set(const CefString& name,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE {
return true;
}
IMPLEMENT_REFCOUNTING(Accessor);
};
CefRefPtr<CefV8Accessor> accessor = new Accessor();
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> value = CefV8Value::CreateObject(accessor);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8ObjectSetValue) {
CefString name = "name";
CefRefPtr<CefV8Value> val = CefV8Value::CreateBool(true);
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(NULL);
obj->SetValue(name, val, V8_PROPERTY_ATTRIBUTE_NONE);
PERF_ITERATIONS_START()
obj->SetValue(name, val, V8_PROPERTY_ATTRIBUTE_NONE);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8ObjectGetValue) {
CefString name = "name";
CefRefPtr<CefV8Value> val = CefV8Value::CreateBool(true);
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(NULL);
obj->SetValue(name, val, V8_PROPERTY_ATTRIBUTE_NONE);
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> ret = obj->GetValue(name);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8ObjectSetValueWithAccessor) {
class Accessor : public CefV8Accessor {
public:
Accessor() {}
virtual bool Get(const CefString& name,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
return true;
}
virtual bool Set(const CefString& name,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE {
val_ = value;
return true;
}
CefRefPtr<CefV8Value> val_;
IMPLEMENT_REFCOUNTING(Accessor);
};
CefRefPtr<CefV8Accessor> accessor = new Accessor();
CefString name = "name";
CefRefPtr<CefV8Value> val = CefV8Value::CreateBool(true);
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(accessor);
obj->SetValue(name, V8_ACCESS_CONTROL_DEFAULT, V8_PROPERTY_ATTRIBUTE_NONE);
obj->SetValue(name, val, V8_PROPERTY_ATTRIBUTE_NONE);
PERF_ITERATIONS_START()
obj->SetValue(name, val, V8_PROPERTY_ATTRIBUTE_NONE);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8ObjectGetValueWithAccessor) {
class Accessor : public CefV8Accessor {
public:
Accessor() : val_(CefV8Value::CreateBool(true)) {}
virtual bool Get(const CefString& name,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
retval = val_;
return true;
}
virtual bool Set(const CefString& name,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE {
return true;
}
CefRefPtr<CefV8Value> val_;
IMPLEMENT_REFCOUNTING(Accessor);
};
CefRefPtr<CefV8Accessor> accessor = new Accessor();
CefString name = "name";
CefRefPtr<CefV8Value> val = CefV8Value::CreateBool(true);
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(accessor);
obj->SetValue(name, V8_ACCESS_CONTROL_DEFAULT, V8_PROPERTY_ATTRIBUTE_NONE);
obj->SetValue(name, val, V8_PROPERTY_ATTRIBUTE_NONE);
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> ret = obj->GetValue(name);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8ContextEnterExit) {
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
PERF_ITERATIONS_START()
context->Enter();
context->Exit();
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8ContextEval) {
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
CefString jsCode = "var i = 0;";
CefRefPtr<CefV8Value> retval;
CefRefPtr<CefV8Exception> exception;
PERF_ITERATIONS_START()
context->Eval(jsCode, retval, exception);
PERF_ITERATIONS_END()
}
} // namespace
// Test function entries.
const PerfTestEntry kPerfTests[] = {
PERF_TEST_ENTRY(V8NullCreate),
PERF_TEST_ENTRY(V8BoolCreate),
PERF_TEST_ENTRY(V8IntCreate),
PERF_TEST_ENTRY(V8UIntCreate),
PERF_TEST_ENTRY(V8DoubleCreate),
PERF_TEST_ENTRY(V8DateCreate),
PERF_TEST_ENTRY(V8StringCreate),
PERF_TEST_ENTRY(V8ArrayCreate),
PERF_TEST_ENTRY(V8ArraySetValue),
PERF_TEST_ENTRY(V8ArrayGetValue),
PERF_TEST_ENTRY(V8FunctionCreate),
PERF_TEST_ENTRY(V8FunctionExecute),
PERF_TEST_ENTRY(V8FunctionExecuteWithContext),
PERF_TEST_ENTRY(V8ObjectCreate),
PERF_TEST_ENTRY(V8ObjectCreateWithAccessor),
PERF_TEST_ENTRY(V8ObjectSetValue),
PERF_TEST_ENTRY(V8ObjectGetValue),
PERF_TEST_ENTRY(V8ObjectSetValueWithAccessor),
PERF_TEST_ENTRY(V8ObjectGetValueWithAccessor),
PERF_TEST_ENTRY(V8ContextEnterExit),
PERF_TEST_ENTRY(V8ContextEval),
};
const int kPerfTestsCount = (sizeof(kPerfTests) / sizeof(kPerfTests[0]));
} // namespace performance_test
} // namespace client

View File

@ -0,0 +1,28 @@
<html>
<head>
<title>Binding Test</title>
<script language="JavaScript">
// Send a query to the browser process.
function sendMessage() {
// Results in a call to the OnQuery method in binding_test.cpp
window.cefQuery({
request: 'BindingTest:' + document.getElementById("message").value,
onSuccess: function(response) {
document.getElementById('result').value = 'Response: '+response;
},
onFailure: function(error_code, error_message) {}
});
}
</script>
</head>
<body bgcolor="white">
<form>
Message: <input type="text" id="message" value="My Message">
<br/><input type="button" onclick="sendMessage();" value="Send Message">
<br/>You should see the reverse of your message below:
<br/><textarea rows="10" cols="40" id="result"></textarea>
</form>
</body>
</html>

View File

@ -0,0 +1,65 @@
<html>
<head>
<title>Dialog Test</title>
<script>
function show_alert() {
alert("I am an alert box!");
}
function show_confirm() {
var r = confirm("Press a button");
var msg = r ? "You pressed OK!" : "You pressed Cancel!";
document.getElementById('cm').innerText = msg;
}
function show_prompt() {
var name = prompt("Please enter your name" ,"Harry Potter");
if (name != null && name != "")
document.getElementById('pm').innerText = "Hello " + name + "!";
}
window.onbeforeunload = function() {
return 'This is an onbeforeunload message.';
}
function update_time() {
document.getElementById('time').innerText = new Date().toLocaleString();
}
function setup() {
update_time();
setInterval(update_time, 1000);
}
function show_file_dialog(element, test) {
var message = 'DialogTest.' + test;
var target = document.getElementById(element);
// Results in a call to the OnQuery method in dialog_test.cpp
window.cefQuery({
request: message,
onSuccess: function(response) {
target.innerText = response;
},
onFailure: function(error_code, error_message) {}
});
}
window.addEventListener('load', setup, false);
</script>
</head>
<body bgcolor="white">
<form>
Click a button to show the associated dialog type.
<br/><input type="button" onclick="show_alert();" value="Show Alert">
<br/><input type="button" onclick="show_confirm();" value="Show Confirm"> <span id="cm"></span>
<br/><input type="button" onclick="show_prompt();" value="Show Prompt"> <span id="pm"></span>
<br/>input type="file": <input type="file" name="pic" accept="text/*,.js,.css,image/*">
<br/><input type="button" onclick="show_file_dialog('fo', 'FileOpen');" value="Show File Open"> <span id="fo"></span>
<br/><input type="button" onclick="show_file_dialog('fom', 'FileOpenMultiple');" value="Show File Open Multiple"> <span id="fom"></span>
<br/><input type="button" onclick="show_file_dialog('fof', 'FileOpenFolder');" value="Show File Open Folder"> <span id="fof"></span>
<br/><input type="button" onclick="show_file_dialog('fs', 'FileSave');" value="Show File Save"> <span id="fs"></span>
<p id="time"></p>
</form>
</body>
</html>

View File

@ -0,0 +1,24 @@
<html>
<body bgcolor="white">
<script language="JavaScript">
var val = window.localStorage.getItem('val');
function addLine() {
if(val == null)
val = '<br/>One Line.';
else
val += '<br/>Another Line.';
window.localStorage.setItem('val', val);
document.getElementById('out').innerHTML = val;
}
</script>
Click the "Add Line" button to add a line or the "Clear" button to clear.<br/>
This data will persist across sessions if a cache path was specified.<br/>
<input type="button" value="Add Line" onClick="addLine();"/>
<input type="button" value="Clear" onClick="window.localStorage.removeItem('val'); window.location.reload();"/>
<div id="out"></div>
<script language="JavaScript">
if(val != null)
document.getElementById('out').innerHTML = val;
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,109 @@
<html>
<head><title>OSR Test</title></head>
<style>
.red_hover:hover {color:red;}
#li { width: 530px; }
body {background:rgba(255, 0, 0, 0.5); }
input {-webkit-appearance: none; }
#LI11select {width: 75px;}
.dropdiv {
width:50px;
height:50px;
border:1px solid #aaaaaa;
float: left;
}
#dragdiv {
width: 30px;
height: 30px;
background-color: green;
margin: 10px;
}
#draghere {
position: relative;
z-index: -1;
top: 7px;
left: 7px;
opacity: 0.4;
}
</style>
<script>
function getElement(id) { return document.getElementById(id); }
function makeH1Red() { getElement('LI00').style.color='red'; }
function makeH1Black() { getElement('LI00').style.color='black'; }
function navigate() { location.href='?k='+getElement('editbox').value; }
function load() { var select = document.getElementById('LI11select');
for (var i = 1; i < 21; i++)
select.options.add(new Option('Option ' + i, i));
}
function onEventTest(event) {
var param = 'osr' + event.type;
if (event.type == "click")
param += event.button;
// Results in a call to the OnQuery method in os_rendering_unittest.cc.
if (window.testQuery)
window.testQuery({request: param});
}
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("Text",ev.target.id);
}
function drop(ev) {
var data=ev.dataTransfer.getData("Text");
ev.target.innerHTML = '';
var dragged = document.getElementById(data);
dragged.setAttribute('draggable', 'false');
ev.target.appendChild(dragged);
if (window.testQuery)
window.testQuery({request: "osrdrop"});
}
</script>
<body onfocus='onEventTest(event)' onblur='onEventTest(event)' onload='load();'>
<h1 id='LI00' onclick="onEventTest(event)">
OSR Testing h1 - Focus and blur
<select id='LI11select'>
<option value='0'>Default</option>
</select>
this page and will get this red black
</h1>
<ol>
<li id='LI01'>OnPaint should be called each time a page loads</li>
<li id='LI02' style='cursor:pointer;'><span>Move mouse
to require an OnCursorChange call</span></li>
<li id='LI03' onmousemove="onEventTest(event)"><span>Hover will color this with
red. Will trigger OnPaint once on enter and once on leave</span></li>
<li id='LI04'>Right clicking will show contextual menu and will request
GetScreenPoint</li>
<li id='LI05'>IsWindowRenderingDisabled should be true</li>
<li id='LI06'>WasResized should trigger full repaint if size changes.
</li>
<li id='LI07'>Invalidate should trigger OnPaint once</li>
<li id='LI08'>Click and write here with SendKeyEvent to trigger repaints:
<input id='editbox' type='text' value='' size="5"></li>
<li id='LI09'>Click here with SendMouseClickEvent to navigate:
<input id='btnnavigate' type='button' onclick='navigate()'
value='Click here to navigate' id='editbox' /></li>
<li id='LI10' title='EXPECTED_TOOLTIP'>Mouse over this element will
trigger show a tooltip</li>
</ol>
<div class="dropdiv" id="dropdiv" ondrop="drop(event)" ondragover="allowDrop(event)">
<span id="draghere">Drag here</span>
</div>
<div class="dropdiv">
<div id="dragdiv" draggable="true" ondragstart="drag(event)"></div>
</div>
<br />
<br />
<br />
<br />
<br />
<br />
</body>
</html>

View File

@ -0,0 +1,35 @@
<html>
<head>
<title>Other Tests</title>
</head>
<body bgcolor="white">
<h3>Various other internal and external tests.</h3>
<ul>
<li><a href="http://mudcu.be/labs/JS1k/BreathingGalaxies.html">Accelerated 2D Canvas</a></li>
<li><a href="http://webkit.org/blog-files/3d-transforms/poster-circle.html">Accelerated Layers</a></li>
<li><a href="http://html5advent2011.digitpaint.nl/3/index.html">Cursors</a></li>
<li><a href="http://tests/dialogs">Dialogs</a></li>
<li><a href="http://html5demos.com/drag">Drag & Drop</a></li>
<li><a href="http://www.adobe.com/software/flash/about/">Flash Plugin</a></li>
<li><a href="http://html5demos.com/geo">Geolocation</a></li>
<li><a href="http://www.html5test.com">HTML5 Feature Test</a></li>
<li><a href="http://www.youtube.com/watch?v=siOHh0uzcuY&html5=True">HTML5 Video</a></li>
<li><a href="http://tests/binding">JavaScript Binding</a></li>
<li><a href="http://tests/performance">JavaScript Performance Tests</a></li>
<li><a href="http://tests/performance2">JavaScript Performance (2) Tests</a></li>
<li><a href="http://tests/window">JavaScript Window Manipulation</a></li>
<li><a href="http://tests/localstorage">Local Storage</a></li>
<li><a href="http://tests/pdf.pdf">PDF Viewer direct</a></li>
<li><a href="http://tests/pdf">PDF Viewer iframe</a></li>
<li><a href="http://mrdoob.com/lab/javascript/requestanimationframe/">requestAnimationFrame</a></li>
<li><a href="client://tests/handler.html">Scheme Handler</a></li>
<li><a href="https://www.google.com/intl/en/chrome/demos/speech.html">Speech Input</a> - requires "enable-speech-input" flag</li>
<li><a href="http://tests/transparency">Transparency</a></li>
<li><a href="http://webglsamples.googlecode.com/hg/field/field.html">WebGL</a></li>
<li><a href="http://apprtc.appspot.com/">WebRTC</a> - requires "enable-media-stream" flag</li>
<li><a href="http://tests/urlrequest">CefURLRequest</a></li>
<li><a href="http://tests/xmlhttprequest">XMLHttpRequest</a></li>
<li><a href="javascript:window.print();">Print this page with &quot;javascript:window.print();&quot;</a></li>
</ul>
</body>
</html>

View File

@ -0,0 +1,9 @@
<html>
<head>
<title>PDF Test</title>
</head>
<body bgcolor="white">
<iframe src="pdf.pdf" width="500" height="500"></iframe>
<iframe src="pdf.pdf" width="500" height="500"></iframe>
</body>
</html>

View File

@ -0,0 +1,293 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Performance Tests</title>
<style>
body { font-family: Tahoma, Serif; font-size: 9pt; }
</style>
</head>
<body bgcolor="white">
<h1>Performance Tests</h1>
<input type="button" value="Run Tests" onClick="run();" id="run"/> Filter: <input type="text" size="50" id="filters"/>
<div><span id="statusBox"></span> <progress id="progressBox" value="0" style="display:none"></progress></div>
<div style="padding-top:10px; padding-bottom:10px">
<table id="resultTable" border="1" cellspacing="1" cellpadding="4">
<thead>
<tr>
<td>Name</td>
<td>Iterations per Run</td>
<td>Avg (ms)</td>
<td>Min (ms)</td>
<td>Max (ms)</td>
<td>StdDev (ms)</td>
<td>Runs (ms)</td>
</tr>
</thead>
<!-- result rows here -->
</table>
</div>
<hr width="80%">
Result 1: <input type="text" size="100" id="result1"/>
<br/>Result 2: <input type="text" size="100" id="result2"/>
<br/><input type="button" value="Compare" onClick="compare();" id="compare"/>
<div style="padding-top:10px; padding-bottom:10px">
<table id="compareTable" border="1" cellspacing="1" cellpadding="4">
<thead>
<tr>
<td>Name</td>
<td>Result 1 Avg (ms)</td>
<td>Result 2 Avg (ms)</td>
<td>% Diff</td>
</tr>
</thead>
<!-- result rows here -->
</table>
</div>
<script type="text/javascript">
function run() {
var runElement = document.getElementById("run");
var filtersElement = document.getElementById("filters");
var compareElement = document.getElementById("compare");
var result1Element = document.getElementById("result1");
var result2Element = document.getElementById("result2");
// Number of runs for each test.
var testRuns = 10;
// Delay between test runs.
var runDelay = 0;
// Retrieve the list of all tests.
var allTests = window.GetPerfTests();
// Populated with the list of tests that will be run.
var tests = [];
var currentTest = 0;
var testList = filtersElement.value.trim();
if (testList.length > 0) {
// Include or exclude specific tests.
var included = [];
var excluded = [];
var testNames = testList.split(",");
// Identify included and excluded tests.
for (i = 0; i < testNames.length; ++i) {
var testName = testNames[i].trim();
if (testName[0] == '-') {
// Exclude the test.
excluded.push(testName.substr(1));
} else {
// Include the test.
included.push(testName);
}
}
if (included.length > 0) {
// Only use the included tests.
for (i = 0; i < allTests.length; ++i) {
var test = allTests[i];
var testName = test[0];
if (included.indexOf(testName) >= 0)
tests.push(test);
}
} else if (excluded.length > 0) {
// Use all tests except the excluded tests.
for (i = 0; i < allTests.length; ++i) {
var test = allTests[i];
var testName = test[0];
if (excluded.indexOf(testName) < 0)
tests.push(test);
}
}
} else {
// Run all tests.
tests = allTests;
}
function updateStatusComplete() {
var statusBox = document.getElementById("statusBox");
statusBox.innerText = 'All tests completed.';
runElement.disabled = false;
filtersElement.disabled = false;
result1Element.disabled = false;
result2Element.disabled = false;
compareElement.disabled = false;
}
function updateStatus(test) {
var statusBox = document.getElementById("statusBox");
var progressBox = document.getElementById("progressBox");
if (test.run >= test.totalRuns) {
statusBox.innerText = test.name + " completed.";
progressBox.style.display = 'none';
} else {
statusBox.innerText = test.name + " (" + test.run + "/" + test.totalRuns + ")";
progressBox.value = (test.run / test.totalRuns);
progressBox.style.display = 'inline';
}
}
function appendResult(test) {
var e = document.getElementById("resultTable");
// Calculate the average.
var avg = test.total / test.totalRuns;
// Calculate the standard deviation.
var sqsum = 0;
for (i = 0; i < test.results.length; ++i) {
var diff = test.results[i] - avg;
sqsum += diff * diff;
}
var stddev = Math.round(Math.sqrt(sqsum / test.totalRuns) * 100.0) / 100.0;
e.insertAdjacentHTML("beforeEnd", [
"<tr>",
"<td>", test.name, "</td>",
"<td>", test.iterations, "</td>",
"<td>", avg, "</td>",
"<td>", test.min, "</td>",
"<td>", test.max, "</td>",
"<td>", stddev, "</td>",
"<td>", test.results.join(", "), "</td>",
"<tr>"
].join(""));
if (result1Element.value.length > 0)
result1Element.value += ",";
result1Element.value += test.name + "=" + avg;
}
// Execute the test function.
function execTestFunc(name) {
return window.RunPerfTest(name);
}
// Schedule the next test.
function nextTest(test) {
appendResult(test);
currentTest++;
runTest();
}
// Schedule the next step for the current test.
function nextTestStep(test) {
setTimeout(function () { execTest(test); }, runDelay);
}
// Perform the next step for the current test.
function execTest(test) {
updateStatus(test);
if (!test.warmedUp) {
execTestFunc(test.name);
test.warmedUp = true;
return nextTestStep(test);
}
if (test.run >= test.totalRuns)
return nextTest(test);
var elapsed = execTestFunc(test.name);
test.results.push(elapsed);
test.total += elapsed;
if (!test.min) test.min = elapsed;
else if (test.min > elapsed) test.min = elapsed;
if (!test.max) test.max = elapsed;
else if (test.max < elapsed) test.max = elapsed;
test.run++;
return nextTestStep(test);
}
function runTest() {
if (currentTest == tests.length) {
updateStatusComplete();
return;
}
var test = {
name: tests[currentTest][0],
iterations: tests[currentTest][1],
warmedUp: false,
total: 0,
totalRuns: testRuns,
run: 0,
results: []
};
setTimeout(function () { execTest(test); }, runDelay);
}
// Schedule the first test.
if (tests.length > 0) {
runElement.disabled = true;
filtersElement.disabled = true;
result1Element.value = "";
result1Element.disabled = true;
result2Element.disabled = true;
compareElement.disabled = true;
runTest();
}
}
function compare() {
var result1 = document.getElementById("result1").value.trim();
var result2 = document.getElementById("result2").value.trim();
if (result1.length == 0 || result2.length == 0)
return;
var r1values = result1.split(",");
var r2values = result2.split(",");
for (i = 0; i < r1values.length; ++i) {
var r1parts = r1values[i].split("=");
var r1name = r1parts[0].trim();
var r1val = r1parts[1].trim();
for (x = 0; x < r2values.length; ++x) {
var r2parts = r2values[x].split("=");
var r2name = r2parts[0].trim();
var r2val = r2parts[1].trim();
if (r2name == r1name) {
appendResult(r1name, r1val, r2val);
// Remove the matching index.
r2values.splice(x, 1);
break;
}
}
}
function appendResult(name, r1val, r2val) {
var e = document.getElementById("compareTable");
// Calculate the percent difference.
var diff = Math.round(((r2val - r1val) / r1val) * 10000.0) / 100.0;
e.insertAdjacentHTML("beforeEnd", [
"<tr>",
"<td>", name, "</td>",
"<td>", r1val, "</td>",
"<td>", r2val, "</td>",
"<td>", diff, "</td>",
"<tr>"
].join(""));
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,442 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Performance Tests (2)</title>
<style>
body { font-family: Tahoma, Serif; font-size: 9pt; }
.left { text-align: left; }
.right { text-align: right; }
.center { text-align: center; }
table.resultTable
{
border: 1px solid black;
border-collapse: collapse;
empty-cells: show;
width: 100%;
}
table.resultTable td
{
padding: 2px 4px;
border: 1px solid black;
}
table.resultTable > thead > tr
{
font-weight: bold;
background: lightblue;
}
table.resultTable > tbody > tr:nth-child(odd)
{
background: white;
}
table.resultTable > tbody > tr:nth-child(even)
{
background: lightgray;
}
.hide { display: none; }
</style>
</head>
<body bgcolor="white">
<h1>Performance Tests (2)</h1>
<form id="sForm" onsubmit="runTestSuite();return false">
<table>
<tr>
<td colspan="2">Settings:</td>
</tr>
<tr>
<td class="right">Iterations:</td>
<td><input id="sIterations" type="text" value="1000" required pattern="[0-9]+" /></td>
</tr>
<tr>
<td class="right">Samples:</td>
<td><input id="sSamples" type="text" value="100" required pattern="[0-9]+" /></td>
</tr>
<tr>
<td class="right">Mode:</td>
<td><input id="sAsync" name="sMode" type="radio" value="async" checked>Asynchronous</input>
<input id="sSync" name="sMode" type="radio" value="sync">Synchronous</input>
</td>
</tr>
<tr>
<td colspan="2"><button type="submit" id="sRun" autofocus>Run!</button></td>
</tr>
</table>
</form>
<div><span id="statusBox"></span> <progress id="progressBox" value="0" style="display:none"></progress></div>
<div style="padding-top:10px; padding-bottom:10px">
<table id="resultTable" class="resultTable">
<thead>
<tr>
<td class="center" style="width:1%">Enabled</td>
<td class="center" style="width:10%">Name</td>
<td class="center" style="width:5%">Samples x Iterations</td>
<td class="center" style="width:5%">Min,&nbsp;ms</td>
<td class="center" style="width:5%">Avg,&nbsp;ms</td>
<td class="center" style="width:5%">Max,&nbsp;ms</td>
<td class="center" style="width:5%">Average calls/sec</td>
<td class="center" style="width:5%">Measuring Inacurracy</td>
<td class="center hide" style="width:5%">Memory, MB</td>
<td class="center hide" style="width:5%">Memory delta, MB</td>
<td class="center" style="width:55%">Description</td>
</tr>
</thead>
<tbody>
<!-- result rows here -->
</tbody>
</table>
</div>
<script type="text/javascript">
(function () {
function getPrivateWorkingSet() {
return 0; // TODO: window.PerfTestGetPrivateWorkingSet();
}
var disableWarmUp = true;
var asyncExecution = true;
var testIterations = 1000;
var totalSamples = 100;
var sampleDelay = 0;
var collectSamples = false;
var tests = [];
var testIndex = -1;
function execTestFunc(test) {
try {
var begin = new Date();
test.func(test.totalIterations);
var end = new Date();
return (end - begin);
} catch (e) {
test.error = e.toString();
return 0;
}
}
function execTest(test) {
if (disableWarmUp) { test.warmedUp = true; }
function nextStep() {
if (asyncExecution) {
setTimeout(function () { execTest(test); }, sampleDelay);
} else {
execTest(test);
}
}
function nextTest() {
updateStatus(test);
appendResult(test);
return execNextTest();
}
updateStatus(test);
if (!test.warmedUp) {
execTestFunc(test);
if (!test.error) {
test.warmedUp = true;
test.beginMemory = getPrivateWorkingSet();
return nextStep();
} else {
return nextTest();
}
}
if (test.sample >= test.totalSamples) {
test.avg = test.total / test.totalSamples;
test.endMemory = getPrivateWorkingSet();
return nextTest();
}
if (test.skipped) return nextTest();
var elapsed = execTestFunc(test);
if (!test.error) {
test.total += elapsed;
if (!test.min) test.min = elapsed;
else if (test.min > elapsed) test.min = elapsed;
if (!test.max) test.max = elapsed;
else if (test.max < elapsed) test.max = elapsed;
if (collectSamples) {
test.results.push(elapsed);
}
test.sample++;
return nextStep();
} else {
return nextTest();
}
}
function updateStatus(test) {
var statusBox = document.getElementById("statusBox");
var progressBox = document.getElementById("progressBox");
if (test.skipped || test.error || test.sample >= test.totalSamples) {
statusBox.innerText = "";
progressBox.style.display = "none";
} else {
statusBox.innerText = (testIndex + 1) + "/" + tests.length + ": " + test.name + " (" + test.sample + "/" + test.totalSamples + ")";
progressBox.value = (test.sample / test.totalSamples);
progressBox.style.display = "inline";
}
}
function appendResult(test) {
if (test.name == "warmup") return;
var id = "testResultRow_" + test.index;
var nearBound = (test.max - test.avg) < (test.avg - test.min) ? test.max : test.min;
var memoryDelta = test.endMemory - test.beginMemory;
if (memoryDelta < 0) memoryDelta = "-" + Math.abs(memoryDelta).toFixed(2);
else memoryDelta = "+" + Math.abs(memoryDelta).toFixed(2);
var markup = ["<tr id='" + id + "'>",
"<td class='left'><input type='checkbox' id='test_enabled_", test.index ,"' ", (!test.skipped ? "checked" : "") ," /></td>",
"<td class='left'>", test.name, "</td>",
"<td class='right'>", test.totalSamples, "x", test.totalIterations, "</td>",
"<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : test.min.toFixed(2), "</td>",
"<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : test.avg.toFixed(2), "</td>",
"<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : test.max.toFixed(2), "</td>",
"<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : (test.totalIterations * 1000 / test.avg).toFixed(2), "</td>",
"<td class='right'>", test.skipped || test.error || !test.prepared ? "-" : ("&#x00B1; " + (Math.abs(test.avg - nearBound) / (test.avg) * (100)).toFixed(2) + "%"), "</td>",
"<td class='right hide'>", test.skipped || test.error || !test.prepared ? "-" : test.endMemory.toFixed(2), "</td>",
"<td class='right hide'>", test.skipped || test.error || !test.prepared ? "-" : memoryDelta, "</td>",
"<td class='left'>", test.description, test.error ? (test.description ? "<br/>" : "") + "<span style='color:red'>" + test.error + "</span>" : "", "</td>",
"</tr>"
].join("");
// test.results.join(", "), "<br/>",
var row = document.getElementById(id);
if (row) {
row.outerHTML = markup;
} else {
var tbody = document.getElementById("resultTable").tBodies[0];
tbody.insertAdjacentHTML("beforeEnd", markup);
}
}
function prepareQueuedTests() {
testIndex = -1;
for (var i = 0; i < tests.length; i++) {
var test = tests[i];
test.index = i;
test.prepared = false;
test.warmedUp = false;
test.sample = 0;
test.total = 0;
test.results = [];
test.error = false;
test.min = null;
test.avg = null;
test.max = null;
test.beginMemory = null;
test.endMemory = null;
test.totalIterations = parseInt(testIterations / test.complex);
test.totalSamples = parseInt(totalSamples / test.complex);
var skipElement = document.getElementById('test_enabled_' + test.index);
test.skipped = skipElement ? !skipElement.checked : (test.skipped || false);
if (test.totalIterations <= 0) test.totalIterations = 1;
if (test.totalSamples <= 0) test.totalSamples = 1;
appendResult(test);
test.prepared = true;
}
}
function queueTest(func, name, description) {
var test;
if (typeof func === "function") {
test = {
name: name,
func: func,
description: description
};
} else {
test = func;
}
test.warmedUp = false;
test.complex = test.complex || 1;
tests.push(test);
}
function execNextTest() {
testIndex++;
if (tests.length <= testIndex) {
return testSuiteFinished();
} else {
return execTest(tests[testIndex]);
}
}
function execQueuedTests() {
prepareQueuedTests();
execNextTest();
}
function setSettingsState(disabled) {
document.getElementById('sIterations').disabled = disabled;
document.getElementById('sSamples').disabled = disabled;
document.getElementById('sAsync').disabled = disabled;
document.getElementById('sSync').disabled = disabled;
document.getElementById('sRun').disabled = disabled;
}
function testSuiteFinished() {
setSettingsState(false);
}
window.runTestSuite = function () {
setSettingsState(true);
testIterations = parseInt(document.getElementById('sIterations').value);
totalSamples = parseInt(document.getElementById('sSamples').value);
asyncExecution = document.getElementById('sAsync').checked;
setTimeout(execQueuedTests, 0);
}
setTimeout(prepareQueuedTests, 0);
// Test queue.
queueTest({
name: "PerfTestReturnValue Default",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue();
}
},
description: "No arguments, returns int32 value.",
skipped: true,
});
queueTest({
name: "PerfTestReturnValue (0, Undefined)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(0);
}
},
description: "Int argument, returns undefined value."
});
queueTest({
name: "PerfTestReturnValue (1, Null)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(1);
}
},
description: "Int argument, returns null value."
});
queueTest({
name: "PerfTestReturnValue (2, Bool)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(2);
}
},
description: "Int argument, returns bool value."
});
queueTest({
name: "PerfTestReturnValue (3, Int)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(3);
}
},
description: "Int argument, returns int value."
});
queueTest({
name: "PerfTestReturnValue (4, UInt)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(4);
}
},
description: "Int argument, returns uint value."
});
queueTest({
name: "PerfTestReturnValue (5, Double)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(5);
}
},
description: "Int argument, returns double value."
});
queueTest({
name: "PerfTestReturnValue (6, Date)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(6);
}
},
description: "Int argument, returns date value.",
skipped: true,
});
queueTest({
name: "PerfTestReturnValue (7, String)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(7);
}
},
description: "Int argument, returns string value."
});
queueTest({
name: "PerfTestReturnValue (8, Object)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(8);
}
},
description: "Int argument, returns object value."
});
queueTest({
name: "PerfTestReturnValue (9, Array)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(9);
}
},
description: "Int argument, returns array value."
});
queueTest({
name: "PerfTestReturnValue (10, Function)",
func: function (count) {
for (var i = 0; i < count; i++) {
window.PerfTestReturnValue(10);
}
},
description: "Int argument, returns function value.",
skipped: true,
});
// add more tests to queueTest
})();
</script>
</body>
</html>

View File

@ -0,0 +1,63 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Transparency Examples</title>
<style type="text/css">
body {
font-family: Verdana, Arial;
}
img {
opacity:0.4;
}
img:hover {
opacity:1.0;
}
.box_white, .box_black {
font-size: 14px;
font-weight: bold;
text-align: center;
padding: 10px;
display: inline-block;
width: 100px;
}
.box_white {
background-color: white;
border: 2px solid black;
color: black;
}
.box_black {
background-color: black;
border: 2px solid white;
color: white;
}
.box_0 {
opacity: 1.0;
}
.box_25 {
opacity: 0.75;
}
.box_50 {
opacity: 0.5;
}
.box_75 {
opacity: 0.25;
}
.box_100 {
opacity: 0;
}
</style>
</head>
<body>
<h1>Image Transparency</h1>
Hover over an image to make it fully opaque.<br>
<img src="http://www.w3schools.com/css/klematis.jpg" width="150" height="113" alt="klematis" />
<img src="http://www.w3schools.com/css/klematis2.jpg" width="150" height="113" alt="klematis" />
<h1>Block Transparency</h1>
<span class="box_white box_0">White 0%</span> <span class="box_white box_25">White 25%</span> <span class="box_white box_50">White 50%</span> <span class="box_white box_75">White 75%</span> <span class="box_white box_100">White 100%</span>
<br>
<span class="box_black box_0">Black 0%</span> <span class="box_black box_25">Black 25%</span> <span class="box_black box_50">Black 50%</span> <span class="box_black box_75">Black 75%</span> <span class="box_black box_100">Black 100%</span>
</body>
</html>

View File

@ -0,0 +1,27 @@
<html>
<body bgcolor="white">
<script language="JavaScript">
// Send a query to the browser process.
function execURLRequest() {
document.getElementById('ta').value = 'Request pending...';
// Results in a call to the OnQuery method in urlrequest_test.cpp
window.cefQuery({
request: 'URLRequestTest:' + document.getElementById("url").value,
onSuccess: function(response) {
document.getElementById('ta').value = response;
},
onFailure: function(error_code, error_message) {
document.getElementById('ta').value = 'Failed with error ' + error_message + ' (' + error_code + ')';
}
});
}
</script>
<form>
URL: <input type="text" id="url" value="http://www.google.com">
<br/><input type="button" onclick="execURLRequest();" value="Execute CefURLRequest">
<br/><textarea rows="10" cols="40" id="ta"></textarea>
</form>
</body>
</html>

View File

@ -0,0 +1,48 @@
<html>
<head>
<title>Window Test</title>
<script>
function send_message(test, params) {
var message = 'WindowTest.' + test;
if (typeof params != 'undefined')
message += ':' + params;
// Results in a call to the OnQuery method in window_test.cpp.
window.cefQuery({'request' : message});
}
function minimize() {
send_message('Minimize');
}
function maximize() {
send_message('Maximize');
}
function restore() {
minimize();
setTimeout(function() { send_message('Restore'); }, 1000);
}
function position() {
var x = parseInt(document.getElementById('x').value);
var y = parseInt(document.getElementById('y').value);
var width = parseInt(document.getElementById('width').value);
var height = parseInt(document.getElementById('height').value);
if (isNaN(x) || isNaN(y) || isNaN(width) || isNaN(height))
alert('Please specify a valid numeric value.');
else
send_message('Position', x + ',' + y + ',' + width + ',' + height);
}
</script>
</head>
<body bgcolor="white">
<form>
Click a button to perform the associated window action.
<br/><input type="button" onclick="minimize();" value="Minimize">
<br/><input type="button" onclick="maximize();" value="Maximize">
<br/><input type="button" onclick="restore();" value="Restore"> (minimizes and then restores the window as topmost)
<br/><input type="button" onclick="position();" value="Set Position"> X: <input type="text" size="4" id="x" value="200"> Y: <input type="text" size="4" id="y" value="100"> Width: <input type="text" size="4" id="width" value="800"> Height: <input type="text" size="4" id="height" value="600">
</form>
</body>
</html>

View File

@ -0,0 +1,26 @@
<html>
<body bgcolor="white">
<script language="JavaScript">
function execXMLHttpRequest()
{
xhr = new XMLHttpRequest();
xhr.open("GET", document.getElementById("url").value, true);
xhr.setRequestHeader('My-Custom-Header', 'Some Value');
xhr.onload = function(e) {
if (xhr.readyState === 4) {
var value = "Status Code: "+xhr.status;
if (xhr.status === 200)
value += "\n\n"+xhr.responseText;
document.getElementById('ta').value = value;
}
}
xhr.send();
}
</script>
<form>
URL: <input type="text" id="url" value="http://tests/request">
<br/><input type="button" onclick="execXMLHttpRequest();" value="Execute XMLHttpRequest">
<br/><textarea rows="10" cols="40" id="ta"></textarea>
</form>
</body>
</html>

View File

@ -0,0 +1,126 @@
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011
// Google Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This is a low level implementation of atomic semantics for reference
// counting. Please use cef_ref_counted.h directly instead.
//
// The Chromium implementation includes annotations to avoid some false
// positives when using data race detection tools. Annotations are not
// currently supported by the CEF implementation.
#ifndef CEF_INCLUDE_BASE_CEF_ATOMIC_REF_COUNT_H_
#define CEF_INCLUDE_BASE_CEF_ATOMIC_REF_COUNT_H_
#pragma once
#if defined(BASE_ATOMIC_REF_COUNT_H_)
// Do nothing if the Chromium header has already been included.
// This can happen in cases where Chromium code is used directly by the
// client application. When using Chromium code directly always include
// the Chromium header first to avoid type conflicts.
#elif defined(BUILDING_CEF_SHARED)
// When building CEF include the Chromium header directly.
#include "base/atomic_ref_count.h"
#else // !BUILDING_CEF_SHARED
// The following is substantially similar to the Chromium implementation.
// If the Chromium implementation diverges the below implementation should be
// updated to match.
#include "include/base/cef_atomicops.h"
// Annotations are not currently supported.
#define ANNOTATE_HAPPENS_BEFORE(obj) /* empty */
#define ANNOTATE_HAPPENS_AFTER(obj) /* empty */
namespace base {
typedef subtle::Atomic32 AtomicRefCount;
// Increment a reference count by "increment", which must exceed 0.
inline void AtomicRefCountIncN(volatile AtomicRefCount *ptr,
AtomicRefCount increment) {
subtle::NoBarrier_AtomicIncrement(ptr, increment);
}
// Decrement a reference count by "decrement", which must exceed 0,
// and return whether the result is non-zero.
// Insert barriers to ensure that state written before the reference count
// became zero will be visible to a thread that has just made the count zero.
inline bool AtomicRefCountDecN(volatile AtomicRefCount *ptr,
AtomicRefCount decrement) {
ANNOTATE_HAPPENS_BEFORE(ptr);
bool res = (subtle::Barrier_AtomicIncrement(ptr, -decrement) != 0);
if (!res) {
ANNOTATE_HAPPENS_AFTER(ptr);
}
return res;
}
// Increment a reference count by 1.
inline void AtomicRefCountInc(volatile AtomicRefCount *ptr) {
base::AtomicRefCountIncN(ptr, 1);
}
// Decrement a reference count by 1 and return whether the result is non-zero.
// Insert barriers to ensure that state written before the reference count
// became zero will be visible to a thread that has just made the count zero.
inline bool AtomicRefCountDec(volatile AtomicRefCount *ptr) {
return base::AtomicRefCountDecN(ptr, 1);
}
// Return whether the reference count is one. If the reference count is used
// in the conventional way, a refrerence count of 1 implies that the current
// thread owns the reference and no other thread shares it. This call performs
// the test for a reference count of one, and performs the memory barrier
// needed for the owning thread to act on the object, knowing that it has
// exclusive access to the object.
inline bool AtomicRefCountIsOne(volatile AtomicRefCount *ptr) {
bool res = (subtle::Acquire_Load(ptr) == 1);
if (res) {
ANNOTATE_HAPPENS_AFTER(ptr);
}
return res;
}
// Return whether the reference count is zero. With conventional object
// referencing counting, the object will be destroyed, so the reference count
// should never be zero. Hence this is generally used for a debug check.
inline bool AtomicRefCountIsZero(volatile AtomicRefCount *ptr) {
bool res = (subtle::Acquire_Load(ptr) == 0);
if (res) {
ANNOTATE_HAPPENS_AFTER(ptr);
}
return res;
}
} // namespace base
#endif // !BUILDING_CEF_SHARED
#endif // CEF_INCLUDE_BASE_CEF_ATOMIC_REF_COUNT_H_

View File

@ -0,0 +1,198 @@
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
// Google Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// For atomic operations on reference counts, see cef_atomic_ref_count.h.
// The routines exported by this module are subtle. If you use them, even if
// you get the code right, it will depend on careful reasoning about atomicity
// and memory ordering; it will be less readable, and harder to maintain. If
// you plan to use these routines, you should have a good reason, such as solid
// evidence that performance would otherwise suffer, or there being no
// alternative. You should assume only properties explicitly guaranteed by the
// specifications in this file. You are almost certainly _not_ writing code
// just for the x86; if you assume x86 semantics, x86 hardware bugs and
// implementations on other archtectures will cause your code to break. If you
// do not know what you are doing, avoid these routines, and use a Mutex.
//
// It is incorrect to make direct assignments to/from an atomic variable.
// You should use one of the Load or Store routines. The NoBarrier
// versions are provided when no barriers are needed:
// NoBarrier_Store()
// NoBarrier_Load()
// Although there are currently no compiler enforcement, you are encouraged
// to use these.
//
#ifndef CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_
#define CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_
#pragma once
#if defined(BASE_ATOMICOPS_H_)
// Do nothing if the Chromium header has already been included.
// This can happen in cases where Chromium code is used directly by the
// client application. When using Chromium code directly always include
// the Chromium header first to avoid type conflicts.
#elif defined(BUILDING_CEF_SHARED)
// When building CEF include the Chromium header directly.
#include "base/atomicops.h"
#else // !BUILDING_CEF_SHARED
// The following is substantially similar to the Chromium implementation.
// If the Chromium implementation diverges the below implementation should be
// updated to match.
#include <stdint.h>
#include "include/base/cef_build.h"
#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
// windows.h #defines this (only on x64). This causes problems because the
// public API also uses MemoryBarrier at the public name for this fence. So, on
// X64, undef it, and call its documented
// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
// implementation directly.
#undef MemoryBarrier
#endif
namespace base {
namespace subtle {
typedef int32_t Atomic32;
#ifdef ARCH_CPU_64_BITS
// We need to be able to go between Atomic64 and AtomicWord implicitly. This
// means Atomic64 and AtomicWord should be the same type on 64-bit.
#if defined(__ILP32__) || defined(OS_NACL)
// NaCl's intptr_t is not actually 64-bits on 64-bit!
// http://code.google.com/p/nativeclient/issues/detail?id=1162
typedef int64_t Atomic64;
#else
typedef intptr_t Atomic64;
#endif
#endif
// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or
// Atomic64 routines below, depending on your architecture.
typedef intptr_t AtomicWord;
// Atomically execute:
// result = *ptr;
// if (*ptr == old_value)
// *ptr = new_value;
// return result;
//
// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
// Always return the old value of "*ptr"
//
// This routine implies no memory barriers.
Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value);
// Atomically store new_value into *ptr, returning the previous value held in
// *ptr. This routine implies no memory barriers.
Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
// Atomically increment *ptr by "increment". Returns the new value of
// *ptr with the increment applied. This routine implies no memory barriers.
Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
Atomic32 increment);
// These following lower-level operations are typically useful only to people
// implementing higher-level synchronization operations like spinlocks,
// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or
// a store with appropriate memory-ordering instructions. "Acquire" operations
// ensure that no later memory access can be reordered ahead of the operation.
// "Release" operations ensure that no previous memory access can be reordered
// after the operation. "Barrier" operations have both "Acquire" and "Release"
// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory
// access.
Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value);
Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value);
void MemoryBarrier();
void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value);
void Acquire_Store(volatile Atomic32* ptr, Atomic32 value);
void Release_Store(volatile Atomic32* ptr, Atomic32 value);
Atomic32 NoBarrier_Load(volatile const Atomic32* ptr);
Atomic32 Acquire_Load(volatile const Atomic32* ptr);
Atomic32 Release_Load(volatile const Atomic32* ptr);
// 64-bit atomic operations (only available on 64-bit processors).
#ifdef ARCH_CPU_64_BITS
Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value);
Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value);
Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment);
Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value);
Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value);
void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value);
void Acquire_Store(volatile Atomic64* ptr, Atomic64 value);
void Release_Store(volatile Atomic64* ptr, Atomic64 value);
Atomic64 NoBarrier_Load(volatile const Atomic64* ptr);
Atomic64 Acquire_Load(volatile const Atomic64* ptr);
Atomic64 Release_Load(volatile const Atomic64* ptr);
#endif // ARCH_CPU_64_BITS
} // namespace subtle
} // namespace base
// Include our platform specific implementation.
#if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY)
#include "include/base/internal/cef_atomicops_x86_msvc.h"
#elif defined(OS_MACOSX)
#include "include/base/internal/cef_atomicops_mac.h"
#elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
#include "include/base/internal/cef_atomicops_x86_gcc.h"
#else
#error "Atomic operations are not supported on your platform"
#endif
// On some platforms we need additional declarations to make
// AtomicWord compatible with our other Atomic* types.
#if defined(OS_MACOSX) || defined(OS_OPENBSD)
#include "include/base/internal/cef_atomicops_atomicword_compat.h"
#endif
#endif // !BUILDING_CEF_SHARED
#endif // CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_

View File

@ -0,0 +1,87 @@
// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012
// Google Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CEF_INCLUDE_BASE_CEF_BASICTYPES_H_
#define CEF_INCLUDE_BASE_CEF_BASICTYPES_H_
#pragma once
#if defined(BUILDING_CEF_SHARED)
// When building CEF include the Chromium header directly.
#include "base/basictypes.h"
#else // !BUILDING_CEF_SHARED
// The following is substantially similar to the Chromium implementation.
// If the Chromium implementation diverges the below implementation should be
// updated to match.
#include <limits.h> // For UINT_MAX
#include <stddef.h> // For size_t
#include "include/base/cef_build.h"
// 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
// <inttypes.h> 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
#endif // !BUILDING_CEF_SHARED
// UTF-16 character type.
// This should be kept synchronized with base/strings/string16.h
#ifndef char16
#if defined(WCHAR_T_IS_UTF16)
typedef wchar_t char16;
#elif defined(WCHAR_T_IS_UTF32)
typedef unsigned short char16;
#endif
#endif
#endif // CEF_INCLUDE_BASE_CEF_BASICTYPES_H_

Some files were not shown because too many files have changed in this diff Show More